From: Sasha Levin Date: Sat, 15 May 2021 02:13:35 +0000 (-0400) Subject: Fixes for 5.12 X-Git-Tag: v5.4.120~93 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f9b18446046daf717add02baeb2b493af444b952;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.12 Signed-off-by: Sasha Levin --- diff --git a/queue-5.12/alsa-bebob-enable-to-deliver-midi-messages-for-multi.patch b/queue-5.12/alsa-bebob-enable-to-deliver-midi-messages-for-multi.patch new file mode 100644 index 00000000000..805e2e7d903 --- /dev/null +++ b/queue-5.12/alsa-bebob-enable-to-deliver-midi-messages-for-multi.patch @@ -0,0 +1,58 @@ +From d36bb9a86b8ac03183877e974a32b5c039834edd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Mar 2021 12:28:31 +0900 +Subject: ALSA: bebob: enable to deliver MIDI messages for multiple ports + +From: Takashi Sakamoto + +[ Upstream commit d2b6f15bc18ac8fbce25398290774c21f5b2cd44 ] + +Current implementation of bebob driver doesn't correctly handle the case +that the device has multiple MIDI ports. The cause is the number of MIDI +conformant data channels is passed to AM824 data block processing layer. + +This commit fixes the bug. + +Signed-off-by: Takashi Sakamoto +Link: https://lore.kernel.org/r/20210321032831.340278-4-o-takashi@sakamocchi.jp +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/firewire/bebob/bebob_stream.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c +index bbae04793c50..c18017e0a3d9 100644 +--- a/sound/firewire/bebob/bebob_stream.c ++++ b/sound/firewire/bebob/bebob_stream.c +@@ -517,20 +517,22 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) + static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, + unsigned int rate, unsigned int index) + { +- struct snd_bebob_stream_formation *formation; ++ unsigned int pcm_channels; ++ unsigned int midi_ports; + struct cmp_connection *conn; + int err; + + if (stream == &bebob->tx_stream) { +- formation = bebob->tx_stream_formations + index; ++ pcm_channels = bebob->tx_stream_formations[index].pcm; ++ midi_ports = bebob->midi_input_ports; + conn = &bebob->out_conn; + } else { +- formation = bebob->rx_stream_formations + index; ++ pcm_channels = bebob->rx_stream_formations[index].pcm; ++ midi_ports = bebob->midi_output_ports; + conn = &bebob->in_conn; + } + +- err = amdtp_am824_set_parameters(stream, rate, formation->pcm, +- formation->midi, false); ++ err = amdtp_am824_set_parameters(stream, rate, pcm_channels, midi_ports, false); + if (err < 0) + return err; + +-- +2.30.2 + diff --git a/queue-5.12/alsa-hda-hdmi-fix-max-dp-mst-dev_num-for-intel-tgl-p.patch b/queue-5.12/alsa-hda-hdmi-fix-max-dp-mst-dev_num-for-intel-tgl-p.patch new file mode 100644 index 00000000000..08299b51baa --- /dev/null +++ b/queue-5.12/alsa-hda-hdmi-fix-max-dp-mst-dev_num-for-intel-tgl-p.patch @@ -0,0 +1,107 @@ +From dbb39456ea41d38e20c2333e87b3f7cd693c9d3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Mar 2021 19:23:37 +0200 +Subject: ALSA: hda/hdmi: fix max DP-MST dev_num for Intel TGL+ platforms + +From: Kai Vehmanen + +[ Upstream commit e839fbed26e8b8713803b8ac73da92fd2b0c7594 ] + +Increase the device select range to 4 on platforms supporting +4 concurrent displays. + +This fixes a problem in scenario where total of 4 displays are active, +and 3 of these are audio capable DP receivers and connected to a DP-MST +hub. Due to incorrect range for device select, audio could not be played +to the 3rd monitor in DP-MST hub. + +BugLink: https://github.com/thesofproject/linux/issues/2798 +Signed-off-by: Kai Vehmanen +Reviewed-by: Ranjani Sridharan +Reviewed-by: Guennadi Liakhovetski +Link: https://lore.kernel.org/r/20210324172337.51730-1-kai.vehmanen@linux.intel.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_hdmi.c | 25 +++++++++++-------------- + 1 file changed, 11 insertions(+), 14 deletions(-) + +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index 45ae845e82df..5de3666a7101 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -1848,16 +1848,12 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) + */ + if (spec->intel_hsw_fixup) { + /* +- * On Intel platforms, device entries number is +- * changed dynamically. If there is a DP MST +- * hub connected, the device entries number is 3. +- * Otherwise, it is 1. +- * Here we manually set dev_num to 3, so that +- * we can initialize all the device entries when +- * bootup statically. ++ * On Intel platforms, device entries count returned ++ * by AC_PAR_DEVLIST_LEN is dynamic, and depends on ++ * the type of receiver that is connected. Allocate pin ++ * structures based on worst case. + */ +- dev_num = 3; +- spec->dev_num = 3; ++ dev_num = spec->dev_num; + } else if (spec->dyn_pcm_assign && codec->dp_mst) { + dev_num = snd_hda_get_num_devices(codec, pin_nid) + 1; + /* +@@ -2942,7 +2938,7 @@ static int parse_intel_hdmi(struct hda_codec *codec) + + /* Intel Haswell and onwards; audio component with eld notifier */ + static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, +- const int *port_map, int port_num) ++ const int *port_map, int port_num, int dev_num) + { + struct hdmi_spec *spec; + int err; +@@ -2957,6 +2953,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, + spec->port_map = port_map; + spec->port_num = port_num; + spec->intel_hsw_fixup = true; ++ spec->dev_num = dev_num; + + intel_haswell_enable_all_pins(codec, true); + intel_haswell_fixup_enable_dp12(codec); +@@ -2982,12 +2979,12 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, + + static int patch_i915_hsw_hdmi(struct hda_codec *codec) + { +- return intel_hsw_common_init(codec, 0x08, NULL, 0); ++ return intel_hsw_common_init(codec, 0x08, NULL, 0, 3); + } + + static int patch_i915_glk_hdmi(struct hda_codec *codec) + { +- return intel_hsw_common_init(codec, 0x0b, NULL, 0); ++ return intel_hsw_common_init(codec, 0x0b, NULL, 0, 3); + } + + static int patch_i915_icl_hdmi(struct hda_codec *codec) +@@ -2998,7 +2995,7 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec) + */ + static const int map[] = {0x0, 0x4, 0x6, 0x8, 0xa, 0xb}; + +- return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map)); ++ return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 3); + } + + static int patch_i915_tgl_hdmi(struct hda_codec *codec) +@@ -3010,7 +3007,7 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec) + static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + int ret; + +- ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map)); ++ ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4); + if (!ret) { + struct hdmi_spec *spec = codec->spec; + +-- +2.30.2 + diff --git a/queue-5.12/alsa-hda-hdmi-fix-race-in-handling-acomp-eld-notific.patch b/queue-5.12/alsa-hda-hdmi-fix-race-in-handling-acomp-eld-notific.patch new file mode 100644 index 00000000000..079d15124f5 --- /dev/null +++ b/queue-5.12/alsa-hda-hdmi-fix-race-in-handling-acomp-eld-notific.patch @@ -0,0 +1,66 @@ +From b9f0268291d0eb9f17bb93bb19dc723133e889e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Apr 2021 16:11:57 +0300 +Subject: ALSA: hda/hdmi: fix race in handling acomp ELD notification at resume + +From: Kai Vehmanen + +[ Upstream commit 0c37e2eb6b83e375e8a654d01598292d5591fc65 ] + +When snd-hda-codec-hdmi is used with ASoC HDA controller like SOF (acomp +used for ELD notifications), display connection change done during suspend, +can be lost due to following sequence of events: + + 1. system in S3 suspend + 2. DP/HDMI receiver connected + 3. system resumed + 4. HDA controller resumed, but card->deferred_resume_work not complete + 5. acomp eld_notify callback + 6. eld_notify ignored as power state is not CTL_POWER_D0 + 7. HDA resume deferred work completed, power state set to CTL_POWER_D0 + +This results in losing the notification, and the jack state reported to +user-space is not correct. + +The check on step 6 was added in commit 8ae743e82f0b ("ALSA: hda - Skip +ELD notification during system suspend"). It would seem with the deferred +resume logic in ASoC core, this check is not safe. + +Fix the issue by modifying the check to use "dev.power.power_state.event" +instead of ALSA specific card power state variable. + +BugLink: https://github.com/thesofproject/linux/issues/2825 +Suggested-by: Takashi Iwai +Signed-off-by: Kai Vehmanen +Link: https://lore.kernel.org/r/20210416131157.1881366-1-kai.vehmanen@linux.intel.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_hdmi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index 5de3666a7101..4b2cc8cb55c4 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -2654,7 +2654,7 @@ static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id) + /* skip notification during system suspend (but not in runtime PM); + * the state will be updated at resume + */ +- if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0) ++ if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) + return; + /* ditto during suspend/resume process itself */ + if (snd_hdac_is_in_pm(&codec->core)) +@@ -2840,7 +2840,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) + /* skip notification during system suspend (but not in runtime PM); + * the state will be updated at resume + */ +- if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0) ++ if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) + return; + /* ditto during suspend/resume process itself */ + if (snd_hdac_is_in_pm(&codec->core)) +-- +2.30.2 + diff --git a/queue-5.12/alsa-hda-realtek-add-quirk-for-lenovo-ideapad-s740.patch b/queue-5.12/alsa-hda-realtek-add-quirk-for-lenovo-ideapad-s740.patch new file mode 100644 index 00000000000..55b847d45bc --- /dev/null +++ b/queue-5.12/alsa-hda-realtek-add-quirk-for-lenovo-ideapad-s740.patch @@ -0,0 +1,569 @@ +From 09a6a3dcba758791987d170ce623ecfd61749a93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Apr 2021 10:12:11 +0200 +Subject: ALSA: hda/realtek: Add quirk for Lenovo Ideapad S740 + +From: Takashi Iwai + +[ Upstream commit 26928ca1f06aab4361eb5adbe7ef3b5c82f13cf2 ] + +Lenovo Ideapad S740 requires quite a few COEF setups to make its +speakers working. The verb table was provided from Ryan Prescott as +the result of investigation via qemu: + https://github.com/ryanprescott/realtek-verb-tools/wiki/How-to-sniff-verbs-from-a-Windows-sound-driver + +BugLink: https://github.com/thesofproject/linux/issues/2748 +Tested-by: Ryan Prescott +Link: https://lore.kernel.org/r/20210416081211.20059-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/ideapad_s740_helper.c | 492 ++++++++++++++++++++++++++++ + sound/pci/hda/patch_realtek.c | 11 + + 2 files changed, 503 insertions(+) + create mode 100644 sound/pci/hda/ideapad_s740_helper.c + +diff --git a/sound/pci/hda/ideapad_s740_helper.c b/sound/pci/hda/ideapad_s740_helper.c +new file mode 100644 +index 000000000000..564b9086e52d +--- /dev/null ++++ b/sound/pci/hda/ideapad_s740_helper.c +@@ -0,0 +1,492 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* Fixes for Lenovo Ideapad S740, to be included from codec driver */ ++ ++static const struct hda_verb alc285_ideapad_s740_coefs[] = { ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x10 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0320 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, ++{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, ++{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, ++{} ++}; ++ ++static void alc285_fixup_ideapad_s740_coef(struct hda_codec *codec, ++ const struct hda_fixup *fix, ++ int action) ++{ ++ switch (action) { ++ case HDA_FIXUP_ACT_PRE_PROBE: ++ snd_hda_add_verbs(codec, alc285_ideapad_s740_coefs); ++ break; ++ } ++} +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 8ec57bd351df..1fe70f2fe4fe 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6282,6 +6282,9 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec, + /* for alc295_fixup_hp_top_speakers */ + #include "hp_x360_helper.c" + ++/* for alc285_fixup_ideapad_s740_coef() */ ++#include "ideapad_s740_helper.c" ++ + enum { + ALC269_FIXUP_GPIO2, + ALC269_FIXUP_SONY_VAIO, +@@ -6481,6 +6484,7 @@ enum { + ALC282_FIXUP_ACER_DISABLE_LINEOUT, + ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST, + ALC256_FIXUP_ACER_HEADSET_MIC, ++ ALC285_FIXUP_IDEAPAD_S740_COEF, + }; + + static const struct hda_fixup alc269_fixups[] = { +@@ -7973,6 +7977,12 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC + }, ++ [ALC285_FIXUP_IDEAPAD_S740_COEF] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc285_fixup_ideapad_s740_coef, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_THINKPAD_ACPI, ++ }, + }; + + static const struct snd_pci_quirk alc269_fixup_tbl[] = { +@@ -8320,6 +8330,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME), ++ SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF), + SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), + SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), + SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), +-- +2.30.2 + diff --git a/queue-5.12/alsa-hdsp-don-t-disable-if-not-enabled.patch b/queue-5.12/alsa-hdsp-don-t-disable-if-not-enabled.patch new file mode 100644 index 00000000000..d2fd82994c8 --- /dev/null +++ b/queue-5.12/alsa-hdsp-don-t-disable-if-not-enabled.patch @@ -0,0 +1,49 @@ +From 014c686db78b648abc0ca17e2e93f4a31caddd40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Mar 2021 11:38:38 -0400 +Subject: ALSA: hdsp: don't disable if not enabled + +From: Tong Zhang + +[ Upstream commit 507cdb9adba006a7798c358456426e1aea3d9c4f ] + +hdsp wants to disable a not enabled pci device, which makes kernel +throw a warning. Make sure the device is enabled before calling disable. + +[ 1.758292] snd_hdsp 0000:00:03.0: disabling already-disabled device +[ 1.758327] WARNING: CPU: 0 PID: 180 at drivers/pci/pci.c:2146 pci_disable_device+0x91/0xb0 +[ 1.766985] Call Trace: +[ 1.767121] snd_hdsp_card_free+0x94/0xf0 [snd_hdsp] +[ 1.767388] release_card_device+0x4b/0x80 [snd] +[ 1.767639] device_release+0x3b/0xa0 +[ 1.767838] kobject_put+0x94/0x1b0 +[ 1.768027] put_device+0x13/0x20 +[ 1.768207] snd_card_free+0x61/0x90 [snd] +[ 1.768430] snd_hdsp_probe+0x524/0x5e0 [snd_hdsp] + +Suggested-by: Takashi Iwai +Signed-off-by: Tong Zhang +Link: https://lore.kernel.org/r/20210321153840.378226-2-ztong0001@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/rme9652/hdsp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c +index 4cf879c42dc4..720297cbdf87 100644 +--- a/sound/pci/rme9652/hdsp.c ++++ b/sound/pci/rme9652/hdsp.c +@@ -5390,7 +5390,8 @@ static int snd_hdsp_free(struct hdsp *hdsp) + if (hdsp->port) + pci_release_regions(hdsp->pci); + +- pci_disable_device(hdsp->pci); ++ if (pci_is_enabled(hdsp->pci)) ++ pci_disable_device(hdsp->pci); + return 0; + } + +-- +2.30.2 + diff --git a/queue-5.12/alsa-hdspm-don-t-disable-if-not-enabled.patch b/queue-5.12/alsa-hdspm-don-t-disable-if-not-enabled.patch new file mode 100644 index 00000000000..06e929e0eda --- /dev/null +++ b/queue-5.12/alsa-hdspm-don-t-disable-if-not-enabled.patch @@ -0,0 +1,49 @@ +From 729af63ffc2ecfc576561aa120f824588fa8cc88 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Mar 2021 11:38:39 -0400 +Subject: ALSA: hdspm: don't disable if not enabled + +From: Tong Zhang + +[ Upstream commit 790f5719b85e12e10c41753b864e74249585ed08 ] + +hdspm wants to disable a not enabled pci device, which makes kernel +throw a warning. Make sure the device is enabled before calling disable. + +[ 1.786391] snd_hdspm 0000:00:03.0: disabling already-disabled device +[ 1.786400] WARNING: CPU: 0 PID: 182 at drivers/pci/pci.c:2146 pci_disable_device+0x91/0xb0 +[ 1.795181] Call Trace: +[ 1.795320] snd_hdspm_card_free+0x58/0xa0 [snd_hdspm] +[ 1.795595] release_card_device+0x4b/0x80 [snd] +[ 1.795860] device_release+0x3b/0xa0 +[ 1.796072] kobject_put+0x94/0x1b0 +[ 1.796260] put_device+0x13/0x20 +[ 1.796438] snd_card_free+0x61/0x90 [snd] +[ 1.796659] snd_hdspm_probe+0x97b/0x1440 [snd_hdspm] + +Suggested-by: Takashi Iwai +Signed-off-by: Tong Zhang +Link: https://lore.kernel.org/r/20210321153840.378226-3-ztong0001@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/rme9652/hdspm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c +index 8d900c132f0f..97a0bff96b28 100644 +--- a/sound/pci/rme9652/hdspm.c ++++ b/sound/pci/rme9652/hdspm.c +@@ -6883,7 +6883,8 @@ static int snd_hdspm_free(struct hdspm * hdspm) + if (hdspm->port) + pci_release_regions(hdspm->pci); + +- pci_disable_device(hdspm->pci); ++ if (pci_is_enabled(hdspm->pci)) ++ pci_disable_device(hdspm->pci); + return 0; + } + +-- +2.30.2 + diff --git a/queue-5.12/alsa-rme9652-don-t-disable-if-not-enabled.patch b/queue-5.12/alsa-rme9652-don-t-disable-if-not-enabled.patch new file mode 100644 index 00000000000..54697192a13 --- /dev/null +++ b/queue-5.12/alsa-rme9652-don-t-disable-if-not-enabled.patch @@ -0,0 +1,49 @@ +From da9fdd612bb66731f7d1fc0d797ce2e11d1eb7a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Mar 2021 11:38:40 -0400 +Subject: ALSA: rme9652: don't disable if not enabled + +From: Tong Zhang + +[ Upstream commit f57a741874bb6995089020e97a1dcdf9b165dcbe ] + +rme9652 wants to disable a not enabled pci device, which makes kernel +throw a warning. Make sure the device is enabled before calling disable. + +[ 1.751595] snd_rme9652 0000:00:03.0: disabling already-disabled device +[ 1.751605] WARNING: CPU: 0 PID: 174 at drivers/pci/pci.c:2146 pci_disable_device+0x91/0xb0 +[ 1.759968] Call Trace: +[ 1.760145] snd_rme9652_card_free+0x76/0xa0 [snd_rme9652] +[ 1.760434] release_card_device+0x4b/0x80 [snd] +[ 1.760679] device_release+0x3b/0xa0 +[ 1.760874] kobject_put+0x94/0x1b0 +[ 1.761059] put_device+0x13/0x20 +[ 1.761235] snd_card_free+0x61/0x90 [snd] +[ 1.761454] snd_rme9652_probe+0x3be/0x700 [snd_rme9652] + +Suggested-by: Takashi Iwai +Signed-off-by: Tong Zhang +Link: https://lore.kernel.org/r/20210321153840.378226-4-ztong0001@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/rme9652/rme9652.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c +index 4df992e846f2..7a4d395abcee 100644 +--- a/sound/pci/rme9652/rme9652.c ++++ b/sound/pci/rme9652/rme9652.c +@@ -1731,7 +1731,8 @@ static int snd_rme9652_free(struct snd_rme9652 *rme9652) + if (rme9652->port) + pci_release_regions(rme9652->pci); + +- pci_disable_device(rme9652->pci); ++ if (pci_is_enabled(rme9652->pci)) ++ pci_disable_device(rme9652->pci); + return 0; + } + +-- +2.30.2 + diff --git a/queue-5.12/alsa-usb-audio-add-pioneer-djm-850-to-quirks-table.patch b/queue-5.12/alsa-usb-audio-add-pioneer-djm-850-to-quirks-table.patch new file mode 100644 index 00000000000..7d12ac82aba --- /dev/null +++ b/queue-5.12/alsa-usb-audio-add-pioneer-djm-850-to-quirks-table.patch @@ -0,0 +1,99 @@ +From 0c98b85150b43c40bd271d2bdae3ff25072bf3bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 16:27:26 +0100 +Subject: ALSA: usb-audio: Add Pioneer DJM-850 to quirks-table + +From: Nicolas MURE + +[ Upstream commit a3c30b0cb6d05f5bf66d1a5d42e876f31753a447 ] + +Declare the Pioneer DJM-850 interfaces for capture and playback. + +See https://github.com/nm2107/Pioneer-DJM-850-driver-reverse-engineering/blob/172fb9a61055960c88c67b7c416fe5bf3609807b/doc/usb-device-specifications.md +for the complete device spec. + +Signed-off-by: Nicolas MURE +Link: https://lore.kernel.org/r/20210301152729.18094-2-nicolas.mure2019@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/quirks-table.h | 63 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 63 insertions(+) + +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 48facd262658..8a8fe2b980a1 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -3827,6 +3827,69 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), + } + } + }, ++{ ++ /* ++ * Pioneer DJ DJM-850 ++ * 8 channels playback and 8 channels capture @ 44.1/48/96kHz S24LE ++ * Playback on EP 0x05 ++ * Capture on EP 0x86 ++ */ ++ USB_DEVICE_VENDOR_SPEC(0x08e4, 0x0163), ++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_FIXED_ENDPOINT, ++ .data = &(const struct audioformat) { ++ .formats = SNDRV_PCM_FMTBIT_S24_3LE, ++ .channels = 8, ++ .iface = 0, ++ .altsetting = 1, ++ .altset_idx = 1, ++ .endpoint = 0x05, ++ .ep_attr = USB_ENDPOINT_XFER_ISOC| ++ USB_ENDPOINT_SYNC_ASYNC| ++ USB_ENDPOINT_USAGE_DATA, ++ .rates = SNDRV_PCM_RATE_44100| ++ SNDRV_PCM_RATE_48000| ++ SNDRV_PCM_RATE_96000, ++ .rate_min = 44100, ++ .rate_max = 96000, ++ .nr_rates = 3, ++ .rate_table = (unsigned int[]) { 44100, 48000, 96000 } ++ } ++ }, ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_FIXED_ENDPOINT, ++ .data = &(const struct audioformat) { ++ .formats = SNDRV_PCM_FMTBIT_S24_3LE, ++ .channels = 8, ++ .iface = 0, ++ .altsetting = 1, ++ .altset_idx = 1, ++ .endpoint = 0x86, ++ .ep_idx = 1, ++ .ep_attr = USB_ENDPOINT_XFER_ISOC| ++ USB_ENDPOINT_SYNC_ASYNC| ++ USB_ENDPOINT_USAGE_DATA, ++ .rates = SNDRV_PCM_RATE_44100| ++ SNDRV_PCM_RATE_48000| ++ SNDRV_PCM_RATE_96000, ++ .rate_min = 44100, ++ .rate_max = 96000, ++ .nr_rates = 3, ++ .rate_table = (unsigned int[]) { 44100, 48000, 96000 } ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, + { + /* + * Pioneer DJ DJM-450 +-- +2.30.2 + diff --git a/queue-5.12/arm-9064-1-hw_breakpoint-do-not-directly-check-the-e.patch b/queue-5.12/arm-9064-1-hw_breakpoint-do-not-directly-check-the-e.patch new file mode 100644 index 00000000000..02e85cb5a65 --- /dev/null +++ b/queue-5.12/arm-9064-1-hw_breakpoint-do-not-directly-check-the-e.patch @@ -0,0 +1,48 @@ +From 3b94a6c9e98aef4955271a1954dc99c4d0b2bf50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Feb 2021 03:00:05 +0100 +Subject: ARM: 9064/1: hw_breakpoint: Do not directly check the event's + overflow_handler hook + +From: Zhen Lei + +[ Upstream commit a506bd5756290821a4314f502b4bafc2afcf5260 ] + +The commit 1879445dfa7b ("perf/core: Set event's default +::overflow_handler()") set a default event->overflow_handler in +perf_event_alloc(), and replace the check event->overflow_handler with +is_default_overflow_handler(), but one is missing. + +Currently, the bp->overflow_handler can not be NULL. As a result, +enable_single_step() is always not invoked. + +Comments from Zhen Lei: + + https://patchwork.kernel.org/project/linux-arm-kernel/patch/20210207105934.2001-1-thunder.leizhen@huawei.com/ + +Fixes: 1879445dfa7b ("perf/core: Set event's default ::overflow_handler()") +Signed-off-by: Zhen Lei +Cc: Wang Nan +Acked-by: Will Deacon +Signed-off-by: Russell King +Signed-off-by: Sasha Levin +--- + arch/arm/kernel/hw_breakpoint.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c +index 08660ae9dcbc..b1423fb130ea 100644 +--- a/arch/arm/kernel/hw_breakpoint.c ++++ b/arch/arm/kernel/hw_breakpoint.c +@@ -886,7 +886,7 @@ static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs) + info->trigger = addr; + pr_debug("breakpoint fired: address = 0x%x\n", addr); + perf_bp_event(bp, regs); +- if (!bp->overflow_handler) ++ if (is_default_overflow_handler(bp)) + enable_single_step(bp, addr); + goto unlock; + } +-- +2.30.2 + diff --git a/queue-5.12/arm64-entry-always-set-gic_prio_psr_i_set-during-ent.patch b/queue-5.12/arm64-entry-always-set-gic_prio_psr_i_set-during-ent.patch new file mode 100644 index 00000000000..83b4d1dc6d9 --- /dev/null +++ b/queue-5.12/arm64-entry-always-set-gic_prio_psr_i_set-during-ent.patch @@ -0,0 +1,217 @@ +From 7137d5b331c289bf43afcc8c0385071e5d48ca2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 May 2021 12:14:31 -0400 +Subject: arm64: entry: always set GIC_PRIO_PSR_I_SET during entry + +[ Upstream commit 4d6a38da8e79e94cbd1344aa90876f0f805db705 ] + +Zenghui reports that booting a kernel with "irqchip.gicv3_pseudo_nmi=1" +on the command line hits a warning during kernel entry, due to the way +we manipulate the PMR. + +Early in the entry sequence, we call lockdep_hardirqs_off() to inform +lockdep that interrupts have been masked (as the HW sets DAIF wqhen +entering an exception). Architecturally PMR_EL1 is not affected by +exception entry, and we don't set GIC_PRIO_PSR_I_SET in the PMR early in +the exception entry sequence, so early in exception entry the PMR can +indicate that interrupts are unmasked even though they are masked by +DAIF. + +If DEBUG_LOCKDEP is selected, lockdep_hardirqs_off() will check that +interrupts are masked, before we set GIC_PRIO_PSR_I_SET in any of the +exception entry paths, and hence lockdep_hardirqs_off() will WARN() that +something is amiss. + +We can avoid this by consistently setting GIC_PRIO_PSR_I_SET during +exception entry so that kernel code sees a consistent environment. We +must also update local_daif_inherit() to undo this, as currently only +touches DAIF. For other paths, local_daif_restore() will update both +DAIF and the PMR. With this done, we can remove the existing special +cases which set this later in the entry code. + +We always use (GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET) for consistency with +local_daif_save(), as this will warn if it ever encounters +(GIC_PRIO_IRQOFF | GIC_PRIO_PSR_I_SET), and never sets this itself. This +matches the gic_prio_kentry_setup that we have to retain for +ret_to_user. + +The original splat from Zenghui's report was: + +| DEBUG_LOCKS_WARN_ON(!irqs_disabled()) +| WARNING: CPU: 3 PID: 125 at kernel/locking/lockdep.c:4258 lockdep_hardirqs_off+0xd4/0xe8 +| Modules linked in: +| CPU: 3 PID: 125 Comm: modprobe Tainted: G W 5.12.0-rc8+ #463 +| Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015 +| pstate: 604003c5 (nZCv DAIF +PAN -UAO -TCO BTYPE=--) +| pc : lockdep_hardirqs_off+0xd4/0xe8 +| lr : lockdep_hardirqs_off+0xd4/0xe8 +| sp : ffff80002a39bad0 +| pmr_save: 000000e0 +| x29: ffff80002a39bad0 x28: ffff0000de214bc0 +| x27: ffff0000de1c0400 x26: 000000000049b328 +| x25: 0000000000406f30 x24: ffff0000de1c00a0 +| x23: 0000000020400005 x22: ffff8000105f747c +| x21: 0000000096000044 x20: 0000000000498ef9 +| x19: ffff80002a39bc88 x18: ffffffffffffffff +| x17: 0000000000000000 x16: ffff800011c61eb0 +| x15: ffff800011700a88 x14: 0720072007200720 +| x13: 0720072007200720 x12: 0720072007200720 +| x11: 0720072007200720 x10: 0720072007200720 +| x9 : ffff80002a39bad0 x8 : ffff80002a39bad0 +| x7 : ffff8000119f0800 x6 : c0000000ffff7fff +| x5 : ffff8000119f07a8 x4 : 0000000000000001 +| x3 : 9bcdab23f2432800 x2 : ffff800011730538 +| x1 : 9bcdab23f2432800 x0 : 0000000000000000 +| Call trace: +| lockdep_hardirqs_off+0xd4/0xe8 +| enter_from_kernel_mode.isra.5+0x7c/0xa8 +| el1_abort+0x24/0x100 +| el1_sync_handler+0x80/0xd0 +| el1_sync+0x6c/0x100 +| __arch_clear_user+0xc/0x90 +| load_elf_binary+0x9fc/0x1450 +| bprm_execve+0x404/0x880 +| kernel_execve+0x180/0x188 +| call_usermodehelper_exec_async+0xdc/0x158 +| ret_from_fork+0x10/0x18 + +Fixes: 23529049c684 ("arm64: entry: fix non-NMI user<->kernel transitions") +Fixes: 7cd1ea1010ac ("arm64: entry: fix non-NMI kernel<->kernel transitions") +Fixes: f0cd5ac1e4c5 ("arm64: entry: fix NMI {user, kernel}->kernel transitions") +Fixes: 2a9b3e6ac69a ("arm64: entry: fix EL1 debug transitions") +Link: https://lore.kernel.org/r/f4012761-026f-4e51-3a0c-7524e434e8b3@huawei.com +Signed-off-by: Mark Rutland +Reported-by: Zenghui Yu +Cc: Marc Zyngier +Cc: Will Deacon +Acked-by: Marc Zyngier +Link: https://lore.kernel.org/r/20210428111555.50880-1-mark.rutland@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/daifflags.h | 3 +++ + arch/arm64/kernel/entry-common.c | 17 ----------------- + arch/arm64/kernel/entry.S | 15 ++------------- + 3 files changed, 5 insertions(+), 30 deletions(-) + +diff --git a/arch/arm64/include/asm/daifflags.h b/arch/arm64/include/asm/daifflags.h +index 1c26d7baa67f..cfdde3a56805 100644 +--- a/arch/arm64/include/asm/daifflags.h ++++ b/arch/arm64/include/asm/daifflags.h +@@ -131,6 +131,9 @@ static inline void local_daif_inherit(struct pt_regs *regs) + if (interrupts_enabled(regs)) + trace_hardirqs_on(); + ++ if (system_uses_irq_prio_masking()) ++ gic_write_pmr(regs->pmr_save); ++ + /* + * We can't use local_daif_restore(regs->pstate) here as + * system_has_prio_mask_debugging() won't restore the I bit if it can +diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c +index 9d3588450473..117412bae915 100644 +--- a/arch/arm64/kernel/entry-common.c ++++ b/arch/arm64/kernel/entry-common.c +@@ -226,14 +226,6 @@ static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr) + { + unsigned long far = read_sysreg(far_el1); + +- /* +- * The CPU masked interrupts, and we are leaving them masked during +- * do_debug_exception(). Update PMR as if we had called +- * local_daif_mask(). +- */ +- if (system_uses_irq_prio_masking()) +- gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); +- + arm64_enter_el1_dbg(regs); + if (!cortex_a76_erratum_1463225_debug_handler(regs)) + do_debug_exception(far, esr, regs); +@@ -398,9 +390,6 @@ static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr) + /* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */ + unsigned long far = read_sysreg(far_el1); + +- if (system_uses_irq_prio_masking()) +- gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); +- + enter_from_user_mode(); + do_debug_exception(far, esr, regs); + local_daif_restore(DAIF_PROCCTX_NOIRQ); +@@ -408,9 +397,6 @@ static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr) + + static void noinstr el0_svc(struct pt_regs *regs) + { +- if (system_uses_irq_prio_masking()) +- gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); +- + enter_from_user_mode(); + cortex_a76_erratum_1463225_svc_handler(); + do_el0_svc(regs); +@@ -486,9 +472,6 @@ static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr) + + static void noinstr el0_svc_compat(struct pt_regs *regs) + { +- if (system_uses_irq_prio_masking()) +- gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); +- + enter_from_user_mode(); + cortex_a76_erratum_1463225_svc_handler(); + do_el0_svc_compat(regs); +diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S +index feb9e4b9f9f2..e03fba3ae2a0 100644 +--- a/arch/arm64/kernel/entry.S ++++ b/arch/arm64/kernel/entry.S +@@ -292,6 +292,8 @@ alternative_else_nop_endif + alternative_if ARM64_HAS_IRQ_PRIO_MASKING + mrs_s x20, SYS_ICC_PMR_EL1 + str x20, [sp, #S_PMR_SAVE] ++ mov x20, #GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET ++ msr_s SYS_ICC_PMR_EL1, x20 + alternative_else_nop_endif + + /* Re-enable tag checking (TCO set on exception entry) */ +@@ -524,17 +526,7 @@ alternative_endif + #endif + .endm + +- .macro gic_prio_irq_setup, pmr:req, tmp:req +-#ifdef CONFIG_ARM64_PSEUDO_NMI +- alternative_if ARM64_HAS_IRQ_PRIO_MASKING +- orr \tmp, \pmr, #GIC_PRIO_PSR_I_SET +- msr_s SYS_ICC_PMR_EL1, \tmp +- alternative_else_nop_endif +-#endif +- .endm +- + .macro el1_interrupt_handler, handler:req +- gic_prio_irq_setup pmr=x20, tmp=x1 + enable_da_f + + mov x0, sp +@@ -562,7 +554,6 @@ alternative_else_nop_endif + .endm + + .macro el0_interrupt_handler, handler:req +- gic_prio_irq_setup pmr=x20, tmp=x0 + user_exit_irqoff + enable_da_f + +@@ -748,7 +739,6 @@ SYM_CODE_END(el0_irq) + SYM_CODE_START_LOCAL(el1_error) + kernel_entry 1 + mrs x1, esr_el1 +- gic_prio_kentry_setup tmp=x2 + enable_dbg + mov x0, sp + bl do_serror +@@ -759,7 +749,6 @@ SYM_CODE_START_LOCAL(el0_error) + kernel_entry 0 + el0_error_naked: + mrs x25, esr_el1 +- gic_prio_kentry_setup tmp=x2 + user_exit_irqoff + enable_dbg + mov x0, sp +-- +2.30.2 + diff --git a/queue-5.12/arm64-entry-factor-irq-triage-logic-into-macros.patch b/queue-5.12/arm64-entry-factor-irq-triage-logic-into-macros.patch new file mode 100644 index 00000000000..e79a1eb709b --- /dev/null +++ b/queue-5.12/arm64-entry-factor-irq-triage-logic-into-macros.patch @@ -0,0 +1,152 @@ +From ec301e4d131aad1648e28305c8d02ae8265a50d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Mar 2021 11:56:27 +0000 +Subject: arm64: entry: factor irq triage logic into macros + +From: Marc Zyngier + +[ Upstream commit 9eb563cdabe1d583c262042d5d44cc256f644543 ] + +In subsequent patches we'll allow an FIQ handler to be registered, and +FIQ exceptions will need to be triaged very similarly to IRQ exceptions. +So that we can reuse the existing logic, this patch factors the IRQ +triage logic out into macros that can be reused for FIQ. + +The macros are named to follow the elX_foo_handler scheme used by the C +exception handlers. For consistency with other top-level exception +handlers, the kernel_entry/kernel_exit logic is not moved into the +macros. As FIQ will use a different C handler, this handler name is +provided as an argument to the macros. + +There should be no functional change as a result of this patch. + +Signed-off-by: Marc Zyngier +[Mark: rework macros, commit message, rebase before DAIF rework] +Signed-off-by: Mark Rutland +Tested-by: Hector Martin +Cc: James Morse +Cc: Thomas Gleixner +Cc: Will Deacon +Acked-by: Will Deacon +Link: https://lore.kernel.org/r/20210315115629.57191-5-mark.rutland@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/kernel/entry.S | 80 +++++++++++++++++++++------------------ + 1 file changed, 43 insertions(+), 37 deletions(-) + +diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S +index 9b205744a233..feb9e4b9f9f2 100644 +--- a/arch/arm64/kernel/entry.S ++++ b/arch/arm64/kernel/entry.S +@@ -493,8 +493,8 @@ tsk .req x28 // current thread_info + /* + * Interrupt handling. + */ +- .macro irq_handler +- ldr_l x1, handle_arch_irq ++ .macro irq_handler, handler:req ++ ldr_l x1, \handler + mov x0, sp + irq_stack_entry + blr x1 +@@ -533,6 +533,45 @@ alternative_endif + #endif + .endm + ++ .macro el1_interrupt_handler, handler:req ++ gic_prio_irq_setup pmr=x20, tmp=x1 ++ enable_da_f ++ ++ mov x0, sp ++ bl enter_el1_irq_or_nmi ++ ++ irq_handler \handler ++ ++#ifdef CONFIG_PREEMPTION ++ ldr x24, [tsk, #TSK_TI_PREEMPT] // get preempt count ++alternative_if ARM64_HAS_IRQ_PRIO_MASKING ++ /* ++ * DA_F were cleared at start of handling. If anything is set in DAIF, ++ * we come back from an NMI, so skip preemption ++ */ ++ mrs x0, daif ++ orr x24, x24, x0 ++alternative_else_nop_endif ++ cbnz x24, 1f // preempt count != 0 || NMI return path ++ bl arm64_preempt_schedule_irq // irq en/disable is done inside ++1: ++#endif ++ ++ mov x0, sp ++ bl exit_el1_irq_or_nmi ++ .endm ++ ++ .macro el0_interrupt_handler, handler:req ++ gic_prio_irq_setup pmr=x20, tmp=x0 ++ user_exit_irqoff ++ enable_da_f ++ ++ tbz x22, #55, 1f ++ bl do_el0_irq_bp_hardening ++1: ++ irq_handler \handler ++ .endm ++ + .text + + /* +@@ -662,32 +701,7 @@ SYM_CODE_END(el1_sync) + .align 6 + SYM_CODE_START_LOCAL_NOALIGN(el1_irq) + kernel_entry 1 +- gic_prio_irq_setup pmr=x20, tmp=x1 +- enable_da_f +- +- mov x0, sp +- bl enter_el1_irq_or_nmi +- +- irq_handler +- +-#ifdef CONFIG_PREEMPTION +- ldr x24, [tsk, #TSK_TI_PREEMPT] // get preempt count +-alternative_if ARM64_HAS_IRQ_PRIO_MASKING +- /* +- * DA_F were cleared at start of handling. If anything is set in DAIF, +- * we come back from an NMI, so skip preemption +- */ +- mrs x0, daif +- orr x24, x24, x0 +-alternative_else_nop_endif +- cbnz x24, 1f // preempt count != 0 || NMI return path +- bl arm64_preempt_schedule_irq // irq en/disable is done inside +-1: +-#endif +- +- mov x0, sp +- bl exit_el1_irq_or_nmi +- ++ el1_interrupt_handler handle_arch_irq + kernel_exit 1 + SYM_CODE_END(el1_irq) + +@@ -727,15 +741,7 @@ SYM_CODE_END(el0_error_compat) + SYM_CODE_START_LOCAL_NOALIGN(el0_irq) + kernel_entry 0 + el0_irq_naked: +- gic_prio_irq_setup pmr=x20, tmp=x0 +- user_exit_irqoff +- enable_da_f +- +- tbz x22, #55, 1f +- bl do_el0_irq_bp_hardening +-1: +- irq_handler +- ++ el0_interrupt_handler handle_arch_irq + b ret_to_user + SYM_CODE_END(el0_irq) + +-- +2.30.2 + diff --git a/queue-5.12/arm64-stacktrace-restore-terminal-records.patch b/queue-5.12/arm64-stacktrace-restore-terminal-records.patch new file mode 100644 index 00000000000..65c05473679 --- /dev/null +++ b/queue-5.12/arm64-stacktrace-restore-terminal-records.patch @@ -0,0 +1,101 @@ +From 4ae787cab828062d08506ea78fec80ea9edc5e7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 11:20:04 +0100 +Subject: arm64: stacktrace: restore terminal records + +From: Mark Rutland + +[ Upstream commit 8533d5bfad41e74b7dd80d292fd484913cdfb374 ] + +We removed the terminal frame records in commit: + + 6106e1112cc69a36 ("arm64: remove EL0 exception frame record") + +... on the assumption that as we no longer used them to find the pt_regs +at exception boundaries, they were no longer necessary. + +However, Leo reports that as an unintended side-effect, this causes +traces which cross secondary_start_kernel to terminate one entry too +late, with a spurious "0" entry. + +There are a few ways we could sovle this, but as we're planning to use +terminal records for RELIABLE_STACKTRACE, let's revert the logic change +for now, keeping the update comments and accounting for the changes in +commit: + + 3c02600144bdb0a1 ("arm64: stacktrace: Report when we reach the end of the stack") + +This is effectively a partial revert of commit: + + 6106e1112cc69a36 ("arm64: remove EL0 exception frame record") + +Signed-off-by: Mark Rutland +Fixes: 6106e1112cc6 ("arm64: remove EL0 exception frame record") +Reported-by: Leo Yan +Tested-by: Leo Yan +Cc: Will Deacon +Cc: Mark Brown +Cc: "Madhavan T. Venkataraman" +Link: https://lore.kernel.org/r/20210429104813.GA33550@C02TD0UTHF1T.local +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/kernel/entry.S | 6 +++--- + arch/arm64/kernel/stacktrace.c | 10 ++++++---- + 2 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S +index 6acfc5e6b5e0..9b205744a233 100644 +--- a/arch/arm64/kernel/entry.S ++++ b/arch/arm64/kernel/entry.S +@@ -263,16 +263,16 @@ alternative_else_nop_endif + stp lr, x21, [sp, #S_LR] + + /* +- * For exceptions from EL0, terminate the callchain here. ++ * For exceptions from EL0, create a terminal frame record. + * For exceptions from EL1, create a synthetic frame record so the + * interrupted code shows up in the backtrace. + */ + .if \el == 0 +- mov x29, xzr ++ stp xzr, xzr, [sp, #S_STACKFRAME] + .else + stp x29, x22, [sp, #S_STACKFRAME] +- add x29, sp, #S_STACKFRAME + .endif ++ add x29, sp, #S_STACKFRAME + + #ifdef CONFIG_ARM64_SW_TTBR0_PAN + alternative_if_not ARM64_HAS_PAN +diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c +index d55bdfb7789c..7032a5f9e624 100644 +--- a/arch/arm64/kernel/stacktrace.c ++++ b/arch/arm64/kernel/stacktrace.c +@@ -44,10 +44,6 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) + unsigned long fp = frame->fp; + struct stack_info info; + +- /* Terminal record; nothing to unwind */ +- if (!fp) +- return -ENOENT; +- + if (fp & 0xf) + return -EINVAL; + +@@ -108,6 +104,12 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) + + frame->pc = ptrauth_strip_insn_pac(frame->pc); + ++ /* ++ * This is a terminal record, so we have finished unwinding. ++ */ ++ if (!frame->fp && !frame->pc) ++ return -ENOENT; ++ + return 0; + } + NOKPROBE_SYMBOL(unwind_frame); +-- +2.30.2 + diff --git a/queue-5.12/asoc-intel-bytcr_rt5640-add-quirk-for-the-chuwi-hi8-.patch b/queue-5.12/asoc-intel-bytcr_rt5640-add-quirk-for-the-chuwi-hi8-.patch new file mode 100644 index 00000000000..6d01fa2879d --- /dev/null +++ b/queue-5.12/asoc-intel-bytcr_rt5640-add-quirk-for-the-chuwi-hi8-.patch @@ -0,0 +1,56 @@ +From c5d02840ec970561dd25caef4276c6a25bb9bc7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Mar 2021 23:10:54 +0100 +Subject: ASoC: Intel: bytcr_rt5640: Add quirk for the Chuwi Hi8 tablet + +From: Hans de Goede + +[ Upstream commit 875c40eadf6ac6644c0f71842a4f30dd9968d281 ] + +The Chuwi Hi8 tablet is using an analog mic on IN1 and has its +jack-detect connected to JD2_IN4N, instead of using the default +IN3 for its internal mic and JD1_IN4P for jack-detect. + +It also only has 1 speaker. + +Add a quirk applying the correct settings for this configuration. + +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20210325221054.22714-1-hdegoede@redhat.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/intel/boards/bytcr_rt5640.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c +index 19faababb78d..22912cab5e63 100644 +--- a/sound/soc/intel/boards/bytcr_rt5640.c ++++ b/sound/soc/intel/boards/bytcr_rt5640.c +@@ -518,6 +518,23 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, ++ { ++ /* Chuwi Hi8 (CWI509) */ ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), ++ DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"), ++ DMI_MATCH(DMI_SYS_VENDOR, "ilife"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "S806"), ++ }, ++ .driver_data = (void *)(BYT_RT5640_IN1_MAP | ++ BYT_RT5640_JD_SRC_JD2_IN4N | ++ BYT_RT5640_OVCD_TH_2000UA | ++ BYT_RT5640_OVCD_SF_0P75 | ++ BYT_RT5640_MONO_SPEAKER | ++ BYT_RT5640_DIFF_MIC | ++ BYT_RT5640_SSP0_AIF1 | ++ BYT_RT5640_MCLK_EN), ++ }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), +-- +2.30.2 + diff --git a/queue-5.12/asoc-intel-bytcr_rt5640-enable-jack-detect-support-o.patch b/queue-5.12/asoc-intel-bytcr_rt5640-enable-jack-detect-support-o.patch new file mode 100644 index 00000000000..1aa96650cbf --- /dev/null +++ b/queue-5.12/asoc-intel-bytcr_rt5640-enable-jack-detect-support-o.patch @@ -0,0 +1,41 @@ +From 82eaadfa072d70cbbdb178ccc1250a3e9d9674a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Mar 2021 12:48:50 +0100 +Subject: ASoC: Intel: bytcr_rt5640: Enable jack-detect support on Asus T100TAF + +From: Hans de Goede + +[ Upstream commit b7c7203a1f751348f35fc4bcb157572d303f7573 ] + +The Asus T100TAF uses the same jack-detect settings as the T100TA, +this has been confirmed on actual hardware. + +Add these settings to the T100TAF quirks to enable jack-detect support +on the T100TAF. + +Signed-off-by: Hans de Goede +Acked-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20210312114850.13832-1-hdegoede@redhat.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/intel/boards/bytcr_rt5640.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c +index 5d48cc359c3d..19faababb78d 100644 +--- a/sound/soc/intel/boards/bytcr_rt5640.c ++++ b/sound/soc/intel/boards/bytcr_rt5640.c +@@ -482,6 +482,9 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), + }, + .driver_data = (void *)(BYT_RT5640_IN1_MAP | ++ BYT_RT5640_JD_SRC_JD2_IN4N | ++ BYT_RT5640_OVCD_TH_2000UA | ++ BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_MONO_SPEAKER | + BYT_RT5640_DIFF_MIC | + BYT_RT5640_SSP0_AIF2 | +-- +2.30.2 + diff --git a/queue-5.12/asoc-intel-sof_sdw-add-quirk-for-new-adl-p-rvp.patch b/queue-5.12/asoc-intel-sof_sdw-add-quirk-for-new-adl-p-rvp.patch new file mode 100644 index 00000000000..503e082ff96 --- /dev/null +++ b/queue-5.12/asoc-intel-sof_sdw-add-quirk-for-new-adl-p-rvp.patch @@ -0,0 +1,47 @@ +From eda6129220714a6becd21bd882c00b761a03b6b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 12:50:09 -0500 +Subject: ASoC: Intel: sof_sdw: add quirk for new ADL-P Rvp + +From: Vamshi Krishna Gopal + +[ Upstream commit d25bbe80485f8bcbbeb91a2a6cd8798c124b27b7 ] + +Add quirks for jack detection, rt711 DAI and DMIC + +Reviewed-by: Bard Liao +Reviewed-by: Kai Vehmanen +Signed-off-by: Vamshi Krishna Gopal +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20210415175013.192862-6-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/intel/boards/sof_sdw.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c +index 8adce6417b02..ecd3f90f4bbe 100644 +--- a/sound/soc/intel/boards/sof_sdw.c ++++ b/sound/soc/intel/boards/sof_sdw.c +@@ -187,6 +187,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { + SOF_RT715_DAI_ID_FIX | + SOF_SDW_FOUR_SPK), + }, ++ /* AlderLake devices */ ++ { ++ .callback = sof_sdw_quirk_cb, ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), ++ }, ++ .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | ++ SOF_SDW_TGL_HDMI | ++ SOF_SDW_PCH_DMIC), ++ }, + {} + }; + +-- +2.30.2 + diff --git a/queue-5.12/asoc-rsnd-call-rsnd_ssi_master_clk_start-from-rsnd_s.patch b/queue-5.12/asoc-rsnd-call-rsnd_ssi_master_clk_start-from-rsnd_s.patch new file mode 100644 index 00000000000..f9e7d33dce3 --- /dev/null +++ b/queue-5.12/asoc-rsnd-call-rsnd_ssi_master_clk_start-from-rsnd_s.patch @@ -0,0 +1,116 @@ +From 4e84395231282ae11294fede37db62895949217a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Apr 2021 13:28:38 +0900 +Subject: ASoC: rsnd: call rsnd_ssi_master_clk_start() from rsnd_ssi_init() + +From: Kuninori Morimoto + +[ Upstream commit a122a116fc6d8fcf2f202dcd185173a54268f239 ] + +Current rsnd needs to call .prepare (P) for clock settings, +.trigger for playback start (S) and stop (E). +It should be called as below from SSI point of view. + + P -> S -> E -> P -> S -> E -> ... + +But, if you used MIXer, below case might happen + + (2) + 1: P -> S ---> E -> ... + 2: P ----> S -> ... + (1) (3) + +P(1) setups clock, but E(2) resets it. and starts playback (3). +In such case, it will reports "SSI parent/child should use same rate". + +rsnd_ssi_master_clk_start() which is the main function at (P) +was called from rsnd_ssi_init() (= S) before, +but was moved by below patch to rsnd_soc_dai_prepare() (= P) to avoid +using clk_get_rate() which shouldn't be used under atomic context. + + commit 4d230d1271064 ("ASoC: rsnd: fixup not to call clk_get/set + under non-atomic") + +Because of above patch, rsnd_ssi_master_clk_start() is now called at (P) +which is for non atomic context. But (P) is assuming that spin lock is +*not* used. +One issue now is rsnd_ssi_master_clk_start() is checking ssi->xxx +which should be protected by spin lock. + +After above patch, adg.c had below patch for other reasons. + + commit 06e8f5c842f2d ("ASoC: rsnd: don't call clk_get_rate() + under atomic context") + +clk_get_rate() is used at probe() timing by this patch. +In other words, rsnd_ssi_master_clk_start() is no longer using +clk_get_rate() any more. + +This means we can call it from rsnd_ssi_init() (= S) again which is +protected by spin lock. +This patch re-move it to under spin lock, and solves +1. checking ssi->xxx without spin lock issue. +2. clk setting / device start / device stop race condition. + +Reported-by: Linh Phung T. Y. +Signed-off-by: Kuninori Morimoto +Link: https://lore.kernel.org/r/875z0x1jt5.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sh/rcar/ssi.c | 14 +++++--------- + 1 file changed, 5 insertions(+), 9 deletions(-) + +diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c +index d0ded427a836..a2f8138d40c7 100644 +--- a/sound/soc/sh/rcar/ssi.c ++++ b/sound/soc/sh/rcar/ssi.c +@@ -507,10 +507,15 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, + struct rsnd_priv *priv) + { + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); ++ int ret; + + if (!rsnd_ssi_is_run_mods(mod, io)) + return 0; + ++ ret = rsnd_ssi_master_clk_start(mod, io); ++ if (ret < 0) ++ return ret; ++ + ssi->usrcnt++; + + rsnd_mod_power_on(mod); +@@ -1060,13 +1065,6 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod, + return 0; + } + +-static int rsnd_ssi_prepare(struct rsnd_mod *mod, +- struct rsnd_dai_stream *io, +- struct rsnd_priv *priv) +-{ +- return rsnd_ssi_master_clk_start(mod, io); +-} +- + static struct rsnd_mod_ops rsnd_ssi_pio_ops = { + .name = SSI_NAME, + .probe = rsnd_ssi_common_probe, +@@ -1079,7 +1077,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { + .pointer = rsnd_ssi_pio_pointer, + .pcm_new = rsnd_ssi_pcm_new, + .hw_params = rsnd_ssi_hw_params, +- .prepare = rsnd_ssi_prepare, + .get_status = rsnd_ssi_get_status, + }; + +@@ -1166,7 +1163,6 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { + .pcm_new = rsnd_ssi_pcm_new, + .fallback = rsnd_ssi_fallback, + .hw_params = rsnd_ssi_hw_params, +- .prepare = rsnd_ssi_prepare, + .get_status = rsnd_ssi_get_status, + }; + +-- +2.30.2 + diff --git a/queue-5.12/asoc-rsnd-core-check-convert-rate-in-rsnd_hw_params.patch b/queue-5.12/asoc-rsnd-core-check-convert-rate-in-rsnd_hw_params.patch new file mode 100644 index 00000000000..8735fc68d2f --- /dev/null +++ b/queue-5.12/asoc-rsnd-core-check-convert-rate-in-rsnd_hw_params.patch @@ -0,0 +1,113 @@ +From 5dbe80685a9ae165422d6916c1a4b9c5bcf639a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Mar 2021 14:47:35 +1000 +Subject: ASoC: rsnd: core: Check convert rate in rsnd_hw_params + +From: Mikhail Durnev + +[ Upstream commit 19c6a63ced5e07e40f3a5255cb1f0fe0d3be7b14 ] + +snd_pcm_hw_params_set_rate_near can return incorrect sample rate in +some cases, e.g. when the backend output rate is set to some value higher +than 48000 Hz and the input rate is 8000 Hz. So passing the value returned +by snd_pcm_hw_params_set_rate_near to snd_pcm_hw_params will result in +"FSO/FSI ratio error" and playing no audio at all while the userland +is not properly notified about the issue. + +If SRC is unable to convert the requested sample rate to the sample rate +the backend is using, then the requested sample rate should be adjusted in +rsnd_hw_params. The userland will be notified about that change in the +returned hw_params structure. + +Signed-off-by: Mikhail Durnev +Link: https://lore.kernel.org/r/1615870055-13954-1-git-send-email-mikhail_durnev@mentor.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sh/rcar/core.c | 69 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 68 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c +index 1029d8d9d800..d2b4632d9c2a 100644 +--- a/sound/soc/sh/rcar/core.c ++++ b/sound/soc/sh/rcar/core.c +@@ -1428,8 +1428,75 @@ static int rsnd_hw_params(struct snd_soc_component *component, + } + if (io->converted_chan) + dev_dbg(dev, "convert channels = %d\n", io->converted_chan); +- if (io->converted_rate) ++ if (io->converted_rate) { ++ /* ++ * SRC supports convert rates from params_rate(hw_params)/k_down ++ * to params_rate(hw_params)*k_up, where k_up is always 6, and ++ * k_down depends on number of channels and SRC unit. ++ * So all SRC units can upsample audio up to 6 times regardless ++ * its number of channels. And all SRC units can downsample ++ * 2 channel audio up to 6 times too. ++ */ ++ int k_up = 6; ++ int k_down = 6; ++ int channel; ++ struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); ++ + dev_dbg(dev, "convert rate = %d\n", io->converted_rate); ++ ++ channel = io->converted_chan ? io->converted_chan : ++ params_channels(hw_params); ++ ++ switch (rsnd_mod_id(src_mod)) { ++ /* ++ * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times. ++ * SRC1, SRC3 and SRC4 can downsample 4 channel audio ++ * up to 4 times. ++ * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio ++ * no more than twice. ++ */ ++ case 1: ++ case 3: ++ case 4: ++ if (channel > 4) { ++ k_down = 2; ++ break; ++ } ++ fallthrough; ++ case 0: ++ if (channel > 2) ++ k_down = 4; ++ break; ++ ++ /* Other SRC units do not support more than 2 channels */ ++ default: ++ if (channel > 2) ++ return -EINVAL; ++ } ++ ++ if (params_rate(hw_params) > io->converted_rate * k_down) { ++ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min = ++ io->converted_rate * k_down; ++ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max = ++ io->converted_rate * k_down; ++ hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE; ++ } else if (params_rate(hw_params) * k_up < io->converted_rate) { ++ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min = ++ (io->converted_rate + k_up - 1) / k_up; ++ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max = ++ (io->converted_rate + k_up - 1) / k_up; ++ hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE; ++ } ++ ++ /* ++ * TBD: Max SRC input and output rates also depend on number ++ * of channels and SRC unit: ++ * SRC1, SRC3 and SRC4 do not support more than 128kHz ++ * for 6 channel and 96kHz for 8 channel audio. ++ * Perhaps this function should return EINVAL if the input or ++ * the output rate exceeds the limitation. ++ */ ++ } + } + + return rsnd_dai_call(hw_params, io, substream, hw_params); +-- +2.30.2 + diff --git a/queue-5.12/asoc-rt286-generalize-support-for-alc3263-codec.patch b/queue-5.12/asoc-rt286-generalize-support-for-alc3263-codec.patch new file mode 100644 index 00000000000..41c514748b4 --- /dev/null +++ b/queue-5.12/asoc-rt286-generalize-support-for-alc3263-codec.patch @@ -0,0 +1,99 @@ +From 7d4bcd28f696c9547455181b9263481e6fb8a693 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 Apr 2021 09:46:58 -0400 +Subject: ASoC: rt286: Generalize support for ALC3263 codec + +From: David Ward + +[ Upstream commit aa2f9c12821e6a4ba1df4fb34a3dbc6a2a1ee7fe ] + +The ALC3263 codec on the XPS 13 9343 is also found on the Latitude 13 7350 +and Venue 11 Pro 7140. They require the same handling for the combo jack to +work with a headset: GPIO pin 6 must be set. + +The HDA driver always sets this pin on the ALC3263, which it distinguishes +by the codec vendor/device ID 0x10ec0288 and PCI subsystem vendor ID 0x1028 +(Dell). The ASoC driver does not use PCI, so adapt this check to use DMI to +determine if Dell is the system vendor. + +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=150601 +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=205961 +Signed-off-by: David Ward +Reviewed-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20210418134658.4333-6-david.ward@gatech.edu +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/rt286.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c +index 8abe232ca4a4..2f18f5114f7e 100644 +--- a/sound/soc/codecs/rt286.c ++++ b/sound/soc/codecs/rt286.c +@@ -1117,12 +1117,11 @@ static const struct dmi_system_id force_combo_jack_table[] = { + { } + }; + +-static const struct dmi_system_id dmi_dell_dino[] = { ++static const struct dmi_system_id dmi_dell[] = { + { +- .ident = "Dell Dino", ++ .ident = "Dell", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343") + } + }, + { } +@@ -1133,7 +1132,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, + { + struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev); + struct rt286_priv *rt286; +- int i, ret, val; ++ int i, ret, vendor_id; + + rt286 = devm_kzalloc(&i2c->dev, sizeof(*rt286), + GFP_KERNEL); +@@ -1149,14 +1148,15 @@ static int rt286_i2c_probe(struct i2c_client *i2c, + } + + ret = regmap_read(rt286->regmap, +- RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val); ++ RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &vendor_id); + if (ret != 0) { + dev_err(&i2c->dev, "I2C error %d\n", ret); + return ret; + } +- if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) { ++ if (vendor_id != RT286_VENDOR_ID && vendor_id != RT288_VENDOR_ID) { + dev_err(&i2c->dev, +- "Device with ID register %#x is not rt286\n", val); ++ "Device with ID register %#x is not rt286\n", ++ vendor_id); + return -ENODEV; + } + +@@ -1180,8 +1180,8 @@ static int rt286_i2c_probe(struct i2c_client *i2c, + if (pdata) + rt286->pdata = *pdata; + +- if (dmi_check_system(force_combo_jack_table) || +- dmi_check_system(dmi_dell_dino)) ++ if ((vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) || ++ dmi_check_system(force_combo_jack_table)) + rt286->pdata.cbj_en = true; + + regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); +@@ -1220,7 +1220,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, + regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); + regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); + +- if (dmi_check_system(dmi_dell_dino)) { ++ if (vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) { + regmap_update_bits(rt286->regmap, + RT286_SET_GPIO_MASK, 0x40, 0x40); + regmap_update_bits(rt286->regmap, +-- +2.30.2 + diff --git a/queue-5.12/asoc-rt286-make-rt286_set_gpio_-readable-and-writabl.patch b/queue-5.12/asoc-rt286-make-rt286_set_gpio_-readable-and-writabl.patch new file mode 100644 index 00000000000..ae50c01c546 --- /dev/null +++ b/queue-5.12/asoc-rt286-make-rt286_set_gpio_-readable-and-writabl.patch @@ -0,0 +1,39 @@ +From 38ef62bc7791683c87bd34c325faef5953195a33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 Apr 2021 09:46:57 -0400 +Subject: ASoC: rt286: Make RT286_SET_GPIO_* readable and writable + +From: David Ward + +[ Upstream commit cd8499d5c03ba260e3191e90236d0e5f6b147563 ] + +The GPIO configuration cannot be applied if the registers are inaccessible. +This prevented the headset mic from working on the Dell XPS 13 9343. + +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=114171 +Signed-off-by: David Ward +Link: https://lore.kernel.org/r/20210418134658.4333-5-david.ward@gatech.edu +Reviewed-by: Pierre-Louis Bossart +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/rt286.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c +index 2f18f5114f7e..ff23a7d4d2ac 100644 +--- a/sound/soc/codecs/rt286.c ++++ b/sound/soc/codecs/rt286.c +@@ -171,6 +171,9 @@ static bool rt286_readable_register(struct device *dev, unsigned int reg) + case RT286_PROC_COEF: + case RT286_SET_AMP_GAIN_ADC_IN1: + case RT286_SET_AMP_GAIN_ADC_IN2: ++ case RT286_SET_GPIO_MASK: ++ case RT286_SET_GPIO_DIRECTION: ++ case RT286_SET_GPIO_DATA: + case RT286_SET_POWER(RT286_DAC_OUT1): + case RT286_SET_POWER(RT286_DAC_OUT2): + case RT286_SET_POWER(RT286_ADC_IN1): +-- +2.30.2 + diff --git a/queue-5.12/asoc-rt5670-add-a-quirk-for-the-dell-venue-10-pro-50.patch b/queue-5.12/asoc-rt5670-add-a-quirk-for-the-dell-venue-10-pro-50.patch new file mode 100644 index 00000000000..4e0008f186a --- /dev/null +++ b/queue-5.12/asoc-rt5670-add-a-quirk-for-the-dell-venue-10-pro-50.patch @@ -0,0 +1,47 @@ +From 7501b5d6f145f5fd4f796967610187e538a100df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Apr 2021 16:07:45 +0200 +Subject: ASoC: rt5670: Add a quirk for the Dell Venue 10 Pro 5055 + +From: Hans de Goede + +[ Upstream commit 84cb0d5581b6a7bd5d96013f67e9f2eb0c7b4378 ] + +Add a quirk with the jack-detect and dmic settings necessary to make +jack-detect and the builtin mic work on Dell Venue 10 Pro 5055 tablets. + +Signed-off-by: Hans de Goede +Acked-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20210402140747.174716-5-hdegoede@redhat.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/rt5670.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c +index 4063aac2a443..dd69d874bad2 100644 +--- a/sound/soc/codecs/rt5670.c ++++ b/sound/soc/codecs/rt5670.c +@@ -2980,6 +2980,18 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { + RT5670_GPIO1_IS_IRQ | + RT5670_JD_MODE3), + }, ++ { ++ .callback = rt5670_quirk_cb, ++ .ident = "Dell Venue 10 Pro 5055", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Venue 10 Pro 5055"), ++ }, ++ .driver_data = (unsigned long *)(RT5670_DMIC_EN | ++ RT5670_DMIC2_INR | ++ RT5670_GPIO1_IS_IRQ | ++ RT5670_JD_MODE1), ++ }, + { + .callback = rt5670_quirk_cb, + .ident = "Aegex 10 tablet (RU2)", +-- +2.30.2 + diff --git a/queue-5.12/asoc-soc-compress-lock-pcm_mutex-to-resolve-lockdep-.patch b/queue-5.12/asoc-soc-compress-lock-pcm_mutex-to-resolve-lockdep-.patch new file mode 100644 index 00000000000..9b0ae6ce939 --- /dev/null +++ b/queue-5.12/asoc-soc-compress-lock-pcm_mutex-to-resolve-lockdep-.patch @@ -0,0 +1,61 @@ +From 16bb2e7ef9c85ac0afd4524e1b1571a7ee07a6b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Apr 2021 13:14:04 +0900 +Subject: ASoC: soc-compress: lock pcm_mutex to resolve lockdep error + +From: Gyeongtaek Lee + +[ Upstream commit 45475bf60cc1d42da229a0aa757180c88bab8d22 ] + +If panic_on_warn=1 is added in bootargs and compress offload playback with +DPCM is started, kernel panic would be occurred because rtd->card->pcm_mutex +isn't held in soc_compr_open_fe() and soc_compr_free_fe() and it generates +lockdep warning in the following code. + +void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, + int stream, int action) +{ + struct snd_soc_dai *dai; + int i; + + lockdep_assert_held(&rtd->card->pcm_mutex); + +To prevent lockdep warning but minimize side effect by adding mutex, +pcm_mutex is held just before snd_soc_runtime_activate() and +snd_soc_runtime_deactivate() and is released right after them. + +Signed-off-by: Gyeongtaek Lee +Link: https://lore.kernel.org/r/1891546521.01617772502282.JavaMail.epsvc@epcpadp3 +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/soc-compress.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c +index 246a5e32e22a..b4810266f5e5 100644 +--- a/sound/soc/soc-compress.c ++++ b/sound/soc/soc-compress.c +@@ -153,7 +153,9 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) + fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; + fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; + ++ mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); + snd_soc_runtime_activate(fe, stream); ++ mutex_unlock(&fe->card->pcm_mutex); + + mutex_unlock(&fe->card->mutex); + +@@ -181,7 +183,9 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) + + mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + ++ mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); + snd_soc_runtime_deactivate(fe, stream); ++ mutex_unlock(&fe->card->pcm_mutex); + + fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; + +-- +2.30.2 + diff --git a/queue-5.12/ata-ahci_brcm-fix-use-of-bcm7216-reset-controller.patch b/queue-5.12/ata-ahci_brcm-fix-use-of-bcm7216-reset-controller.patch new file mode 100644 index 00000000000..15bc77b1ff9 --- /dev/null +++ b/queue-5.12/ata-ahci_brcm-fix-use-of-bcm7216-reset-controller.patch @@ -0,0 +1,129 @@ +From 571dde1f73e559540f354c58bb3e08640f8b6d2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Apr 2021 11:21:55 -0400 +Subject: ata: ahci_brcm: Fix use of BCM7216 reset controller + +From: Jim Quinlan + +[ Upstream commit e8d6f9e56187c101b325e8d18f1d4032420d08ff ] + +This driver may use one of two resets controllers. Keep them in separate +variables to keep things simple. The reset controller "rescal" is shared +between the AHCI driver and the PCIe driver for the BrcmSTB 7216 chip. Use +devm_reset_control_get_optional_shared() to handle this sharing. + +[bhelgaas: add Jens' ack from v5 posting] +Fixes: 272ecd60a636 ("ata: ahci_brcm: BCM7216 reset is self de-asserting") +Fixes: c345ec6a50e9 ("ata: ahci_brcm: Support BCM7216 reset controller name") +Link: https://lore.kernel.org/r/20210430152156.21162-3-jim2101024@gmail.com +Signed-off-by: Jim Quinlan +Signed-off-by: Bjorn Helgaas +Acked-by: Jens Axboe +Acked-by: Florian Fainelli +Signed-off-by: Sasha Levin +--- + drivers/ata/ahci_brcm.c | 46 ++++++++++++++++++++--------------------- + 1 file changed, 23 insertions(+), 23 deletions(-) + +diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c +index 5b32df5d33ad..6e9c5ade4c2e 100644 +--- a/drivers/ata/ahci_brcm.c ++++ b/drivers/ata/ahci_brcm.c +@@ -86,7 +86,8 @@ struct brcm_ahci_priv { + u32 port_mask; + u32 quirks; + enum brcm_ahci_version version; +- struct reset_control *rcdev; ++ struct reset_control *rcdev_rescal; ++ struct reset_control *rcdev_ahci; + }; + + static inline u32 brcm_sata_readreg(void __iomem *addr) +@@ -352,8 +353,8 @@ static int brcm_ahci_suspend(struct device *dev) + else + ret = 0; + +- if (priv->version != BRCM_SATA_BCM7216) +- reset_control_assert(priv->rcdev); ++ reset_control_assert(priv->rcdev_ahci); ++ reset_control_rearm(priv->rcdev_rescal); + + return ret; + } +@@ -365,10 +366,10 @@ static int __maybe_unused brcm_ahci_resume(struct device *dev) + struct brcm_ahci_priv *priv = hpriv->plat_data; + int ret = 0; + +- if (priv->version == BRCM_SATA_BCM7216) +- ret = reset_control_reset(priv->rcdev); +- else +- ret = reset_control_deassert(priv->rcdev); ++ ret = reset_control_deassert(priv->rcdev_ahci); ++ if (ret) ++ return ret; ++ ret = reset_control_reset(priv->rcdev_rescal); + if (ret) + return ret; + +@@ -434,7 +435,6 @@ static int brcm_ahci_probe(struct platform_device *pdev) + { + const struct of_device_id *of_id; + struct device *dev = &pdev->dev; +- const char *reset_name = NULL; + struct brcm_ahci_priv *priv; + struct ahci_host_priv *hpriv; + struct resource *res; +@@ -456,15 +456,15 @@ static int brcm_ahci_probe(struct platform_device *pdev) + if (IS_ERR(priv->top_ctrl)) + return PTR_ERR(priv->top_ctrl); + +- /* Reset is optional depending on platform and named differently */ +- if (priv->version == BRCM_SATA_BCM7216) +- reset_name = "rescal"; +- else +- reset_name = "ahci"; +- +- priv->rcdev = devm_reset_control_get_optional(&pdev->dev, reset_name); +- if (IS_ERR(priv->rcdev)) +- return PTR_ERR(priv->rcdev); ++ if (priv->version == BRCM_SATA_BCM7216) { ++ priv->rcdev_rescal = devm_reset_control_get_optional_shared( ++ &pdev->dev, "rescal"); ++ if (IS_ERR(priv->rcdev_rescal)) ++ return PTR_ERR(priv->rcdev_rescal); ++ } ++ priv->rcdev_ahci = devm_reset_control_get_optional(&pdev->dev, "ahci"); ++ if (IS_ERR(priv->rcdev_ahci)) ++ return PTR_ERR(priv->rcdev_ahci); + + hpriv = ahci_platform_get_resources(pdev, 0); + if (IS_ERR(hpriv)) +@@ -485,10 +485,10 @@ static int brcm_ahci_probe(struct platform_device *pdev) + break; + } + +- if (priv->version == BRCM_SATA_BCM7216) +- ret = reset_control_reset(priv->rcdev); +- else +- ret = reset_control_deassert(priv->rcdev); ++ ret = reset_control_reset(priv->rcdev_rescal); ++ if (ret) ++ return ret; ++ ret = reset_control_deassert(priv->rcdev_ahci); + if (ret) + return ret; + +@@ -539,8 +539,8 @@ out_disable_regulators: + out_disable_clks: + ahci_platform_disable_clks(hpriv); + out_reset: +- if (priv->version != BRCM_SATA_BCM7216) +- reset_control_assert(priv->rcdev); ++ reset_control_assert(priv->rcdev_ahci); ++ reset_control_rearm(priv->rcdev_rescal); + return ret; + } + +-- +2.30.2 + diff --git a/queue-5.12/ath11k-fix-thermal-temperature-read.patch b/queue-5.12/ath11k-fix-thermal-temperature-read.patch new file mode 100644 index 00000000000..1007bbec712 --- /dev/null +++ b/queue-5.12/ath11k-fix-thermal-temperature-read.patch @@ -0,0 +1,106 @@ +From 3e97ad80123de989dff3d0306b52fd07520a6cd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Feb 2021 10:27:08 -0800 +Subject: ath11k: fix thermal temperature read + +From: Pradeep Kumar Chitrapu + +[ Upstream commit e3de5bb7ac1a4cb262f8768924fd3ef6182b10bb ] + +Fix dangling pointer in thermal temperature event which causes +incorrect temperature read. + +Tested-on: IPQ8074 AHB WLAN.HK.2.4.0.1-00041-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Pradeep Kumar Chitrapu +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20210218182708.8844-1-pradeepc@codeaurora.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/wmi.c | 53 +++++++++++---------------- + 1 file changed, 21 insertions(+), 32 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index cccfd3bd4d27..ca5cda890d58 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -5417,31 +5417,6 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb, + return 0; + } + +-static int +-ath11k_pull_pdev_temp_ev(struct ath11k_base *ab, u8 *evt_buf, +- u32 len, const struct wmi_pdev_temperature_event *ev) +-{ +- const void **tb; +- int ret; +- +- tb = ath11k_wmi_tlv_parse_alloc(ab, evt_buf, len, GFP_ATOMIC); +- if (IS_ERR(tb)) { +- ret = PTR_ERR(tb); +- ath11k_warn(ab, "failed to parse tlv: %d\n", ret); +- return ret; +- } +- +- ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT]; +- if (!ev) { +- ath11k_warn(ab, "failed to fetch pdev temp ev"); +- kfree(tb); +- return -EPROTO; +- } +- +- kfree(tb); +- return 0; +-} +- + size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head) + { + struct ath11k_fw_stats_vdev *i; +@@ -6849,23 +6824,37 @@ ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab, + struct sk_buff *skb) + { + struct ath11k *ar; +- struct wmi_pdev_temperature_event ev = {0}; ++ const void **tb; ++ const struct wmi_pdev_temperature_event *ev; ++ int ret; ++ ++ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); ++ if (IS_ERR(tb)) { ++ ret = PTR_ERR(tb); ++ ath11k_warn(ab, "failed to parse tlv: %d\n", ret); ++ return; ++ } + +- if (ath11k_pull_pdev_temp_ev(ab, skb->data, skb->len, &ev) != 0) { +- ath11k_warn(ab, "failed to extract pdev temperature event"); ++ ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT]; ++ if (!ev) { ++ ath11k_warn(ab, "failed to fetch pdev temp ev"); ++ kfree(tb); + return; + } + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "pdev temperature ev temp %d pdev_id %d\n", ev.temp, ev.pdev_id); ++ "pdev temperature ev temp %d pdev_id %d\n", ev->temp, ev->pdev_id); + +- ar = ath11k_mac_get_ar_by_pdev_id(ab, ev.pdev_id); ++ ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id); + if (!ar) { +- ath11k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev.pdev_id); ++ ath11k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev->pdev_id); ++ kfree(tb); + return; + } + +- ath11k_thermal_event_temperature(ar, ev.temp); ++ ath11k_thermal_event_temperature(ar, ev->temp); ++ ++ kfree(tb); + } + + static void ath11k_fils_discovery_event(struct ath11k_base *ab, +-- +2.30.2 + diff --git a/queue-5.12/block-rnbd-clt-change-queue_depth-type-in-rnbd_clt_s.patch b/queue-5.12/block-rnbd-clt-change-queue_depth-type-in-rnbd_clt_s.patch new file mode 100644 index 00000000000..c9d5cf1832f --- /dev/null +++ b/queue-5.12/block-rnbd-clt-change-queue_depth-type-in-rnbd_clt_s.patch @@ -0,0 +1,40 @@ +From 3b3c3dda45001cf29c758892becefdb0d3455a97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Apr 2021 08:13:56 +0200 +Subject: block/rnbd-clt: Change queue_depth type in rnbd_clt_session to size_t + +From: Md Haris Iqbal + +[ Upstream commit 80d43cbd46155744ee450d2476ee4fcf2917ae9b ] + +The member queue_depth in the structure rnbd_clt_session is read from the +rtrs client side using the function rtrs_clt_query, which in turn is read +from the rtrs_clt structure. It should really be of type size_t. + +Fixes: 90426e89f54db ("block/rnbd: client: private header with client structs and functions") +Signed-off-by: Md Haris Iqbal +Reviewed-by: Guoqing Jiang +Signed-off-by: Gioh Kim +Link: https://lore.kernel.org/r/20210428061359.206794-2-gi-oh.kim@ionos.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/rnbd/rnbd-clt.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/block/rnbd/rnbd-clt.h b/drivers/block/rnbd/rnbd-clt.h +index 537d499dad3b..73d980840531 100644 +--- a/drivers/block/rnbd/rnbd-clt.h ++++ b/drivers/block/rnbd/rnbd-clt.h +@@ -87,7 +87,7 @@ struct rnbd_clt_session { + DECLARE_BITMAP(cpu_queues_bm, NR_CPUS); + int __percpu *cpu_rr; /* per-cpu var for CPU round-robin */ + atomic_t busy; +- int queue_depth; ++ size_t queue_depth; + u32 max_io_size; + struct blk_mq_tag_set tag_set; + struct mutex lock; /* protects state and devs_list */ +-- +2.30.2 + diff --git a/queue-5.12/block-rnbd-clt-check-the-return-value-of-the-functio.patch b/queue-5.12/block-rnbd-clt-check-the-return-value-of-the-functio.patch new file mode 100644 index 00000000000..afec036ef9b --- /dev/null +++ b/queue-5.12/block-rnbd-clt-check-the-return-value-of-the-functio.patch @@ -0,0 +1,58 @@ +From b207ed4b53285dc8f4ee8db554ad3f8c176ed147 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Apr 2021 08:13:58 +0200 +Subject: block/rnbd-clt: Check the return value of the function rtrs_clt_query + +From: Md Haris Iqbal + +[ Upstream commit 1056ad829ec43f9b705b507c2093b05e2088b0b7 ] + +In case none of the paths are in connected state, the function +rtrs_clt_query returns an error. In such a case, error out since the +values in the rtrs_attrs structure would be garbage. + +Fixes: f7a7a5c228d45 ("block/rnbd: client: main functionality") +Signed-off-by: Md Haris Iqbal +Reviewed-by: Guoqing Jiang +Signed-off-by: Jack Wang +Signed-off-by: Gioh Kim +Link: https://lore.kernel.org/r/20210428061359.206794-4-gi-oh.kim@ionos.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/rnbd/rnbd-clt.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c +index 45a470076652..5ab7319ff2ea 100644 +--- a/drivers/block/rnbd/rnbd-clt.c ++++ b/drivers/block/rnbd/rnbd-clt.c +@@ -693,7 +693,11 @@ static void remap_devs(struct rnbd_clt_session *sess) + return; + } + +- rtrs_clt_query(sess->rtrs, &attrs); ++ err = rtrs_clt_query(sess->rtrs, &attrs); ++ if (err) { ++ pr_err("rtrs_clt_query(\"%s\"): %d\n", sess->sessname, err); ++ return; ++ } + mutex_lock(&sess->lock); + sess->max_io_size = attrs.max_io_size; + +@@ -1234,7 +1238,11 @@ find_and_get_or_create_sess(const char *sessname, + err = PTR_ERR(sess->rtrs); + goto wake_up_and_put; + } +- rtrs_clt_query(sess->rtrs, &attrs); ++ ++ err = rtrs_clt_query(sess->rtrs, &attrs); ++ if (err) ++ goto close_rtrs; ++ + sess->max_io_size = attrs.max_io_size; + sess->queue_depth = attrs.queue_depth; + +-- +2.30.2 + diff --git a/queue-5.12/bluetooth-btusb-enable-quirk-boolean-flag-for-mediat.patch b/queue-5.12/bluetooth-btusb-enable-quirk-boolean-flag-for-mediat.patch new file mode 100644 index 00000000000..1149ef53890 --- /dev/null +++ b/queue-5.12/bluetooth-btusb-enable-quirk-boolean-flag-for-mediat.patch @@ -0,0 +1,36 @@ +From 092dbf860de09620da16558a128fda8ee32afae8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Mar 2021 01:18:33 +0800 +Subject: Bluetooth: btusb: Enable quirk boolean flag for Mediatek Chip. + +From: mark-yw.chen + +[ Upstream commit 27e554a4fcd84e499bf0a82122b8c4c3f1de38b6 ] + +Adding support LE scatternet and WBS for Mediatek Chip + +Signed-off-by: mark-yw.chen +Signed-off-by: Marcel Holtmann +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 5cbfbd948f67..4a901508e48e 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -399,7 +399,9 @@ static const struct usb_device_id blacklist_table[] = { + + /* MediaTek Bluetooth devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0e8d, 0xe0, 0x01, 0x01), +- .driver_info = BTUSB_MEDIATEK }, ++ .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, + + /* Additional MediaTek MT7615E Bluetooth devices */ + { USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK}, +-- +2.30.2 + diff --git a/queue-5.12/bluetooth-check-for-zapped-sk-before-connecting.patch b/queue-5.12/bluetooth-check-for-zapped-sk-before-connecting.patch new file mode 100644 index 00000000000..fce83c5734b --- /dev/null +++ b/queue-5.12/bluetooth-check-for-zapped-sk-before-connecting.patch @@ -0,0 +1,69 @@ +From c93169d8f271e727938395d71e15a91a36d812e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Mar 2021 16:32:20 +0800 +Subject: Bluetooth: check for zapped sk before connecting + +From: Archie Pusaka + +[ Upstream commit 3af70b39fa2d415dc86c370e5b24ddb9fdacbd6f ] + +There is a possibility of receiving a zapped sock on +l2cap_sock_connect(). This could lead to interesting crashes, one +such case is tearing down an already tore l2cap_sock as is happened +with this call trace: + +__dump_stack lib/dump_stack.c:15 [inline] +dump_stack+0xc4/0x118 lib/dump_stack.c:56 +register_lock_class kernel/locking/lockdep.c:792 [inline] +register_lock_class+0x239/0x6f6 kernel/locking/lockdep.c:742 +__lock_acquire+0x209/0x1e27 kernel/locking/lockdep.c:3105 +lock_acquire+0x29c/0x2fb kernel/locking/lockdep.c:3599 +__raw_spin_lock_bh include/linux/spinlock_api_smp.h:137 [inline] +_raw_spin_lock_bh+0x38/0x47 kernel/locking/spinlock.c:175 +spin_lock_bh include/linux/spinlock.h:307 [inline] +lock_sock_nested+0x44/0xfa net/core/sock.c:2518 +l2cap_sock_teardown_cb+0x88/0x2fb net/bluetooth/l2cap_sock.c:1345 +l2cap_chan_del+0xa3/0x383 net/bluetooth/l2cap_core.c:598 +l2cap_chan_close+0x537/0x5dd net/bluetooth/l2cap_core.c:756 +l2cap_chan_timeout+0x104/0x17e net/bluetooth/l2cap_core.c:429 +process_one_work+0x7e3/0xcb0 kernel/workqueue.c:2064 +worker_thread+0x5a5/0x773 kernel/workqueue.c:2196 +kthread+0x291/0x2a6 kernel/kthread.c:211 +ret_from_fork+0x4e/0x80 arch/x86/entry/entry_64.S:604 + +Signed-off-by: Archie Pusaka +Reported-by: syzbot+abfc0f5e668d4099af73@syzkaller.appspotmail.com +Reviewed-by: Alain Michaud +Reviewed-by: Abhishek Pandit-Subedi +Reviewed-by: Guenter Roeck +Signed-off-by: Marcel Holtmann +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_sock.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index f1b1edd0b697..c99d65ef13b1 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -179,9 +179,17 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + struct sockaddr_l2 la; + int len, err = 0; ++ bool zapped; + + BT_DBG("sk %p", sk); + ++ lock_sock(sk); ++ zapped = sock_flag(sk, SOCK_ZAPPED); ++ release_sock(sk); ++ ++ if (zapped) ++ return -EINVAL; ++ + if (!addr || alen < offsetofend(struct sockaddr, sa_family) || + addr->sa_family != AF_BLUETOOTH) + return -EINVAL; +-- +2.30.2 + diff --git a/queue-5.12/bluetooth-do-not-set-cur_adv_instance-in-adv-param-m.patch b/queue-5.12/bluetooth-do-not-set-cur_adv_instance-in-adv-param-m.patch new file mode 100644 index 00000000000..382a77e0494 --- /dev/null +++ b/queue-5.12/bluetooth-do-not-set-cur_adv_instance-in-adv-param-m.patch @@ -0,0 +1,51 @@ +From 64e66760c1761fd3fd96076c125a043489f8327e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Apr 2021 16:33:05 -0700 +Subject: Bluetooth: Do not set cur_adv_instance in adv param MGMT request + +From: Daniel Winkler + +[ Upstream commit b6f1b79deabd32f89adbf24ef7b30f82d029808a ] + +We set hdev->cur_adv_instance in the adv param MGMT request to allow the +callback to the hci param request to set the tx power to the correct +instance. Now that the callbacks use the advertising handle from the hci +request (as they should), this workaround is no longer necessary. + +Furthermore, this change resolves a race condition that is more +prevalent when using the extended advertising MGMT calls - if +hdev->cur_adv_instance is set in the params request, then when the data +request is called, we believe our new instance is already active. This +treats it as an update and immediately schedules the instance with the +controller, which has a potential race with the software rotation adv +update. By not setting hdev->cur_adv_instance too early, the new +instance is queued as it should be, to be used when the rotation comes +around again. + +This change is tested on harrison peak to confirm that it resolves the +race condition on registration, and that there is no regression in +single- and multi-advertising automated tests. + +Reviewed-by: Miao-chen Chou +Signed-off-by: Daniel Winkler +Signed-off-by: Marcel Holtmann +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 74971b4bd457..939c6f77fecc 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -7976,7 +7976,6 @@ static int add_ext_adv_params(struct sock *sk, struct hci_dev *hdev, + goto unlock; + } + +- hdev->cur_adv_instance = cp->instance; + /* Submit request for advertising params if ext adv available */ + if (ext_adv_capable(hdev)) { + hci_req_init(&req, hdev); +-- +2.30.2 + diff --git a/queue-5.12/bluetooth-fix-incorrect-status-handling-in-le-phy-up.patch b/queue-5.12/bluetooth-fix-incorrect-status-handling-in-le-phy-up.patch new file mode 100644 index 00000000000..590a9da6dce --- /dev/null +++ b/queue-5.12/bluetooth-fix-incorrect-status-handling-in-le-phy-up.patch @@ -0,0 +1,35 @@ +From 544f07470990ed6a219921f1b7c788a4b239a573 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Mar 2021 16:52:14 +0530 +Subject: Bluetooth: Fix incorrect status handling in LE PHY UPDATE event + +From: Ayush Garg + +[ Upstream commit 87df8bcccd2cede62dfb97dc3d4ca1fe66cb4f83 ] + +Skip updation of tx and rx PHYs values, when PHY Update +event's status is not successful. + +Signed-off-by: Ayush Garg +Signed-off-by: Marcel Holtmann +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 7a3e42e75235..82f4973a011d 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -5912,7 +5912,7 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb) + + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + +- if (!ev->status) ++ if (ev->status) + return; + + hci_dev_lock(hdev); +-- +2.30.2 + diff --git a/queue-5.12/bluetooth-initialize-skb_queue_head-at-l2cap_chan_cr.patch b/queue-5.12/bluetooth-initialize-skb_queue_head-at-l2cap_chan_cr.patch new file mode 100644 index 00000000000..eb3cb2127bc --- /dev/null +++ b/queue-5.12/bluetooth-initialize-skb_queue_head-at-l2cap_chan_cr.patch @@ -0,0 +1,43 @@ +From 00070554cee5b024e4f582b5d0c465f8b0df0af8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Mar 2021 07:52:07 +0900 +Subject: Bluetooth: initialize skb_queue_head at l2cap_chan_create() + +From: Tetsuo Handa + +[ Upstream commit be8597239379f0f53c9710dd6ab551bbf535bec6 ] + +syzbot is hitting "INFO: trying to register non-static key." message [1], +for "struct l2cap_chan"->tx_q.lock spinlock is not yet initialized when +l2cap_chan_del() is called due to e.g. timeout. + +Since "struct l2cap_chan"->lock mutex is initialized at l2cap_chan_create() +immediately after "struct l2cap_chan" is allocated using kzalloc(), let's +as well initialize "struct l2cap_chan"->{tx_q,srej_q}.lock spinlocks there. + +[1] https://syzkaller.appspot.com/bug?extid=fadfba6a911f6bf71842 + +Reported-and-tested-by: syzbot +Signed-off-by: Tetsuo Handa +Signed-off-by: Marcel Holtmann +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index db6a4b2d0d77..53ddbee459b9 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -451,6 +451,8 @@ struct l2cap_chan *l2cap_chan_create(void) + if (!chan) + return NULL; + ++ skb_queue_head_init(&chan->tx_q); ++ skb_queue_head_init(&chan->srej_q); + mutex_init(&chan->lock); + + /* Set default lock nesting level */ +-- +2.30.2 + diff --git a/queue-5.12/bluetooth-set-conf_not_complete-as-l2cap_chan-defaul.patch b/queue-5.12/bluetooth-set-conf_not_complete-as-l2cap_chan-defaul.patch new file mode 100644 index 00000000000..e4fdbafad6e --- /dev/null +++ b/queue-5.12/bluetooth-set-conf_not_complete-as-l2cap_chan-defaul.patch @@ -0,0 +1,77 @@ +From fdb8a4ce8c80f50f2106862e3739da3e8e89b9eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Mar 2021 14:02:15 +0800 +Subject: Bluetooth: Set CONF_NOT_COMPLETE as l2cap_chan default + +From: Archie Pusaka + +[ Upstream commit 3a9d54b1947ecea8eea9a902c0b7eb58a98add8a ] + +Currently l2cap_chan_set_defaults() reset chan->conf_state to zero. +However, there is a flag CONF_NOT_COMPLETE which is set when +creating the l2cap_chan. It is suggested that the flag should be +cleared when l2cap_chan is ready, but when l2cap_chan_set_defaults() +is called, l2cap_chan is not yet ready. Therefore, we must set this +flag as the default. + +Example crash call trace: +__dump_stack lib/dump_stack.c:15 [inline] +dump_stack+0xc4/0x118 lib/dump_stack.c:56 +panic+0x1c6/0x38b kernel/panic.c:117 +__warn+0x170/0x1b9 kernel/panic.c:471 +warn_slowpath_fmt+0xc7/0xf8 kernel/panic.c:494 +debug_print_object+0x175/0x193 lib/debugobjects.c:260 +debug_object_assert_init+0x171/0x1bf lib/debugobjects.c:614 +debug_timer_assert_init kernel/time/timer.c:629 [inline] +debug_assert_init kernel/time/timer.c:677 [inline] +del_timer+0x7c/0x179 kernel/time/timer.c:1034 +try_to_grab_pending+0x81/0x2e5 kernel/workqueue.c:1230 +cancel_delayed_work+0x7c/0x1c4 kernel/workqueue.c:2929 +l2cap_clear_timer+0x1e/0x41 include/net/bluetooth/l2cap.h:834 +l2cap_chan_del+0x2d8/0x37e net/bluetooth/l2cap_core.c:640 +l2cap_chan_close+0x532/0x5d8 net/bluetooth/l2cap_core.c:756 +l2cap_sock_shutdown+0x806/0x969 net/bluetooth/l2cap_sock.c:1174 +l2cap_sock_release+0x64/0x14d net/bluetooth/l2cap_sock.c:1217 +__sock_release+0xda/0x217 net/socket.c:580 +sock_close+0x1b/0x1f net/socket.c:1039 +__fput+0x322/0x55c fs/file_table.c:208 +____fput+0x17/0x19 fs/file_table.c:244 +task_work_run+0x19b/0x1d3 kernel/task_work.c:115 +exit_task_work include/linux/task_work.h:21 [inline] +do_exit+0xe4c/0x204a kernel/exit.c:766 +do_group_exit+0x291/0x291 kernel/exit.c:891 +get_signal+0x749/0x1093 kernel/signal.c:2396 +do_signal+0xa5/0xcdb arch/x86/kernel/signal.c:737 +exit_to_usermode_loop arch/x86/entry/common.c:243 [inline] +prepare_exit_to_usermode+0xed/0x235 arch/x86/entry/common.c:277 +syscall_return_slowpath+0x3a7/0x3b3 arch/x86/entry/common.c:348 +int_ret_from_sys_call+0x25/0xa3 + +Signed-off-by: Archie Pusaka +Reported-by: syzbot+338f014a98367a08a114@syzkaller.appspotmail.com +Reviewed-by: Alain Michaud +Reviewed-by: Abhishek Pandit-Subedi +Reviewed-by: Guenter Roeck +Signed-off-by: Marcel Holtmann +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 72c2f5226d67..db6a4b2d0d77 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -516,7 +516,9 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan) + chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; + chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; + chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; ++ + chan->conf_state = 0; ++ set_bit(CONF_NOT_COMPLETE, &chan->conf_state); + + set_bit(FLAG_FORCE_ACTIVE, &chan->flags); + } +-- +2.30.2 + diff --git a/queue-5.12/bnxt_en-add-pci-ids-for-hyper-v-vf-devices.patch b/queue-5.12/bnxt_en-add-pci-ids-for-hyper-v-vf-devices.patch new file mode 100644 index 00000000000..b9c47aef39b --- /dev/null +++ b/queue-5.12/bnxt_en-add-pci-ids-for-hyper-v-vf-devices.patch @@ -0,0 +1,86 @@ +From c24f3ee978a2ab605c071a2e7e63d7021bb8489d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 25 Apr 2021 13:45:25 -0400 +Subject: bnxt_en: Add PCI IDs for Hyper-V VF devices. + +From: Michael Chan + +[ Upstream commit 7fbf359bb2c19c824cbb1954020680824f6ee5a5 ] + +Support VF device IDs used by the Hyper-V hypervisor. + +Reviewed-by: Vasundhara Volam +Reviewed-by: Andy Gospodarek +Signed-off-by: Edwin Peer +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 73239d3eaca1..cf4249d59383 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -122,7 +122,10 @@ enum board_idx { + NETXTREME_E_VF, + NETXTREME_C_VF, + NETXTREME_S_VF, ++ NETXTREME_C_VF_HV, ++ NETXTREME_E_VF_HV, + NETXTREME_E_P5_VF, ++ NETXTREME_E_P5_VF_HV, + }; + + /* indexed by enum above */ +@@ -170,7 +173,10 @@ static const struct { + [NETXTREME_E_VF] = { "Broadcom NetXtreme-E Ethernet Virtual Function" }, + [NETXTREME_C_VF] = { "Broadcom NetXtreme-C Ethernet Virtual Function" }, + [NETXTREME_S_VF] = { "Broadcom NetXtreme-S Ethernet Virtual Function" }, ++ [NETXTREME_C_VF_HV] = { "Broadcom NetXtreme-C Virtual Function for Hyper-V" }, ++ [NETXTREME_E_VF_HV] = { "Broadcom NetXtreme-E Virtual Function for Hyper-V" }, + [NETXTREME_E_P5_VF] = { "Broadcom BCM5750X NetXtreme-E Ethernet Virtual Function" }, ++ [NETXTREME_E_P5_VF_HV] = { "Broadcom BCM5750X NetXtreme-E Virtual Function for Hyper-V" }, + }; + + static const struct pci_device_id bnxt_pci_tbl[] = { +@@ -222,15 +228,25 @@ static const struct pci_device_id bnxt_pci_tbl[] = { + { PCI_VDEVICE(BROADCOM, 0xd804), .driver_data = BCM58804 }, + #ifdef CONFIG_BNXT_SRIOV + { PCI_VDEVICE(BROADCOM, 0x1606), .driver_data = NETXTREME_E_VF }, ++ { PCI_VDEVICE(BROADCOM, 0x1607), .driver_data = NETXTREME_E_VF_HV }, ++ { PCI_VDEVICE(BROADCOM, 0x1608), .driver_data = NETXTREME_E_VF_HV }, + { PCI_VDEVICE(BROADCOM, 0x1609), .driver_data = NETXTREME_E_VF }, ++ { PCI_VDEVICE(BROADCOM, 0x16bd), .driver_data = NETXTREME_E_VF_HV }, + { PCI_VDEVICE(BROADCOM, 0x16c1), .driver_data = NETXTREME_E_VF }, ++ { PCI_VDEVICE(BROADCOM, 0x16c2), .driver_data = NETXTREME_C_VF_HV }, ++ { PCI_VDEVICE(BROADCOM, 0x16c3), .driver_data = NETXTREME_C_VF_HV }, ++ { PCI_VDEVICE(BROADCOM, 0x16c4), .driver_data = NETXTREME_E_VF_HV }, ++ { PCI_VDEVICE(BROADCOM, 0x16c5), .driver_data = NETXTREME_E_VF_HV }, + { PCI_VDEVICE(BROADCOM, 0x16cb), .driver_data = NETXTREME_C_VF }, + { PCI_VDEVICE(BROADCOM, 0x16d3), .driver_data = NETXTREME_E_VF }, + { PCI_VDEVICE(BROADCOM, 0x16dc), .driver_data = NETXTREME_E_VF }, + { PCI_VDEVICE(BROADCOM, 0x16e1), .driver_data = NETXTREME_C_VF }, + { PCI_VDEVICE(BROADCOM, 0x16e5), .driver_data = NETXTREME_C_VF }, ++ { PCI_VDEVICE(BROADCOM, 0x16e6), .driver_data = NETXTREME_C_VF_HV }, + { PCI_VDEVICE(BROADCOM, 0x1806), .driver_data = NETXTREME_E_P5_VF }, + { PCI_VDEVICE(BROADCOM, 0x1807), .driver_data = NETXTREME_E_P5_VF }, ++ { PCI_VDEVICE(BROADCOM, 0x1808), .driver_data = NETXTREME_E_P5_VF_HV }, ++ { PCI_VDEVICE(BROADCOM, 0x1809), .driver_data = NETXTREME_E_P5_VF_HV }, + { PCI_VDEVICE(BROADCOM, 0xd800), .driver_data = NETXTREME_S_VF }, + #endif + { 0 } +@@ -265,7 +281,8 @@ static struct workqueue_struct *bnxt_pf_wq; + static bool bnxt_vf_pciid(enum board_idx idx) + { + return (idx == NETXTREME_C_VF || idx == NETXTREME_E_VF || +- idx == NETXTREME_S_VF || idx == NETXTREME_E_P5_VF); ++ idx == NETXTREME_S_VF || idx == NETXTREME_C_VF_HV || ++ idx == NETXTREME_E_VF_HV || idx == NETXTREME_E_P5_VF); + } + + #define DB_CP_REARM_FLAGS (DB_KEY_CP | DB_IDX_VALID) +-- +2.30.2 + diff --git a/queue-5.12/can-dev-can_free_echo_skb-don-t-crash-the-kernel-if-.patch b/queue-5.12/can-dev-can_free_echo_skb-don-t-crash-the-kernel-if-.patch new file mode 100644 index 00000000000..fd039fa3d0f --- /dev/null +++ b/queue-5.12/can-dev-can_free_echo_skb-don-t-crash-the-kernel-if-.patch @@ -0,0 +1,46 @@ +From b63b01c6ae3b2e05cdf297419ee455dbe1c809cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Mar 2021 15:08:13 +0100 +Subject: can: dev: can_free_echo_skb(): don't crash the kernel if + can_priv::echo_skb is accessed out of bounds + +From: Marc Kleine-Budde + +[ Upstream commit 4168d079aa41498639b2c64b4583375bcdf360d9 ] + +A out of bounds access to "struct can_priv::echo_skb" leads to a +kernel crash. Better print a sensible warning message instead and try +to recover. + +This patch is similar to: + +| e7a6994d043a ("can: dev: __can_get_echo_skb(): Don't crash the kernel +| if can_priv::echo_skb is accessed out of bounds") + +Link: https://lore.kernel.org/r/20210319142700.305648-2-mkl@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/dev/skb.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c +index 6a64fe410987..c3508109263e 100644 +--- a/drivers/net/can/dev/skb.c ++++ b/drivers/net/can/dev/skb.c +@@ -151,7 +151,11 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx) + { + struct can_priv *priv = netdev_priv(dev); + +- BUG_ON(idx >= priv->echo_skb_max); ++ if (idx >= priv->echo_skb_max) { ++ netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n", ++ __func__, idx, priv->echo_skb_max); ++ return; ++ } + + if (priv->echo_skb[idx]) { + dev_kfree_skb_any(priv->echo_skb[idx]); +-- +2.30.2 + diff --git a/queue-5.12/can-m_can-m_can_tx_work_queue-fix-tx_skb-race-condit.patch b/queue-5.12/can-m_can-m_can_tx_work_queue-fix-tx_skb-race-condit.patch new file mode 100644 index 00000000000..36c60e0ec68 --- /dev/null +++ b/queue-5.12/can-m_can-m_can_tx_work_queue-fix-tx_skb-race-condit.patch @@ -0,0 +1,49 @@ +From 7e32575c4169498f09f66435f1f41f86f968e773 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 May 2021 13:32:27 +0200 +Subject: can: m_can: m_can_tx_work_queue(): fix tx_skb race condition + +From: Marc Kleine-Budde + +[ Upstream commit e04b2cfe61072c7966e1a5fb73dd1feb30c206ed ] + +The m_can_start_xmit() function checks if the cdev->tx_skb is NULL and +returns with NETDEV_TX_BUSY in case tx_sbk is not NULL. + +There is a race condition in the m_can_tx_work_queue(), where first +the skb is send to the driver and then the case tx_sbk is set to NULL. +A TX complete IRQ might come in between and wake the queue, which +results in tx_skb not being cleared yet. + +Fixes: f524f829b75a ("can: m_can: Create a m_can platform framework") +Tested-by: Torin Cooper-Bennun +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/m_can/m_can.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c +index 0c8d36bc668c..f71127229caf 100644 +--- a/drivers/net/can/m_can/m_can.c ++++ b/drivers/net/can/m_can/m_can.c +@@ -1455,6 +1455,8 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev) + int i; + int putidx; + ++ cdev->tx_skb = NULL; ++ + /* Generate ID field for TX buffer Element */ + /* Common to all supported M_CAN versions */ + if (cf->can_id & CAN_EFF_FLAG) { +@@ -1571,7 +1573,6 @@ static void m_can_tx_work_queue(struct work_struct *ws) + tx_work); + + m_can_tx_handler(cdev); +- cdev->tx_skb = NULL; + } + + static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, +-- +2.30.2 + diff --git a/queue-5.12/can-mcp251x-fix-resume-from-sleep-before-interface-w.patch b/queue-5.12/can-mcp251x-fix-resume-from-sleep-before-interface-w.patch new file mode 100644 index 00000000000..cd72ccf5f41 --- /dev/null +++ b/queue-5.12/can-mcp251x-fix-resume-from-sleep-before-interface-w.patch @@ -0,0 +1,119 @@ +From 63f97974b26f65fad8a0924cdd58ff776920cb07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 May 2021 09:14:15 +0200 +Subject: can: mcp251x: fix resume from sleep before interface was brought up + +From: Frieder Schrempf + +[ Upstream commit 03c427147b2d3e503af258711af4fc792b89b0af ] + +Since 8ce8c0abcba3 the driver queues work via priv->restart_work when +resuming after suspend, even when the interface was not previously +enabled. This causes a null dereference error as the workqueue is only +allocated and initialized in mcp251x_open(). + +To fix this we move the workqueue init to mcp251x_can_probe() as there +is no reason to do it later and repeat it whenever mcp251x_open() is +called. + +Fixes: 8ce8c0abcba3 ("can: mcp251x: only reset hardware as required") +Link: https://lore.kernel.org/r/17d5d714-b468-482f-f37a-482e3d6df84e@kontron.de +Signed-off-by: Frieder Schrempf +Reviewed-by: Andy Shevchenko +[mkl: fix error handling in mcp251x_stop()] +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/spi/mcp251x.c | 35 ++++++++++++++++++----------------- + 1 file changed, 18 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c +index a57da43680d8..bd7d0251be10 100644 +--- a/drivers/net/can/spi/mcp251x.c ++++ b/drivers/net/can/spi/mcp251x.c +@@ -956,8 +956,6 @@ static int mcp251x_stop(struct net_device *net) + + priv->force_quit = 1; + free_irq(spi->irq, priv); +- destroy_workqueue(priv->wq); +- priv->wq = NULL; + + mutex_lock(&priv->mcp_lock); + +@@ -1224,24 +1222,15 @@ static int mcp251x_open(struct net_device *net) + goto out_close; + } + +- priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM, +- 0); +- if (!priv->wq) { +- ret = -ENOMEM; +- goto out_clean; +- } +- INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); +- INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); +- + ret = mcp251x_hw_wake(spi); + if (ret) +- goto out_free_wq; ++ goto out_free_irq; + ret = mcp251x_setup(net, spi); + if (ret) +- goto out_free_wq; ++ goto out_free_irq; + ret = mcp251x_set_normal_mode(spi); + if (ret) +- goto out_free_wq; ++ goto out_free_irq; + + can_led_event(net, CAN_LED_EVENT_OPEN); + +@@ -1250,9 +1239,7 @@ static int mcp251x_open(struct net_device *net) + + return 0; + +-out_free_wq: +- destroy_workqueue(priv->wq); +-out_clean: ++out_free_irq: + free_irq(spi->irq, priv); + mcp251x_hw_sleep(spi); + out_close: +@@ -1373,6 +1360,15 @@ static int mcp251x_can_probe(struct spi_device *spi) + if (ret) + goto out_clk; + ++ priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM, ++ 0); ++ if (!priv->wq) { ++ ret = -ENOMEM; ++ goto out_clk; ++ } ++ INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); ++ INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); ++ + priv->spi = spi; + mutex_init(&priv->mcp_lock); + +@@ -1417,6 +1413,8 @@ static int mcp251x_can_probe(struct spi_device *spi) + return 0; + + error_probe: ++ destroy_workqueue(priv->wq); ++ priv->wq = NULL; + mcp251x_power_enable(priv->power, 0); + + out_clk: +@@ -1438,6 +1436,9 @@ static int mcp251x_can_remove(struct spi_device *spi) + + mcp251x_power_enable(priv->power, 0); + ++ destroy_workqueue(priv->wq); ++ priv->wq = NULL; ++ + clk_disable_unprepare(priv->clk); + + free_candev(net); +-- +2.30.2 + diff --git a/queue-5.12/can-mcp251xfd-mcp251xfd_probe-add-missing-can_rx_off.patch b/queue-5.12/can-mcp251xfd-mcp251xfd_probe-add-missing-can_rx_off.patch new file mode 100644 index 00000000000..7d6df95725d --- /dev/null +++ b/queue-5.12/can-mcp251xfd-mcp251xfd_probe-add-missing-can_rx_off.patch @@ -0,0 +1,42 @@ +From 58cc3de465b002b45014edfcd22e97f034551586 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 May 2021 11:34:34 +0200 +Subject: can: mcp251xfd: mcp251xfd_probe(): add missing can_rx_offload_del() + in error path + +From: Marc Kleine-Budde + +[ Upstream commit 4376ea42db8bfcac2bc3a30bba93917244a8c2d4 ] + +This patch adds the missing can_rx_offload_del(), that must be called +if mcp251xfd_register() fails. + +Fixes: 55e5b97f003e ("can: mcp25xxfd: add driver for Microchip MCP25xxFD SPI CAN") +Link: https://lore.kernel.org/r/20210504091838.1109047-1-mkl@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +index 15b04db6ed9c..4a742aa5c417 100644 +--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c ++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +@@ -2957,10 +2957,12 @@ static int mcp251xfd_probe(struct spi_device *spi) + + err = mcp251xfd_register(priv); + if (err) +- goto out_free_candev; ++ goto out_can_rx_offload_del; + + return 0; + ++ out_can_rx_offload_del: ++ can_rx_offload_del(&priv->offload); + out_free_candev: + spi->max_speed_hz = priv->spi_max_speed_hz_orig; + +-- +2.30.2 + diff --git a/queue-5.12/can-mcp251xfd-mcp251xfd_probe-fix-an-error-pointer-d.patch b/queue-5.12/can-mcp251xfd-mcp251xfd_probe-fix-an-error-pointer-d.patch new file mode 100644 index 00000000000..57a28375c2d --- /dev/null +++ b/queue-5.12/can-mcp251xfd-mcp251xfd_probe-fix-an-error-pointer-d.patch @@ -0,0 +1,42 @@ +From aec96ed4c89e9ff606d36924f090da198789c6aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 May 2021 17:49:09 +0300 +Subject: can: mcp251xfd: mcp251xfd_probe(): fix an error pointer dereference + in probe + +From: Dan Carpenter + +[ Upstream commit 4cc7faa406975b460aa674606291dea197c1210c ] + +When we converted this code to use dev_err_probe() we accidentally +removed a return. It means that if devm_clk_get() it will lead to an +Oops when we call clk_get_rate() on the next line. + +Fixes: cf8ee6de2543 ("can: mcp251xfd: mcp251xfd_probe(): use dev_err_probe() to simplify error handling") +Link: https://lore.kernel.org/r/YJANZf13Qxd5Mhr1@mwanda +Signed-off-by: Dan Carpenter +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +index 799e9d5d3481..15b04db6ed9c 100644 +--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c ++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +@@ -2856,8 +2856,8 @@ static int mcp251xfd_probe(struct spi_device *spi) + + clk = devm_clk_get(&spi->dev, NULL); + if (IS_ERR(clk)) +- dev_err_probe(&spi->dev, PTR_ERR(clk), +- "Failed to get Oscillator (clock)!\n"); ++ return dev_err_probe(&spi->dev, PTR_ERR(clk), ++ "Failed to get Oscillator (clock)!\n"); + freq = clk_get_rate(clk); + + /* Sanity check */ +-- +2.30.2 + diff --git a/queue-5.12/ceph-fix-inode-leak-on-getattr-error-in-__fh_to_dent.patch b/queue-5.12/ceph-fix-inode-leak-on-getattr-error-in-__fh_to_dent.patch new file mode 100644 index 00000000000..bcf0e4be967 --- /dev/null +++ b/queue-5.12/ceph-fix-inode-leak-on-getattr-error-in-__fh_to_dent.patch @@ -0,0 +1,37 @@ +From b7cf55c4730f06fd01d59898473098c2b79b12d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Mar 2021 09:21:53 -0400 +Subject: ceph: fix inode leak on getattr error in __fh_to_dentry + +From: Jeff Layton + +[ Upstream commit 1775c7ddacfcea29051c67409087578f8f4d751b ] + +Fixes: 878dabb64117 ("ceph: don't return -ESTALE if there's still an open file") +Signed-off-by: Jeff Layton +Reviewed-by: Xiubo Li +Signed-off-by: Ilya Dryomov +Signed-off-by: Sasha Levin +--- + fs/ceph/export.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/ceph/export.c b/fs/ceph/export.c +index e088843a7734..baa6368bece5 100644 +--- a/fs/ceph/export.c ++++ b/fs/ceph/export.c +@@ -178,8 +178,10 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino) + return ERR_CAST(inode); + /* We need LINK caps to reliably check i_nlink */ + err = ceph_do_getattr(inode, CEPH_CAP_LINK_SHARED, false); +- if (err) ++ if (err) { ++ iput(inode); + return ERR_PTR(err); ++ } + /* -ESTALE if inode as been unlinked and no file is open */ + if ((inode->i_nlink == 0) && (atomic_read(&inode->i_count) == 1)) { + iput(inode); +-- +2.30.2 + diff --git a/queue-5.12/coresight-do-not-scan-for-graph-if-none-is-present.patch b/queue-5.12/coresight-do-not-scan-for-graph-if-none-is-present.patch new file mode 100644 index 00000000000..b18473e6dec --- /dev/null +++ b/queue-5.12/coresight-do-not-scan-for-graph-if-none-is-present.patch @@ -0,0 +1,50 @@ +From 8389b47ffde84ba77a2bf9ced9e98da43e857ce3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Apr 2021 17:42:57 +0100 +Subject: coresight: Do not scan for graph if none is present + +From: Suzuki K Poulose + +[ Upstream commit 2b921b671a8d29c2adb255a86409aad1e3267309 ] + +If a graph node is not found for a given node, of_get_next_endpoint() +will emit the following error message : + + OF: graph: no port node found in / + +If the given component doesn't have any explicit connections (e.g, +ETE) we could simply ignore the graph parsing. As for any legacy +component where this is mandatory, the device will not be usable +as before this patch. Updating the DT bindings to Yaml and enabling +the schema checks can detect such issues with the DT. + +Cc: Mike Leach +Cc: Leo Yan +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20210405164307.1720226-11-suzuki.poulose@arm.com +Signed-off-by: Mathieu Poirier +Signed-off-by: Sasha Levin +--- + drivers/hwtracing/coresight/coresight-platform.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c +index 3629b7885aca..c594f45319fc 100644 +--- a/drivers/hwtracing/coresight/coresight-platform.c ++++ b/drivers/hwtracing/coresight/coresight-platform.c +@@ -90,6 +90,12 @@ static void of_coresight_get_ports_legacy(const struct device_node *node, + struct of_endpoint endpoint; + int in = 0, out = 0; + ++ /* ++ * Avoid warnings in of_graph_get_next_endpoint() ++ * if the device doesn't have any graph connections ++ */ ++ if (!of_graph_is_present(node)) ++ return; + do { + ep = of_graph_get_next_endpoint(node, ep); + if (!ep) +-- +2.30.2 + diff --git a/queue-5.12/crypto-ccp-free-sev-device-if-sev-init-fails.patch b/queue-5.12/crypto-ccp-free-sev-device-if-sev-init-fails.patch new file mode 100644 index 00000000000..bf3df8fc94f --- /dev/null +++ b/queue-5.12/crypto-ccp-free-sev-device-if-sev-init-fails.patch @@ -0,0 +1,49 @@ +From 746510222dda06f6def4d596d698b9b415506eca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Apr 2021 15:49:45 -0700 +Subject: crypto: ccp: Free SEV device if SEV init fails + +From: Sean Christopherson + +[ Upstream commit b61a9071dc72a3c709192c0c00ab87c2b3de1d94 ] + +Free the SEV device if later initialization fails. The memory isn't +technically leaked as it's tracked in the top-level device's devres +list, but unless the top-level device is removed, the memory won't be +freed and is effectively leaked. + +Signed-off-by: Sean Christopherson +Message-Id: <20210406224952.4177376-2-seanjc@google.com> +Reviewed-by: Brijesh Singh +Acked-by: Tom Lendacky +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + drivers/crypto/ccp/sev-dev.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c +index 8fd43c1acac1..3e0d1d6922ba 100644 +--- a/drivers/crypto/ccp/sev-dev.c ++++ b/drivers/crypto/ccp/sev-dev.c +@@ -990,7 +990,7 @@ int sev_dev_init(struct psp_device *psp) + if (!sev->vdata) { + ret = -ENODEV; + dev_err(dev, "sev: missing driver data\n"); +- goto e_err; ++ goto e_sev; + } + + psp_set_sev_irq_handler(psp, sev_irq_handler, sev); +@@ -1005,6 +1005,8 @@ int sev_dev_init(struct psp_device *psp) + + e_irq: + psp_clear_sev_irq_handler(psp); ++e_sev: ++ devm_kfree(dev, sev); + e_err: + psp->sev_data = NULL; + +-- +2.30.2 + diff --git a/queue-5.12/cuse-prevent-clone.patch b/queue-5.12/cuse-prevent-clone.patch new file mode 100644 index 00000000000..980be113926 --- /dev/null +++ b/queue-5.12/cuse-prevent-clone.patch @@ -0,0 +1,37 @@ +From b031db52ded39f980180dc51a361e1a6a91b6462 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Apr 2021 10:40:58 +0200 +Subject: cuse: prevent clone + +From: Miklos Szeredi + +[ Upstream commit 8217673d07256b22881127bf50dce874d0e51653 ] + +For cloned connections cuse_channel_release() will be called more than +once, resulting in use after free. + +Prevent device cloning for CUSE, which does not make sense at this point, +and highly unlikely to be used in real life. + +Signed-off-by: Miklos Szeredi +Signed-off-by: Sasha Levin +--- + fs/fuse/cuse.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c +index 45082269e698..a37528b51798 100644 +--- a/fs/fuse/cuse.c ++++ b/fs/fuse/cuse.c +@@ -627,6 +627,8 @@ static int __init cuse_init(void) + cuse_channel_fops.owner = THIS_MODULE; + cuse_channel_fops.open = cuse_channel_open; + cuse_channel_fops.release = cuse_channel_release; ++ /* CUSE is not prepared for FUSE_DEV_IOC_CLONE */ ++ cuse_channel_fops.unlocked_ioctl = NULL; + + cuse_class = class_create(THIS_MODULE, "cuse"); + if (IS_ERR(cuse_class)) +-- +2.30.2 + diff --git a/queue-5.12/dmaengine-idxd-cleanup-pci-interrupt-vector-allocati.patch b/queue-5.12/dmaengine-idxd-cleanup-pci-interrupt-vector-allocati.patch new file mode 100644 index 00000000000..f3edf0fd59e --- /dev/null +++ b/queue-5.12/dmaengine-idxd-cleanup-pci-interrupt-vector-allocati.patch @@ -0,0 +1,209 @@ +From effed7c1c81eab3440510f394b17a3f22071604b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 16:37:15 -0700 +Subject: dmaengine: idxd: cleanup pci interrupt vector allocation management + +From: Dave Jiang + +[ Upstream commit 5fc8e85ff12ce0530ac658686902a0ee64600f56 ] + +The devm managed lifetime is incompatible with 'struct device' objects that +resides in idxd context. This is one of the series that clean up the idxd +driver 'struct device' lifetime. Remove devm managed pci interrupt vectors +and replace with unmanged allocators. + +Reported-by: Jason Gunthorpe +Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") +Signed-off-by: Dave Jiang +Reviewed-by: Dan Williams +Link: https://lore.kernel.org/r/161852983563.2203940.8116028229124776669.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/device.c | 4 +-- + drivers/dma/idxd/idxd.h | 2 +- + drivers/dma/idxd/init.c | 64 +++++++++++++++++---------------------- + 3 files changed, 30 insertions(+), 40 deletions(-) + +diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c +index d255bb016c4d..3f696abd74ac 100644 +--- a/drivers/dma/idxd/device.c ++++ b/drivers/dma/idxd/device.c +@@ -19,7 +19,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, + /* Interrupt control bits */ + void idxd_mask_msix_vector(struct idxd_device *idxd, int vec_id) + { +- struct irq_data *data = irq_get_irq_data(idxd->msix_entries[vec_id].vector); ++ struct irq_data *data = irq_get_irq_data(idxd->irq_entries[vec_id].vector); + + pci_msi_mask_irq(data); + } +@@ -36,7 +36,7 @@ void idxd_mask_msix_vectors(struct idxd_device *idxd) + + void idxd_unmask_msix_vector(struct idxd_device *idxd, int vec_id) + { +- struct irq_data *data = irq_get_irq_data(idxd->msix_entries[vec_id].vector); ++ struct irq_data *data = irq_get_irq_data(idxd->irq_entries[vec_id].vector); + + pci_msi_unmask_irq(data); + } +diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h +index 80e534680c9a..401b035e42b1 100644 +--- a/drivers/dma/idxd/idxd.h ++++ b/drivers/dma/idxd/idxd.h +@@ -36,6 +36,7 @@ struct idxd_device_driver { + struct idxd_irq_entry { + struct idxd_device *idxd; + int id; ++ int vector; + struct llist_head pending_llist; + struct list_head work_list; + /* +@@ -219,7 +220,6 @@ struct idxd_device { + + union sw_err_reg sw_err; + wait_queue_head_t cmd_waitq; +- struct msix_entry *msix_entries; + int num_wq_irqs; + struct idxd_irq_entry *irq_entries; + +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index 6584b0ec07d5..5cf1bf095ae1 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -61,7 +61,6 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) + { + struct pci_dev *pdev = idxd->pdev; + struct device *dev = &pdev->dev; +- struct msix_entry *msix; + struct idxd_irq_entry *irq_entry; + int i, msixcnt; + int rc = 0; +@@ -69,23 +68,13 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) + msixcnt = pci_msix_vec_count(pdev); + if (msixcnt < 0) { + dev_err(dev, "Not MSI-X interrupt capable.\n"); +- goto err_no_irq; ++ return -ENOSPC; + } + +- idxd->msix_entries = devm_kzalloc(dev, sizeof(struct msix_entry) * +- msixcnt, GFP_KERNEL); +- if (!idxd->msix_entries) { +- rc = -ENOMEM; +- goto err_no_irq; +- } +- +- for (i = 0; i < msixcnt; i++) +- idxd->msix_entries[i].entry = i; +- +- rc = pci_enable_msix_exact(pdev, idxd->msix_entries, msixcnt); +- if (rc) { +- dev_err(dev, "Failed enabling %d MSIX entries.\n", msixcnt); +- goto err_no_irq; ++ rc = pci_alloc_irq_vectors(pdev, msixcnt, msixcnt, PCI_IRQ_MSIX); ++ if (rc != msixcnt) { ++ dev_err(dev, "Failed enabling %d MSIX entries: %d\n", msixcnt, rc); ++ return -ENOSPC; + } + dev_dbg(dev, "Enabled %d msix vectors\n", msixcnt); + +@@ -98,58 +87,57 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) + GFP_KERNEL); + if (!idxd->irq_entries) { + rc = -ENOMEM; +- goto err_no_irq; ++ goto err_irq_entries; + } + + for (i = 0; i < msixcnt; i++) { + idxd->irq_entries[i].id = i; + idxd->irq_entries[i].idxd = idxd; ++ idxd->irq_entries[i].vector = pci_irq_vector(pdev, i); + spin_lock_init(&idxd->irq_entries[i].list_lock); + } + +- msix = &idxd->msix_entries[0]; + irq_entry = &idxd->irq_entries[0]; +- rc = devm_request_threaded_irq(dev, msix->vector, idxd_irq_handler, +- idxd_misc_thread, 0, "idxd-misc", +- irq_entry); ++ rc = request_threaded_irq(irq_entry->vector, idxd_irq_handler, idxd_misc_thread, ++ 0, "idxd-misc", irq_entry); + if (rc < 0) { + dev_err(dev, "Failed to allocate misc interrupt.\n"); +- goto err_no_irq; ++ goto err_misc_irq; + } + +- dev_dbg(dev, "Allocated idxd-misc handler on msix vector %d\n", +- msix->vector); ++ dev_dbg(dev, "Allocated idxd-misc handler on msix vector %d\n", irq_entry->vector); + + /* first MSI-X entry is not for wq interrupts */ + idxd->num_wq_irqs = msixcnt - 1; + + for (i = 1; i < msixcnt; i++) { +- msix = &idxd->msix_entries[i]; + irq_entry = &idxd->irq_entries[i]; + + init_llist_head(&idxd->irq_entries[i].pending_llist); + INIT_LIST_HEAD(&idxd->irq_entries[i].work_list); +- rc = devm_request_threaded_irq(dev, msix->vector, +- idxd_irq_handler, +- idxd_wq_thread, 0, +- "idxd-portal", irq_entry); ++ rc = request_threaded_irq(irq_entry->vector, idxd_irq_handler, ++ idxd_wq_thread, 0, "idxd-portal", irq_entry); + if (rc < 0) { +- dev_err(dev, "Failed to allocate irq %d.\n", +- msix->vector); +- goto err_no_irq; ++ dev_err(dev, "Failed to allocate irq %d.\n", irq_entry->vector); ++ goto err_wq_irqs; + } +- dev_dbg(dev, "Allocated idxd-msix %d for vector %d\n", +- i, msix->vector); ++ dev_dbg(dev, "Allocated idxd-msix %d for vector %d\n", i, irq_entry->vector); + } + + idxd_unmask_error_interrupts(idxd); + idxd_msix_perm_setup(idxd); + return 0; + +- err_no_irq: ++ err_wq_irqs: ++ while (--i >= 0) { ++ irq_entry = &idxd->irq_entries[i]; ++ free_irq(irq_entry->vector, irq_entry); ++ } ++ err_misc_irq: + /* Disable error interrupt generation */ + idxd_mask_error_interrupts(idxd); +- pci_disable_msix(pdev); ++ err_irq_entries: ++ pci_free_irq_vectors(pdev); + dev_err(dev, "No usable interrupts\n"); + return rc; + } +@@ -495,7 +483,8 @@ static void idxd_shutdown(struct pci_dev *pdev) + + for (i = 0; i < msixcnt; i++) { + irq_entry = &idxd->irq_entries[i]; +- synchronize_irq(idxd->msix_entries[i].vector); ++ synchronize_irq(irq_entry->vector); ++ free_irq(irq_entry->vector, irq_entry); + if (i == 0) + continue; + idxd_flush_pending_llist(irq_entry); +@@ -503,6 +492,7 @@ static void idxd_shutdown(struct pci_dev *pdev) + } + + idxd_msix_perm_clear(idxd); ++ pci_free_irq_vectors(pdev); + destroy_workqueue(idxd->wq); + } + +-- +2.30.2 + diff --git a/queue-5.12/dmaengine-idxd-fix-cdev-setup-and-free-device-lifeti.patch b/queue-5.12/dmaengine-idxd-fix-cdev-setup-and-free-device-lifeti.patch new file mode 100644 index 00000000000..8000cc4c289 --- /dev/null +++ b/queue-5.12/dmaengine-idxd-fix-cdev-setup-and-free-device-lifeti.patch @@ -0,0 +1,312 @@ +From 4a469a007cf28c07f7c00b04952480811537e9ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 16:37:57 -0700 +Subject: dmaengine: idxd: fix cdev setup and free device lifetime issues + +From: Dave Jiang + +[ Upstream commit 04922b7445a1950b86f130a1fe8c52cc27b3e30b ] + +The char device setup and cleanup has device lifetime issues regarding when +parts are initialized and cleaned up. The initialization of struct device is +done incorrectly. device_initialize() needs to be called on the 'struct +device' and then additional changes can be added. The ->release() function +needs to be setup via device_type before dev_set_name() to allow proper +cleanup. The change re-parents the cdev under the wq->conf_dev to get +natural reference inheritance. No known dependency on the old device path exists. + +Reported-by: Jason Gunthorpe +Fixes: 42d279f9137a ("dmaengine: idxd: add char driver to expose submission portal to userland") +Signed-off-by: Dave Jiang +Reviewed-by: Dan Williams +Link: https://lore.kernel.org/r/161852987721.2203940.1478218825576630810.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/cdev.c | 129 ++++++++++++++------------------------- + drivers/dma/idxd/idxd.h | 7 ++- + drivers/dma/idxd/init.c | 2 +- + drivers/dma/idxd/irq.c | 4 +- + drivers/dma/idxd/sysfs.c | 10 ++- + 5 files changed, 63 insertions(+), 89 deletions(-) + +diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c +index 0db9b82ed8cf..1d8a3876b745 100644 +--- a/drivers/dma/idxd/cdev.c ++++ b/drivers/dma/idxd/cdev.c +@@ -39,15 +39,15 @@ struct idxd_user_context { + struct iommu_sva *sva; + }; + +-enum idxd_cdev_cleanup { +- CDEV_NORMAL = 0, +- CDEV_FAILED, +-}; +- + static void idxd_cdev_dev_release(struct device *dev) + { +- dev_dbg(dev, "releasing cdev device\n"); +- kfree(dev); ++ struct idxd_cdev *idxd_cdev = container_of(dev, struct idxd_cdev, dev); ++ struct idxd_cdev_context *cdev_ctx; ++ struct idxd_wq *wq = idxd_cdev->wq; ++ ++ cdev_ctx = &ictx[wq->idxd->type]; ++ ida_simple_remove(&cdev_ctx->minor_ida, idxd_cdev->minor); ++ kfree(idxd_cdev); + } + + static struct device_type idxd_cdev_device_type = { +@@ -62,14 +62,11 @@ static inline struct idxd_cdev *inode_idxd_cdev(struct inode *inode) + return container_of(cdev, struct idxd_cdev, cdev); + } + +-static inline struct idxd_wq *idxd_cdev_wq(struct idxd_cdev *idxd_cdev) +-{ +- return container_of(idxd_cdev, struct idxd_wq, idxd_cdev); +-} +- + static inline struct idxd_wq *inode_wq(struct inode *inode) + { +- return idxd_cdev_wq(inode_idxd_cdev(inode)); ++ struct idxd_cdev *idxd_cdev = inode_idxd_cdev(inode); ++ ++ return idxd_cdev->wq; + } + + static int idxd_cdev_open(struct inode *inode, struct file *filp) +@@ -220,11 +217,10 @@ static __poll_t idxd_cdev_poll(struct file *filp, + struct idxd_user_context *ctx = filp->private_data; + struct idxd_wq *wq = ctx->wq; + struct idxd_device *idxd = wq->idxd; +- struct idxd_cdev *idxd_cdev = &wq->idxd_cdev; + unsigned long flags; + __poll_t out = 0; + +- poll_wait(filp, &idxd_cdev->err_queue, wait); ++ poll_wait(filp, &wq->err_queue, wait); + spin_lock_irqsave(&idxd->dev_lock, flags); + if (idxd->sw_err.valid) + out = EPOLLIN | EPOLLRDNORM; +@@ -246,98 +242,67 @@ int idxd_cdev_get_major(struct idxd_device *idxd) + return MAJOR(ictx[idxd->type].devt); + } + +-static int idxd_wq_cdev_dev_setup(struct idxd_wq *wq) ++int idxd_wq_add_cdev(struct idxd_wq *wq) + { + struct idxd_device *idxd = wq->idxd; +- struct idxd_cdev *idxd_cdev = &wq->idxd_cdev; +- struct idxd_cdev_context *cdev_ctx; ++ struct idxd_cdev *idxd_cdev; ++ struct cdev *cdev; + struct device *dev; +- int minor, rc; ++ struct idxd_cdev_context *cdev_ctx; ++ int rc, minor; + +- idxd_cdev->dev = kzalloc(sizeof(*idxd_cdev->dev), GFP_KERNEL); +- if (!idxd_cdev->dev) ++ idxd_cdev = kzalloc(sizeof(*idxd_cdev), GFP_KERNEL); ++ if (!idxd_cdev) + return -ENOMEM; + +- dev = idxd_cdev->dev; +- dev->parent = &idxd->pdev->dev; +- dev_set_name(dev, "%s/wq%u.%u", idxd_get_dev_name(idxd), +- idxd->id, wq->id); +- dev->bus = idxd_get_bus_type(idxd); +- ++ idxd_cdev->wq = wq; ++ cdev = &idxd_cdev->cdev; ++ dev = &idxd_cdev->dev; + cdev_ctx = &ictx[wq->idxd->type]; + minor = ida_simple_get(&cdev_ctx->minor_ida, 0, MINORMASK, GFP_KERNEL); + if (minor < 0) { +- rc = minor; +- kfree(dev); +- goto ida_err; +- } +- +- dev->devt = MKDEV(MAJOR(cdev_ctx->devt), minor); +- dev->type = &idxd_cdev_device_type; +- rc = device_register(dev); +- if (rc < 0) { +- dev_err(&idxd->pdev->dev, "device register failed\n"); +- goto dev_reg_err; ++ kfree(idxd_cdev); ++ return minor; + } + idxd_cdev->minor = minor; + +- return 0; +- +- dev_reg_err: +- ida_simple_remove(&cdev_ctx->minor_ida, MINOR(dev->devt)); +- put_device(dev); +- ida_err: +- idxd_cdev->dev = NULL; +- return rc; +-} +- +-static void idxd_wq_cdev_cleanup(struct idxd_wq *wq, +- enum idxd_cdev_cleanup cdev_state) +-{ +- struct idxd_cdev *idxd_cdev = &wq->idxd_cdev; +- struct idxd_cdev_context *cdev_ctx; +- +- cdev_ctx = &ictx[wq->idxd->type]; +- if (cdev_state == CDEV_NORMAL) +- cdev_del(&idxd_cdev->cdev); +- device_unregister(idxd_cdev->dev); +- /* +- * The device_type->release() will be called on the device and free +- * the allocated struct device. We can just forget it. +- */ +- ida_simple_remove(&cdev_ctx->minor_ida, idxd_cdev->minor); +- idxd_cdev->dev = NULL; +- idxd_cdev->minor = -1; +-} +- +-int idxd_wq_add_cdev(struct idxd_wq *wq) +-{ +- struct idxd_cdev *idxd_cdev = &wq->idxd_cdev; +- struct cdev *cdev = &idxd_cdev->cdev; +- struct device *dev; +- int rc; ++ device_initialize(dev); ++ dev->parent = &wq->conf_dev; ++ dev->bus = idxd_get_bus_type(idxd); ++ dev->type = &idxd_cdev_device_type; ++ dev->devt = MKDEV(MAJOR(cdev_ctx->devt), minor); + +- rc = idxd_wq_cdev_dev_setup(wq); ++ rc = dev_set_name(dev, "%s/wq%u.%u", idxd_get_dev_name(idxd), ++ idxd->id, wq->id); + if (rc < 0) +- return rc; ++ goto err; + +- dev = idxd_cdev->dev; ++ wq->idxd_cdev = idxd_cdev; + cdev_init(cdev, &idxd_cdev_fops); +- cdev_set_parent(cdev, &dev->kobj); +- rc = cdev_add(cdev, dev->devt, 1); ++ rc = cdev_device_add(cdev, dev); + if (rc) { + dev_dbg(&wq->idxd->pdev->dev, "cdev_add failed: %d\n", rc); +- idxd_wq_cdev_cleanup(wq, CDEV_FAILED); +- return rc; ++ goto err; + } + +- init_waitqueue_head(&idxd_cdev->err_queue); + return 0; ++ ++ err: ++ put_device(dev); ++ wq->idxd_cdev = NULL; ++ return rc; + } + + void idxd_wq_del_cdev(struct idxd_wq *wq) + { +- idxd_wq_cdev_cleanup(wq, CDEV_NORMAL); ++ struct idxd_cdev *idxd_cdev; ++ struct idxd_cdev_context *cdev_ctx; ++ ++ cdev_ctx = &ictx[wq->idxd->type]; ++ idxd_cdev = wq->idxd_cdev; ++ wq->idxd_cdev = NULL; ++ cdev_device_del(&idxd_cdev->cdev, &idxd_cdev->dev); ++ put_device(&idxd_cdev->dev); + } + + int idxd_cdev_register(void) +diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h +index 3c4ce7997c88..89daf746d121 100644 +--- a/drivers/dma/idxd/idxd.h ++++ b/drivers/dma/idxd/idxd.h +@@ -80,10 +80,10 @@ enum idxd_wq_type { + }; + + struct idxd_cdev { ++ struct idxd_wq *wq; + struct cdev cdev; +- struct device *dev; ++ struct device dev; + int minor; +- struct wait_queue_head err_queue; + }; + + #define IDXD_ALLOCATED_BATCH_SIZE 128U +@@ -109,7 +109,8 @@ struct idxd_dma_chan { + struct idxd_wq { + void __iomem *portal; + struct device conf_dev; +- struct idxd_cdev idxd_cdev; ++ struct idxd_cdev *idxd_cdev; ++ struct wait_queue_head err_queue; + struct idxd_device *idxd; + int id; + enum idxd_wq_type type; +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index c20ea6bf09bf..07cf7977a045 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -176,7 +176,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd) + } + + mutex_init(&wq->wq_lock); +- wq->idxd_cdev.minor = -1; ++ init_waitqueue_head(&wq->err_queue); + wq->max_xfer_bytes = idxd->max_xfer_bytes; + wq->max_batch_size = idxd->max_batch_size; + wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); +diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c +index 7b0181532f77..fc0781e3f36d 100644 +--- a/drivers/dma/idxd/irq.c ++++ b/drivers/dma/idxd/irq.c +@@ -133,7 +133,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) + struct idxd_wq *wq = idxd->wqs[id]; + + if (wq->type == IDXD_WQT_USER) +- wake_up_interruptible(&wq->idxd_cdev.err_queue); ++ wake_up_interruptible(&wq->err_queue); + } else { + int i; + +@@ -141,7 +141,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) + struct idxd_wq *wq = idxd->wqs[i]; + + if (wq->type == IDXD_WQT_USER) +- wake_up_interruptible(&wq->idxd_cdev.err_queue); ++ wake_up_interruptible(&wq->err_queue); + } + } + +diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c +index f793688039c9..9586b55abce5 100644 +--- a/drivers/dma/idxd/sysfs.c ++++ b/drivers/dma/idxd/sysfs.c +@@ -1169,8 +1169,16 @@ static ssize_t wq_cdev_minor_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); ++ int minor = -1; + +- return sprintf(buf, "%d\n", wq->idxd_cdev.minor); ++ mutex_lock(&wq->wq_lock); ++ if (wq->idxd_cdev) ++ minor = wq->idxd_cdev->minor; ++ mutex_unlock(&wq->wq_lock); ++ ++ if (minor == -1) ++ return -ENXIO; ++ return sysfs_emit(buf, "%d\n", minor); + } + + static struct device_attribute dev_attr_wq_cdev_minor = +-- +2.30.2 + diff --git a/queue-5.12/dmaengine-idxd-fix-dma-device-lifetime.patch b/queue-5.12/dmaengine-idxd-fix-dma-device-lifetime.patch new file mode 100644 index 00000000000..71920c4cd24 --- /dev/null +++ b/queue-5.12/dmaengine-idxd-fix-dma-device-lifetime.patch @@ -0,0 +1,243 @@ +From d507f463f5eabdd88c627857767a516b5bf066b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 16:37:10 -0700 +Subject: dmaengine: idxd: fix dma device lifetime + +From: Dave Jiang + +[ Upstream commit 397862855619271296e46d10f7dfa7bafe71eb81 ] + +The devm managed lifetime is incompatible with 'struct device' objects that +resides in idxd context. This is one of the series that clean up the idxd +driver 'struct device' lifetime. Remove embedding of dma_device and dma_chan +in idxd since it's not the only interface that idxd will use. The freeing of +the dma_device will be managed by the ->release() function. + +Reported-by: Jason Gunthorpe +Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") +Signed-off-by: Dave Jiang +Reviewed-by: Dan Williams +Link: https://lore.kernel.org/r/161852983001.2203940.14817017492384561719.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/device.c | 2 - + drivers/dma/idxd/dma.c | 77 ++++++++++++++++++++++++++++++++------- + drivers/dma/idxd/idxd.h | 18 +++++++-- + 3 files changed, 79 insertions(+), 18 deletions(-) + +diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c +index 78d2dc5e9bd8..d255bb016c4d 100644 +--- a/drivers/dma/idxd/device.c ++++ b/drivers/dma/idxd/device.c +@@ -186,8 +186,6 @@ int idxd_wq_alloc_resources(struct idxd_wq *wq) + desc->id = i; + desc->wq = wq; + desc->cpu = -1; +- dma_async_tx_descriptor_init(&desc->txd, &wq->dma_chan); +- desc->txd.tx_submit = idxd_dma_tx_submit; + } + + return 0; +diff --git a/drivers/dma/idxd/dma.c b/drivers/dma/idxd/dma.c +index a15e50126434..77439b645044 100644 +--- a/drivers/dma/idxd/dma.c ++++ b/drivers/dma/idxd/dma.c +@@ -14,7 +14,10 @@ + + static inline struct idxd_wq *to_idxd_wq(struct dma_chan *c) + { +- return container_of(c, struct idxd_wq, dma_chan); ++ struct idxd_dma_chan *idxd_chan; ++ ++ idxd_chan = container_of(c, struct idxd_dma_chan, chan); ++ return idxd_chan->wq; + } + + void idxd_dma_complete_txd(struct idxd_desc *desc, +@@ -135,7 +138,7 @@ static void idxd_dma_issue_pending(struct dma_chan *dma_chan) + { + } + +-dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx) ++static dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx) + { + struct dma_chan *c = tx->chan; + struct idxd_wq *wq = to_idxd_wq(c); +@@ -156,14 +159,25 @@ dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx) + + static void idxd_dma_release(struct dma_device *device) + { ++ struct idxd_dma_dev *idxd_dma = container_of(device, struct idxd_dma_dev, dma); ++ ++ kfree(idxd_dma); + } + + int idxd_register_dma_device(struct idxd_device *idxd) + { +- struct dma_device *dma = &idxd->dma_dev; ++ struct idxd_dma_dev *idxd_dma; ++ struct dma_device *dma; ++ struct device *dev = &idxd->pdev->dev; ++ int rc; + ++ idxd_dma = kzalloc_node(sizeof(*idxd_dma), GFP_KERNEL, dev_to_node(dev)); ++ if (!idxd_dma) ++ return -ENOMEM; ++ ++ dma = &idxd_dma->dma; + INIT_LIST_HEAD(&dma->channels); +- dma->dev = &idxd->pdev->dev; ++ dma->dev = dev; + + dma_cap_set(DMA_PRIVATE, dma->cap_mask); + dma_cap_set(DMA_COMPLETION_NO_ORDER, dma->cap_mask); +@@ -179,35 +193,72 @@ int idxd_register_dma_device(struct idxd_device *idxd) + dma->device_alloc_chan_resources = idxd_dma_alloc_chan_resources; + dma->device_free_chan_resources = idxd_dma_free_chan_resources; + +- return dma_async_device_register(&idxd->dma_dev); ++ rc = dma_async_device_register(dma); ++ if (rc < 0) { ++ kfree(idxd_dma); ++ return rc; ++ } ++ ++ idxd_dma->idxd = idxd; ++ /* ++ * This pointer is protected by the refs taken by the dma_chan. It will remain valid ++ * as long as there are outstanding channels. ++ */ ++ idxd->idxd_dma = idxd_dma; ++ return 0; + } + + void idxd_unregister_dma_device(struct idxd_device *idxd) + { +- dma_async_device_unregister(&idxd->dma_dev); ++ dma_async_device_unregister(&idxd->idxd_dma->dma); + } + + int idxd_register_dma_channel(struct idxd_wq *wq) + { + struct idxd_device *idxd = wq->idxd; +- struct dma_device *dma = &idxd->dma_dev; +- struct dma_chan *chan = &wq->dma_chan; +- int rc; ++ struct dma_device *dma = &idxd->idxd_dma->dma; ++ struct device *dev = &idxd->pdev->dev; ++ struct idxd_dma_chan *idxd_chan; ++ struct dma_chan *chan; ++ int rc, i; ++ ++ idxd_chan = kzalloc_node(sizeof(*idxd_chan), GFP_KERNEL, dev_to_node(dev)); ++ if (!idxd_chan) ++ return -ENOMEM; + +- memset(&wq->dma_chan, 0, sizeof(struct dma_chan)); ++ chan = &idxd_chan->chan; + chan->device = dma; + list_add_tail(&chan->device_node, &dma->channels); ++ ++ for (i = 0; i < wq->num_descs; i++) { ++ struct idxd_desc *desc = wq->descs[i]; ++ ++ dma_async_tx_descriptor_init(&desc->txd, chan); ++ desc->txd.tx_submit = idxd_dma_tx_submit; ++ } ++ + rc = dma_async_device_channel_register(dma, chan); +- if (rc < 0) ++ if (rc < 0) { ++ kfree(idxd_chan); + return rc; ++ } ++ ++ wq->idxd_chan = idxd_chan; ++ idxd_chan->wq = wq; ++ get_device(&wq->conf_dev); + + return 0; + } + + void idxd_unregister_dma_channel(struct idxd_wq *wq) + { +- struct dma_chan *chan = &wq->dma_chan; ++ struct idxd_dma_chan *idxd_chan = wq->idxd_chan; ++ struct dma_chan *chan = &idxd_chan->chan; ++ struct idxd_dma_dev *idxd_dma = wq->idxd->idxd_dma; + +- dma_async_device_channel_unregister(&wq->idxd->dma_dev, chan); ++ dma_async_device_channel_unregister(&idxd_dma->dma, chan); + list_del(&chan->device_node); ++ kfree(wq->idxd_chan); ++ wq->idxd_chan = NULL; ++ put_device(&wq->conf_dev); + } +diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h +index 76014c14f473..80e534680c9a 100644 +--- a/drivers/dma/idxd/idxd.h ++++ b/drivers/dma/idxd/idxd.h +@@ -14,6 +14,9 @@ + + extern struct kmem_cache *idxd_desc_pool; + ++struct idxd_device; ++struct idxd_wq; ++ + #define IDXD_REG_TIMEOUT 50 + #define IDXD_DRAIN_TIMEOUT 5000 + +@@ -96,6 +99,11 @@ enum idxd_complete_type { + IDXD_COMPLETE_DEV_FAIL, + }; + ++struct idxd_dma_chan { ++ struct dma_chan chan; ++ struct idxd_wq *wq; ++}; ++ + struct idxd_wq { + void __iomem *portal; + struct device conf_dev; +@@ -125,7 +133,7 @@ struct idxd_wq { + int compls_size; + struct idxd_desc **descs; + struct sbitmap_queue sbq; +- struct dma_chan dma_chan; ++ struct idxd_dma_chan *idxd_chan; + char name[WQ_NAME_SIZE + 1]; + u64 max_xfer_bytes; + u32 max_batch_size; +@@ -162,6 +170,11 @@ enum idxd_device_flag { + IDXD_FLAG_PASID_ENABLED, + }; + ++struct idxd_dma_dev { ++ struct idxd_device *idxd; ++ struct dma_device dma; ++}; ++ + struct idxd_device { + enum idxd_type type; + struct device conf_dev; +@@ -210,7 +223,7 @@ struct idxd_device { + int num_wq_irqs; + struct idxd_irq_entry *irq_entries; + +- struct dma_device dma_dev; ++ struct idxd_dma_dev *idxd_dma; + struct workqueue_struct *wq; + struct work_struct work; + }; +@@ -363,7 +376,6 @@ void idxd_unregister_dma_channel(struct idxd_wq *wq); + void idxd_parse_completion_status(u8 status, enum dmaengine_tx_result *res); + void idxd_dma_complete_txd(struct idxd_desc *desc, + enum idxd_complete_type comp_type); +-dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx); + + /* cdev */ + int idxd_cdev_register(void); +-- +2.30.2 + diff --git a/queue-5.12/dmaengine-idxd-fix-engine-conf_dev-lifetime.patch b/queue-5.12/dmaengine-idxd-fix-engine-conf_dev-lifetime.patch new file mode 100644 index 00000000000..6b809bf8c37 --- /dev/null +++ b/queue-5.12/dmaengine-idxd-fix-engine-conf_dev-lifetime.patch @@ -0,0 +1,293 @@ +From 4f6cd6eb1badedc601cf9f632bb6870795f511d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 16:37:44 -0700 +Subject: dmaengine: idxd: fix engine conf_dev lifetime + +From: Dave Jiang + +[ Upstream commit 75b911309060f42ba94bbbf46f5f497d35d5cd02 ] + +Remove devm_* allocation and fix engine->conf_dev 'struct device' +lifetime. Address issues flagged by CONFIG_DEBUG_KOBJECT_RELEASE. +Add release functions in order to free the allocated memory at the +engine conf_dev destruction time. + +Reported-by: Jason Gunthorpe +Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") +Signed-off-by: Dave Jiang +Link: https://lore.kernel.org/r/161852986460.2203940.16603218225412118431.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/device.c | 2 +- + drivers/dma/idxd/idxd.h | 3 +- + drivers/dma/idxd/init.c | 60 +++++++++++++++++++++++++------- + drivers/dma/idxd/sysfs.c | 72 +++++++++++++++++++-------------------- + 4 files changed, 86 insertions(+), 51 deletions(-) + +diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c +index c4183294a704..be1dcddfe3c4 100644 +--- a/drivers/dma/idxd/device.c ++++ b/drivers/dma/idxd/device.c +@@ -786,7 +786,7 @@ static int idxd_engines_setup(struct idxd_device *idxd) + } + + for (i = 0; i < idxd->max_engines; i++) { +- eng = &idxd->engines[i]; ++ eng = idxd->engines[i]; + group = eng->group; + + if (!group) +diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h +index 6cade6a05314..b9b7e8e8c384 100644 +--- a/drivers/dma/idxd/idxd.h ++++ b/drivers/dma/idxd/idxd.h +@@ -195,7 +195,7 @@ struct idxd_device { + struct completion *cmd_done; + struct idxd_group *groups; + struct idxd_wq **wqs; +- struct idxd_engine *engines; ++ struct idxd_engine **engines; + + struct iommu_sva *sva; + unsigned int pasid; +@@ -259,6 +259,7 @@ extern bool support_enqcmd; + extern struct device_type dsa_device_type; + extern struct device_type iax_device_type; + extern struct device_type idxd_wq_device_type; ++extern struct device_type idxd_engine_device_type; + + static inline bool is_dsa_dev(struct device *dev) + { +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index a2dca27aebc3..b90ef2f519eb 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -196,6 +196,46 @@ static int idxd_setup_wqs(struct idxd_device *idxd) + return rc; + } + ++static int idxd_setup_engines(struct idxd_device *idxd) ++{ ++ struct idxd_engine *engine; ++ struct device *dev = &idxd->pdev->dev; ++ int i, rc; ++ ++ idxd->engines = kcalloc_node(idxd->max_engines, sizeof(struct idxd_engine *), ++ GFP_KERNEL, dev_to_node(dev)); ++ if (!idxd->engines) ++ return -ENOMEM; ++ ++ for (i = 0; i < idxd->max_engines; i++) { ++ engine = kzalloc_node(sizeof(*engine), GFP_KERNEL, dev_to_node(dev)); ++ if (!engine) { ++ rc = -ENOMEM; ++ goto err; ++ } ++ ++ engine->id = i; ++ engine->idxd = idxd; ++ device_initialize(&engine->conf_dev); ++ engine->conf_dev.parent = &idxd->conf_dev; ++ engine->conf_dev.type = &idxd_engine_device_type; ++ rc = dev_set_name(&engine->conf_dev, "engine%d.%d", idxd->id, engine->id); ++ if (rc < 0) { ++ put_device(&engine->conf_dev); ++ goto err; ++ } ++ ++ idxd->engines[i] = engine; ++ } ++ ++ return 0; ++ ++ err: ++ while (--i >= 0) ++ put_device(&idxd->engines[i]->conf_dev); ++ return rc; ++} ++ + static int idxd_setup_internals(struct idxd_device *idxd) + { + struct device *dev = &idxd->pdev->dev; +@@ -207,6 +247,10 @@ static int idxd_setup_internals(struct idxd_device *idxd) + if (rc < 0) + return rc; + ++ rc = idxd_setup_engines(idxd); ++ if (rc < 0) ++ goto err_engine; ++ + idxd->groups = devm_kcalloc(dev, idxd->max_groups, + sizeof(struct idxd_group), GFP_KERNEL); + if (!idxd->groups) { +@@ -221,19 +265,6 @@ static int idxd_setup_internals(struct idxd_device *idxd) + idxd->groups[i].tc_b = -1; + } + +- idxd->engines = devm_kcalloc(dev, idxd->max_engines, +- sizeof(struct idxd_engine), GFP_KERNEL); +- if (!idxd->engines) { +- rc = -ENOMEM; +- goto err; +- } +- +- +- for (i = 0; i < idxd->max_engines; i++) { +- idxd->engines[i].idxd = idxd; +- idxd->engines[i].id = i; +- } +- + idxd->wq = create_workqueue(dev_name(dev)); + if (!idxd->wq) { + rc = -ENOMEM; +@@ -243,6 +274,9 @@ static int idxd_setup_internals(struct idxd_device *idxd) + return 0; + + err: ++ for (i = 0; i < idxd->max_engines; i++) ++ put_device(&idxd->engines[i]->conf_dev); ++ err_engine: + for (i = 0; i < idxd->max_wqs; i++) + put_device(&idxd->wqs[i]->conf_dev); + return rc; +diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c +index 409b3ce52f07..ab02e3b4d75d 100644 +--- a/drivers/dma/idxd/sysfs.c ++++ b/drivers/dma/idxd/sysfs.c +@@ -26,11 +26,6 @@ static struct device_type idxd_group_device_type = { + .release = idxd_conf_sub_device_release, + }; + +-static struct device_type idxd_engine_device_type = { +- .name = "engine", +- .release = idxd_conf_sub_device_release, +-}; +- + static int idxd_config_bus_match(struct device *dev, + struct device_driver *drv) + { +@@ -464,6 +459,19 @@ static const struct attribute_group *idxd_engine_attribute_groups[] = { + NULL, + }; + ++static void idxd_conf_engine_release(struct device *dev) ++{ ++ struct idxd_engine *engine = container_of(dev, struct idxd_engine, conf_dev); ++ ++ kfree(engine); ++} ++ ++struct device_type idxd_engine_device_type = { ++ .name = "engine", ++ .release = idxd_conf_engine_release, ++ .groups = idxd_engine_attribute_groups, ++}; ++ + /* Group attributes */ + + static void idxd_set_free_tokens(struct idxd_device *idxd) +@@ -626,7 +634,7 @@ static ssize_t group_engines_show(struct device *dev, + struct idxd_device *idxd = group->idxd; + + for (i = 0; i < idxd->max_engines; i++) { +- struct idxd_engine *engine = &idxd->engines[i]; ++ struct idxd_engine *engine = idxd->engines[i]; + + if (!engine->group) + continue; +@@ -1634,37 +1642,27 @@ struct device_type iax_device_type = { + .groups = idxd_attribute_groups, + }; + +-static int idxd_setup_engine_sysfs(struct idxd_device *idxd) ++static int idxd_register_engine_devices(struct idxd_device *idxd) + { +- struct device *dev = &idxd->pdev->dev; +- int i, rc; ++ int i, j, rc; + + for (i = 0; i < idxd->max_engines; i++) { +- struct idxd_engine *engine = &idxd->engines[i]; +- +- engine->conf_dev.parent = &idxd->conf_dev; +- dev_set_name(&engine->conf_dev, "engine%d.%d", +- idxd->id, engine->id); +- engine->conf_dev.bus = idxd_get_bus_type(idxd); +- engine->conf_dev.groups = idxd_engine_attribute_groups; +- engine->conf_dev.type = &idxd_engine_device_type; +- dev_dbg(dev, "Engine device register: %s\n", +- dev_name(&engine->conf_dev)); +- rc = device_register(&engine->conf_dev); +- if (rc < 0) { +- put_device(&engine->conf_dev); ++ struct idxd_engine *engine = idxd->engines[i]; ++ ++ rc = device_add(&engine->conf_dev); ++ if (rc < 0) + goto cleanup; +- } + } + + return 0; + + cleanup: +- while (i--) { +- struct idxd_engine *engine = &idxd->engines[i]; ++ j = i - 1; ++ for (; i < idxd->max_engines; i++) ++ put_device(&idxd->engines[i]->conf_dev); + +- device_unregister(&engine->conf_dev); +- } ++ while (j--) ++ device_unregister(&idxd->engines[j]->conf_dev); + return rc; + } + +@@ -1741,23 +1739,25 @@ int idxd_register_devices(struct idxd_device *idxd) + goto err_wq; + } + +- rc = idxd_setup_group_sysfs(idxd); ++ rc = idxd_register_engine_devices(idxd); + if (rc < 0) { +- /* unregister conf dev */ +- dev_dbg(dev, "Group sysfs registering failed: %d\n", rc); +- goto err; ++ dev_dbg(dev, "Engine devices registering failed: %d\n", rc); ++ goto err_engine; + } + +- rc = idxd_setup_engine_sysfs(idxd); ++ rc = idxd_setup_group_sysfs(idxd); + if (rc < 0) { + /* unregister conf dev */ +- dev_dbg(dev, "Engine sysfs registering failed: %d\n", rc); +- goto err; ++ dev_dbg(dev, "Group sysfs registering failed: %d\n", rc); ++ goto err_group; + } + + return 0; + +- err: ++ err_group: ++ for (i = 0; i < idxd->max_engines; i++) ++ device_unregister(&idxd->engines[i]->conf_dev); ++ err_engine: + for (i = 0; i < idxd->max_wqs; i++) + device_unregister(&idxd->wqs[i]->conf_dev); + err_wq: +@@ -1776,7 +1776,7 @@ void idxd_unregister_devices(struct idxd_device *idxd) + } + + for (i = 0; i < idxd->max_engines; i++) { +- struct idxd_engine *engine = &idxd->engines[i]; ++ struct idxd_engine *engine = idxd->engines[i]; + + device_unregister(&engine->conf_dev); + } +-- +2.30.2 + diff --git a/queue-5.12/dmaengine-idxd-fix-group-conf_dev-lifetime.patch b/queue-5.12/dmaengine-idxd-fix-group-conf_dev-lifetime.patch new file mode 100644 index 00000000000..451ce22c4ca --- /dev/null +++ b/queue-5.12/dmaengine-idxd-fix-group-conf_dev-lifetime.patch @@ -0,0 +1,328 @@ +From 566572f390dfe8280fd114c7c64d5725f2985d22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 16:37:51 -0700 +Subject: dmaengine: idxd: fix group conf_dev lifetime + +From: Dave Jiang + +[ Upstream commit defe49f96012ca91e8e673cb95b5c30b4a3735e8 ] + +Remove devm_* allocation and fix group->conf_dev 'struct device' +lifetime. Address issues flagged by CONFIG_DEBUG_KOBJECT_RELEASE. +Add release functions in order to free the allocated memory at the +group->conf_dev destruction time. + +Reported-by: Jason Gunthorpe +Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") +Signed-off-by: Dave Jiang +Link: https://lore.kernel.org/r/161852987144.2203940.8830315575880047.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/device.c | 8 ++--- + drivers/dma/idxd/idxd.h | 3 +- + drivers/dma/idxd/init.c | 68 ++++++++++++++++++++++++++++++--------- + drivers/dma/idxd/sysfs.c | 68 +++++++++++++++++---------------------- + 4 files changed, 88 insertions(+), 59 deletions(-) + +diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c +index be1dcddfe3c4..4fef57717049 100644 +--- a/drivers/dma/idxd/device.c ++++ b/drivers/dma/idxd/device.c +@@ -659,7 +659,7 @@ static int idxd_groups_config_write(struct idxd_device *idxd) + ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET)); + + for (i = 0; i < idxd->max_groups; i++) { +- struct idxd_group *group = &idxd->groups[i]; ++ struct idxd_group *group = idxd->groups[i]; + + idxd_group_config_write(group); + } +@@ -754,7 +754,7 @@ static void idxd_group_flags_setup(struct idxd_device *idxd) + + /* TC-A 0 and TC-B 1 should be defaults */ + for (i = 0; i < idxd->max_groups; i++) { +- struct idxd_group *group = &idxd->groups[i]; ++ struct idxd_group *group = idxd->groups[i]; + + if (group->tc_a == -1) + group->tc_a = group->grpcfg.flags.tc_a = 0; +@@ -781,7 +781,7 @@ static int idxd_engines_setup(struct idxd_device *idxd) + struct idxd_group *group; + + for (i = 0; i < idxd->max_groups; i++) { +- group = &idxd->groups[i]; ++ group = idxd->groups[i]; + group->grpcfg.engines = 0; + } + +@@ -810,7 +810,7 @@ static int idxd_wqs_setup(struct idxd_device *idxd) + struct device *dev = &idxd->pdev->dev; + + for (i = 0; i < idxd->max_groups; i++) { +- group = &idxd->groups[i]; ++ group = idxd->groups[i]; + for (j = 0; j < 4; j++) + group->grpcfg.wqs[j] = 0; + } +diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h +index b9b7e8e8c384..3c4ce7997c88 100644 +--- a/drivers/dma/idxd/idxd.h ++++ b/drivers/dma/idxd/idxd.h +@@ -193,7 +193,7 @@ struct idxd_device { + + spinlock_t dev_lock; /* spinlock for device */ + struct completion *cmd_done; +- struct idxd_group *groups; ++ struct idxd_group **groups; + struct idxd_wq **wqs; + struct idxd_engine **engines; + +@@ -260,6 +260,7 @@ extern struct device_type dsa_device_type; + extern struct device_type iax_device_type; + extern struct device_type idxd_wq_device_type; + extern struct device_type idxd_engine_device_type; ++extern struct device_type idxd_group_device_type; + + static inline bool is_dsa_dev(struct device *dev) + { +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index b90ef2f519eb..c20ea6bf09bf 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -236,11 +236,54 @@ static int idxd_setup_engines(struct idxd_device *idxd) + return rc; + } + +-static int idxd_setup_internals(struct idxd_device *idxd) ++static int idxd_setup_groups(struct idxd_device *idxd) + { + struct device *dev = &idxd->pdev->dev; ++ struct idxd_group *group; + int i, rc; + ++ idxd->groups = kcalloc_node(idxd->max_groups, sizeof(struct idxd_group *), ++ GFP_KERNEL, dev_to_node(dev)); ++ if (!idxd->groups) ++ return -ENOMEM; ++ ++ for (i = 0; i < idxd->max_groups; i++) { ++ group = kzalloc_node(sizeof(*group), GFP_KERNEL, dev_to_node(dev)); ++ if (!group) { ++ rc = -ENOMEM; ++ goto err; ++ } ++ ++ group->id = i; ++ group->idxd = idxd; ++ device_initialize(&group->conf_dev); ++ group->conf_dev.parent = &idxd->conf_dev; ++ group->conf_dev.bus = idxd_get_bus_type(idxd); ++ group->conf_dev.type = &idxd_group_device_type; ++ rc = dev_set_name(&group->conf_dev, "group%d.%d", idxd->id, group->id); ++ if (rc < 0) { ++ put_device(&group->conf_dev); ++ goto err; ++ } ++ ++ idxd->groups[i] = group; ++ group->tc_a = -1; ++ group->tc_b = -1; ++ } ++ ++ return 0; ++ ++ err: ++ while (--i >= 0) ++ put_device(&idxd->groups[i]->conf_dev); ++ return rc; ++} ++ ++static int idxd_setup_internals(struct idxd_device *idxd) ++{ ++ struct device *dev = &idxd->pdev->dev; ++ int rc, i; ++ + init_waitqueue_head(&idxd->cmd_waitq); + + rc = idxd_setup_wqs(idxd); +@@ -251,29 +294,22 @@ static int idxd_setup_internals(struct idxd_device *idxd) + if (rc < 0) + goto err_engine; + +- idxd->groups = devm_kcalloc(dev, idxd->max_groups, +- sizeof(struct idxd_group), GFP_KERNEL); +- if (!idxd->groups) { +- rc = -ENOMEM; +- goto err; +- } +- +- for (i = 0; i < idxd->max_groups; i++) { +- idxd->groups[i].idxd = idxd; +- idxd->groups[i].id = i; +- idxd->groups[i].tc_a = -1; +- idxd->groups[i].tc_b = -1; +- } ++ rc = idxd_setup_groups(idxd); ++ if (rc < 0) ++ goto err_group; + + idxd->wq = create_workqueue(dev_name(dev)); + if (!idxd->wq) { + rc = -ENOMEM; +- goto err; ++ goto err_wkq_create; + } + + return 0; + +- err: ++ err_wkq_create: ++ for (i = 0; i < idxd->max_groups; i++) ++ put_device(&idxd->groups[i]->conf_dev); ++ err_group: + for (i = 0; i < idxd->max_engines; i++) + put_device(&idxd->engines[i]->conf_dev); + err_engine: +diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c +index ab02e3b4d75d..f793688039c9 100644 +--- a/drivers/dma/idxd/sysfs.c ++++ b/drivers/dma/idxd/sysfs.c +@@ -16,16 +16,6 @@ static char *idxd_wq_type_names[] = { + [IDXD_WQT_USER] = "user", + }; + +-static void idxd_conf_sub_device_release(struct device *dev) +-{ +- dev_dbg(dev, "%s for %s\n", __func__, dev_name(dev)); +-} +- +-static struct device_type idxd_group_device_type = { +- .name = "group", +- .release = idxd_conf_sub_device_release, +-}; +- + static int idxd_config_bus_match(struct device *dev, + struct device_driver *drv) + { +@@ -435,7 +425,7 @@ static ssize_t engine_group_id_store(struct device *dev, + + if (prevg) + prevg->num_engines--; +- engine->group = &idxd->groups[id]; ++ engine->group = idxd->groups[id]; + engine->group->num_engines++; + + return count; +@@ -479,7 +469,7 @@ static void idxd_set_free_tokens(struct idxd_device *idxd) + int i, tokens; + + for (i = 0, tokens = 0; i < idxd->max_groups; i++) { +- struct idxd_group *g = &idxd->groups[i]; ++ struct idxd_group *g = idxd->groups[i]; + + tokens += g->tokens_reserved; + } +@@ -784,6 +774,19 @@ static const struct attribute_group *idxd_group_attribute_groups[] = { + NULL, + }; + ++static void idxd_conf_group_release(struct device *dev) ++{ ++ struct idxd_group *group = container_of(dev, struct idxd_group, conf_dev); ++ ++ kfree(group); ++} ++ ++struct device_type idxd_group_device_type = { ++ .name = "group", ++ .release = idxd_conf_group_release, ++ .groups = idxd_group_attribute_groups, ++}; ++ + /* IDXD work queue attribs */ + static ssize_t wq_clients_show(struct device *dev, + struct device_attribute *attr, char *buf) +@@ -856,7 +859,7 @@ static ssize_t wq_group_id_store(struct device *dev, + return count; + } + +- group = &idxd->groups[id]; ++ group = idxd->groups[id]; + prevg = wq->group; + + if (prevg) +@@ -1666,37 +1669,27 @@ cleanup: + return rc; + } + +-static int idxd_setup_group_sysfs(struct idxd_device *idxd) ++static int idxd_register_group_devices(struct idxd_device *idxd) + { +- struct device *dev = &idxd->pdev->dev; +- int i, rc; ++ int i, j, rc; + + for (i = 0; i < idxd->max_groups; i++) { +- struct idxd_group *group = &idxd->groups[i]; +- +- group->conf_dev.parent = &idxd->conf_dev; +- dev_set_name(&group->conf_dev, "group%d.%d", +- idxd->id, group->id); +- group->conf_dev.bus = idxd_get_bus_type(idxd); +- group->conf_dev.groups = idxd_group_attribute_groups; +- group->conf_dev.type = &idxd_group_device_type; +- dev_dbg(dev, "Group device register: %s\n", +- dev_name(&group->conf_dev)); +- rc = device_register(&group->conf_dev); +- if (rc < 0) { +- put_device(&group->conf_dev); ++ struct idxd_group *group = idxd->groups[i]; ++ ++ rc = device_add(&group->conf_dev); ++ if (rc < 0) + goto cleanup; +- } + } + + return 0; + + cleanup: +- while (i--) { +- struct idxd_group *group = &idxd->groups[i]; ++ j = i - 1; ++ for (; i < idxd->max_groups; i++) ++ put_device(&idxd->groups[i]->conf_dev); + +- device_unregister(&group->conf_dev); +- } ++ while (j--) ++ device_unregister(&idxd->groups[j]->conf_dev); + return rc; + } + +@@ -1745,10 +1738,9 @@ int idxd_register_devices(struct idxd_device *idxd) + goto err_engine; + } + +- rc = idxd_setup_group_sysfs(idxd); ++ rc = idxd_register_group_devices(idxd); + if (rc < 0) { +- /* unregister conf dev */ +- dev_dbg(dev, "Group sysfs registering failed: %d\n", rc); ++ dev_dbg(dev, "Group device registering failed: %d\n", rc); + goto err_group; + } + +@@ -1782,7 +1774,7 @@ void idxd_unregister_devices(struct idxd_device *idxd) + } + + for (i = 0; i < idxd->max_groups; i++) { +- struct idxd_group *group = &idxd->groups[i]; ++ struct idxd_group *group = idxd->groups[i]; + + device_unregister(&group->conf_dev); + } +-- +2.30.2 + diff --git a/queue-5.12/dmaengine-idxd-fix-idxd-conf_dev-struct-device-lifet.patch b/queue-5.12/dmaengine-idxd-fix-idxd-conf_dev-struct-device-lifet.patch new file mode 100644 index 00000000000..f9525784bf8 --- /dev/null +++ b/queue-5.12/dmaengine-idxd-fix-idxd-conf_dev-struct-device-lifet.patch @@ -0,0 +1,390 @@ +From 754370abfbca6a2037ed66f96411978412cd9fd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 16:37:33 -0700 +Subject: dmaengine: idxd: fix idxd conf_dev 'struct device' lifetime + +From: Dave Jiang + +[ Upstream commit 47c16ac27d4cb664cee53ee0b9b7e2f907923fb3 ] + +The devm managed lifetime is incompatible with 'struct device' objects that +resides in idxd context. This is one of the series that clean up the idxd +driver 'struct device' lifetime. Fix idxd->conf_dev 'struct device' +lifetime. Address issues flagged by CONFIG_DEBUG_KOBJECT_RELEASE. +Add release functions in order to free the allocated memory at the +appropriate time. + +Reported-by: Jason Gunthorpe +Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") +Signed-off-by: Dave Jiang +Link: https://lore.kernel.org/r/161852985319.2203940.4650791514462735368.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/idxd.h | 36 ++++++++++------ + drivers/dma/idxd/init.c | 56 ++++++++++++++++-------- + drivers/dma/idxd/sysfs.c | 92 ++++++++++++++-------------------------- + 3 files changed, 94 insertions(+), 90 deletions(-) + +diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h +index 401b035e42b1..bb3a580732af 100644 +--- a/drivers/dma/idxd/idxd.h ++++ b/drivers/dma/idxd/idxd.h +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include "registers.h" + + #define IDXD_DRIVER_VERSION "1.00" +@@ -255,6 +256,23 @@ extern struct bus_type dsa_bus_type; + extern struct bus_type iax_bus_type; + + extern bool support_enqcmd; ++extern struct device_type dsa_device_type; ++extern struct device_type iax_device_type; ++ ++static inline bool is_dsa_dev(struct device *dev) ++{ ++ return dev->type == &dsa_device_type; ++} ++ ++static inline bool is_iax_dev(struct device *dev) ++{ ++ return dev->type == &iax_device_type; ++} ++ ++static inline bool is_idxd_dev(struct device *dev) ++{ ++ return is_dsa_dev(dev) || is_iax_dev(dev); ++} + + static inline bool wq_dedicated(struct idxd_wq *wq) + { +@@ -292,18 +310,6 @@ static inline int idxd_get_wq_portal_full_offset(int wq_id, + return ((wq_id * 4) << PAGE_SHIFT) + idxd_get_wq_portal_offset(prot); + } + +-static inline void idxd_set_type(struct idxd_device *idxd) +-{ +- struct pci_dev *pdev = idxd->pdev; +- +- if (pdev->device == PCI_DEVICE_ID_INTEL_DSA_SPR0) +- idxd->type = IDXD_TYPE_DSA; +- else if (pdev->device == PCI_DEVICE_ID_INTEL_IAX_SPR0) +- idxd->type = IDXD_TYPE_IAX; +- else +- idxd->type = IDXD_TYPE_UNKNOWN; +-} +- + static inline void idxd_wq_get(struct idxd_wq *wq) + { + wq->client_count++; +@@ -319,14 +325,16 @@ static inline int idxd_wq_refcount(struct idxd_wq *wq) + return wq->client_count; + }; + ++struct ida *idxd_ida(struct idxd_device *idxd); + const char *idxd_get_dev_name(struct idxd_device *idxd); + int idxd_register_bus_type(void); + void idxd_unregister_bus_type(void); +-int idxd_setup_sysfs(struct idxd_device *idxd); +-void idxd_cleanup_sysfs(struct idxd_device *idxd); ++int idxd_register_devices(struct idxd_device *idxd); ++void idxd_unregister_devices(struct idxd_device *idxd); + int idxd_register_driver(void); + void idxd_unregister_driver(void); + struct bus_type *idxd_get_bus_type(struct idxd_device *idxd); ++struct device_type *idxd_get_device_type(struct idxd_device *idxd); + + /* device interrupt control */ + void idxd_msix_perm_setup(struct idxd_device *idxd); +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index a4f0489515b4..17d3b36610a9 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -51,6 +51,11 @@ static char *idxd_name[] = { + "iax" + }; + ++struct ida *idxd_ida(struct idxd_device *idxd) ++{ ++ return &idxd_idas[idxd->type]; ++} ++ + const char *idxd_get_dev_name(struct idxd_device *idxd) + { + return idxd_name[idxd->type]; +@@ -81,9 +86,8 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) + * We implement 1 completion list per MSI-X entry except for + * entry 0, which is for errors and others. + */ +- idxd->irq_entries = devm_kcalloc(dev, msixcnt, +- sizeof(struct idxd_irq_entry), +- GFP_KERNEL); ++ idxd->irq_entries = kcalloc_node(msixcnt, sizeof(struct idxd_irq_entry), ++ GFP_KERNEL, dev_to_node(dev)); + if (!idxd->irq_entries) { + rc = -ENOMEM; + goto err_irq_entries; +@@ -262,16 +266,44 @@ static void idxd_read_caps(struct idxd_device *idxd) + } + } + ++static inline void idxd_set_type(struct idxd_device *idxd) ++{ ++ struct pci_dev *pdev = idxd->pdev; ++ ++ if (pdev->device == PCI_DEVICE_ID_INTEL_DSA_SPR0) ++ idxd->type = IDXD_TYPE_DSA; ++ else if (pdev->device == PCI_DEVICE_ID_INTEL_IAX_SPR0) ++ idxd->type = IDXD_TYPE_IAX; ++ else ++ idxd->type = IDXD_TYPE_UNKNOWN; ++} ++ + static struct idxd_device *idxd_alloc(struct pci_dev *pdev) + { + struct device *dev = &pdev->dev; + struct idxd_device *idxd; ++ int rc; + +- idxd = devm_kzalloc(dev, sizeof(struct idxd_device), GFP_KERNEL); ++ idxd = kzalloc_node(sizeof(*idxd), GFP_KERNEL, dev_to_node(dev)); + if (!idxd) + return NULL; + + idxd->pdev = pdev; ++ idxd_set_type(idxd); ++ idxd->id = ida_alloc(idxd_ida(idxd), GFP_KERNEL); ++ if (idxd->id < 0) ++ return NULL; ++ ++ device_initialize(&idxd->conf_dev); ++ idxd->conf_dev.parent = dev; ++ idxd->conf_dev.bus = idxd_get_bus_type(idxd); ++ idxd->conf_dev.type = idxd_get_device_type(idxd); ++ rc = dev_set_name(&idxd->conf_dev, "%s%d", idxd_get_dev_name(idxd), idxd->id); ++ if (rc < 0) { ++ put_device(&idxd->conf_dev); ++ return NULL; ++ } ++ + spin_lock_init(&idxd->dev_lock); + + return idxd; +@@ -347,20 +379,11 @@ static int idxd_probe(struct idxd_device *idxd) + + dev_dbg(dev, "IDXD interrupt setup complete.\n"); + +- idxd->id = ida_alloc(&idxd_idas[idxd->type], GFP_KERNEL); +- if (idxd->id < 0) { +- rc = -ENOMEM; +- goto err_ida_fail; +- } +- + idxd->major = idxd_cdev_get_major(idxd); + + dev_dbg(dev, "IDXD device %d probed successfully\n", idxd->id); + return 0; + +- err_ida_fail: +- idxd_mask_error_interrupts(idxd); +- idxd_mask_msix_vectors(idxd); + err_setup: + if (device_pasid_enabled(idxd)) + idxd_disable_system_pasid(idxd); +@@ -412,7 +435,6 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if (rc) + goto err; + +- idxd_set_type(idxd); + + idxd_type_init(idxd); + +@@ -427,7 +449,7 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + goto err; + } + +- rc = idxd_setup_sysfs(idxd); ++ rc = idxd_register_devices(idxd); + if (rc) { + dev_err(dev, "IDXD sysfs setup failed\n"); + goto err; +@@ -443,6 +465,7 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + err: + pci_iounmap(pdev, idxd->reg_base); + err_iomap: ++ put_device(&idxd->conf_dev); + err_idxd_alloc: + pci_disable_device(pdev); + return rc; +@@ -511,11 +534,10 @@ static void idxd_remove(struct pci_dev *pdev) + struct idxd_device *idxd = pci_get_drvdata(pdev); + + dev_dbg(&pdev->dev, "%s called\n", __func__); +- idxd_cleanup_sysfs(idxd); + idxd_shutdown(pdev); + if (device_pasid_enabled(idxd)) + idxd_disable_system_pasid(idxd); +- ida_free(&idxd_idas[idxd->type], idxd->id); ++ idxd_unregister_devices(idxd); + } + + static struct pci_driver idxd_pci_driver = { +diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c +index 18bf4d148989..36193e555e36 100644 +--- a/drivers/dma/idxd/sysfs.c ++++ b/drivers/dma/idxd/sysfs.c +@@ -16,51 +16,26 @@ static char *idxd_wq_type_names[] = { + [IDXD_WQT_USER] = "user", + }; + +-static void idxd_conf_device_release(struct device *dev) ++static void idxd_conf_sub_device_release(struct device *dev) + { + dev_dbg(dev, "%s for %s\n", __func__, dev_name(dev)); + } + + static struct device_type idxd_group_device_type = { + .name = "group", +- .release = idxd_conf_device_release, ++ .release = idxd_conf_sub_device_release, + }; + + static struct device_type idxd_wq_device_type = { + .name = "wq", +- .release = idxd_conf_device_release, ++ .release = idxd_conf_sub_device_release, + }; + + static struct device_type idxd_engine_device_type = { + .name = "engine", +- .release = idxd_conf_device_release, ++ .release = idxd_conf_sub_device_release, + }; + +-static struct device_type dsa_device_type = { +- .name = "dsa", +- .release = idxd_conf_device_release, +-}; +- +-static struct device_type iax_device_type = { +- .name = "iax", +- .release = idxd_conf_device_release, +-}; +- +-static inline bool is_dsa_dev(struct device *dev) +-{ +- return dev ? dev->type == &dsa_device_type : false; +-} +- +-static inline bool is_iax_dev(struct device *dev) +-{ +- return dev ? dev->type == &iax_device_type : false; +-} +- +-static inline bool is_idxd_dev(struct device *dev) +-{ +- return is_dsa_dev(dev) || is_iax_dev(dev); +-} +- + static inline bool is_idxd_wq_dev(struct device *dev) + { + return dev ? dev->type == &idxd_wq_device_type : false; +@@ -405,7 +380,7 @@ struct bus_type *idxd_get_bus_type(struct idxd_device *idxd) + return idxd_bus_types[idxd->type]; + } + +-static struct device_type *idxd_get_device_type(struct idxd_device *idxd) ++struct device_type *idxd_get_device_type(struct idxd_device *idxd) + { + if (idxd->type == IDXD_TYPE_DSA) + return &dsa_device_type; +@@ -1644,6 +1619,30 @@ static const struct attribute_group *idxd_attribute_groups[] = { + NULL, + }; + ++static void idxd_conf_device_release(struct device *dev) ++{ ++ struct idxd_device *idxd = container_of(dev, struct idxd_device, conf_dev); ++ ++ kfree(idxd->groups); ++ kfree(idxd->wqs); ++ kfree(idxd->engines); ++ kfree(idxd->irq_entries); ++ ida_free(idxd_ida(idxd), idxd->id); ++ kfree(idxd); ++} ++ ++struct device_type dsa_device_type = { ++ .name = "dsa", ++ .release = idxd_conf_device_release, ++ .groups = idxd_attribute_groups, ++}; ++ ++struct device_type iax_device_type = { ++ .name = "iax", ++ .release = idxd_conf_device_release, ++ .groups = idxd_attribute_groups, ++}; ++ + static int idxd_setup_engine_sysfs(struct idxd_device *idxd) + { + struct device *dev = &idxd->pdev->dev; +@@ -1745,39 +1744,14 @@ cleanup: + return rc; + } + +-static int idxd_setup_device_sysfs(struct idxd_device *idxd) ++int idxd_register_devices(struct idxd_device *idxd) + { + struct device *dev = &idxd->pdev->dev; + int rc; +- char devname[IDXD_NAME_SIZE]; + +- sprintf(devname, "%s%d", idxd_get_dev_name(idxd), idxd->id); +- idxd->conf_dev.parent = dev; +- dev_set_name(&idxd->conf_dev, "%s", devname); +- idxd->conf_dev.bus = idxd_get_bus_type(idxd); +- idxd->conf_dev.groups = idxd_attribute_groups; +- idxd->conf_dev.type = idxd_get_device_type(idxd); +- +- dev_dbg(dev, "IDXD device register: %s\n", dev_name(&idxd->conf_dev)); +- rc = device_register(&idxd->conf_dev); +- if (rc < 0) { +- put_device(&idxd->conf_dev); +- return rc; +- } +- +- return 0; +-} +- +-int idxd_setup_sysfs(struct idxd_device *idxd) +-{ +- struct device *dev = &idxd->pdev->dev; +- int rc; +- +- rc = idxd_setup_device_sysfs(idxd); +- if (rc < 0) { +- dev_dbg(dev, "Device sysfs registering failed: %d\n", rc); ++ rc = device_add(&idxd->conf_dev); ++ if (rc < 0) + return rc; +- } + + rc = idxd_setup_wq_sysfs(idxd); + if (rc < 0) { +@@ -1803,7 +1777,7 @@ int idxd_setup_sysfs(struct idxd_device *idxd) + return 0; + } + +-void idxd_cleanup_sysfs(struct idxd_device *idxd) ++void idxd_unregister_devices(struct idxd_device *idxd) + { + int i; + +-- +2.30.2 + diff --git a/queue-5.12/dmaengine-idxd-fix-potential-null-dereference-on-poi.patch b/queue-5.12/dmaengine-idxd-fix-potential-null-dereference-on-poi.patch new file mode 100644 index 00000000000..ecbe628200c --- /dev/null +++ b/queue-5.12/dmaengine-idxd-fix-potential-null-dereference-on-poi.patch @@ -0,0 +1,44 @@ +From b96fe86d7dd2be099ce5cb785ba70f5f40fca957 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 12:06:54 +0100 +Subject: dmaengine: idxd: Fix potential null dereference on pointer status + +From: Colin Ian King + +[ Upstream commit 28ac8e03c43dfc6a703aa420d18222540b801120 ] + +There are calls to idxd_cmd_exec that pass a null status pointer however +a recent commit has added an assignment to *status that can end up +with a null pointer dereference. The function expects a null status +pointer sometimes as there is a later assignment to *status where +status is first null checked. Fix the issue by null checking status +before making the assignment. + +Addresses-Coverity: ("Explicit null dereferenced") +Fixes: 89e3becd8f82 ("dmaengine: idxd: check device state before issue command") +Signed-off-by: Colin Ian King +Acked-by: Dave Jiang +Link: https://lore.kernel.org/r/20210415110654.1941580-1-colin.king@canonical.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/device.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c +index 31c819544a22..78d2dc5e9bd8 100644 +--- a/drivers/dma/idxd/device.c ++++ b/drivers/dma/idxd/device.c +@@ -451,7 +451,8 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, + + if (idxd_device_is_halted(idxd)) { + dev_warn(&idxd->pdev->dev, "Device is HALTED!\n"); +- *status = IDXD_CMDSTS_HW_ERR; ++ if (status) ++ *status = IDXD_CMDSTS_HW_ERR; + return; + } + +-- +2.30.2 + diff --git a/queue-5.12/dmaengine-idxd-fix-wq-conf_dev-struct-device-lifetim.patch b/queue-5.12/dmaengine-idxd-fix-wq-conf_dev-struct-device-lifetim.patch new file mode 100644 index 00000000000..0d9cfc1066b --- /dev/null +++ b/queue-5.12/dmaengine-idxd-fix-wq-conf_dev-struct-device-lifetim.patch @@ -0,0 +1,506 @@ +From ac2d5b8ea596e7e3b5dd21d7b77aeb0cfc47870d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 16:37:39 -0700 +Subject: dmaengine: idxd: fix wq conf_dev 'struct device' lifetime + +From: Dave Jiang + +[ Upstream commit 7c5dd23e57c14cf7177b8a5e0fd08916e0c60005 ] + +Remove devm_* allocation and fix wq->conf_dev 'struct device' lifetime. +Address issues flagged by CONFIG_DEBUG_KOBJECT_RELEASE. Add release +functions in order to free the allocated memory for the wq context at +device destruction time. + +Reported-by: Jason Gunthorpe +Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") +Signed-off-by: Dave Jiang +Link: https://lore.kernel.org/r/161852985907.2203940.6840120734115043753.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/device.c | 6 +-- + drivers/dma/idxd/idxd.h | 20 +++++++- + drivers/dma/idxd/init.c | 105 ++++++++++++++++++++++++++++---------- + drivers/dma/idxd/irq.c | 6 +-- + drivers/dma/idxd/sysfs.c | 100 ++++++++++++++++-------------------- + 5 files changed, 146 insertions(+), 91 deletions(-) + +diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c +index 3f696abd74ac..c4183294a704 100644 +--- a/drivers/dma/idxd/device.c ++++ b/drivers/dma/idxd/device.c +@@ -520,7 +520,7 @@ void idxd_device_wqs_clear_state(struct idxd_device *idxd) + lockdep_assert_held(&idxd->dev_lock); + + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ struct idxd_wq *wq = idxd->wqs[i]; + + if (wq->state == IDXD_WQ_ENABLED) { + idxd_wq_disable_cleanup(wq); +@@ -738,7 +738,7 @@ static int idxd_wqs_config_write(struct idxd_device *idxd) + int i, rc; + + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ struct idxd_wq *wq = idxd->wqs[i]; + + rc = idxd_wq_config_write(wq); + if (rc < 0) +@@ -816,7 +816,7 @@ static int idxd_wqs_setup(struct idxd_device *idxd) + } + + for (i = 0; i < idxd->max_wqs; i++) { +- wq = &idxd->wqs[i]; ++ wq = idxd->wqs[i]; + group = wq->group; + + if (!wq->group) +diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h +index bb3a580732af..6cade6a05314 100644 +--- a/drivers/dma/idxd/idxd.h ++++ b/drivers/dma/idxd/idxd.h +@@ -194,7 +194,7 @@ struct idxd_device { + spinlock_t dev_lock; /* spinlock for device */ + struct completion *cmd_done; + struct idxd_group *groups; +- struct idxd_wq *wqs; ++ struct idxd_wq **wqs; + struct idxd_engine *engines; + + struct iommu_sva *sva; +@@ -258,6 +258,7 @@ extern struct bus_type iax_bus_type; + extern bool support_enqcmd; + extern struct device_type dsa_device_type; + extern struct device_type iax_device_type; ++extern struct device_type idxd_wq_device_type; + + static inline bool is_dsa_dev(struct device *dev) + { +@@ -274,6 +275,23 @@ static inline bool is_idxd_dev(struct device *dev) + return is_dsa_dev(dev) || is_iax_dev(dev); + } + ++static inline bool is_idxd_wq_dev(struct device *dev) ++{ ++ return dev->type == &idxd_wq_device_type; ++} ++ ++static inline bool is_idxd_wq_dmaengine(struct idxd_wq *wq) ++{ ++ if (wq->type == IDXD_WQT_KERNEL && strcmp(wq->name, "dmaengine") == 0) ++ return true; ++ return false; ++} ++ ++static inline bool is_idxd_wq_cdev(struct idxd_wq *wq) ++{ ++ return wq->type == IDXD_WQT_USER; ++} ++ + static inline bool wq_dedicated(struct idxd_wq *wq) + { + return test_bit(WQ_FLAG_DEDICATED, &wq->flags); +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index 17d3b36610a9..a2dca27aebc3 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -145,16 +145,74 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) + return rc; + } + ++static int idxd_setup_wqs(struct idxd_device *idxd) ++{ ++ struct device *dev = &idxd->pdev->dev; ++ struct idxd_wq *wq; ++ int i, rc; ++ ++ idxd->wqs = kcalloc_node(idxd->max_wqs, sizeof(struct idxd_wq *), ++ GFP_KERNEL, dev_to_node(dev)); ++ if (!idxd->wqs) ++ return -ENOMEM; ++ ++ for (i = 0; i < idxd->max_wqs; i++) { ++ wq = kzalloc_node(sizeof(*wq), GFP_KERNEL, dev_to_node(dev)); ++ if (!wq) { ++ rc = -ENOMEM; ++ goto err; ++ } ++ ++ wq->id = i; ++ wq->idxd = idxd; ++ device_initialize(&wq->conf_dev); ++ wq->conf_dev.parent = &idxd->conf_dev; ++ wq->conf_dev.bus = idxd_get_bus_type(idxd); ++ wq->conf_dev.type = &idxd_wq_device_type; ++ rc = dev_set_name(&wq->conf_dev, "wq%d.%d", idxd->id, wq->id); ++ if (rc < 0) { ++ put_device(&wq->conf_dev); ++ goto err; ++ } ++ ++ mutex_init(&wq->wq_lock); ++ wq->idxd_cdev.minor = -1; ++ wq->max_xfer_bytes = idxd->max_xfer_bytes; ++ wq->max_batch_size = idxd->max_batch_size; ++ wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); ++ if (!wq->wqcfg) { ++ put_device(&wq->conf_dev); ++ rc = -ENOMEM; ++ goto err; ++ } ++ idxd->wqs[i] = wq; ++ } ++ ++ return 0; ++ ++ err: ++ while (--i >= 0) ++ put_device(&idxd->wqs[i]->conf_dev); ++ return rc; ++} ++ + static int idxd_setup_internals(struct idxd_device *idxd) + { + struct device *dev = &idxd->pdev->dev; +- int i; ++ int i, rc; + + init_waitqueue_head(&idxd->cmd_waitq); ++ ++ rc = idxd_setup_wqs(idxd); ++ if (rc < 0) ++ return rc; ++ + idxd->groups = devm_kcalloc(dev, idxd->max_groups, + sizeof(struct idxd_group), GFP_KERNEL); +- if (!idxd->groups) +- return -ENOMEM; ++ if (!idxd->groups) { ++ rc = -ENOMEM; ++ goto err; ++ } + + for (i = 0; i < idxd->max_groups; i++) { + idxd->groups[i].idxd = idxd; +@@ -163,40 +221,31 @@ static int idxd_setup_internals(struct idxd_device *idxd) + idxd->groups[i].tc_b = -1; + } + +- idxd->wqs = devm_kcalloc(dev, idxd->max_wqs, sizeof(struct idxd_wq), +- GFP_KERNEL); +- if (!idxd->wqs) +- return -ENOMEM; +- + idxd->engines = devm_kcalloc(dev, idxd->max_engines, + sizeof(struct idxd_engine), GFP_KERNEL); +- if (!idxd->engines) +- return -ENOMEM; +- +- for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; +- +- wq->id = i; +- wq->idxd = idxd; +- mutex_init(&wq->wq_lock); +- wq->idxd_cdev.minor = -1; +- wq->max_xfer_bytes = idxd->max_xfer_bytes; +- wq->max_batch_size = idxd->max_batch_size; +- wq->wqcfg = devm_kzalloc(dev, idxd->wqcfg_size, GFP_KERNEL); +- if (!wq->wqcfg) +- return -ENOMEM; ++ if (!idxd->engines) { ++ rc = -ENOMEM; ++ goto err; + } + ++ + for (i = 0; i < idxd->max_engines; i++) { + idxd->engines[i].idxd = idxd; + idxd->engines[i].id = i; + } + + idxd->wq = create_workqueue(dev_name(dev)); +- if (!idxd->wq) +- return -ENOMEM; ++ if (!idxd->wq) { ++ rc = -ENOMEM; ++ goto err; ++ } + + return 0; ++ ++ err: ++ for (i = 0; i < idxd->max_wqs; i++) ++ put_device(&idxd->wqs[i]->conf_dev); ++ return rc; + } + + static void idxd_read_table_offsets(struct idxd_device *idxd) +@@ -371,11 +420,11 @@ static int idxd_probe(struct idxd_device *idxd) + + rc = idxd_setup_internals(idxd); + if (rc) +- goto err_setup; ++ goto err; + + rc = idxd_setup_interrupts(idxd); + if (rc) +- goto err_setup; ++ goto err; + + dev_dbg(dev, "IDXD interrupt setup complete.\n"); + +@@ -384,7 +433,7 @@ static int idxd_probe(struct idxd_device *idxd) + dev_dbg(dev, "IDXD device %d probed successfully\n", idxd->id); + return 0; + +- err_setup: ++ err: + if (device_pasid_enabled(idxd)) + idxd_disable_system_pasid(idxd); + return rc; +diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c +index f1463fc58112..7b0181532f77 100644 +--- a/drivers/dma/idxd/irq.c ++++ b/drivers/dma/idxd/irq.c +@@ -45,7 +45,7 @@ static void idxd_device_reinit(struct work_struct *work) + goto out; + + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ struct idxd_wq *wq = idxd->wqs[i]; + + if (wq->state == IDXD_WQ_ENABLED) { + rc = idxd_wq_enable(wq); +@@ -130,7 +130,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) + + if (idxd->sw_err.valid && idxd->sw_err.wq_idx_valid) { + int id = idxd->sw_err.wq_idx; +- struct idxd_wq *wq = &idxd->wqs[id]; ++ struct idxd_wq *wq = idxd->wqs[id]; + + if (wq->type == IDXD_WQT_USER) + wake_up_interruptible(&wq->idxd_cdev.err_queue); +@@ -138,7 +138,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) + int i; + + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ struct idxd_wq *wq = idxd->wqs[i]; + + if (wq->type == IDXD_WQT_USER) + wake_up_interruptible(&wq->idxd_cdev.err_queue); +diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c +index 36193e555e36..409b3ce52f07 100644 +--- a/drivers/dma/idxd/sysfs.c ++++ b/drivers/dma/idxd/sysfs.c +@@ -26,34 +26,11 @@ static struct device_type idxd_group_device_type = { + .release = idxd_conf_sub_device_release, + }; + +-static struct device_type idxd_wq_device_type = { +- .name = "wq", +- .release = idxd_conf_sub_device_release, +-}; +- + static struct device_type idxd_engine_device_type = { + .name = "engine", + .release = idxd_conf_sub_device_release, + }; + +-static inline bool is_idxd_wq_dev(struct device *dev) +-{ +- return dev ? dev->type == &idxd_wq_device_type : false; +-} +- +-static inline bool is_idxd_wq_dmaengine(struct idxd_wq *wq) +-{ +- if (wq->type == IDXD_WQT_KERNEL && +- strcmp(wq->name, "dmaengine") == 0) +- return true; +- return false; +-} +- +-static inline bool is_idxd_wq_cdev(struct idxd_wq *wq) +-{ +- return wq->type == IDXD_WQT_USER; +-} +- + static int idxd_config_bus_match(struct device *dev, + struct device_driver *drv) + { +@@ -297,7 +274,7 @@ static int idxd_config_bus_remove(struct device *dev) + dev_dbg(dev, "%s removing dev %s\n", __func__, + dev_name(&idxd->conf_dev)); + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ struct idxd_wq *wq = idxd->wqs[i]; + + if (wq->state == IDXD_WQ_DISABLED) + continue; +@@ -309,7 +286,7 @@ static int idxd_config_bus_remove(struct device *dev) + idxd_unregister_dma_device(idxd); + rc = idxd_device_disable(idxd); + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ struct idxd_wq *wq = idxd->wqs[i]; + + mutex_lock(&wq->wq_lock); + idxd_wq_disable_cleanup(wq); +@@ -678,7 +655,7 @@ static ssize_t group_work_queues_show(struct device *dev, + struct idxd_device *idxd = group->idxd; + + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ struct idxd_wq *wq = idxd->wqs[i]; + + if (!wq->group) + continue; +@@ -935,7 +912,7 @@ static int total_claimed_wq_size(struct idxd_device *idxd) + int wq_size = 0; + + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ struct idxd_wq *wq = idxd->wqs[i]; + + wq_size += wq->size; + } +@@ -1331,6 +1308,20 @@ static const struct attribute_group *idxd_wq_attribute_groups[] = { + NULL, + }; + ++static void idxd_conf_wq_release(struct device *dev) ++{ ++ struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); ++ ++ kfree(wq->wqcfg); ++ kfree(wq); ++} ++ ++struct device_type idxd_wq_device_type = { ++ .name = "wq", ++ .release = idxd_conf_wq_release, ++ .groups = idxd_wq_attribute_groups, ++}; ++ + /* IDXD device attribs */ + static ssize_t version_show(struct device *dev, struct device_attribute *attr, + char *buf) +@@ -1461,7 +1452,7 @@ static ssize_t clients_show(struct device *dev, + + spin_lock_irqsave(&idxd->dev_lock, flags); + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ struct idxd_wq *wq = idxd->wqs[i]; + + count += wq->client_count; + } +@@ -1711,70 +1702,67 @@ cleanup: + return rc; + } + +-static int idxd_setup_wq_sysfs(struct idxd_device *idxd) ++static int idxd_register_wq_devices(struct idxd_device *idxd) + { +- struct device *dev = &idxd->pdev->dev; +- int i, rc; ++ int i, rc, j; + + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; +- +- wq->conf_dev.parent = &idxd->conf_dev; +- dev_set_name(&wq->conf_dev, "wq%d.%d", idxd->id, wq->id); +- wq->conf_dev.bus = idxd_get_bus_type(idxd); +- wq->conf_dev.groups = idxd_wq_attribute_groups; +- wq->conf_dev.type = &idxd_wq_device_type; +- dev_dbg(dev, "WQ device register: %s\n", +- dev_name(&wq->conf_dev)); +- rc = device_register(&wq->conf_dev); +- if (rc < 0) { +- put_device(&wq->conf_dev); ++ struct idxd_wq *wq = idxd->wqs[i]; ++ ++ rc = device_add(&wq->conf_dev); ++ if (rc < 0) + goto cleanup; +- } + } + + return 0; + + cleanup: +- while (i--) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ j = i - 1; ++ for (; i < idxd->max_wqs; i++) ++ put_device(&idxd->wqs[i]->conf_dev); + +- device_unregister(&wq->conf_dev); +- } ++ while (j--) ++ device_unregister(&idxd->wqs[j]->conf_dev); + return rc; + } + + int idxd_register_devices(struct idxd_device *idxd) + { + struct device *dev = &idxd->pdev->dev; +- int rc; ++ int rc, i; + + rc = device_add(&idxd->conf_dev); + if (rc < 0) + return rc; + +- rc = idxd_setup_wq_sysfs(idxd); ++ rc = idxd_register_wq_devices(idxd); + if (rc < 0) { +- /* unregister conf dev */ +- dev_dbg(dev, "Work Queue sysfs registering failed: %d\n", rc); +- return rc; ++ dev_dbg(dev, "WQ devices registering failed: %d\n", rc); ++ goto err_wq; + } + + rc = idxd_setup_group_sysfs(idxd); + if (rc < 0) { + /* unregister conf dev */ + dev_dbg(dev, "Group sysfs registering failed: %d\n", rc); +- return rc; ++ goto err; + } + + rc = idxd_setup_engine_sysfs(idxd); + if (rc < 0) { + /* unregister conf dev */ + dev_dbg(dev, "Engine sysfs registering failed: %d\n", rc); +- return rc; ++ goto err; + } + + return 0; ++ ++ err: ++ for (i = 0; i < idxd->max_wqs; i++) ++ device_unregister(&idxd->wqs[i]->conf_dev); ++ err_wq: ++ device_del(&idxd->conf_dev); ++ return rc; + } + + void idxd_unregister_devices(struct idxd_device *idxd) +@@ -1782,7 +1770,7 @@ void idxd_unregister_devices(struct idxd_device *idxd) + int i; + + for (i = 0; i < idxd->max_wqs; i++) { +- struct idxd_wq *wq = &idxd->wqs[i]; ++ struct idxd_wq *wq = idxd->wqs[i]; + + device_unregister(&wq->conf_dev); + } +-- +2.30.2 + diff --git a/queue-5.12/dmaengine-idxd-removal-of-pcim-managed-mmio-mapping.patch b/queue-5.12/dmaengine-idxd-removal-of-pcim-managed-mmio-mapping.patch new file mode 100644 index 00000000000..4699a7ea2f0 --- /dev/null +++ b/queue-5.12/dmaengine-idxd-removal-of-pcim-managed-mmio-mapping.patch @@ -0,0 +1,117 @@ +From 861222097726bdea1d91b552e77c0400141fd99e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 16:37:21 -0700 +Subject: dmaengine: idxd: removal of pcim managed mmio mapping + +From: Dave Jiang + +[ Upstream commit a39c7cd0438ee2f0b859ee1eb86cdc52217d2223 ] + +The devm managed lifetime is incompatible with 'struct device' objects that +resides in idxd context. This is one of the series that clean up the idxd +driver 'struct device' lifetime. Remove pcim_* management of the PCI device +and the ioremap of MMIO BAR and replace with unmanaged versions. This is +for consistency of removing all the pcim/devm based calls. + +Reported-by: Jason Gunthorpe +Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") +Signed-off-by: Dave Jiang +Reviewed-by: Dan Williams +Link: https://lore.kernel.org/r/161852984150.2203940.8043988289748519056.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/init.c | 33 +++++++++++++++++++++++---------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index 5cf1bf095ae1..11a2e14b5b80 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -384,32 +384,36 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + struct idxd_device *idxd; + int rc; + +- rc = pcim_enable_device(pdev); ++ rc = pci_enable_device(pdev); + if (rc) + return rc; + + dev_dbg(dev, "Alloc IDXD context\n"); + idxd = idxd_alloc(pdev); +- if (!idxd) +- return -ENOMEM; ++ if (!idxd) { ++ rc = -ENOMEM; ++ goto err_idxd_alloc; ++ } + + dev_dbg(dev, "Mapping BARs\n"); +- idxd->reg_base = pcim_iomap(pdev, IDXD_MMIO_BAR, 0); +- if (!idxd->reg_base) +- return -ENOMEM; ++ idxd->reg_base = pci_iomap(pdev, IDXD_MMIO_BAR, 0); ++ if (!idxd->reg_base) { ++ rc = -ENOMEM; ++ goto err_iomap; ++ } + + dev_dbg(dev, "Set DMA masks\n"); + rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (rc) + rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (rc) +- return rc; ++ goto err; + + rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (rc) + rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (rc) +- return rc; ++ goto err; + + idxd_set_type(idxd); + +@@ -423,13 +427,13 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + rc = idxd_probe(idxd); + if (rc) { + dev_err(dev, "Intel(R) IDXD DMA Engine init failed\n"); +- return -ENODEV; ++ goto err; + } + + rc = idxd_setup_sysfs(idxd); + if (rc) { + dev_err(dev, "IDXD sysfs setup failed\n"); +- return -ENODEV; ++ goto err; + } + + idxd->state = IDXD_DEV_CONF_READY; +@@ -438,6 +442,13 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + idxd->hw.version); + + return 0; ++ ++ err: ++ pci_iounmap(pdev, idxd->reg_base); ++ err_iomap: ++ err_idxd_alloc: ++ pci_disable_device(pdev); ++ return rc; + } + + static void idxd_flush_pending_llist(struct idxd_irq_entry *ie) +@@ -493,6 +504,8 @@ static void idxd_shutdown(struct pci_dev *pdev) + + idxd_msix_perm_clear(idxd); + pci_free_irq_vectors(pdev); ++ pci_iounmap(pdev, idxd->reg_base); ++ pci_disable_device(pdev); + destroy_workqueue(idxd->wq); + } + +-- +2.30.2 + diff --git a/queue-5.12/dmaengine-idxd-use-ida-for-device-instance-enumerati.patch b/queue-5.12/dmaengine-idxd-use-ida-for-device-instance-enumerati.patch new file mode 100644 index 00000000000..cc0b4273f4c --- /dev/null +++ b/queue-5.12/dmaengine-idxd-use-ida-for-device-instance-enumerati.patch @@ -0,0 +1,83 @@ +From 55022ff73ce0cf2072365df2841de41702f62fe7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 16:37:27 -0700 +Subject: dmaengine: idxd: use ida for device instance enumeration + +From: Dave Jiang + +[ Upstream commit f7f7739847bd68b3c3103fd1b50d943038bd14c7 ] + +The idr is only used for an device id, never to lookup context from that +id. Switch to plain ida. + +Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") +Reported-by: Jason Gunthorpe +Signed-off-by: Dave Jiang +Link: https://lore.kernel.org/r/161852984730.2203940.15032482460902003819.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/init.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index 11a2e14b5b80..a4f0489515b4 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -34,8 +34,7 @@ MODULE_PARM_DESC(sva, "Toggle SVA support on/off"); + + bool support_enqcmd; + +-static struct idr idxd_idrs[IDXD_TYPE_MAX]; +-static DEFINE_MUTEX(idxd_idr_lock); ++static struct ida idxd_idas[IDXD_TYPE_MAX]; + + static struct pci_device_id idxd_pci_tbl[] = { + /* DSA ver 1.0 platforms */ +@@ -348,12 +347,10 @@ static int idxd_probe(struct idxd_device *idxd) + + dev_dbg(dev, "IDXD interrupt setup complete.\n"); + +- mutex_lock(&idxd_idr_lock); +- idxd->id = idr_alloc(&idxd_idrs[idxd->type], idxd, 0, 0, GFP_KERNEL); +- mutex_unlock(&idxd_idr_lock); ++ idxd->id = ida_alloc(&idxd_idas[idxd->type], GFP_KERNEL); + if (idxd->id < 0) { + rc = -ENOMEM; +- goto err_idr_fail; ++ goto err_ida_fail; + } + + idxd->major = idxd_cdev_get_major(idxd); +@@ -361,7 +358,7 @@ static int idxd_probe(struct idxd_device *idxd) + dev_dbg(dev, "IDXD device %d probed successfully\n", idxd->id); + return 0; + +- err_idr_fail: ++ err_ida_fail: + idxd_mask_error_interrupts(idxd); + idxd_mask_msix_vectors(idxd); + err_setup: +@@ -518,9 +515,7 @@ static void idxd_remove(struct pci_dev *pdev) + idxd_shutdown(pdev); + if (device_pasid_enabled(idxd)) + idxd_disable_system_pasid(idxd); +- mutex_lock(&idxd_idr_lock); +- idr_remove(&idxd_idrs[idxd->type], idxd->id); +- mutex_unlock(&idxd_idr_lock); ++ ida_free(&idxd_idas[idxd->type], idxd->id); + } + + static struct pci_driver idxd_pci_driver = { +@@ -550,7 +545,7 @@ static int __init idxd_init_module(void) + support_enqcmd = true; + + for (i = 0; i < IDXD_TYPE_MAX; i++) +- idr_init(&idxd_idrs[i]); ++ ida_init(&idxd_idas[i]); + + err = idxd_register_bus_type(); + if (err < 0) +-- +2.30.2 + diff --git a/queue-5.12/drm-amd-display-add-handling-for-hdcp2-rx-id-list-va.patch b/queue-5.12/drm-amd-display-add-handling-for-hdcp2-rx-id-list-va.patch new file mode 100644 index 00000000000..a9192026eb0 --- /dev/null +++ b/queue-5.12/drm-amd-display-add-handling-for-hdcp2-rx-id-list-va.patch @@ -0,0 +1,44 @@ +From b4198299fec5145e1600aa4b13aa8c5ea7cb3a80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jan 2021 18:05:50 -0500 +Subject: drm/amd/display: add handling for hdcp2 rx id list validation + +From: Dingchen (David) Zhang + +[ Upstream commit 4ccf9446b2a3615615045346c97f8a1e2a16568a ] + +[why] +the current implementation of hdcp2 rx id list validation does not +have handler/checker for invalid message status, e.g. HMAC, the V +parameter calculated from PSP not matching the V prime from Rx. + +[how] +return a generic FAILURE for any message status not SUCCESS or +REVOKED. + +Signed-off-by: Dingchen (David) Zhang +Reviewed-by: Bhawanpreet Lakha +Acked-by: Aurabindo Pillai +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +index 904ce9b88088..afbe8856468a 100644 +--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c ++++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +@@ -791,6 +791,8 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_rx_id_list(struct mod_hdcp *hdcp) + TA_HDCP2_MSG_AUTHENTICATION_STATUS__RECEIVERID_REVOKED) { + hdcp->connection.is_hdcp2_revoked = 1; + status = MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_REVOKED; ++ } else { ++ status = MOD_HDCP_STATUS_HDCP2_VALIDATE_RX_ID_LIST_FAILURE; + } + } + mutex_unlock(&psp->hdcp_context.mutex); +-- +2.30.2 + diff --git a/queue-5.12/drm-amd-display-fixed-divide-by-zero-kernel-crash-du.patch b/queue-5.12/drm-amd-display-fixed-divide-by-zero-kernel-crash-du.patch new file mode 100644 index 00000000000..c9915521443 --- /dev/null +++ b/queue-5.12/drm-amd-display-fixed-divide-by-zero-kernel-crash-du.patch @@ -0,0 +1,112 @@ +From 38a1cac47a04da6f2e1bc1b1ec2140f9847c57dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Dec 2020 19:14:48 -0500 +Subject: drm/amd/display: fixed divide by zero kernel crash during dsc + enablement + +From: Robin Singh + +[ Upstream commit 19cc1f3829567e7dca21c1389ea6407b8f5efab4 ] + +[why] +During dsc enable, a divide by zero condition triggered the +kernel crash. + +[how] +An IGT test, which enable the DSC, was crashing at the time of +restore the default dsc status, becaue of h_totals value +becoming 0. So add a check before divide condition. If h_total +is zero, gracefully ignore and set the default value. + +kernel panic log: + + [ 128.758827] divide error: 0000 [#1] PREEMPT SMP NOPTI + [ 128.762714] CPU: 5 PID: 4562 Comm: amd_dp_dsc Tainted: G W 5.4.19-android-x86_64 #1 + [ 128.769728] Hardware name: ADVANCED MICRO DEVICES, INC. Mauna/Mauna, BIOS WMN0B13N Nov 11 2020 + [ 128.777695] RIP: 0010:hubp2_vready_at_or_After_vsync+0x37/0x7a [amdgpu] + [ 128.785707] Code: 80 02 00 00 48 89 f3 48 8b 7f 08 b ...... + [ 128.805696] RSP: 0018:ffffad8f82d43628 EFLAGS: 00010246 + ...... + [ 128.857707] CR2: 00007106d8465000 CR3: 0000000426530000 CR4: 0000000000140ee0 + [ 128.865695] Call Trace: + [ 128.869712] hubp3_setup+0x1f/0x7f [amdgpu] + [ 128.873705] dcn20_update_dchubp_dpp+0xc8/0x54a [amdgpu] + [ 128.877706] dcn20_program_front_end_for_ctx+0x31d/0x463 [amdgpu] + [ 128.885706] dc_commit_state+0x3d2/0x658 [amdgpu] + [ 128.889707] amdgpu_dm_atomic_commit_tail+0x4b3/0x1e7c [amdgpu] + [ 128.897699] ? dm_read_reg_func+0x41/0xb5 [amdgpu] + [ 128.901707] ? dm_read_reg_func+0x41/0xb5 [amdgpu] + [ 128.905706] ? __is_insn_slot_addr+0x43/0x48 + [ 128.909706] ? fill_plane_buffer_attributes+0x29e/0x3dc [amdgpu] + [ 128.917705] ? dm_plane_helper_prepare_fb+0x255/0x284 [amdgpu] + [ 128.921700] ? usleep_range+0x7c/0x7c + [ 128.925705] ? preempt_count_sub+0xf/0x18 + [ 128.929706] ? _raw_spin_unlock_irq+0x13/0x24 + [ 128.933732] ? __wait_for_common+0x11e/0x18f + [ 128.937705] ? _raw_spin_unlock_irq+0x13/0x24 + [ 128.941706] ? __wait_for_common+0x11e/0x18f + [ 128.945705] commit_tail+0x8b/0xd2 [drm_kms_helper] + [ 128.949707] drm_atomic_helper_commit+0xd8/0xf5 [drm_kms_helper] + [ 128.957706] amdgpu_dm_atomic_commit+0x337/0x360 [amdgpu] + [ 128.961705] ? drm_atomic_check_only+0x543/0x68d [drm] + [ 128.969705] ? drm_atomic_set_property+0x760/0x7af [drm] + [ 128.973704] ? drm_mode_atomic_ioctl+0x6f3/0x85a [drm] + [ 128.977705] drm_mode_atomic_ioctl+0x6f3/0x85a [drm] + [ 128.985705] ? drm_atomic_set_property+0x7af/0x7af [drm] + [ 128.989706] drm_ioctl_kernel+0x82/0xda [drm] + [ 128.993706] drm_ioctl+0x225/0x319 [drm] + [ 128.997707] ? drm_atomic_set_property+0x7af/0x7af [drm] + [ 129.001706] ? preempt_count_sub+0xf/0x18 + [ 129.005713] amdgpu_drm_ioctl+0x4b/0x76 [amdgpu] + [ 129.009705] vfs_ioctl+0x1d/0x2a + [ 129.013705] do_vfs_ioctl+0x419/0x43d + [ 129.017707] ksys_ioctl+0x52/0x71 + [ 129.021707] __x64_sys_ioctl+0x16/0x19 + [ 129.025706] do_syscall_64+0x78/0x85 + [ 129.029705] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Signed-off-by: Robin Singh +Reviewed-by: Harry Wentland +Reviewed-by: Robin Singh +Acked-by: Aurabindo Pillai +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +index bec7059f6d5d..a1318c31bcfa 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +@@ -1,5 +1,5 @@ + /* +- * Copyright 2012-17 Advanced Micro Devices, Inc. ++ * Copyright 2012-2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), +@@ -181,11 +181,14 @@ void hubp2_vready_at_or_After_vsync(struct hubp *hubp, + else + Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 0 + */ +- if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width +- + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { +- value = 1; +- } else +- value = 0; ++ if (pipe_dest->htotal != 0) { ++ if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width ++ + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { ++ value = 1; ++ } else ++ value = 0; ++ } ++ + REG_UPDATE(DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, value); + } + +-- +2.30.2 + diff --git a/queue-5.12/drm-amd-display-force-vsync-flip-when-reconfiguring-.patch b/queue-5.12/drm-amd-display-force-vsync-flip-when-reconfiguring-.patch new file mode 100644 index 00000000000..b10c7316055 --- /dev/null +++ b/queue-5.12/drm-amd-display-force-vsync-flip-when-reconfiguring-.patch @@ -0,0 +1,45 @@ +From 809f28eb12b023a801ee58c0e164fb57c449ed28 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Mar 2021 11:03:35 -0400 +Subject: drm/amd/display: Force vsync flip when reconfiguring MPCC + +From: Anthony Wang + +[ Upstream commit 56d63782af9bbd1271bff1422a6a013123eade4d ] + +[Why] +Underflow observed when disabling PIP overlay in-game when +vsync is disabled, due to OTC master lock not working with +game pipe which is immediate flip. + +[How] +When performing a full update, override flip_immediate value +to false for all planes, so that flip occurs on vsync. + +Signed-off-by: Anthony Wang +Acked-by: Bindu Ramamurthy +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index c0b827d16268..4781279024a9 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -2546,6 +2546,10 @@ static void commit_planes_for_stream(struct dc *dc, + plane_state->triplebuffer_flips = true; + } + } ++ if (update_type == UPDATE_TYPE_FULL) { ++ /* force vsync flip when reconfiguring pipes to prevent underflow */ ++ plane_state->flip_immediate = false; ++ } + } + } + +-- +2.30.2 + diff --git a/queue-5.12/drm-amdgpu-add-mem-sync-flag-for-ib-allocated-by-sa.patch b/queue-5.12/drm-amdgpu-add-mem-sync-flag-for-ib-allocated-by-sa.patch new file mode 100644 index 00000000000..d0edc4ce20d --- /dev/null +++ b/queue-5.12/drm-amdgpu-add-mem-sync-flag-for-ib-allocated-by-sa.patch @@ -0,0 +1,40 @@ +From 39d93c9665451a15eaa0ef3e98909cf29b075379 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Apr 2021 16:17:14 +0800 +Subject: drm/amdgpu: Add mem sync flag for IB allocated by SA +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jinzhou Su + +[ Upstream commit 5c88e3b86a88f14efa0a3ddd28641c6ff49fb9c4 ] + +The buffer of SA bo will be used by many cases. So it's better +to invalidate the cache of indirect buffer allocated by SA before +commit the IB. + +Signed-off-by: Jinzhou Su +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +index 7645223ea0ef..97c11aa47ad0 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +@@ -77,6 +77,8 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, + } + + ib->ptr = amdgpu_sa_bo_cpu_addr(ib->sa_bo); ++ /* flush the cache before commit the IB */ ++ ib->flags = AMDGPU_IB_FLAG_EMIT_MEM_SYNC; + + if (!vm) + ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); +-- +2.30.2 + diff --git a/queue-5.12/drm-radeon-avoid-power-table-parsing-memory-leaks.patch b/queue-5.12/drm-radeon-avoid-power-table-parsing-memory-leaks.patch new file mode 100644 index 00000000000..b9c52265c0f --- /dev/null +++ b/queue-5.12/drm-radeon-avoid-power-table-parsing-memory-leaks.patch @@ -0,0 +1,64 @@ +From ede15584b9b647742bff6617b6680a26aba4c926 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 May 2021 22:06:08 -0700 +Subject: drm/radeon: Avoid power table parsing memory leaks + +From: Kees Cook + +[ Upstream commit c69f27137a38d24301a6b659454a91ad85dff4aa ] + +Avoid leaving a hanging pre-allocated clock_info if last mode is +invalid, and avoid heap corruption if no valid modes are found. + +Bug: https://bugzilla.kernel.org/show_bug.cgi?id=211537 +Fixes: 6991b8f2a319 ("drm/radeon/kms: fix segfault in pm rework") +Signed-off-by: Kees Cook +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/radeon/radeon_atombios.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +index f9f4efa1738c..28c4413f4dc8 100644 +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -2120,11 +2120,14 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) + return state_index; + /* last mode is usually default, array is low to high */ + for (i = 0; i < num_modes; i++) { +- rdev->pm.power_state[state_index].clock_info = +- kcalloc(1, sizeof(struct radeon_pm_clock_info), +- GFP_KERNEL); ++ /* avoid memory leaks from invalid modes or unknown frev. */ ++ if (!rdev->pm.power_state[state_index].clock_info) { ++ rdev->pm.power_state[state_index].clock_info = ++ kzalloc(sizeof(struct radeon_pm_clock_info), ++ GFP_KERNEL); ++ } + if (!rdev->pm.power_state[state_index].clock_info) +- return state_index; ++ goto out; + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; + switch (frev) { +@@ -2243,8 +2246,15 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) + break; + } + } ++out: ++ /* free any unused clock_info allocation. */ ++ if (state_index && state_index < num_modes) { ++ kfree(rdev->pm.power_state[state_index].clock_info); ++ rdev->pm.power_state[state_index].clock_info = NULL; ++ } ++ + /* last mode is usually default */ +- if (rdev->pm.default_power_state_index == -1) { ++ if (state_index && rdev->pm.default_power_state_index == -1) { + rdev->pm.power_state[state_index - 1].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = state_index - 1; +-- +2.30.2 + diff --git a/queue-5.12/drm-radeon-fix-off-by-one-power_state-index-heap-ove.patch b/queue-5.12/drm-radeon-fix-off-by-one-power_state-index-heap-ove.patch new file mode 100644 index 00000000000..c8fe219c80d --- /dev/null +++ b/queue-5.12/drm-radeon-fix-off-by-one-power_state-index-heap-ove.patch @@ -0,0 +1,119 @@ +From 4f4621caacbb42efcab48dcea0105781dd5a897c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 May 2021 22:06:07 -0700 +Subject: drm/radeon: Fix off-by-one power_state index heap overwrite + +From: Kees Cook + +[ Upstream commit 5bbf219328849e83878bddb7c226d8d42e84affc ] + +An out of bounds write happens when setting the default power state. +KASAN sees this as: + +[drm] radeon: 512M of GTT memory ready. +[drm] GART: num cpu pages 131072, num gpu pages 131072 +================================================================== +BUG: KASAN: slab-out-of-bounds in +radeon_atombios_parse_power_table_1_3+0x1837/0x1998 [radeon] +Write of size 4 at addr ffff88810178d858 by task systemd-udevd/157 + +CPU: 0 PID: 157 Comm: systemd-udevd Not tainted 5.12.0-E620 #50 +Hardware name: eMachines eMachines E620 /Nile , BIOS V1.03 09/30/2008 +Call Trace: + dump_stack+0xa5/0xe6 + print_address_description.constprop.0+0x18/0x239 + kasan_report+0x170/0x1a8 + radeon_atombios_parse_power_table_1_3+0x1837/0x1998 [radeon] + radeon_atombios_get_power_modes+0x144/0x1888 [radeon] + radeon_pm_init+0x1019/0x1904 [radeon] + rs690_init+0x76e/0x84a [radeon] + radeon_device_init+0x1c1a/0x21e5 [radeon] + radeon_driver_load_kms+0xf5/0x30b [radeon] + drm_dev_register+0x255/0x4a0 [drm] + radeon_pci_probe+0x246/0x2f6 [radeon] + pci_device_probe+0x1aa/0x294 + really_probe+0x30e/0x850 + driver_probe_device+0xe6/0x135 + device_driver_attach+0xc1/0xf8 + __driver_attach+0x13f/0x146 + bus_for_each_dev+0xfa/0x146 + bus_add_driver+0x2b3/0x447 + driver_register+0x242/0x2c1 + do_one_initcall+0x149/0x2fd + do_init_module+0x1ae/0x573 + load_module+0x4dee/0x5cca + __do_sys_finit_module+0xf1/0x140 + do_syscall_64+0x33/0x40 + entry_SYSCALL_64_after_hwframe+0x44/0xae + +Without KASAN, this will manifest later when the kernel attempts to +allocate memory that was stomped, since it collides with the inline slab +freelist pointer: + +invalid opcode: 0000 [#1] SMP NOPTI +CPU: 0 PID: 781 Comm: openrc-run.sh Tainted: G W 5.10.12-gentoo-E620 #2 +Hardware name: eMachines eMachines E620 /Nile , BIOS V1.03 09/30/2008 +RIP: 0010:kfree+0x115/0x230 +Code: 89 c5 e8 75 ea ff ff 48 8b 00 0f ba e0 09 72 63 e8 1f f4 ff ff 41 89 c4 48 8b 45 00 0f ba e0 10 72 0a 48 8b 45 08 a8 01 75 02 <0f> 0b 44 89 e1 48 c7 c2 00 f0 ff ff be 06 00 00 00 48 d3 e2 48 c7 +RSP: 0018:ffffb42f40267e10 EFLAGS: 00010246 +RAX: ffffd61280ee8d88 RBX: 0000000000000004 RCX: 000000008010000d +RDX: 4000000000000000 RSI: ffffffffba1360b0 RDI: ffffd61280ee8d80 +RBP: ffffd61280ee8d80 R08: ffffffffb91bebdf R09: 0000000000000000 +R10: ffff8fe2c1047ac8 R11: 0000000000000000 R12: 0000000000000000 +R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000100 +FS: 00007fe80eff6b68(0000) GS:ffff8fe339c00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007fe80eec7bc0 CR3: 0000000038012000 CR4: 00000000000006f0 +Call Trace: + __free_fdtable+0x16/0x1f + put_files_struct+0x81/0x9b + do_exit+0x433/0x94d + do_group_exit+0xa6/0xa6 + __x64_sys_exit_group+0xf/0xf + do_syscall_64+0x33/0x40 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 +RIP: 0033:0x7fe80ef64bea +Code: Unable to access opcode bytes at RIP 0x7fe80ef64bc0. +RSP: 002b:00007ffdb1c47528 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7 +RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fe80ef64bea +RDX: 00007fe80ef64f60 RSI: 0000000000000000 RDI: 0000000000000000 +RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 +R10: 00007fe80ee2c620 R11: 0000000000000246 R12: 00007fe80eff41e0 +R13: 00000000ffffffff R14: 0000000000000024 R15: 00007fe80edf9cd0 +Modules linked in: radeon(+) ath5k(+) snd_hda_codec_realtek ... + +Use a valid power_state index when initializing the "flags" and "misc" +and "misc2" fields. + +Bug: https://bugzilla.kernel.org/show_bug.cgi?id=211537 +Reported-by: Erhard F. +Fixes: a48b9b4edb8b ("drm/radeon/kms/pm: add asic specific callbacks for getting power state (v2)") +Fixes: 79daedc94281 ("drm/radeon/kms: minor pm cleanups") +Signed-off-by: Kees Cook +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/radeon/radeon_atombios.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +index 42301b4e56f5..f9f4efa1738c 100644 +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -2250,10 +2250,10 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) + rdev->pm.default_power_state_index = state_index - 1; + rdev->pm.power_state[state_index - 1].default_clock_mode = + &rdev->pm.power_state[state_index - 1].clock_info[0]; +- rdev->pm.power_state[state_index].flags &= ++ rdev->pm.power_state[state_index - 1].flags &= + ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; +- rdev->pm.power_state[state_index].misc = 0; +- rdev->pm.power_state[state_index].misc2 = 0; ++ rdev->pm.power_state[state_index - 1].misc = 0; ++ rdev->pm.power_state[state_index - 1].misc2 = 0; + } + return state_index; + } +-- +2.30.2 + diff --git a/queue-5.12/ethernet-enic-fix-a-use-after-free-bug-in-enic_hard_.patch b/queue-5.12/ethernet-enic-fix-a-use-after-free-bug-in-enic_hard_.patch new file mode 100644 index 00000000000..bb47f0f9f87 --- /dev/null +++ b/queue-5.12/ethernet-enic-fix-a-use-after-free-bug-in-enic_hard_.patch @@ -0,0 +1,69 @@ +From 1ff016eb454a0eae4eb1f67f85132bee100fb383 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 May 2021 04:58:18 -0700 +Subject: ethernet:enic: Fix a use after free bug in enic_hard_start_xmit + +From: Lv Yunlong + +[ Upstream commit 643001b47adc844ae33510c4bb93c236667008a3 ] + +In enic_hard_start_xmit, it calls enic_queue_wq_skb(). Inside +enic_queue_wq_skb, if some error happens, the skb will be freed +by dev_kfree_skb(skb). But the freed skb is still used in +skb_tx_timestamp(skb). + +My patch makes enic_queue_wq_skb() return error and goto spin_unlock() +incase of error. The solution is provided by Govind. +See https://lkml.org/lkml/2021/4/30/961. + +Fixes: fb7516d42478e ("enic: add sw timestamp support") +Signed-off-by: Lv Yunlong +Acked-by: Govindarajulu Varadarajan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cisco/enic/enic_main.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c +index f04ec53544ae..b1443ff439de 100644 +--- a/drivers/net/ethernet/cisco/enic/enic_main.c ++++ b/drivers/net/ethernet/cisco/enic/enic_main.c +@@ -768,7 +768,7 @@ static inline int enic_queue_wq_skb_encap(struct enic *enic, struct vnic_wq *wq, + return err; + } + +-static inline void enic_queue_wq_skb(struct enic *enic, ++static inline int enic_queue_wq_skb(struct enic *enic, + struct vnic_wq *wq, struct sk_buff *skb) + { + unsigned int mss = skb_shinfo(skb)->gso_size; +@@ -814,6 +814,7 @@ static inline void enic_queue_wq_skb(struct enic *enic, + wq->to_use = buf->next; + dev_kfree_skb(skb); + } ++ return err; + } + + /* netif_tx_lock held, process context with BHs disabled, or BH */ +@@ -857,7 +858,8 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb, + return NETDEV_TX_BUSY; + } + +- enic_queue_wq_skb(enic, wq, skb); ++ if (enic_queue_wq_skb(enic, wq, skb)) ++ goto error; + + if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS) + netif_tx_stop_queue(txq); +@@ -865,6 +867,7 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb, + if (!netdev_xmit_more() || netif_xmit_stopped(txq)) + vnic_wq_doorbell(wq); + ++error: + spin_unlock(&enic->wq_lock[txq_map]); + + return NETDEV_TX_OK; +-- +2.30.2 + diff --git a/queue-5.12/ethtool-fix-missing-nlm_f_multi-flag-when-dumping.patch b/queue-5.12/ethtool-fix-missing-nlm_f_multi-flag-when-dumping.patch new file mode 100644 index 00000000000..b04208e7bd5 --- /dev/null +++ b/queue-5.12/ethtool-fix-missing-nlm_f_multi-flag-when-dumping.patch @@ -0,0 +1,39 @@ +From 8e9f2e6c5fe5982f91f2cdc7aadf169354042ed6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 May 2021 00:47:14 +0200 +Subject: ethtool: fix missing NLM_F_MULTI flag when dumping + +From: Fernando Fernandez Mancera + +[ Upstream commit cf754ae331be7cc192b951756a1dd031e9ed978a ] + +When dumping the ethtool information from all the interfaces, the +netlink reply should contain the NLM_F_MULTI flag. This flag allows +userspace tools to identify that multiple messages are expected. + +Link: https://bugzilla.redhat.com/1953847 +Fixes: 365f9ae4ee36 ("ethtool: fix genlmsg_put() failure handling in ethnl_default_dumpit()") +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ethtool/netlink.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c +index 50d3c8896f91..25a55086d2b6 100644 +--- a/net/ethtool/netlink.c ++++ b/net/ethtool/netlink.c +@@ -384,7 +384,8 @@ static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev, + int ret; + + ehdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, +- ðtool_genl_family, 0, ctx->ops->reply_cmd); ++ ðtool_genl_family, NLM_F_MULTI, ++ ctx->ops->reply_cmd); + if (!ehdr) + return -EMSGSIZE; + +-- +2.30.2 + diff --git a/queue-5.12/ethtool-ioctl-fix-out-of-bounds-warning-in-store_lin.patch b/queue-5.12/ethtool-ioctl-fix-out-of-bounds-warning-in-store_lin.patch new file mode 100644 index 00000000000..ee6209a6aed --- /dev/null +++ b/queue-5.12/ethtool-ioctl-fix-out-of-bounds-warning-in-store_lin.patch @@ -0,0 +1,50 @@ +From fef72863f58b72e14f9afddef9ebeaf438cd0784 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Apr 2021 15:15:40 -0500 +Subject: ethtool: ioctl: Fix out-of-bounds warning in + store_link_ksettings_for_user() + +From: Gustavo A. R. Silva + +[ Upstream commit c1d9e34e11281a8ba1a1c54e4db554232a461488 ] + +Fix the following out-of-bounds warning: + +net/ethtool/ioctl.c:492:2: warning: 'memcpy' offset [49, 84] from the object at 'link_usettings' is out of the bounds of referenced subobject 'base' with type 'struct ethtool_link_settings' at offset 0 [-Warray-bounds] + +The problem is that the original code is trying to copy data into a +some struct members adjacent to each other in a single call to +memcpy(). This causes a legitimate compiler warning because memcpy() +overruns the length of &link_usettings.base. Fix this by directly +using &link_usettings and _from_ as destination and source addresses, +instead. + +This helps with the ongoing efforts to globally enable -Warray-bounds +and get us closer to being able to tighten the FORTIFY_SOURCE routines +on memcpy(). + +Link: https://github.com/KSPP/linux/issues/109 +Reported-by: kernel test robot +Signed-off-by: Gustavo A. R. Silva +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 771688e1b0da..2603966da904 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -489,7 +489,7 @@ store_link_ksettings_for_user(void __user *to, + { + struct ethtool_link_usettings link_usettings; + +- memcpy(&link_usettings.base, &from->base, sizeof(link_usettings)); ++ memcpy(&link_usettings, from, sizeof(link_usettings)); + bitmap_to_arr32(link_usettings.link_modes.supported, + from->link_modes.supported, + __ETHTOOL_LINK_MODE_MASK_NBITS); +-- +2.30.2 + diff --git a/queue-5.12/f2fs-fix-a-hungtask-problem-in-atomic-write.patch b/queue-5.12/f2fs-fix-a-hungtask-problem-in-atomic-write.patch new file mode 100644 index 00000000000..5f73fec9652 --- /dev/null +++ b/queue-5.12/f2fs-fix-a-hungtask-problem-in-atomic-write.patch @@ -0,0 +1,114 @@ +From 339ccb7ba5baea0681480d1cc87c2002505a59ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Mar 2021 17:34:14 +0800 +Subject: f2fs: Fix a hungtask problem in atomic write +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Yi Zhuang + +[ Upstream commit be1ee45d51384161681ecf21085a42d316ae25f7 ] + +In the cache writing process, if it is an atomic file, increase the page +count of F2FS_WB_CP_DATA, otherwise increase the page count of +F2FS_WB_DATA. + +When you step into the hook branch due to insufficient memory in +f2fs_write_begin, f2fs_drop_inmem_pages_all will be called to traverse +all atomic inodes and clear the FI_ATOMIC_FILE mark of all atomic files. + +In f2fs_drop_inmem_pages,first acquire the inmem_lock , revoke all the +inmem_pages, and then clear the FI_ATOMIC_FILE mark. Before this mark is +cleared, other threads may hold inmem_lock to add inmem_pages to the inode +that has just been emptied inmem_pages, and increase the page count of +F2FS_WB_CP_DATA. + +When the IO returns, it is found that the FI_ATOMIC_FILE flag is cleared +by f2fs_drop_inmem_pages_all, and f2fs_is_atomic_file returns false,which +causes the page count of F2FS_WB_DATA to be decremented. The page count of +F2FS_WB_CP_DATA cannot be cleared. Finally, hungtask is triggered in +f2fs_wait_on_all_pages because get_pages will never return zero. + +process A: process B: +f2fs_drop_inmem_pages_all +->f2fs_drop_inmem_pages of inode#1 + ->mutex_lock(&fi->inmem_lock) + ->__revoke_inmem_pages of inode#1 f2fs_ioc_commit_atomic_write + ->mutex_unlock(&fi->inmem_lock) ->f2fs_commit_inmem_pages of inode#1 + ->mutex_lock(&fi->inmem_lock) + ->__f2fs_commit_inmem_pages + ->f2fs_do_write_data_page + ->f2fs_outplace_write_data + ->do_write_page + ->f2fs_submit_page_write + ->inc_page_count(sbi, F2FS_WB_CP_DATA ) + ->mutex_unlock(&fi->inmem_lock) + ->spin_lock(&sbi->inode_lock[ATOMIC_FILE]); + ->clear_inode_flag(inode, FI_ATOMIC_FILE) + ->spin_unlock(&sbi->inode_lock[ATOMIC_FILE]) + f2fs_write_end_io + ->dec_page_count(sbi, F2FS_WB_DATA ); + +We can fix the problem by putting the action of clearing the FI_ATOMIC_FILE +mark into the inmem_lock lock. This operation can ensure that no one will +submit the inmem pages before the FI_ATOMIC_FILE mark is cleared, so that +there will be no atomic writes waiting for writeback. + +Fixes: 57864ae5ce3a ("f2fs: limit # of inmemory pages") +Signed-off-by: Yi Zhuang +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/segment.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 4fba82294a73..d83cb1359e53 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -324,23 +324,27 @@ void f2fs_drop_inmem_pages(struct inode *inode) + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_inode_info *fi = F2FS_I(inode); + +- while (!list_empty(&fi->inmem_pages)) { ++ do { + mutex_lock(&fi->inmem_lock); ++ if (list_empty(&fi->inmem_pages)) { ++ fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0; ++ ++ spin_lock(&sbi->inode_lock[ATOMIC_FILE]); ++ if (!list_empty(&fi->inmem_ilist)) ++ list_del_init(&fi->inmem_ilist); ++ if (f2fs_is_atomic_file(inode)) { ++ clear_inode_flag(inode, FI_ATOMIC_FILE); ++ sbi->atomic_files--; ++ } ++ spin_unlock(&sbi->inode_lock[ATOMIC_FILE]); ++ ++ mutex_unlock(&fi->inmem_lock); ++ break; ++ } + __revoke_inmem_pages(inode, &fi->inmem_pages, + true, false, true); + mutex_unlock(&fi->inmem_lock); +- } +- +- fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0; +- +- spin_lock(&sbi->inode_lock[ATOMIC_FILE]); +- if (!list_empty(&fi->inmem_ilist)) +- list_del_init(&fi->inmem_ilist); +- if (f2fs_is_atomic_file(inode)) { +- clear_inode_flag(inode, FI_ATOMIC_FILE); +- sbi->atomic_files--; +- } +- spin_unlock(&sbi->inode_lock[ATOMIC_FILE]); ++ } while (1); + } + + void f2fs_drop_inmem_page(struct inode *inode, struct page *page) +-- +2.30.2 + diff --git a/queue-5.12/f2fs-fix-a-redundant-call-to-f2fs_balance_fs-if-an-e.patch b/queue-5.12/f2fs-fix-a-redundant-call-to-f2fs_balance_fs-if-an-e.patch new file mode 100644 index 00000000000..1e8e68fee3f --- /dev/null +++ b/queue-5.12/f2fs-fix-a-redundant-call-to-f2fs_balance_fs-if-an-e.patch @@ -0,0 +1,45 @@ +From 66cd1a41951b52c468f0ef4038b1f2a6d21cfd25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Mar 2021 09:21:18 +0000 +Subject: f2fs: fix a redundant call to f2fs_balance_fs if an error occurs + +From: Colin Ian King + +[ Upstream commit 28e18ee636ba28532dbe425540af06245a0bbecb ] + +The uninitialized variable dn.node_changed does not get set when a +call to f2fs_get_node_page fails. This uninitialized value gets used +in the call to f2fs_balance_fs() that may or not may not balances +dirty node and dentry pages depending on the uninitialized state of +the variable. Fix this by only calling f2fs_balance_fs if err is +not set. + +Thanks to Jaegeuk Kim for suggesting an appropriate fix. + +Addresses-Coverity: ("Uninitialized scalar variable") +Fixes: 2a3407607028 ("f2fs: call f2fs_balance_fs only when node was changed") +Signed-off-by: Colin Ian King +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/inline.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c +index 993caefcd2bb..92652ca7a7c8 100644 +--- a/fs/f2fs/inline.c ++++ b/fs/f2fs/inline.c +@@ -219,7 +219,8 @@ out: + + f2fs_put_page(page, 1); + +- f2fs_balance_fs(sbi, dn.node_changed); ++ if (!err) ++ f2fs_balance_fs(sbi, dn.node_changed); + + return err; + } +-- +2.30.2 + diff --git a/queue-5.12/f2fs-fix-panic-during-f2fs_resize_fs.patch b/queue-5.12/f2fs-fix-panic-during-f2fs_resize_fs.patch new file mode 100644 index 00000000000..53c11f99bdf --- /dev/null +++ b/queue-5.12/f2fs-fix-panic-during-f2fs_resize_fs.patch @@ -0,0 +1,75 @@ +From 9d6022eb74fe019e24dbedc62a66f27b99ce2d65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Feb 2021 17:35:41 +0800 +Subject: f2fs: fix panic during f2fs_resize_fs() + +From: Chao Yu + +[ Upstream commit 3ab0598e6d860ef49d029943ba80f627c15c15d6 ] + +f2fs_resize_fs() hangs in below callstack with testcase: +- mkfs 16GB image & mount image +- dd 8GB fileA +- dd 8GB fileB +- sync +- rm fileA +- sync +- resize filesystem to 8GB + +kernel BUG at segment.c:2484! +Call Trace: + allocate_segment_by_default+0x92/0xf0 [f2fs] + f2fs_allocate_data_block+0x44b/0x7e0 [f2fs] + do_write_page+0x5a/0x110 [f2fs] + f2fs_outplace_write_data+0x55/0x100 [f2fs] + f2fs_do_write_data_page+0x392/0x850 [f2fs] + move_data_page+0x233/0x320 [f2fs] + do_garbage_collect+0x14d9/0x1660 [f2fs] + free_segment_range+0x1f7/0x310 [f2fs] + f2fs_resize_fs+0x118/0x330 [f2fs] + __f2fs_ioctl+0x487/0x3680 [f2fs] + __x64_sys_ioctl+0x8e/0xd0 + do_syscall_64+0x33/0x80 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +The root cause is we forgot to check that whether we have enough space +in resized filesystem to store all valid blocks in before-resizing +filesystem, then allocator will run out-of-space during block migration +in free_segment_range(). + +Fixes: b4b10061ef98 ("f2fs: refactor resize_fs to avoid meta updates in progress") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/gc.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index b3af76340026..86ba8ed0b8a7 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -1977,7 +1977,20 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count) + + /* stop CP to protect MAIN_SEC in free_segment_range */ + f2fs_lock_op(sbi); ++ ++ spin_lock(&sbi->stat_lock); ++ if (shrunk_blocks + valid_user_blocks(sbi) + ++ sbi->current_reserved_blocks + sbi->unusable_block_count + ++ F2FS_OPTION(sbi).root_reserved_blocks > sbi->user_block_count) ++ err = -ENOSPC; ++ spin_unlock(&sbi->stat_lock); ++ ++ if (err) ++ goto out_unlock; ++ + err = free_segment_range(sbi, secs, true); ++ ++out_unlock: + f2fs_unlock_op(sbi); + up_write(&sbi->gc_lock); + if (err) +-- +2.30.2 + diff --git a/queue-5.12/f2fs-fix-to-align-to-section-for-fallocate-on-pinned.patch b/queue-5.12/f2fs-fix-to-align-to-section-for-fallocate-on-pinned.patch new file mode 100644 index 00000000000..fb9dc838eda --- /dev/null +++ b/queue-5.12/f2fs-fix-to-align-to-section-for-fallocate-on-pinned.patch @@ -0,0 +1,163 @@ +From e090fabd281cf3de9f1758d867f25adea88786f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Mar 2021 17:56:01 +0800 +Subject: f2fs: fix to align to section for fallocate() on pinned file + +From: Chao Yu + +[ Upstream commit e1175f02291141bbd924fc578299305fcde35855 ] + +Now, fallocate() on a pinned file only allocates blocks which aligns +to segment rather than section, so GC may try to migrate pinned file's +block, and after several times of failure, pinned file's block could +be migrated to other place, however user won't be aware of such +condition, and then old obsolete block address may be readed/written +incorrectly. + +To avoid such condition, let's try to allocate pinned file's blocks +with section alignment. + +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/f2fs.h | 2 +- + fs/f2fs/file.c | 19 +++++++++---------- + fs/f2fs/segment.c | 34 ++++++++++++++++++++++++++-------- + 3 files changed, 36 insertions(+), 19 deletions(-) + +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index cccdfb1a40ab..45a83f8c9e87 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -3383,7 +3383,7 @@ void f2fs_get_new_segment(struct f2fs_sb_info *sbi, + unsigned int *newseg, bool new_sec, int dir); + void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type, + unsigned int start, unsigned int end); +-void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type); ++void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type); + void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi); + int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range); + bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi, +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index 1863944f4073..bd5a77091d23 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -1646,27 +1646,26 @@ static int expand_inode_data(struct inode *inode, loff_t offset, + return 0; + + if (f2fs_is_pinned_file(inode)) { +- block_t len = (map.m_len >> sbi->log_blocks_per_seg) << +- sbi->log_blocks_per_seg; ++ block_t sec_blks = BLKS_PER_SEC(sbi); ++ block_t sec_len = roundup(map.m_len, sec_blks); + block_t done = 0; + +- if (map.m_len % sbi->blocks_per_seg) +- len += sbi->blocks_per_seg; +- +- map.m_len = sbi->blocks_per_seg; ++ map.m_len = sec_blks; + next_alloc: + if (has_not_enough_free_secs(sbi, 0, + GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) { + down_write(&sbi->gc_lock); + err = f2fs_gc(sbi, true, false, false, NULL_SEGNO); +- if (err && err != -ENODATA && err != -EAGAIN) ++ if (err && err != -ENODATA && err != -EAGAIN) { ++ map.m_len = done; + goto out_err; ++ } + } + + down_write(&sbi->pin_sem); + + f2fs_lock_op(sbi); +- f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA_PINNED); ++ f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED); + f2fs_unlock_op(sbi); + + map.m_seg_type = CURSEG_COLD_DATA_PINNED; +@@ -1675,9 +1674,9 @@ next_alloc: + up_write(&sbi->pin_sem); + + done += map.m_len; +- len -= map.m_len; ++ sec_len -= map.m_len; + map.m_lblk += map.m_len; +- if (!err && len) ++ if (!err && sec_len) + goto next_alloc; + + map.m_len = done; +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index dcba4ac3dd2b..91708460f584 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -2893,7 +2893,8 @@ unlock: + up_read(&SM_I(sbi)->curseg_lock); + } + +-static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type) ++static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type, ++ bool new_sec) + { + struct curseg_info *curseg = CURSEG_I(sbi, type); + unsigned int old_segno; +@@ -2901,10 +2902,22 @@ static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type) + if (!curseg->inited) + goto alloc; + +- if (!curseg->next_blkoff && +- !get_valid_blocks(sbi, curseg->segno, false) && +- !get_ckpt_valid_blocks(sbi, curseg->segno)) +- return; ++ if (curseg->next_blkoff || ++ get_valid_blocks(sbi, curseg->segno, new_sec)) ++ goto alloc; ++ ++ if (new_sec) { ++ unsigned int segno = START_SEGNO(curseg->segno); ++ int i; ++ ++ for (i = 0; i < sbi->segs_per_sec; i++, segno++) { ++ if (get_ckpt_valid_blocks(sbi, segno)) ++ goto alloc; ++ } ++ } else { ++ if (!get_ckpt_valid_blocks(sbi, curseg->segno)) ++ return; ++ } + + alloc: + old_segno = curseg->segno; +@@ -2912,10 +2925,15 @@ alloc: + locate_dirty_segment(sbi, old_segno); + } + +-void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type) ++static void __allocate_new_section(struct f2fs_sb_info *sbi, int type) ++{ ++ __allocate_new_segment(sbi, type, true); ++} ++ ++void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type) + { + down_write(&SIT_I(sbi)->sentry_lock); +- __allocate_new_segment(sbi, type); ++ __allocate_new_section(sbi, type); + up_write(&SIT_I(sbi)->sentry_lock); + } + +@@ -2925,7 +2943,7 @@ void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi) + + down_write(&SIT_I(sbi)->sentry_lock); + for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) +- __allocate_new_segment(sbi, i); ++ __allocate_new_segment(sbi, i, false); + up_write(&SIT_I(sbi)->sentry_lock); + } + +-- +2.30.2 + diff --git a/queue-5.12/f2fs-fix-to-allow-migrating-fully-valid-segment.patch b/queue-5.12/f2fs-fix-to-allow-migrating-fully-valid-segment.patch new file mode 100644 index 00000000000..658fa54de53 --- /dev/null +++ b/queue-5.12/f2fs-fix-to-allow-migrating-fully-valid-segment.patch @@ -0,0 +1,193 @@ +From b32a8ff4416edaedc7cf08bc1ded76dd698d93e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Feb 2021 17:35:40 +0800 +Subject: f2fs: fix to allow migrating fully valid segment + +From: Chao Yu + +[ Upstream commit 7dede88659df38f96128ab3922c50dde2d29c574 ] + +F2FS_IOC_FLUSH_DEVICE/F2FS_IOC_RESIZE_FS needs to migrate all blocks of +target segment to other place, no matter the segment has partially or fully +valid blocks. + +However, after commit 803e74be04b3 ("f2fs: stop GC when the victim becomes +fully valid"), we may skip migration due to target segment is fully valid, +result in failing the ioctl interface, fix this. + +Fixes: 803e74be04b3 ("f2fs: stop GC when the victim becomes fully valid") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/f2fs.h | 2 +- + fs/f2fs/file.c | 9 +++++---- + fs/f2fs/gc.c | 21 ++++++++++++--------- + fs/f2fs/segment.c | 2 +- + fs/f2fs/super.c | 2 +- + 5 files changed, 20 insertions(+), 16 deletions(-) + +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index e2d302ae3a46..cccdfb1a40ab 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -3547,7 +3547,7 @@ void f2fs_destroy_post_read_wq(struct f2fs_sb_info *sbi); + int f2fs_start_gc_thread(struct f2fs_sb_info *sbi); + void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi); + block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode); +-int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background, ++int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background, bool force, + unsigned int segno); + void f2fs_build_gc_manager(struct f2fs_sb_info *sbi); + int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count); +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index d26ff2ae3f5e..1863944f4073 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -1658,7 +1658,7 @@ next_alloc: + if (has_not_enough_free_secs(sbi, 0, + GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) { + down_write(&sbi->gc_lock); +- err = f2fs_gc(sbi, true, false, NULL_SEGNO); ++ err = f2fs_gc(sbi, true, false, false, NULL_SEGNO); + if (err && err != -ENODATA && err != -EAGAIN) + goto out_err; + } +@@ -2489,7 +2489,7 @@ static int f2fs_ioc_gc(struct file *filp, unsigned long arg) + down_write(&sbi->gc_lock); + } + +- ret = f2fs_gc(sbi, sync, true, NULL_SEGNO); ++ ret = f2fs_gc(sbi, sync, true, false, NULL_SEGNO); + out: + mnt_drop_write_file(filp); + return ret; +@@ -2525,7 +2525,8 @@ do_more: + down_write(&sbi->gc_lock); + } + +- ret = f2fs_gc(sbi, range->sync, true, GET_SEGNO(sbi, range->start)); ++ ret = f2fs_gc(sbi, range->sync, true, false, ++ GET_SEGNO(sbi, range->start)); + if (ret) { + if (ret == -EBUSY) + ret = -EAGAIN; +@@ -2978,7 +2979,7 @@ static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg) + sm->last_victim[GC_CB] = end_segno + 1; + sm->last_victim[GC_GREEDY] = end_segno + 1; + sm->last_victim[ALLOC_NEXT] = end_segno + 1; +- ret = f2fs_gc(sbi, true, true, start_segno); ++ ret = f2fs_gc(sbi, true, true, true, start_segno); + if (ret == -EAGAIN) + ret = 0; + else if (ret < 0) +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index 39330ad3c44e..b3af76340026 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -112,7 +112,7 @@ do_gc: + sync_mode = F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_SYNC; + + /* if return value is not zero, no victim was selected */ +- if (f2fs_gc(sbi, sync_mode, true, NULL_SEGNO)) ++ if (f2fs_gc(sbi, sync_mode, true, false, NULL_SEGNO)) + wait_ms = gc_th->no_gc_sleep_time; + + trace_f2fs_background_gc(sbi->sb, wait_ms, +@@ -1354,7 +1354,8 @@ out: + * the victim data block is ignored. + */ + static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, +- struct gc_inode_list *gc_list, unsigned int segno, int gc_type) ++ struct gc_inode_list *gc_list, unsigned int segno, int gc_type, ++ bool force_migrate) + { + struct super_block *sb = sbi->sb; + struct f2fs_summary *entry; +@@ -1383,8 +1384,8 @@ next_step: + * race condition along with SSR block allocation. + */ + if ((gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) || +- get_valid_blocks(sbi, segno, true) == +- BLKS_PER_SEC(sbi)) ++ (!force_migrate && get_valid_blocks(sbi, segno, true) == ++ BLKS_PER_SEC(sbi))) + return submitted; + + if (check_valid_map(sbi, segno, off) == 0) +@@ -1519,7 +1520,8 @@ static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim, + + static int do_garbage_collect(struct f2fs_sb_info *sbi, + unsigned int start_segno, +- struct gc_inode_list *gc_list, int gc_type) ++ struct gc_inode_list *gc_list, int gc_type, ++ bool force_migrate) + { + struct page *sum_page; + struct f2fs_summary_block *sum; +@@ -1606,7 +1608,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, + gc_type); + else + submitted += gc_data_segment(sbi, sum->entries, gc_list, +- segno, gc_type); ++ segno, gc_type, ++ force_migrate); + + stat_inc_seg_count(sbi, type, gc_type); + migrated++; +@@ -1634,7 +1637,7 @@ skip: + } + + int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, +- bool background, unsigned int segno) ++ bool background, bool force, unsigned int segno) + { + int gc_type = sync ? FG_GC : BG_GC; + int sec_freed = 0, seg_freed = 0, total_freed = 0; +@@ -1696,7 +1699,7 @@ gc_more: + if (ret) + goto stop; + +- seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type); ++ seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type, force); + if (gc_type == FG_GC && + seg_freed == f2fs_usable_segs_in_sec(sbi, segno)) + sec_freed++; +@@ -1835,7 +1838,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi, + .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS), + }; + +- do_garbage_collect(sbi, segno, &gc_list, FG_GC); ++ do_garbage_collect(sbi, segno, &gc_list, FG_GC, true); + put_gc_inode(&gc_list); + + if (!gc_only && get_valid_blocks(sbi, segno, true)) { +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index c2866561263e..dcba4ac3dd2b 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -504,7 +504,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need) + */ + if (has_not_enough_free_secs(sbi, 0, 0)) { + down_write(&sbi->gc_lock); +- f2fs_gc(sbi, false, false, NULL_SEGNO); ++ f2fs_gc(sbi, false, false, false, NULL_SEGNO); + } + } + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 82592b19b4e0..1d010a3a144f 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -1865,7 +1865,7 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi) + + while (!f2fs_time_over(sbi, DISABLE_TIME)) { + down_write(&sbi->gc_lock); +- err = f2fs_gc(sbi, true, false, NULL_SEGNO); ++ err = f2fs_gc(sbi, true, false, false, NULL_SEGNO); + if (err == -ENODATA) { + err = 0; + break; +-- +2.30.2 + diff --git a/queue-5.12/f2fs-fix-to-avoid-accessing-invalid-fio-in-f2fs_allo.patch b/queue-5.12/f2fs-fix-to-avoid-accessing-invalid-fio-in-f2fs_allo.patch new file mode 100644 index 00000000000..23ae2b4d97b --- /dev/null +++ b/queue-5.12/f2fs-fix-to-avoid-accessing-invalid-fio-in-f2fs_allo.patch @@ -0,0 +1,44 @@ +From 3c8bcc3af43c72986187c6ee39148eee850345ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Apr 2021 17:22:23 +0800 +Subject: f2fs: fix to avoid accessing invalid fio in + f2fs_allocate_data_block() + +From: Chao Yu + +[ Upstream commit 25ae837e61dee712b4b1df36602ebfe724b2a0b6 ] + +Callers may pass fio parameter with NULL value to f2fs_allocate_data_block(), +so we should make sure accessing fio's field after fio's validation check. + +Fixes: f608c38c59c6 ("f2fs: clean up parameter of f2fs_allocate_data_block()") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/segment.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index d83cb1359e53..77456d228f2a 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -3397,12 +3397,12 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, + f2fs_inode_chksum_set(sbi, page); + } + +- if (F2FS_IO_ALIGNED(sbi)) +- fio->retry = false; +- + if (fio) { + struct f2fs_bio_info *io; + ++ if (F2FS_IO_ALIGNED(sbi)) ++ fio->retry = false; ++ + INIT_LIST_HEAD(&fio->list); + fio->in_list = true; + io = sbi->write_io[fio->type] + fio->temp; +-- +2.30.2 + diff --git a/queue-5.12/f2fs-fix-to-avoid-touching-checkpointed-data-in-get_.patch b/queue-5.12/f2fs-fix-to-avoid-touching-checkpointed-data-in-get_.patch new file mode 100644 index 00000000000..bd4a328bfd3 --- /dev/null +++ b/queue-5.12/f2fs-fix-to-avoid-touching-checkpointed-data-in-get_.patch @@ -0,0 +1,200 @@ +From 353099f0b08fd9978802f1d240f3e901d9adcd6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Mar 2021 11:18:28 +0800 +Subject: f2fs: fix to avoid touching checkpointed data in get_victim() + +From: Chao Yu + +[ Upstream commit 61461fc921b756ae16e64243f72af2bfc2e620db ] + +In CP disabling mode, there are two issues when using LFS or SSR | AT_SSR +mode to select victim: + +1. LFS is set to find source section during GC, the victim should have +no checkpointed data, since after GC, section could not be set free for +reuse. + +Previously, we only check valid chpt blocks in current segment rather +than section, fix it. + +2. SSR | AT_SSR are set to find target segment for writes which can be +fully filled by checkpointed and newly written blocks, we should never +select such segment, otherwise it can cause panic or data corruption +during allocation, potential case is described as below: + + a) target segment has 'n' (n < 512) ckpt valid blocks + b) GC migrates 'n' valid blocks to other segment (segment is still + in dirty list) + c) GC migrates '512 - n' blocks to target segment (segment has 'n' + cp_vblocks and '512 - n' vblocks) + d) If GC selects target segment via {AT,}SSR allocator, however there + is no free space in targe segment. + +Fixes: 4354994f097d ("f2fs: checkpoint disabling") +Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/f2fs.h | 1 + + fs/f2fs/gc.c | 28 ++++++++++++++++++++-------- + fs/f2fs/segment.c | 36 +++++++++++++++++++++--------------- + fs/f2fs/segment.h | 14 +++++++++++++- + 4 files changed, 55 insertions(+), 24 deletions(-) + +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index 45a83f8c9e87..eaf6f62206de 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi); + int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable); + void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi); + int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra); ++bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno); + void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi); + void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi); + void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi); +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index 86ba8ed0b8a7..a8567cb47621 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi, + if (p->gc_mode == GC_AT && + get_valid_blocks(sbi, segno, true) == 0) + return; +- +- if (p->alloc_mode == AT_SSR && +- get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0) +- return; + } + + for (i = 0; i < sbi->segs_per_sec; i++) +@@ -728,11 +724,27 @@ retry: + + if (sec_usage_check(sbi, secno)) + goto next; ++ + /* Don't touch checkpointed data */ +- if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) && +- get_ckpt_valid_blocks(sbi, segno) && +- p.alloc_mode == LFS)) +- goto next; ++ if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { ++ if (p.alloc_mode == LFS) { ++ /* ++ * LFS is set to find source section during GC. ++ * The victim should have no checkpointed data. ++ */ ++ if (get_ckpt_valid_blocks(sbi, segno, true)) ++ goto next; ++ } else { ++ /* ++ * SSR | AT_SSR are set to find target segment ++ * for writes which can be full by checkpointed ++ * and newly written blocks. ++ */ ++ if (!f2fs_segment_has_free_slot(sbi, segno)) ++ goto next; ++ } ++ } ++ + if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap)) + goto next; + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 91708460f584..0fbb0e07ca53 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -861,7 +861,7 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) + mutex_lock(&dirty_i->seglist_lock); + + valid_blocks = get_valid_blocks(sbi, segno, false); +- ckpt_valid_blocks = get_ckpt_valid_blocks(sbi, segno); ++ ckpt_valid_blocks = get_ckpt_valid_blocks(sbi, segno, false); + + if (valid_blocks == 0 && (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) || + ckpt_valid_blocks == usable_blocks)) { +@@ -946,7 +946,7 @@ static unsigned int get_free_segment(struct f2fs_sb_info *sbi) + for_each_set_bit(segno, dirty_i->dirty_segmap[DIRTY], MAIN_SEGS(sbi)) { + if (get_valid_blocks(sbi, segno, false)) + continue; +- if (get_ckpt_valid_blocks(sbi, segno)) ++ if (get_ckpt_valid_blocks(sbi, segno, false)) + continue; + mutex_unlock(&dirty_i->seglist_lock); + return segno; +@@ -2636,6 +2636,23 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi, + seg->next_blkoff++; + } + ++bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno) ++{ ++ struct seg_entry *se = get_seg_entry(sbi, segno); ++ int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long); ++ unsigned long *target_map = SIT_I(sbi)->tmp_map; ++ unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map; ++ unsigned long *cur_map = (unsigned long *)se->cur_valid_map; ++ int i, pos; ++ ++ for (i = 0; i < entries; i++) ++ target_map[i] = ckpt_map[i] | cur_map[i]; ++ ++ pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0); ++ ++ return pos < sbi->blocks_per_seg; ++} ++ + /* + * This function always allocates a used segment(from dirty seglist) by SSR + * manner, so it should recover the existing segment information of valid blocks +@@ -2906,19 +2923,8 @@ static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type, + get_valid_blocks(sbi, curseg->segno, new_sec)) + goto alloc; + +- if (new_sec) { +- unsigned int segno = START_SEGNO(curseg->segno); +- int i; +- +- for (i = 0; i < sbi->segs_per_sec; i++, segno++) { +- if (get_ckpt_valid_blocks(sbi, segno)) +- goto alloc; +- } +- } else { +- if (!get_ckpt_valid_blocks(sbi, curseg->segno)) +- return; +- } +- ++ if (!get_ckpt_valid_blocks(sbi, curseg->segno, new_sec)) ++ return; + alloc: + old_segno = curseg->segno; + SIT_I(sbi)->s_ops->allocate_segment(sbi, type, true); +diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h +index e9a7a637d688..afb175739de5 100644 +--- a/fs/f2fs/segment.h ++++ b/fs/f2fs/segment.h +@@ -361,8 +361,20 @@ static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi, + } + + static inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi, +- unsigned int segno) ++ unsigned int segno, bool use_section) + { ++ if (use_section && __is_large_section(sbi)) { ++ unsigned int start_segno = START_SEGNO(segno); ++ unsigned int blocks = 0; ++ int i; ++ ++ for (i = 0; i < sbi->segs_per_sec; i++, start_segno++) { ++ struct seg_entry *se = get_seg_entry(sbi, start_segno); ++ ++ blocks += se->ckpt_valid_blocks; ++ } ++ return blocks; ++ } + return get_seg_entry(sbi, segno)->ckpt_valid_blocks; + } + +-- +2.30.2 + diff --git a/queue-5.12/f2fs-fix-to-cover-__allocate_new_section-with-curseg.patch b/queue-5.12/f2fs-fix-to-cover-__allocate_new_section-with-curseg.patch new file mode 100644 index 00000000000..d0521eca3d9 --- /dev/null +++ b/queue-5.12/f2fs-fix-to-cover-__allocate_new_section-with-curseg.patch @@ -0,0 +1,50 @@ +From ab8ba52a746234577f031462f76359cd024fc290 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Mar 2021 09:46:22 +0800 +Subject: f2fs: fix to cover __allocate_new_section() with curseg_lock + +From: Chao Yu + +[ Upstream commit 823d13e12b6cbaef2f6e5d63c648643e7bc094dd ] + +In order to avoid race with f2fs_do_replace_block(). + +Fixes: f5a53edcf01e ("f2fs: support aligned pinned file") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/segment.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 0fbb0e07ca53..4fba82294a73 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -2938,19 +2938,23 @@ static void __allocate_new_section(struct f2fs_sb_info *sbi, int type) + + void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type) + { ++ down_read(&SM_I(sbi)->curseg_lock); + down_write(&SIT_I(sbi)->sentry_lock); + __allocate_new_section(sbi, type); + up_write(&SIT_I(sbi)->sentry_lock); ++ up_read(&SM_I(sbi)->curseg_lock); + } + + void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi) + { + int i; + ++ down_read(&SM_I(sbi)->curseg_lock); + down_write(&SIT_I(sbi)->sentry_lock); + for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) + __allocate_new_segment(sbi, i, false); + up_write(&SIT_I(sbi)->sentry_lock); ++ up_read(&SM_I(sbi)->curseg_lock); + } + + static const struct segment_allocation default_salloc_ops = { +-- +2.30.2 + diff --git a/queue-5.12/f2fs-fix-to-restrict-mount-condition-on-readonly-blo.patch b/queue-5.12/f2fs-fix-to-restrict-mount-condition-on-readonly-blo.patch new file mode 100644 index 00000000000..c4c3599b6d3 --- /dev/null +++ b/queue-5.12/f2fs-fix-to-restrict-mount-condition-on-readonly-blo.patch @@ -0,0 +1,52 @@ +From bbf0016bf9bc05a52417aa44485f8299b8efa222 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Mar 2021 11:16:32 +0800 +Subject: f2fs: fix to restrict mount condition on readonly block device + +From: Chao Yu + +[ Upstream commit 23738e74472f9c5f3a05a68724a2ccfba97d283d ] + +When we mount an unclean f2fs image in a readonly block device, let's +make mount() succeed only when there is no recoverable data in that +image, otherwise after mount(), file fsyned won't be recovered as user +expected. + +Fixes: 938a184265d7 ("f2fs: give a warning only for readonly partition") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/super.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 1d010a3a144f..d852d96773a3 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -3929,10 +3929,18 @@ try_onemore: + * previous checkpoint was not done by clean system shutdown. + */ + if (f2fs_hw_is_readonly(sbi)) { +- if (!is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) +- f2fs_err(sbi, "Need to recover fsync data, but write access unavailable"); +- else +- f2fs_info(sbi, "write access unavailable, skipping recovery"); ++ if (!is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) { ++ err = f2fs_recover_fsync_data(sbi, true); ++ if (err > 0) { ++ err = -EROFS; ++ f2fs_err(sbi, "Need to recover fsync data, but " ++ "write access unavailable, please try " ++ "mount w/ disable_roll_forward or norecovery"); ++ } ++ if (err < 0) ++ goto free_meta; ++ } ++ f2fs_info(sbi, "write access unavailable, skipping recovery"); + goto reset_checkpoint; + } + +-- +2.30.2 + diff --git a/queue-5.12/f2fs-fix-to-update-last-i_size-if-fallocate-partiall.patch b/queue-5.12/f2fs-fix-to-update-last-i_size-if-fallocate-partiall.patch new file mode 100644 index 00000000000..05b85145b28 --- /dev/null +++ b/queue-5.12/f2fs-fix-to-update-last-i_size-if-fallocate-partiall.patch @@ -0,0 +1,106 @@ +From 6e98397e577bbc98adc1dabfae7cb977088d30c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Mar 2021 11:24:33 +0800 +Subject: f2fs: fix to update last i_size if fallocate partially succeeds + +From: Chao Yu + +[ Upstream commit 88f2cfc5fa90326edb569b4a81bb38ed4dcd3108 ] + +In the case of expanding pinned file, map.m_lblk and map.m_len +will update in each round of section allocation, so in error +path, last i_size will be calculated with wrong m_lblk and m_len, +fix it. + +Fixes: f5a53edcf01e ("f2fs: support aligned pinned file") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/file.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index bd5a77091d23..dc79694e512c 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -1619,9 +1619,10 @@ static int expand_inode_data(struct inode *inode, loff_t offset, + struct f2fs_map_blocks map = { .m_next_pgofs = NULL, + .m_next_extent = NULL, .m_seg_type = NO_CHECK_TYPE, + .m_may_create = true }; +- pgoff_t pg_end; ++ pgoff_t pg_start, pg_end; + loff_t new_size = i_size_read(inode); + loff_t off_end; ++ block_t expanded = 0; + int err; + + err = inode_newsize_ok(inode, (len + offset)); +@@ -1634,11 +1635,12 @@ static int expand_inode_data(struct inode *inode, loff_t offset, + + f2fs_balance_fs(sbi, true); + ++ pg_start = ((unsigned long long)offset) >> PAGE_SHIFT; + pg_end = ((unsigned long long)offset + len) >> PAGE_SHIFT; + off_end = (offset + len) & (PAGE_SIZE - 1); + +- map.m_lblk = ((unsigned long long)offset) >> PAGE_SHIFT; +- map.m_len = pg_end - map.m_lblk; ++ map.m_lblk = pg_start; ++ map.m_len = pg_end - pg_start; + if (off_end) + map.m_len++; + +@@ -1648,7 +1650,6 @@ static int expand_inode_data(struct inode *inode, loff_t offset, + if (f2fs_is_pinned_file(inode)) { + block_t sec_blks = BLKS_PER_SEC(sbi); + block_t sec_len = roundup(map.m_len, sec_blks); +- block_t done = 0; + + map.m_len = sec_blks; + next_alloc: +@@ -1656,10 +1657,8 @@ next_alloc: + GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) { + down_write(&sbi->gc_lock); + err = f2fs_gc(sbi, true, false, false, NULL_SEGNO); +- if (err && err != -ENODATA && err != -EAGAIN) { +- map.m_len = done; ++ if (err && err != -ENODATA && err != -EAGAIN) + goto out_err; +- } + } + + down_write(&sbi->pin_sem); +@@ -1673,24 +1672,25 @@ next_alloc: + + up_write(&sbi->pin_sem); + +- done += map.m_len; ++ expanded += map.m_len; + sec_len -= map.m_len; + map.m_lblk += map.m_len; + if (!err && sec_len) + goto next_alloc; + +- map.m_len = done; ++ map.m_len = expanded; + } else { + err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_AIO); ++ expanded = map.m_len; + } + out_err: + if (err) { + pgoff_t last_off; + +- if (!map.m_len) ++ if (!expanded) + return err; + +- last_off = map.m_lblk + map.m_len - 1; ++ last_off = pg_start + expanded - 1; + + /* update new size to the failed position */ + new_size = (last_off == pg_end) ? offset + len : +-- +2.30.2 + diff --git a/queue-5.12/flow_dissector-fix-out-of-bounds-warning-in-__skb_fl.patch b/queue-5.12/flow_dissector-fix-out-of-bounds-warning-in-__skb_fl.patch new file mode 100644 index 00000000000..7c79e8d38b2 --- /dev/null +++ b/queue-5.12/flow_dissector-fix-out-of-bounds-warning-in-__skb_fl.patch @@ -0,0 +1,53 @@ +From aa29e93272fa876e54a3954d6deacabb5e892d5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Apr 2021 14:31:51 -0500 +Subject: flow_dissector: Fix out-of-bounds warning in + __skb_flow_bpf_to_target() + +From: Gustavo A. R. Silva + +[ Upstream commit 1e3d976dbb23b3fce544752b434bdc32ce64aabc ] + +Fix the following out-of-bounds warning: + +net/core/flow_dissector.c:835:3: warning: 'memcpy' offset [33, 48] from the object at 'flow_keys' is out of the bounds of referenced subobject 'ipv6_src' with type '__u32[4]' {aka 'unsigned int[4]'} at offset 16 [-Warray-bounds] + +The problem is that the original code is trying to copy data into a +couple of struct members adjacent to each other in a single call to +memcpy(). So, the compiler legitimately complains about it. As these +are just a couple of members, fix this by copying each one of them in +separate calls to memcpy(). + +This helps with the ongoing efforts to globally enable -Warray-bounds +and get us closer to being able to tighten the FORTIFY_SOURCE routines +on memcpy(). + +Link: https://github.com/KSPP/linux/issues/109 +Reported-by: kernel test robot +Signed-off-by: Gustavo A. R. Silva +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/core/flow_dissector.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c +index a96a4f5de0ce..3f36b04d86a0 100644 +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -828,8 +828,10 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys, + key_addrs = skb_flow_dissector_target(flow_dissector, + FLOW_DISSECTOR_KEY_IPV6_ADDRS, + target_container); +- memcpy(&key_addrs->v6addrs, &flow_keys->ipv6_src, +- sizeof(key_addrs->v6addrs)); ++ memcpy(&key_addrs->v6addrs.src, &flow_keys->ipv6_src, ++ sizeof(key_addrs->v6addrs.src)); ++ memcpy(&key_addrs->v6addrs.dst, &flow_keys->ipv6_dst, ++ sizeof(key_addrs->v6addrs.dst)); + key_control->addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; + } + +-- +2.30.2 + diff --git a/queue-5.12/fs-9p-fix-v9fs_file_open-writeback-fid-error-check.patch b/queue-5.12/fs-9p-fix-v9fs_file_open-writeback-fid-error-check.patch new file mode 100644 index 00000000000..4e59d3f9330 --- /dev/null +++ b/queue-5.12/fs-9p-fix-v9fs_file_open-writeback-fid-error-check.patch @@ -0,0 +1,41 @@ +From 7ae0d7fabd28ba6d93a202e4ae0dc3fa84f85da9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Mar 2021 21:06:32 +0800 +Subject: fs: 9p: fix v9fs_file_open writeback fid error check + +From: Yang Yingliang + +[ Upstream commit f8b139e2f24112f4e21f1eb02c7fc7600fea4b8d ] + +IS_ERR() and PTR_ERR() use wrong pointer, it should be +writeback_fid, fix it. + +Link: http://lkml.kernel.org/r/20210330130632.1054357-1-yangyingliang@huawei.com +Fixes: 5bfe97d7382b ("9p: Fix writeback fid incorrectly being attached to dentry") +Reported-by: Hulk Robot +Signed-off-by: Yang Yingliang +[Dominique: adjusted commit summary] +Signed-off-by: Dominique Martinet +Signed-off-by: Sasha Levin +--- + fs/9p/vfs_file.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c +index 649f04f112dc..59c32c9b799f 100644 +--- a/fs/9p/vfs_file.c ++++ b/fs/9p/vfs_file.c +@@ -86,8 +86,8 @@ int v9fs_file_open(struct inode *inode, struct file *file) + * to work. + */ + writeback_fid = v9fs_writeback_fid(file_dentry(file)); +- if (IS_ERR(fid)) { +- err = PTR_ERR(fid); ++ if (IS_ERR(writeback_fid)) { ++ err = PTR_ERR(writeback_fid); + mutex_unlock(&v9inode->v_mutex); + goto out_error; + } +-- +2.30.2 + diff --git a/queue-5.12/fs-dlm-add-check-if-dlm-is-currently-running.patch b/queue-5.12/fs-dlm-add-check-if-dlm-is-currently-running.patch new file mode 100644 index 00000000000..3ef0c2a474a --- /dev/null +++ b/queue-5.12/fs-dlm-add-check-if-dlm-is-currently-running.patch @@ -0,0 +1,112 @@ +From 461150f82badac4bb8b9752cdda8c209218277a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 17:05:13 -0500 +Subject: fs: dlm: add check if dlm is currently running + +From: Alexander Aring + +[ Upstream commit 517461630d1c25ee4dfc1dee80973a64189d6ccf ] + +This patch adds checks for dlm config attributes regarding to protocol +parameters as it makes only sense to change them when dlm is not running. +It also adds a check for valid protocol specifiers and return invalid +argument if they are not supported. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/config.c | 34 ++++++++++++++++++++++++++++++++-- + fs/dlm/lowcomms.c | 2 +- + fs/dlm/lowcomms.h | 3 +++ + 3 files changed, 36 insertions(+), 3 deletions(-) + +diff --git a/fs/dlm/config.c b/fs/dlm/config.c +index 8439610c266a..88d95d96e36c 100644 +--- a/fs/dlm/config.c ++++ b/fs/dlm/config.c +@@ -164,6 +164,36 @@ static ssize_t cluster_##name##_show(struct config_item *item, char *buf) \ + } \ + CONFIGFS_ATTR(cluster_, name); + ++static int dlm_check_protocol_and_dlm_running(unsigned int x) ++{ ++ switch (x) { ++ case 0: ++ /* TCP */ ++ break; ++ case 1: ++ /* SCTP */ ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (dlm_allow_conn) ++ return -EBUSY; ++ ++ return 0; ++} ++ ++static int dlm_check_zero_and_dlm_running(unsigned int x) ++{ ++ if (!x) ++ return -EINVAL; ++ ++ if (dlm_allow_conn) ++ return -EBUSY; ++ ++ return 0; ++} ++ + static int dlm_check_zero(unsigned int x) + { + if (!x) +@@ -180,7 +210,7 @@ static int dlm_check_buffer_size(unsigned int x) + return 0; + } + +-CLUSTER_ATTR(tcp_port, dlm_check_zero); ++CLUSTER_ATTR(tcp_port, dlm_check_zero_and_dlm_running); + CLUSTER_ATTR(buffer_size, dlm_check_buffer_size); + CLUSTER_ATTR(rsbtbl_size, dlm_check_zero); + CLUSTER_ATTR(recover_timer, dlm_check_zero); +@@ -188,7 +218,7 @@ CLUSTER_ATTR(toss_secs, dlm_check_zero); + CLUSTER_ATTR(scan_secs, dlm_check_zero); + CLUSTER_ATTR(log_debug, NULL); + CLUSTER_ATTR(log_info, NULL); +-CLUSTER_ATTR(protocol, NULL); ++CLUSTER_ATTR(protocol, dlm_check_protocol_and_dlm_running); + CLUSTER_ATTR(mark, NULL); + CLUSTER_ATTR(timewarn_cs, dlm_check_zero); + CLUSTER_ATTR(waitwarn_us, NULL); +diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c +index a4fabcced0f2..0f7fa23cccf0 100644 +--- a/fs/dlm/lowcomms.c ++++ b/fs/dlm/lowcomms.c +@@ -135,7 +135,7 @@ static DEFINE_SPINLOCK(dlm_node_addrs_spin); + static struct listen_connection listen_con; + static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT]; + static int dlm_local_count; +-static int dlm_allow_conn; ++int dlm_allow_conn; + + /* Work queues */ + static struct workqueue_struct *recv_workqueue; +diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h +index 790d6703b17e..bcd4dbd1dc98 100644 +--- a/fs/dlm/lowcomms.h ++++ b/fs/dlm/lowcomms.h +@@ -14,6 +14,9 @@ + + #define LOWCOMMS_MAX_TX_BUFFER_LEN 4096 + ++/* switch to check if dlm is running */ ++extern int dlm_allow_conn; ++ + int dlm_lowcomms_start(void); + void dlm_lowcomms_stop(void); + void dlm_lowcomms_exit(void); +-- +2.30.2 + diff --git a/queue-5.12/fs-dlm-add-errno-handling-to-check-callback.patch b/queue-5.12/fs-dlm-add-errno-handling-to-check-callback.patch new file mode 100644 index 00000000000..cf47e8669af --- /dev/null +++ b/queue-5.12/fs-dlm-add-errno-handling-to-check-callback.patch @@ -0,0 +1,74 @@ +From 5a3b172dca4c4448c8115e35d8ca7b3b34de54d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 17:05:12 -0500 +Subject: fs: dlm: add errno handling to check callback + +From: Alexander Aring + +[ Upstream commit 8aa9540b49e0833feba75dbf4f45babadd0ed215 ] + +This allows to return individual errno values for the config attribute +check callback instead of returning invalid argument only. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/config.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +diff --git a/fs/dlm/config.c b/fs/dlm/config.c +index 582bffa09a66..8439610c266a 100644 +--- a/fs/dlm/config.c ++++ b/fs/dlm/config.c +@@ -125,7 +125,7 @@ static ssize_t cluster_cluster_name_store(struct config_item *item, + CONFIGFS_ATTR(cluster_, cluster_name); + + static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, +- int *info_field, bool (*check_cb)(unsigned int x), ++ int *info_field, int (*check_cb)(unsigned int x), + const char *buf, size_t len) + { + unsigned int x; +@@ -137,8 +137,11 @@ static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, + if (rc) + return rc; + +- if (check_cb && check_cb(x)) +- return -EINVAL; ++ if (check_cb) { ++ rc = check_cb(x); ++ if (rc) ++ return rc; ++ } + + *cl_field = x; + *info_field = x; +@@ -161,14 +164,20 @@ static ssize_t cluster_##name##_show(struct config_item *item, char *buf) \ + } \ + CONFIGFS_ATTR(cluster_, name); + +-static bool dlm_check_zero(unsigned int x) ++static int dlm_check_zero(unsigned int x) + { +- return !x; ++ if (!x) ++ return -EINVAL; ++ ++ return 0; + } + +-static bool dlm_check_buffer_size(unsigned int x) ++static int dlm_check_buffer_size(unsigned int x) + { +- return (x < DEFAULT_BUFFER_SIZE); ++ if (x < DEFAULT_BUFFER_SIZE) ++ return -EINVAL; ++ ++ return 0; + } + + CLUSTER_ATTR(tcp_port, dlm_check_zero); +-- +2.30.2 + diff --git a/queue-5.12/fs-dlm-add-shutdown-hook.patch b/queue-5.12/fs-dlm-add-shutdown-hook.patch new file mode 100644 index 00000000000..b5c729c357b --- /dev/null +++ b/queue-5.12/fs-dlm-add-shutdown-hook.patch @@ -0,0 +1,197 @@ +From 12b17ebd3eb6740cec5ec7562e655915dcb5fda6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 17:05:20 -0500 +Subject: fs: dlm: add shutdown hook + +From: Alexander Aring + +[ Upstream commit 9d232469bcd772dbedb9e75a165c681b920524ee ] + +This patch fixes issues which occurs when dlm lowcomms synchronize their +workqueues but dlm application layer already released the lockspace. In +such cases messages like: + +dlm: gfs2: release_lockspace final free +dlm: invalid lockspace 3841231384 from 1 cmd 1 type 11 + +are printed on the kernel log. This patch is solving this issue by +introducing a new "shutdown" hook before calling "stop" hook when the +lockspace is going to be released finally. This should pretend any +dlm messages sitting in the workqueues during or after lockspace +removal. + +It's necessary to call dlm_scand_stop() as I instrumented +dlm_lowcomms_get_buffer() code to report a warning after it's called after +dlm_midcomms_shutdown() functionality, see below: + +WARNING: CPU: 1 PID: 3794 at fs/dlm/midcomms.c:1003 dlm_midcomms_get_buffer+0x167/0x180 +Modules linked in: joydev iTCO_wdt intel_pmc_bxt iTCO_vendor_support drm_ttm_helper ttm pcspkr serio_raw i2c_i801 i2c_smbus drm_kms_helper virtio_scsi lpc_ich virtio_balloon virtio_console xhci_pci xhci_pci_renesas cec qemu_fw_cfg drm [last unloaded: qxl] +CPU: 1 PID: 3794 Comm: dlm_scand Tainted: G W 5.11.0+ #26 +Hardware name: Red Hat KVM/RHEL-AV, BIOS 1.13.0-2.module+el8.3.0+7353+9de0a3cc 04/01/2014 +RIP: 0010:dlm_midcomms_get_buffer+0x167/0x180 +Code: 5d 41 5c 41 5d 41 5e 41 5f c3 0f 0b 45 31 e4 5b 5d 4c 89 e0 41 5c 41 5d 41 5e 41 5f c3 4c 89 e7 45 31 e4 e8 3b f1 ec ff eb 86 <0f> 0b 4c 89 e7 45 31 e4 e8 2c f1 ec ff e9 74 ff ff ff 0f 1f 80 00 +RSP: 0018:ffffa81503f8fe60 EFLAGS: 00010202 +RAX: 0000000000000008 RBX: ffff8f969827f200 RCX: 0000000000000001 +RDX: 0000000000000000 RSI: ffffffffad1e89a0 RDI: ffff8f96a5294160 +RBP: 0000000000000001 R08: 0000000000000000 R09: ffff8f96a250bc60 +R10: 00000000000045d3 R11: 0000000000000000 R12: ffff8f96a250bc60 +R13: ffffa81503f8fec8 R14: 0000000000000070 R15: 0000000000000c40 +FS: 0000000000000000(0000) GS:ffff8f96fbc00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000055aa3351c000 CR3: 000000010bf22000 CR4: 00000000000006e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + dlm_scan_rsbs+0x420/0x670 + ? dlm_uevent+0x20/0x20 + dlm_scand+0xbf/0xe0 + kthread+0x13a/0x150 + ? __kthread_bind_mask+0x60/0x60 + ret_from_fork+0x22/0x30 + +To synchronize all dlm scand messages we stop it right before shutdown +hook. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/lockspace.c | 20 +++++++++++--------- + fs/dlm/lowcomms.c | 42 +++++++++++++++++++++++------------------- + fs/dlm/lowcomms.h | 1 + + 3 files changed, 35 insertions(+), 28 deletions(-) + +diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c +index 561dcad08ad6..c14cf2b7faab 100644 +--- a/fs/dlm/lockspace.c ++++ b/fs/dlm/lockspace.c +@@ -404,12 +404,6 @@ static int threads_start(void) + return error; + } + +-static void threads_stop(void) +-{ +- dlm_scand_stop(); +- dlm_lowcomms_stop(); +-} +- + static int new_lockspace(const char *name, const char *cluster, + uint32_t flags, int lvblen, + const struct dlm_lockspace_ops *ops, void *ops_arg, +@@ -702,8 +696,11 @@ int dlm_new_lockspace(const char *name, const char *cluster, + ls_count++; + if (error > 0) + error = 0; +- if (!ls_count) +- threads_stop(); ++ if (!ls_count) { ++ dlm_scand_stop(); ++ dlm_lowcomms_shutdown(); ++ dlm_lowcomms_stop(); ++ } + out: + mutex_unlock(&ls_lock); + return error; +@@ -788,6 +785,11 @@ static int release_lockspace(struct dlm_ls *ls, int force) + + dlm_recoverd_stop(ls); + ++ if (ls_count == 1) { ++ dlm_scand_stop(); ++ dlm_lowcomms_shutdown(); ++ } ++ + dlm_callback_stop(ls); + + remove_lockspace(ls); +@@ -880,7 +882,7 @@ int dlm_release_lockspace(void *lockspace, int force) + if (!error) + ls_count--; + if (!ls_count) +- threads_stop(); ++ dlm_lowcomms_stop(); + mutex_unlock(&ls_lock); + + return error; +diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c +index 5fe571e44b1a..45c2fdaf34c4 100644 +--- a/fs/dlm/lowcomms.c ++++ b/fs/dlm/lowcomms.c +@@ -1608,6 +1608,29 @@ static int work_start(void) + return 0; + } + ++static void shutdown_conn(struct connection *con) ++{ ++ if (con->shutdown_action) ++ con->shutdown_action(con); ++} ++ ++void dlm_lowcomms_shutdown(void) ++{ ++ /* Set all the flags to prevent any ++ * socket activity. ++ */ ++ dlm_allow_conn = 0; ++ ++ if (recv_workqueue) ++ flush_workqueue(recv_workqueue); ++ if (send_workqueue) ++ flush_workqueue(send_workqueue); ++ ++ dlm_close_sock(&listen_con.sock); ++ ++ foreach_conn(shutdown_conn); ++} ++ + static void _stop_conn(struct connection *con, bool and_other) + { + mutex_lock(&con->sock_mutex); +@@ -1629,12 +1652,6 @@ static void stop_conn(struct connection *con) + _stop_conn(con, true); + } + +-static void shutdown_conn(struct connection *con) +-{ +- if (con->shutdown_action) +- con->shutdown_action(con); +-} +- + static void connection_release(struct rcu_head *rcu) + { + struct connection *con = container_of(rcu, struct connection, rcu); +@@ -1691,19 +1708,6 @@ static void work_flush(void) + + void dlm_lowcomms_stop(void) + { +- /* Set all the flags to prevent any +- socket activity. +- */ +- dlm_allow_conn = 0; +- +- if (recv_workqueue) +- flush_workqueue(recv_workqueue); +- if (send_workqueue) +- flush_workqueue(send_workqueue); +- +- dlm_close_sock(&listen_con.sock); +- +- foreach_conn(shutdown_conn); + work_flush(); + foreach_conn(free_conn); + work_stop(); +diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h +index bcd4dbd1dc98..48bbc4e18761 100644 +--- a/fs/dlm/lowcomms.h ++++ b/fs/dlm/lowcomms.h +@@ -18,6 +18,7 @@ + extern int dlm_allow_conn; + + int dlm_lowcomms_start(void); ++void dlm_lowcomms_shutdown(void); + void dlm_lowcomms_stop(void); + void dlm_lowcomms_exit(void); + int dlm_lowcomms_close(int nodeid); +-- +2.30.2 + diff --git a/queue-5.12/fs-dlm-change-allocation-limits.patch b/queue-5.12/fs-dlm-change-allocation-limits.patch new file mode 100644 index 00000000000..cd6e6236b73 --- /dev/null +++ b/queue-5.12/fs-dlm-change-allocation-limits.patch @@ -0,0 +1,45 @@ +From 8db6e06a1990cd91c6ed492c66893ed2b775070b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 17:05:14 -0500 +Subject: fs: dlm: change allocation limits + +From: Alexander Aring + +[ Upstream commit c45674fbdda138814ca21138475219c96fa5aa1f ] + +While running tcpkill I experienced invalid header length values while +receiving to check that a node doesn't try to send a invalid dlm message +we also check on applications minimum allocation limit. Also use +DEFAULT_BUFFER_SIZE as maximum allocation limit. The define +LOWCOMMS_MAX_TX_BUFFER_LEN is to calculate maximum buffer limits on +application layer, future midcomms layer will subtract their needs from +this define. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/lowcomms.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c +index 0f7fa23cccf0..f827d0b3962a 100644 +--- a/fs/dlm/lowcomms.c ++++ b/fs/dlm/lowcomms.c +@@ -1375,9 +1375,11 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc) + struct writequeue_entry *e; + int offset = 0; + +- if (len > LOWCOMMS_MAX_TX_BUFFER_LEN) { +- BUILD_BUG_ON(PAGE_SIZE < LOWCOMMS_MAX_TX_BUFFER_LEN); ++ if (len > DEFAULT_BUFFER_SIZE || ++ len < sizeof(struct dlm_header)) { ++ BUILD_BUG_ON(PAGE_SIZE < DEFAULT_BUFFER_SIZE); + log_print("failed to allocate a buffer of size %d", len); ++ WARN_ON(1); + return NULL; + } + +-- +2.30.2 + diff --git a/queue-5.12/fs-dlm-check-on-minimum-msglen-size.patch b/queue-5.12/fs-dlm-check-on-minimum-msglen-size.patch new file mode 100644 index 00000000000..eecefe66904 --- /dev/null +++ b/queue-5.12/fs-dlm-check-on-minimum-msglen-size.patch @@ -0,0 +1,42 @@ +From f2d54ea647f4d033dc729ecd437105ea81162934 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 17:05:17 -0500 +Subject: fs: dlm: check on minimum msglen size + +From: Alexander Aring + +[ Upstream commit 710176e8363f269c6ecd73d203973b31ace119d3 ] + +This patch adds an additional check for minimum dlm header size which is +an invalid dlm message and signals a broken stream. A msglen field cannot +be less than the dlm header size because the field is inclusive header +lengths. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/midcomms.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c +index fde3a6afe4be..0bedfa8606a2 100644 +--- a/fs/dlm/midcomms.c ++++ b/fs/dlm/midcomms.c +@@ -49,9 +49,10 @@ int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len) + * cannot deliver this message to upper layers + */ + msglen = get_unaligned_le16(&hd->h_length); +- if (msglen > DEFAULT_BUFFER_SIZE) { +- log_print("received invalid length header: %u, will abort message parsing", +- msglen); ++ if (msglen > DEFAULT_BUFFER_SIZE || ++ msglen < sizeof(struct dlm_header)) { ++ log_print("received invalid length header: %u from node %d, will abort message parsing", ++ msglen, nodeid); + return -EBADMSG; + } + +-- +2.30.2 + diff --git a/queue-5.12/fs-dlm-fix-debugfs-dump.patch b/queue-5.12/fs-dlm-fix-debugfs-dump.patch new file mode 100644 index 00000000000..ef6cbcbd582 --- /dev/null +++ b/queue-5.12/fs-dlm-fix-debugfs-dump.patch @@ -0,0 +1,40 @@ +From ce785497794004b99ac240c2aedba7f51d1aff05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 17:05:08 -0500 +Subject: fs: dlm: fix debugfs dump + +From: Alexander Aring + +[ Upstream commit 92c48950b43f4a767388cf87709d8687151a641f ] + +This patch fixes the following message which randomly pops up during +glocktop call: + +seq_file: buggy .next function table_seq_next did not update position index + +The issue is that seq_read_iter() in fs/seq_file.c also needs an +increment of the index in an non next record case as well which this +patch fixes otherwise seq_read_iter() will print out the above message. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/debug_fs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c +index d6bbccb0ed15..d5bd990bcab8 100644 +--- a/fs/dlm/debug_fs.c ++++ b/fs/dlm/debug_fs.c +@@ -542,6 +542,7 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos) + + if (bucket >= ls->ls_rsbtbl_size) { + kfree(ri); ++ ++*pos; + return NULL; + } + tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep; +-- +2.30.2 + diff --git a/queue-5.12/fs-dlm-fix-mark-setting-deadlock.patch b/queue-5.12/fs-dlm-fix-mark-setting-deadlock.patch new file mode 100644 index 00000000000..d48ac055cf5 --- /dev/null +++ b/queue-5.12/fs-dlm-fix-mark-setting-deadlock.patch @@ -0,0 +1,287 @@ +From c7663374e7a6ce6c0daa0419e87bca0bb029ddbc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 17:05:09 -0500 +Subject: fs: dlm: fix mark setting deadlock + +From: Alexander Aring + +[ Upstream commit e125fbeb538e5e35a00c6c8150a5361bef34814c ] + +This patch fixes an deadlock issue when dlm_lowcomms_close() is called. +When dlm_lowcomms_close() is called the clusters_root.subsys.su_mutex is +held to remove configfs items. At this time we flushing (e.g. +cancel_work_sync()) the workers of send and recv workqueue. Due the fact +that we accessing configfs items (mark values), these workers will lock +clusters_root.subsys.su_mutex as well which are already hold by +dlm_lowcomms_close() and ends in a deadlock situation. + +[67170.703046] ====================================================== +[67170.703965] WARNING: possible circular locking dependency detected +[67170.704758] 5.11.0-rc4+ #22 Tainted: G W +[67170.705433] ------------------------------------------------------ +[67170.706228] dlm_controld/280 is trying to acquire lock: +[67170.706915] ffff9f2f475a6948 ((wq_completion)dlm_recv){+.+.}-{0:0}, at: __flush_work+0x203/0x4c0 +[67170.708026] + but task is already holding lock: +[67170.708758] ffffffffa132f878 (&clusters_root.subsys.su_mutex){+.+.}-{3:3}, at: configfs_rmdir+0x29b/0x310 +[67170.710016] + which lock already depends on the new lock. + +The new behaviour adds the mark value to the node address configuration +which doesn't require to held the clusters_root.subsys.su_mutex by +accessing mark values in a separate datastructure. However the mark +values can be set now only after a node address was set which is the +case when the user is using dlm_controld. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/config.c | 29 ++++++++++------------------ + fs/dlm/config.h | 1 - + fs/dlm/lowcomms.c | 49 ++++++++++++++++++++++++++++++++--------------- + fs/dlm/lowcomms.h | 1 + + 4 files changed, 45 insertions(+), 35 deletions(-) + +diff --git a/fs/dlm/config.c b/fs/dlm/config.c +index 49c5f9407098..582bffa09a66 100644 +--- a/fs/dlm/config.c ++++ b/fs/dlm/config.c +@@ -688,6 +688,7 @@ static ssize_t comm_mark_show(struct config_item *item, char *buf) + static ssize_t comm_mark_store(struct config_item *item, const char *buf, + size_t len) + { ++ struct dlm_comm *comm; + unsigned int mark; + int rc; + +@@ -695,7 +696,15 @@ static ssize_t comm_mark_store(struct config_item *item, const char *buf, + if (rc) + return rc; + +- config_item_to_comm(item)->mark = mark; ++ if (mark == 0) ++ mark = dlm_config.ci_mark; ++ ++ comm = config_item_to_comm(item); ++ rc = dlm_lowcomms_nodes_set_mark(comm->nodeid, mark); ++ if (rc) ++ return rc; ++ ++ comm->mark = mark; + return len; + } + +@@ -870,24 +879,6 @@ int dlm_comm_seq(int nodeid, uint32_t *seq) + return 0; + } + +-void dlm_comm_mark(int nodeid, unsigned int *mark) +-{ +- struct dlm_comm *cm; +- +- cm = get_comm(nodeid); +- if (!cm) { +- *mark = dlm_config.ci_mark; +- return; +- } +- +- if (cm->mark) +- *mark = cm->mark; +- else +- *mark = dlm_config.ci_mark; +- +- put_comm(cm); +-} +- + int dlm_our_nodeid(void) + { + return local_comm ? local_comm->nodeid : 0; +diff --git a/fs/dlm/config.h b/fs/dlm/config.h +index c210250a2581..d2cd4bd20313 100644 +--- a/fs/dlm/config.h ++++ b/fs/dlm/config.h +@@ -48,7 +48,6 @@ void dlm_config_exit(void); + int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, + int *count_out); + int dlm_comm_seq(int nodeid, uint32_t *seq); +-void dlm_comm_mark(int nodeid, unsigned int *mark); + int dlm_our_nodeid(void); + int dlm_our_addr(struct sockaddr_storage *addr, int num); + +diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c +index f7d2c52791f8..a4fabcced0f2 100644 +--- a/fs/dlm/lowcomms.c ++++ b/fs/dlm/lowcomms.c +@@ -116,6 +116,7 @@ struct writequeue_entry { + struct dlm_node_addr { + struct list_head list; + int nodeid; ++ int mark; + int addr_count; + int curr_addr_index; + struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT]; +@@ -303,7 +304,8 @@ static int addr_compare(const struct sockaddr_storage *x, + } + + static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out, +- struct sockaddr *sa_out, bool try_new_addr) ++ struct sockaddr *sa_out, bool try_new_addr, ++ unsigned int *mark) + { + struct sockaddr_storage sas; + struct dlm_node_addr *na; +@@ -331,6 +333,8 @@ static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out, + if (!na->addr_count) + return -ENOENT; + ++ *mark = na->mark; ++ + if (sas_out) + memcpy(sas_out, &sas, sizeof(struct sockaddr_storage)); + +@@ -350,7 +354,8 @@ static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out, + return 0; + } + +-static int addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid) ++static int addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid, ++ unsigned int *mark) + { + struct dlm_node_addr *na; + int rv = -EEXIST; +@@ -364,6 +369,7 @@ static int addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid) + for (addr_i = 0; addr_i < na->addr_count; addr_i++) { + if (addr_compare(na->addr[addr_i], addr)) { + *nodeid = na->nodeid; ++ *mark = na->mark; + rv = 0; + goto unlock; + } +@@ -412,6 +418,7 @@ int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len) + new_node->nodeid = nodeid; + new_node->addr[0] = new_addr; + new_node->addr_count = 1; ++ new_node->mark = dlm_config.ci_mark; + list_add(&new_node->list, &dlm_node_addrs); + spin_unlock(&dlm_node_addrs_spin); + return 0; +@@ -519,6 +526,23 @@ int dlm_lowcomms_connect_node(int nodeid) + return 0; + } + ++int dlm_lowcomms_nodes_set_mark(int nodeid, unsigned int mark) ++{ ++ struct dlm_node_addr *na; ++ ++ spin_lock(&dlm_node_addrs_spin); ++ na = find_node_addr(nodeid); ++ if (!na) { ++ spin_unlock(&dlm_node_addrs_spin); ++ return -ENOENT; ++ } ++ ++ na->mark = mark; ++ spin_unlock(&dlm_node_addrs_spin); ++ ++ return 0; ++} ++ + static void lowcomms_error_report(struct sock *sk) + { + struct connection *con; +@@ -867,7 +891,7 @@ static int accept_from_sock(struct listen_connection *con) + + /* Get the new node's NODEID */ + make_sockaddr(&peeraddr, 0, &len); +- if (addr_to_nodeid(&peeraddr, &nodeid)) { ++ if (addr_to_nodeid(&peeraddr, &nodeid, &mark)) { + unsigned char *b=(unsigned char *)&peeraddr; + log_print("connect from non cluster node"); + print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, +@@ -876,9 +900,6 @@ static int accept_from_sock(struct listen_connection *con) + return -1; + } + +- dlm_comm_mark(nodeid, &mark); +- sock_set_mark(newsock->sk, mark); +- + log_print("got connection from %d", nodeid); + + /* Check to see if we already have a connection to this node. This +@@ -892,6 +913,8 @@ static int accept_from_sock(struct listen_connection *con) + goto accept_err; + } + ++ sock_set_mark(newsock->sk, mark); ++ + mutex_lock(&newcon->sock_mutex); + if (newcon->sock) { + struct connection *othercon = newcon->othercon; +@@ -1016,8 +1039,6 @@ static void sctp_connect_to_sock(struct connection *con) + struct socket *sock; + unsigned int mark; + +- dlm_comm_mark(con->nodeid, &mark); +- + mutex_lock(&con->sock_mutex); + + /* Some odd races can cause double-connects, ignore them */ +@@ -1030,7 +1051,7 @@ static void sctp_connect_to_sock(struct connection *con) + } + + memset(&daddr, 0, sizeof(daddr)); +- result = nodeid_to_addr(con->nodeid, &daddr, NULL, true); ++ result = nodeid_to_addr(con->nodeid, &daddr, NULL, true, &mark); + if (result < 0) { + log_print("no address for nodeid %d", con->nodeid); + goto out; +@@ -1105,13 +1126,11 @@ out: + static void tcp_connect_to_sock(struct connection *con) + { + struct sockaddr_storage saddr, src_addr; ++ unsigned int mark; + int addr_len; + struct socket *sock = NULL; +- unsigned int mark; + int result; + +- dlm_comm_mark(con->nodeid, &mark); +- + mutex_lock(&con->sock_mutex); + if (con->retries++ > MAX_CONNECT_RETRIES) + goto out; +@@ -1126,15 +1145,15 @@ static void tcp_connect_to_sock(struct connection *con) + if (result < 0) + goto out_err; + +- sock_set_mark(sock->sk, mark); +- + memset(&saddr, 0, sizeof(saddr)); +- result = nodeid_to_addr(con->nodeid, &saddr, NULL, false); ++ result = nodeid_to_addr(con->nodeid, &saddr, NULL, false, &mark); + if (result < 0) { + log_print("no address for nodeid %d", con->nodeid); + goto out_err; + } + ++ sock_set_mark(sock->sk, mark); ++ + add_sock(sock, con); + + /* Bind to our cluster-known address connecting to avoid +diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h +index 0918f9376489..790d6703b17e 100644 +--- a/fs/dlm/lowcomms.h ++++ b/fs/dlm/lowcomms.h +@@ -21,6 +21,7 @@ int dlm_lowcomms_close(int nodeid); + void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc); + void dlm_lowcomms_commit_buffer(void *mh); + int dlm_lowcomms_connect_node(int nodeid); ++int dlm_lowcomms_nodes_set_mark(int nodeid, unsigned int mark); + int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len); + + #endif /* __LOWCOMMS_DOT_H__ */ +-- +2.30.2 + diff --git a/queue-5.12/fs-dlm-flush-swork-on-shutdown.patch b/queue-5.12/fs-dlm-flush-swork-on-shutdown.patch new file mode 100644 index 00000000000..1e967348b1d --- /dev/null +++ b/queue-5.12/fs-dlm-flush-swork-on-shutdown.patch @@ -0,0 +1,42 @@ +From 1e51144d99990a9a63fcae72ba15cdeec7b64653 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 17:05:19 -0500 +Subject: fs: dlm: flush swork on shutdown + +From: Alexander Aring + +[ Upstream commit eec054b5a7cfe6d1f1598a323b05771ee99857b5 ] + +This patch fixes the flushing of send work before shutdown. The function +cancel_work_sync() is not the right workqueue functionality to use here +as it would cancel the work if the work queues itself. In cases of +EAGAIN in send() for dlm message we need to be sure that everything is +send out before. The function flush_work() will ensure that every send +work is be done inclusive in EAGAIN cases. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/lowcomms.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c +index f827d0b3962a..5fe571e44b1a 100644 +--- a/fs/dlm/lowcomms.c ++++ b/fs/dlm/lowcomms.c +@@ -709,10 +709,7 @@ static void shutdown_connection(struct connection *con) + { + int ret; + +- if (cancel_work_sync(&con->swork)) { +- log_print("canceled swork for node %d", con->nodeid); +- clear_bit(CF_WRITE_PENDING, &con->flags); +- } ++ flush_work(&con->swork); + + mutex_lock(&con->sock_mutex); + /* nothing to shutdown */ +-- +2.30.2 + diff --git a/queue-5.12/fs-proc-generic.c-fix-incorrect-pde_is_permanent-che.patch b/queue-5.12/fs-proc-generic.c-fix-incorrect-pde_is_permanent-che.patch new file mode 100644 index 00000000000..06e61338d00 --- /dev/null +++ b/queue-5.12/fs-proc-generic.c-fix-incorrect-pde_is_permanent-che.patch @@ -0,0 +1,43 @@ +From 77a1bf5d97c36cd05378a4d3d725f1dc5dfd9420 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 May 2021 18:02:10 -0700 +Subject: fs/proc/generic.c: fix incorrect pde_is_permanent check + +From: Colin Ian King + +[ Upstream commit f4bf74d82915708208bc9d0c9bd3f769f56bfbec ] + +Currently the pde_is_permanent() check is being run on root multiple times +rather than on the next proc directory entry. This looks like a +copy-paste error. Fix this by replacing root with next. + +Addresses-Coverity: ("Copy-paste error") +Link: https://lkml.kernel.org/r/20210318122633.14222-1-colin.king@canonical.com +Fixes: d919b33dafb3 ("proc: faster open/read/close with "permanent" files") +Signed-off-by: Colin Ian King +Acked-by: Christian Brauner +Reviewed-by: Alexey Dobriyan +Cc: Greg Kroah-Hartman +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + fs/proc/generic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/proc/generic.c b/fs/proc/generic.c +index bc86aa87cc41..5600da30e289 100644 +--- a/fs/proc/generic.c ++++ b/fs/proc/generic.c +@@ -756,7 +756,7 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) + while (1) { + next = pde_subdir_first(de); + if (next) { +- if (unlikely(pde_is_permanent(root))) { ++ if (unlikely(pde_is_permanent(next))) { + write_unlock(&proc_subdir_lock); + WARN(1, "removing permanent /proc entry '%s/%s'", + next->parent->name, next->name); +-- +2.30.2 + diff --git a/queue-5.12/fuse-invalidate-attrs-when-page-writeback-completes.patch b/queue-5.12/fuse-invalidate-attrs-when-page-writeback-completes.patch new file mode 100644 index 00000000000..63c624c9ccd --- /dev/null +++ b/queue-5.12/fuse-invalidate-attrs-when-page-writeback-completes.patch @@ -0,0 +1,80 @@ +From d2e69e6e74dd1f0bc64c3b842f99727362833b01 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Apr 2021 10:07:06 -0400 +Subject: fuse: invalidate attrs when page writeback completes + +From: Vivek Goyal + +[ Upstream commit 3466958beb31a8e9d3a1441a34228ed088b84f3e ] + +In fuse when a direct/write-through write happens we invalidate attrs +because that might have updated mtime/ctime on server and cached +mtime/ctime will be stale. + +What about page writeback path. Looks like we don't invalidate attrs +there. To be consistent, invalidate attrs in writeback path as well. Only +exception is when writeback_cache is enabled. In that case we strust local +mtime/ctime and there is no need to invalidate attrs. + +Recently users started experiencing failure of xfstests generic/080, +geneirc/215 and generic/614 on virtiofs. This happened only newer "stat" +utility and not older one. This patch fixes the issue. + +So what's the root cause of the issue. Here is detailed explanation. + +generic/080 test does mmap write to a file, closes the file and then checks +if mtime has been updated or not. When file is closed, it leads to +flushing of dirty pages (and that should update mtime/ctime on server). +But we did not explicitly invalidate attrs after writeback finished. Still +generic/080 passed so far and reason being that we invalidated atime in +fuse_readpages_end(). This is called in fuse_readahead() path and always +seems to trigger before mmaped write. + +So after mmaped write when lstat() is called, it sees that atleast one of +the fields being asked for is invalid (atime) and that results in +generating GETATTR to server and mtime/ctime also get updated and test +passes. + +But newer /usr/bin/stat seems to have moved to using statx() syscall now +(instead of using lstat()). And statx() allows it to query only ctime or +mtime (and not rest of the basic stat fields). That means when querying +for mtime, fuse_update_get_attr() sees that mtime is not invalid (only +atime is invalid). So it does not generate a new GETATTR and fill stat +with cached mtime/ctime. And that means updated mtime is not seen by +xfstest and tests start failing. + +Invalidating attrs after writeback completion should solve this problem in +a generic manner. + +Signed-off-by: Vivek Goyal +Signed-off-by: Miklos Szeredi +Signed-off-by: Sasha Levin +--- + fs/fuse/file.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index eff4abaa87da..6e6d1e599869 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -1776,8 +1776,17 @@ static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args, + container_of(args, typeof(*wpa), ia.ap.args); + struct inode *inode = wpa->inode; + struct fuse_inode *fi = get_fuse_inode(inode); ++ struct fuse_conn *fc = get_fuse_conn(inode); + + mapping_set_error(inode->i_mapping, error); ++ /* ++ * A writeback finished and this might have updated mtime/ctime on ++ * server making local mtime/ctime stale. Hence invalidate attrs. ++ * Do this only if writeback_cache is not enabled. If writeback_cache ++ * is enabled, we trust local ctime/mtime. ++ */ ++ if (!fc->writeback_cache) ++ fuse_invalidate_attr(inode); + spin_lock(&fi->lock); + rb_erase(&wpa->writepages_entry, &fi->writepages); + while (wpa->next) { +-- +2.30.2 + diff --git a/queue-5.12/i2c-add-i2c_aq_no_rep_start-adapter-quirk.patch b/queue-5.12/i2c-add-i2c_aq_no_rep_start-adapter-quirk.patch new file mode 100644 index 00000000000..da240023927 --- /dev/null +++ b/queue-5.12/i2c-add-i2c_aq_no_rep_start-adapter-quirk.patch @@ -0,0 +1,39 @@ +From 2ead8697fca8a8049096fea366c5a993b7bc9a48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Mar 2021 19:19:20 +0000 +Subject: i2c: Add I2C_AQ_NO_REP_START adapter quirk +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bence Csókás + +[ Upstream commit aca01415e076aa96cca0f801f4420ee5c10c660d ] + +This quirk signifies that the adapter cannot do a repeated +START, it always issues a STOP condition after transfers. + +Suggested-by: Wolfram Sang +Signed-off-by: Bence Csókás +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + include/linux/i2c.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/linux/i2c.h b/include/linux/i2c.h +index 56622658b215..a670ae129f4b 100644 +--- a/include/linux/i2c.h ++++ b/include/linux/i2c.h +@@ -687,6 +687,8 @@ struct i2c_adapter_quirks { + #define I2C_AQ_NO_ZERO_LEN_READ BIT(5) + #define I2C_AQ_NO_ZERO_LEN_WRITE BIT(6) + #define I2C_AQ_NO_ZERO_LEN (I2C_AQ_NO_ZERO_LEN_READ | I2C_AQ_NO_ZERO_LEN_WRITE) ++/* adapter cannot do repeated START */ ++#define I2C_AQ_NO_REP_START BIT(7) + + /* + * i2c_adapter is the structure used to identify a physical i2c bus along +-- +2.30.2 + diff --git a/queue-5.12/i2c-bail-out-early-when-rdwr-parameters-are-wrong.patch b/queue-5.12/i2c-bail-out-early-when-rdwr-parameters-are-wrong.patch new file mode 100644 index 00000000000..fb84f6734a8 --- /dev/null +++ b/queue-5.12/i2c-bail-out-early-when-rdwr-parameters-are-wrong.patch @@ -0,0 +1,46 @@ +From 9943a3cff7543c3cd279311c1c950a10bafbdc14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Mar 2021 12:57:34 +0100 +Subject: i2c: bail out early when RDWR parameters are wrong + +From: Wolfram Sang + +[ Upstream commit 71581562ee36032d2d574a9b23ad4af6d6a64cf7 ] + +The buggy parameters currently get caught later, but emit a noisy WARN. +Userspace should not be able to trigger this, so add similar checks much +earlier. Also avoids some unneeded code paths, of course. Apply kernel +coding stlye to a comment while here. + +Reported-by: syzbot+ffb0b3ffa6cfbc7d7b3f@syzkaller.appspotmail.com +Tested-by: syzbot+ffb0b3ffa6cfbc7d7b3f@syzkaller.appspotmail.com +Signed-off-by: Wolfram Sang +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/i2c-dev.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c +index 6ceb11cc4be1..6ef38a8ee95c 100644 +--- a/drivers/i2c/i2c-dev.c ++++ b/drivers/i2c/i2c-dev.c +@@ -440,8 +440,13 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + sizeof(rdwr_arg))) + return -EFAULT; + +- /* Put an arbitrary limit on the number of messages that can +- * be sent at once */ ++ if (!rdwr_arg.msgs || rdwr_arg.nmsgs == 0) ++ return -EINVAL; ++ ++ /* ++ * Put an arbitrary limit on the number of messages that can ++ * be sent at once ++ */ + if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) + return -EINVAL; + +-- +2.30.2 + diff --git a/queue-5.12/i2c-i801-add-support-for-intel-alder-lake-pch-m.patch b/queue-5.12/i2c-i801-add-support-for-intel-alder-lake-pch-m.patch new file mode 100644 index 00000000000..fc140cea877 --- /dev/null +++ b/queue-5.12/i2c-i801-add-support-for-intel-alder-lake-pch-m.patch @@ -0,0 +1,57 @@ +From c9ee6b06ceca365a070b03fcab5c30a0c09c39aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Apr 2021 16:41:12 +0300 +Subject: i2c: i801: Add support for Intel Alder Lake PCH-M + +From: Jarkko Nikula + +[ Upstream commit 8f51c1763ae98bb63fc04627ceae383aa0e8ff7b ] + +Add PCI ID of SMBus controller on Intel Alder Lake PCH-M. + +Signed-off-by: Jarkko Nikula +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-i801.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c +index 4acee6f9e5a3..99d446763530 100644 +--- a/drivers/i2c/busses/i2c-i801.c ++++ b/drivers/i2c/busses/i2c-i801.c +@@ -73,6 +73,7 @@ + * Comet Lake-V (PCH) 0xa3a3 32 hard yes yes yes + * Alder Lake-S (PCH) 0x7aa3 32 hard yes yes yes + * Alder Lake-P (PCH) 0x51a3 32 hard yes yes yes ++ * Alder Lake-M (PCH) 0x54a3 32 hard yes yes yes + * + * Features supported by this driver: + * Software PEC no +@@ -230,6 +231,7 @@ + #define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23 + #define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3 + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS 0x51a3 ++#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3 + #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4 + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3 + #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 +@@ -1087,6 +1089,7 @@ static const struct pci_device_id i801_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS) }, + { 0, } + }; + +@@ -1771,6 +1774,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) + case PCI_DEVICE_ID_INTEL_EBG_SMBUS: + case PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS: + case PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS: ++ case PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS: + priv->features |= FEATURE_BLOCK_PROC; + priv->features |= FEATURE_I2C_BLOCK_READ; + priv->features |= FEATURE_IRQ; +-- +2.30.2 + diff --git a/queue-5.12/i2c-imx-fix-pm-reference-leak-in-i2c_imx_reg_slave.patch b/queue-5.12/i2c-imx-fix-pm-reference-leak-in-i2c_imx_reg_slave.patch new file mode 100644 index 00000000000..9c43a9bd4cd --- /dev/null +++ b/queue-5.12/i2c-imx-fix-pm-reference-leak-in-i2c_imx_reg_slave.patch @@ -0,0 +1,39 @@ +From 067cd7b0e7d60417106f56a2242bbae2455f3f3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Apr 2021 19:06:38 +0800 +Subject: i2c: imx: Fix PM reference leak in i2c_imx_reg_slave() + +From: Ye Weihua + +[ Upstream commit c4b1fcc310e655fa8414696c38a84d36c00684c8 ] + +pm_runtime_get_sync() will increment the PM reference count even on +failure. Forgetting to put the reference again will result in a leak. + +Replace it with pm_runtime_resume_and_get() to keep the usage counter +balanced. + +Reported-by: Hulk Robot +Signed-off-by: Ye Weihua +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-imx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c +index dc9c4b4cc25a..dc5ca71906db 100644 +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -801,7 +801,7 @@ static int i2c_imx_reg_slave(struct i2c_client *client) + i2c_imx->last_slave_event = I2C_SLAVE_STOP; + + /* Resume */ +- ret = pm_runtime_get_sync(i2c_imx->adapter.dev.parent); ++ ret = pm_runtime_resume_and_get(i2c_imx->adapter.dev.parent); + if (ret < 0) { + dev_err(&i2c_imx->adapter.dev, "failed to resume i2c controller"); + return ret; +-- +2.30.2 + diff --git a/queue-5.12/i40e-fix-broken-xdp-support.patch b/queue-5.12/i40e-fix-broken-xdp-support.patch new file mode 100644 index 00000000000..4d0a0c4196d --- /dev/null +++ b/queue-5.12/i40e-fix-broken-xdp-support.patch @@ -0,0 +1,77 @@ +From 4eca865a45a9cc0f5909d2d9ba6ffeeb72c873cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Apr 2021 13:14:01 +0200 +Subject: i40e: fix broken XDP support + +From: Magnus Karlsson + +[ Upstream commit ae4393dfd472b194c90d75d2123105fb5ed59b04 ] + +Commit 12738ac4754e ("i40e: Fix sparse errors in i40e_txrx.c") broke +XDP support in the i40e driver. That commit was fixing a sparse error +in the code by introducing a new variable xdp_res instead of +overloading this into the skb pointer. The problem is that the code +later uses the skb pointer in if statements and these where not +extended to also test for the new xdp_res variable. Fix this by adding +the correct tests for xdp_res in these places. + +The skb pointer was used to store the result of the XDP program by +overloading the results in the error pointer +ERR_PTR(-result). Therefore, the allocation failure test that used to +only test for !skb now need to be extended to also consider !xdp_res. + +i40e_cleanup_headers() had a check that based on the skb value being +an error pointer, i.e. a result from the XDP program != XDP_PASS, and +if so start to process a new packet immediately, instead of populating +skb fields and sending the skb to the stack. This check is not needed +anymore, since we have added an explicit test for xdp_res being set +and if so just do continue to pick the next packet from the NIC. + +Fixes: 12738ac4754e ("i40e: Fix sparse errors in i40e_txrx.c") +Acked-by: Jesper Dangaard Brouer +Tested-by: Jesper Dangaard Brouer +Reported-by: Jesper Dangaard Brouer +Reviewed-by: Maciej Fijalkowski +Signed-off-by: Magnus Karlsson +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_txrx.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c +index 06b4271219b1..70b515049540 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c +@@ -1961,10 +1961,6 @@ static bool i40e_cleanup_headers(struct i40e_ring *rx_ring, struct sk_buff *skb, + union i40e_rx_desc *rx_desc) + + { +- /* XDP packets use error pointer so abort at this point */ +- if (IS_ERR(skb)) +- return true; +- + /* ERR_MASK will only have valid bits if EOP set, and + * what we are doing here is actually checking + * I40E_RX_DESC_ERROR_RXE_SHIFT, since it is the zeroth bit in +@@ -2534,7 +2530,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) + } + + /* exit if we failed to retrieve a buffer */ +- if (!skb) { ++ if (!xdp_res && !skb) { + rx_ring->rx_stats.alloc_buff_failed++; + rx_buffer->pagecnt_bias++; + break; +@@ -2547,7 +2543,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) + if (i40e_is_non_eop(rx_ring, rx_desc)) + continue; + +- if (i40e_cleanup_headers(rx_ring, skb, rx_desc)) { ++ if (xdp_res || i40e_cleanup_headers(rx_ring, skb, rx_desc)) { + skb = NULL; + continue; + } +-- +2.30.2 + diff --git a/queue-5.12/i40e-fix-phy-type-identifiers-for-2.5g-and-5g-adapte.patch b/queue-5.12/i40e-fix-phy-type-identifiers-for-2.5g-and-5g-adapte.patch new file mode 100644 index 00000000000..4fa92bebd66 --- /dev/null +++ b/queue-5.12/i40e-fix-phy-type-identifiers-for-2.5g-and-5g-adapte.patch @@ -0,0 +1,96 @@ +From 8478baea8ca8e47f281c7e60b4eb91ef72b2453a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Apr 2021 14:43:07 +0000 +Subject: i40e: Fix PHY type identifiers for 2.5G and 5G adapters + +From: Mateusz Palczewski + +[ Upstream commit 15395ec4685bd45a43d1b54b8fd9846b87e2c621 ] + +Unlike other supported adapters, 2.5G and 5G use different +PHY type identifiers for reading/writing PHY settings +and for reading link status. This commit introduces +separate PHY identifiers for these two operation types. + +Fixes: 2e45d3f4677a ("i40e: Add support for X710 B/P & SFP+ cards") +Signed-off-by: Dawid Lukwinski +Signed-off-by: Mateusz Palczewski +Reviewed-by: Aleksandr Loktionov +Tested-by: Dave Switzer +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 6 ++++-- + drivers/net/ethernet/intel/i40e/i40e_common.c | 4 ++-- + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 4 ++-- + drivers/net/ethernet/intel/i40e/i40e_type.h | 7 ++----- + 4 files changed, 10 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +index ce626eace692..140b677f114d 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h ++++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +@@ -1566,8 +1566,10 @@ enum i40e_aq_phy_type { + I40E_PHY_TYPE_25GBASE_LR = 0x22, + I40E_PHY_TYPE_25GBASE_AOC = 0x23, + I40E_PHY_TYPE_25GBASE_ACC = 0x24, +- I40E_PHY_TYPE_2_5GBASE_T = 0x30, +- I40E_PHY_TYPE_5GBASE_T = 0x31, ++ I40E_PHY_TYPE_2_5GBASE_T = 0x26, ++ I40E_PHY_TYPE_5GBASE_T = 0x27, ++ I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS = 0x30, ++ I40E_PHY_TYPE_5GBASE_T_LINK_STATUS = 0x31, + I40E_PHY_TYPE_MAX, + I40E_PHY_TYPE_NOT_SUPPORTED_HIGH_TEMP = 0xFD, + I40E_PHY_TYPE_EMPTY = 0xFE, +diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c +index ec19e18305ec..ce35e064cf60 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_common.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_common.c +@@ -1154,8 +1154,8 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw) + break; + case I40E_PHY_TYPE_100BASE_TX: + case I40E_PHY_TYPE_1000BASE_T: +- case I40E_PHY_TYPE_2_5GBASE_T: +- case I40E_PHY_TYPE_5GBASE_T: ++ case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS: ++ case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS: + case I40E_PHY_TYPE_10GBASE_T: + media = I40E_MEDIA_TYPE_BASET; + break; +diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +index 6f3b7e0faa13..e8da7339137c 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +@@ -841,8 +841,8 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, + 10000baseT_Full); + break; + case I40E_PHY_TYPE_10GBASE_T: +- case I40E_PHY_TYPE_5GBASE_T: +- case I40E_PHY_TYPE_2_5GBASE_T: ++ case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS: ++ case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS: + case I40E_PHY_TYPE_1000BASE_T: + case I40E_PHY_TYPE_100BASE_TX: + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); +diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h +index 5c10faaca790..c81109a63e90 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_type.h ++++ b/drivers/net/ethernet/intel/i40e/i40e_type.h +@@ -239,11 +239,8 @@ struct i40e_phy_info { + #define I40E_CAP_PHY_TYPE_25GBASE_ACC BIT_ULL(I40E_PHY_TYPE_25GBASE_ACC + \ + I40E_PHY_TYPE_OFFSET) + /* Offset for 2.5G/5G PHY Types value to bit number conversion */ +-#define I40E_PHY_TYPE_OFFSET2 (-10) +-#define I40E_CAP_PHY_TYPE_2_5GBASE_T BIT_ULL(I40E_PHY_TYPE_2_5GBASE_T + \ +- I40E_PHY_TYPE_OFFSET2) +-#define I40E_CAP_PHY_TYPE_5GBASE_T BIT_ULL(I40E_PHY_TYPE_5GBASE_T + \ +- I40E_PHY_TYPE_OFFSET2) ++#define I40E_CAP_PHY_TYPE_2_5GBASE_T BIT_ULL(I40E_PHY_TYPE_2_5GBASE_T) ++#define I40E_CAP_PHY_TYPE_5GBASE_T BIT_ULL(I40E_PHY_TYPE_5GBASE_T) + #define I40E_HW_CAP_MAX_GPIO 30 + /* Capabilities of a PF or a VF or the whole device */ + struct i40e_hw_capabilities { +-- +2.30.2 + diff --git a/queue-5.12/i40e-fix-the-restart-auto-negotiation-after-fec-modi.patch b/queue-5.12/i40e-fix-the-restart-auto-negotiation-after-fec-modi.patch new file mode 100644 index 00000000000..0485717cb10 --- /dev/null +++ b/queue-5.12/i40e-fix-the-restart-auto-negotiation-after-fec-modi.patch @@ -0,0 +1,41 @@ +From a96bccbc0be5400485a7b5e270d36b3f6cc3c4ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Apr 2021 14:19:40 +0000 +Subject: i40e: fix the restart auto-negotiation after FEC modified + +From: Jaroslaw Gawin + +[ Upstream commit 61343e6da7810de81d6b826698946ae4f9070819 ] + +When FEC mode was changed the link didn't know it because +the link was not reset and new parameters were not negotiated. +Set a flag 'I40E_AQ_PHY_ENABLE_ATOMIC_LINK' in 'abilities' +to restart the link and make it run with the new settings. + +Fixes: 1d96340196f1 ("i40e: Add support FEC configuration for Fortville 25G") +Signed-off-by: Jaroslaw Gawin +Signed-off-by: Mateusz Palczewski +Tested-by: Dave Switzer +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +index 0e92668012e3..6f3b7e0faa13 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +@@ -1409,7 +1409,8 @@ static int i40e_set_fec_cfg(struct net_device *netdev, u8 fec_cfg) + + memset(&config, 0, sizeof(config)); + config.phy_type = abilities.phy_type; +- config.abilities = abilities.abilities; ++ config.abilities = abilities.abilities | ++ I40E_AQ_PHY_ENABLE_ATOMIC_LINK; + config.phy_type_ext = abilities.phy_type_ext; + config.link_speed = abilities.link_speed; + config.eee_capability = abilities.eee_capability; +-- +2.30.2 + diff --git a/queue-5.12/i40e-fix-use-after-free-in-i40e_client_subtask.patch b/queue-5.12/i40e-fix-use-after-free-in-i40e_client_subtask.patch new file mode 100644 index 00000000000..941b4d1309e --- /dev/null +++ b/queue-5.12/i40e-fix-use-after-free-in-i40e_client_subtask.patch @@ -0,0 +1,37 @@ +From a85901e549fafcde30171ded64234d2e29530acc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Apr 2021 22:41:18 +0800 +Subject: i40e: Fix use-after-free in i40e_client_subtask() + +From: Yunjian Wang + +[ Upstream commit 38318f23a7ef86a8b1862e5e8078c4de121960c3 ] + +Currently the call to i40e_client_del_instance frees the object +pf->cinst, however pf->cinst->lan_info is being accessed after +the free. Fix this by adding the missing return. + +Addresses-Coverity: ("Read from pointer after free") +Fixes: 7b0b1a6d0ac9 ("i40e: Disable iWARP VSI PETCP_ENA flag on netdev down events") +Signed-off-by: Yunjian Wang +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_client.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.c b/drivers/net/ethernet/intel/i40e/i40e_client.c +index a2dba32383f6..32f3facbed1a 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_client.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_client.c +@@ -375,6 +375,7 @@ void i40e_client_subtask(struct i40e_pf *pf) + clear_bit(__I40E_CLIENT_INSTANCE_OPENED, + &cdev->state); + i40e_client_del_instance(pf); ++ return; + } + } + } +-- +2.30.2 + diff --git a/queue-5.12/i40e-remove-lldp-frame-filters.patch b/queue-5.12/i40e-remove-lldp-frame-filters.patch new file mode 100644 index 00000000000..a02227aef94 --- /dev/null +++ b/queue-5.12/i40e-remove-lldp-frame-filters.patch @@ -0,0 +1,121 @@ +From 24a4552733791fb97a0a350882413bbe871e5280 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Apr 2021 23:43:57 +0200 +Subject: i40e: Remove LLDP frame filters + +From: Arkadiusz Kubalewski + +[ Upstream commit 8085a36db71f54d2592426eb76bdf71b82479140 ] + +Remove filters from being setup in case of software DCB and allow the +LLDP frames to be properly transmitted to the wire. + +It is not possible to transmit the LLDP frame out of the port, if they +are filtered by control VSI. This prohibits software LLDP agent +properly communicate its DCB capabilities to the neighbors. + +Fixes: 4b208eaa8078 ("i40e: Add init and default config of software based DCB") +Signed-off-by: Arkadiusz Kubalewski +Tested-by: Imam Hassan Reza Biswas +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e.h | 1 - + .../net/ethernet/intel/i40e/i40e_ethtool.c | 1 - + drivers/net/ethernet/intel/i40e/i40e_main.c | 42 ------------------- + 3 files changed, 44 deletions(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h +index 15f93b355099..5069f690cf0b 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e.h ++++ b/drivers/net/ethernet/intel/i40e/i40e.h +@@ -1142,7 +1142,6 @@ static inline bool i40e_is_sw_dcb(struct i40e_pf *pf) + return !!(pf->flags & I40E_FLAG_DISABLE_FW_LLDP); + } + +-void i40e_set_lldp_forwarding(struct i40e_pf *pf, bool enable); + #ifdef CONFIG_I40E_DCB + void i40e_dcbnl_flush_apps(struct i40e_pf *pf, + struct i40e_dcbx_config *old_cfg, +diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +index e8da7339137c..93dd58fda272 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +@@ -5288,7 +5288,6 @@ flags_complete: + i40e_aq_cfg_lldp_mib_change_event(&pf->hw, false, NULL); + i40e_aq_stop_lldp(&pf->hw, true, false, NULL); + } else { +- i40e_set_lldp_forwarding(pf, false); + status = i40e_aq_start_lldp(&pf->hw, false, NULL); + if (status) { + adq_err = pf->hw.aq.asq_last_status; +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index 527023ee4c07..ac4b44fc19f1 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -6878,40 +6878,6 @@ out: + } + #endif /* CONFIG_I40E_DCB */ + +-/** +- * i40e_set_lldp_forwarding - set forwarding of lldp frames +- * @pf: PF being configured +- * @enable: if forwarding to OS shall be enabled +- * +- * Toggle forwarding of lldp frames behavior, +- * When passing DCB control from firmware to software +- * lldp frames must be forwarded to the software based +- * lldp agent. +- */ +-void i40e_set_lldp_forwarding(struct i40e_pf *pf, bool enable) +-{ +- if (pf->lan_vsi == I40E_NO_VSI) +- return; +- +- if (!pf->vsi[pf->lan_vsi]) +- return; +- +- /* No need to check the outcome, commands may fail +- * if desired value is already set +- */ +- i40e_aq_add_rem_control_packet_filter(&pf->hw, NULL, ETH_P_LLDP, +- I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX | +- I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC, +- pf->vsi[pf->lan_vsi]->seid, 0, +- enable, NULL, NULL); +- +- i40e_aq_add_rem_control_packet_filter(&pf->hw, NULL, ETH_P_LLDP, +- I40E_AQC_ADD_CONTROL_PACKET_FLAGS_RX | +- I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC, +- pf->vsi[pf->lan_vsi]->seid, 0, +- enable, NULL, NULL); +-} +- + /** + * i40e_print_link_message - print link up or down + * @vsi: the VSI for which link needs a message +@@ -10735,10 +10701,6 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) + */ + i40e_add_filter_to_drop_tx_flow_control_frames(&pf->hw, + pf->main_vsi_seid); +-#ifdef CONFIG_I40E_DCB +- if (pf->flags & I40E_FLAG_DISABLE_FW_LLDP) +- i40e_set_lldp_forwarding(pf, true); +-#endif /* CONFIG_I40E_DCB */ + + /* restart the VSIs that were rebuilt and running before the reset */ + i40e_pf_unquiesce_all_vsi(pf); +@@ -15753,10 +15715,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + */ + i40e_add_filter_to_drop_tx_flow_control_frames(&pf->hw, + pf->main_vsi_seid); +-#ifdef CONFIG_I40E_DCB +- if (pf->flags & I40E_FLAG_DISABLE_FW_LLDP) +- i40e_set_lldp_forwarding(pf, true); +-#endif /* CONFIG_I40E_DCB */ + + if ((pf->hw.device_id == I40E_DEV_ID_10G_BASE_T) || + (pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4)) +-- +2.30.2 + diff --git a/queue-5.12/ia64-module-fix-symbolizer-crash-on-fdescr.patch b/queue-5.12/ia64-module-fix-symbolizer-crash-on-fdescr.patch new file mode 100644 index 00000000000..594df249b9e --- /dev/null +++ b/queue-5.12/ia64-module-fix-symbolizer-crash-on-fdescr.patch @@ -0,0 +1,120 @@ +From d6864def57edaa838948f4bec1a37b9f5e79b366 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 22:53:48 -0700 +Subject: ia64: module: fix symbolizer crash on fdescr + +From: Sergei Trofimovich + +[ Upstream commit 99e729bd40fb3272fa4b0140839d5e957b58588a ] + +Noticed failure as a crash on ia64 when tried to symbolize all backtraces +collected by page_owner=on: + + $ cat /sys/kernel/debug/page_owner + + + CPU: 1 PID: 2074 Comm: cat Not tainted 5.12.0-rc4 #226 + Hardware name: hp server rx3600, BIOS 04.03 04/08/2008 + ip is at dereference_module_function_descriptor+0x41/0x100 + +Crash happens at dereference_module_function_descriptor() due to +use-after-free when dereferencing ".opd" section header. + +All section headers are already freed after module is laoded successfully. + +To keep symbolizer working the change stores ".opd" address and size after +module is relocated to a new place and before section headers are +discarded. + +To make similar errors less obscure module_finalize() now zeroes out all +variables relevant to module loading only. + +Link: https://lkml.kernel.org/r/20210403074803.3309096-1-slyfox@gentoo.org +Signed-off-by: Sergei Trofimovich +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + arch/ia64/include/asm/module.h | 6 +++++- + arch/ia64/kernel/module.c | 29 +++++++++++++++++++++++++---- + 2 files changed, 30 insertions(+), 5 deletions(-) + +diff --git a/arch/ia64/include/asm/module.h b/arch/ia64/include/asm/module.h +index 5a29652e6def..7271b9c5fc76 100644 +--- a/arch/ia64/include/asm/module.h ++++ b/arch/ia64/include/asm/module.h +@@ -14,16 +14,20 @@ + struct elf64_shdr; /* forward declration */ + + struct mod_arch_specific { ++ /* Used only at module load time. */ + struct elf64_shdr *core_plt; /* core PLT section */ + struct elf64_shdr *init_plt; /* init PLT section */ + struct elf64_shdr *got; /* global offset table */ + struct elf64_shdr *opd; /* official procedure descriptors */ + struct elf64_shdr *unwind; /* unwind-table section */ + unsigned long gp; /* global-pointer for module */ ++ unsigned int next_got_entry; /* index of next available got entry */ + ++ /* Used at module run and cleanup time. */ + void *core_unw_table; /* core unwind-table cookie returned by unwinder */ + void *init_unw_table; /* init unwind-table cookie returned by unwinder */ +- unsigned int next_got_entry; /* index of next available got entry */ ++ void *opd_addr; /* symbolize uses .opd to get to actual function */ ++ unsigned long opd_size; + }; + + #define ARCH_SHF_SMALL SHF_IA_64_SHORT +diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c +index 00a496cb346f..2cba53c1da82 100644 +--- a/arch/ia64/kernel/module.c ++++ b/arch/ia64/kernel/module.c +@@ -905,9 +905,31 @@ register_unwind_table (struct module *mod) + int + module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod) + { ++ struct mod_arch_specific *mas = &mod->arch; ++ + DEBUGP("%s: init: entry=%p\n", __func__, mod->init); +- if (mod->arch.unwind) ++ if (mas->unwind) + register_unwind_table(mod); ++ ++ /* ++ * ".opd" was already relocated to the final destination. Store ++ * it's address for use in symbolizer. ++ */ ++ mas->opd_addr = (void *)mas->opd->sh_addr; ++ mas->opd_size = mas->opd->sh_size; ++ ++ /* ++ * Module relocation was already done at this point. Section ++ * headers are about to be deleted. Wipe out load-time context. ++ */ ++ mas->core_plt = NULL; ++ mas->init_plt = NULL; ++ mas->got = NULL; ++ mas->opd = NULL; ++ mas->unwind = NULL; ++ mas->gp = 0; ++ mas->next_got_entry = 0; ++ + return 0; + } + +@@ -926,10 +948,9 @@ module_arch_cleanup (struct module *mod) + + void *dereference_module_function_descriptor(struct module *mod, void *ptr) + { +- Elf64_Shdr *opd = mod->arch.opd; ++ struct mod_arch_specific *mas = &mod->arch; + +- if (ptr < (void *)opd->sh_addr || +- ptr >= (void *)(opd->sh_addr + opd->sh_size)) ++ if (ptr < mas->opd_addr || ptr >= mas->opd_addr + mas->opd_size) + return ptr; + + return dereference_function_descriptor(ptr); +-- +2.30.2 + diff --git a/queue-5.12/iavf-remove-duplicate-free-resources-calls.patch b/queue-5.12/iavf-remove-duplicate-free-resources-calls.patch new file mode 100644 index 00000000000..be6bc8450d6 --- /dev/null +++ b/queue-5.12/iavf-remove-duplicate-free-resources-calls.patch @@ -0,0 +1,36 @@ +From e7582dbf2aeb319833b1003c6de919219adb2e8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Mar 2021 15:41:42 +0100 +Subject: iavf: remove duplicate free resources calls + +From: Stefan Assmann + +[ Upstream commit 1a0e880b028f97478dc689e2900b312741d0d772 ] + +Both iavf_free_all_tx_resources() and iavf_free_all_rx_resources() have +already been called in the very same function. +Remove the duplicate calls. + +Signed-off-by: Stefan Assmann +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/iavf/iavf_main.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index dc5b3c06d1e0..ebd08543791b 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -3899,8 +3899,6 @@ static void iavf_remove(struct pci_dev *pdev) + + iounmap(hw->hw_addr); + pci_release_regions(pdev); +- iavf_free_all_tx_resources(adapter); +- iavf_free_all_rx_resources(adapter); + iavf_free_queues(adapter); + kfree(adapter->vf_res); + spin_lock_bh(&adapter->mac_vlan_list_lock); +-- +2.30.2 + diff --git a/queue-5.12/ib-hfi1-correct-oversized-ring-allocation.patch b/queue-5.12/ib-hfi1-correct-oversized-ring-allocation.patch new file mode 100644 index 00000000000..d721c57b191 --- /dev/null +++ b/queue-5.12/ib-hfi1-correct-oversized-ring-allocation.patch @@ -0,0 +1,96 @@ +From 0ad109efa893a137d8c733b158650e36c4c2d6d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Mar 2021 09:54:09 -0400 +Subject: IB/hfi1: Correct oversized ring allocation + +From: Mike Marciniszyn + +[ Upstream commit b536d4b2a279733f440c911dc831764690b90050 ] + +The completion ring for tx is using the wrong size to size the ring, +oversizing the ring by two orders of magniture. + +Correct the allocation size and use kcalloc_node() to allocate the ring. +Fix mistaken GFP defines in similar allocations. + +Link: https://lore.kernel.org/r/1617026056-50483-4-git-send-email-dennis.dalessandro@cornelisnetworks.com +Reviewed-by: Kaike Wan +Signed-off-by: Mike Marciniszyn +Signed-off-by: Dennis Dalessandro +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hfi1/ipoib.h | 3 ++- + drivers/infiniband/hw/hfi1/ipoib_tx.c | 14 +++++++------- + 2 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/infiniband/hw/hfi1/ipoib.h b/drivers/infiniband/hw/hfi1/ipoib.h +index f650cac9d424..d30c23b6527a 100644 +--- a/drivers/infiniband/hw/hfi1/ipoib.h ++++ b/drivers/infiniband/hw/hfi1/ipoib.h +@@ -52,8 +52,9 @@ union hfi1_ipoib_flow { + * @producer_lock: producer sync lock + * @consumer_lock: consumer sync lock + */ ++struct ipoib_txreq; + struct hfi1_ipoib_circ_buf { +- void **items; ++ struct ipoib_txreq **items; + unsigned long head; + unsigned long tail; + unsigned long max_items; +diff --git a/drivers/infiniband/hw/hfi1/ipoib_tx.c b/drivers/infiniband/hw/hfi1/ipoib_tx.c +index edd4eeac8dd1..cdc26ee3cf52 100644 +--- a/drivers/infiniband/hw/hfi1/ipoib_tx.c ++++ b/drivers/infiniband/hw/hfi1/ipoib_tx.c +@@ -702,14 +702,14 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv) + + priv->tx_napis = kcalloc_node(dev->num_tx_queues, + sizeof(struct napi_struct), +- GFP_ATOMIC, ++ GFP_KERNEL, + priv->dd->node); + if (!priv->tx_napis) + goto free_txreq_cache; + + priv->txqs = kcalloc_node(dev->num_tx_queues, + sizeof(struct hfi1_ipoib_txq), +- GFP_ATOMIC, ++ GFP_KERNEL, + priv->dd->node); + if (!priv->txqs) + goto free_tx_napis; +@@ -741,9 +741,9 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv) + priv->dd->node); + + txq->tx_ring.items = +- vzalloc_node(array_size(tx_ring_size, +- sizeof(struct ipoib_txreq)), +- priv->dd->node); ++ kcalloc_node(tx_ring_size, ++ sizeof(struct ipoib_txreq *), ++ GFP_KERNEL, priv->dd->node); + if (!txq->tx_ring.items) + goto free_txqs; + +@@ -764,7 +764,7 @@ free_txqs: + struct hfi1_ipoib_txq *txq = &priv->txqs[i]; + + netif_napi_del(txq->napi); +- vfree(txq->tx_ring.items); ++ kfree(txq->tx_ring.items); + } + + kfree(priv->txqs); +@@ -817,7 +817,7 @@ void hfi1_ipoib_txreq_deinit(struct hfi1_ipoib_dev_priv *priv) + hfi1_ipoib_drain_tx_list(txq); + netif_napi_del(txq->napi); + (void)hfi1_ipoib_drain_tx_ring(txq, txq->tx_ring.max_items); +- vfree(txq->tx_ring.items); ++ kfree(txq->tx_ring.items); + } + + kfree(priv->txqs); +-- +2.30.2 + diff --git a/queue-5.12/ice-handle-increasing-tx-or-rx-ring-sizes.patch b/queue-5.12/ice-handle-increasing-tx-or-rx-ring-sizes.patch new file mode 100644 index 00000000000..1349f1c9c8c --- /dev/null +++ b/queue-5.12/ice-handle-increasing-tx-or-rx-ring-sizes.patch @@ -0,0 +1,215 @@ +From c1284ac7634bae901abc77a3a318b67d15890145 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Mar 2021 10:12:05 -0800 +Subject: ice: handle increasing Tx or Rx ring sizes + +From: Paul M Stillwell Jr + +[ Upstream commit 2ec5638559c13b923250eccf495d2a033fccb3e7 ] + +There is an issue when the Tx or Rx ring size increases using +'ethtool -L ...' where the new rings don't get the correct ITR +values because when we rebuild the VSI we don't know that some +of the rings may be new. + +Fix this by looking at the original number of rings and +determining if the rings in ice_vsi_rebuild_set_coalesce() +were not present in the original rings received in +ice_vsi_rebuild_get_coalesce(). + +Also change the code to return an error if we can't allocate +memory for the coalesce data in ice_vsi_rebuild(). + +Signed-off-by: Paul M Stillwell Jr +Tested-by: Tony Brelinski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_lib.c | 123 ++++++++++++++++------ + drivers/net/ethernet/intel/ice/ice_txrx.h | 2 + + 2 files changed, 92 insertions(+), 33 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index d13c7fc8fb0a..195d122c9cb2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -2818,38 +2818,46 @@ int ice_vsi_release(struct ice_vsi *vsi) + } + + /** +- * ice_vsi_rebuild_update_coalesce - set coalesce for a q_vector ++ * ice_vsi_rebuild_update_coalesce_intrl - set interrupt rate limit for a q_vector + * @q_vector: pointer to q_vector which is being updated +- * @coalesce: pointer to array of struct with stored coalesce ++ * @stored_intrl_setting: original INTRL setting + * + * Set coalesce param in q_vector and update these parameters in HW. + */ + static void +-ice_vsi_rebuild_update_coalesce(struct ice_q_vector *q_vector, +- struct ice_coalesce_stored *coalesce) ++ice_vsi_rebuild_update_coalesce_intrl(struct ice_q_vector *q_vector, ++ u16 stored_intrl_setting) + { +- struct ice_ring_container *rx_rc = &q_vector->rx; +- struct ice_ring_container *tx_rc = &q_vector->tx; + struct ice_hw *hw = &q_vector->vsi->back->hw; + +- tx_rc->itr_setting = coalesce->itr_tx; +- rx_rc->itr_setting = coalesce->itr_rx; +- +- /* dynamic ITR values will be updated during Tx/Rx */ +- if (!ITR_IS_DYNAMIC(tx_rc->itr_setting)) +- wr32(hw, GLINT_ITR(tx_rc->itr_idx, q_vector->reg_idx), +- ITR_REG_ALIGN(tx_rc->itr_setting) >> +- ICE_ITR_GRAN_S); +- if (!ITR_IS_DYNAMIC(rx_rc->itr_setting)) +- wr32(hw, GLINT_ITR(rx_rc->itr_idx, q_vector->reg_idx), +- ITR_REG_ALIGN(rx_rc->itr_setting) >> +- ICE_ITR_GRAN_S); +- +- q_vector->intrl = coalesce->intrl; ++ q_vector->intrl = stored_intrl_setting; + wr32(hw, GLINT_RATE(q_vector->reg_idx), + ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); + } + ++/** ++ * ice_vsi_rebuild_update_coalesce_itr - set coalesce for a q_vector ++ * @q_vector: pointer to q_vector which is being updated ++ * @rc: pointer to ring container ++ * @stored_itr_setting: original ITR setting ++ * ++ * Set coalesce param in q_vector and update these parameters in HW. ++ */ ++static void ++ice_vsi_rebuild_update_coalesce_itr(struct ice_q_vector *q_vector, ++ struct ice_ring_container *rc, ++ u16 stored_itr_setting) ++{ ++ struct ice_hw *hw = &q_vector->vsi->back->hw; ++ ++ rc->itr_setting = stored_itr_setting; ++ ++ /* dynamic ITR values will be updated during Tx/Rx */ ++ if (!ITR_IS_DYNAMIC(rc->itr_setting)) ++ wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx), ++ ITR_REG_ALIGN(rc->itr_setting) >> ICE_ITR_GRAN_S); ++} ++ + /** + * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors + * @vsi: VSI connected with q_vectors +@@ -2869,6 +2877,11 @@ ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi, + coalesce[i].itr_tx = q_vector->tx.itr_setting; + coalesce[i].itr_rx = q_vector->rx.itr_setting; + coalesce[i].intrl = q_vector->intrl; ++ ++ if (i < vsi->num_txq) ++ coalesce[i].tx_valid = true; ++ if (i < vsi->num_rxq) ++ coalesce[i].rx_valid = true; + } + + return vsi->num_q_vectors; +@@ -2893,17 +2906,59 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi, + if ((size && !coalesce) || !vsi) + return; + +- for (i = 0; i < size && i < vsi->num_q_vectors; i++) +- ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i], +- &coalesce[i]); +- +- /* number of q_vectors increased, so assume coalesce settings were +- * changed globally (i.e. ethtool -C eth0 instead of per-queue) and use +- * the previous settings from q_vector 0 for all of the new q_vectors ++ /* There are a couple of cases that have to be handled here: ++ * 1. The case where the number of queue vectors stays the same, but ++ * the number of Tx or Rx rings changes (the first for loop) ++ * 2. The case where the number of queue vectors increased (the ++ * second for loop) + */ +- for (; i < vsi->num_q_vectors; i++) +- ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i], +- &coalesce[0]); ++ for (i = 0; i < size && i < vsi->num_q_vectors; i++) { ++ /* There are 2 cases to handle here and they are the same for ++ * both Tx and Rx: ++ * if the entry was valid previously (coalesce[i].[tr]x_valid ++ * and the loop variable is less than the number of rings ++ * allocated, then write the previous values ++ * ++ * if the entry was not valid previously, but the number of ++ * rings is less than are allocated (this means the number of ++ * rings increased from previously), then write out the ++ * values in the first element ++ */ ++ if (i < vsi->alloc_rxq && coalesce[i].rx_valid) ++ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], ++ &vsi->q_vectors[i]->rx, ++ coalesce[i].itr_rx); ++ else if (i < vsi->alloc_rxq) ++ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], ++ &vsi->q_vectors[i]->rx, ++ coalesce[0].itr_rx); ++ ++ if (i < vsi->alloc_txq && coalesce[i].tx_valid) ++ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], ++ &vsi->q_vectors[i]->tx, ++ coalesce[i].itr_tx); ++ else if (i < vsi->alloc_txq) ++ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], ++ &vsi->q_vectors[i]->tx, ++ coalesce[0].itr_tx); ++ ++ ice_vsi_rebuild_update_coalesce_intrl(vsi->q_vectors[i], ++ coalesce[i].intrl); ++ } ++ ++ /* the number of queue vectors increased so write whatever is in ++ * the first element ++ */ ++ for (; i < vsi->num_q_vectors; i++) { ++ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], ++ &vsi->q_vectors[i]->tx, ++ coalesce[0].itr_tx); ++ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], ++ &vsi->q_vectors[i]->rx, ++ coalesce[0].itr_rx); ++ ice_vsi_rebuild_update_coalesce_intrl(vsi->q_vectors[i], ++ coalesce[0].intrl); ++ } + } + + /** +@@ -2932,9 +2987,11 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi) + + coalesce = kcalloc(vsi->num_q_vectors, + sizeof(struct ice_coalesce_stored), GFP_KERNEL); +- if (coalesce) +- prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, +- coalesce); ++ if (!coalesce) ++ return -ENOMEM; ++ ++ prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce); ++ + ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); + ice_vsi_free_q_vectors(vsi); + +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h +index 5dab77504fa5..672a7ff0ee36 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.h ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.h +@@ -351,6 +351,8 @@ struct ice_coalesce_stored { + u16 itr_tx; + u16 itr_rx; + u8 intrl; ++ u8 tx_valid; ++ u8 rx_valid; + }; + + /* iterator for handling rings in ring container */ +-- +2.30.2 + diff --git a/queue-5.12/iommu-amd-remove-performance-counter-pre-initializat.patch b/queue-5.12/iommu-amd-remove-performance-counter-pre-initializat.patch new file mode 100644 index 00000000000..e01576e3575 --- /dev/null +++ b/queue-5.12/iommu-amd-remove-performance-counter-pre-initializat.patch @@ -0,0 +1,98 @@ +From 6da82a94cafa03cd0321fd68c4e228bca3572073 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Apr 2021 03:58:48 -0500 +Subject: iommu/amd: Remove performance counter pre-initialization test + +From: Suravee Suthikulpanit + +[ Upstream commit 994d6608efe4a4c8834bdc5014c86f4bc6aceea6 ] + +In early AMD desktop/mobile platforms (during 2013), when the IOMMU +Performance Counter (PMC) support was first introduced in +commit 30861ddc9cca ("perf/x86/amd: Add IOMMU Performance Counter +resource management"), there was a HW bug where the counters could not +be accessed. The result was reading of the counter always return zero. + +At the time, the suggested workaround was to add a test logic prior +to initializing the PMC feature to check if the counters can be programmed +and read back the same value. This has been working fine until the more +recent desktop/mobile platforms start enabling power gating for the PMC, +which prevents access to the counters. This results in the PMC support +being disabled unnecesarily. + +Unfortunatly, there is no documentation of since which generation +of hardware the original PMC HW bug was fixed. Although, it was fixed +soon after the first introduction of the PMC. Base on this, we assume +that the buggy platforms are less likely to be in used, and it should +be relatively safe to remove this legacy logic. + +Link: https://lore.kernel.org/linux-iommu/alpine.LNX.3.20.13.2006030935570.3181@monopod.intra.ispras.ru/ +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=201753 +Cc: Tj (Elloe Linux) +Cc: Shuah Khan +Cc: Alexander Monakov +Cc: David Coe +Cc: Paul Menzel +Signed-off-by: Suravee Suthikulpanit +Tested-by: Shuah Khan +Link: https://lore.kernel.org/r/20210409085848.3908-3-suravee.suthikulpanit@amd.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/init.c | 24 +----------------------- + 1 file changed, 1 insertion(+), 23 deletions(-) + +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index ad53f516e46e..df7b19ff0a9e 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -1714,33 +1714,16 @@ static int __init init_iommu_all(struct acpi_table_header *table) + return 0; + } + +-static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, +- u8 fxn, u64 *value, bool is_write); +- + static void init_iommu_perf_ctr(struct amd_iommu *iommu) + { ++ u64 val; + struct pci_dev *pdev = iommu->dev; +- u64 val = 0xabcd, val2 = 0, save_reg = 0; + + if (!iommu_feature(iommu, FEATURE_PC)) + return; + + amd_iommu_pc_present = true; + +- /* save the value to restore, if writable */ +- if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, false)) +- goto pc_false; +- +- /* Check if the performance counters can be written to */ +- if ((iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true)) || +- (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false)) || +- (val != val2)) +- goto pc_false; +- +- /* restore */ +- if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, true)) +- goto pc_false; +- + pci_info(pdev, "IOMMU performance counters supported\n"); + + val = readl(iommu->mmio_base + MMIO_CNTR_CONF_OFFSET); +@@ -1748,11 +1731,6 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu) + iommu->max_counters = (u8) ((val >> 7) & 0xf); + + return; +- +-pc_false: +- pci_err(pdev, "Unable to read/write to IOMMU perf counter.\n"); +- amd_iommu_pc_present = false; +- return; + } + + static ssize_t amd_iommu_show_cap(struct device *dev, +-- +2.30.2 + diff --git a/queue-5.12/iommu-arm-smmu-v3-add-a-check-to-avoid-invalid-iotlb.patch b/queue-5.12/iommu-arm-smmu-v3-add-a-check-to-avoid-invalid-iotlb.patch new file mode 100644 index 00000000000..820231d2f1b --- /dev/null +++ b/queue-5.12/iommu-arm-smmu-v3-add-a-check-to-avoid-invalid-iotlb.patch @@ -0,0 +1,38 @@ +From 00b5f9112da8ab643f4ecca17216d6bfbbb454d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Mar 2021 20:58:26 +0800 +Subject: iommu/arm-smmu-v3: Add a check to avoid invalid iotlb sync + +From: Xiang Chen + +[ Upstream commit 6cc7e5a9c6b02507b9be5a99b51e970afa91c85f ] + +It may send a invalid tlb sync for smmuv3 if iotlb_gather is not valid +(iotlb_gather->pgsize = 0). So add a check to avoid invalid iotlb sync +for it. + +Signed-off-by: Xiang Chen +Link: https://lore.kernel.org/r/1617109106-121844-1-git-send-email-chenxiang66@hisilicon.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +index 8594b4a83043..941ba5484731 100644 +--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c ++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +@@ -2305,6 +2305,9 @@ static void arm_smmu_iotlb_sync(struct iommu_domain *domain, + { + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + ++ if (!gather->pgsize) ++ return; ++ + arm_smmu_tlb_inv_range_domain(gather->start, + gather->end - gather->start + 1, + gather->pgsize, true, smmu_domain); +-- +2.30.2 + diff --git a/queue-5.12/ip6_vti-proper-dev_-hold-put-in-ndo_-un-init-methods.patch b/queue-5.12/ip6_vti-proper-dev_-hold-put-in-ndo_-un-init-methods.patch new file mode 100644 index 00000000000..6b78364bb63 --- /dev/null +++ b/queue-5.12/ip6_vti-proper-dev_-hold-put-in-ndo_-un-init-methods.patch @@ -0,0 +1,98 @@ +From 1254b05be21d4c6ee697df02adb7056b0a2e6ec0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Mar 2021 12:12:54 -0700 +Subject: ip6_vti: proper dev_{hold|put} in ndo_[un]init methods + +From: Eric Dumazet + +[ Upstream commit 40cb881b5aaa0b69a7d93dec8440d5c62dae299f ] + +After adopting CONFIG_PCPU_DEV_REFCNT=n option, syzbot was able to trigger +a warning [1] + +Issue here is that: + +- all dev_put() should be paired with a corresponding prior dev_hold(). + +- A driver doing a dev_put() in its ndo_uninit() MUST also + do a dev_hold() in its ndo_init(), only when ndo_init() + is returning 0. + +Otherwise, register_netdevice() would call ndo_uninit() +in its error path and release a refcount too soon. + +Therefore, we need to move dev_hold() call from +vti6_tnl_create2() to vti6_dev_init_gen() + +[1] +WARNING: CPU: 0 PID: 15951 at lib/refcount.c:31 refcount_warn_saturate+0xbf/0x1e0 lib/refcount.c:31 +Modules linked in: +CPU: 0 PID: 15951 Comm: syz-executor.3 Not tainted 5.12.0-rc4-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +RIP: 0010:refcount_warn_saturate+0xbf/0x1e0 lib/refcount.c:31 +Code: 1d 6a 5a e8 09 31 ff 89 de e8 8d 1a ab fd 84 db 75 e0 e8 d4 13 ab fd 48 c7 c7 a0 e1 c1 89 c6 05 4a 5a e8 09 01 e8 2e 36 fb 04 <0f> 0b eb c4 e8 b8 13 ab fd 0f b6 1d 39 5a e8 09 31 ff 89 de e8 58 +RSP: 0018:ffffc90001eaef28 EFLAGS: 00010282 +RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 +RDX: 0000000000040000 RSI: ffffffff815c51f5 RDI: fffff520003d5dd7 +RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000 +R10: ffffffff815bdf8e R11: 0000000000000000 R12: ffff88801bb1c568 +R13: ffff88801f69e800 R14: 00000000ffffffff R15: ffff888050889d40 +FS: 00007fc79314e700(0000) GS:ffff8880b9c00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f1c1ff47108 CR3: 0000000020fd5000 CR4: 00000000001506f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + __refcount_dec include/linux/refcount.h:344 [inline] + refcount_dec include/linux/refcount.h:359 [inline] + dev_put include/linux/netdevice.h:4135 [inline] + vti6_dev_uninit+0x31a/0x360 net/ipv6/ip6_vti.c:297 + register_netdevice+0xadf/0x1500 net/core/dev.c:10308 + vti6_tnl_create2+0x1b5/0x400 net/ipv6/ip6_vti.c:190 + vti6_newlink+0x9d/0xd0 net/ipv6/ip6_vti.c:1020 + __rtnl_newlink+0x1062/0x1710 net/core/rtnetlink.c:3443 + rtnl_newlink+0x64/0xa0 net/core/rtnetlink.c:3491 + rtnetlink_rcv_msg+0x44e/0xad0 net/core/rtnetlink.c:5553 + netlink_rcv_skb+0x153/0x420 net/netlink/af_netlink.c:2502 + netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] + netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1338 + netlink_sendmsg+0x856/0xd90 net/netlink/af_netlink.c:1927 + sock_sendmsg_nosec net/socket.c:654 [inline] + sock_sendmsg+0xcf/0x120 net/socket.c:674 + ____sys_sendmsg+0x331/0x810 net/socket.c:2350 + ___sys_sendmsg+0xf3/0x170 net/socket.c:2404 + __sys_sendmmsg+0x195/0x470 net/socket.c:2490 + __do_sys_sendmmsg net/socket.c:2519 [inline] + __se_sys_sendmmsg net/socket.c:2516 [inline] + __x64_sys_sendmmsg+0x99/0x100 net/socket.c:2516 + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_vti.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c +index e0cc32e45880..932b15b13053 100644 +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -193,7 +193,6 @@ static int vti6_tnl_create2(struct net_device *dev) + + strcpy(t->parms.name, dev->name); + +- dev_hold(dev); + vti6_tnl_link(ip6n, t); + + return 0; +@@ -934,6 +933,7 @@ static inline int vti6_dev_init_gen(struct net_device *dev) + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); + if (!dev->tstats) + return -ENOMEM; ++ dev_hold(dev); + return 0; + } + +-- +2.30.2 + diff --git a/queue-5.12/iwlwifi-pcie-make-cfg-vs.-trans_cfg-more-robust.patch b/queue-5.12/iwlwifi-pcie-make-cfg-vs.-trans_cfg-more-robust.patch new file mode 100644 index 00000000000..282ffaab58b --- /dev/null +++ b/queue-5.12/iwlwifi-pcie-make-cfg-vs.-trans_cfg-more-robust.patch @@ -0,0 +1,113 @@ +From cf80a3e64299354500451afe14361ae4380c8fe3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Mar 2021 16:24:58 +0300 +Subject: iwlwifi: pcie: make cfg vs. trans_cfg more robust + +From: Johannes Berg + +[ Upstream commit 48a5494d6a4cb5812f0640d9515f1876ffc7a013 ] + +If we (for example) have a trans_cfg entry in the PCI IDs table, +but then don't find a full cfg entry for it in the info table, +we fall through to the code that treats the PCI ID table entry +as a full cfg entry. This obviously causes crashes later, e.g. +when trying to build the firmware name string. + +Avoid such crashes by using the low bit of the pointer as a tag +for trans_cfg entries (automatically using a macro that checks +the type when assigning) and then checking that before trying to +use the data as a full entry - if it's just a partial entry at +that point, fail. + +Since we're adding some macro magic, also check that the type is +in fact either struct iwl_cfg_trans_params or struct iwl_cfg, +failing compilation ("initializer element is not constant") if +it isn't. + +Signed-off-by: Johannes Berg +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/iwlwifi.20210330162204.6f69fe6e4128.I921d4ae20ef5276716baeeeda0b001cf25b9b968@changeid +Signed-off-by: Luca Coelho +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 35 +++++++++++++++---- + 1 file changed, 28 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +index 558a0b2ef0fc..6f4db04ead4a 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +@@ -17,10 +17,20 @@ + #include "iwl-prph.h" + #include "internal.h" + ++#define TRANS_CFG_MARKER BIT(0) ++#define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg), \ ++ struct _struct) ++extern int _invalid_type; ++#define _TRANS_CFG_MARKER(cfg) \ ++ (__builtin_choose_expr(_IS_A(cfg, iwl_cfg_trans_params), \ ++ TRANS_CFG_MARKER, \ ++ __builtin_choose_expr(_IS_A(cfg, iwl_cfg), 0, _invalid_type))) ++#define _ASSIGN_CFG(cfg) (_TRANS_CFG_MARKER(cfg) + (kernel_ulong_t)&(cfg)) ++ + #define IWL_PCI_DEVICE(dev, subdev, cfg) \ + .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ +- .driver_data = (kernel_ulong_t)&(cfg) ++ .driver_data = _ASSIGN_CFG(cfg) + + /* Hardware specific file defines the PCI IDs table for that hardware module */ + static const struct pci_device_id iwl_hw_card_ids[] = { +@@ -1075,19 +1085,22 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { + + static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + { +- const struct iwl_cfg_trans_params *trans = +- (struct iwl_cfg_trans_params *)(ent->driver_data); ++ const struct iwl_cfg_trans_params *trans; + const struct iwl_cfg *cfg_7265d __maybe_unused = NULL; + struct iwl_trans *iwl_trans; + struct iwl_trans_pcie *trans_pcie; + int i, ret; ++ const struct iwl_cfg *cfg; ++ ++ trans = (void *)(ent->driver_data & ~TRANS_CFG_MARKER); ++ + /* + * This is needed for backwards compatibility with the old + * tables, so we don't need to change all the config structs + * at the same time. The cfg is used to compare with the old + * full cfg structs. + */ +- const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); ++ cfg = (void *)(ent->driver_data & ~TRANS_CFG_MARKER); + + /* make sure trans is the first element in iwl_cfg */ + BUILD_BUG_ON(offsetof(struct iwl_cfg, trans)); +@@ -1202,11 +1215,19 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + + #endif + /* +- * If we didn't set the cfg yet, assume the trans is actually +- * a full cfg from the old tables. ++ * If we didn't set the cfg yet, the PCI ID table entry should have ++ * been a full config - if yes, use it, otherwise fail. + */ +- if (!iwl_trans->cfg) ++ if (!iwl_trans->cfg) { ++ if (ent->driver_data & TRANS_CFG_MARKER) { ++ pr_err("No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n", ++ pdev->device, pdev->subsystem_device, ++ iwl_trans->hw_rev, iwl_trans->hw_rf_id); ++ ret = -EINVAL; ++ goto out_free_trans; ++ } + iwl_trans->cfg = cfg; ++ } + + /* if we don't have a name yet, copy name from the old cfg */ + if (!iwl_trans->name) +-- +2.30.2 + diff --git a/queue-5.12/iwlwifi-queue-avoid-memory-leak-in-reset-flow.patch b/queue-5.12/iwlwifi-queue-avoid-memory-leak-in-reset-flow.patch new file mode 100644 index 00000000000..e3ef0d028e3 --- /dev/null +++ b/queue-5.12/iwlwifi-queue-avoid-memory-leak-in-reset-flow.patch @@ -0,0 +1,121 @@ +From 521a05ad2a806a69d5844e718d0294b8f97b10df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Apr 2021 12:46:22 +0300 +Subject: iwlwifi: queue: avoid memory leak in reset flow + +From: Mordechay Goodstein + +[ Upstream commit 4cf2f5904d971a461f67825434ae3c31900ff84b ] + +In case the device is stopped any usage of hw queues needs to be +reallocated in fw due to fw reset after device stop, so all driver +internal queue should also be freed, and if we don't free the next usage +would leak the old memory and get in recover flows +"iwlwifi 0000:00:03.0: dma_pool_destroy iwlwifi:bc" warning. + +Also warn about trying to reuse an internal allocated queue. + +Signed-off-by: Mordechay Goodstein +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/iwlwifi.20210411124417.c72d2f0355c4.Ia3baff633b9b9109f88ab379ef0303aa152c16bf@changeid +Signed-off-by: Luca Coelho +Signed-off-by: Sasha Levin +--- + .../wireless/intel/iwlwifi/pcie/trans-gen2.c | 4 +-- + drivers/net/wireless/intel/iwlwifi/queue/tx.c | 30 ++++--------------- + drivers/net/wireless/intel/iwlwifi/queue/tx.h | 3 +- + 3 files changed, 9 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +index 94ffc1ae484d..af9412bd697e 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* + * Copyright (C) 2017 Intel Deutschland GmbH +- * Copyright (C) 2018-2020 Intel Corporation ++ * Copyright (C) 2018-2021 Intel Corporation + */ + #include "iwl-trans.h" + #include "iwl-prph.h" +@@ -143,7 +143,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) + if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { + IWL_DEBUG_INFO(trans, + "DEVICE_ENABLED bit was set and is now cleared\n"); +- iwl_txq_gen2_tx_stop(trans); ++ iwl_txq_gen2_tx_free(trans); + iwl_pcie_rx_stop(trans); + } + +diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c +index 833f43d1ca7a..810dcb3df242 100644 +--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c ++++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c +@@ -13,30 +13,6 @@ + #include "iwl-scd.h" + #include + +-/* +- * iwl_txq_gen2_tx_stop - Stop all Tx DMA channels +- */ +-void iwl_txq_gen2_tx_stop(struct iwl_trans *trans) +-{ +- int txq_id; +- +- /* +- * This function can be called before the op_mode disabled the +- * queues. This happens when we have an rfkill interrupt. +- * Since we stop Tx altogether - mark the queues as stopped. +- */ +- memset(trans->txqs.queue_stopped, 0, +- sizeof(trans->txqs.queue_stopped)); +- memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used)); +- +- /* Unmap DMA from host system and free skb's */ +- for (txq_id = 0; txq_id < ARRAY_SIZE(trans->txqs.txq); txq_id++) { +- if (!trans->txqs.txq[txq_id]) +- continue; +- iwl_txq_gen2_unmap(trans, txq_id); +- } +-} +- + /* + * iwl_txq_update_byte_tbl - Set up entry in Tx byte-count array + */ +@@ -1189,6 +1165,12 @@ static int iwl_txq_alloc_response(struct iwl_trans *trans, struct iwl_txq *txq, + goto error_free_resp; + } + ++ if (WARN_ONCE(trans->txqs.txq[qid], ++ "queue %d already allocated\n", qid)) { ++ ret = -EIO; ++ goto error_free_resp; ++ } ++ + txq->id = qid; + trans->txqs.txq[qid] = txq; + wr_ptr &= (trans->trans_cfg->base_params->max_tfd_queue_size - 1); +diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.h b/drivers/net/wireless/intel/iwlwifi/queue/tx.h +index af1dbdf5617a..20efc62acf13 100644 +--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.h ++++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ + /* +- * Copyright (C) 2020 Intel Corporation ++ * Copyright (C) 2020-2021 Intel Corporation + */ + #ifndef __iwl_trans_queue_tx_h__ + #define __iwl_trans_queue_tx_h__ +@@ -123,7 +123,6 @@ int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, + void iwl_txq_dyn_free(struct iwl_trans *trans, int queue); + void iwl_txq_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq); + void iwl_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq); +-void iwl_txq_gen2_tx_stop(struct iwl_trans *trans); + void iwl_txq_gen2_tx_free(struct iwl_trans *trans); + int iwl_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, + bool cmd_queue); +-- +2.30.2 + diff --git a/queue-5.12/iwlwifi-trans-pcie-defer-transport-initialisation.patch b/queue-5.12/iwlwifi-trans-pcie-defer-transport-initialisation.patch new file mode 100644 index 00000000000..816003e99e8 --- /dev/null +++ b/queue-5.12/iwlwifi-trans-pcie-defer-transport-initialisation.patch @@ -0,0 +1,221 @@ +From 01dc5eb2a593a40331bb941f8779149e07b99ad6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Apr 2021 13:25:41 +0300 +Subject: iwlwifi: trans/pcie: defer transport initialisation + +From: Johannes Berg + +[ Upstream commit d12455fdbfe9430affd88bfbfee51777356667a0 ] + +In a few PCIe devices we may have to swap out the configuration +after we allocate/initialise some parts of the device because +we only know the correct one after reading some registers. This +causes some things such as the byte-count table allocations to +be incorrect, since the configuration is swapped for one with a +bigger queue size. + +Fix this by initialising most of the transport much later, only +after the configuration has finally been determined. + +Signed-off-by: Johannes Berg +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/iwlwifi.20210411132130.8f5db97db1e4.Ic622da559b586a04ca536a0ec49ed5ecf03a9354@changeid +Signed-off-by: Luca Coelho +Signed-off-by: Sasha Levin +--- + .../net/wireless/intel/iwlwifi/iwl-trans.c | 91 +++++++++++-------- + .../net/wireless/intel/iwlwifi/iwl-trans.h | 1 + + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 + + 3 files changed, 57 insertions(+), 39 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +index 60e0db4a5e20..9236f9106826 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +@@ -2,7 +2,7 @@ + /* + * Copyright (C) 2015 Intel Mobile Communications GmbH + * Copyright (C) 2016-2017 Intel Deutschland GmbH +- * Copyright (C) 2019-2020 Intel Corporation ++ * Copyright (C) 2019-2021 Intel Corporation + */ + #include + #include +@@ -21,7 +21,6 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, + const struct iwl_cfg_trans_params *cfg_trans) + { + struct iwl_trans *trans; +- int txcmd_size, txcmd_align; + #ifdef CONFIG_LOCKDEP + static struct lock_class_key __key; + #endif +@@ -31,10 +30,40 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, + return NULL; + + trans->trans_cfg = cfg_trans; +- if (!cfg_trans->gen2) { ++ ++#ifdef CONFIG_LOCKDEP ++ lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map", ++ &__key, 0); ++#endif ++ ++ trans->dev = dev; ++ trans->ops = ops; ++ trans->num_rx_queues = 1; ++ ++ WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty); ++ ++ if (trans->trans_cfg->use_tfh) { ++ trans->txqs.tfd.addr_size = 64; ++ trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS; ++ trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd); ++ } else { ++ trans->txqs.tfd.addr_size = 36; ++ trans->txqs.tfd.max_tbs = IWL_NUM_OF_TBS; ++ trans->txqs.tfd.size = sizeof(struct iwl_tfd); ++ } ++ trans->max_skb_frags = IWL_TRANS_MAX_FRAGS(trans); ++ ++ return trans; ++} ++ ++int iwl_trans_init(struct iwl_trans *trans) ++{ ++ int txcmd_size, txcmd_align; ++ ++ if (!trans->trans_cfg->gen2) { + txcmd_size = sizeof(struct iwl_tx_cmd); + txcmd_align = sizeof(void *); +- } else if (cfg_trans->device_family < IWL_DEVICE_FAMILY_AX210) { ++ } else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { + txcmd_size = sizeof(struct iwl_tx_cmd_gen2); + txcmd_align = 64; + } else { +@@ -46,17 +75,8 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, + txcmd_size += 36; /* biggest possible 802.11 header */ + + /* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */ +- if (WARN_ON(cfg_trans->gen2 && txcmd_size >= txcmd_align)) +- return ERR_PTR(-EINVAL); +- +-#ifdef CONFIG_LOCKDEP +- lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map", +- &__key, 0); +-#endif +- +- trans->dev = dev; +- trans->ops = ops; +- trans->num_rx_queues = 1; ++ if (WARN_ON(trans->trans_cfg->gen2 && txcmd_size >= txcmd_align)) ++ return -EINVAL; + + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) + trans->txqs.bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl); +@@ -68,23 +88,16 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, + * allocate here. + */ + if (trans->trans_cfg->gen2) { +- trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", dev, ++ trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", trans->dev, + trans->txqs.bc_tbl_size, + 256, 0); + if (!trans->txqs.bc_pool) +- return NULL; ++ return -ENOMEM; + } + +- if (trans->trans_cfg->use_tfh) { +- trans->txqs.tfd.addr_size = 64; +- trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS; +- trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd); +- } else { +- trans->txqs.tfd.addr_size = 36; +- trans->txqs.tfd.max_tbs = IWL_NUM_OF_TBS; +- trans->txqs.tfd.size = sizeof(struct iwl_tfd); +- } +- trans->max_skb_frags = IWL_TRANS_MAX_FRAGS(trans); ++ /* Some things must not change even if the config does */ ++ WARN_ON(trans->txqs.tfd.addr_size != ++ (trans->trans_cfg->use_tfh ? 64 : 36)); + + snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), + "iwl_cmd_pool:%s", dev_name(trans->dev)); +@@ -93,35 +106,35 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, + txcmd_size, txcmd_align, + SLAB_HWCACHE_ALIGN, NULL); + if (!trans->dev_cmd_pool) +- return NULL; +- +- WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty); ++ return -ENOMEM; + + trans->txqs.tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page); + if (!trans->txqs.tso_hdr_page) { + kmem_cache_destroy(trans->dev_cmd_pool); +- return NULL; ++ return -ENOMEM; + } + + /* Initialize the wait queue for commands */ + init_waitqueue_head(&trans->wait_command_queue); + +- return trans; ++ return 0; + } + + void iwl_trans_free(struct iwl_trans *trans) + { + int i; + +- for_each_possible_cpu(i) { +- struct iwl_tso_hdr_page *p = +- per_cpu_ptr(trans->txqs.tso_hdr_page, i); ++ if (trans->txqs.tso_hdr_page) { ++ for_each_possible_cpu(i) { ++ struct iwl_tso_hdr_page *p = ++ per_cpu_ptr(trans->txqs.tso_hdr_page, i); + +- if (p->page) +- __free_page(p->page); +- } ++ if (p && p->page) ++ __free_page(p->page); ++ } + +- free_percpu(trans->txqs.tso_hdr_page); ++ free_percpu(trans->txqs.tso_hdr_page); ++ } + + kmem_cache_destroy(trans->dev_cmd_pool); + } +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +index 4a5822c1be13..3e0df6fbb642 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +@@ -1438,6 +1438,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, + struct device *dev, + const struct iwl_trans_ops *ops, + const struct iwl_cfg_trans_params *cfg_trans); ++int iwl_trans_init(struct iwl_trans *trans); + void iwl_trans_free(struct iwl_trans *trans); + + /***************************************************** +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +index 6f4db04ead4a..66faf7914bd8 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +@@ -1243,6 +1243,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + trans_pcie->num_rx_bufs = RX_QUEUE_SIZE; + } + ++ ret = iwl_trans_init(iwl_trans); ++ if (ret) ++ goto out_free_trans; ++ + pci_set_drvdata(pdev, iwl_trans); + iwl_trans->drv = iwl_drv_start(iwl_trans); + +-- +2.30.2 + diff --git a/queue-5.12/kbuild-generate-module.symvers-only-when-vmlinux-exi.patch b/queue-5.12/kbuild-generate-module.symvers-only-when-vmlinux-exi.patch new file mode 100644 index 00000000000..8cb0b07aa57 --- /dev/null +++ b/queue-5.12/kbuild-generate-module.symvers-only-when-vmlinux-exi.patch @@ -0,0 +1,144 @@ +From e0b3f94b0804d774eb5f28a053db75a9124f7ed1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Mar 2021 03:54:09 +0900 +Subject: kbuild: generate Module.symvers only when vmlinux exists + +From: Masahiro Yamada + +[ Upstream commit 69bc8d386aebbd91a6bb44b6d33f77c8dfa9ed8c ] + +The external module build shows the following warning if Module.symvers +is missing in the kernel tree. + + WARNING: Symbol version dump "Module.symvers" is missing. + Modules may not have dependencies or modversions. + +I think this is an important heads-up because the resulting modules may +not work as expected. This happens when you did not build the entire +kernel tree, for example, you might have prepared the minimal setups +for external modules by 'make defconfig && make modules_preapre'. + +A problem is that 'make modules' creates Module.symvers even without +vmlinux. In this case, that warning is suppressed since Module.symvers +already exists in spite of its incomplete content. + +The incomplete (i.e. invalid) Module.symvers should not be created. + +This commit changes the second pass of modpost to dump symbols into +modules-only.symvers. The final Module.symvers is created by +concatenating vmlinux.symvers and modules-only.symvers if both exist. + +Module.symvers is supposed to collect symbols from both vmlinux and +modules. It might be a bit confusing, and I am not quite sure if it +is an official interface, but presumably it is difficult to rename it +because some tools (e.g. kmod) parse it. + +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + .gitignore | 1 + + Documentation/dontdiff | 1 + + Makefile | 2 +- + scripts/Makefile.modpost | 15 ++++++++++++++- + scripts/mod/modpost.c | 15 +-------------- + 5 files changed, 18 insertions(+), 16 deletions(-) + +diff --git a/.gitignore b/.gitignore +index 3af66272d6f1..127012c1f717 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -57,6 +57,7 @@ modules.order + /tags + /TAGS + /linux ++/modules-only.symvers + /vmlinux + /vmlinux.32 + /vmlinux.symvers +diff --git a/Documentation/dontdiff b/Documentation/dontdiff +index e361fc95ca29..82e3eee7363b 100644 +--- a/Documentation/dontdiff ++++ b/Documentation/dontdiff +@@ -178,6 +178,7 @@ mktables + mktree + mkutf8data + modpost ++modules-only.symvers + modules.builtin + modules.builtin.modinfo + modules.nsdeps +diff --git a/Makefile b/Makefile +index 0b1852621615..7503ffef6424 100644 +--- a/Makefile ++++ b/Makefile +@@ -1513,7 +1513,7 @@ endif # CONFIG_MODULES + # make distclean Remove editor backup files, patch leftover files and the like + + # Directories & files removed with 'make clean' +-CLEAN_FILES += include/ksym vmlinux.symvers \ ++CLEAN_FILES += include/ksym vmlinux.symvers modules-only.symvers \ + modules.builtin modules.builtin.modinfo modules.nsdeps \ + compile_commands.json .thinlto-cache + +diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost +index 066beffca09a..4ca5579af4e4 100644 +--- a/scripts/Makefile.modpost ++++ b/scripts/Makefile.modpost +@@ -68,7 +68,20 @@ else + ifeq ($(KBUILD_EXTMOD),) + + input-symdump := vmlinux.symvers +-output-symdump := Module.symvers ++output-symdump := modules-only.symvers ++ ++quiet_cmd_cat = GEN $@ ++ cmd_cat = cat $(real-prereqs) > $@ ++ ++ifneq ($(wildcard vmlinux.symvers),) ++ ++__modpost: Module.symvers ++Module.symvers: vmlinux.symvers modules-only.symvers FORCE ++ $(call if_changed,cat) ++ ++targets += Module.symvers ++ ++endif + + else + +diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c +index 24725e50c7b4..10c3fba26f03 100644 +--- a/scripts/mod/modpost.c ++++ b/scripts/mod/modpost.c +@@ -2423,19 +2423,6 @@ fail: + fatal("parse error in symbol dump file\n"); + } + +-/* For normal builds always dump all symbols. +- * For external modules only dump symbols +- * that are not read from kernel Module.symvers. +- **/ +-static int dump_sym(struct symbol *sym) +-{ +- if (!external_module) +- return 1; +- if (sym->module->from_dump) +- return 0; +- return 1; +-} +- + static void write_dump(const char *fname) + { + struct buffer buf = { }; +@@ -2446,7 +2433,7 @@ static void write_dump(const char *fname) + for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { + symbol = symbolhash[n]; + while (symbol) { +- if (dump_sym(symbol)) { ++ if (!symbol->module->from_dump) { + namespace = symbol->namespace; + buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n", + symbol->crc, symbol->name, +-- +2.30.2 + diff --git a/queue-5.12/kconfig-nconf-stop-endless-search-loops.patch b/queue-5.12/kconfig-nconf-stop-endless-search-loops.patch new file mode 100644 index 00000000000..44c0ae76c25 --- /dev/null +++ b/queue-5.12/kconfig-nconf-stop-endless-search-loops.patch @@ -0,0 +1,62 @@ +From 42cbad1bcd1eaaa2a17523eb204f7310fa14b25b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 09:28:03 +0200 +Subject: kconfig: nconf: stop endless search loops + +From: Mihai Moldovan + +[ Upstream commit 8c94b430b9f6213dec84e309bb480a71778c4213 ] + +If the user selects the very first entry in a page and performs a +search-up operation, or selects the very last entry in a page and +performs a search-down operation that will not succeed (e.g., via +[/]asdfzzz[Up Arrow]), nconf will never terminate searching the page. + +The reason is that in this case, the starting point will be set to -1 +or n, which is then translated into (n - 1) (i.e., the last entry of +the page) or 0 (i.e., the first entry of the page) and finally the +search begins. This continues to work fine until the index reaches 0 or +(n - 1), at which point it will be decremented to -1 or incremented to +n, but not checked against the starting point right away. Instead, it's +wrapped around to the bottom or top again, after which the starting +point check occurs... and naturally fails. + +My original implementation added another check for -1 before wrapping +the running index variable around, but Masahiro Yamada pointed out that +the actual issue is that the comparison point (starting point) exceeds +bounds (i.e., the [0,n-1] interval) in the first place and that, +instead, the starting point should be fixed. + +This has the welcome side-effect of also fixing the case where the +starting point was n while searching down, which also lead to an +infinite loop. + +OTOH, this code is now essentially all his work. + +Amazingly, nobody seems to have been hit by this for 11 years - or at +the very least nobody bothered to debug and fix this. + +Signed-off-by: Mihai Moldovan +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/kconfig/nconf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c +index e0f965529166..af814b39b876 100644 +--- a/scripts/kconfig/nconf.c ++++ b/scripts/kconfig/nconf.c +@@ -504,8 +504,8 @@ static int get_mext_match(const char *match_str, match_f flag) + else if (flag == FIND_NEXT_MATCH_UP) + --match_start; + ++ match_start = (match_start + items_num) % items_num; + index = match_start; +- index = (index + items_num) % items_num; + while (true) { + char *str = k_menu_items[index].str; + if (strcasestr(str, match_str) != NULL) +-- +2.30.2 + diff --git a/queue-5.12/kernel-kexec_file-fix-error-return-code-of-kexec_cal.patch b/queue-5.12/kernel-kexec_file-fix-error-return-code-of-kexec_cal.patch new file mode 100644 index 00000000000..76029fb490d --- /dev/null +++ b/queue-5.12/kernel-kexec_file-fix-error-return-code-of-kexec_cal.patch @@ -0,0 +1,45 @@ +From 7df062d9de46a7e151f8fba65129fb8ba607e380 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 May 2021 18:04:38 -0700 +Subject: kernel: kexec_file: fix error return code of + kexec_calculate_store_digests() + +From: Jia-Ju Bai + +[ Upstream commit 31d82c2c787d5cf65fedd35ebbc0c1bd95c1a679 ] + +When vzalloc() returns NULL to sha_regions, no error return code of +kexec_calculate_store_digests() is assigned. To fix this bug, ret is +assigned with -ENOMEM in this case. + +Link: https://lkml.kernel.org/r/20210309083904.24321-1-baijiaju1990@gmail.com +Fixes: a43cac0d9dc2 ("kexec: split kexec_file syscall code to kexec_file.c") +Signed-off-by: Jia-Ju Bai +Reported-by: TOTE Robot +Acked-by: Baoquan He +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/kexec_file.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c +index 5c3447cf7ad5..33400ff051a8 100644 +--- a/kernel/kexec_file.c ++++ b/kernel/kexec_file.c +@@ -740,8 +740,10 @@ static int kexec_calculate_store_digests(struct kimage *image) + + sha_region_sz = KEXEC_SEGMENT_MAX * sizeof(struct kexec_sha_region); + sha_regions = vzalloc(sha_region_sz); +- if (!sha_regions) ++ if (!sha_regions) { ++ ret = -ENOMEM; + goto out_free_desc; ++ } + + desc->tfm = tfm; + +-- +2.30.2 + diff --git a/queue-5.12/kernel-resource-make-walk_mem_res-find-all-busy-iore.patch b/queue-5.12/kernel-resource-make-walk_mem_res-find-all-busy-iore.patch new file mode 100644 index 00000000000..60daab7fd16 --- /dev/null +++ b/queue-5.12/kernel-resource-make-walk_mem_res-find-all-busy-iore.patch @@ -0,0 +1,76 @@ +From b34229343bbed603e2f7e1949f96c681d9230390 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 May 2021 18:05:16 -0700 +Subject: kernel/resource: make walk_mem_res() find all busy IORESOURCE_MEM + resources + +From: David Hildenbrand + +[ Upstream commit 3c9c797534364593b73ba6ab060a014af8934721 ] + +It used to be true that we can have system RAM (IORESOURCE_SYSTEM_RAM | +IORESOURCE_BUSY) only on the first level in the resource tree. However, +this is no longer holds for driver-managed system RAM (i.e., added via +dax/kmem and virtio-mem), which gets added on lower levels, for example, +inside device containers. + +IORESOURCE_SYSTEM_RAM is defined as IORESOURCE_MEM | IORESOURCE_SYSRAM and +just a special type of IORESOURCE_MEM. + +The function walk_mem_res() only considers the first level and is used in +arch/x86/mm/ioremap.c:__ioremap_check_mem() only. We currently fail to +identify System RAM added by dax/kmem and virtio-mem as +"IORES_MAP_SYSTEM_RAM", for example, allowing for remapping of such +"normal RAM" in __ioremap_caller(). + +Let's find all IORESOURCE_MEM | IORESOURCE_BUSY resources, making the +function behave similar to walk_system_ram_res(). + +Link: https://lkml.kernel.org/r/20210325115326.7826-3-david@redhat.com +Fixes: ebf71552bb0e ("virtio-mem: Add parent resource for all added "System RAM"") +Fixes: c221c0b0308f ("device-dax: "Hotplug" persistent memory for use like normal RAM") +Signed-off-by: David Hildenbrand +Reviewed-by: Dan Williams +Cc: Greg Kroah-Hartman +Cc: Dan Williams +Cc: Daniel Vetter +Cc: Andy Shevchenko +Cc: Mauro Carvalho Chehab +Cc: Dave Young +Cc: Baoquan He +Cc: Vivek Goyal +Cc: Dave Hansen +Cc: Keith Busch +Cc: Michal Hocko +Cc: Qian Cai +Cc: Oscar Salvador +Cc: Eric Biederman +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: Borislav Petkov +Cc: "H. Peter Anvin" +Cc: Tom Lendacky +Cc: Brijesh Singh +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/resource.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/resource.c b/kernel/resource.c +index 4efd6e912279..16e0c7e8ed24 100644 +--- a/kernel/resource.c ++++ b/kernel/resource.c +@@ -470,7 +470,7 @@ int walk_mem_res(u64 start, u64 end, void *arg, + { + unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY; + +- return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, true, ++ return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, false, + arg, func); + } + +-- +2.30.2 + diff --git a/queue-5.12/kernel-resource-make-walk_system_ram_res-find-all-bu.patch b/queue-5.12/kernel-resource-make-walk_system_ram_res-find-all-bu.patch new file mode 100644 index 00000000000..9b9ca67f65f --- /dev/null +++ b/queue-5.12/kernel-resource-make-walk_system_ram_res-find-all-bu.patch @@ -0,0 +1,106 @@ +From 9fdbc17f684227f26129ff9b62ae38989c526c7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 May 2021 18:05:12 -0700 +Subject: kernel/resource: make walk_system_ram_res() find all busy + IORESOURCE_SYSTEM_RAM resources + +From: David Hildenbrand + +[ Upstream commit 97f61c8f44ec9020708b97a51188170add4f3084 ] + +Patch series "kernel/resource: make walk_system_ram_res() and walk_mem_res() search the whole tree", v2. + +Playing with kdump+virtio-mem I noticed that kexec_file_load() does not +consider System RAM added via dax/kmem and virtio-mem when preparing the +elf header for kdump. Looking into the details, the logic used in +walk_system_ram_res() and walk_mem_res() seems to be outdated. + +walk_system_ram_range() already does the right thing, let's change +walk_system_ram_res() and walk_mem_res(), and clean up. + +Loading a kdump kernel via "kexec -p -s" ... will result in the kdump +kernel to also dump dax/kmem and virtio-mem added System RAM now. + +Note: kexec-tools on x86-64 also have to be updated to consider this +memory in the kexec_load() case when processing /proc/iomem. + +This patch (of 3): + +It used to be true that we can have system RAM (IORESOURCE_SYSTEM_RAM | +IORESOURCE_BUSY) only on the first level in the resource tree. However, +this is no longer holds for driver-managed system RAM (i.e., added via +dax/kmem and virtio-mem), which gets added on lower levels, for example, +inside device containers. + +We have two users of walk_system_ram_res(), which currently only +consideres the first level: + +a) kernel/kexec_file.c:kexec_walk_resources() -- We properly skip + IORESOURCE_SYSRAM_DRIVER_MANAGED resources via + locate_mem_hole_callback(), so even after this change, we won't be + placing kexec images onto dax/kmem and virtio-mem added memory. No + change. + +b) arch/x86/kernel/crash.c:fill_up_crash_elf_data() -- we're currently + not adding relevant ranges to the crash elf header, resulting in them + not getting dumped via kdump. + +This change fixes loading a crashkernel via kexec_file_load() and +including dax/kmem and virtio-mem added System RAM in the crashdump on +x86-64. Note that e.g,, arm64 relies on memblock data and, therefore, +always considers all added System RAM already. + +Let's find all IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY resources, making +the function behave like walk_system_ram_range(). + +Link: https://lkml.kernel.org/r/20210325115326.7826-1-david@redhat.com +Link: https://lkml.kernel.org/r/20210325115326.7826-2-david@redhat.com +Fixes: ebf71552bb0e ("virtio-mem: Add parent resource for all added "System RAM"") +Fixes: c221c0b0308f ("device-dax: "Hotplug" persistent memory for use like normal RAM") +Signed-off-by: David Hildenbrand +Reviewed-by: Dan Williams +Acked-by: Baoquan He +Cc: Greg Kroah-Hartman +Cc: Dan Williams +Cc: Daniel Vetter +Cc: Andy Shevchenko +Cc: Mauro Carvalho Chehab +Cc: Dave Young +Cc: Baoquan He +Cc: Vivek Goyal +Cc: Dave Hansen +Cc: Keith Busch +Cc: Michal Hocko +Cc: Qian Cai +Cc: Oscar Salvador +Cc: Eric Biederman +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: Borislav Petkov +Cc: "H. Peter Anvin" +Cc: Tom Lendacky +Cc: Brijesh Singh +Cc: "Eric W. Biederman" +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/resource.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/resource.c b/kernel/resource.c +index 627e61b0c124..4efd6e912279 100644 +--- a/kernel/resource.c ++++ b/kernel/resource.c +@@ -457,7 +457,7 @@ int walk_system_ram_res(u64 start, u64 end, void *arg, + { + unsigned long flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; + +- return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, true, ++ return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, false, + arg, func); + } + +-- +2.30.2 + diff --git a/queue-5.12/kfence-await-for-allocation-using-wait_event.patch b/queue-5.12/kfence-await-for-allocation-using-wait_event.patch new file mode 100644 index 00000000000..af84f693f69 --- /dev/null +++ b/queue-5.12/kfence-await-for-allocation-using-wait_event.patch @@ -0,0 +1,166 @@ +From 26918cdb2ab56b4056a14d4156096ec76a4dcd6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 May 2021 18:40:21 -0700 +Subject: kfence: await for allocation using wait_event + +From: Marco Elver + +[ Upstream commit 407f1d8c1b5f3ec66a6a3eb835d3b81c76440f4e ] + +Patch series "kfence: optimize timer scheduling", v2. + +We have observed that mostly-idle systems with KFENCE enabled wake up +otherwise idle CPUs, preventing such to enter a lower power state. +Debugging revealed that KFENCE spends too much active time in +toggle_allocation_gate(). + +While the first version of KFENCE was using all the right bits to be +scheduling optimal, and thus power efficient, by simply using wait_event() ++ wake_up(), that code was unfortunately removed. + +As KFENCE was exposed to various different configs and tests, the +scheduling optimal code slowly disappeared. First because of hung task +warnings, and finally because of deadlocks when an allocation is made by +timer code with debug objects enabled. Clearly, the "fixes" were not too +friendly for devices that want to be power efficient. + +Therefore, let's try a little harder to fix the hung task and deadlock +problems that we have with wait_event() + wake_up(), while remaining as +scheduling friendly and power efficient as possible. + +Crucially, we need to defer the wake_up() to an irq_work, avoiding any +potential for deadlock. + +The result with this series is that on the devices where we observed a +power regression, power usage returns back to baseline levels. + +This patch (of 3): + +On mostly-idle systems, we have observed that toggle_allocation_gate() is +a cause of frequent wake-ups, preventing an otherwise idle CPU to go into +a lower power state. + +A late change in KFENCE's development, due to a potential deadlock [1], +required changing the scheduling-friendly wait_event_timeout() and +wake_up() to an open-coded wait-loop using schedule_timeout(). [1] +https://lkml.kernel.org/r/000000000000c0645805b7f982e4@google.com + +To avoid unnecessary wake-ups, switch to using wait_event_timeout(). + +Unfortunately, we still cannot use a version with direct wake_up() in +__kfence_alloc() due to the same potential for deadlock as in [1]. +Instead, add a level of indirection via an irq_work that is scheduled if +we determine that the kfence_timer requires a wake_up(). + +Link: https://lkml.kernel.org/r/20210421105132.3965998-1-elver@google.com +Link: https://lkml.kernel.org/r/20210421105132.3965998-2-elver@google.com +Fixes: 0ce20dd84089 ("mm: add Kernel Electric-Fence infrastructure") +Signed-off-by: Marco Elver +Cc: Alexander Potapenko +Cc: Dmitry Vyukov +Cc: Jann Horn +Cc: Mark Rutland +Cc: Hillf Danton +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + lib/Kconfig.kfence | 1 + + mm/kfence/core.c | 45 +++++++++++++++++++++++++++++---------------- + 2 files changed, 30 insertions(+), 16 deletions(-) + +diff --git a/lib/Kconfig.kfence b/lib/Kconfig.kfence +index 78f50ccb3b45..e641add33947 100644 +--- a/lib/Kconfig.kfence ++++ b/lib/Kconfig.kfence +@@ -7,6 +7,7 @@ menuconfig KFENCE + bool "KFENCE: low-overhead sampling-based memory safety error detector" + depends on HAVE_ARCH_KFENCE && (SLAB || SLUB) + select STACKTRACE ++ select IRQ_WORK + help + KFENCE is a low-overhead sampling-based detector of heap out-of-bounds + access, use-after-free, and invalid-free errors. KFENCE is designed +diff --git a/mm/kfence/core.c b/mm/kfence/core.c +index d53c91f881a4..f0be2c5038b5 100644 +--- a/mm/kfence/core.c ++++ b/mm/kfence/core.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -586,6 +587,17 @@ late_initcall(kfence_debugfs_init); + + /* === Allocation Gate Timer ================================================ */ + ++#ifdef CONFIG_KFENCE_STATIC_KEYS ++/* Wait queue to wake up allocation-gate timer task. */ ++static DECLARE_WAIT_QUEUE_HEAD(allocation_wait); ++ ++static void wake_up_kfence_timer(struct irq_work *work) ++{ ++ wake_up(&allocation_wait); ++} ++static DEFINE_IRQ_WORK(wake_up_kfence_timer_work, wake_up_kfence_timer); ++#endif ++ + /* + * Set up delayed work, which will enable and disable the static key. We need to + * use a work queue (rather than a simple timer), since enabling and disabling a +@@ -603,25 +615,13 @@ static void toggle_allocation_gate(struct work_struct *work) + if (!READ_ONCE(kfence_enabled)) + return; + +- /* Enable static key, and await allocation to happen. */ + atomic_set(&kfence_allocation_gate, 0); + #ifdef CONFIG_KFENCE_STATIC_KEYS ++ /* Enable static key, and await allocation to happen. */ + static_branch_enable(&kfence_allocation_key); +- /* +- * Await an allocation. Timeout after 1 second, in case the kernel stops +- * doing allocations, to avoid stalling this worker task for too long. +- */ +- { +- unsigned long end_wait = jiffies + HZ; +- +- do { +- set_current_state(TASK_UNINTERRUPTIBLE); +- if (atomic_read(&kfence_allocation_gate) != 0) +- break; +- schedule_timeout(1); +- } while (time_before(jiffies, end_wait)); +- __set_current_state(TASK_RUNNING); +- } ++ ++ wait_event_timeout(allocation_wait, atomic_read(&kfence_allocation_gate), HZ); ++ + /* Disable static key and reset timer. */ + static_branch_disable(&kfence_allocation_key); + #endif +@@ -728,6 +728,19 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags) + */ + if (atomic_read(&kfence_allocation_gate) || atomic_inc_return(&kfence_allocation_gate) > 1) + return NULL; ++#ifdef CONFIG_KFENCE_STATIC_KEYS ++ /* ++ * waitqueue_active() is fully ordered after the update of ++ * kfence_allocation_gate per atomic_inc_return(). ++ */ ++ if (waitqueue_active(&allocation_wait)) { ++ /* ++ * Calling wake_up() here may deadlock when allocations happen ++ * from within timer code. Use an irq_work to defer it. ++ */ ++ irq_work_queue(&wake_up_kfence_timer_work); ++ } ++#endif + + if (!READ_ONCE(kfence_enabled)) + return NULL; +-- +2.30.2 + diff --git a/queue-5.12/khugepaged-fix-wrong-result-value-for-trace_mm_colla.patch b/queue-5.12/khugepaged-fix-wrong-result-value-for-trace_mm_colla.patch new file mode 100644 index 00000000000..34b0d44e230 --- /dev/null +++ b/queue-5.12/khugepaged-fix-wrong-result-value-for-trace_mm_colla.patch @@ -0,0 +1,63 @@ +From 9989b7e2b84947d53ebb4335c33c907aac7c5bb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 May 2021 18:33:46 -0700 +Subject: khugepaged: fix wrong result value for + trace_mm_collapse_huge_page_isolate() + +From: Miaohe Lin + +[ Upstream commit 74e579bf231a337ab3786d59e64bc94f45ca7b3f ] + +In writable and !referenced case, the result value should be +SCAN_LACK_REFERENCED_PAGE for trace_mm_collapse_huge_page_isolate() +instead of default 0 (SCAN_FAIL) here. + +Link: https://lkml.kernel.org/r/20210306032947.35921-5-linmiaohe@huawei.com +Fixes: 7d2eba0557c1 ("mm: add tracepoint for scanning pages") +Signed-off-by: Miaohe Lin +Acked-by: Kirill A. Shutemov +Cc: Dan Carpenter +Cc: Ebru Akagunduz +Cc: Mike Kravetz +Cc: Rik van Riel +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/khugepaged.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/mm/khugepaged.c b/mm/khugepaged.c +index a7d6cb912b05..2680d5ffee7f 100644 +--- a/mm/khugepaged.c ++++ b/mm/khugepaged.c +@@ -716,17 +716,17 @@ next: + if (pte_write(pteval)) + writable = true; + } +- if (likely(writable)) { +- if (likely(referenced)) { +- result = SCAN_SUCCEED; +- trace_mm_collapse_huge_page_isolate(page, none_or_zero, +- referenced, writable, result); +- return 1; +- } +- } else { ++ ++ if (unlikely(!writable)) { + result = SCAN_PAGE_RO; ++ } else if (unlikely(!referenced)) { ++ result = SCAN_LACK_REFERENCED_PAGE; ++ } else { ++ result = SCAN_SUCCEED; ++ trace_mm_collapse_huge_page_isolate(page, none_or_zero, ++ referenced, writable, result); ++ return 1; + } +- + out: + release_pte_pages(pte, _pte, compound_pagelist); + trace_mm_collapse_huge_page_isolate(page, none_or_zero, +-- +2.30.2 + diff --git a/queue-5.12/ksm-fix-potential-missing-rmap_item-for-stable_node.patch b/queue-5.12/ksm-fix-potential-missing-rmap_item-for-stable_node.patch new file mode 100644 index 00000000000..a8b20670d3f --- /dev/null +++ b/queue-5.12/ksm-fix-potential-missing-rmap_item-for-stable_node.patch @@ -0,0 +1,57 @@ +From bbf2ed6ec23082f4bdfce0a5b62436e71007d043 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 May 2021 18:37:45 -0700 +Subject: ksm: fix potential missing rmap_item for stable_node + +From: Miaohe Lin + +[ Upstream commit c89a384e2551c692a9fe60d093fd7080f50afc51 ] + +When removing rmap_item from stable tree, STABLE_FLAG of rmap_item is +cleared with head reserved. So the following scenario might happen: For +ksm page with rmap_item1: + +cmp_and_merge_page + stable_node->head = &migrate_nodes; + remove_rmap_item_from_tree, but head still equal to stable_node; + try_to_merge_with_ksm_page failed; + return; + +For the same ksm page with rmap_item2, stable node migration succeed this +time. The stable_node->head does not equal to migrate_nodes now. For ksm +page with rmap_item1 again: + +cmp_and_merge_page + stable_node->head != &migrate_nodes && rmap_item->head == stable_node + return; + +We would miss the rmap_item for stable_node and might result in failed +rmap_walk_ksm(). Fix this by set rmap_item->head to NULL when rmap_item +is removed from stable tree. + +Link: https://lkml.kernel.org/r/20210330140228.45635-5-linmiaohe@huawei.com +Fixes: 4146d2d673e8 ("ksm: make !merge_across_nodes migration safe") +Signed-off-by: Miaohe Lin +Cc: Hugh Dickins +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/ksm.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/mm/ksm.c b/mm/ksm.c +index 9694ee2c71de..b32391ccf6d5 100644 +--- a/mm/ksm.c ++++ b/mm/ksm.c +@@ -794,6 +794,7 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item) + stable_node->rmap_hlist_len--; + + put_anon_vma(rmap_item->anon_vma); ++ rmap_item->head = NULL; + rmap_item->address &= PAGE_MASK; + + } else if (rmap_item->address & UNSTABLE_FLAG) { +-- +2.30.2 + diff --git a/queue-5.12/leds-lgm-fix-gpiolib-dependency.patch b/queue-5.12/leds-lgm-fix-gpiolib-dependency.patch new file mode 100644 index 00000000000..ceba537e16c --- /dev/null +++ b/queue-5.12/leds-lgm-fix-gpiolib-dependency.patch @@ -0,0 +1,53 @@ +From 643488ed9650d349983325a6e8dbeb8224670f27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Mar 2021 16:30:46 +0100 +Subject: leds: lgm: fix gpiolib dependency + +From: Arnd Bergmann + +[ Upstream commit 34731ed13e8a8ca95fa0dca466537396b5f2d1af ] + +Without gpiolib, the driver fails to build: + + drivers/leds/blink/leds-lgm-sso.c:123:19: error: field has incomplete type 'struct gpio_chip' + struct gpio_chip chip; + ^ + include/linux/gpio.h:107:8: note: forward declaration of 'struct gpio_chip' + struct gpio_chip; + ^ + drivers/leds/blink/leds-lgm-sso.c:263:3: error: implicit declaration of function 'gpiod_set_value' [-Werror,-Wimplicit-function-declaration] + gpiod_set_value(led->gpiod, val); + ^ + drivers/leds/blink/leds-lgm-sso.c:263:3: note: did you mean 'gpio_set_value'? + include/linux/gpio.h:168:20: note: 'gpio_set_value' declared here + static inline void gpio_set_value(unsigned gpio, int value) + ^ + drivers/leds/blink/leds-lgm-sso.c:345:3: error: implicit declaration of function 'gpiod_set_value' [-Werror,-Wimplicit-function-declaration] + gpiod_set_value(led->gpiod, 1); + ^ + +Add the dependency in Kconfig. + +Fixes: c3987cd2bca3 ("leds: lgm: Add LED controller driver for LGM SoC") +Signed-off-by: Arnd Bergmann +Signed-off-by: Pavel Machek +Signed-off-by: Sasha Levin +--- + drivers/leds/blink/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/leds/blink/Kconfig b/drivers/leds/blink/Kconfig +index 265b53476a80..6dedc58c47b3 100644 +--- a/drivers/leds/blink/Kconfig ++++ b/drivers/leds/blink/Kconfig +@@ -9,6 +9,7 @@ if LEDS_BLINK + + config LEDS_BLINK_LGM + tristate "LED support for Intel LGM SoC series" ++ depends on GPIOLIB + depends on LEDS_CLASS + depends on MFD_SYSCON + depends on OF +-- +2.30.2 + diff --git a/queue-5.12/libbpf-fix-signed-overflow-in-ringbuf_process_ring.patch b/queue-5.12/libbpf-fix-signed-overflow-in-ringbuf_process_ring.patch new file mode 100644 index 00000000000..43cf1429416 --- /dev/null +++ b/queue-5.12/libbpf-fix-signed-overflow-in-ringbuf_process_ring.patch @@ -0,0 +1,106 @@ +From f51cfcbb00e7086873571ada8d978c441ead6260 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 13:05:10 +0000 +Subject: libbpf: Fix signed overflow in ringbuf_process_ring + +From: Brendan Jackman + +[ Upstream commit 2a30f9440640c418bcfbea9b2b344d268b58e0a2 ] + +One of our benchmarks running in (Google-internal) CI pushes data +through the ringbuf faster htan than userspace is able to consume +it. In this case it seems we're actually able to get >INT_MAX entries +in a single ring_buffer__consume() call. ASAN detected that cnt +overflows in this case. + +Fix by using 64-bit counter internally and then capping the result to +INT_MAX before converting to the int return type. Do the same for +the ring_buffer__poll(). + +Fixes: bf99c936f947 (libbpf: Add BPF ring buffer support) +Signed-off-by: Brendan Jackman +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20210429130510.1621665-1-jackmanb@google.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/ringbuf.c | 30 +++++++++++++++++++++--------- + 1 file changed, 21 insertions(+), 9 deletions(-) + +diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c +index e7a8d847161f..1d80ad4e0de8 100644 +--- a/tools/lib/bpf/ringbuf.c ++++ b/tools/lib/bpf/ringbuf.c +@@ -202,9 +202,11 @@ static inline int roundup_len(__u32 len) + return (len + 7) / 8 * 8; + } + +-static int ringbuf_process_ring(struct ring* r) ++static int64_t ringbuf_process_ring(struct ring* r) + { +- int *len_ptr, len, err, cnt = 0; ++ int *len_ptr, len, err; ++ /* 64-bit to avoid overflow in case of extreme application behavior */ ++ int64_t cnt = 0; + unsigned long cons_pos, prod_pos; + bool got_new_data; + void *sample; +@@ -244,12 +246,14 @@ done: + } + + /* Consume available ring buffer(s) data without event polling. +- * Returns number of records consumed across all registered ring buffers, or +- * negative number if any of the callbacks return error. ++ * Returns number of records consumed across all registered ring buffers (or ++ * INT_MAX, whichever is less), or negative number if any of the callbacks ++ * return error. + */ + int ring_buffer__consume(struct ring_buffer *rb) + { +- int i, err, res = 0; ++ int64_t err, res = 0; ++ int i; + + for (i = 0; i < rb->ring_cnt; i++) { + struct ring *ring = &rb->rings[i]; +@@ -259,18 +263,24 @@ int ring_buffer__consume(struct ring_buffer *rb) + return err; + res += err; + } ++ if (res > INT_MAX) ++ return INT_MAX; + return res; + } + + /* Poll for available data and consume records, if any are available. +- * Returns number of records consumed, or negative number, if any of the +- * registered callbacks returned error. ++ * Returns number of records consumed (or INT_MAX, whichever is less), or ++ * negative number, if any of the registered callbacks returned error. + */ + int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms) + { +- int i, cnt, err, res = 0; ++ int i, cnt; ++ int64_t err, res = 0; + + cnt = epoll_wait(rb->epoll_fd, rb->events, rb->ring_cnt, timeout_ms); ++ if (cnt < 0) ++ return -errno; ++ + for (i = 0; i < cnt; i++) { + __u32 ring_id = rb->events[i].data.fd; + struct ring *ring = &rb->rings[ring_id]; +@@ -280,7 +290,9 @@ int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms) + return err; + res += err; + } +- return cnt < 0 ? -errno : res; ++ if (res > INT_MAX) ++ return INT_MAX; ++ return res; + } + + /* Get an fd that can be used to sleep until data is available in the ring(s) */ +-- +2.30.2 + diff --git a/queue-5.12/mac80211-clear-the-beacon-s-crc-after-channel-switch.patch b/queue-5.12/mac80211-clear-the-beacon-s-crc-after-channel-switch.patch new file mode 100644 index 00000000000..bff5752c043 --- /dev/null +++ b/queue-5.12/mac80211-clear-the-beacon-s-crc-after-channel-switch.patch @@ -0,0 +1,52 @@ +From a44526d78a23e64d581ee69e73bbacb68384c0da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Apr 2021 14:31:25 +0200 +Subject: mac80211: clear the beacon's CRC after channel switch + +From: Emmanuel Grumbach + +[ Upstream commit d6843d1ee283137723b4a8c76244607ce6db1951 ] + +After channel switch, we should consider any beacon with a +CSA IE as a new switch. If the CSA IE is a leftover from +before the switch that the AP forgot to remove, we'll get +a CSA-to-Self. + +This caused issues in iwlwifi where the firmware saw a beacon +with a CSA-to-Self with mode = 1 on the new channel after a +switch. The firmware considered this a new switch and closed +its queues. Since the beacon didn't change between before and +after the switch, we wouldn't handle it (the CRC is the same) +and we wouldn't let the firmware open its queues again or +disconnect if the CSA IE stays for too long. + +Clear the CRC valid state after we switch to make sure that +we handle the beacon and handle the CSA IE as required. + +Signed-off-by: Emmanuel Grumbach +Link: https://lore.kernel.org/r/20210408143124.b9e68aa98304.I465afb55ca2c7d59f7bf610c6046a1fd732b4c28@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 96f487fc0071..4a8f1b8ce768 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1295,6 +1295,11 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata) + + sdata->vif.csa_active = false; + ifmgd->csa_waiting_bcn = false; ++ /* ++ * If the CSA IE is still present on the beacon after the switch, ++ * we need to consider it as a new CSA (possibly to self). ++ */ ++ ifmgd->beacon_crc_valid = false; + + ret = drv_post_channel_switch(sdata); + if (ret) { +-- +2.30.2 + diff --git a/queue-5.12/mac80211-properly-drop-the-connection-in-case-of-inv.patch b/queue-5.12/mac80211-properly-drop-the-connection-in-case-of-inv.patch new file mode 100644 index 00000000000..0cb640a166c --- /dev/null +++ b/queue-5.12/mac80211-properly-drop-the-connection-in-case-of-inv.patch @@ -0,0 +1,46 @@ +From d5cd41d1d5d2a9a5d9417d63817bf399109d3760 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Apr 2021 12:40:16 +0300 +Subject: mac80211: properly drop the connection in case of invalid CSA IE + +From: Emmanuel Grumbach + +[ Upstream commit 253907ab8bc0818639af382f6398810fa1f022b3 ] + +In case the frequency is invalid, ieee80211_parse_ch_switch_ie +will fail and we may not even reach the check in +ieee80211_sta_process_chanswitch. Drop the connection +in case ieee80211_parse_ch_switch_ie failed, but still +take into account the CSA mode to remember not to send +a deauth frame in case if it is forbidden to. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/iwlwifi.20210409123755.34712ef96a0a.I75d7ad7f1d654e8b0aa01cd7189ff00a510512b3@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 4a8f1b8ce768..0fe91dc9817e 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1405,11 +1405,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, + ch_switch.delay = csa_ie.max_switch_time; + } + +- if (res < 0) { +- ieee80211_queue_work(&local->hw, +- &ifmgd->csa_connection_drop_work); +- return; +- } ++ if (res < 0) ++ goto lock_and_drop_connection; + + if (beacon && sdata->vif.csa_active && !ifmgd->csa_waiting_bcn) { + if (res) +-- +2.30.2 + diff --git a/queue-5.12/mac80211-set-priority-and-queue-mapping-for-injected.patch b/queue-5.12/mac80211-set-priority-and-queue-mapping-for-injected.patch new file mode 100644 index 00000000000..0da1fb70066 --- /dev/null +++ b/queue-5.12/mac80211-set-priority-and-queue-mapping-for-injected.patch @@ -0,0 +1,68 @@ +From 8a33eca4086f5b073acfc583033c79015287a54b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Apr 2021 18:44:55 +0200 +Subject: mac80211: Set priority and queue mapping for injected frames + +From: Johan Almbladh + +[ Upstream commit 96a7109a16665255b65d021e24141c2edae0e202 ] + +Some drivers, for example mt76, use the skb priority field, and +expects that to be consistent with the skb queue mapping. On some +frame injection code paths that was not true, and it broke frame +injection. Now the skb queue mapping is set according to the skb +priority value when the frame is injected. The skb priority value +is also derived from the frame data for all frame types, as it +was done prior to commit dbd50a851c50 (only allocate one queue +when using iTXQs). Fixes frame injection with the mt76 driver on +MT7610E chipset. + +Signed-off-by: Johan Almbladh +Link: https://lore.kernel.org/r/20210401164455.978245-1-johan.almbladh@anyfinetworks.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/tx.c | 20 +++++++++----------- + 1 file changed, 9 insertions(+), 11 deletions(-) + +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 3b3bcefbf657..28422d687096 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -2267,17 +2267,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, + payload[7]); + } + +- /* Initialize skb->priority for QoS frames. If the DONT_REORDER flag +- * is set, stick to the default value for skb->priority to assure +- * frames injected with this flag are not reordered relative to each +- * other. +- */ +- if (ieee80211_is_data_qos(hdr->frame_control) && +- !(info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER)) { +- u8 *p = ieee80211_get_qos_ctl(hdr); +- skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; +- } +- + rcu_read_lock(); + + /* +@@ -2341,6 +2330,15 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, + + info->band = chandef->chan->band; + ++ /* Initialize skb->priority according to frame type and TID class, ++ * with respect to the sub interface that the frame will actually ++ * be transmitted on. If the DONT_REORDER flag is set, the original ++ * skb-priority is preserved to assure frames injected with this ++ * flag are not reordered relative to each other. ++ */ ++ ieee80211_select_queue_80211(sdata, skb, hdr); ++ skb_set_queue_mapping(skb, ieee80211_ac_from_tid(skb->priority)); ++ + /* remove the injection radiotap header */ + skb_pull(skb, len_rthdr); + +-- +2.30.2 + diff --git a/queue-5.12/mips-loongson64-use-_cache_uncached-instead-of-_cach.patch b/queue-5.12/mips-loongson64-use-_cache_uncached-instead-of-_cach.patch new file mode 100644 index 00000000000..66d091f6b4c --- /dev/null +++ b/queue-5.12/mips-loongson64-use-_cache_uncached-instead-of-_cach.patch @@ -0,0 +1,68 @@ +From 381acc0edf61850b277ce240be125f873b895f62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Apr 2021 17:25:12 +0800 +Subject: MIPS: Loongson64: Use _CACHE_UNCACHED instead of + _CACHE_UNCACHED_ACCELERATED + +From: Tiezhu Yang + +[ Upstream commit 5e65c52ec716af6e8f51dacdaeb4a4d872249af1 ] + +Loongson64 processors have a writecombine issue that maybe failed to +write back framebuffer used with ATI Radeon or AMD GPU at times, after +commit 8a08e50cee66 ("drm: Permit video-buffers writecombine mapping +for MIPS"), there exists some errors such as blurred screen and lockup, +and so on. + +[ 60.958721] radeon 0000:03:00.0: ring 0 stalled for more than 10079msec +[ 60.965315] radeon 0000:03:00.0: GPU lockup (current fence id 0x0000000000000112 last fence id 0x000000000000011d on ring 0) +[ 60.976525] radeon 0000:03:00.0: ring 3 stalled for more than 10086msec +[ 60.983156] radeon 0000:03:00.0: GPU lockup (current fence id 0x0000000000000374 last fence id 0x00000000000003a8 on ring 3) + +As discussed earlier [1], it might be better to disable writecombine +on the CPU detection side because the root cause is unknown now. + +Actually, this patch is a temporary solution to just make it work well, +it is not a proper and final solution, I hope someone will have a better +solution to fix this issue in the future. + +[1] https://lore.kernel.org/patchwork/patch/1285542/ + +Signed-off-by: Tiezhu Yang +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/kernel/cpu-probe.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c +index b71892064f27..0ef240adefb5 100644 +--- a/arch/mips/kernel/cpu-probe.c ++++ b/arch/mips/kernel/cpu-probe.c +@@ -1752,7 +1752,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) + set_isa(c, MIPS_CPU_ISA_M64R2); + break; + } +- c->writecombine = _CACHE_UNCACHED_ACCELERATED; + c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_EXT | + MIPS_ASE_LOONGSON_EXT2); + break; +@@ -1782,7 +1781,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) + * register, we correct it here. + */ + c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE; +- c->writecombine = _CACHE_UNCACHED_ACCELERATED; + c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM | + MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2); + c->ases &= ~MIPS_ASE_VZ; /* VZ of Loongson-3A2000/3000 is incomplete */ +@@ -1793,7 +1791,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) + set_elf_platform(cpu, "loongson3a"); + set_isa(c, MIPS_CPU_ISA_M64R2); + decode_cpucfg(c); +- c->writecombine = _CACHE_UNCACHED_ACCELERATED; + break; + default: + panic("Unknown Loongson Processor ID!"); +-- +2.30.2 + diff --git a/queue-5.12/mm-gup-check-every-subpage-of-a-compound-page-during.patch b/queue-5.12/mm-gup-check-every-subpage-of-a-compound-page-during.patch new file mode 100644 index 00000000000..2de6f0dfa48 --- /dev/null +++ b/queue-5.12/mm-gup-check-every-subpage-of-a-compound-page-during.patch @@ -0,0 +1,108 @@ +From 5d613bce4f128b1f22345975b10bae9dedfc7b08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 May 2021 18:38:42 -0700 +Subject: mm/gup: check every subpage of a compound page during isolation + +From: Pavel Tatashin + +[ Upstream commit 83c02c23d0747a7bdcd71f99a538aacec94b146c ] + +When pages are isolated in check_and_migrate_movable_pages() we skip +compound number of pages at a time. However, as Jason noted, it is not +necessary correct that pages[i] corresponds to the pages that we +skipped. This is because it is possible that the addresses in this +range had split_huge_pmd()/split_huge_pud(), and these functions do not +update the compound page metadata. + +The problem can be reproduced if something like this occurs: + +1. User faulted huge pages. +2. split_huge_pmd() was called for some reason +3. User has unmapped some sub-pages in the range +4. User tries to longterm pin the addresses. + +The resulting pages[i] might end-up having pages which are not compound +size page aligned. + +Link: https://lkml.kernel.org/r/20210215161349.246722-3-pasha.tatashin@soleen.com +Fixes: aa712399c1e8 ("mm/gup: speed up check_and_migrate_cma_pages() on huge page") +Signed-off-by: Pavel Tatashin +Reported-by: Jason Gunthorpe +Reviewed-by: Jason Gunthorpe +Cc: Dan Williams +Cc: David Hildenbrand +Cc: David Rientjes +Cc: Ingo Molnar +Cc: Ira Weiny +Cc: James Morris +Cc: Jason Gunthorpe +Cc: John Hubbard +Cc: Joonsoo Kim +Cc: Matthew Wilcox +Cc: Mel Gorman +Cc: Michal Hocko +Cc: Michal Hocko +Cc: Mike Kravetz +Cc: Oscar Salvador +Cc: Peter Zijlstra +Cc: Sasha Levin +Cc: Steven Rostedt (VMware) +Cc: Tyler Hicks +Cc: Vlastimil Babka +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/gup.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +diff --git a/mm/gup.c b/mm/gup.c +index ef7d2da9f03f..6530672131db 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -1552,26 +1552,23 @@ static long check_and_migrate_cma_pages(struct mm_struct *mm, + unsigned int gup_flags) + { + unsigned long i; +- unsigned long step; + bool drain_allow = true; + bool migrate_allow = true; + LIST_HEAD(cma_page_list); + long ret = nr_pages; ++ struct page *prev_head, *head; + struct migration_target_control mtc = { + .nid = NUMA_NO_NODE, + .gfp_mask = GFP_USER | __GFP_MOVABLE | __GFP_NOWARN, + }; + + check_again: +- for (i = 0; i < nr_pages;) { +- +- struct page *head = compound_head(pages[i]); +- +- /* +- * gup may start from a tail page. Advance step by the left +- * part. +- */ +- step = compound_nr(head) - (pages[i] - head); ++ prev_head = NULL; ++ for (i = 0; i < nr_pages; i++) { ++ head = compound_head(pages[i]); ++ if (head == prev_head) ++ continue; ++ prev_head = head; + /* + * If we get a page from the CMA zone, since we are going to + * be pinning these entries, we might as well move them out +@@ -1595,8 +1592,6 @@ check_again: + } + } + } +- +- i += step; + } + + if (!list_empty(&cma_page_list)) { +-- +2.30.2 + diff --git a/queue-5.12/mm-gup-check-for-isolation-errors.patch b/queue-5.12/mm-gup-check-for-isolation-errors.patch new file mode 100644 index 00000000000..cc4e9032a5f --- /dev/null +++ b/queue-5.12/mm-gup-check-for-isolation-errors.patch @@ -0,0 +1,155 @@ +From 62a1628f8ae226e5ab5890f5e51b8bb37f5ad8f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 May 2021 18:38:49 -0700 +Subject: mm/gup: check for isolation errors + +From: Pavel Tatashin + +[ Upstream commit 6e7f34ebb8d25d71ce7f4580ba3cbfc10b895580 ] + +It is still possible that we pin movable CMA pages if there are +isolation errors and cma_page_list stays empty when we check again. + +Check for isolation errors, and return success only when there are no +isolation errors, and cma_page_list is empty after checking. + +Because isolation errors are transient, we retry indefinitely. + +Link: https://lkml.kernel.org/r/20210215161349.246722-5-pasha.tatashin@soleen.com +Fixes: 9a4e9f3b2d73 ("mm: update get_user_pages_longterm to migrate pages allocated from CMA region") +Signed-off-by: Pavel Tatashin +Reviewed-by: Jason Gunthorpe +Cc: Dan Williams +Cc: David Hildenbrand +Cc: David Rientjes +Cc: Ingo Molnar +Cc: Ira Weiny +Cc: James Morris +Cc: Jason Gunthorpe +Cc: John Hubbard +Cc: Joonsoo Kim +Cc: Matthew Wilcox +Cc: Mel Gorman +Cc: Michal Hocko +Cc: Michal Hocko +Cc: Mike Kravetz +Cc: Oscar Salvador +Cc: Peter Zijlstra +Cc: Sasha Levin +Cc: Steven Rostedt (VMware) +Cc: Tyler Hicks +Cc: Vlastimil Babka +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/gup.c | 60 ++++++++++++++++++++++++++++++++------------------------ + 1 file changed, 34 insertions(+), 26 deletions(-) + +diff --git a/mm/gup.c b/mm/gup.c +index 2b48c65e27cc..333f5dfd8942 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -1551,8 +1551,8 @@ static long check_and_migrate_cma_pages(struct mm_struct *mm, + struct vm_area_struct **vmas, + unsigned int gup_flags) + { +- unsigned long i; +- bool drain_allow = true; ++ unsigned long i, isolation_error_count; ++ bool drain_allow; + LIST_HEAD(cma_page_list); + long ret = nr_pages; + struct page *prev_head, *head; +@@ -1563,6 +1563,8 @@ static long check_and_migrate_cma_pages(struct mm_struct *mm, + + check_again: + prev_head = NULL; ++ isolation_error_count = 0; ++ drain_allow = true; + for (i = 0; i < nr_pages; i++) { + head = compound_head(pages[i]); + if (head == prev_head) +@@ -1574,25 +1576,35 @@ check_again: + * of the CMA zone if possible. + */ + if (is_migrate_cma_page(head)) { +- if (PageHuge(head)) +- isolate_huge_page(head, &cma_page_list); +- else { ++ if (PageHuge(head)) { ++ if (!isolate_huge_page(head, &cma_page_list)) ++ isolation_error_count++; ++ } else { + if (!PageLRU(head) && drain_allow) { + lru_add_drain_all(); + drain_allow = false; + } + +- if (!isolate_lru_page(head)) { +- list_add_tail(&head->lru, &cma_page_list); +- mod_node_page_state(page_pgdat(head), +- NR_ISOLATED_ANON + +- page_is_file_lru(head), +- thp_nr_pages(head)); ++ if (isolate_lru_page(head)) { ++ isolation_error_count++; ++ continue; + } ++ list_add_tail(&head->lru, &cma_page_list); ++ mod_node_page_state(page_pgdat(head), ++ NR_ISOLATED_ANON + ++ page_is_file_lru(head), ++ thp_nr_pages(head)); + } + } + } + ++ /* ++ * If list is empty, and no isolation errors, means that all pages are ++ * in the correct zone. ++ */ ++ if (list_empty(&cma_page_list) && !isolation_error_count) ++ return ret; ++ + if (!list_empty(&cma_page_list)) { + /* + * drop the above get_user_pages reference. +@@ -1612,23 +1624,19 @@ check_again: + return ret > 0 ? -ENOMEM : ret; + } + +- /* +- * We did migrate all the pages, Try to get the page references +- * again migrating any new CMA pages which we failed to isolate +- * earlier. +- */ +- ret = __get_user_pages_locked(mm, start, nr_pages, +- pages, vmas, NULL, +- gup_flags); +- +- if (ret > 0) { +- nr_pages = ret; +- drain_allow = true; +- goto check_again; +- } ++ /* We unpinned pages before migration, pin them again */ ++ ret = __get_user_pages_locked(mm, start, nr_pages, pages, vmas, ++ NULL, gup_flags); ++ if (ret <= 0) ++ return ret; ++ nr_pages = ret; + } + +- return ret; ++ /* ++ * check again because pages were unpinned, and we also might have ++ * had isolation errors and need more pages to migrate. ++ */ ++ goto check_again; + } + #else + static long check_and_migrate_cma_pages(struct mm_struct *mm, +-- +2.30.2 + diff --git a/queue-5.12/mm-gup-return-an-error-on-migration-failure.patch b/queue-5.12/mm-gup-return-an-error-on-migration-failure.patch new file mode 100644 index 00000000000..2827ab7fda4 --- /dev/null +++ b/queue-5.12/mm-gup-return-an-error-on-migration-failure.patch @@ -0,0 +1,96 @@ +From b7279c4f217a352265e9671215a6f5c6f706426f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 May 2021 18:38:46 -0700 +Subject: mm/gup: return an error on migration failure + +From: Pavel Tatashin + +[ Upstream commit f0f4463837da17a89d965dcbe4e411629dbcf308 ] + +When migration failure occurs, we still pin pages, which means that we +may pin CMA movable pages which should never be the case. + +Instead return an error without pinning pages when migration failure +happens. + +No need to retry migrating, because migrate_pages() already retries 10 +times. + +Link: https://lkml.kernel.org/r/20210215161349.246722-4-pasha.tatashin@soleen.com +Signed-off-by: Pavel Tatashin +Reviewed-by: Jason Gunthorpe +Cc: Dan Williams +Cc: David Hildenbrand +Cc: David Rientjes +Cc: Ingo Molnar +Cc: Ira Weiny +Cc: James Morris +Cc: Jason Gunthorpe +Cc: John Hubbard +Cc: Joonsoo Kim +Cc: Matthew Wilcox +Cc: Mel Gorman +Cc: Michal Hocko +Cc: Michal Hocko +Cc: Mike Kravetz +Cc: Oscar Salvador +Cc: Peter Zijlstra +Cc: Sasha Levin +Cc: Steven Rostedt (VMware) +Cc: Tyler Hicks +Cc: Vlastimil Babka +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/gup.c | 17 +++++++---------- + 1 file changed, 7 insertions(+), 10 deletions(-) + +diff --git a/mm/gup.c b/mm/gup.c +index 6530672131db..2b48c65e27cc 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -1553,7 +1553,6 @@ static long check_and_migrate_cma_pages(struct mm_struct *mm, + { + unsigned long i; + bool drain_allow = true; +- bool migrate_allow = true; + LIST_HEAD(cma_page_list); + long ret = nr_pages; + struct page *prev_head, *head; +@@ -1604,17 +1603,15 @@ check_again: + for (i = 0; i < nr_pages; i++) + put_page(pages[i]); + +- if (migrate_pages(&cma_page_list, alloc_migration_target, NULL, +- (unsigned long)&mtc, MIGRATE_SYNC, MR_CONTIG_RANGE)) { +- /* +- * some of the pages failed migration. Do get_user_pages +- * without migration. +- */ +- migrate_allow = false; +- ++ ret = migrate_pages(&cma_page_list, alloc_migration_target, ++ NULL, (unsigned long)&mtc, MIGRATE_SYNC, ++ MR_CONTIG_RANGE); ++ if (ret) { + if (!list_empty(&cma_page_list)) + putback_movable_pages(&cma_page_list); ++ return ret > 0 ? -ENOMEM : ret; + } ++ + /* + * We did migrate all the pages, Try to get the page references + * again migrating any new CMA pages which we failed to isolate +@@ -1624,7 +1621,7 @@ check_again: + pages, vmas, NULL, + gup_flags); + +- if ((ret > 0) && migrate_allow) { ++ if (ret > 0) { + nr_pages = ret; + drain_allow = true; + goto check_again; +-- +2.30.2 + diff --git a/queue-5.12/mm-hugeltb-handle-the-error-case-in-hugetlb_fix_rese.patch b/queue-5.12/mm-hugeltb-handle-the-error-case-in-hugetlb_fix_rese.patch new file mode 100644 index 00000000000..e4caf1028ae --- /dev/null +++ b/queue-5.12/mm-hugeltb-handle-the-error-case-in-hugetlb_fix_rese.patch @@ -0,0 +1,57 @@ +From d9d9ab846a7514e5cb9429573609e0c8d64d77e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 May 2021 18:34:38 -0700 +Subject: mm/hugeltb: handle the error case in hugetlb_fix_reserve_counts() + +From: Miaohe Lin + +[ Upstream commit da56388c4397878a65b74f7fe97760f5aa7d316b ] + +A rare out of memory error would prevent removal of the reserve map region +for a page. hugetlb_fix_reserve_counts() handles this rare case to avoid +dangling with incorrect counts. Unfortunately, hugepage_subpool_get_pages +and hugetlb_acct_memory could possibly fail too. We should correctly +handle these cases. + +Link: https://lkml.kernel.org/r/20210410072348.20437-5-linmiaohe@huawei.com +Fixes: b5cec28d36f5 ("hugetlbfs: truncate_hugepages() takes a range of pages") +Signed-off-by: Miaohe Lin +Cc: Feilong Lin +Cc: Mike Kravetz +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/hugetlb.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index a86a58ef132d..cb253c8e55cc 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -743,13 +743,20 @@ void hugetlb_fix_reserve_counts(struct inode *inode) + { + struct hugepage_subpool *spool = subpool_inode(inode); + long rsv_adjust; ++ bool reserved = false; + + rsv_adjust = hugepage_subpool_get_pages(spool, 1); +- if (rsv_adjust) { ++ if (rsv_adjust > 0) { + struct hstate *h = hstate_inode(inode); + +- hugetlb_acct_memory(h, 1); ++ if (!hugetlb_acct_memory(h, 1)) ++ reserved = true; ++ } else if (!rsv_adjust) { ++ reserved = true; + } ++ ++ if (!reserved) ++ pr_warn("hugetlb: Huge Page Reserved count may go negative.\n"); + } + + /* +-- +2.30.2 + diff --git a/queue-5.12/mm-migrate.c-fix-potential-indeterminate-pte-entry-i.patch b/queue-5.12/mm-migrate.c-fix-potential-indeterminate-pte-entry-i.patch new file mode 100644 index 00000000000..5e8c9273bdb --- /dev/null +++ b/queue-5.12/mm-migrate.c-fix-potential-indeterminate-pte-entry-i.patch @@ -0,0 +1,50 @@ +From cb2925ba5aad02ffe204ebd7d5205a24b6d19d8b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 May 2021 18:37:10 -0700 +Subject: mm/migrate.c: fix potential indeterminate pte entry in + migrate_vma_insert_page() + +From: Miaohe Lin + +[ Upstream commit 34f5e9b9d1990d286199084efa752530ee3d8297 ] + +If the zone device page does not belong to un-addressable device memory, +the variable entry will be uninitialized and lead to indeterminate pte +entry ultimately. Fix this unexpected case and warn about it. + +Link: https://lkml.kernel.org/r/20210325131524.48181-4-linmiaohe@huawei.com +Fixes: df6ad69838fc ("mm/device-public-memory: device memory cache coherent with CPU") +Signed-off-by: Miaohe Lin +Reviewed-by: David Hildenbrand +Cc: Alistair Popple +Cc: Jerome Glisse +Cc: Rafael Aquini +Cc: Yang Shi +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/migrate.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/mm/migrate.c b/mm/migrate.c +index 62b81d5257aa..773622cffe77 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -2973,6 +2973,13 @@ static void migrate_vma_insert_page(struct migrate_vma *migrate, + + swp_entry = make_device_private_entry(page, vma->vm_flags & VM_WRITE); + entry = swp_entry_to_pte(swp_entry); ++ } else { ++ /* ++ * For now we only support migrating to un-addressable ++ * device memory. ++ */ ++ pr_warn_once("Unsupported ZONE_DEVICE page type.\n"); ++ goto abort; + } + } else { + entry = mk_pte(page, vma->vm_page_prot); +-- +2.30.2 + diff --git a/queue-5.12/mptcp-fix-splat-when-closing-unaccepted-socket.patch b/queue-5.12/mptcp-fix-splat-when-closing-unaccepted-socket.patch new file mode 100644 index 00000000000..1787a645720 --- /dev/null +++ b/queue-5.12/mptcp-fix-splat-when-closing-unaccepted-socket.patch @@ -0,0 +1,50 @@ +From 8d6e1966c22aa663e66bf7af5032ac6e2171a4e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 May 2021 17:16:38 -0700 +Subject: mptcp: fix splat when closing unaccepted socket + +From: Paolo Abeni + +[ Upstream commit 578c18eff1627d6a911f08f4cf351eca41fdcc7d ] + +If userspace exits before calling accept() on a listener that had at least +one new connection ready, we get: + + Attempt to release TCP socket in state 8 + +This happens because the mptcp socket gets cloned when the TCP connection +is ready, but the socket is never exposed to userspace. + +The client additionally sends a DATA_FIN, which brings connection into +CLOSE_WAIT state. This in turn prevents the orphan+state reset fixup +in mptcp_sock_destruct() from doing its job. + +Fixes: 3721b9b64676b ("mptcp: Track received DATA_FIN sequence number and add related helpers") +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/185 +Tested-by: Florian Westphal +Signed-off-by: Paolo Abeni +Signed-off-by: Mat Martineau +Link: https://lore.kernel.org/r/20210507001638.225468-1-mathew.j.martineau@linux.intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/mptcp/subflow.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c +index d17d39ccdf34..4fe7acaa472f 100644 +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -524,8 +524,7 @@ static void mptcp_sock_destruct(struct sock *sk) + * ESTABLISHED state and will not have the SOCK_DEAD flag. + * Both result in warnings from inet_sock_destruct. + */ +- +- if (sk->sk_state == TCP_ESTABLISHED) { ++ if ((1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) { + sk->sk_state = TCP_CLOSE; + WARN_ON_ONCE(sk->sk_socket); + sock_orphan(sk); +-- +2.30.2 + diff --git a/queue-5.12/mt76-connac-always-check-return-value-from-mt76_conn.patch b/queue-5.12/mt76-connac-always-check-return-value-from-mt76_conn.patch new file mode 100644 index 00000000000..90a42e3d13a --- /dev/null +++ b/queue-5.12/mt76-connac-always-check-return-value-from-mt76_conn.patch @@ -0,0 +1,55 @@ +From eb92c00bf286020dd41aeb6bc5ada41cbb3b1cc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Feb 2021 12:51:05 +0100 +Subject: mt76: connac: always check return value from + mt76_connac_mcu_alloc_wtbl_req + +From: Lorenzo Bianconi + +[ Upstream commit baa3afb39e94965f4ca5b5d3d274379504b8fa24 ] + +Even if this is not a real bug since mt76_connac_mcu_alloc_wtbl_req routine +can fails just if nskb is NULL , always check return value from +mt76_connac_mcu_alloc_wtbl_req in order to avoid possible future +mistake. + +Reported-by: Dan Carpenter +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 3 +++ + drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +index 631596fc2f36..4ecbd5406e2a 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +@@ -1040,6 +1040,9 @@ mt7615_mcu_sta_ba(struct mt7615_dev *dev, + + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, + WTBL_SET, sta_wtbl, &skb); ++ if (IS_ERR(wtbl_hdr)) ++ return PTR_ERR(wtbl_hdr); ++ + mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, tx, + sta_wtbl, wtbl_hdr); + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index 76a61e8b7fb9..cefd33b74a87 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -833,6 +833,9 @@ int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy, + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, + WTBL_RESET_AND_SET, + sta_wtbl, &skb); ++ if (IS_ERR(wtbl_hdr)) ++ return PTR_ERR(wtbl_hdr); ++ + if (enable) { + mt76_connac_mcu_wtbl_generic_tlv(dev, skb, vif, sta, sta_wtbl, + wtbl_hdr); +-- +2.30.2 + diff --git a/queue-5.12/mt76-mt7615-fix-entering-driver-own-state-on-mt7663.patch b/queue-5.12/mt76-mt7615-fix-entering-driver-own-state-on-mt7663.patch new file mode 100644 index 00000000000..b6fab823edc --- /dev/null +++ b/queue-5.12/mt76-mt7615-fix-entering-driver-own-state-on-mt7663.patch @@ -0,0 +1,47 @@ +From 784d8f74891b271165fcaa6c7c7a2c27771ae29d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 21:07:53 +0200 +Subject: mt76: mt7615: fix entering driver-own state on mt7663 + +From: Felix Fietkau + +[ Upstream commit 5c7d374444afdeb9dd534a37c4f6c13af032da0c ] + +Fixes hardware wakeup issues + +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +index 4ecbd5406e2a..198e9025b681 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +@@ -291,12 +291,20 @@ static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev) + u32 addr; + int err; + +- addr = is_mt7663(mdev) ? MT_PCIE_DOORBELL_PUSH : MT_CFG_LPCR_HOST; ++ if (is_mt7663(mdev)) { ++ /* Clear firmware own via N9 eint */ ++ mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN); ++ mt76_poll(dev, MT_CONN_ON_MISC, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000); ++ ++ addr = MT_CONN_HIF_ON_LPCTL; ++ } else { ++ addr = MT_CFG_LPCR_HOST; ++ } ++ + mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN); + + mt7622_trigger_hif_int(dev, true); + +- addr = is_mt7663(mdev) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; + err = !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000); + + mt7622_trigger_hif_int(dev, false); +-- +2.30.2 + diff --git a/queue-5.12/mt76-mt7615-fix-key-set-delete-issues.patch b/queue-5.12/mt76-mt7615-fix-key-set-delete-issues.patch new file mode 100644 index 00000000000..02e1151ed46 --- /dev/null +++ b/queue-5.12/mt76-mt7615-fix-key-set-delete-issues.patch @@ -0,0 +1,257 @@ +From 2b6c4fea2bfdb5ff194f89c71c37e8cb1cccae98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Feb 2021 17:07:27 +0100 +Subject: mt76: mt7615: fix key set/delete issues + +From: Felix Fietkau + +[ Upstream commit 730d6d0da8d8f5905faafe645a5b3c08ac3f5a8f ] + +There were multiple issues in the current key set/remove code: +- deleting a key with the previous key index deletes the current key +- BIP key would only be uploaded correctly initially and corrupted on rekey + +Rework the code to better keep track of multiple keys and check for the +key index before deleting the current key + +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76.h | 1 + + .../net/wireless/mediatek/mt76/mt7615/mac.c | 97 ++++++++++--------- + .../net/wireless/mediatek/mt76/mt7615/main.c | 18 ++-- + 3 files changed, 65 insertions(+), 51 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h +index 8bf45497cfca..36a430f09f64 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76.h +@@ -222,6 +222,7 @@ struct mt76_wcid { + + u16 idx; + u8 hw_key_idx; ++ u8 hw_key_idx2; + + u8 sta:1; + u8 ext_phy:1; +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +index d73841480544..8dccb589b756 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +@@ -1037,7 +1037,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_set_rates); + static int + mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, +- enum mt7615_cipher_type cipher, ++ enum mt7615_cipher_type cipher, u16 cipher_mask, + enum set_key_cmd cmd) + { + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4; +@@ -1054,22 +1054,22 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, + memcpy(data + 16, key->key + 24, 8); + memcpy(data + 24, key->key + 16, 8); + } else { +- if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher) +- memmove(data + 16, data, 16); +- if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) ++ if (cipher_mask == BIT(cipher)) + memcpy(data, key->key, key->keylen); +- else if (cipher == MT_CIPHER_BIP_CMAC_128) ++ else if (cipher != MT_CIPHER_BIP_CMAC_128) ++ memcpy(data, key->key, 16); ++ if (cipher == MT_CIPHER_BIP_CMAC_128) + memcpy(data + 16, key->key, 16); + } + } else { +- if (wcid->cipher & ~BIT(cipher)) { +- if (cipher != MT_CIPHER_BIP_CMAC_128) +- memmove(data, data + 16, 16); ++ if (cipher == MT_CIPHER_BIP_CMAC_128) + memset(data + 16, 0, 16); +- } else { ++ else if (cipher_mask) ++ memset(data, 0, 16); ++ if (!cipher_mask) + memset(data, 0, sizeof(data)); +- } + } ++ + mt76_wr_copy(dev, addr, data, sizeof(data)); + + return 0; +@@ -1077,7 +1077,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, + + static int + mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, +- enum mt7615_cipher_type cipher, ++ enum mt7615_cipher_type cipher, u16 cipher_mask, + int keyidx, enum set_key_cmd cmd) + { + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; +@@ -1087,20 +1087,23 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, + + w0 = mt76_rr(dev, addr); + w1 = mt76_rr(dev, addr + 4); +- if (cmd == SET_KEY) { +- w0 |= MT_WTBL_W0_RX_KEY_VALID | +- FIELD_PREP(MT_WTBL_W0_RX_IK_VALID, +- cipher == MT_CIPHER_BIP_CMAC_128); +- if (cipher != MT_CIPHER_BIP_CMAC_128 || +- !wcid->cipher) +- w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); +- } else { +- if (!(wcid->cipher & ~BIT(cipher))) +- w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | +- MT_WTBL_W0_KEY_IDX); +- if (cipher == MT_CIPHER_BIP_CMAC_128) +- w0 &= ~MT_WTBL_W0_RX_IK_VALID; ++ ++ if (cipher_mask) ++ w0 |= MT_WTBL_W0_RX_KEY_VALID; ++ else ++ w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | MT_WTBL_W0_KEY_IDX); ++ if (cipher_mask & BIT(MT_CIPHER_BIP_CMAC_128)) ++ w0 |= MT_WTBL_W0_RX_IK_VALID; ++ else ++ w0 &= ~MT_WTBL_W0_RX_IK_VALID; ++ ++ if (cmd == SET_KEY && ++ (cipher != MT_CIPHER_BIP_CMAC_128 || ++ cipher_mask == BIT(cipher))) { ++ w0 &= ~MT_WTBL_W0_KEY_IDX; ++ w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); + } ++ + mt76_wr(dev, MT_WTBL_RICR0, w0); + mt76_wr(dev, MT_WTBL_RICR1, w1); + +@@ -1113,24 +1116,25 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, + + static void + mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, +- enum mt7615_cipher_type cipher, ++ enum mt7615_cipher_type cipher, u16 cipher_mask, + enum set_key_cmd cmd) + { + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx); + +- if (cmd == SET_KEY) { +- if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) +- mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, +- FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher)); +- } else { +- if (cipher != MT_CIPHER_BIP_CMAC_128 && +- wcid->cipher & BIT(MT_CIPHER_BIP_CMAC_128)) +- mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, +- FIELD_PREP(MT_WTBL_W2_KEY_TYPE, +- MT_CIPHER_BIP_CMAC_128)); +- else if (!(wcid->cipher & ~BIT(cipher))) +- mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); ++ if (!cipher_mask) { ++ mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); ++ return; + } ++ ++ if (cmd != SET_KEY) ++ return; ++ ++ if (cipher == MT_CIPHER_BIP_CMAC_128 && ++ cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128)) ++ return; ++ ++ mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, ++ FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher)); + } + + int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, +@@ -1139,25 +1143,30 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, + enum set_key_cmd cmd) + { + enum mt7615_cipher_type cipher; ++ u16 cipher_mask = wcid->cipher; + int err; + + cipher = mt7615_mac_get_cipher(key->cipher); + if (cipher == MT_CIPHER_NONE) + return -EOPNOTSUPP; + +- mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd); +- err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd); ++ if (cmd == SET_KEY) ++ cipher_mask |= BIT(cipher); ++ else ++ cipher_mask &= ~BIT(cipher); ++ ++ mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd); ++ err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask, ++ cmd); + if (err < 0) + return err; + +- err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd); ++ err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask, ++ key->keyidx, cmd); + if (err < 0) + return err; + +- if (cmd == SET_KEY) +- wcid->cipher |= BIT(cipher); +- else +- wcid->cipher &= ~BIT(cipher); ++ wcid->cipher = cipher_mask; + + return 0; + } +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c +index 6107e827b383..d334491667a4 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c +@@ -334,7 +334,8 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : + &mvif->sta; + struct mt76_wcid *wcid = &msta->wcid; +- int idx = key->keyidx, err; ++ int idx = key->keyidx, err = 0; ++ u8 *wcid_keyidx = &wcid->hw_key_idx; + + /* The hardware does not support per-STA RX GTK, fallback + * to software mode for these. +@@ -349,6 +350,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + /* fall back to sw encryption for unsupported ciphers */ + switch (key->cipher) { + case WLAN_CIPHER_SUITE_AES_CMAC: ++ wcid_keyidx = &wcid->hw_key_idx2; + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; + break; + case WLAN_CIPHER_SUITE_TKIP: +@@ -366,12 +368,13 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + + mt7615_mutex_acquire(dev); + +- if (cmd == SET_KEY) { +- key->hw_key_idx = wcid->idx; +- wcid->hw_key_idx = idx; +- } else if (idx == wcid->hw_key_idx) { +- wcid->hw_key_idx = -1; +- } ++ if (cmd == SET_KEY) ++ *wcid_keyidx = idx; ++ else if (idx == *wcid_keyidx) ++ *wcid_keyidx = -1; ++ else ++ goto out; ++ + mt76_wcid_key_setup(&dev->mt76, wcid, + cmd == SET_KEY ? key : NULL); + +@@ -380,6 +383,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + else + err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); + ++out: + mt7615_mutex_release(dev); + + return err; +-- +2.30.2 + diff --git a/queue-5.12/mt76-mt7615-support-loading-eeprom-for-mt7613be.patch b/queue-5.12/mt76-mt7615-support-loading-eeprom-for-mt7613be.patch new file mode 100644 index 00000000000..465641e308c --- /dev/null +++ b/queue-5.12/mt76-mt7615-support-loading-eeprom-for-mt7613be.patch @@ -0,0 +1,38 @@ +From 02ee02e2e17b698e4190cc589f3c16aaba3c4983 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Feb 2021 09:59:53 +0100 +Subject: mt76: mt7615: support loading EEPROM for MT7613BE + +From: Sander Vanheule + +[ Upstream commit 858ebf446bee7d5077bd99488aae617908c3f4fe ] + +EEPROM blobs for MT7613BE radios start with (little endian) 0x7663, +which is also the PCI device ID for this device. The EEPROM is required +for the radio to work at useful power levels, otherwise only the lowest +power level is available. + +Suggested-by: Georgi Vlaev +Tested-by: Stijn Segers +Signed-off-by: Sander Vanheule +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +index 2eab23898c77..6dbaaf95ee38 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +@@ -86,6 +86,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) + switch (val) { + case 0x7615: + case 0x7622: ++ case 0x7663: + return 0; + default: + return -EINVAL; +-- +2.30.2 + diff --git a/queue-5.12/mt76-mt76x0-disable-gtk-offloading.patch b/queue-5.12/mt76-mt76x0-disable-gtk-offloading.patch new file mode 100644 index 00000000000..e058faa2786 --- /dev/null +++ b/queue-5.12/mt76-mt76x0-disable-gtk-offloading.patch @@ -0,0 +1,46 @@ +From d759c0642f61b6b3ababa0f4a9c3351880c891bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 7 Feb 2021 16:09:17 +0100 +Subject: mt76: mt76x0: disable GTK offloading + +From: David Bauer + +[ Upstream commit 4b36cc6b390f18dbc59a45fb4141f90d7dfe2b23 ] + +When operating two VAP on a MT7610 with encryption (PSK2, SAE, OWE), +only the first one to be created will transmit properly encrypteded +frames. + +All subsequently created VAPs will sent out frames with the payload left +unencrypted, breaking multicast traffic (ICMP6 NDP) and potentially +disclosing information to a third party. + +Disable GTK offloading and encrypt these frames in software to +circumvent this issue. THis only seems to be necessary on MT7610 chips, +as MT7612 is not affected from our testing. + +Signed-off-by: David Bauer +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +index ab671e21f882..02db5d66735d 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +@@ -447,6 +447,10 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + ++ /* MT76x0 GTK offloading does not work with more than one VIF */ ++ if (is_mt76x0(dev) && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) ++ return -EOPNOTSUPP; ++ + msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL; + wcid = msta ? &msta->wcid : &mvif->group_wcid; + +-- +2.30.2 + diff --git a/queue-5.12/mt76-mt7915-add-wifi-subsystem-reset.patch b/queue-5.12/mt76-mt7915-add-wifi-subsystem-reset.patch new file mode 100644 index 00000000000..727e1425876 --- /dev/null +++ b/queue-5.12/mt76-mt7915-add-wifi-subsystem-reset.patch @@ -0,0 +1,177 @@ +From b5c3c75e3b5be91997d9fd8ed51061e85ec75407 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Apr 2021 12:46:09 +0800 +Subject: mt76: mt7915: add wifi subsystem reset + +From: Ryder Lee + +[ Upstream commit e07419a7dca97dd9bddfe5d099380857c19535f3 ] + +Reset wifi subsystem when MCU is already running. +Fixes firmware download failure after soft reboot on systems where the PCIe +reset could not be performed properly. + +Signed-off-by: Ryder Lee +Co-developed-by: Felix Fietkau +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7915/init.c | 58 ++++++++++++++++++- + .../net/wireless/mediatek/mt76/mt7915/mcu.c | 15 +---- + .../net/wireless/mediatek/mt76/mt7915/regs.h | 13 +++++ + 3 files changed, 70 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c +index 894016fdcf07..c7d4268d860a 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c +@@ -4,6 +4,7 @@ + #include + #include "mt7915.h" + #include "mac.h" ++#include "mcu.h" + #include "eeprom.h" + + #define CCK_RATE(_idx, _rate) { \ +@@ -283,9 +284,50 @@ static void mt7915_init_work(struct work_struct *work) + mt7915_register_ext_phy(dev); + } + ++static void mt7915_wfsys_reset(struct mt7915_dev *dev) ++{ ++ u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON; ++ u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); ++ ++#define MT_MCU_DUMMY_RANDOM GENMASK(15, 0) ++#define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16) ++ ++ mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM); ++ ++ /* change to software control */ ++ val |= MT_TOP_PWR_SW_RST; ++ mt76_wr(dev, MT_TOP_PWR_CTRL, val); ++ ++ /* reset wfsys */ ++ val &= ~MT_TOP_PWR_SW_RST; ++ mt76_wr(dev, MT_TOP_PWR_CTRL, val); ++ ++ /* release wfsys then mcu re-excutes romcode */ ++ val |= MT_TOP_PWR_SW_RST; ++ mt76_wr(dev, MT_TOP_PWR_CTRL, val); ++ ++ /* switch to hw control */ ++ val &= ~MT_TOP_PWR_SW_RST; ++ val |= MT_TOP_PWR_HW_CTRL; ++ mt76_wr(dev, MT_TOP_PWR_CTRL, val); ++ ++ /* check whether mcu resets to default */ ++ if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_DEFAULT, ++ MT_MCU_DUMMY_DEFAULT, 1000)) { ++ dev_err(dev->mt76.dev, "wifi subsystem reset failure\n"); ++ return; ++ } ++ ++ /* wfsys reset won't clear host registers */ ++ mt76_clear(dev, reg, MT_TOP_MISC_FW_STATE); ++ ++ msleep(100); ++} ++ + static int mt7915_init_hardware(struct mt7915_dev *dev) + { + int ret, idx; ++ u32 val; + + mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); + +@@ -295,6 +337,12 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) + + dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5)); + ++ val = mt76_rr(dev, mt7915_reg_map_l1(dev, MT_TOP_MISC)); ++ ++ /* If MCU was already running, it is likely in a bad state */ ++ if (FIELD_GET(MT_TOP_MISC_FW_STATE, val) > FW_STATE_FW_DOWNLOAD) ++ mt7915_wfsys_reset(dev); ++ + ret = mt7915_dma_init(dev); + if (ret) + return ret; +@@ -308,8 +356,14 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) + mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); + + ret = mt7915_mcu_init(dev); +- if (ret) +- return ret; ++ if (ret) { ++ /* Reset and try again */ ++ mt7915_wfsys_reset(dev); ++ ++ ret = mt7915_mcu_init(dev); ++ if (ret) ++ return ret; ++ } + + ret = mt7915_eeprom_init(dev); + if (ret < 0) +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +index c747349a4c13..f069a5a03e14 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +@@ -2764,21 +2764,8 @@ out: + + static int mt7915_load_firmware(struct mt7915_dev *dev) + { ++ u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); + int ret; +- u32 val, reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); +- +- val = FIELD_PREP(MT_TOP_MISC_FW_STATE, FW_STATE_FW_DOWNLOAD); +- +- if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, val, 1000)) { +- /* restart firmware once */ +- __mt76_mcu_restart(&dev->mt76); +- if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, +- val, 1000)) { +- dev_err(dev->mt76.dev, +- "Firmware is not ready for download\n"); +- return -EIO; +- } +- } + + ret = mt7915_load_patch(dev); + if (ret) +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +index ed0c9a24bb53..dfb8880657bf 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +@@ -4,6 +4,11 @@ + #ifndef __MT7915_REGS_H + #define __MT7915_REGS_H + ++/* MCU WFDMA0 */ ++#define MT_MCU_WFDMA0_BASE 0x2000 ++#define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs)) ++#define MT_MCU_WFDMA0_DUMMY_CR MT_MCU_WFDMA0(0x120) ++ + /* MCU WFDMA1 */ + #define MT_MCU_WFDMA1_BASE 0x3000 + #define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs)) +@@ -396,6 +401,14 @@ + #define MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1) + #define MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO BIT(2) + ++#define MT_TOP_RGU_BASE 0xf0000 ++#define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0)) ++#define MT_TOP_PWR_KEY (0x5746 << 16) ++#define MT_TOP_PWR_SW_RST BIT(0) ++#define MT_TOP_PWR_SW_PWR_ON GENMASK(3, 2) ++#define MT_TOP_PWR_HW_CTRL BIT(4) ++#define MT_TOP_PWR_PWR_ON BIT(7) ++ + #define MT_INFRA_CFG_BASE 0xf1000 + #define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs)) + +-- +2.30.2 + diff --git a/queue-5.12/mt76-mt7915-always-check-return-value-from-mt7915_mc.patch b/queue-5.12/mt76-mt7915-always-check-return-value-from-mt7915_mc.patch new file mode 100644 index 00000000000..491f07877c1 --- /dev/null +++ b/queue-5.12/mt76-mt7915-always-check-return-value-from-mt7915_mc.patch @@ -0,0 +1,69 @@ +From 7edb90bd9c854386ea7343faca3849e5220ccdbd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Feb 2021 20:30:04 +0100 +Subject: mt76: mt7915: always check return value from + mt7915_mcu_alloc_wtbl_req + +From: Lorenzo Bianconi + +[ Upstream commit 45f93e368211fbbd247e1ece254ffb121e20fa10 ] + +As done for mt76_connac_mcu_alloc_wtbl_req, even if this is not a real +bug since mt7915_mcu_alloc_wtbl_req routine can fails just if nskb is NULL, +always check return value from mt7915_mcu_alloc_wtbl_req in order to avoid +possible future mistake. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +index 443cb09ae7cb..c747349a4c13 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +@@ -1198,6 +1198,9 @@ mt7915_mcu_sta_ba(struct mt7915_dev *dev, + + wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, + &skb); ++ if (IS_ERR(wtbl_hdr)) ++ return PTR_ERR(wtbl_hdr); ++ + mt7915_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); + + ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, +@@ -1714,6 +1717,9 @@ int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev, + return -ENOMEM; + + wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, NULL, &skb); ++ if (IS_ERR(wtbl_hdr)) ++ return PTR_ERR(wtbl_hdr); ++ + mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(WTBL_UPDATE), +@@ -1738,6 +1744,9 @@ int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, + + wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, + &skb); ++ if (IS_ERR(wtbl_hdr)) ++ return PTR_ERR(wtbl_hdr); ++ + mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, +@@ -2263,6 +2272,9 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, + + wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_RESET_AND_SET, + sta_wtbl, &skb); ++ if (IS_ERR(wtbl_hdr)) ++ return PTR_ERR(wtbl_hdr); ++ + if (enable) { + mt7915_mcu_wtbl_generic_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); + mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); +-- +2.30.2 + diff --git a/queue-5.12/mt76-mt7915-fix-key-set-delete-issue.patch b/queue-5.12/mt76-mt7915-fix-key-set-delete-issue.patch new file mode 100644 index 00000000000..bfb89653933 --- /dev/null +++ b/queue-5.12/mt76-mt7915-fix-key-set-delete-issue.patch @@ -0,0 +1,76 @@ +From 685825039d01796b90b8e910a76e49ed7693bc7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Mar 2021 21:39:57 +0100 +Subject: mt76: mt7915: fix key set/delete issue + +From: Felix Fietkau + +[ Upstream commit 1da4fd48d28436f8b690cdc2879603dede6d8355 ] + +Deleting a key with the previous key index deletes the current key +Rework the code to better keep track of multiple keys and check for the +key index before deleting the current key + +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7915/main.c | 25 +++++++++++++------ + 1 file changed, 18 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c +index 98f4b49642a8..bf032d943f74 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c +@@ -317,7 +317,9 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct mt7915_sta *msta = sta ? (struct mt7915_sta *)sta->drv_priv : + &mvif->sta; + struct mt76_wcid *wcid = &msta->wcid; ++ u8 *wcid_keyidx = &wcid->hw_key_idx; + int idx = key->keyidx; ++ int err = 0; + + /* The hardware does not support per-STA RX GTK, fallback + * to software mode for these. +@@ -332,6 +334,7 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + /* fall back to sw encryption for unsupported ciphers */ + switch (key->cipher) { + case WLAN_CIPHER_SUITE_AES_CMAC: ++ wcid_keyidx = &wcid->hw_key_idx2; + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; + break; + case WLAN_CIPHER_SUITE_TKIP: +@@ -347,16 +350,24 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + return -EOPNOTSUPP; + } + +- if (cmd == SET_KEY) { +- key->hw_key_idx = wcid->idx; +- wcid->hw_key_idx = idx; +- } else if (idx == wcid->hw_key_idx) { +- wcid->hw_key_idx = -1; +- } ++ mutex_lock(&dev->mt76.mutex); ++ ++ if (cmd == SET_KEY) ++ *wcid_keyidx = idx; ++ else if (idx == *wcid_keyidx) ++ *wcid_keyidx = -1; ++ else ++ goto out; ++ + mt76_wcid_key_setup(&dev->mt76, wcid, + cmd == SET_KEY ? key : NULL); + +- return mt7915_mcu_add_key(dev, vif, msta, key, cmd); ++ err = mt7915_mcu_add_key(dev, vif, msta, key, cmd); ++ ++out: ++ mutex_unlock(&dev->mt76.mutex); ++ ++ return err; + } + + static int mt7915_config(struct ieee80211_hw *hw, u32 changed) +-- +2.30.2 + diff --git a/queue-5.12/mt76-mt7915-fix-txpower-init-for-tssi-off-chips.patch b/queue-5.12/mt76-mt7915-fix-txpower-init-for-tssi-off-chips.patch new file mode 100644 index 00000000000..969831dab1b --- /dev/null +++ b/queue-5.12/mt76-mt7915-fix-txpower-init-for-tssi-off-chips.patch @@ -0,0 +1,63 @@ +From 2add7fa9bdbadd47dba29c4a7974fae51bd4452d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Apr 2021 10:31:29 +0800 +Subject: mt76: mt7915: fix txpower init for TSSI off chips + +From: Shayne Chen + +[ Upstream commit a226ccd04c479ccd23d6927c64bad1b441707f70 ] + +Fix incorrect txpower init value for TSSI off chips which causes +too small txpower. + +Signed-off-by: Shayne Chen +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../wireless/mediatek/mt76/mt7915/eeprom.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +index 660398ac53c2..738ecf8f4fa2 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +@@ -124,7 +124,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, + struct ieee80211_channel *chan, + u8 chain_idx) + { +- int index; ++ int index, target_power; + bool tssi_on; + + if (chain_idx > 3) +@@ -133,15 +133,22 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, + tssi_on = mt7915_tssi_enabled(dev, chan->band); + + if (chan->band == NL80211_BAND_2GHZ) { +- index = MT_EE_TX0_POWER_2G + chain_idx * 3 + !tssi_on; ++ index = MT_EE_TX0_POWER_2G + chain_idx * 3; ++ target_power = mt7915_eeprom_read(dev, index); ++ ++ if (!tssi_on) ++ target_power += mt7915_eeprom_read(dev, index + 1); + } else { +- int group = tssi_on ? +- mt7915_get_channel_group(chan->hw_value) : 8; ++ int group = mt7915_get_channel_group(chan->hw_value); ++ ++ index = MT_EE_TX0_POWER_5G + chain_idx * 12; ++ target_power = mt7915_eeprom_read(dev, index + group); + +- index = MT_EE_TX0_POWER_5G + chain_idx * 12 + group; ++ if (!tssi_on) ++ target_power += mt7915_eeprom_read(dev, index + 8); + } + +- return mt7915_eeprom_read(dev, index); ++ return target_power; + } + + static const u8 sku_cck_delta_map[] = { +-- +2.30.2 + diff --git a/queue-5.12/mt76-mt7921-fix-key-set-delete-issue.patch b/queue-5.12/mt76-mt7921-fix-key-set-delete-issue.patch new file mode 100644 index 00000000000..c50c920a0ac --- /dev/null +++ b/queue-5.12/mt76-mt7921-fix-key-set-delete-issue.patch @@ -0,0 +1,77 @@ +From e4253040ac9494e8727d6cb0a542c266cff7fafe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Mar 2021 10:10:14 +0100 +Subject: mt76: mt7921: fix key set/delete issue + +From: Lorenzo Bianconi + +[ Upstream commit 60468f7fd7072c804b2613f1cadabace8d77d311 ] + +Similar to the mt7915 driver, deleting a key with the previous key index +deletes the current key. Rework the code to better keep track of +multiple keys and check for the key index before deleting the current +key + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7921/main.c | 25 +++++++++++++------ + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +index cd9fd0e24e3e..ada943c7a950 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +@@ -413,7 +413,8 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct mt7921_sta *msta = sta ? (struct mt7921_sta *)sta->drv_priv : + &mvif->sta; + struct mt76_wcid *wcid = &msta->wcid; +- int idx = key->keyidx; ++ u8 *wcid_keyidx = &wcid->hw_key_idx; ++ int idx = key->keyidx, err = 0; + + /* The hardware does not support per-STA RX GTK, fallback + * to software mode for these. +@@ -429,6 +430,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + switch (key->cipher) { + case WLAN_CIPHER_SUITE_AES_CMAC: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; ++ wcid_keyidx = &wcid->hw_key_idx2; + break; + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: +@@ -443,16 +445,23 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + return -EOPNOTSUPP; + } + +- if (cmd == SET_KEY) { +- key->hw_key_idx = wcid->idx; +- wcid->hw_key_idx = idx; +- } else if (idx == wcid->hw_key_idx) { +- wcid->hw_key_idx = -1; +- } ++ mt7921_mutex_acquire(dev); ++ ++ if (cmd == SET_KEY) ++ *wcid_keyidx = idx; ++ else if (idx == *wcid_keyidx) ++ *wcid_keyidx = -1; ++ else ++ goto out; ++ + mt76_wcid_key_setup(&dev->mt76, wcid, + cmd == SET_KEY ? key : NULL); + +- return mt7921_mcu_add_key(dev, vif, msta, key, cmd); ++ err = mt7921_mcu_add_key(dev, vif, msta, key, cmd); ++out: ++ mt7921_mutex_release(dev); ++ ++ return err; + } + + static int mt7921_config(struct ieee80211_hw *hw, u32 changed) +-- +2.30.2 + diff --git a/queue-5.12/net-bridge-propagate-error-code-and-extack-from-br_m.patch b/queue-5.12/net-bridge-propagate-error-code-and-extack-from-br_m.patch new file mode 100644 index 00000000000..06e21f74ea4 --- /dev/null +++ b/queue-5.12/net-bridge-propagate-error-code-and-extack-from-br_m.patch @@ -0,0 +1,162 @@ +From b3205c5b85e0e2e116f874b646efc05e520ef16d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Apr 2021 22:22:57 +0300 +Subject: net: bridge: propagate error code and extack from + br_mc_disabled_update + +From: Florian Fainelli + +[ Upstream commit ae1ea84b33dab45c7b6c1754231ebda5959b504c ] + +Some Ethernet switches might only be able to support disabling multicast +snooping globally, which is an issue for example when several bridges +span the same physical device and request contradictory settings. + +Propagate the return value of br_mc_disabled_update() such that this +limitation is transmitted correctly to user-space. + +Signed-off-by: Florian Fainelli +Signed-off-by: Vladimir Oltean +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/bridge/br_multicast.c | 28 +++++++++++++++++++++------- + net/bridge/br_netlink.c | 4 +++- + net/bridge/br_private.h | 3 ++- + net/bridge/br_sysfs_br.c | 8 +------- + 4 files changed, 27 insertions(+), 16 deletions(-) + +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 229309d7b4ff..72b3193b08ec 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -1593,7 +1593,8 @@ out: + spin_unlock(&br->multicast_lock); + } + +-static void br_mc_disabled_update(struct net_device *dev, bool value) ++static int br_mc_disabled_update(struct net_device *dev, bool value, ++ struct netlink_ext_ack *extack) + { + struct switchdev_attr attr = { + .orig_dev = dev, +@@ -1602,11 +1603,13 @@ static void br_mc_disabled_update(struct net_device *dev, bool value) + .u.mc_disabled = !value, + }; + +- switchdev_port_attr_set(dev, &attr, NULL); ++ return switchdev_port_attr_set(dev, &attr, extack); + } + + int br_multicast_add_port(struct net_bridge_port *port) + { ++ int err; ++ + port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; + port->multicast_eht_hosts_limit = BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT; + +@@ -1618,8 +1621,12 @@ int br_multicast_add_port(struct net_bridge_port *port) + timer_setup(&port->ip6_own_query.timer, + br_ip6_multicast_port_query_expired, 0); + #endif +- br_mc_disabled_update(port->dev, +- br_opt_get(port->br, BROPT_MULTICAST_ENABLED)); ++ err = br_mc_disabled_update(port->dev, ++ br_opt_get(port->br, ++ BROPT_MULTICAST_ENABLED), ++ NULL); ++ if (err) ++ return err; + + port->mcast_stats = netdev_alloc_pcpu_stats(struct bridge_mcast_stats); + if (!port->mcast_stats) +@@ -3543,16 +3550,23 @@ static void br_multicast_start_querier(struct net_bridge *br, + rcu_read_unlock(); + } + +-int br_multicast_toggle(struct net_bridge *br, unsigned long val) ++int br_multicast_toggle(struct net_bridge *br, unsigned long val, ++ struct netlink_ext_ack *extack) + { + struct net_bridge_port *port; + bool change_snoopers = false; ++ int err = 0; + + spin_lock_bh(&br->multicast_lock); + if (!!br_opt_get(br, BROPT_MULTICAST_ENABLED) == !!val) + goto unlock; + +- br_mc_disabled_update(br->dev, val); ++ err = br_mc_disabled_update(br->dev, val, extack); ++ if (err == -EOPNOTSUPP) ++ err = 0; ++ if (err) ++ goto unlock; ++ + br_opt_toggle(br, BROPT_MULTICAST_ENABLED, !!val); + if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) { + change_snoopers = true; +@@ -3590,7 +3604,7 @@ unlock: + br_multicast_leave_snoopers(br); + } + +- return 0; ++ return err; + } + + bool br_multicast_enabled(const struct net_device *dev) +diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c +index f2b1343f8332..0456593aceec 100644 +--- a/net/bridge/br_netlink.c ++++ b/net/bridge/br_netlink.c +@@ -1293,7 +1293,9 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], + if (data[IFLA_BR_MCAST_SNOOPING]) { + u8 mcast_snooping = nla_get_u8(data[IFLA_BR_MCAST_SNOOPING]); + +- br_multicast_toggle(br, mcast_snooping); ++ err = br_multicast_toggle(br, mcast_snooping, extack); ++ if (err) ++ return err; + } + + if (data[IFLA_BR_MCAST_QUERY_USE_IFADDR]) { +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index d7d167e10b70..af3430c2d6ea 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -810,7 +810,8 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst, + struct sk_buff *skb, bool local_rcv, bool local_orig); + int br_multicast_set_router(struct net_bridge *br, unsigned long val); + int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val); +-int br_multicast_toggle(struct net_bridge *br, unsigned long val); ++int br_multicast_toggle(struct net_bridge *br, unsigned long val, ++ struct netlink_ext_ack *extack); + int br_multicast_set_querier(struct net_bridge *br, unsigned long val); + int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val); + int br_multicast_set_igmp_version(struct net_bridge *br, unsigned long val); +diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c +index 072e29840082..381467b691d5 100644 +--- a/net/bridge/br_sysfs_br.c ++++ b/net/bridge/br_sysfs_br.c +@@ -409,17 +409,11 @@ static ssize_t multicast_snooping_show(struct device *d, + return sprintf(buf, "%d\n", br_opt_get(br, BROPT_MULTICAST_ENABLED)); + } + +-static int toggle_multicast(struct net_bridge *br, unsigned long val, +- struct netlink_ext_ack *extack) +-{ +- return br_multicast_toggle(br, val); +-} +- + static ssize_t multicast_snooping_store(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) + { +- return store_bridge_parm(d, buf, len, toggle_multicast); ++ return store_bridge_parm(d, buf, len, br_multicast_toggle); + } + static DEVICE_ATTR_RW(multicast_snooping); + +-- +2.30.2 + diff --git a/queue-5.12/net-bridge-when-suppression-is-enabled-exclude-rarp-.patch b/queue-5.12/net-bridge-when-suppression-is-enabled-exclude-rarp-.patch new file mode 100644 index 00000000000..a9fd6eb0222 --- /dev/null +++ b/queue-5.12/net-bridge-when-suppression-is-enabled-exclude-rarp-.patch @@ -0,0 +1,44 @@ +From 155ef1194f97e35175eba512515cae76252fa6a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Mar 2021 17:45:27 +0200 +Subject: net: bridge: when suppression is enabled exclude RARP packets + +From: Nikolay Aleksandrov + +[ Upstream commit 0353b4a96b7a9f60fe20d1b3ebd4931a4085f91c ] + +Recently we had an interop issue where RARP packets got suppressed with +bridge neigh suppression enabled, but the check in the code was meant to +suppress GARP. Exclude RARP packets from it which would allow some VMWare +setups to work, to quote the report: +"Those RARP packets usually get generated by vMware to notify physical +switches when vMotion occurs. vMware may use random sip/tip or just use +sip=tip=0. So the RARP packet sometimes get properly flooded by the vtep +and other times get dropped by the logic" + +Reported-by: Amer Abdalamer +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/bridge/br_arp_nd_proxy.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c +index dfec65eca8a6..3db1def4437b 100644 +--- a/net/bridge/br_arp_nd_proxy.c ++++ b/net/bridge/br_arp_nd_proxy.c +@@ -160,7 +160,9 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br, + if (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) { + if (p && (p->flags & BR_NEIGH_SUPPRESS)) + return; +- if (ipv4_is_zeronet(sip) || sip == tip) { ++ if (parp->ar_op != htons(ARPOP_RREQUEST) && ++ parp->ar_op != htons(ARPOP_RREPLY) && ++ (ipv4_is_zeronet(sip) || sip == tip)) { + /* prevent flooding to neigh suppress ports */ + BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1; + return; +-- +2.30.2 + diff --git a/queue-5.12/net-ethernet-mtk_eth_soc-fix-rx-vlan-offload.patch b/queue-5.12/net-ethernet-mtk_eth_soc-fix-rx-vlan-offload.patch new file mode 100644 index 00000000000..4469f46fd11 --- /dev/null +++ b/queue-5.12/net-ethernet-mtk_eth_soc-fix-rx-vlan-offload.patch @@ -0,0 +1,50 @@ +From a51874a3c46a78da9f6510d30d5341d15232a651 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Apr 2021 22:20:54 -0700 +Subject: net: ethernet: mtk_eth_soc: fix RX VLAN offload + +From: Felix Fietkau + +[ Upstream commit 3f57d8c40fea9b20543cab4da12f4680d2ef182c ] + +The VLAN ID in the rx descriptor is only valid if the RX_DMA_VTAG bit is +set. Fixes frames wrongly marked with VLAN tags. + +Signed-off-by: Felix Fietkau +[Ilya: fix commit message] +Signed-off-by: Ilya Lipnitskiy +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 01d3ee4b5829..bcd5e7ae8482 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1319,7 +1319,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, + skb->protocol = eth_type_trans(skb, netdev); + + if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX && +- RX_DMA_VID(trxd.rxd3)) ++ (trxd.rxd2 & RX_DMA_VTAG)) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + RX_DMA_VID(trxd.rxd3)); + skb_record_rx_queue(skb, 0); +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index fd3cec8f06ba..c47272100615 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -296,6 +296,7 @@ + #define RX_DMA_LSO BIT(30) + #define RX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16) + #define RX_DMA_GET_PLEN0(_x) (((_x) >> 16) & 0x3fff) ++#define RX_DMA_VTAG BIT(15) + + /* QDMA descriptor rxd3 */ + #define RX_DMA_VID(_x) ((_x) & 0xfff) +-- +2.30.2 + diff --git a/queue-5.12/net-fec-use-mac-managed-phy-pm.patch b/queue-5.12/net-fec-use-mac-managed-phy-pm.patch new file mode 100644 index 00000000000..b29acc99d19 --- /dev/null +++ b/queue-5.12/net-fec-use-mac-managed-phy-pm.patch @@ -0,0 +1,45 @@ +From 02c6f5bbbb9a24d467f475c65ff65fb0c6a56a34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Apr 2021 17:52:45 +0200 +Subject: net: fec: use mac-managed PHY PM + +From: Heiner Kallweit + +[ Upstream commit 557d5dc83f6831b4e54d141e9b121850406f9a60 ] + +Use the new mac_managed_pm flag to work around an issue with KSZ8081 PHY +that becomes unstable when a soft reset is triggered during aneg. + +Reported-by: Joakim Zhang +Tested-by: Joakim Zhang +Signed-off-by: Heiner Kallweit +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 3db882322b2b..70aea9c274fe 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -2048,6 +2048,8 @@ static int fec_enet_mii_probe(struct net_device *ndev) + fep->link = 0; + fep->full_duplex = 0; + ++ phy_dev->mac_managed_pm = 1; ++ + phy_attached_info(phy_dev); + + return 0; +@@ -3864,6 +3866,7 @@ static int __maybe_unused fec_resume(struct device *dev) + netif_device_attach(ndev); + netif_tx_unlock_bh(ndev); + napi_enable(&fep->napi); ++ phy_init_hw(ndev->phydev); + phy_start(ndev->phydev); + } + rtnl_unlock(); +-- +2.30.2 + diff --git a/queue-5.12/net-fix-nla_strcmp-to-handle-more-then-one-trailing-.patch b/queue-5.12/net-fix-nla_strcmp-to-handle-more-then-one-trailing-.patch new file mode 100644 index 00000000000..5c4ed4620cf --- /dev/null +++ b/queue-5.12/net-fix-nla_strcmp-to-handle-more-then-one-trailing-.patch @@ -0,0 +1,52 @@ +From a0d3accb9c29d0ad226261eaaa971a74cf6eac1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 May 2021 09:58:31 -0700 +Subject: net: fix nla_strcmp to handle more then one trailing null character +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maciej Å»enczykowski + +[ Upstream commit 2c16db6c92b0ee4aa61e88366df82169e83c3f7e ] + +Android userspace has been using TCA_KIND with a char[IFNAMESIZ] +many-null-terminated buffer containing the string 'bpf'. + +This works on 4.19 and ceases to work on 5.10. + +I'm not entirely sure what fixes tag to use, but I think the issue +was likely introduced in the below mentioned 5.4 commit. + +Reported-by: Nucca Chen +Cc: Cong Wang +Cc: David Ahern +Cc: David S. Miller +Cc: Jakub Kicinski +Cc: Jamal Hadi Salim +Cc: Jiri Pirko +Cc: Jiri Pirko +Fixes: 62794fc4fbf5 ("net_sched: add max len check for TCA_KIND") +Change-Id: I66dc281f165a2858fc29a44869a270a2d698a82b +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + lib/nlattr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/nlattr.c b/lib/nlattr.c +index 5b6116e81f9f..1d051ef66afe 100644 +--- a/lib/nlattr.c ++++ b/lib/nlattr.c +@@ -828,7 +828,7 @@ int nla_strcmp(const struct nlattr *nla, const char *str) + int attrlen = nla_len(nla); + int d; + +- if (attrlen > 0 && buf[attrlen - 1] == '\0') ++ while (attrlen > 0 && buf[attrlen - 1] == '\0') + attrlen--; + + d = attrlen - len; +-- +2.30.2 + diff --git a/queue-5.12/net-hns3-add-check-for-hns3_nic_state_inited-in-hns3.patch b/queue-5.12/net-hns3-add-check-for-hns3_nic_state_inited-in-hns3.patch new file mode 100644 index 00000000000..1b727ec3774 --- /dev/null +++ b/queue-5.12/net-hns3-add-check-for-hns3_nic_state_inited-in-hns3.patch @@ -0,0 +1,44 @@ +From 34586bf93c298a14d36d7b7494a921719e96dc73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 16:34:52 +0800 +Subject: net: hns3: add check for HNS3_NIC_STATE_INITED in + hns3_reset_notify_up_enet() + +From: Jian Shen + +[ Upstream commit b4047aac4ec1066bab6c71950623746d7bcf7154 ] + +In some cases, the device is not initialized because reset failed. +If another task calls hns3_reset_notify_up_enet() before reset +retry, it will cause an error since uninitialized pointer access. +So add check for HNS3_NIC_STATE_INITED before calling +hns3_nic_net_open() in hns3_reset_notify_up_enet(). + +Fixes: bb6b94a896d4 ("net: hns3: Add reset interface implementation in client") +Signed-off-by: Jian Shen +Signed-off-by: Huazhong Tan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +index b19df09ffb76..59d4d1e87f65 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -4588,6 +4588,11 @@ static int hns3_reset_notify_up_enet(struct hnae3_handle *handle) + struct hns3_nic_priv *priv = netdev_priv(kinfo->netdev); + int ret = 0; + ++ if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state)) { ++ netdev_err(kinfo->netdev, "device is not initialized yet\n"); ++ return -EFAULT; ++ } ++ + clear_bit(HNS3_NIC_STATE_RESETTING, &priv->state); + + if (netif_running(kinfo->netdev)) { +-- +2.30.2 + diff --git a/queue-5.12/net-hns3-add-handling-for-xmit-skb-with-recursive-fr.patch b/queue-5.12/net-hns3-add-handling-for-xmit-skb-with-recursive-fr.patch new file mode 100644 index 00000000000..3df5b6f9e9a --- /dev/null +++ b/queue-5.12/net-hns3-add-handling-for-xmit-skb-with-recursive-fr.patch @@ -0,0 +1,297 @@ +From ab9971f45fc1cfbb205d9cb93d08c39b080a7ee8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Mar 2021 11:57:50 +0800 +Subject: net: hns3: add handling for xmit skb with recursive fraglist + +From: Yunsheng Lin + +[ Upstream commit d5d5e0193ee8f88efbbc7f1471087255657bc19a ] + +Currently hns3 driver only handle the xmit skb with one level of +fraglist skb, add handling for multi level by calling hns3_tx_bd_num() +recursively when calculating bd num and calling hns3_fill_skb_to_desc() +recursively when filling tx desc. + +When the skb has a fraglist level of 24, the skb is simply dropped and +stats.max_recursion_level is added to record the error. Move the stat +handling from hns3_nic_net_xmit() to hns3_nic_maybe_stop_tx() in order +to handle different error stat and add the 'max_recursion_level' and +'hw_limitation' stat. + +Note that the max recursive level as 24 is chose according to below: +commit 48a1df65334b ("skbuff: return -EMSGSIZE in skb_to_sgvec to +prevent overflow"). + +And that we are not able to find a testcase to verify the recursive +fraglist case, so Fixes tag is not provided. + +Reported-by: Barry Song +Signed-off-by: Yunsheng Lin +Signed-off-by: Huazhong Tan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + .../net/ethernet/hisilicon/hns3/hns3_enet.c | 115 +++++++++++------- + .../net/ethernet/hisilicon/hns3/hns3_enet.h | 2 + + .../ethernet/hisilicon/hns3/hns3_ethtool.c | 2 + + 3 files changed, 78 insertions(+), 41 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +index 65752f363f43..b19df09ffb76 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -1277,23 +1277,21 @@ static unsigned int hns3_skb_bd_num(struct sk_buff *skb, unsigned int *bd_size, + } + + static unsigned int hns3_tx_bd_num(struct sk_buff *skb, unsigned int *bd_size, +- u8 max_non_tso_bd_num) ++ u8 max_non_tso_bd_num, unsigned int bd_num, ++ unsigned int recursion_level) + { ++#define HNS3_MAX_RECURSION_LEVEL 24 ++ + struct sk_buff *frag_skb; +- unsigned int bd_num = 0; + + /* If the total len is within the max bd limit */ +- if (likely(skb->len <= HNS3_MAX_BD_SIZE && !skb_has_frag_list(skb) && ++ if (likely(skb->len <= HNS3_MAX_BD_SIZE && !recursion_level && ++ !skb_has_frag_list(skb) && + skb_shinfo(skb)->nr_frags < max_non_tso_bd_num)) + return skb_shinfo(skb)->nr_frags + 1U; + +- /* The below case will always be linearized, return +- * HNS3_MAX_BD_NUM_TSO + 1U to make sure it is linearized. +- */ +- if (unlikely(skb->len > HNS3_MAX_TSO_SIZE || +- (!skb_is_gso(skb) && skb->len > +- HNS3_MAX_NON_TSO_SIZE(max_non_tso_bd_num)))) +- return HNS3_MAX_TSO_BD_NUM + 1U; ++ if (unlikely(recursion_level >= HNS3_MAX_RECURSION_LEVEL)) ++ return UINT_MAX; + + bd_num = hns3_skb_bd_num(skb, bd_size, bd_num); + +@@ -1301,7 +1299,8 @@ static unsigned int hns3_tx_bd_num(struct sk_buff *skb, unsigned int *bd_size, + return bd_num; + + skb_walk_frags(skb, frag_skb) { +- bd_num = hns3_skb_bd_num(frag_skb, bd_size, bd_num); ++ bd_num = hns3_tx_bd_num(frag_skb, bd_size, max_non_tso_bd_num, ++ bd_num, recursion_level + 1); + if (bd_num > HNS3_MAX_TSO_BD_NUM) + return bd_num; + } +@@ -1361,6 +1360,43 @@ void hns3_shinfo_pack(struct skb_shared_info *shinfo, __u32 *size) + size[i] = skb_frag_size(&shinfo->frags[i]); + } + ++static int hns3_skb_linearize(struct hns3_enet_ring *ring, ++ struct sk_buff *skb, ++ u8 max_non_tso_bd_num, ++ unsigned int bd_num) ++{ ++ /* 'bd_num == UINT_MAX' means the skb' fraglist has a ++ * recursion level of over HNS3_MAX_RECURSION_LEVEL. ++ */ ++ if (bd_num == UINT_MAX) { ++ u64_stats_update_begin(&ring->syncp); ++ ring->stats.over_max_recursion++; ++ u64_stats_update_end(&ring->syncp); ++ return -ENOMEM; ++ } ++ ++ /* The skb->len has exceeded the hw limitation, linearization ++ * will not help. ++ */ ++ if (skb->len > HNS3_MAX_TSO_SIZE || ++ (!skb_is_gso(skb) && skb->len > ++ HNS3_MAX_NON_TSO_SIZE(max_non_tso_bd_num))) { ++ u64_stats_update_begin(&ring->syncp); ++ ring->stats.hw_limitation++; ++ u64_stats_update_end(&ring->syncp); ++ return -ENOMEM; ++ } ++ ++ if (__skb_linearize(skb)) { ++ u64_stats_update_begin(&ring->syncp); ++ ring->stats.sw_err_cnt++; ++ u64_stats_update_end(&ring->syncp); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ + static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, + struct net_device *netdev, + struct sk_buff *skb) +@@ -1370,7 +1406,7 @@ static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, + unsigned int bd_size[HNS3_MAX_TSO_BD_NUM + 1U]; + unsigned int bd_num; + +- bd_num = hns3_tx_bd_num(skb, bd_size, max_non_tso_bd_num); ++ bd_num = hns3_tx_bd_num(skb, bd_size, max_non_tso_bd_num, 0, 0); + if (unlikely(bd_num > max_non_tso_bd_num)) { + if (bd_num <= HNS3_MAX_TSO_BD_NUM && skb_is_gso(skb) && + !hns3_skb_need_linearized(skb, bd_size, bd_num, +@@ -1379,16 +1415,11 @@ static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, + goto out; + } + +- if (__skb_linearize(skb)) ++ if (hns3_skb_linearize(ring, skb, max_non_tso_bd_num, ++ bd_num)) + return -ENOMEM; + + bd_num = hns3_tx_bd_count(skb->len); +- if ((skb_is_gso(skb) && bd_num > HNS3_MAX_TSO_BD_NUM) || +- (!skb_is_gso(skb) && +- bd_num > max_non_tso_bd_num)) { +- trace_hns3_over_max_bd(skb); +- return -ENOMEM; +- } + + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_copy++; +@@ -1412,6 +1443,10 @@ out: + return bd_num; + } + ++ u64_stats_update_begin(&ring->syncp); ++ ring->stats.tx_busy++; ++ u64_stats_update_end(&ring->syncp); ++ + return -EBUSY; + } + +@@ -1459,6 +1494,7 @@ static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring, + struct sk_buff *skb, enum hns_desc_type type) + { + unsigned int size = skb_headlen(skb); ++ struct sk_buff *frag_skb; + int i, ret, bd_num = 0; + + if (size) { +@@ -1483,6 +1519,15 @@ static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring, + bd_num += ret; + } + ++ skb_walk_frags(skb, frag_skb) { ++ ret = hns3_fill_skb_to_desc(ring, frag_skb, ++ DESC_TYPE_FRAGLIST_SKB); ++ if (unlikely(ret < 0)) ++ return ret; ++ ++ bd_num += ret; ++ } ++ + return bd_num; + } + +@@ -1513,8 +1558,6 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) + struct hns3_enet_ring *ring = &priv->ring[skb->queue_mapping]; + struct netdev_queue *dev_queue; + int pre_ntu, next_to_use_head; +- struct sk_buff *frag_skb; +- int bd_num = 0; + bool doorbell; + int ret; + +@@ -1530,15 +1573,8 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) + ret = hns3_nic_maybe_stop_tx(ring, netdev, skb); + if (unlikely(ret <= 0)) { + if (ret == -EBUSY) { +- u64_stats_update_begin(&ring->syncp); +- ring->stats.tx_busy++; +- u64_stats_update_end(&ring->syncp); + hns3_tx_doorbell(ring, 0, true); + return NETDEV_TX_BUSY; +- } else if (ret == -ENOMEM) { +- u64_stats_update_begin(&ring->syncp); +- ring->stats.sw_err_cnt++; +- u64_stats_update_end(&ring->syncp); + } + + hns3_rl_err(netdev, "xmit error: %d!\n", ret); +@@ -1551,21 +1587,14 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) + if (unlikely(ret < 0)) + goto fill_err; + ++ /* 'ret < 0' means filling error, 'ret == 0' means skb->len is ++ * zero, which is unlikely, and 'ret > 0' means how many tx desc ++ * need to be notified to the hw. ++ */ + ret = hns3_fill_skb_to_desc(ring, skb, DESC_TYPE_SKB); +- if (unlikely(ret < 0)) ++ if (unlikely(ret <= 0)) + goto fill_err; + +- bd_num += ret; +- +- skb_walk_frags(skb, frag_skb) { +- ret = hns3_fill_skb_to_desc(ring, frag_skb, +- DESC_TYPE_FRAGLIST_SKB); +- if (unlikely(ret < 0)) +- goto fill_err; +- +- bd_num += ret; +- } +- + pre_ntu = ring->next_to_use ? (ring->next_to_use - 1) : + (ring->desc_num - 1); + ring->desc[pre_ntu].tx.bdtp_fe_sc_vld_ra_ri |= +@@ -1576,7 +1605,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) + dev_queue = netdev_get_tx_queue(netdev, ring->queue_index); + doorbell = __netdev_tx_sent_queue(dev_queue, skb->len, + netdev_xmit_more()); +- hns3_tx_doorbell(ring, bd_num, doorbell); ++ hns3_tx_doorbell(ring, ret, doorbell); + + return NETDEV_TX_OK; + +@@ -1748,11 +1777,15 @@ static void hns3_nic_get_stats64(struct net_device *netdev, + tx_drop += ring->stats.tx_l4_proto_err; + tx_drop += ring->stats.tx_l2l3l4_err; + tx_drop += ring->stats.tx_tso_err; ++ tx_drop += ring->stats.over_max_recursion; ++ tx_drop += ring->stats.hw_limitation; + tx_errors += ring->stats.sw_err_cnt; + tx_errors += ring->stats.tx_vlan_err; + tx_errors += ring->stats.tx_l4_proto_err; + tx_errors += ring->stats.tx_l2l3l4_err; + tx_errors += ring->stats.tx_tso_err; ++ tx_errors += ring->stats.over_max_recursion; ++ tx_errors += ring->stats.hw_limitation; + } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); + + /* fetch the rx stats */ +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +index d069b04ee587..e44224e23315 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +@@ -376,6 +376,8 @@ struct ring_stats { + u64 tx_l4_proto_err; + u64 tx_l2l3l4_err; + u64 tx_tso_err; ++ u64 over_max_recursion; ++ u64 hw_limitation; + }; + struct { + u64 rx_pkts; +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +index adcec4ea7cb9..d20f2e246017 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +@@ -44,6 +44,8 @@ static const struct hns3_stats hns3_txq_stats[] = { + HNS3_TQP_STAT("l4_proto_err", tx_l4_proto_err), + HNS3_TQP_STAT("l2l3l4_err", tx_l2l3l4_err), + HNS3_TQP_STAT("tso_err", tx_tso_err), ++ HNS3_TQP_STAT("over_max_recursion", over_max_recursion), ++ HNS3_TQP_STAT("hw_limitation", hw_limitation), + }; + + #define HNS3_TXQ_STATS_COUNT ARRAY_SIZE(hns3_txq_stats) +-- +2.30.2 + diff --git a/queue-5.12/net-hns3-disable-phy-loopback-setting-in-hclge_mac_s.patch b/queue-5.12/net-hns3-disable-phy-loopback-setting-in-hclge_mac_s.patch new file mode 100644 index 00000000000..db795a50b9f --- /dev/null +++ b/queue-5.12/net-hns3-disable-phy-loopback-setting-in-hclge_mac_s.patch @@ -0,0 +1,39 @@ +From c385383b1e50c598f1cbc2796f73553861c4e5a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Apr 2021 17:06:22 +0800 +Subject: net: hns3: disable phy loopback setting in hclge_mac_start_phy + +From: Yufeng Mo + +[ Upstream commit 472497d0bdae890a896013332a0b673f9acdf2bf ] + +If selftest and reset are performed at the same time, the phy +loopback setting may be still in enable state after the reset, +and device cannot link up. So fix this issue by disabling phy +loopback before phy_start(). + +Fixes: 256727da7395 ("net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC") +Signed-off-by: Yufeng Mo +Signed-off-by: Huazhong Tan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +index e89820702540..c194bba187d6 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +@@ -255,6 +255,8 @@ void hclge_mac_start_phy(struct hclge_dev *hdev) + if (!phydev) + return; + ++ phy_loopback(phydev, false); ++ + phy_start(phydev); + } + +-- +2.30.2 + diff --git a/queue-5.12/net-hns3-fix-for-vxlan-gpe-tx-checksum-bug.patch b/queue-5.12/net-hns3-fix-for-vxlan-gpe-tx-checksum-bug.patch new file mode 100644 index 00000000000..016d06c9b9a --- /dev/null +++ b/queue-5.12/net-hns3-fix-for-vxlan-gpe-tx-checksum-bug.patch @@ -0,0 +1,51 @@ +From 13b37855db0f68988a52de869c23d4bb589f3246 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Apr 2021 17:06:19 +0800 +Subject: net: hns3: fix for vxlan gpe tx checksum bug + +From: Hao Chen + +[ Upstream commit 905416f18fe74bdd4de91bf94ef5a790a36e4b99 ] + +When skb->ip_summed is CHECKSUM_PARTIAL, for non-tunnel udp packet, +which has a dest port as the IANA assigned, the hardware is expected +to do the checksum offload, but the hardware whose version is below +V3 will not do the checksum offload when udp dest port is 4790. + +So fixes it by doing the checksum in software for this case. + +Fixes: 76ad4f0ee747 ("net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC") +Signed-off-by: Hao Chen +Signed-off-by: Huazhong Tan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +index 59d4d1e87f65..d24bafb7ce46 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -823,7 +823,7 @@ static int hns3_get_l4_protocol(struct sk_buff *skb, u8 *ol4_proto, + * and it is udp packet, which has a dest port as the IANA assigned. + * the hardware is expected to do the checksum offload, but the + * hardware will not do the checksum offload when udp dest port is +- * 4789 or 6081. ++ * 4789, 4790 or 6081. + */ + static bool hns3_tunnel_csum_bug(struct sk_buff *skb) + { +@@ -841,7 +841,8 @@ static bool hns3_tunnel_csum_bug(struct sk_buff *skb) + + if (!(!skb->encapsulation && + (l4.udp->dest == htons(IANA_VXLAN_UDP_PORT) || +- l4.udp->dest == htons(GENEVE_UDP_PORT)))) ++ l4.udp->dest == htons(GENEVE_UDP_PORT) || ++ l4.udp->dest == htons(4790)))) + return false; + + skb_checksum_help(skb); +-- +2.30.2 + diff --git a/queue-5.12/net-hns3-fix-incorrect-configuration-for-igu_egu_hw_.patch b/queue-5.12/net-hns3-fix-incorrect-configuration-for-igu_egu_hw_.patch new file mode 100644 index 00000000000..1a43c3f177b --- /dev/null +++ b/queue-5.12/net-hns3-fix-incorrect-configuration-for-igu_egu_hw_.patch @@ -0,0 +1,56 @@ +From 8bbcdd994fa2d01989825fd4b7b16621f0f795c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 16:34:50 +0800 +Subject: net: hns3: fix incorrect configuration for igu_egu_hw_err + +From: Yufeng Mo + +[ Upstream commit 2867298dd49ee84214b8721521dc7a5a6382520c ] + +According to the UM, the type and enable status of igu_egu_hw_err +should be configured separately. Currently, the type field is +incorrect when disable this error. So fix it by configuring these +two fields separately. + +Fixes: bf1faf9415dd ("net: hns3: Add enable and process hw errors from IGU, EGU and NCSI") +Signed-off-by: Yufeng Mo +Signed-off-by: Huazhong Tan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 3 ++- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +index 0ca7f1b984bf..78d3eb142df8 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +@@ -753,8 +753,9 @@ static int hclge_config_igu_egu_hw_err_int(struct hclge_dev *hdev, bool en) + + /* configure IGU,EGU error interrupts */ + hclge_cmd_setup_basic_desc(&desc, HCLGE_IGU_COMMON_INT_EN, false); ++ desc.data[0] = cpu_to_le32(HCLGE_IGU_ERR_INT_TYPE); + if (en) +- desc.data[0] = cpu_to_le32(HCLGE_IGU_ERR_INT_EN); ++ desc.data[0] |= cpu_to_le32(HCLGE_IGU_ERR_INT_EN); + + desc.data[1] = cpu_to_le32(HCLGE_IGU_ERR_INT_EN_MASK); + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h +index 608fe26fc3fe..d647f3c84134 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h +@@ -32,7 +32,8 @@ + #define HCLGE_TQP_ECC_ERR_INT_EN_MASK 0x0FFF + #define HCLGE_MSIX_SRAM_ECC_ERR_INT_EN_MASK 0x0F000000 + #define HCLGE_MSIX_SRAM_ECC_ERR_INT_EN 0x0F000000 +-#define HCLGE_IGU_ERR_INT_EN 0x0000066F ++#define HCLGE_IGU_ERR_INT_EN 0x0000000F ++#define HCLGE_IGU_ERR_INT_TYPE 0x00000660 + #define HCLGE_IGU_ERR_INT_EN_MASK 0x000F + #define HCLGE_IGU_TNL_ERR_INT_EN 0x0002AABF + #define HCLGE_IGU_TNL_ERR_INT_EN_MASK 0x003F +-- +2.30.2 + diff --git a/queue-5.12/net-hns3-initialize-the-message-content-in-hclge_get.patch b/queue-5.12/net-hns3-initialize-the-message-content-in-hclge_get.patch new file mode 100644 index 00000000000..f24ecef6a3c --- /dev/null +++ b/queue-5.12/net-hns3-initialize-the-message-content-in-hclge_get.patch @@ -0,0 +1,38 @@ +From 2691ddfbf42408d100ff0211c8200351f24f0f1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 16:34:51 +0800 +Subject: net: hns3: initialize the message content in hclge_get_link_mode() + +From: Yufeng Mo + +[ Upstream commit 568a54bdf70b143f3e0befa298e22ad469ffc732 ] + +The message sent to VF should be initialized, otherwise random +value of some contents may cause improper processing by the target. +So add a initialization to message in hclge_get_link_mode(). + +Fixes: 9194d18b0577 ("net: hns3: fix the problem that the supported port is empty") +Signed-off-by: Yufeng Mo +Signed-off-by: Huazhong Tan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +index 51a36e74f088..c3bb16b1f060 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +@@ -535,7 +535,7 @@ static void hclge_get_link_mode(struct hclge_vport *vport, + unsigned long advertising; + unsigned long supported; + unsigned long send_data; +- u8 msg_data[10]; ++ u8 msg_data[10] = {}; + u8 dest_vfid; + + advertising = hdev->hw.mac.advertising[0]; +-- +2.30.2 + diff --git a/queue-5.12/net-hns3-remediate-a-potential-overflow-risk-of-bd_n.patch b/queue-5.12/net-hns3-remediate-a-potential-overflow-risk-of-bd_n.patch new file mode 100644 index 00000000000..184d8c46124 --- /dev/null +++ b/queue-5.12/net-hns3-remediate-a-potential-overflow-risk-of-bd_n.patch @@ -0,0 +1,113 @@ +From 7f6031e500a116e0487f33e4637f5c376551e272 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Mar 2021 11:57:47 +0800 +Subject: net: hns3: remediate a potential overflow risk of bd_num_list + +From: Guangbin Huang + +[ Upstream commit a2ee6fd28a190588e142ad8ea9d40069cd3c9f98 ] + +The array size of bd_num_list is a fixed value, it may have potential +overflow risk when array size of hclge_dfx_bd_offset_list is greater +than that fixed value. So modify bd_num_list as a pointer and allocate +memory for it according to array size of hclge_dfx_bd_offset_list. + +Signed-off-by: Guangbin Huang +Signed-off-by: Huazhong Tan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + .../hisilicon/hns3/hns3pf/hclge_main.c | 27 ++++++++++++++----- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index b0dbe6dcaa7b..7a560d0e19b9 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -11379,7 +11379,6 @@ static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num, + #define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) + #define REG_SEPARATOR_LINE 1 + #define REG_NUM_REMAIN_MASK 3 +-#define BD_LIST_MAX_NUM 30 + + int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc) + { +@@ -11473,15 +11472,19 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) + { + u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); + int data_len_per_desc, bd_num, i; +- int bd_num_list[BD_LIST_MAX_NUM]; ++ int *bd_num_list; + u32 data_len; + int ret; + ++ bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); ++ if (!bd_num_list) ++ return -ENOMEM; ++ + ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg bd num fail, status is %d.\n", ret); +- return ret; ++ goto out; + } + + data_len_per_desc = sizeof_field(struct hclge_desc, data); +@@ -11492,6 +11495,8 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) + *len += (data_len / REG_LEN_PER_LINE + 1) * REG_LEN_PER_LINE; + } + ++out: ++ kfree(bd_num_list); + return ret; + } + +@@ -11499,16 +11504,20 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) + { + u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); + int bd_num, bd_num_max, buf_len, i; +- int bd_num_list[BD_LIST_MAX_NUM]; + struct hclge_desc *desc_src; ++ int *bd_num_list; + u32 *reg = data; + int ret; + ++ bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); ++ if (!bd_num_list) ++ return -ENOMEM; ++ + ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg bd num fail, status is %d.\n", ret); +- return ret; ++ goto out; + } + + bd_num_max = bd_num_list[0]; +@@ -11517,8 +11526,10 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) + + buf_len = sizeof(*desc_src) * bd_num_max; + desc_src = kzalloc(buf_len, GFP_KERNEL); +- if (!desc_src) +- return -ENOMEM; ++ if (!desc_src) { ++ ret = -ENOMEM; ++ goto out; ++ } + + for (i = 0; i < dfx_reg_type_num; i++) { + bd_num = bd_num_list[i]; +@@ -11534,6 +11545,8 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) + } + + kfree(desc_src); ++out: ++ kfree(bd_num_list); + return ret; + } + +-- +2.30.2 + diff --git a/queue-5.12/net-hns3-use-netif_tx_disable-to-stop-the-transmit-q.patch b/queue-5.12/net-hns3-use-netif_tx_disable-to-stop-the-transmit-q.patch new file mode 100644 index 00000000000..8302c3ad591 --- /dev/null +++ b/queue-5.12/net-hns3-use-netif_tx_disable-to-stop-the-transmit-q.patch @@ -0,0 +1,44 @@ +From d32a49f37bf804e9660a9eacd2f4e6a0d9db42b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Apr 2021 17:06:20 +0800 +Subject: net: hns3: use netif_tx_disable to stop the transmit queue + +From: Peng Li + +[ Upstream commit b416e872be06fdace3c36cf5210130509d0f0e72 ] + +Currently, netif_tx_stop_all_queues() is used to ensure that +the xmit is not running, but for the concurrent case it will +not take effect, since netif_tx_stop_all_queues() just sets +a flag without locking to indicate that the xmit queue(s) +should not be run. + +So use netif_tx_disable() to replace netif_tx_stop_all_queues(), +it takes the xmit queue lock while marking the queue stopped. + +Fixes: 76ad4f0ee747 ("net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC") +Signed-off-by: Peng Li +Signed-off-by: Huazhong Tan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +index d24bafb7ce46..0f70158c2551 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -576,8 +576,8 @@ static int hns3_nic_net_stop(struct net_device *netdev) + if (h->ae_algo->ops->set_timer_task) + h->ae_algo->ops->set_timer_task(priv->ae_handle, false); + +- netif_tx_stop_all_queues(netdev); + netif_carrier_off(netdev); ++ netif_tx_disable(netdev); + + hns3_nic_net_down(netdev); + +-- +2.30.2 + diff --git a/queue-5.12/net-ipa-fix-inter-ee-irq-register-definitions.patch b/queue-5.12/net-ipa-fix-inter-ee-irq-register-definitions.patch new file mode 100644 index 00000000000..810ac0014ea --- /dev/null +++ b/queue-5.12/net-ipa-fix-inter-ee-irq-register-definitions.patch @@ -0,0 +1,76 @@ +From 5318348409d3e19250f5c32d1cb023458ba58af6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 May 2021 17:36:36 -0500 +Subject: net: ipa: fix inter-EE IRQ register definitions + +From: Alex Elder + +[ Upstream commit 6a780f51f87b430cc69ebf4e859e7e9be720b283 ] + +In gsi_irq_setup(), two registers are written with the intention of +disabling inter-EE channel and event IRQs. + +But the wrong registers are used (and defined); the ones used are +read-only registers that indicate whether the interrupt condition is +present. + +Define the mask registers instead of the status registers, and use +them to disable the inter-EE interrupt types. + +Fixes: 46f748ccaf01 ("net: ipa: explicitly disallow inter-EE interrupts") +Signed-off-by: Alex Elder +Link: https://lore.kernel.org/r/20210505223636.232527-1-elder@linaro.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ipa/gsi.c | 4 ++-- + drivers/net/ipa/gsi_reg.h | 18 +++++++++--------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c +index 390d3403386a..144892060718 100644 +--- a/drivers/net/ipa/gsi.c ++++ b/drivers/net/ipa/gsi.c +@@ -211,8 +211,8 @@ static void gsi_irq_setup(struct gsi *gsi) + iowrite32(0, gsi->virt + GSI_CNTXT_SRC_IEOB_IRQ_MSK_OFFSET); + + /* The inter-EE registers are in the non-adjusted address range */ +- iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_CH_IRQ_OFFSET); +- iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_EV_CH_IRQ_OFFSET); ++ iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_CH_IRQ_MSK_OFFSET); ++ iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_EV_CH_IRQ_MSK_OFFSET); + + iowrite32(0, gsi->virt + GSI_CNTXT_GSI_IRQ_EN_OFFSET); + } +diff --git a/drivers/net/ipa/gsi_reg.h b/drivers/net/ipa/gsi_reg.h +index 1622d8cf8dea..48ef04afab79 100644 +--- a/drivers/net/ipa/gsi_reg.h ++++ b/drivers/net/ipa/gsi_reg.h +@@ -53,15 +53,15 @@ + #define GSI_EE_REG_ADJUST 0x0000d000 /* IPA v4.5+ */ + + /* The two inter-EE IRQ register offsets are relative to gsi->virt_raw */ +-#define GSI_INTER_EE_SRC_CH_IRQ_OFFSET \ +- GSI_INTER_EE_N_SRC_CH_IRQ_OFFSET(GSI_EE_AP) +-#define GSI_INTER_EE_N_SRC_CH_IRQ_OFFSET(ee) \ +- (0x0000c018 + 0x1000 * (ee)) +- +-#define GSI_INTER_EE_SRC_EV_CH_IRQ_OFFSET \ +- GSI_INTER_EE_N_SRC_EV_CH_IRQ_OFFSET(GSI_EE_AP) +-#define GSI_INTER_EE_N_SRC_EV_CH_IRQ_OFFSET(ee) \ +- (0x0000c01c + 0x1000 * (ee)) ++#define GSI_INTER_EE_SRC_CH_IRQ_MSK_OFFSET \ ++ GSI_INTER_EE_N_SRC_CH_IRQ_MSK_OFFSET(GSI_EE_AP) ++#define GSI_INTER_EE_N_SRC_CH_IRQ_MSK_OFFSET(ee) \ ++ (0x0000c020 + 0x1000 * (ee)) ++ ++#define GSI_INTER_EE_SRC_EV_CH_IRQ_MSK_OFFSET \ ++ GSI_INTER_EE_N_SRC_EV_CH_IRQ_MSK_OFFSET(GSI_EE_AP) ++#define GSI_INTER_EE_N_SRC_EV_CH_IRQ_MSK_OFFSET(ee) \ ++ (0x0000c024 + 0x1000 * (ee)) + + /* All other register offsets are relative to gsi->virt */ + #define GSI_CH_C_CNTXT_0_OFFSET(ch) \ +-- +2.30.2 + diff --git a/queue-5.12/net-mlx5e-use-net_prefetchw-instead-of-prefetchw-in-.patch b/queue-5.12/net-mlx5e-use-net_prefetchw-instead-of-prefetchw-in-.patch new file mode 100644 index 00000000000..9f86fd00ea0 --- /dev/null +++ b/queue-5.12/net-mlx5e-use-net_prefetchw-instead-of-prefetchw-in-.patch @@ -0,0 +1,46 @@ +From b2884930b572b3787193533cf165f659470d8aa2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Jan 2021 18:43:31 +0200 +Subject: net/mlx5e: Use net_prefetchw instead of prefetchw in MPWQE TX + datapath + +From: Maxim Mikityanskiy + +[ Upstream commit 991b2654605b455a94dac73e14b23480e7e20991 ] + +Commit e20f0dbf204f ("net/mlx5e: RX, Add a prefetch command for small +L1_CACHE_BYTES") switched to using net_prefetchw at all places in mlx5e. +In the same time frame, commit 5af75c747e2a ("net/mlx5e: Enhanced TX +MPWQE for SKBs") added one more usage of prefetchw. When these two +changes were merged, this new occurrence of prefetchw wasn't replaced +with net_prefetchw. + +This commit fixes this last occurrence of prefetchw in +mlx5e_tx_mpwqe_session_start, making the same change that was done in +mlx5e_xdp_mpwqe_session_start. + +Signed-off-by: Maxim Mikityanskiy +Reviewed-by: Saeed Mahameed +Reviewed-by: Tariq Toukan +Signed-off-by: Saeed Mahameed +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +index bdbffe484fce..d2efe2455955 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +@@ -576,7 +576,7 @@ static void mlx5e_tx_mpwqe_session_start(struct mlx5e_txqsq *sq, + + pi = mlx5e_txqsq_get_next_pi(sq, MLX5E_TX_MPW_MAX_WQEBBS); + wqe = MLX5E_TX_FETCH_WQE(sq, pi); +- prefetchw(wqe->data); ++ net_prefetchw(wqe->data); + + *session = (struct mlx5e_tx_mpwqe) { + .wqe = wqe, +-- +2.30.2 + diff --git a/queue-5.12/net-phy-make-phy-pm-ops-a-no-op-if-mac-driver-manage.patch b/queue-5.12/net-phy-make-phy-pm-ops-a-no-op-if-mac-driver-manage.patch new file mode 100644 index 00000000000..42fc87508c2 --- /dev/null +++ b/queue-5.12/net-phy-make-phy-pm-ops-a-no-op-if-mac-driver-manage.patch @@ -0,0 +1,74 @@ +From 5aa4697bc9a74e5e4239c74c9b85393cb1852eef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Apr 2021 17:51:56 +0200 +Subject: net: phy: make PHY PM ops a no-op if MAC driver manages PHY PM + +From: Heiner Kallweit + +[ Upstream commit fba863b816049b03f3fbb07b10ebdcfe5c4141f7 ] + +Resume callback of the PHY driver is called after the one for the MAC +driver. The PHY driver resume callback calls phy_init_hw(), and this is +potentially problematic if the MAC driver calls phy_start() in its resume +callback. One issue was reported with the fec driver and a KSZ8081 PHY +which seems to become unstable if a soft reset is triggered during aneg. + +The new flag allows MAC drivers to indicate that they take care of +suspending/resuming the PHY. Then the MAC PM callbacks can handle +any dependency between MAC and PHY PM. + +Signed-off-by: Heiner Kallweit +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/phy_device.c | 6 ++++++ + include/linux/phy.h | 2 ++ + 2 files changed, 8 insertions(+) + +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index cc38e326405a..af2e1759b523 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -273,6 +273,9 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev) + { + struct phy_device *phydev = to_phy_device(dev); + ++ if (phydev->mac_managed_pm) ++ return 0; ++ + /* We must stop the state machine manually, otherwise it stops out of + * control, possibly with the phydev->lock held. Upon resume, netdev + * may call phy routines that try to grab the same lock, and that may +@@ -294,6 +297,9 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev) + struct phy_device *phydev = to_phy_device(dev); + int ret; + ++ if (phydev->mac_managed_pm) ++ return 0; ++ + if (!phydev->suspended_by_mdio_bus) + goto no_resume; + +diff --git a/include/linux/phy.h b/include/linux/phy.h +index 1a12e4436b5b..8644b097dea3 100644 +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -493,6 +493,7 @@ struct macsec_ops; + * @loopback_enabled: Set true if this PHY has been loopbacked successfully. + * @downshifted_rate: Set true if link speed has been downshifted. + * @is_on_sfp_module: Set true if PHY is located on an SFP module. ++ * @mac_managed_pm: Set true if MAC driver takes of suspending/resuming PHY + * @state: State of the PHY for management purposes + * @dev_flags: Device-specific flags used by the PHY driver. + * @irq: IRQ number of the PHY's interrupt (-1 if none) +@@ -567,6 +568,7 @@ struct phy_device { + unsigned loopback_enabled:1; + unsigned downshifted_rate:1; + unsigned is_on_sfp_module:1; ++ unsigned mac_managed_pm:1; + + unsigned autoneg:1; + /* The most recently read link state */ +-- +2.30.2 + diff --git a/queue-5.12/net-sched-cls_flower-use-ntohs-for-struct-flow_disse.patch b/queue-5.12/net-sched-cls_flower-use-ntohs-for-struct-flow_disse.patch new file mode 100644 index 00000000000..e2d698227af --- /dev/null +++ b/queue-5.12/net-sched-cls_flower-use-ntohs-for-struct-flow_disse.patch @@ -0,0 +1,108 @@ +From 62ba0c8e7db81cdcd0257b4a7799afae3b39bd12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Mar 2021 23:05:48 +0200 +Subject: net/sched: cls_flower: use ntohs for struct flow_dissector_key_ports + +From: Vladimir Oltean + +[ Upstream commit 6215afcb9a7e35cef334dc0ae7f998cc72c8465f ] + +A make W=1 build complains that: + +net/sched/cls_flower.c:214:20: warning: cast from restricted __be16 +net/sched/cls_flower.c:214:20: warning: incorrect type in argument 1 (different base types) +net/sched/cls_flower.c:214:20: expected unsigned short [usertype] val +net/sched/cls_flower.c:214:20: got restricted __be16 [usertype] dst + +This is because we use htons on struct flow_dissector_key_ports members +src and dst, which are defined as __be16, so they are already in network +byte order, not host. The byte swap function for the other direction +should have been used. + +Because htons and ntohs do the same thing (either both swap, or none +does), this change has no functional effect except to silence the +warnings. + +Signed-off-by: Vladimir Oltean +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/sched/cls_flower.c | 36 ++++++++++++++++++------------------ + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c +index c69a4ba9c33f..3035f96c6e6c 100644 +--- a/net/sched/cls_flower.c ++++ b/net/sched/cls_flower.c +@@ -209,16 +209,16 @@ static bool fl_range_port_dst_cmp(struct cls_fl_filter *filter, + struct fl_flow_key *key, + struct fl_flow_key *mkey) + { +- __be16 min_mask, max_mask, min_val, max_val; ++ u16 min_mask, max_mask, min_val, max_val; + +- min_mask = htons(filter->mask->key.tp_range.tp_min.dst); +- max_mask = htons(filter->mask->key.tp_range.tp_max.dst); +- min_val = htons(filter->key.tp_range.tp_min.dst); +- max_val = htons(filter->key.tp_range.tp_max.dst); ++ min_mask = ntohs(filter->mask->key.tp_range.tp_min.dst); ++ max_mask = ntohs(filter->mask->key.tp_range.tp_max.dst); ++ min_val = ntohs(filter->key.tp_range.tp_min.dst); ++ max_val = ntohs(filter->key.tp_range.tp_max.dst); + + if (min_mask && max_mask) { +- if (htons(key->tp_range.tp.dst) < min_val || +- htons(key->tp_range.tp.dst) > max_val) ++ if (ntohs(key->tp_range.tp.dst) < min_val || ++ ntohs(key->tp_range.tp.dst) > max_val) + return false; + + /* skb does not have min and max values */ +@@ -232,16 +232,16 @@ static bool fl_range_port_src_cmp(struct cls_fl_filter *filter, + struct fl_flow_key *key, + struct fl_flow_key *mkey) + { +- __be16 min_mask, max_mask, min_val, max_val; ++ u16 min_mask, max_mask, min_val, max_val; + +- min_mask = htons(filter->mask->key.tp_range.tp_min.src); +- max_mask = htons(filter->mask->key.tp_range.tp_max.src); +- min_val = htons(filter->key.tp_range.tp_min.src); +- max_val = htons(filter->key.tp_range.tp_max.src); ++ min_mask = ntohs(filter->mask->key.tp_range.tp_min.src); ++ max_mask = ntohs(filter->mask->key.tp_range.tp_max.src); ++ min_val = ntohs(filter->key.tp_range.tp_min.src); ++ max_val = ntohs(filter->key.tp_range.tp_max.src); + + if (min_mask && max_mask) { +- if (htons(key->tp_range.tp.src) < min_val || +- htons(key->tp_range.tp.src) > max_val) ++ if (ntohs(key->tp_range.tp.src) < min_val || ++ ntohs(key->tp_range.tp.src) > max_val) + return false; + + /* skb does not have min and max values */ +@@ -783,16 +783,16 @@ static int fl_set_key_port_range(struct nlattr **tb, struct fl_flow_key *key, + TCA_FLOWER_UNSPEC, sizeof(key->tp_range.tp_max.src)); + + if (mask->tp_range.tp_min.dst && mask->tp_range.tp_max.dst && +- htons(key->tp_range.tp_max.dst) <= +- htons(key->tp_range.tp_min.dst)) { ++ ntohs(key->tp_range.tp_max.dst) <= ++ ntohs(key->tp_range.tp_min.dst)) { + NL_SET_ERR_MSG_ATTR(extack, + tb[TCA_FLOWER_KEY_PORT_DST_MIN], + "Invalid destination port range (min must be strictly smaller than max)"); + return -EINVAL; + } + if (mask->tp_range.tp_min.src && mask->tp_range.tp_max.src && +- htons(key->tp_range.tp_max.src) <= +- htons(key->tp_range.tp_min.src)) { ++ ntohs(key->tp_range.tp_max.src) <= ++ ntohs(key->tp_range.tp_min.src)) { + NL_SET_ERR_MSG_ATTR(extack, + tb[TCA_FLOWER_KEY_PORT_SRC_MIN], + "Invalid source port range (min must be strictly smaller than max)"); +-- +2.30.2 + diff --git a/queue-5.12/net-sched-tapr-prevent-cycle_time-0-in-parse_taprio_.patch b/queue-5.12/net-sched-tapr-prevent-cycle_time-0-in-parse_taprio_.patch new file mode 100644 index 00000000000..4a4d7858f84 --- /dev/null +++ b/queue-5.12/net-sched-tapr-prevent-cycle_time-0-in-parse_taprio_.patch @@ -0,0 +1,46 @@ +From 2c1dce73bb1f7865e2f4bc26b2e68d71742b6034 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Apr 2021 07:30:46 +0800 +Subject: net: sched: tapr: prevent cycle_time == 0 in parse_taprio_schedule + +From: Du Cheng + +[ Upstream commit ed8157f1ebf1ae81a8fa2653e3f20d2076fad1c9 ] + +There is a reproducible sequence from the userland that will trigger a WARN_ON() +condition in taprio_get_start_time, which causes kernel to panic if configured +as "panic_on_warn". Catch this condition in parse_taprio_schedule to +prevent this condition. + +Reported as bug on syzkaller: +https://syzkaller.appspot.com/bug?extid=d50710fd0873a9c6b40c + +Reported-by: syzbot+d50710fd0873a9c6b40c@syzkaller.appspotmail.com +Signed-off-by: Du Cheng +Acked-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/sched/sch_taprio.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c +index 8287894541e3..909c798b7403 100644 +--- a/net/sched/sch_taprio.c ++++ b/net/sched/sch_taprio.c +@@ -901,6 +901,12 @@ static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb, + + list_for_each_entry(entry, &new->entries, list) + cycle = ktime_add_ns(cycle, entry->interval); ++ ++ if (!cycle) { ++ NL_SET_ERR_MSG(extack, "'cycle_time' can never be 0"); ++ return -EINVAL; ++ } ++ + new->cycle_time = cycle; + } + +-- +2.30.2 + diff --git a/queue-5.12/net-stmmac-clear-receive-all-ra-bit-when-promiscuous.patch b/queue-5.12/net-stmmac-clear-receive-all-ra-bit-when-promiscuous.patch new file mode 100644 index 00000000000..4c46a4e44df --- /dev/null +++ b/queue-5.12/net-stmmac-clear-receive-all-ra-bit-when-promiscuous.patch @@ -0,0 +1,37 @@ +From 2de0182e4294b98fa3e5ee29d08f5817c3bc0811 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 May 2021 21:12:41 +0530 +Subject: net: stmmac: Clear receive all(RA) bit when promiscuous mode is off + +From: Ramesh Babu B + +[ Upstream commit 4c7a94286ef7ac7301d633f17519fb1bb89d7550 ] + +In promiscuous mode Receive All bit is set in GMAC packet filter register, +but outside promiscuous mode Receive All bit is not cleared, +which resulted in all network packets are received when toggle (ON/OFF) +the promiscuous mode. + +Fixes: e0f9956a3862 ("net: stmmac: Add option for VLAN filter fail queue enable") +Signed-off-by: Ramesh Babu B +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +index 29f765a246a0..aaf37598cbd3 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +@@ -638,6 +638,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw, + value &= ~GMAC_PACKET_FILTER_PCF; + value &= ~GMAC_PACKET_FILTER_PM; + value &= ~GMAC_PACKET_FILTER_PR; ++ value &= ~GMAC_PACKET_FILTER_RA; + if (dev->flags & IFF_PROMISC) { + /* VLAN Tag Filter Fail Packets Queuing */ + if (hw->vlan_fail_q_en) { +-- +2.30.2 + diff --git a/queue-5.12/net-stmmac-set-fifo-sizes-for-ipq806x.patch b/queue-5.12/net-stmmac-set-fifo-sizes-for-ipq806x.patch new file mode 100644 index 00000000000..948d0c99f19 --- /dev/null +++ b/queue-5.12/net-stmmac-set-fifo-sizes-for-ipq806x.patch @@ -0,0 +1,44 @@ +From 098663522e9284fdfd77066a1ee2ffa2312c315e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 13 Mar 2021 13:18:26 +0000 +Subject: net: stmmac: Set FIFO sizes for ipq806x + +From: Jonathan McDowell + +[ Upstream commit e127906b68b49ddb3ecba39ffa36a329c48197d3 ] + +Commit eaf4fac47807 ("net: stmmac: Do not accept invalid MTU values") +started using the TX FIFO size to verify what counts as a valid MTU +request for the stmmac driver. This is unset for the ipq806x variant. +Looking at older patches for this it seems the RX + TXs buffers can be +up to 8k, so set appropriately. + +(I sent this as an RFC patch in June last year, but received no replies. +I've been running with this on my hardware (a MikroTik RB3011) since +then with larger MTUs to support both the internal qca8k switch and +VLANs with no problems. Without the patch it's impossible to set the +larger MTU required to support this.) + +Signed-off-by: Jonathan McDowell +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +index bf3250e0e59c..749585fe6fc9 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +@@ -352,6 +352,8 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) + plat_dat->bsp_priv = gmac; + plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed; + plat_dat->multicast_filter_bins = 0; ++ plat_dat->tx_fifo_size = 8192; ++ plat_dat->rx_fifo_size = 8192; + + err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (err) +-- +2.30.2 + diff --git a/queue-5.12/netfilter-nfnetlink_osf-fix-a-missing-skb_header_poi.patch b/queue-5.12/netfilter-nfnetlink_osf-fix-a-missing-skb_header_poi.patch new file mode 100644 index 00000000000..fe2271a9bd0 --- /dev/null +++ b/queue-5.12/netfilter-nfnetlink_osf-fix-a-missing-skb_header_poi.patch @@ -0,0 +1,36 @@ +From 3d2b54df32a8d30e2aad8b7ccbb7274f89c2b346 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 May 2021 22:25:24 +0200 +Subject: netfilter: nfnetlink_osf: Fix a missing skb_header_pointer() NULL + check + +From: Pablo Neira Ayuso + +[ Upstream commit 5e024c325406470d1165a09c6feaf8ec897936be ] + +Do not assume that the tcph->doff field is correct when parsing for TCP +options, skb_header_pointer() might fail to fetch these bits. + +Fixes: 11eeef41d5f6 ("netfilter: passive OS fingerprint xtables match") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nfnetlink_osf.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/netfilter/nfnetlink_osf.c b/net/netfilter/nfnetlink_osf.c +index 916a3c7f9eaf..79fbf37291f3 100644 +--- a/net/netfilter/nfnetlink_osf.c ++++ b/net/netfilter/nfnetlink_osf.c +@@ -186,6 +186,8 @@ static const struct tcphdr *nf_osf_hdr_ctx_init(struct nf_osf_hdr_ctx *ctx, + + ctx->optp = skb_header_pointer(skb, ip_hdrlen(skb) + + sizeof(struct tcphdr), ctx->optsize, opts); ++ if (!ctx->optp) ++ return NULL; + } + + return tcp; +-- +2.30.2 + diff --git a/queue-5.12/netfilter-nftables-avoid-overflows-in-nft_hash_bucke.patch b/queue-5.12/netfilter-nftables-avoid-overflows-in-nft_hash_bucke.patch new file mode 100644 index 00000000000..340a2082a55 --- /dev/null +++ b/queue-5.12/netfilter-nftables-avoid-overflows-in-nft_hash_bucke.patch @@ -0,0 +1,76 @@ +From 0e95d0a794e2b924101e458ef8d4388b6514ab37 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 May 2021 05:53:23 -0700 +Subject: netfilter: nftables: avoid overflows in nft_hash_buckets() + +From: Eric Dumazet + +[ Upstream commit a54754ec9891830ba548e2010c889e3c8146e449 ] + +Number of buckets being stored in 32bit variables, we have to +ensure that no overflows occur in nft_hash_buckets() + +syzbot injected a size == 0x40000000 and reported: + +UBSAN: shift-out-of-bounds in ./include/linux/log2.h:57:13 +shift exponent 64 is too large for 64-bit type 'long unsigned int' +CPU: 1 PID: 29539 Comm: syz-executor.4 Not tainted 5.12.0-rc7-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:79 [inline] + dump_stack+0x141/0x1d7 lib/dump_stack.c:120 + ubsan_epilogue+0xb/0x5a lib/ubsan.c:148 + __ubsan_handle_shift_out_of_bounds.cold+0xb1/0x181 lib/ubsan.c:327 + __roundup_pow_of_two include/linux/log2.h:57 [inline] + nft_hash_buckets net/netfilter/nft_set_hash.c:411 [inline] + nft_hash_estimate.cold+0x19/0x1e net/netfilter/nft_set_hash.c:652 + nft_select_set_ops net/netfilter/nf_tables_api.c:3586 [inline] + nf_tables_newset+0xe62/0x3110 net/netfilter/nf_tables_api.c:4322 + nfnetlink_rcv_batch+0xa09/0x24b0 net/netfilter/nfnetlink.c:488 + nfnetlink_rcv_skb_batch net/netfilter/nfnetlink.c:612 [inline] + nfnetlink_rcv+0x3af/0x420 net/netfilter/nfnetlink.c:630 + netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] + netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1338 + netlink_sendmsg+0x856/0xd90 net/netlink/af_netlink.c:1927 + sock_sendmsg_nosec net/socket.c:654 [inline] + sock_sendmsg+0xcf/0x120 net/socket.c:674 + ____sys_sendmsg+0x6e8/0x810 net/socket.c:2350 + ___sys_sendmsg+0xf3/0x170 net/socket.c:2404 + __sys_sendmsg+0xe5/0x1b0 net/socket.c:2433 + do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 + +Fixes: 0ed6389c483d ("netfilter: nf_tables: rename set implementations") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_set_hash.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c +index bf618b7ec1ae..560c2cda52ee 100644 +--- a/net/netfilter/nft_set_hash.c ++++ b/net/netfilter/nft_set_hash.c +@@ -406,9 +406,17 @@ static void nft_rhash_destroy(const struct nft_set *set) + (void *)set); + } + ++/* Number of buckets is stored in u32, so cap our result to 1U<<31 */ ++#define NFT_MAX_BUCKETS (1U << 31) ++ + static u32 nft_hash_buckets(u32 size) + { +- return roundup_pow_of_two(size * 4 / 3); ++ u64 val = div_u64((u64)size * 4, 3); ++ ++ if (val >= NFT_MAX_BUCKETS) ++ return NFT_MAX_BUCKETS; ++ ++ return roundup_pow_of_two(val); + } + + static bool nft_rhash_estimate(const struct nft_set_desc *desc, u32 features, +-- +2.30.2 + diff --git a/queue-5.12/netfilter-nftables-fix-a-memleak-from-userdata-error.patch b/queue-5.12/netfilter-nftables-fix-a-memleak-from-userdata-error.patch new file mode 100644 index 00000000000..98be35a180e --- /dev/null +++ b/queue-5.12/netfilter-nftables-fix-a-memleak-from-userdata-error.patch @@ -0,0 +1,38 @@ +From 772746309ab390bb04d375c4c2d04d3b796eeb5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 May 2021 23:06:43 +0200 +Subject: netfilter: nftables: Fix a memleak from userdata error path in new + objects + +From: Pablo Neira Ayuso + +[ Upstream commit 85dfd816fabfc16e71786eda0a33a7046688b5b0 ] + +Release object name if userdata allocation fails. + +Fixes: b131c96496b3 ("netfilter: nf_tables: add userdata support for nft_object") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 589d2f6978d3..878ed49d0c56 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -6246,9 +6246,9 @@ err_obj_ht: + INIT_LIST_HEAD(&obj->list); + return err; + err_trans: +- kfree(obj->key.name); +-err_userdata: + kfree(obj->udata); ++err_userdata: ++ kfree(obj->key.name); + err_strdup: + if (obj->ops->destroy) + obj->ops->destroy(&ctx, obj); +-- +2.30.2 + diff --git a/queue-5.12/netfilter-xt_secmark-add-new-revision-to-fix-structu.patch b/queue-5.12/netfilter-xt_secmark-add-new-revision-to-fix-structu.patch new file mode 100644 index 00000000000..d31e3bd77a4 --- /dev/null +++ b/queue-5.12/netfilter-xt_secmark-add-new-revision-to-fix-structu.patch @@ -0,0 +1,173 @@ +From d20013dc2bc7a9af79493ad301a651259b51a493 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Apr 2021 14:00:13 +0200 +Subject: netfilter: xt_SECMARK: add new revision to fix structure layout + +From: Pablo Neira Ayuso + +[ Upstream commit c7d13358b6a2f49f81a34aa323a2d0878a0532a2 ] + +This extension breaks when trying to delete rules, add a new revision to +fix this. + +Fixes: 5e6874cdb8de ("[SECMARK]: Add xtables SECMARK target") +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + include/uapi/linux/netfilter/xt_SECMARK.h | 6 ++ + net/netfilter/xt_SECMARK.c | 88 ++++++++++++++++++----- + 2 files changed, 75 insertions(+), 19 deletions(-) + +diff --git a/include/uapi/linux/netfilter/xt_SECMARK.h b/include/uapi/linux/netfilter/xt_SECMARK.h +index 1f2a708413f5..beb2cadba8a9 100644 +--- a/include/uapi/linux/netfilter/xt_SECMARK.h ++++ b/include/uapi/linux/netfilter/xt_SECMARK.h +@@ -20,4 +20,10 @@ struct xt_secmark_target_info { + char secctx[SECMARK_SECCTX_MAX]; + }; + ++struct xt_secmark_target_info_v1 { ++ __u8 mode; ++ char secctx[SECMARK_SECCTX_MAX]; ++ __u32 secid; ++}; ++ + #endif /*_XT_SECMARK_H_target */ +diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c +index 75625d13e976..498a0bf6f044 100644 +--- a/net/netfilter/xt_SECMARK.c ++++ b/net/netfilter/xt_SECMARK.c +@@ -24,10 +24,9 @@ MODULE_ALIAS("ip6t_SECMARK"); + static u8 mode; + + static unsigned int +-secmark_tg(struct sk_buff *skb, const struct xt_action_param *par) ++secmark_tg(struct sk_buff *skb, const struct xt_secmark_target_info_v1 *info) + { + u32 secmark = 0; +- const struct xt_secmark_target_info *info = par->targinfo; + + switch (mode) { + case SECMARK_MODE_SEL: +@@ -41,7 +40,7 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par) + return XT_CONTINUE; + } + +-static int checkentry_lsm(struct xt_secmark_target_info *info) ++static int checkentry_lsm(struct xt_secmark_target_info_v1 *info) + { + int err; + +@@ -73,15 +72,15 @@ static int checkentry_lsm(struct xt_secmark_target_info *info) + return 0; + } + +-static int secmark_tg_check(const struct xt_tgchk_param *par) ++static int ++secmark_tg_check(const char *table, struct xt_secmark_target_info_v1 *info) + { +- struct xt_secmark_target_info *info = par->targinfo; + int err; + +- if (strcmp(par->table, "mangle") != 0 && +- strcmp(par->table, "security") != 0) { ++ if (strcmp(table, "mangle") != 0 && ++ strcmp(table, "security") != 0) { + pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n", +- par->table); ++ table); + return -EINVAL; + } + +@@ -116,25 +115,76 @@ static void secmark_tg_destroy(const struct xt_tgdtor_param *par) + } + } + +-static struct xt_target secmark_tg_reg __read_mostly = { +- .name = "SECMARK", +- .revision = 0, +- .family = NFPROTO_UNSPEC, +- .checkentry = secmark_tg_check, +- .destroy = secmark_tg_destroy, +- .target = secmark_tg, +- .targetsize = sizeof(struct xt_secmark_target_info), +- .me = THIS_MODULE, ++static int secmark_tg_check_v0(const struct xt_tgchk_param *par) ++{ ++ struct xt_secmark_target_info *info = par->targinfo; ++ struct xt_secmark_target_info_v1 newinfo = { ++ .mode = info->mode, ++ }; ++ int ret; ++ ++ memcpy(newinfo.secctx, info->secctx, SECMARK_SECCTX_MAX); ++ ++ ret = secmark_tg_check(par->table, &newinfo); ++ info->secid = newinfo.secid; ++ ++ return ret; ++} ++ ++static unsigned int ++secmark_tg_v0(struct sk_buff *skb, const struct xt_action_param *par) ++{ ++ const struct xt_secmark_target_info *info = par->targinfo; ++ struct xt_secmark_target_info_v1 newinfo = { ++ .secid = info->secid, ++ }; ++ ++ return secmark_tg(skb, &newinfo); ++} ++ ++static int secmark_tg_check_v1(const struct xt_tgchk_param *par) ++{ ++ return secmark_tg_check(par->table, par->targinfo); ++} ++ ++static unsigned int ++secmark_tg_v1(struct sk_buff *skb, const struct xt_action_param *par) ++{ ++ return secmark_tg(skb, par->targinfo); ++} ++ ++static struct xt_target secmark_tg_reg[] __read_mostly = { ++ { ++ .name = "SECMARK", ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .checkentry = secmark_tg_check_v0, ++ .destroy = secmark_tg_destroy, ++ .target = secmark_tg_v0, ++ .targetsize = sizeof(struct xt_secmark_target_info), ++ .me = THIS_MODULE, ++ }, ++ { ++ .name = "SECMARK", ++ .revision = 1, ++ .family = NFPROTO_UNSPEC, ++ .checkentry = secmark_tg_check_v1, ++ .destroy = secmark_tg_destroy, ++ .target = secmark_tg_v1, ++ .targetsize = sizeof(struct xt_secmark_target_info_v1), ++ .usersize = offsetof(struct xt_secmark_target_info_v1, secid), ++ .me = THIS_MODULE, ++ }, + }; + + static int __init secmark_tg_init(void) + { +- return xt_register_target(&secmark_tg_reg); ++ return xt_register_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg)); + } + + static void __exit secmark_tg_exit(void) + { +- xt_unregister_target(&secmark_tg_reg); ++ xt_unregister_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg)); + } + + module_init(secmark_tg_init); +-- +2.30.2 + diff --git a/queue-5.12/nfs-deal-correctly-with-attribute-generation-counter.patch b/queue-5.12/nfs-deal-correctly-with-attribute-generation-counter.patch new file mode 100644 index 00000000000..bef3e087e63 --- /dev/null +++ b/queue-5.12/nfs-deal-correctly-with-attribute-generation-counter.patch @@ -0,0 +1,49 @@ +From 4a708739ae495d89536ae9c1295f807242333d95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Mar 2021 16:46:05 -0400 +Subject: NFS: Deal correctly with attribute generation counter overflow + +From: Trond Myklebust + +[ Upstream commit 9fdbfad1777cb4638f489eeb62d85432010c0031 ] + +We need to use unsigned long subtraction and then convert to signed in +order to deal correcly with C overflow rules. + +Fixes: f5062003465c ("NFS: Set an attribute barrier on all updates") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/inode.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c +index a7fb076a5f44..7cfeee3eeef7 100644 +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -1662,10 +1662,10 @@ EXPORT_SYMBOL_GPL(_nfs_display_fhandle); + */ + static int nfs_inode_attrs_need_update(const struct inode *inode, const struct nfs_fattr *fattr) + { +- const struct nfs_inode *nfsi = NFS_I(inode); ++ unsigned long attr_gencount = NFS_I(inode)->attr_gencount; + +- return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || +- ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); ++ return (long)(fattr->gencount - attr_gencount) > 0 || ++ (long)(attr_gencount - nfs_read_attr_generation_counter()) > 0; + } + + static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) +@@ -2094,7 +2094,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) + nfsi->attrtimeo_timestamp = now; + } + /* Set the barrier to be more recent than this fattr */ +- if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0) ++ if ((long)(fattr->gencount - nfsi->attr_gencount) > 0) + nfsi->attr_gencount = fattr->gencount; + } + +-- +2.30.2 + diff --git a/queue-5.12/nfs-fix-attribute-bitmask-in-_nfs42_proc_fallocate.patch b/queue-5.12/nfs-fix-attribute-bitmask-in-_nfs42_proc_fallocate.patch new file mode 100644 index 00000000000..a8b8cb71d66 --- /dev/null +++ b/queue-5.12/nfs-fix-attribute-bitmask-in-_nfs42_proc_fallocate.patch @@ -0,0 +1,63 @@ +From 6a3d73998ff9bcb1bc87ec2f41fc14ca42ea4712 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 28 Mar 2021 18:12:03 -0400 +Subject: NFS: Fix attribute bitmask in _nfs42_proc_fallocate() + +From: Trond Myklebust + +[ Upstream commit e99812e1382f0bfb6149393262bc70645c9f537a ] + +We can't use nfs4_fattr_bitmap as a bitmask, because it hasn't been +filtered to represent the attributes supported by the server. Instead, +let's revert to using server->cache_consistency_bitmask after adding in +the missing SPACE_USED attribute. + +Fixes: 913eca1aea87 ("NFS: Fallocate should use the nfs4_fattr_bitmap") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs42proc.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c +index 094024b0aca1..597005bc8a05 100644 +--- a/fs/nfs/nfs42proc.c ++++ b/fs/nfs/nfs42proc.c +@@ -46,11 +46,12 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, + { + struct inode *inode = file_inode(filep); + struct nfs_server *server = NFS_SERVER(inode); ++ u32 bitmask[3]; + struct nfs42_falloc_args args = { + .falloc_fh = NFS_FH(inode), + .falloc_offset = offset, + .falloc_length = len, +- .falloc_bitmask = nfs4_fattr_bitmap, ++ .falloc_bitmask = bitmask, + }; + struct nfs42_falloc_res res = { + .falloc_server = server, +@@ -68,6 +69,10 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, + return status; + } + ++ memcpy(bitmask, server->cache_consistency_bitmask, sizeof(bitmask)); ++ if (server->attr_bitmask[1] & FATTR4_WORD1_SPACE_USED) ++ bitmask[1] |= FATTR4_WORD1_SPACE_USED; ++ + res.falloc_fattr = nfs_alloc_fattr(); + if (!res.falloc_fattr) + return -ENOMEM; +@@ -75,7 +80,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, + status = nfs4_call_sync(server->client, server, msg, + &args.seq_args, &res.seq_res, 0); + if (status == 0) +- status = nfs_post_op_update_inode(inode, res.falloc_fattr); ++ status = nfs_post_op_update_inode_force_wcc(inode, ++ res.falloc_fattr); + + kfree(res.falloc_fattr); + return status; +-- +2.30.2 + diff --git a/queue-5.12/nfs-fix-handling-of-cookie-verifier-in-uncached_read.patch b/queue-5.12/nfs-fix-handling-of-cookie-verifier-in-uncached_read.patch new file mode 100644 index 00000000000..0a99eaa7fbd --- /dev/null +++ b/queue-5.12/nfs-fix-handling-of-cookie-verifier-in-uncached_read.patch @@ -0,0 +1,84 @@ +From fe411d276240e5b009ba6ef5cf36233e3087f05d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Mar 2021 07:57:40 -0400 +Subject: NFS: Fix handling of cookie verifier in uncached_readdir() + +From: Trond Myklebust + +[ Upstream commit 13884ff2bef01df37c450c6dd09122f92333dccc ] + +If we're doing uncached readdir(), then the readdir cookie could be +different from the one cached in the nfs_inode. We should therefore +ensure that we save that one in the struct nfs_open_dir_context. + +Fixes: 35df59d3ef69 ("NFS: Reduce number of RPC calls when doing uncached readdir") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/dir.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index 08a1e2e31d0b..2cf2a7d92faf 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -976,10 +976,10 @@ static int readdir_search_pagecache(struct nfs_readdir_descriptor *desc) + /* + * Once we've found the start of the dirent within a page: fill 'er up... + */ +-static void nfs_do_filldir(struct nfs_readdir_descriptor *desc) ++static void nfs_do_filldir(struct nfs_readdir_descriptor *desc, ++ const __be32 *verf) + { + struct file *file = desc->file; +- struct nfs_inode *nfsi = NFS_I(file_inode(file)); + struct nfs_cache_array *array; + unsigned int i = 0; + +@@ -993,7 +993,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc) + desc->eof = true; + break; + } +- memcpy(desc->verf, nfsi->cookieverf, sizeof(desc->verf)); ++ memcpy(desc->verf, verf, sizeof(desc->verf)); + if (i < (array->size-1)) + desc->dir_cookie = array->array[i+1].cookie; + else +@@ -1050,7 +1050,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc) + + for (i = 0; !desc->eof && i < sz && arrays[i]; i++) { + desc->page = arrays[i]; +- nfs_do_filldir(desc); ++ nfs_do_filldir(desc, verf); + } + desc->page = NULL; + +@@ -1071,6 +1071,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) + { + struct dentry *dentry = file_dentry(file); + struct inode *inode = d_inode(dentry); ++ struct nfs_inode *nfsi = NFS_I(inode); + struct nfs_open_dir_context *dir_ctx = file->private_data; + struct nfs_readdir_descriptor *desc; + int res; +@@ -1124,7 +1125,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) + break; + } + if (res == -ETOOSMALL && desc->plus) { +- clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); ++ clear_bit(NFS_INO_ADVISE_RDPLUS, &nfsi->flags); + nfs_zap_caches(inode); + desc->page_index = 0; + desc->plus = false; +@@ -1134,7 +1135,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) + if (res < 0) + break; + +- nfs_do_filldir(desc); ++ nfs_do_filldir(desc, nfsi->cookieverf); + nfs_readdir_page_unlock_and_put_cached(desc); + } while (!desc->eof); + +-- +2.30.2 + diff --git a/queue-5.12/nfs-nfs4_bitmask_adjust-must-not-change-the-server-g.patch b/queue-5.12/nfs-nfs4_bitmask_adjust-must-not-change-the-server-g.patch new file mode 100644 index 00000000000..bb071184798 --- /dev/null +++ b/queue-5.12/nfs-nfs4_bitmask_adjust-must-not-change-the-server-g.patch @@ -0,0 +1,188 @@ +From 8d0ff78f19d76601aa4df2b9b0ee449b11293511 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Mar 2021 18:15:36 -0400 +Subject: NFS: nfs4_bitmask_adjust() must not change the server global bitmasks + +From: Trond Myklebust + +[ Upstream commit 332d1a0373be32a3a3c152756bca45ff4f4e11b5 ] + +As currently set, the calls to nfs4_bitmask_adjust() will end up +overwriting the contents of the nfs_server cache_consistency_bitmask +field. +The intention here should be to modify a private copy of that mask in +the close/delegreturn/write arguments. + +Fixes: 76bd5c016ef4 ("NFSv4: make cache consistency bitmask dynamic") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4proc.c | 56 +++++++++++++++++++++++++---------------- + include/linux/nfs_xdr.h | 11 +++++--- + 2 files changed, 42 insertions(+), 25 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index c65c4b41e2c1..820abae88cf0 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -108,9 +108,10 @@ static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *, + static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *, + const struct cred *, bool); + #endif +-static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode, +- struct nfs_server *server, +- struct nfs4_label *label); ++static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], ++ const __u32 *src, struct inode *inode, ++ struct nfs_server *server, ++ struct nfs4_label *label); + + #ifdef CONFIG_NFS_V4_SECURITY_LABEL + static inline struct nfs4_label * +@@ -3591,6 +3592,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) + struct nfs4_closedata *calldata = data; + struct nfs4_state *state = calldata->state; + struct inode *inode = calldata->inode; ++ struct nfs_server *server = NFS_SERVER(inode); + struct pnfs_layout_hdr *lo; + bool is_rdonly, is_wronly, is_rdwr; + int call_close = 0; +@@ -3647,8 +3649,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) + if (calldata->arg.fmode == 0 || calldata->arg.fmode == FMODE_READ) { + /* Close-to-open cache consistency revalidation */ + if (!nfs4_have_delegation(inode, FMODE_READ)) { +- calldata->arg.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; +- nfs4_bitmask_adjust(calldata->arg.bitmask, inode, NFS_SERVER(inode), NULL); ++ nfs4_bitmask_set(calldata->arg.bitmask_store, ++ server->cache_consistency_bitmask, ++ inode, server, NULL); ++ calldata->arg.bitmask = calldata->arg.bitmask_store; + } else + calldata->arg.bitmask = NULL; + } +@@ -5416,19 +5420,17 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr) + return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0; + } + +-static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode, +- struct nfs_server *server, +- struct nfs4_label *label) ++static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], const __u32 *src, ++ struct inode *inode, struct nfs_server *server, ++ struct nfs4_label *label) + { +- + unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity); ++ unsigned int i; + +- if ((cache_validity & NFS_INO_INVALID_DATA) || +- (cache_validity & NFS_INO_REVAL_PAGECACHE) || +- (cache_validity & NFS_INO_REVAL_FORCED) || +- (cache_validity & NFS_INO_INVALID_OTHER)) +- nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode); ++ memcpy(bitmask, src, sizeof(*bitmask) * NFS4_BITMASK_SZ); + ++ if (cache_validity & (NFS_INO_INVALID_CHANGE | NFS_INO_REVAL_PAGECACHE)) ++ bitmask[0] |= FATTR4_WORD0_CHANGE; + if (cache_validity & NFS_INO_INVALID_ATIME) + bitmask[1] |= FATTR4_WORD1_TIME_ACCESS; + if (cache_validity & NFS_INO_INVALID_OTHER) +@@ -5437,16 +5439,22 @@ static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode, + FATTR4_WORD1_NUMLINKS; + if (label && label->len && cache_validity & NFS_INO_INVALID_LABEL) + bitmask[2] |= FATTR4_WORD2_SECURITY_LABEL; +- if (cache_validity & NFS_INO_INVALID_CHANGE) +- bitmask[0] |= FATTR4_WORD0_CHANGE; + if (cache_validity & NFS_INO_INVALID_CTIME) + bitmask[1] |= FATTR4_WORD1_TIME_METADATA; + if (cache_validity & NFS_INO_INVALID_MTIME) + bitmask[1] |= FATTR4_WORD1_TIME_MODIFY; +- if (cache_validity & NFS_INO_INVALID_SIZE) +- bitmask[0] |= FATTR4_WORD0_SIZE; + if (cache_validity & NFS_INO_INVALID_BLOCKS) + bitmask[1] |= FATTR4_WORD1_SPACE_USED; ++ ++ if (nfs4_have_delegation(inode, FMODE_READ) && ++ !(cache_validity & NFS_INO_REVAL_FORCED)) ++ bitmask[0] &= ~FATTR4_WORD0_SIZE; ++ else if (cache_validity & ++ (NFS_INO_INVALID_SIZE | NFS_INO_REVAL_PAGECACHE)) ++ bitmask[0] |= FATTR4_WORD0_SIZE; ++ ++ for (i = 0; i < NFS4_BITMASK_SZ; i++) ++ bitmask[i] &= server->attr_bitmask[i]; + } + + static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr, +@@ -5459,8 +5467,10 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr, + hdr->args.bitmask = NULL; + hdr->res.fattr = NULL; + } else { +- hdr->args.bitmask = server->cache_consistency_bitmask; +- nfs4_bitmask_adjust(hdr->args.bitmask, hdr->inode, server, NULL); ++ nfs4_bitmask_set(hdr->args.bitmask_store, ++ server->cache_consistency_bitmask, ++ hdr->inode, server, NULL); ++ hdr->args.bitmask = hdr->args.bitmask_store; + } + + if (!hdr->pgio_done_cb) +@@ -6502,8 +6512,10 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred, + + data->args.fhandle = &data->fh; + data->args.stateid = &data->stateid; +- data->args.bitmask = server->cache_consistency_bitmask; +- nfs4_bitmask_adjust(data->args.bitmask, inode, server, NULL); ++ nfs4_bitmask_set(data->args.bitmask_store, ++ server->cache_consistency_bitmask, inode, server, ++ NULL); ++ data->args.bitmask = data->args.bitmask_store; + nfs_copy_fh(&data->fh, NFS_FH(inode)); + nfs4_stateid_copy(&data->stateid, stateid); + data->res.fattr = &data->fattr; +diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h +index 3327239fa2f9..cc29dee508f7 100644 +--- a/include/linux/nfs_xdr.h ++++ b/include/linux/nfs_xdr.h +@@ -15,6 +15,8 @@ + #define NFS_DEF_FILE_IO_SIZE (4096U) + #define NFS_MIN_FILE_IO_SIZE (1024U) + ++#define NFS_BITMASK_SZ 3 ++ + struct nfs4_string { + unsigned int len; + char *data; +@@ -525,7 +527,8 @@ struct nfs_closeargs { + struct nfs_seqid * seqid; + fmode_t fmode; + u32 share_access; +- u32 * bitmask; ++ const u32 * bitmask; ++ u32 bitmask_store[NFS_BITMASK_SZ]; + struct nfs4_layoutreturn_args *lr_args; + }; + +@@ -608,7 +611,8 @@ struct nfs4_delegreturnargs { + struct nfs4_sequence_args seq_args; + const struct nfs_fh *fhandle; + const nfs4_stateid *stateid; +- u32 * bitmask; ++ const u32 *bitmask; ++ u32 bitmask_store[NFS_BITMASK_SZ]; + struct nfs4_layoutreturn_args *lr_args; + }; + +@@ -648,7 +652,8 @@ struct nfs_pgio_args { + union { + unsigned int replen; /* used by read */ + struct { +- u32 * bitmask; /* used by write */ ++ const u32 * bitmask; /* used by write */ ++ u32 bitmask_store[NFS_BITMASK_SZ]; /* used by write */ + enum nfs3_stable_how stable; /* used by write */ + }; + }; +-- +2.30.2 + diff --git a/queue-5.12/nfs-only-change-the-cookie-verifier-if-the-directory.patch b/queue-5.12/nfs-only-change-the-cookie-verifier-if-the-directory.patch new file mode 100644 index 00000000000..0719c3354aa --- /dev/null +++ b/queue-5.12/nfs-only-change-the-cookie-verifier-if-the-directory.patch @@ -0,0 +1,45 @@ +From 6bbb755bc63b171702876350481bb1eb4d1c4866 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Mar 2021 08:46:19 -0400 +Subject: NFS: Only change the cookie verifier if the directory page cache is + empty + +From: Trond Myklebust + +[ Upstream commit f892c41c14e0fa3d78ce37de1d5c8161ed13bf08 ] + +The cached NFSv3/v4 readdir cookies are associated with a verifier, +which is checked by the server on subsequent calls to readdir, and is +only expected to change when the cookies (and hence also the page cache +contents) are considered invalid. +We therefore do have to store the verifier, but only when the page cache +is empty. + +Fixes: b593c09f83a2 ("NFS: Improve handling of directory verifiers") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/dir.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index 2cf2a7d92faf..0cd7c59a6601 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -929,7 +929,12 @@ static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc) + } + return res; + } +- memcpy(nfsi->cookieverf, verf, sizeof(nfsi->cookieverf)); ++ /* ++ * Set the cookie verifier if the page cache was empty ++ */ ++ if (desc->page_index == 0) ++ memcpy(nfsi->cookieverf, verf, ++ sizeof(nfsi->cookieverf)); + } + res = nfs_readdir_search_array(desc); + if (res == 0) { +-- +2.30.2 + diff --git a/queue-5.12/nfs-subsequent-readdir-calls-should-carry-non-zero-c.patch b/queue-5.12/nfs-subsequent-readdir-calls-should-carry-non-zero-c.patch new file mode 100644 index 00000000000..ed4ad9ab7af --- /dev/null +++ b/queue-5.12/nfs-subsequent-readdir-calls-should-carry-non-zero-c.patch @@ -0,0 +1,38 @@ +From 8ab688e09a5e1cb20720ff297d4cee62bb3c55f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Mar 2021 10:25:14 +0000 +Subject: nfs: Subsequent READDIR calls should carry non-zero cookieverifier + +From: Nagendra S Tomar + +[ Upstream commit ee3707ae2c1f1327ad5188836b7ab62ed2c93b28 ] + +If the loop in nfs_readdir_xdr_to_array() runs more than once, subsequent +READDIR RPCs may wrongly carry a zero cookie verifier and non-zero cookie. +Make sure subsequent calls to READDIR carry the cookie verifier returned +by the first call. + +Signed-off-by: Nagendra S Tomar +Fixes: b593c09f83a2 ("NFS: Improve handling of directory verifiers") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/dir.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index fc4f490f2d78..08a1e2e31d0b 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -866,6 +866,8 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc, + break; + } + ++ verf_arg = verf_res; ++ + status = nfs_readdir_page_filler(desc, entry, pages, pglen, + arrays, narrays); + } while (!status && nfs_readdir_page_needs_filling(page)); +-- +2.30.2 + diff --git a/queue-5.12/nfsd-ensure-new-clients-break-delegations.patch b/queue-5.12/nfsd-ensure-new-clients-break-delegations.patch new file mode 100644 index 00000000000..758ba9536f4 --- /dev/null +++ b/queue-5.12/nfsd-ensure-new-clients-break-delegations.patch @@ -0,0 +1,71 @@ +From a7947f0fbf1f5421e687f1bf96c382b78bb2f380 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Apr 2021 14:00:14 -0400 +Subject: nfsd: ensure new clients break delegations + +From: J. Bruce Fields + +[ Upstream commit 217fd6f625af591e2866bebb8cda778cf85bea2e ] + +If nfsd already has an open file that it plans to use for IO from +another, it may not need to do another vfs open, but it still may need +to break any delegations in case the existing opens are for another +client. + +Symptoms are that we may incorrectly fail to break a delegation on a +write open from a different client, when the delegation-holding client +already has a write open. + +Fixes: 28df3d1539de ("nfsd: clients don't need to break their own delegations") +Signed-off-by: J. Bruce Fields +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4state.c | 24 +++++++++++++++++++----- + 1 file changed, 19 insertions(+), 5 deletions(-) + +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 97447a64bad0..886e50ed07c2 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -4869,6 +4869,11 @@ static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp, + if (nf) + nfsd_file_put(nf); + ++ status = nfserrno(nfsd_open_break_lease(cur_fh->fh_dentry->d_inode, ++ access)); ++ if (status) ++ goto out_put_access; ++ + status = nfsd4_truncate(rqstp, cur_fh, open); + if (status) + goto out_put_access; +@@ -6849,11 +6854,20 @@ out: + static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock) + { + struct nfsd_file *nf; +- __be32 err = nfsd_file_acquire(rqstp, fhp, NFSD_MAY_READ, &nf); +- if (!err) { +- err = nfserrno(vfs_test_lock(nf->nf_file, lock)); +- nfsd_file_put(nf); +- } ++ __be32 err; ++ ++ err = nfsd_file_acquire(rqstp, fhp, NFSD_MAY_READ, &nf); ++ if (err) ++ return err; ++ fh_lock(fhp); /* to block new leases till after test_lock: */ ++ err = nfserrno(nfsd_open_break_lease(fhp->fh_dentry->d_inode, ++ NFSD_MAY_READ)); ++ if (err) ++ goto out; ++ err = nfserrno(vfs_test_lock(nf->nf_file, lock)); ++out: ++ fh_unlock(fhp); ++ nfsd_file_put(nf); + return err; + } + +-- +2.30.2 + diff --git a/queue-5.12/nfsv4.2-always-flush-out-writes-in-nfs42_proc_falloc.patch b/queue-5.12/nfsv4.2-always-flush-out-writes-in-nfs42_proc_falloc.patch new file mode 100644 index 00000000000..1a91c7e28dc --- /dev/null +++ b/queue-5.12/nfsv4.2-always-flush-out-writes-in-nfs42_proc_falloc.patch @@ -0,0 +1,78 @@ +From 81e9025d3e24f9833a9d610c7dd2ae7f5330127c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 28 Mar 2021 18:17:14 -0400 +Subject: NFSv4.2: Always flush out writes in nfs42_proc_fallocate() + +From: Trond Myklebust + +[ Upstream commit 99f23783224355e7022ceea9b8d9f62c0fd01bd8 ] + +Whether we're allocating or delallocating space, we should flush out the +pending writes in order to avoid races with attribute updates. + +Fixes: 1e564d3dbd68 ("NFSv4.2: Fix a race in nfs42_proc_deallocate()") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs42proc.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c +index 597005bc8a05..704a5246ccb5 100644 +--- a/fs/nfs/nfs42proc.c ++++ b/fs/nfs/nfs42proc.c +@@ -90,7 +90,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, + static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, + loff_t offset, loff_t len) + { +- struct nfs_server *server = NFS_SERVER(file_inode(filep)); ++ struct inode *inode = file_inode(filep); ++ struct nfs_server *server = NFS_SERVER(inode); + struct nfs4_exception exception = { }; + struct nfs_lock_context *lock; + int err; +@@ -99,9 +100,13 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, + if (IS_ERR(lock)) + return PTR_ERR(lock); + +- exception.inode = file_inode(filep); ++ exception.inode = inode; + exception.state = lock->open_context->state; + ++ err = nfs_sync_inode(inode); ++ if (err) ++ goto out; ++ + do { + err = _nfs42_proc_fallocate(msg, filep, lock, offset, len); + if (err == -ENOTSUPP) { +@@ -110,7 +115,7 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, + } + err = nfs4_handle_exception(server, err, &exception); + } while (exception.retry); +- ++out: + nfs_put_lock_context(lock); + return err; + } +@@ -148,16 +153,13 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len) + return -EOPNOTSUPP; + + inode_lock(inode); +- err = nfs_sync_inode(inode); +- if (err) +- goto out_unlock; + + err = nfs42_proc_fallocate(&msg, filep, offset, len); + if (err == 0) + truncate_pagecache_range(inode, offset, (offset + len) -1); + if (err == -EOPNOTSUPP) + NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE; +-out_unlock: ++ + inode_unlock(inode); + return err; + } +-- +2.30.2 + diff --git a/queue-5.12/nfsv4.2-fix-handling-of-sr_eof-in-seek-s-reply.patch b/queue-5.12/nfsv4.2-fix-handling-of-sr_eof-in-seek-s-reply.patch new file mode 100644 index 00000000000..0f090ae6bec --- /dev/null +++ b/queue-5.12/nfsv4.2-fix-handling-of-sr_eof-in-seek-s-reply.patch @@ -0,0 +1,43 @@ +From 79ae3d9fc487741fea861259c9624ae8482cfbfa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Mar 2021 15:30:25 -0400 +Subject: NFSv4.2 fix handling of sr_eof in SEEK's reply + +From: Olga Kornievskaia + +[ Upstream commit 73f5c88f521a630ea1628beb9c2d48a2e777a419 ] + +Currently the client ignores the value of the sr_eof of the SEEK +operation. According to the spec, if the server didn't find the +requested extent and reached the end of the file, the server +would return sr_eof=true. In case the request for DATA and no +data was found (ie in the middle of the hole), then the lseek +expects that ENXIO would be returned. + +Fixes: 1c6dcbe5ceff8 ("NFS: Implement SEEK") +Signed-off-by: Olga Kornievskaia +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs42proc.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c +index 704a5246ccb5..8d64eb953347 100644 +--- a/fs/nfs/nfs42proc.c ++++ b/fs/nfs/nfs42proc.c +@@ -667,7 +667,10 @@ static loff_t _nfs42_proc_llseek(struct file *filep, + if (status) + return status; + +- return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes); ++ if (whence == SEEK_DATA && res.sr_eof) ++ return -NFS4ERR_NXIO; ++ else ++ return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes); + } + + loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) +-- +2.30.2 + diff --git a/queue-5.12/nfsv4.x-don-t-return-nfs4err_nomatching_layout-if-we.patch b/queue-5.12/nfsv4.x-don-t-return-nfs4err_nomatching_layout-if-we.patch new file mode 100644 index 00000000000..b54dbb2e12a --- /dev/null +++ b/queue-5.12/nfsv4.x-don-t-return-nfs4err_nomatching_layout-if-we.patch @@ -0,0 +1,61 @@ +From 7c9440e8c2b1e975cb849cdc5304d562853aa0be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 15:09:41 -0400 +Subject: NFSv4.x: Don't return NFS4ERR_NOMATCHING_LAYOUT if we're unmounting + +From: Trond Myklebust + +[ Upstream commit 8926cc8302819be9e67f70409ed001ecb2c924a9 ] + +If the NFS super block is being unmounted, then we currently may end up +telling the server that we've forgotten the layout while it is actually +still in use by the client. +In that case, just assume that the client will soon return the layout +anyway, and so return NFS4ERR_DELAY in response to the layout recall. + +Fixes: 58ac3e59235f ("NFSv4/pnfs: Clean up nfs_layout_find_inode()") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/callback_proc.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c +index f7786e00a6a7..ed9d580826f5 100644 +--- a/fs/nfs/callback_proc.c ++++ b/fs/nfs/callback_proc.c +@@ -137,12 +137,12 @@ static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp, + list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) { + if (!pnfs_layout_is_valid(lo)) + continue; +- if (stateid != NULL && +- !nfs4_stateid_match_other(stateid, &lo->plh_stateid)) ++ if (!nfs4_stateid_match_other(stateid, &lo->plh_stateid)) + continue; +- if (!nfs_sb_active(server->super)) +- continue; +- inode = igrab(lo->plh_inode); ++ if (nfs_sb_active(server->super)) ++ inode = igrab(lo->plh_inode); ++ else ++ inode = ERR_PTR(-EAGAIN); + rcu_read_unlock(); + if (inode) + return inode; +@@ -176,9 +176,10 @@ static struct inode *nfs_layout_find_inode_by_fh(struct nfs_client *clp, + continue; + if (nfsi->layout != lo) + continue; +- if (!nfs_sb_active(server->super)) +- continue; +- inode = igrab(lo->plh_inode); ++ if (nfs_sb_active(server->super)) ++ inode = igrab(lo->plh_inode); ++ else ++ inode = ERR_PTR(-EAGAIN); + rcu_read_unlock(); + if (inode) + return inode; +-- +2.30.2 + diff --git a/queue-5.12/nfsv42-copy-offload-should-update-the-file-size-when.patch b/queue-5.12/nfsv42-copy-offload-should-update-the-file-size-when.patch new file mode 100644 index 00000000000..74c0c60697a --- /dev/null +++ b/queue-5.12/nfsv42-copy-offload-should-update-the-file-size-when.patch @@ -0,0 +1,90 @@ +From 81447d4a3fe700272ee4b925c030856ace74a4bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Apr 2021 10:10:09 -0400 +Subject: NFSv42: Copy offload should update the file size when appropriate + +From: Trond Myklebust + +[ Upstream commit 94d202d5ca39d0eb757d16ef2624b013fb64f64d ] + +If the result of a copy offload or clone operation is to grow the +destination file size, then we should update it. The reason is that when +a client holds a delegation, it is authoritative for the file size. + +Fixes: 16abd2a0c124 ("NFSv4.2: fix client's attribute cache management for copy_file_range") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs42proc.c | 41 ++++++++++++++++++++++++++++++++--------- + 1 file changed, 32 insertions(+), 9 deletions(-) + +diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c +index 8d64eb953347..3875120ef3ef 100644 +--- a/fs/nfs/nfs42proc.c ++++ b/fs/nfs/nfs42proc.c +@@ -269,6 +269,33 @@ out: + return status; + } + ++/** ++ * nfs42_copy_dest_done - perform inode cache updates after clone/copy offload ++ * @inode: pointer to destination inode ++ * @pos: destination offset ++ * @len: copy length ++ * ++ * Punch a hole in the inode page cache, so that the NFS client will ++ * know to retrieve new data. ++ * Update the file size if necessary, and then mark the inode as having ++ * invalid cached values for change attribute, ctime, mtime and space used. ++ */ ++static void nfs42_copy_dest_done(struct inode *inode, loff_t pos, loff_t len) ++{ ++ loff_t newsize = pos + len; ++ loff_t end = newsize - 1; ++ ++ truncate_pagecache_range(inode, pos, end); ++ spin_lock(&inode->i_lock); ++ if (newsize > i_size_read(inode)) ++ i_size_write(inode, newsize); ++ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE | ++ NFS_INO_INVALID_CTIME | ++ NFS_INO_INVALID_MTIME | ++ NFS_INO_INVALID_BLOCKS); ++ spin_unlock(&inode->i_lock); ++} ++ + static ssize_t _nfs42_proc_copy(struct file *src, + struct nfs_lock_context *src_lock, + struct file *dst, +@@ -362,14 +389,8 @@ static ssize_t _nfs42_proc_copy(struct file *src, + goto out; + } + +- truncate_pagecache_range(dst_inode, pos_dst, +- pos_dst + res->write_res.count); +- spin_lock(&dst_inode->i_lock); +- nfs_set_cache_invalid( +- dst_inode, NFS_INO_REVAL_PAGECACHE | NFS_INO_REVAL_FORCED | +- NFS_INO_INVALID_SIZE | NFS_INO_INVALID_ATTR | +- NFS_INO_INVALID_DATA); +- spin_unlock(&dst_inode->i_lock); ++ nfs42_copy_dest_done(dst_inode, pos_dst, res->write_res.count); ++ + spin_lock(&src_inode->i_lock); + nfs_set_cache_invalid(src_inode, NFS_INO_REVAL_PAGECACHE | + NFS_INO_REVAL_FORCED | +@@ -1055,8 +1076,10 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f, + + status = nfs4_call_sync(server->client, server, msg, + &args.seq_args, &res.seq_res, 0); +- if (status == 0) ++ if (status == 0) { ++ nfs42_copy_dest_done(dst_inode, dst_offset, count); + status = nfs_post_op_update_inode(dst_inode, res.dst_fattr); ++ } + + kfree(res.dst_fattr); + return status; +-- +2.30.2 + diff --git a/queue-5.12/pci-brcmstb-fix-error-return-code-in-brcm_pcie_probe.patch b/queue-5.12/pci-brcmstb-fix-error-return-code-in-brcm_pcie_probe.patch new file mode 100644 index 00000000000..5cdc09d8d67 --- /dev/null +++ b/queue-5.12/pci-brcmstb-fix-error-return-code-in-brcm_pcie_probe.patch @@ -0,0 +1,42 @@ +From 2d181020cc1ea304799c8fca1683d548804805f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Mar 2021 13:56:19 +0000 +Subject: PCI: brcmstb: Fix error return code in brcm_pcie_probe() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Wei Yongjun + +[ Upstream commit b5d9209d50838474fc1b2901d0e11bba59906428 ] + +Fix to return negative error code -ENODEV from the unsupported revision +error handling case instead of 0, as done elsewhere in this function. + +Link: https://lore.kernel.org/r/20210308135619.19133-1-weiyongjun1@huawei.com +Fixes: 0cdfaceb9889 ("PCI: brcmstb: support BCM4908 with external PERST# signal controller") +Reported-by: Hulk Robot +Signed-off-by: Wei Yongjun +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Krzysztof Wilczyński +Acked-by: Florian Fainelli +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-brcmstb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c +index e330e6811f0b..69c999222cc8 100644 +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -1296,6 +1296,7 @@ static int brcm_pcie_probe(struct platform_device *pdev) + pcie->hw_rev = readl(pcie->base + PCIE_MISC_REVISION); + if (pcie->type == BCM4908 && pcie->hw_rev >= BRCM_PCIE_HW_REV_3_20) { + dev_err(pcie->dev, "hardware revision with unsupported PERST# setup\n"); ++ ret = -ENODEV; + goto fail; + } + +-- +2.30.2 + diff --git a/queue-5.12/pci-brcmstb-use-reset-rearm-instead-of-deassert-asse.patch b/queue-5.12/pci-brcmstb-use-reset-rearm-instead-of-deassert-asse.patch new file mode 100644 index 00000000000..2e08cdb25e6 --- /dev/null +++ b/queue-5.12/pci-brcmstb-use-reset-rearm-instead-of-deassert-asse.patch @@ -0,0 +1,102 @@ +From 6ffed3593921ed7a37a3b0b0fea2cdeccd9c1316 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Apr 2021 11:21:56 -0400 +Subject: PCI: brcmstb: Use reset/rearm instead of deassert/assert + +From: Jim Quinlan + +[ Upstream commit bb610757fcd74558ad94fe19993fd4470208dd02 ] + +The Broadcom STB PCIe RC uses a reset control "rescal" for certain chips. +The "rescal" implements a "pulse reset" so using assert/deassert is wrong +for this device. Instead, we use reset/rearm. We need to use rearm so +that we can reset it after a suspend/resume cycle; w/o using "rearm", the +"rescal" device will only ever fire once. + +Of course for suspend/resume to work we also need to put the reset/rearm +calls in the suspend and resume routines. + +Fixes: 740d6c3708a9 ("PCI: brcmstb: Add control of rescal reset") +Link: https://lore.kernel.org/r/20210430152156.21162-4-jim2101024@gmail.com +Signed-off-by: Jim Quinlan +Signed-off-by: Bjorn Helgaas +Acked-by: Florian Fainelli +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-brcmstb.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c +index 69c999222cc8..08bc788d9422 100644 +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -1148,6 +1148,7 @@ static int brcm_pcie_suspend(struct device *dev) + + brcm_pcie_turn_off(pcie); + ret = brcm_phy_stop(pcie); ++ reset_control_rearm(pcie->rescal); + clk_disable_unprepare(pcie->clk); + + return ret; +@@ -1163,9 +1164,13 @@ static int brcm_pcie_resume(struct device *dev) + base = pcie->base; + clk_prepare_enable(pcie->clk); + ++ ret = reset_control_reset(pcie->rescal); ++ if (ret) ++ goto err_disable_clk; ++ + ret = brcm_phy_start(pcie); + if (ret) +- goto err; ++ goto err_reset; + + /* Take bridge out of reset so we can access the SERDES reg */ + pcie->bridge_sw_init_set(pcie, 0); +@@ -1180,14 +1185,16 @@ static int brcm_pcie_resume(struct device *dev) + + ret = brcm_pcie_setup(pcie); + if (ret) +- goto err; ++ goto err_reset; + + if (pcie->msi) + brcm_msi_set_regs(pcie->msi); + + return 0; + +-err: ++err_reset: ++ reset_control_rearm(pcie->rescal); ++err_disable_clk: + clk_disable_unprepare(pcie->clk); + return ret; + } +@@ -1197,7 +1204,7 @@ static void __brcm_pcie_remove(struct brcm_pcie *pcie) + brcm_msi_remove(pcie); + brcm_pcie_turn_off(pcie); + brcm_phy_stop(pcie); +- reset_control_assert(pcie->rescal); ++ reset_control_rearm(pcie->rescal); + clk_disable_unprepare(pcie->clk); + } + +@@ -1278,13 +1285,13 @@ static int brcm_pcie_probe(struct platform_device *pdev) + return PTR_ERR(pcie->perst_reset); + } + +- ret = reset_control_deassert(pcie->rescal); ++ ret = reset_control_reset(pcie->rescal); + if (ret) + dev_err(&pdev->dev, "failed to deassert 'rescal'\n"); + + ret = brcm_phy_start(pcie); + if (ret) { +- reset_control_assert(pcie->rescal); ++ reset_control_rearm(pcie->rescal); + clk_disable_unprepare(pcie->clk); + return ret; + } +-- +2.30.2 + diff --git a/queue-5.12/pci-endpoint-fix-missing-destroy_workqueue.patch b/queue-5.12/pci-endpoint-fix-missing-destroy_workqueue.patch new file mode 100644 index 00000000000..27e283d8ff4 --- /dev/null +++ b/queue-5.12/pci-endpoint-fix-missing-destroy_workqueue.patch @@ -0,0 +1,47 @@ +From 53afdb308843a8085c9d0268ee9373ed5935ac19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Mar 2021 16:40:12 +0800 +Subject: PCI: endpoint: Fix missing destroy_workqueue() + +From: Yang Yingliang + +[ Upstream commit acaef7981a218813e3617edb9c01837808de063c ] + +Add the missing destroy_workqueue() before return from +pci_epf_test_init() in the error handling case and add +destroy_workqueue() in pci_epf_test_exit(). + +Link: https://lore.kernel.org/r/20210331084012.2091010-1-yangyingliang@huawei.com +Fixes: 349e7a85b25fa ("PCI: endpoint: functions: Add an EP function to test PCI") +Reported-by: Hulk Robot +Signed-off-by: Yang Yingliang +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-test.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c +index bc35b3566be6..f9760e73d568 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-test.c ++++ b/drivers/pci/endpoint/functions/pci-epf-test.c +@@ -925,6 +925,7 @@ static int __init pci_epf_test_init(void) + + ret = pci_epf_register_driver(&test_driver); + if (ret) { ++ destroy_workqueue(kpcitest_workqueue); + pr_err("Failed to register pci epf test driver --> %d\n", ret); + return ret; + } +@@ -935,6 +936,8 @@ module_init(pci_epf_test_init); + + static void __exit pci_epf_test_exit(void) + { ++ if (kpcitest_workqueue) ++ destroy_workqueue(kpcitest_workqueue); + pci_epf_unregister_driver(&test_driver); + } + module_exit(pci_epf_test_exit); +-- +2.30.2 + diff --git a/queue-5.12/pci-endpoint-fix-null-pointer-dereference-for-get_fe.patch b/queue-5.12/pci-endpoint-fix-null-pointer-dereference-for-get_fe.patch new file mode 100644 index 00000000000..dbfe9ea7e5d --- /dev/null +++ b/queue-5.12/pci-endpoint-fix-null-pointer-dereference-for-get_fe.patch @@ -0,0 +1,78 @@ +From cbeb7eaa4b64ae2b029ccb5253d6315233f7f000 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Mar 2021 15:46:09 +0530 +Subject: PCI: endpoint: Fix NULL pointer dereference for ->get_features() + +From: Shradha Todi + +[ Upstream commit 6613bc2301ba291a1c5a90e1dc24cf3edf223c03 ] + +get_features ops of pci_epc_ops may return NULL, causing NULL pointer +dereference in pci_epf_test_alloc_space function. Let us add a check for +pci_epc_feature pointer in pci_epf_test_bind before we access it to avoid +any such NULL pointer dereference and return -ENOTSUPP in case +pci_epc_feature is not found. + +When the patch is not applied and EPC features is not implemented in the +platform driver, we see the following dump due to kernel NULL pointer +dereference. + +Call trace: + pci_epf_test_bind+0xf4/0x388 + pci_epf_bind+0x3c/0x80 + pci_epc_epf_link+0xa8/0xcc + configfs_symlink+0x1a4/0x48c + vfs_symlink+0x104/0x184 + do_symlinkat+0x80/0xd4 + __arm64_sys_symlinkat+0x1c/0x24 + el0_svc_common.constprop.3+0xb8/0x170 + el0_svc_handler+0x70/0x88 + el0_svc+0x8/0x640 +Code: d2800581 b9403ab9 f9404ebb 8b394f60 (f9400400) +---[ end trace a438e3c5a24f9df0 ]--- + +Link: https://lore.kernel.org/r/20210324101609.79278-1-shradha.t@samsung.com +Fixes: 2c04c5b8eef79 ("PCI: pci-epf-test: Use pci_epc_get_features() to get EPC features") +Signed-off-by: Sriram Dash +Signed-off-by: Shradha Todi +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Pankaj Dubey +Reviewed-by: Kishon Vijay Abraham I +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-test.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c +index c0ac4e9cbe72..bc35b3566be6 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-test.c ++++ b/drivers/pci/endpoint/functions/pci-epf-test.c +@@ -833,15 +833,18 @@ static int pci_epf_test_bind(struct pci_epf *epf) + return -EINVAL; + + epc_features = pci_epc_get_features(epc, epf->func_no); +- if (epc_features) { +- linkup_notifier = epc_features->linkup_notifier; +- core_init_notifier = epc_features->core_init_notifier; +- test_reg_bar = pci_epc_get_first_free_bar(epc_features); +- if (test_reg_bar < 0) +- return -EINVAL; +- pci_epf_configure_bar(epf, epc_features); ++ if (!epc_features) { ++ dev_err(&epf->dev, "epc_features not implemented\n"); ++ return -EOPNOTSUPP; + } + ++ linkup_notifier = epc_features->linkup_notifier; ++ core_init_notifier = epc_features->core_init_notifier; ++ test_reg_bar = pci_epc_get_first_free_bar(epc_features); ++ if (test_reg_bar < 0) ++ return -EINVAL; ++ pci_epf_configure_bar(epf, epc_features); ++ + epf_test->test_reg_bar = test_reg_bar; + epf_test->epc_features = epc_features; + +-- +2.30.2 + diff --git a/queue-5.12/pci-iproc-fix-return-value-of-iproc_msi_irq_domain_a.patch b/queue-5.12/pci-iproc-fix-return-value-of-iproc_msi_irq_domain_a.patch new file mode 100644 index 00000000000..9e96ab193c6 --- /dev/null +++ b/queue-5.12/pci-iproc-fix-return-value-of-iproc_msi_irq_domain_a.patch @@ -0,0 +1,43 @@ +From bdb9c51db851a0891330a36f27c92336a21fb23f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Mar 2021 15:22:02 +0100 +Subject: PCI: iproc: Fix return value of iproc_msi_irq_domain_alloc() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 1e83130f01b04c16579ed5a5e03d729bcffc4c5d ] + +IRQ domain alloc function should return zero on success. Non-zero value +indicates failure. + +Link: https://lore.kernel.org/r/20210303142202.25780-1-pali@kernel.org +Fixes: fc54bae28818 ("PCI: iproc: Allow allocation of multiple MSIs") +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Krzysztof Wilczyński +Acked-by: Ray Jui +Acked-by: Marc Zyngier +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-iproc-msi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c +index 908475d27e0e..eede4e8f3f75 100644 +--- a/drivers/pci/controller/pcie-iproc-msi.c ++++ b/drivers/pci/controller/pcie-iproc-msi.c +@@ -271,7 +271,7 @@ static int iproc_msi_irq_domain_alloc(struct irq_domain *domain, + NULL, NULL); + } + +- return hwirq; ++ return 0; + } + + static void iproc_msi_irq_domain_free(struct irq_domain *domain, +-- +2.30.2 + diff --git a/queue-5.12/pci-rcec-fix-rciep-device-to-rcec-association.patch b/queue-5.12/pci-rcec-fix-rciep-device-to-rcec-association.patch new file mode 100644 index 00000000000..fabba2919a3 --- /dev/null +++ b/queue-5.12/pci-rcec-fix-rciep-device-to-rcec-association.patch @@ -0,0 +1,47 @@ +From 8d394731cae777ab0ab8d3ac04afb9a6d9dabf0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Feb 2021 09:17:17 +0800 +Subject: PCI/RCEC: Fix RCiEP device to RCEC association + +From: Qiuxu Zhuo + +[ Upstream commit d9b7eae8e3424c3480fe9f40ebafbb0c96426e4c ] + +rcec_assoc_rciep() used "rciep->devfn" (a single byte encoding both the +device and function number) as the device number to check whether the +corresponding bit was set in the RCEC's Association Bitmap for RCiEPs. + +But per PCIe r5.0, sec 7.9.10.2, "Association Bitmap for RCiEPs", the +32-bit bitmap contains one bit per device. That bit applies to all +functions of the device. + +Fix rcec_assoc_rciep() to convert the value of "rciep->devfn" to a device +number to ensure that RCiEP devices are correctly associated with the RCEC. + +Reported-and-tested-by: Wen Jin +Fixes: 507b460f8144 ("PCI/ERR: Add pcie_link_rcec() to associate RCiEPs") +Link: https://lore.kernel.org/r/20210222011717.43266-1-qiuxu.zhuo@intel.com +Signed-off-by: Qiuxu Zhuo +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sean V Kelley +Signed-off-by: Sasha Levin +--- + drivers/pci/pcie/rcec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/pcie/rcec.c b/drivers/pci/pcie/rcec.c +index 2c5c552994e4..d0bcd141ac9c 100644 +--- a/drivers/pci/pcie/rcec.c ++++ b/drivers/pci/pcie/rcec.c +@@ -32,7 +32,7 @@ static bool rcec_assoc_rciep(struct pci_dev *rcec, struct pci_dev *rciep) + + /* Same bus, so check bitmap */ + for_each_set_bit(devn, &bitmap, 32) +- if (devn == rciep->devfn) ++ if (devn == PCI_SLOT(rciep->devfn)) + return true; + + return false; +-- +2.30.2 + diff --git a/queue-5.12/pci-release-of-node-in-pci_scan_device-s-error-path.patch b/queue-5.12/pci-release-of-node-in-pci_scan_device-s-error-path.patch new file mode 100644 index 00000000000..75b27173be7 --- /dev/null +++ b/queue-5.12/pci-release-of-node-in-pci_scan_device-s-error-path.patch @@ -0,0 +1,38 @@ +From c657790c2f3f9e57fd4b2fe4921fc9f62194073d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jan 2021 02:28:26 +0300 +Subject: PCI: Release OF node in pci_scan_device()'s error path + +From: Dmitry Baryshkov + +[ Upstream commit c99e755a4a4c165cad6effb39faffd0f3377c02d ] + +In pci_scan_device(), if pci_setup_device() fails for any reason, the code +will not release device's of_node by calling pci_release_of_node(). Fix +that by calling the release function. + +Fixes: 98d9f30c820d ("pci/of: Match PCI devices to OF nodes dynamically") +Link: https://lore.kernel.org/r/20210124232826.1879-1-dmitry.baryshkov@linaro.org +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Bjorn Helgaas +Reviewed-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/pci/probe.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 953f15abc850..be51670572fa 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -2353,6 +2353,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) + pci_set_of_node(dev); + + if (pci_setup_device(dev)) { ++ pci_release_of_node(dev); + pci_bus_put(dev->bus); + kfree(dev); + return NULL; +-- +2.30.2 + diff --git a/queue-5.12/pinctrl-samsung-use-int-for-register-masks-in-exynos.patch b/queue-5.12/pinctrl-samsung-use-int-for-register-masks-in-exynos.patch new file mode 100644 index 00000000000..41e1e7ca5e4 --- /dev/null +++ b/queue-5.12/pinctrl-samsung-use-int-for-register-masks-in-exynos.patch @@ -0,0 +1,72 @@ +From ab8de5170786679dea3eca0b8b416700d0c68b7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Apr 2021 21:50:29 +0200 +Subject: pinctrl: samsung: use 'int' for register masks in Exynos + +From: Krzysztof Kozlowski + +[ Upstream commit fa0c10a5f3a49130dd11281aa27e7e1c8654abc7 ] + +The Special Function Registers on all Exynos SoC, including ARM64, are +32-bit wide, so entire driver uses matching functions like readl() or +writel(). On 64-bit ARM using unsigned long for register masks: +1. makes little sense as immediately after bitwise operation it will be + cast to 32-bit value when calling writel(), +2. is actually error-prone because it might promote other operands to + 64-bit. + +Addresses-Coverity: Unintentional integer overflow +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Sylwester Nawrocki +Link: https://lore.kernel.org/r/20210408195029.69974-1-krzysztof.kozlowski@canonical.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/samsung/pinctrl-exynos.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c +index 0cd7f33cdf25..2b99f4130e1e 100644 +--- a/drivers/pinctrl/samsung/pinctrl-exynos.c ++++ b/drivers/pinctrl/samsung/pinctrl-exynos.c +@@ -55,7 +55,7 @@ static void exynos_irq_mask(struct irq_data *irqd) + struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); + unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset; +- unsigned long mask; ++ unsigned int mask; + unsigned long flags; + + raw_spin_lock_irqsave(&bank->slock, flags); +@@ -83,7 +83,7 @@ static void exynos_irq_unmask(struct irq_data *irqd) + struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); + unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset; +- unsigned long mask; ++ unsigned int mask; + unsigned long flags; + + /* +@@ -483,7 +483,7 @@ static void exynos_irq_eint0_15(struct irq_desc *desc) + chained_irq_exit(chip, desc); + } + +-static inline void exynos_irq_demux_eint(unsigned long pend, ++static inline void exynos_irq_demux_eint(unsigned int pend, + struct irq_domain *domain) + { + unsigned int irq; +@@ -500,8 +500,8 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc) + { + struct irq_chip *chip = irq_desc_get_chip(desc); + struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc); +- unsigned long pend; +- unsigned long mask; ++ unsigned int pend; ++ unsigned int mask; + int i; + + chained_irq_enter(chip, desc); +-- +2.30.2 + diff --git a/queue-5.12/pnfs-flexfiles-fix-incorrect-size-check-in-decode_nf.patch b/queue-5.12/pnfs-flexfiles-fix-incorrect-size-check-in-decode_nf.patch new file mode 100644 index 00000000000..3b124af7589 --- /dev/null +++ b/queue-5.12/pnfs-flexfiles-fix-incorrect-size-check-in-decode_nf.patch @@ -0,0 +1,52 @@ +From 4135381dcb9d36d4c7ffefe6b8f4d088563a636d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Mar 2021 11:56:49 +0300 +Subject: pNFS/flexfiles: fix incorrect size check in decode_nfs_fh() + +From: Nikola Livic + +[ Upstream commit ed34695e15aba74f45247f1ee2cf7e09d449f925 ] + +We (adam zabrocki, alexander matrosov, alexander tereshkin, maksym +bazalii) observed the check: + + if (fh->size > sizeof(struct nfs_fh)) + +should not use the size of the nfs_fh struct which includes an extra two +bytes from the size field. + +struct nfs_fh { + unsigned short size; + unsigned char data[NFS_MAXFHSIZE]; +} + +but should determine the size from data[NFS_MAXFHSIZE] so the memcpy +will not write 2 bytes beyond destination. The proposed fix is to +compare against the NFS_MAXFHSIZE directly, as is done elsewhere in fs +code base. + +Fixes: d67ae825a59d ("pnfs/flexfiles: Add the FlexFile Layout Driver") +Signed-off-by: Nikola Livic +Signed-off-by: Dan Carpenter +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/flexfilelayout/flexfilelayout.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c +index 872112bffcab..d383de00d486 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -106,7 +106,7 @@ static int decode_nfs_fh(struct xdr_stream *xdr, struct nfs_fh *fh) + if (unlikely(!p)) + return -ENOBUFS; + fh->size = be32_to_cpup(p++); +- if (fh->size > sizeof(struct nfs_fh)) { ++ if (fh->size > NFS_MAXFHSIZE) { + printk(KERN_ERR "NFS flexfiles: Too big fh received %d\n", + fh->size); + return -EOVERFLOW; +-- +2.30.2 + diff --git a/queue-5.12/powerpc-32-statically-initialise-first-emergency-con.patch b/queue-5.12/powerpc-32-statically-initialise-first-emergency-con.patch new file mode 100644 index 00000000000..f23b9fc0186 --- /dev/null +++ b/queue-5.12/powerpc-32-statically-initialise-first-emergency-con.patch @@ -0,0 +1,59 @@ +From b8182a1eb159e49b29b9ed241fb4b63d69d59be4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Mar 2021 12:50:25 +0000 +Subject: powerpc/32: Statically initialise first emergency context + +From: Christophe Leroy + +[ Upstream commit a4719f5bb6d7dc220bffdc1b9f5ce5eaa5543581 ] + +The check of the emergency context initialisation in +vmap_stack_overflow is buggy for the SMP case, as it +compares r1 with 0 while in the SMP case r1 is offseted +by the CPU id. + +Instead of fixing it, just perform static initialisation +of the first emergency context. + +Signed-off-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/4a67ba422be75713286dca0c86ee0d3df2eb6dfa.1615552867.git.christophe.leroy@csgroup.eu +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/head_32.h | 6 +----- + arch/powerpc/kernel/setup_32.c | 2 +- + 2 files changed, 2 insertions(+), 6 deletions(-) + +diff --git a/arch/powerpc/kernel/head_32.h b/arch/powerpc/kernel/head_32.h +index 5d4706c14572..cf8ca08295bf 100644 +--- a/arch/powerpc/kernel/head_32.h ++++ b/arch/powerpc/kernel/head_32.h +@@ -261,11 +261,7 @@ label: + lis r1, emergency_ctx@ha + #endif + lwz r1, emergency_ctx@l(r1) +- cmpwi cr1, r1, 0 +- bne cr1, 1f +- lis r1, init_thread_union@ha +- addi r1, r1, init_thread_union@l +-1: addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE ++ addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE + EXCEPTION_PROLOG_2 + SAVE_NVGPRS(r11) + addi r3, r1, STACK_FRAME_OVERHEAD +diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c +index 8ba49a6bf515..d7c1f92152af 100644 +--- a/arch/powerpc/kernel/setup_32.c ++++ b/arch/powerpc/kernel/setup_32.c +@@ -164,7 +164,7 @@ void __init irqstack_early_init(void) + } + + #ifdef CONFIG_VMAP_STACK +-void *emergency_ctx[NR_CPUS] __ro_after_init; ++void *emergency_ctx[NR_CPUS] __ro_after_init = {[0] = &init_stack}; + + void __init emergency_stack_init(void) + { +-- +2.30.2 + diff --git a/queue-5.12/powerpc-iommu-annotate-nested-lock-for-lockdep.patch b/queue-5.12/powerpc-iommu-annotate-nested-lock-for-lockdep.patch new file mode 100644 index 00000000000..f2982416819 --- /dev/null +++ b/queue-5.12/powerpc-iommu-annotate-nested-lock-for-lockdep.patch @@ -0,0 +1,70 @@ +From c31eae85622fd837e89a714b0e233062a5995726 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Mar 2021 17:36:53 +1100 +Subject: powerpc/iommu: Annotate nested lock for lockdep + +From: Alexey Kardashevskiy + +[ Upstream commit cc7130bf119add37f36238343a593b71ef6ecc1e ] + +The IOMMU table is divided into pools for concurrent mappings and each +pool has a separate spinlock. When taking the ownership of an IOMMU group +to pass through a device to a VM, we lock these spinlocks which triggers +a false negative warning in lockdep (below). + +This fixes it by annotating the large pool's spinlock as a nest lock +which makes lockdep not complaining when locking nested locks if +the nest lock is locked already. + +=== +WARNING: possible recursive locking detected +5.11.0-le_syzkaller_a+fstn1 #100 Not tainted +-------------------------------------------- +qemu-system-ppc/4129 is trying to acquire lock: +c0000000119bddb0 (&(p->lock)/1){....}-{2:2}, at: iommu_take_ownership+0xac/0x1e0 + +but task is already holding lock: +c0000000119bdd30 (&(p->lock)/1){....}-{2:2}, at: iommu_take_ownership+0xac/0x1e0 + +other info that might help us debug this: + Possible unsafe locking scenario: + + CPU0 + ---- + lock(&(p->lock)/1); + lock(&(p->lock)/1); +=== + +Signed-off-by: Alexey Kardashevskiy +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20210301063653.51003-1-aik@ozlabs.ru +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/iommu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c +index c00214a4355c..4023f91defa6 100644 +--- a/arch/powerpc/kernel/iommu.c ++++ b/arch/powerpc/kernel/iommu.c +@@ -1096,7 +1096,7 @@ int iommu_take_ownership(struct iommu_table *tbl) + + spin_lock_irqsave(&tbl->large_pool.lock, flags); + for (i = 0; i < tbl->nr_pools; i++) +- spin_lock(&tbl->pools[i].lock); ++ spin_lock_nest_lock(&tbl->pools[i].lock, &tbl->large_pool.lock); + + iommu_table_release_pages(tbl); + +@@ -1124,7 +1124,7 @@ void iommu_release_ownership(struct iommu_table *tbl) + + spin_lock_irqsave(&tbl->large_pool.lock, flags); + for (i = 0; i < tbl->nr_pools; i++) +- spin_lock(&tbl->pools[i].lock); ++ spin_lock_nest_lock(&tbl->pools[i].lock, &tbl->large_pool.lock); + + memset(tbl->it_map, 0, sz); + +-- +2.30.2 + diff --git a/queue-5.12/powerpc-mm-add-cond_resched-while-removing-hpte-mapp.patch b/queue-5.12/powerpc-mm-add-cond_resched-while-removing-hpte-mapp.patch new file mode 100644 index 00000000000..6d39c688ef1 --- /dev/null +++ b/queue-5.12/powerpc-mm-add-cond_resched-while-removing-hpte-mapp.patch @@ -0,0 +1,87 @@ +From 270be26b8f546d32f57a5152cd4bb76d86f8b0d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Apr 2021 22:01:48 +0530 +Subject: powerpc/mm: Add cond_resched() while removing hpte mappings + +From: Vaibhav Jain + +[ Upstream commit a5d6a3e73acbd619dd5b7b831762b755f9e2db80 ] + +While removing large number of mappings from hash page tables for +large memory systems as soft-lockup is reported because of the time +spent inside htap_remove_mapping() like one below: + + watchdog: BUG: soft lockup - CPU#8 stuck for 23s! + + NIP plpar_hcall+0x38/0x58 + LR pSeries_lpar_hpte_invalidate+0x68/0xb0 + Call Trace: + 0x1fffffffffff000 (unreliable) + pSeries_lpar_hpte_removebolted+0x9c/0x230 + hash__remove_section_mapping+0xec/0x1c0 + remove_section_mapping+0x28/0x3c + arch_remove_memory+0xfc/0x150 + devm_memremap_pages_release+0x180/0x2f0 + devm_action_release+0x30/0x50 + release_nodes+0x28c/0x300 + device_release_driver_internal+0x16c/0x280 + unbind_store+0x124/0x170 + drv_attr_store+0x44/0x60 + sysfs_kf_write+0x64/0x90 + kernfs_fop_write+0x1b0/0x290 + __vfs_write+0x3c/0x70 + vfs_write+0xd4/0x270 + ksys_write+0xdc/0x130 + system_call+0x5c/0x70 + +Fix this by adding a cond_resched() to the loop in +htap_remove_mapping() that issues hcall to remove hpte mapping. The +call to cond_resched() is issued every HZ jiffies which should prevent +the soft-lockup from being reported. + +Suggested-by: Aneesh Kumar K.V +Signed-off-by: Vaibhav Jain +Reviewed-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20210404163148.321346-1-vaibhav@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/mm/book3s64/hash_utils.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c +index 7719995323c3..12de1906e97b 100644 +--- a/arch/powerpc/mm/book3s64/hash_utils.c ++++ b/arch/powerpc/mm/book3s64/hash_utils.c +@@ -338,7 +338,7 @@ repeat: + int htab_remove_mapping(unsigned long vstart, unsigned long vend, + int psize, int ssize) + { +- unsigned long vaddr; ++ unsigned long vaddr, time_limit; + unsigned int step, shift; + int rc; + int ret = 0; +@@ -351,8 +351,19 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend, + + /* Unmap the full range specificied */ + vaddr = ALIGN_DOWN(vstart, step); ++ time_limit = jiffies + HZ; ++ + for (;vaddr < vend; vaddr += step) { + rc = mmu_hash_ops.hpte_removebolted(vaddr, psize, ssize); ++ ++ /* ++ * For large number of mappings introduce a cond_resched() ++ * to prevent softlockup warnings. ++ */ ++ if (time_after(jiffies, time_limit)) { ++ cond_resched(); ++ time_limit = jiffies + HZ; ++ } + if (rc == -ENOENT) { + ret = -ENOENT; + continue; +-- +2.30.2 + diff --git a/queue-5.12/powerpc-powernv-memtrace-fix-dcache-flushing.patch b/queue-5.12/powerpc-powernv-memtrace-fix-dcache-flushing.patch new file mode 100644 index 00000000000..e3a43d10ceb --- /dev/null +++ b/queue-5.12/powerpc-powernv-memtrace-fix-dcache-flushing.patch @@ -0,0 +1,42 @@ +From c9cb7faf2ed722bf5d60f834a6e0b8cb18bc6318 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 May 2021 21:32:54 +0530 +Subject: powerpc/powernv/memtrace: Fix dcache flushing + +From: Sandipan Das + +[ Upstream commit b910fcbada9721c21f1d59ab59e07e8e354c23cc ] + +Trace memory is cleared and the corresponding dcache lines +are flushed after allocation. However, this should not be +done using the PFN. This adds the missing conversion to +virtual address. + +Fixes: 2ac02e5ecec0 ("powerpc/mm: Remove dcache flush from memory remove.") +Signed-off-by: Sandipan Das +Reviewed-by: Aneesh Kumar K.V +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20210501160254.1179831-1-sandipan@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/powernv/memtrace.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c +index 019669eb21d2..4ab7c3ef5826 100644 +--- a/arch/powerpc/platforms/powernv/memtrace.c ++++ b/arch/powerpc/platforms/powernv/memtrace.c +@@ -88,8 +88,8 @@ static void memtrace_clear_range(unsigned long start_pfn, + * Before we go ahead and use this range as cache inhibited range + * flush the cache. + */ +- flush_dcache_range_chunked(PFN_PHYS(start_pfn), +- PFN_PHYS(start_pfn + nr_pages), ++ flush_dcache_range_chunked((unsigned long)pfn_to_kaddr(start_pfn), ++ (unsigned long)pfn_to_kaddr(start_pfn + nr_pages), + FLUSH_CHUNK_SIZE); + } + +-- +2.30.2 + diff --git a/queue-5.12/powerpc-pseries-stop-calling-printk-in-rtas_stop_sel.patch b/queue-5.12/powerpc-pseries-stop-calling-printk-in-rtas_stop_sel.patch new file mode 100644 index 00000000000..6b3d8bafbac --- /dev/null +++ b/queue-5.12/powerpc-pseries-stop-calling-printk-in-rtas_stop_sel.patch @@ -0,0 +1,72 @@ +From 836d4f458beb8778d8a686e41b006d87e8f3ced3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 Apr 2021 23:54:13 +1000 +Subject: powerpc/pseries: Stop calling printk in rtas_stop_self() + +From: Michael Ellerman + +[ Upstream commit ed8029d7b472369a010a1901358567ca3b6dbb0d ] + +RCU complains about us calling printk() from an offline CPU: + + ============================= + WARNING: suspicious RCU usage + 5.12.0-rc7-02874-g7cf90e481cb8 #1 Not tainted + ----------------------------- + kernel/locking/lockdep.c:3568 RCU-list traversed in non-reader section!! + + other info that might help us debug this: + + RCU used illegally from offline CPU! + rcu_scheduler_active = 2, debug_locks = 1 + no locks held by swapper/0/0. + + stack backtrace: + CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.12.0-rc7-02874-g7cf90e481cb8 #1 + Call Trace: + dump_stack+0xec/0x144 (unreliable) + lockdep_rcu_suspicious+0x124/0x144 + __lock_acquire+0x1098/0x28b0 + lock_acquire+0x128/0x600 + _raw_spin_lock_irqsave+0x6c/0xc0 + down_trylock+0x2c/0x70 + __down_trylock_console_sem+0x60/0x140 + vprintk_emit+0x1a8/0x4b0 + vprintk_func+0xcc/0x200 + printk+0x40/0x54 + pseries_cpu_offline_self+0xc0/0x120 + arch_cpu_idle_dead+0x54/0x70 + do_idle+0x174/0x4a0 + cpu_startup_entry+0x38/0x40 + rest_init+0x268/0x388 + start_kernel+0x748/0x790 + start_here_common+0x1c/0x614 + +Which happens because by the time we get to rtas_stop_self() we are +already offline. In addition the message can be spammy, and is not that +helpful for users, so remove it. + +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20210418135413.1204031-1-mpe@ellerman.id.au +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/pseries/hotplug-cpu.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c +index 12cbffd3c2e3..325f3b220f36 100644 +--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c ++++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c +@@ -47,9 +47,6 @@ static void rtas_stop_self(void) + + BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE); + +- printk("cpu %u (hwid %u) Ready to die...\n", +- smp_processor_id(), hard_smp_processor_id()); +- + rtas_call_unlocked(&args, rtas_stop_self_token, 0, 1, NULL); + + panic("Alas, I survived.\n"); +-- +2.30.2 + diff --git a/queue-5.12/powerpc-smp-set-numa-node-before-updating-mask.patch b/queue-5.12/powerpc-smp-set-numa-node-before-updating-mask.patch new file mode 100644 index 00000000000..db73834dd5f --- /dev/null +++ b/queue-5.12/powerpc-smp-set-numa-node-before-updating-mask.patch @@ -0,0 +1,90 @@ +From 3f4ca87e059f3c14baf078099e947c002e383141 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Apr 2021 21:12:00 +0530 +Subject: powerpc/smp: Set numa node before updating mask + +From: Srikar Dronamraju + +[ Upstream commit 6980d13f0dd189846887bbbfa43793d9a41768d3 ] + +Geethika reported a trace when doing a dlpar CPU add. + +------------[ cut here ]------------ +WARNING: CPU: 152 PID: 1134 at kernel/sched/topology.c:2057 +CPU: 152 PID: 1134 Comm: kworker/152:1 Not tainted 5.12.0-rc5-master #5 +Workqueue: events cpuset_hotplug_workfn +NIP: c0000000001cfc14 LR: c0000000001cfc10 CTR: c0000000007e3420 +REGS: c0000034a08eb260 TRAP: 0700 Not tainted (5.12.0-rc5-master+) +MSR: 8000000000029033 CR: 28828422 XER: 00000020 +CFAR: c0000000001fd888 IRQMASK: 0 #012GPR00: c0000000001cfc10 +c0000034a08eb500 c000000001f35400 0000000000000027 #012GPR04: +c0000035abaa8010 c0000035abb30a00 0000000000000027 c0000035abaa8018 +#012GPR08: 0000000000000023 c0000035abaaef48 00000035aa540000 +c0000035a49dffe8 #012GPR12: 0000000028828424 c0000035bf1a1c80 +0000000000000497 0000000000000004 #012GPR16: c00000000347a258 +0000000000000140 c00000000203d468 c000000001a1a490 #012GPR20: +c000000001f9c160 c0000034adf70920 c0000034aec9fd20 0000000100087bd3 +#012GPR24: 0000000100087bd3 c0000035b3de09f8 0000000000000030 +c0000035b3de09f8 #012GPR28: 0000000000000028 c00000000347a280 +c0000034aefe0b00 c0000000010a2a68 +NIP [c0000000001cfc14] build_sched_domains+0x6a4/0x1500 +LR [c0000000001cfc10] build_sched_domains+0x6a0/0x1500 +Call Trace: +[c0000034a08eb500] [c0000000001cfc10] build_sched_domains+0x6a0/0x1500 (unreliable) +[c0000034a08eb640] [c0000000001d1e6c] partition_sched_domains_locked+0x3ec/0x530 +[c0000034a08eb6e0] [c0000000002936d4] rebuild_sched_domains_locked+0x524/0xbf0 +[c0000034a08eb7e0] [c000000000296bb0] rebuild_sched_domains+0x40/0x70 +[c0000034a08eb810] [c000000000296e74] cpuset_hotplug_workfn+0x294/0xe20 +[c0000034a08ebc30] [c000000000178dd0] process_one_work+0x300/0x670 +[c0000034a08ebd10] [c0000000001791b8] worker_thread+0x78/0x520 +[c0000034a08ebda0] [c000000000185090] kthread+0x1a0/0x1b0 +[c0000034a08ebe10] [c00000000000ccec] ret_from_kernel_thread+0x5c/0x70 +Instruction dump: +7d2903a6 4e800421 e8410018 7f67db78 7fe6fb78 7f45d378 7f84e378 7c681b78 +3c62ff1a 3863c6f8 4802dc35 60000000 <0fe00000> 3920fff4 f9210070 e86100a0 +---[ end trace 532d9066d3d4d7ec ]--- + +Some of the per-CPU masks use cpu_cpu_mask as a filter to limit the search +for related CPUs. On a dlpar add of a CPU, update cpu_cpu_mask before +updating the per-CPU masks. This will ensure the cpu_cpu_mask is updated +correctly before its used in setting the masks. Setting the numa_node will +ensure that when cpu_cpu_mask() gets called, the correct node number is +used. This code movement helped fix the above call trace. + +Reported-by: Geetika Moolchandani +Signed-off-by: Srikar Dronamraju +Reviewed-by: Nathan Lynch +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20210401154200.150077-1-srikar@linux.vnet.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/smp.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c +index 5c7ce1d50631..c2473e20f5f5 100644 +--- a/arch/powerpc/kernel/smp.c ++++ b/arch/powerpc/kernel/smp.c +@@ -1546,6 +1546,9 @@ void start_secondary(void *unused) + + vdso_getcpu_init(); + #endif ++ set_numa_node(numa_cpu_lookup_table[cpu]); ++ set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu])); ++ + /* Update topology CPU masks */ + add_cpu_to_masks(cpu); + +@@ -1564,9 +1567,6 @@ void start_secondary(void *unused) + shared_caches = true; + } + +- set_numa_node(numa_cpu_lookup_table[cpu]); +- set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu])); +- + smp_wmb(); + notify_cpu_starting(cpu); + set_cpu_online(cpu, true); +-- +2.30.2 + diff --git a/queue-5.12/powerpc-xive-use-the-ibm-chip-id-property-only-under.patch b/queue-5.12/powerpc-xive-use-the-ibm-chip-id-property-only-under.patch new file mode 100644 index 00000000000..f2409c45142 --- /dev/null +++ b/queue-5.12/powerpc-xive-use-the-ibm-chip-id-property-only-under.patch @@ -0,0 +1,101 @@ +From 48c1ec6cc54ba73fcf7c6b1da49c07bf9b7c9b44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Apr 2021 15:03:52 +0200 +Subject: powerpc/xive: Use the "ibm, chip-id" property only under PowerNV +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Cédric Le Goater + +[ Upstream commit e9e16917bc388846163b8566a298a291d71e44c9 ] + +The 'chip_id' field of the XIVE CPU structure is used to choose a +target for a source located on the same chip. For that, the XIVE +driver queries the chip identifier from the "ibm,chip-id" property +and compares it to a 'src_chip' field identifying the chip of a +source. This information is only available on the PowerNV platform, +'src_chip' being assigned to XIVE_INVALID_CHIP_ID under pSeries. + +The "ibm,chip-id" property is also not available on all platforms. It +was first introduced on PowerNV and later, under QEMU for pSeries/KVM. +However, the property is not part of PAPR and does not exist under +pSeries/PowerVM. + +Assign 'chip_id' to XIVE_INVALID_CHIP_ID by default and let the +PowerNV platform override the value with the "ibm,chip-id" property. + +Signed-off-by: Cédric Le Goater +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20210413130352.1183267-1-clg@kaod.org +Signed-off-by: Sasha Levin +--- + arch/powerpc/sysdev/xive/common.c | 9 +++------ + arch/powerpc/sysdev/xive/native.c | 6 ++++++ + arch/powerpc/sysdev/xive/xive-internal.h | 1 + + 3 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c +index 5cacb632eb37..31b657c37735 100644 +--- a/arch/powerpc/sysdev/xive/common.c ++++ b/arch/powerpc/sysdev/xive/common.c +@@ -1341,17 +1341,14 @@ static int xive_prepare_cpu(unsigned int cpu) + + xc = per_cpu(xive_cpu, cpu); + if (!xc) { +- struct device_node *np; +- + xc = kzalloc_node(sizeof(struct xive_cpu), + GFP_KERNEL, cpu_to_node(cpu)); + if (!xc) + return -ENOMEM; +- np = of_get_cpu_node(cpu, NULL); +- if (np) +- xc->chip_id = of_get_ibm_chip_id(np); +- of_node_put(np); + xc->hw_ipi = XIVE_BAD_IRQ; ++ xc->chip_id = XIVE_INVALID_CHIP_ID; ++ if (xive_ops->prepare_cpu) ++ xive_ops->prepare_cpu(cpu, xc); + + per_cpu(xive_cpu, cpu) = xc; + } +diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c +index 05a800a3104e..57e3f1540435 100644 +--- a/arch/powerpc/sysdev/xive/native.c ++++ b/arch/powerpc/sysdev/xive/native.c +@@ -380,6 +380,11 @@ static void xive_native_update_pending(struct xive_cpu *xc) + } + } + ++static void xive_native_prepare_cpu(unsigned int cpu, struct xive_cpu *xc) ++{ ++ xc->chip_id = cpu_to_chip_id(cpu); ++} ++ + static void xive_native_setup_cpu(unsigned int cpu, struct xive_cpu *xc) + { + s64 rc; +@@ -462,6 +467,7 @@ static const struct xive_ops xive_native_ops = { + .match = xive_native_match, + .shutdown = xive_native_shutdown, + .update_pending = xive_native_update_pending, ++ .prepare_cpu = xive_native_prepare_cpu, + .setup_cpu = xive_native_setup_cpu, + .teardown_cpu = xive_native_teardown_cpu, + .sync_source = xive_native_sync_source, +diff --git a/arch/powerpc/sysdev/xive/xive-internal.h b/arch/powerpc/sysdev/xive/xive-internal.h +index 9cf57c722faa..6478be19b4d3 100644 +--- a/arch/powerpc/sysdev/xive/xive-internal.h ++++ b/arch/powerpc/sysdev/xive/xive-internal.h +@@ -46,6 +46,7 @@ struct xive_ops { + u32 *sw_irq); + int (*setup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio); + void (*cleanup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio); ++ void (*prepare_cpu)(unsigned int cpu, struct xive_cpu *xc); + void (*setup_cpu)(unsigned int cpu, struct xive_cpu *xc); + void (*teardown_cpu)(unsigned int cpu, struct xive_cpu *xc); + bool (*match)(struct device_node *np); +-- +2.30.2 + diff --git a/queue-5.12/pwm-atmel-fix-duty-cycle-calculation-in-.get_state.patch b/queue-5.12/pwm-atmel-fix-duty-cycle-calculation-in-.get_state.patch new file mode 100644 index 00000000000..17d667c11b5 --- /dev/null +++ b/queue-5.12/pwm-atmel-fix-duty-cycle-calculation-in-.get_state.patch @@ -0,0 +1,39 @@ +From 08cd487d9ecd03f27b6bf632b040449ed8c0fb18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Apr 2021 11:51:17 +0200 +Subject: pwm: atmel: Fix duty cycle calculation in .get_state() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 453e8b3d8e36ddcb283b3d1698864a03ea45599a ] + +The CDTY register contains the number of inactive cycles. .apply() does +this correctly, however .get_state() got this wrong. + +Fixes: 651b510a74d4 ("pwm: atmel: Implement .get_state()") +Signed-off-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-atmel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c +index 5813339b597b..3292158157b6 100644 +--- a/drivers/pwm/pwm-atmel.c ++++ b/drivers/pwm/pwm-atmel.c +@@ -319,7 +319,7 @@ static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + + cdty = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, + atmel_pwm->data->regs.duty); +- tmp = (u64)cdty * NSEC_PER_SEC; ++ tmp = (u64)(cprd - cdty) * NSEC_PER_SEC; + tmp <<= pres; + state->duty_cycle = DIV64_U64_ROUND_UP(tmp, rate); + +-- +2.30.2 + diff --git a/queue-5.12/qtnfmac-fix-possible-buffer-overflow-in-qtnf_event_h.patch b/queue-5.12/qtnfmac-fix-possible-buffer-overflow-in-qtnf_event_h.patch new file mode 100644 index 00000000000..b9e9689b9df --- /dev/null +++ b/queue-5.12/qtnfmac-fix-possible-buffer-overflow-in-qtnf_event_h.patch @@ -0,0 +1,43 @@ +From e07c47d0e7a085b2fb64f913d65373c6be693650 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Apr 2021 15:58:42 +0100 +Subject: qtnfmac: Fix possible buffer overflow in + qtnf_event_handle_external_auth + +From: Lee Gibson + +[ Upstream commit 130f634da1af649205f4a3dd86cbe5c126b57914 ] + +Function qtnf_event_handle_external_auth calls memcpy without +checking the length. +A user could control that length and trigger a buffer overflow. +Fix by checking the length is within the maximum allowed size. + +Signed-off-by: Lee Gibson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20210419145842.345787-1-leegib@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/quantenna/qtnfmac/event.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c +index c775c177933b..8dc80574d08d 100644 +--- a/drivers/net/wireless/quantenna/qtnfmac/event.c ++++ b/drivers/net/wireless/quantenna/qtnfmac/event.c +@@ -570,8 +570,10 @@ qtnf_event_handle_external_auth(struct qtnf_vif *vif, + return 0; + + if (ev->ssid_len) { +- memcpy(auth.ssid.ssid, ev->ssid, ev->ssid_len); +- auth.ssid.ssid_len = ev->ssid_len; ++ int len = clamp_val(ev->ssid_len, 0, IEEE80211_MAX_SSID_LEN); ++ ++ memcpy(auth.ssid.ssid, ev->ssid, len); ++ auth.ssid.ssid_len = len; + } + + auth.key_mgmt_suite = le32_to_cpu(ev->akm_suite); +-- +2.30.2 + diff --git a/queue-5.12/remoteproc-pru-fix-and-cleanup-firmware-interrupt-ma.patch b/queue-5.12/remoteproc-pru-fix-and-cleanup-firmware-interrupt-ma.patch new file mode 100644 index 00000000000..a49b594d2df --- /dev/null +++ b/queue-5.12/remoteproc-pru-fix-and-cleanup-firmware-interrupt-ma.patch @@ -0,0 +1,103 @@ +From b98aab3b2fc3e7cdff24819d136f4eec86ab3f26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Apr 2021 10:56:41 -0500 +Subject: remoteproc: pru: Fix and cleanup firmware interrupt mapping logic + +From: Suman Anna + +[ Upstream commit 880a66e026fbe6a17cd59fe0ee942bbad62a6c26 ] + +The PRU firmware interrupt mappings are configured and unconfigured in +.start() and .stop() callbacks respectively using the variables 'evt_count' +and a 'mapped_irq' pointer. These variables are modified only during these +callbacks but are not re-initialized/reset properly during unwind or +failure paths. These stale values caused a kernel crash while stopping a +PRU remoteproc running a different firmware with no events on a subsequent +run after a previous run that was running a firmware with events. + +Fix this crash by ensuring that the evt_count is 0 and the mapped_irq +pointer is set to NULL in pru_dispose_irq_mapping(). Also, reset these +variables properly during any failures in the .start() callback. While +at this, the pru_dispose_irq_mapping() callsites are all made to look +the same, moving any conditional logic to inside the function. + +Reviewed-by: Mathieu Poirier +Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration") +Reported-by: Vignesh Raghavendra +Signed-off-by: Suman Anna +Link: https://lore.kernel.org/r/20210407155641.5501-4-s-anna@ti.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/pru_rproc.c | 22 +++++++++++++++++----- + 1 file changed, 17 insertions(+), 5 deletions(-) + +diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c +index dcd5ea0d1f37..549ed3fed625 100644 +--- a/drivers/remoteproc/pru_rproc.c ++++ b/drivers/remoteproc/pru_rproc.c +@@ -266,12 +266,17 @@ static void pru_rproc_create_debug_entries(struct rproc *rproc) + + static void pru_dispose_irq_mapping(struct pru_rproc *pru) + { +- while (pru->evt_count--) { ++ if (!pru->mapped_irq) ++ return; ++ ++ while (pru->evt_count) { ++ pru->evt_count--; + if (pru->mapped_irq[pru->evt_count] > 0) + irq_dispose_mapping(pru->mapped_irq[pru->evt_count]); + } + + kfree(pru->mapped_irq); ++ pru->mapped_irq = NULL; + } + + /* +@@ -307,8 +312,10 @@ static int pru_handle_intrmap(struct rproc *rproc) + pru->evt_count = rsc->num_evts; + pru->mapped_irq = kcalloc(pru->evt_count, sizeof(unsigned int), + GFP_KERNEL); +- if (!pru->mapped_irq) ++ if (!pru->mapped_irq) { ++ pru->evt_count = 0; + return -ENOMEM; ++ } + + /* + * parse and fill in system event to interrupt channel and +@@ -317,13 +324,19 @@ static int pru_handle_intrmap(struct rproc *rproc) + * corresponding sibling PRUSS INTC node. + */ + parent = of_get_parent(dev_of_node(pru->dev)); +- if (!parent) ++ if (!parent) { ++ kfree(pru->mapped_irq); ++ pru->mapped_irq = NULL; ++ pru->evt_count = 0; + return -ENODEV; ++ } + + irq_parent = of_get_child_by_name(parent, "interrupt-controller"); + of_node_put(parent); + if (!irq_parent) { + kfree(pru->mapped_irq); ++ pru->mapped_irq = NULL; ++ pru->evt_count = 0; + return -ENODEV; + } + +@@ -398,8 +411,7 @@ static int pru_rproc_stop(struct rproc *rproc) + pru_control_write_reg(pru, PRU_CTRL_CTRL, val); + + /* dispose irq mapping - new firmware can provide new mapping */ +- if (pru->mapped_irq) +- pru_dispose_irq_mapping(pru); ++ pru_dispose_irq_mapping(pru); + + return 0; + } +-- +2.30.2 + diff --git a/queue-5.12/remoteproc-pru-fix-wrong-success-return-value-for-fw.patch b/queue-5.12/remoteproc-pru-fix-wrong-success-return-value-for-fw.patch new file mode 100644 index 00000000000..c9494e8fd37 --- /dev/null +++ b/queue-5.12/remoteproc-pru-fix-wrong-success-return-value-for-fw.patch @@ -0,0 +1,49 @@ +From f87e40ed8495b0ec250801680223a141ff66652b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Apr 2021 10:56:40 -0500 +Subject: remoteproc: pru: Fix wrong success return value for fw events + +From: Suman Anna + +[ Upstream commit 1fe72bcfac087dba5ab52778e0646ed9e145cd32 ] + +The irq_create_fwspec_mapping() returns a proper virq value on success +and 0 upon any failure. The pru_handle_intrmap() treats this as an error +and disposes all firmware event mappings correctly, but is returning +this incorrect value as is, letting the pru_rproc_start() interpret it +as a success and boot the PRU. + +Fix this by returning an error value back upon any such failure. While +at this, revise the error trace to print some meaningful info about the +failed event. + +Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration") +Signed-off-by: Suman Anna +Reviewed-by: Mathieu Poirier +Link: https://lore.kernel.org/r/20210407155641.5501-3-s-anna@ti.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/pru_rproc.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c +index 9226b8f3fe14..dcd5ea0d1f37 100644 +--- a/drivers/remoteproc/pru_rproc.c ++++ b/drivers/remoteproc/pru_rproc.c +@@ -339,8 +339,10 @@ static int pru_handle_intrmap(struct rproc *rproc) + + pru->mapped_irq[i] = irq_create_fwspec_mapping(&fwspec); + if (!pru->mapped_irq[i]) { +- dev_err(dev, "failed to get virq\n"); +- ret = pru->mapped_irq[i]; ++ dev_err(dev, "failed to get virq for fw mapping %d: event %d chnl %d host %d\n", ++ i, fwspec.param[0], fwspec.param[1], ++ fwspec.param[2]); ++ ret = -EINVAL; + goto map_fail; + } + } +-- +2.30.2 + diff --git a/queue-5.12/remoteproc-pru-fixup-interrupt-parent-logic-for-fw-e.patch b/queue-5.12/remoteproc-pru-fixup-interrupt-parent-logic-for-fw-e.patch new file mode 100644 index 00000000000..c68859df23f --- /dev/null +++ b/queue-5.12/remoteproc-pru-fixup-interrupt-parent-logic-for-fw-e.patch @@ -0,0 +1,82 @@ +From 0c0809c0e26d2fa78a77afc6d62322ea49d0b7b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Apr 2021 10:56:39 -0500 +Subject: remoteproc: pru: Fixup interrupt-parent logic for fw events + +From: Suman Anna + +[ Upstream commit 6d1f2803cb6b414c2e45fa64d1fdad6b581e1e88 ] + +The PRU firmware interrupt mapping logic in pru_handle_intrmap() uses +of_irq_find_parent() with PRU device node to get a handle to the PRUSS +Interrupt Controller at present. This logic however requires that the +PRU nodes always define a interrupt-parent property. This property is +neither a required/defined property as per the PRU remoteproc binding, +nor is relevant from a DT node point of view without any associated +interrupts. The current logic finds a wrong interrupt controller and +fails to perform proper mapping without any interrupt-parent property +in the PRU nodes. + +Fix this logic to always find and use the sibling interrupt controller. +Also, while at this, fix the acquired interrupt controller device node +reference properly. + +Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration") +Signed-off-by: Suman Anna +Reviewed-by: Mathieu Poirier +Link: https://lore.kernel.org/r/20210407155641.5501-2-s-anna@ti.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/pru_rproc.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c +index dcb380e868df..9226b8f3fe14 100644 +--- a/drivers/remoteproc/pru_rproc.c ++++ b/drivers/remoteproc/pru_rproc.c +@@ -284,7 +284,7 @@ static int pru_handle_intrmap(struct rproc *rproc) + struct pru_rproc *pru = rproc->priv; + struct pru_irq_rsc *rsc = pru->pru_interrupt_map; + struct irq_fwspec fwspec; +- struct device_node *irq_parent; ++ struct device_node *parent, *irq_parent; + int i, ret = 0; + + /* not having pru_interrupt_map is not an error */ +@@ -312,9 +312,16 @@ static int pru_handle_intrmap(struct rproc *rproc) + + /* + * parse and fill in system event to interrupt channel and +- * channel-to-host mapping ++ * channel-to-host mapping. The interrupt controller to be used ++ * for these mappings for a given PRU remoteproc is always its ++ * corresponding sibling PRUSS INTC node. + */ +- irq_parent = of_irq_find_parent(pru->dev->of_node); ++ parent = of_get_parent(dev_of_node(pru->dev)); ++ if (!parent) ++ return -ENODEV; ++ ++ irq_parent = of_get_child_by_name(parent, "interrupt-controller"); ++ of_node_put(parent); + if (!irq_parent) { + kfree(pru->mapped_irq); + return -ENODEV; +@@ -337,11 +344,13 @@ static int pru_handle_intrmap(struct rproc *rproc) + goto map_fail; + } + } ++ of_node_put(irq_parent); + + return ret; + + map_fail: + pru_dispose_irq_mapping(pru); ++ of_node_put(irq_parent); + + return ret; + } +-- +2.30.2 + diff --git a/queue-5.12/remoteproc-qcom_q6v5_mss-validate-p_filesz-in-elf-lo.patch b/queue-5.12/remoteproc-qcom_q6v5_mss-validate-p_filesz-in-elf-lo.patch new file mode 100644 index 00000000000..610c108b2d4 --- /dev/null +++ b/queue-5.12/remoteproc-qcom_q6v5_mss-validate-p_filesz-in-elf-lo.patch @@ -0,0 +1,62 @@ +From 8cdfb843c5bf22c9b9917c9139e85a1c19809e92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Mar 2021 15:20:02 -0800 +Subject: remoteproc: qcom_q6v5_mss: Validate p_filesz in ELF loader + +From: Bjorn Andersson + +[ Upstream commit 3d2ee78906af5f08d499d6aa3aa504406fa38106 ] + +Analog to the issue in the common mdt_loader code the MSS ELF loader +does not validate that p_filesz bytes will fit in the memory region and +that the loaded segments are not truncated. Fix this in the same way +as proposed for the mdt_loader. + +Reviewed-by: Mathieu Poirier +Fixes: 135b9e8d1cd8 ("remoteproc: qcom_q6v5_mss: Validate modem blob firmware size before load") +Link: https://lore.kernel.org/r/20210312232002.3466791-1-bjorn.andersson@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_q6v5_mss.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c +index 66106ba25ba3..14e0ce5f18f5 100644 +--- a/drivers/remoteproc/qcom_q6v5_mss.c ++++ b/drivers/remoteproc/qcom_q6v5_mss.c +@@ -1210,6 +1210,14 @@ static int q6v5_mpss_load(struct q6v5 *qproc) + goto release_firmware; + } + ++ if (phdr->p_filesz > phdr->p_memsz) { ++ dev_err(qproc->dev, ++ "refusing to load segment %d with p_filesz > p_memsz\n", ++ i); ++ ret = -EINVAL; ++ goto release_firmware; ++ } ++ + ptr = memremap(qproc->mpss_phys + offset, phdr->p_memsz, MEMREMAP_WC); + if (!ptr) { + dev_err(qproc->dev, +@@ -1241,6 +1249,16 @@ static int q6v5_mpss_load(struct q6v5 *qproc) + goto release_firmware; + } + ++ if (seg_fw->size != phdr->p_filesz) { ++ dev_err(qproc->dev, ++ "failed to load segment %d from truncated file %s\n", ++ i, fw_name); ++ ret = -EINVAL; ++ release_firmware(seg_fw); ++ memunmap(ptr); ++ goto release_firmware; ++ } ++ + release_firmware(seg_fw); + } + +-- +2.30.2 + diff --git a/queue-5.12/revert-iommu-amd-fix-performance-counter-initializat.patch b/queue-5.12/revert-iommu-amd-fix-performance-counter-initializat.patch new file mode 100644 index 00000000000..0e1d559d27c --- /dev/null +++ b/queue-5.12/revert-iommu-amd-fix-performance-counter-initializat.patch @@ -0,0 +1,125 @@ +From 0ad084e217a7ddd38a474c4cf15f94f43c1471b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Apr 2021 03:58:47 -0500 +Subject: Revert "iommu/amd: Fix performance counter initialization" + +From: Paul Menzel + +[ Upstream commit 715601e4e36903a653cd4294dfd3ed0019101991 ] + +This reverts commit 6778ff5b21bd8e78c8bd547fd66437cf2657fd9b. + +The original commit tries to address an issue, where PMC power-gating +causing the IOMMU PMC pre-init test to fail on certain desktop/mobile +platforms where the power-gating is normally enabled. + +There have been several reports that the workaround still does not +guarantee to work, and can add up to 100 ms (on the worst case) +to the boot process on certain platforms such as the MSI B350M MORTAR +with AMD Ryzen 3 2200G. + +Therefore, revert this commit as a prelude to removing the pre-init +test. + +Link: https://lore.kernel.org/linux-iommu/alpine.LNX.3.20.13.2006030935570.3181@monopod.intra.ispras.ru/ +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=201753 +Cc: Tj (Elloe Linux) +Cc: Shuah Khan +Cc: Alexander Monakov +Cc: David Coe +Signed-off-by: Paul Menzel +Signed-off-by: Suravee Suthikulpanit +Link: https://lore.kernel.org/r/20210409085848.3908-2-suravee.suthikulpanit@amd.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/init.c | 45 ++++++++++------------------------------ + 1 file changed, 11 insertions(+), 34 deletions(-) + +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index f7e31018cd0b..ad53f516e46e 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -12,7 +12,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -257,8 +256,6 @@ static enum iommu_init_state init_state = IOMMU_START_STATE; + static int amd_iommu_enable_interrupts(void); + static int __init iommu_go_to_state(enum iommu_init_state state); + static void init_device_table_dma(void); +-static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, +- u8 fxn, u64 *value, bool is_write); + + static bool amd_iommu_pre_enabled = true; + +@@ -1717,11 +1714,13 @@ static int __init init_iommu_all(struct acpi_table_header *table) + return 0; + } + +-static void __init init_iommu_perf_ctr(struct amd_iommu *iommu) ++static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, ++ u8 fxn, u64 *value, bool is_write); ++ ++static void init_iommu_perf_ctr(struct amd_iommu *iommu) + { +- int retry; + struct pci_dev *pdev = iommu->dev; +- u64 val = 0xabcd, val2 = 0, save_reg, save_src; ++ u64 val = 0xabcd, val2 = 0, save_reg = 0; + + if (!iommu_feature(iommu, FEATURE_PC)) + return; +@@ -1729,39 +1728,17 @@ static void __init init_iommu_perf_ctr(struct amd_iommu *iommu) + amd_iommu_pc_present = true; + + /* save the value to restore, if writable */ +- if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, false) || +- iommu_pc_get_set_reg(iommu, 0, 0, 8, &save_src, false)) +- goto pc_false; +- +- /* +- * Disable power gating by programing the performance counter +- * source to 20 (i.e. counts the reads and writes from/to IOMMU +- * Reserved Register [MMIO Offset 1FF8h] that are ignored.), +- * which never get incremented during this init phase. +- * (Note: The event is also deprecated.) +- */ +- val = 20; +- if (iommu_pc_get_set_reg(iommu, 0, 0, 8, &val, true)) ++ if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, false)) + goto pc_false; + + /* Check if the performance counters can be written to */ +- val = 0xabcd; +- for (retry = 5; retry; retry--) { +- if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true) || +- iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false) || +- val2) +- break; +- +- /* Wait about 20 msec for power gating to disable and retry. */ +- msleep(20); +- } +- +- /* restore */ +- if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, true) || +- iommu_pc_get_set_reg(iommu, 0, 0, 8, &save_src, true)) ++ if ((iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true)) || ++ (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false)) || ++ (val != val2)) + goto pc_false; + +- if (val != val2) ++ /* restore */ ++ if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, true)) + goto pc_false; + + pci_info(pdev, "IOMMU performance counters supported\n"); +-- +2.30.2 + diff --git a/queue-5.12/risc-v-fix-error-code-returned-by-riscv_hartid_to_cp.patch b/queue-5.12/risc-v-fix-error-code-returned-by-riscv_hartid_to_cp.patch new file mode 100644 index 00000000000..739b30f639f --- /dev/null +++ b/queue-5.12/risc-v-fix-error-code-returned-by-riscv_hartid_to_cp.patch @@ -0,0 +1,39 @@ +From 1f5965dd85d41790c6fb4d2ceda0c5ddef2635a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Apr 2021 14:25:22 +0530 +Subject: RISC-V: Fix error code returned by riscv_hartid_to_cpuid() + +From: Anup Patel + +[ Upstream commit 533b4f3a789d49574e7ae0f6ececed153f651f97 ] + +We should return a negative error code upon failure in +riscv_hartid_to_cpuid() instead of NR_CPUS. This is also +aligned with all uses of riscv_hartid_to_cpuid() which +expect negative error code upon failure. + +Fixes: 6825c7a80f18 ("RISC-V: Add logical CPU indexing for RISC-V") +Fixes: f99fb607fb2b ("RISC-V: Use Linux logical CPU number instead of hartid") +Signed-off-by: Anup Patel +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/smp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c +index ea028d9e0d24..d44567490d91 100644 +--- a/arch/riscv/kernel/smp.c ++++ b/arch/riscv/kernel/smp.c +@@ -54,7 +54,7 @@ int riscv_hartid_to_cpuid(int hartid) + return i; + + pr_err("Couldn't find cpu id for hartid [%d]\n", hartid); +- return i; ++ return -ENOENT; + } + + void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out) +-- +2.30.2 + diff --git a/queue-5.12/riscv-select-have_dynamic_ftrace-when-fpatchable-fun.patch b/queue-5.12/riscv-select-have_dynamic_ftrace-when-fpatchable-fun.patch new file mode 100644 index 00000000000..93b9157cadc --- /dev/null +++ b/queue-5.12/riscv-select-have_dynamic_ftrace-when-fpatchable-fun.patch @@ -0,0 +1,45 @@ +From 07a09261d2bc509cfe5207887d9fe54cd1d80189 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Mar 2021 15:38:07 -0700 +Subject: riscv: Select HAVE_DYNAMIC_FTRACE when -fpatchable-function-entry is + available + +From: Nathan Chancellor + +[ Upstream commit adebc8817b5c975d598ac379bbdf67a7a5186ade ] + +clang prior to 13.0.0 does not support -fpatchable-function-entry for +RISC-V. + +clang: error: unsupported option '-fpatchable-function-entry=8' for target 'riscv64-unknown-linux-gnu' + +To avoid this error, only select HAVE_DYNAMIC_FTRACE when this option is +not available. + +Fixes: afc76b8b8011 ("riscv: Using PATCHABLE_FUNCTION_ENTRY instead of MCOUNT") +Link: https://github.com/ClangBuiltLinux/linux/issues/1268 +Reported-by: kernel test robot +Signed-off-by: Nathan Chancellor +Reviewed-by: Fangrui Song +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + arch/riscv/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig +index 4515a10c5d22..d9522fc35ca5 100644 +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -227,7 +227,7 @@ config ARCH_RV64I + bool "RV64I" + select 64BIT + select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && GCC_VERSION >= 50000 +- select HAVE_DYNAMIC_FTRACE if MMU ++ select HAVE_DYNAMIC_FTRACE if MMU && $(cc-option,-fpatchable-function-entry=8) + select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE + select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_FUNCTION_GRAPH_TRACER +-- +2.30.2 + diff --git a/queue-5.12/rpmsg-qcom_glink_native-fix-error-return-code-of-qco.patch b/queue-5.12/rpmsg-qcom_glink_native-fix-error-return-code-of-qco.patch new file mode 100644 index 00000000000..7c2122ada8d --- /dev/null +++ b/queue-5.12/rpmsg-qcom_glink_native-fix-error-return-code-of-qco.patch @@ -0,0 +1,39 @@ +From 6a66a9859ec064453fabdf722c72696c5a6d01f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Mar 2021 05:36:24 -0800 +Subject: rpmsg: qcom_glink_native: fix error return code of + qcom_glink_rx_data() + +From: Jia-Ju Bai + +[ Upstream commit 26594c6bbb60c6bc87e3762a86ceece57d164c66 ] + +When idr_find() returns NULL to intent, no error return code of +qcom_glink_rx_data() is assigned. +To fix this bug, ret is assigned with -ENOENT in this case. + +Fixes: 64f95f87920d ("rpmsg: glink: Use the local intents when receiving data") +Reported-by: TOTE Robot +Signed-off-by: Jia-Ju Bai +Link: https://lore.kernel.org/r/20210306133624.17237-1-baijiaju1990@gmail.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/rpmsg/qcom_glink_native.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c +index 27a05167c18c..4840886532ff 100644 +--- a/drivers/rpmsg/qcom_glink_native.c ++++ b/drivers/rpmsg/qcom_glink_native.c +@@ -857,6 +857,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) + dev_err(glink->dev, + "no intent found for channel %s intent %d", + channel->name, liid); ++ ret = -ENOENT; + goto advance_rx; + } + } +-- +2.30.2 + diff --git a/queue-5.12/rtc-ds1307-fix-wday-settings-for-rx8130.patch b/queue-5.12/rtc-ds1307-fix-wday-settings-for-rx8130.patch new file mode 100644 index 00000000000..ae00d739ae8 --- /dev/null +++ b/queue-5.12/rtc-ds1307-fix-wday-settings-for-rx8130.patch @@ -0,0 +1,53 @@ +From c16540bd7e491e2395eec31adfea3efc57c5e6d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Apr 2021 11:39:17 +0900 +Subject: rtc: ds1307: Fix wday settings for rx8130 + +From: Nobuhiro Iwamatsu + +[ Upstream commit 204756f016726a380bafe619438ed979088bd04a ] + +rx8130 wday specifies the bit position, not BCD. + +Fixes: ee0981be7704 ("rtc: ds1307: Add support for Epson RX8130CE") +Signed-off-by: Nobuhiro Iwamatsu +Signed-off-by: Alexandre Belloni +Link: https://lore.kernel.org/r/20210420023917.1949066-1-nobuhiro1.iwamatsu@toshiba.co.jp +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-ds1307.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c +index cd8e438bc9c4..8752620d8e34 100644 +--- a/drivers/rtc/rtc-ds1307.c ++++ b/drivers/rtc/rtc-ds1307.c +@@ -296,7 +296,11 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) + t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f); + tmp = regs[DS1307_REG_HOUR] & 0x3f; + t->tm_hour = bcd2bin(tmp); +- t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1; ++ /* rx8130 is bit position, not BCD */ ++ if (ds1307->type == rx_8130) ++ t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f); ++ else ++ t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1; + t->tm_mday = bcd2bin(regs[DS1307_REG_MDAY] & 0x3f); + tmp = regs[DS1307_REG_MONTH] & 0x1f; + t->tm_mon = bcd2bin(tmp) - 1; +@@ -343,7 +347,11 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) + regs[DS1307_REG_SECS] = bin2bcd(t->tm_sec); + regs[DS1307_REG_MIN] = bin2bcd(t->tm_min); + regs[DS1307_REG_HOUR] = bin2bcd(t->tm_hour); +- regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1); ++ /* rx8130 is bit position, not BCD */ ++ if (ds1307->type == rx_8130) ++ regs[DS1307_REG_WDAY] = 1 << t->tm_wday; ++ else ++ regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1); + regs[DS1307_REG_MDAY] = bin2bcd(t->tm_mday); + regs[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1); + +-- +2.30.2 + diff --git a/queue-5.12/rtc-fsl-ftm-alarm-add-module_table.patch b/queue-5.12/rtc-fsl-ftm-alarm-add-module_table.patch new file mode 100644 index 00000000000..a9daa5bff33 --- /dev/null +++ b/queue-5.12/rtc-fsl-ftm-alarm-add-module_table.patch @@ -0,0 +1,36 @@ +From b217c133fa812423e3a1407bd50c3a0b2c939da4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Apr 2021 10:40:06 +0200 +Subject: rtc: fsl-ftm-alarm: add MODULE_TABLE() + +From: Michael Walle + +[ Upstream commit 7fcb86185978661c9188397d474f90364745b8d9 ] + +The module doesn't load automatically. Fix it by adding the missing +MODULE_TABLE(). + +Fixes: 7b0b551dbc1e ("rtc: fsl-ftm-alarm: add FTM alarm driver") +Signed-off-by: Michael Walle +Signed-off-by: Alexandre Belloni +Link: https://lore.kernel.org/r/20210414084006.17933-1-michael@walle.cc +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-fsl-ftm-alarm.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/rtc/rtc-fsl-ftm-alarm.c b/drivers/rtc/rtc-fsl-ftm-alarm.c +index 57cc09d0a806..c0df49fb978c 100644 +--- a/drivers/rtc/rtc-fsl-ftm-alarm.c ++++ b/drivers/rtc/rtc-fsl-ftm-alarm.c +@@ -310,6 +310,7 @@ static const struct of_device_id ftm_rtc_match[] = { + { .compatible = "fsl,lx2160a-ftm-alarm", }, + { }, + }; ++MODULE_DEVICE_TABLE(of, ftm_rtc_match); + + static const struct acpi_device_id ftm_imx_acpi_ids[] = { + {"NXP0014",}, +-- +2.30.2 + diff --git a/queue-5.12/rtc-tps65910-include-linux-property.h.patch b/queue-5.12/rtc-tps65910-include-linux-property.h.patch new file mode 100644 index 00000000000..9fd6011207c --- /dev/null +++ b/queue-5.12/rtc-tps65910-include-linux-property.h.patch @@ -0,0 +1,39 @@ +From 56d8d92b9b05a2c4b8e4a9f6d85d2253ed884deb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Feb 2021 14:42:04 +0100 +Subject: rtc: tps65910: include linux/property.h + +From: Arnd Bergmann + +[ Upstream commit 936d3685e62436a378f02b8b74759b054d4aeca1 ] + +The added device_property_present() call causes a build +failure in some configurations because of the missing header: + +drivers/rtc/rtc-tps65910.c:422:7: error: implicit declaration of function 'device_property_present' [-Werror,-Wimplicit-function-declaration] + +Fixes: 454ba154a62c ("rtc: tps65910: Support wakeup-source property") +Signed-off-by: Arnd Bergmann +Reviewed-by: Dmitry Osipenko +Signed-off-by: Alexandre Belloni +Link: https://lore.kernel.org/r/20210225134215.2263694-1-arnd@kernel.org +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-tps65910.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c +index 288abb1abdb8..bc89c62ccb9b 100644 +--- a/drivers/rtc/rtc-tps65910.c ++++ b/drivers/rtc/rtc-tps65910.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +-- +2.30.2 + diff --git a/queue-5.12/rtw88-8822c-add-lc-calibration-for-rtl8822c.patch b/queue-5.12/rtw88-8822c-add-lc-calibration-for-rtl8822c.patch new file mode 100644 index 00000000000..e7fdad207ce --- /dev/null +++ b/queue-5.12/rtw88-8822c-add-lc-calibration-for-rtl8822c.patch @@ -0,0 +1,167 @@ +From 1b3508c83c5a2d85ee45ec8fec71584c3a492cbe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Mar 2021 13:42:16 +0800 +Subject: rtw88: 8822c: add LC calibration for RTL8822C + +From: Po-Hao Huang + +[ Upstream commit 7ae7784ec2a812c07d2ca91a6538ef2470154fb6 ] + +Fix power tracking issue by replacing unnecessary IQ calibration +with LC calibration. +When thermal difference exceeds limitation, let RF circuit adjsut +its characteristic to fit in current environment. + +Signed-off-by: Po-Hao Huang +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20210319054218.3319-6-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/main.h | 2 ++ + drivers/net/wireless/realtek/rtw88/phy.c | 14 ++++++++++ + drivers/net/wireless/realtek/rtw88/phy.h | 1 + + drivers/net/wireless/realtek/rtw88/reg.h | 5 ++++ + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 27 +++++++++++++++++-- + 5 files changed, 47 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 35afea91fd29..92b9cf1f9525 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -1166,6 +1166,7 @@ struct rtw_chip_info { + bool en_dis_dpd; + u16 dpd_ratemask; + u8 iqk_threshold; ++ u8 lck_threshold; + const struct rtw_pwr_track_tbl *pwr_track_tbl; + + u8 bfer_su_max_num; +@@ -1534,6 +1535,7 @@ struct rtw_dm_info { + u32 rrsr_mask_min; + u8 thermal_avg[RTW_RF_PATH_MAX]; + u8 thermal_meter_k; ++ u8 thermal_meter_lck; + s8 delta_power_index[RTW_RF_PATH_MAX]; + s8 delta_power_index_last[RTW_RF_PATH_MAX]; + u8 default_ofdm_index; +diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c +index 0b3da5bef703..21e77fcfa4d5 100644 +--- a/drivers/net/wireless/realtek/rtw88/phy.c ++++ b/drivers/net/wireless/realtek/rtw88/phy.c +@@ -2220,6 +2220,20 @@ s8 rtw_phy_pwrtrack_get_pwridx(struct rtw_dev *rtwdev, + } + EXPORT_SYMBOL(rtw_phy_pwrtrack_get_pwridx); + ++bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev) ++{ ++ struct rtw_dm_info *dm_info = &rtwdev->dm_info; ++ u8 delta_lck; ++ ++ delta_lck = abs(dm_info->thermal_avg[0] - dm_info->thermal_meter_lck); ++ if (delta_lck >= rtwdev->chip->lck_threshold) { ++ dm_info->thermal_meter_lck = dm_info->thermal_avg[0]; ++ return true; ++ } ++ return false; ++} ++EXPORT_SYMBOL(rtw_phy_pwrtrack_need_lck); ++ + bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev) + { + struct rtw_dm_info *dm_info = &rtwdev->dm_info; +diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h +index a4fcfb878550..a0742a69446d 100644 +--- a/drivers/net/wireless/realtek/rtw88/phy.h ++++ b/drivers/net/wireless/realtek/rtw88/phy.h +@@ -55,6 +55,7 @@ u8 rtw_phy_pwrtrack_get_delta(struct rtw_dev *rtwdev, u8 path); + s8 rtw_phy_pwrtrack_get_pwridx(struct rtw_dev *rtwdev, + struct rtw_swing_table *swing_table, + u8 tbl_path, u8 therm_path, u8 delta); ++bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev); + bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev); + void rtw_phy_config_swing_table(struct rtw_dev *rtwdev, + struct rtw_swing_table *swing_table); +diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h +index ea518aa78552..819af34dac34 100644 +--- a/drivers/net/wireless/realtek/rtw88/reg.h ++++ b/drivers/net/wireless/realtek/rtw88/reg.h +@@ -652,8 +652,13 @@ + #define RF_TXATANK 0x64 + #define RF_TRXIQ 0x66 + #define RF_RXIQGEN 0x8d ++#define RF_SYN_PFD 0xb0 + #define RF_XTALX2 0xb8 ++#define RF_SYN_CTRL 0xbb + #define RF_MALSEL 0xbe ++#define RF_SYN_AAC 0xc9 ++#define RF_AAC_CTRL 0xca ++#define RF_FAST_LCK 0xcc + #define RF_RCKD 0xde + #define RF_TXADBG 0xde + #define RF_LUTDBG 0xdf +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index dd560c28abb2..448922cb2e63 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -1126,6 +1126,7 @@ static void rtw8822c_pwrtrack_init(struct rtw_dev *rtwdev) + + dm_info->pwr_trk_triggered = false; + dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k; ++ dm_info->thermal_meter_lck = rtwdev->efuse.thermal_meter_k; + } + + static void rtw8822c_phy_set_param(struct rtw_dev *rtwdev) +@@ -2108,6 +2109,26 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev) + rtw_write32_set(rtwdev, REG_RX_BREAK, BIT_COM_RX_GCK_EN); + } + ++static void rtw8822c_do_lck(struct rtw_dev *rtwdev) ++{ ++ u32 val; ++ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_CTRL, RFREG_MASK, 0x80010); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_PFD, RFREG_MASK, 0x1F0FA); ++ fsleep(1); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_AAC_CTRL, RFREG_MASK, 0x80000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_AAC, RFREG_MASK, 0x80001); ++ read_poll_timeout(rtw_read_rf, val, val != 0x1, 1000, 100000, ++ true, rtwdev, RF_PATH_A, RF_AAC_CTRL, 0x1000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_PFD, RFREG_MASK, 0x1F0F8); ++ rtw_write_rf(rtwdev, RF_PATH_B, RF_SYN_CTRL, RFREG_MASK, 0x80010); ++ ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_FAST_LCK, RFREG_MASK, 0x0f000); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_FAST_LCK, RFREG_MASK, 0x4f000); ++ fsleep(1); ++ rtw_write_rf(rtwdev, RF_PATH_A, RF_FAST_LCK, RFREG_MASK, 0x0f000); ++} ++ + static void rtw8822c_do_iqk(struct rtw_dev *rtwdev) + { + struct rtw_iqk_para para = {0}; +@@ -3538,11 +3559,12 @@ static void __rtw8822c_pwr_track(struct rtw_dev *rtwdev) + + rtw_phy_config_swing_table(rtwdev, &swing_table); + ++ if (rtw_phy_pwrtrack_need_lck(rtwdev)) ++ rtw8822c_do_lck(rtwdev); ++ + for (i = 0; i < rtwdev->hal.rf_path_num; i++) + rtw8822c_pwr_track_path(rtwdev, &swing_table, i); + +- if (rtw_phy_pwrtrack_need_iqk(rtwdev)) +- rtw8822c_do_iqk(rtwdev); + } + + static void rtw8822c_pwr_track(struct rtw_dev *rtwdev) +@@ -4351,6 +4373,7 @@ struct rtw_chip_info rtw8822c_hw_spec = { + .dpd_ratemask = DIS_DPD_RATEALL, + .pwr_track_tbl = &rtw8822c_rtw_pwr_track_tbl, + .iqk_threshold = 8, ++ .lck_threshold = 8, + .bfer_su_max_num = 2, + .bfer_mu_max_num = 1, + .rx_ldpc = true, +-- +2.30.2 + diff --git a/queue-5.12/samples-bpf-fix-broken-tracex1-due-to-kprobe-argumen.patch b/queue-5.12/samples-bpf-fix-broken-tracex1-due-to-kprobe-argumen.patch new file mode 100644 index 00000000000..60fa6250ed3 --- /dev/null +++ b/queue-5.12/samples-bpf-fix-broken-tracex1-due-to-kprobe-argumen.patch @@ -0,0 +1,49 @@ +From 662620728db4ce66c2d47509e93f0a1ba7ac64ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Apr 2021 23:48:03 +0800 +Subject: samples/bpf: Fix broken tracex1 due to kprobe argument change + +From: Yaqi Chen + +[ Upstream commit 137733d08f4ab14a354dacaa9a8fc35217747605 ] + +>From commit c0bbbdc32feb ("__netif_receive_skb_core: pass skb by +reference"), the first argument passed into __netif_receive_skb_core +has changed to reference of a skb pointer. + +This commit fixes by using bpf_probe_read_kernel. + +Signed-off-by: Yaqi Chen +Signed-off-by: Alexei Starovoitov +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/20210416154803.37157-1-chendotjs@gmail.com +Signed-off-by: Sasha Levin +--- + samples/bpf/tracex1_kern.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/samples/bpf/tracex1_kern.c b/samples/bpf/tracex1_kern.c +index 3f4599c9a202..ef30d2b353b0 100644 +--- a/samples/bpf/tracex1_kern.c ++++ b/samples/bpf/tracex1_kern.c +@@ -26,7 +26,7 @@ + SEC("kprobe/__netif_receive_skb_core") + int bpf_prog1(struct pt_regs *ctx) + { +- /* attaches to kprobe netif_receive_skb, ++ /* attaches to kprobe __netif_receive_skb_core, + * looks for packets on loobpack device and prints them + */ + char devname[IFNAMSIZ]; +@@ -35,7 +35,7 @@ int bpf_prog1(struct pt_regs *ctx) + int len; + + /* non-portable! works for the given kernel only */ +- skb = (struct sk_buff *) PT_REGS_PARM1(ctx); ++ bpf_probe_read_kernel(&skb, sizeof(skb), (void *)PT_REGS_PARM1(ctx)); + dev = _(skb->dev); + len = _(skb->len); + +-- +2.30.2 + diff --git a/queue-5.12/sched-fair-fix-unfairness-caused-by-missing-load-dec.patch b/queue-5.12/sched-fair-fix-unfairness-caused-by-missing-load-dec.patch new file mode 100644 index 00000000000..3f5b9ff5f8f --- /dev/null +++ b/queue-5.12/sched-fair-fix-unfairness-caused-by-missing-load-dec.patch @@ -0,0 +1,123 @@ +From 402e8a7e2b4f85144afa5ce775c81cdfb28152a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 May 2021 16:19:50 +0200 +Subject: sched/fair: Fix unfairness caused by missing load decay + +From: Odin Ugedal + +[ Upstream commit 0258bdfaff5bd13c4d2383150b7097aecd6b6d82 ] + +This fixes an issue where old load on a cfs_rq is not properly decayed, +resulting in strange behavior where fairness can decrease drastically. +Real workloads with equally weighted control groups have ended up +getting a respective 99% and 1%(!!) of cpu time. + +When an idle task is attached to a cfs_rq by attaching a pid to a cgroup, +the old load of the task is attached to the new cfs_rq and sched_entity by +attach_entity_cfs_rq. If the task is then moved to another cpu (and +therefore cfs_rq) before being enqueued/woken up, the load will be moved +to cfs_rq->removed from the sched_entity. Such a move will happen when +enforcing a cpuset on the task (eg. via a cgroup) that force it to move. + +The load will however not be removed from the task_group itself, making +it look like there is a constant load on that cfs_rq. This causes the +vruntime of tasks on other sibling cfs_rq's to increase faster than they +are supposed to; causing severe fairness issues. If no other task is +started on the given cfs_rq, and due to the cpuset it would not happen, +this load would never be properly unloaded. With this patch the load +will be properly removed inside update_blocked_averages. This also +applies to tasks moved to the fair scheduling class and moved to another +cpu, and this path will also fix that. For fork, the entity is queued +right away, so this problem does not affect that. + +This applies to cases where the new process is the first in the cfs_rq, +issue introduced 3d30544f0212 ("sched/fair: Apply more PELT fixes"), and +when there has previously been load on the cgroup but the cgroup was +removed from the leaflist due to having null PELT load, indroduced +in 039ae8bcf7a5 ("sched/fair: Fix O(nr_cgroups) in the load balancing +path"). + +For a simple cgroup hierarchy (as seen below) with two equally weighted +groups, that in theory should get 50/50 of cpu time each, it often leads +to a load of 60/40 or 70/30. + +parent/ + cg-1/ + cpu.weight: 100 + cpuset.cpus: 1 + cg-2/ + cpu.weight: 100 + cpuset.cpus: 1 + +If the hierarchy is deeper (as seen below), while keeping cg-1 and cg-2 +equally weighted, they should still get a 50/50 balance of cpu time. +This however sometimes results in a balance of 10/90 or 1/99(!!) between +the task groups. + +$ ps u -C stress +USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND +root 18568 1.1 0.0 3684 100 pts/12 R+ 13:36 0:00 stress --cpu 1 +root 18580 99.3 0.0 3684 100 pts/12 R+ 13:36 0:09 stress --cpu 1 + +parent/ + cg-1/ + cpu.weight: 100 + sub-group/ + cpu.weight: 1 + cpuset.cpus: 1 + cg-2/ + cpu.weight: 100 + sub-group/ + cpu.weight: 10000 + cpuset.cpus: 1 + +This can be reproduced by attaching an idle process to a cgroup and +moving it to a given cpuset before it wakes up. The issue is evident in +many (if not most) container runtimes, and has been reproduced +with both crun and runc (and therefore docker and all its "derivatives"), +and with both cgroup v1 and v2. + +Fixes: 3d30544f0212 ("sched/fair: Apply more PELT fixes") +Fixes: 039ae8bcf7a5 ("sched/fair: Fix O(nr_cgroups) in the load balancing path") +Signed-off-by: Odin Ugedal +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Vincent Guittot +Link: https://lkml.kernel.org/r/20210501141950.23622-2-odin@uged.al +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index d078767f677f..edcabae5c658 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -10915,16 +10915,22 @@ static void propagate_entity_cfs_rq(struct sched_entity *se) + { + struct cfs_rq *cfs_rq; + ++ list_add_leaf_cfs_rq(cfs_rq_of(se)); ++ + /* Start to propagate at parent */ + se = se->parent; + + for_each_sched_entity(se) { + cfs_rq = cfs_rq_of(se); + +- if (cfs_rq_throttled(cfs_rq)) +- break; ++ if (!cfs_rq_throttled(cfs_rq)){ ++ update_load_avg(cfs_rq, se, UPDATE_TG); ++ list_add_leaf_cfs_rq(cfs_rq); ++ continue; ++ } + +- update_load_avg(cfs_rq, se, UPDATE_TG); ++ if (list_add_leaf_cfs_rq(cfs_rq)) ++ break; + } + } + #else +-- +2.30.2 + diff --git a/queue-5.12/sched-fix-out-of-bound-access-in-uclamp.patch b/queue-5.12/sched-fix-out-of-bound-access-in-uclamp.patch new file mode 100644 index 00000000000..672ab32a809 --- /dev/null +++ b/queue-5.12/sched-fix-out-of-bound-access-in-uclamp.patch @@ -0,0 +1,49 @@ +From cf01e7e64e72e6a05d4a4b79963e74b93bd26f10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Apr 2021 15:14:12 +0000 +Subject: sched: Fix out-of-bound access in uclamp + +From: Quentin Perret + +[ Upstream commit 6d2f8909a5fabb73fe2a63918117943986c39b6c ] + +Util-clamp places tasks in different buckets based on their clamp values +for performance reasons. However, the size of buckets is currently +computed using a rounding division, which can lead to an off-by-one +error in some configurations. + +For instance, with 20 buckets, the bucket size will be 1024/20=51. A +task with a clamp of 1024 will be mapped to bucket id 1024/51=20. Sadly, +correct indexes are in range [0,19], hence leading to an out of bound +memory access. + +Clamp the bucket id to fix the issue. + +Fixes: 69842cba9ace ("sched/uclamp: Add CPU's clamp buckets refcounting") +Suggested-by: Qais Yousef +Signed-off-by: Quentin Perret +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Vincent Guittot +Reviewed-by: Dietmar Eggemann +Link: https://lkml.kernel.org/r/20210430151412.160913-1-qperret@google.com +Signed-off-by: Sasha Levin +--- + kernel/sched/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 17ad829a114c..814200541f8f 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -928,7 +928,7 @@ DEFINE_STATIC_KEY_FALSE(sched_uclamp_used); + + static inline unsigned int uclamp_bucket_id(unsigned int clamp_value) + { +- return clamp_value / UCLAMP_BUCKET_DELTA; ++ return min_t(unsigned int, clamp_value / UCLAMP_BUCKET_DELTA, UCLAMP_BUCKETS - 1); + } + + static inline unsigned int uclamp_none(enum uclamp_id clamp_id) +-- +2.30.2 + diff --git a/queue-5.12/scsi-qla2xxx-prevent-prli-in-target-mode.patch b/queue-5.12/scsi-qla2xxx-prevent-prli-in-target-mode.patch new file mode 100644 index 00000000000..b72fda71746 --- /dev/null +++ b/queue-5.12/scsi-qla2xxx-prevent-prli-in-target-mode.patch @@ -0,0 +1,48 @@ +From beca1913082b435b9950e7423b904bfb75025515 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Apr 2021 18:34:14 +0300 +Subject: scsi: qla2xxx: Prevent PRLI in target mode + +From: Anastasia Kovaleva + +[ Upstream commit fcb16d9a8ecf1e9bfced0fc654ea4e2caa7517f4 ] + +In a case when the initiator in P2P mode by some circumstances does not +send PRLI, the target, in a case when the target port's WWPN is less than +initiator's, changes the discovery state in DSC_GNL. When gnl completes it +sends PRLI to the initiator. + +Usually the initiator in P2P mode always sends PRLI. We caught this issue +on Linux stable v5.4.6 https://www.spinics.net/lists/stable/msg458515.html. + +Fix this particular corner case in the behaviour of the P2P mod target +login state machine. + +Link: https://lore.kernel.org/r/20210422153414.4022-1-a.kovaleva@yadro.com +Fixes: a9ed06d4e640 ("scsi: qla2xxx: Allow PLOGI in target mode") +Reviewed-by: Roman Bolshakov +Reviewed-by: Himanshu Madhani +Signed-off-by: Anastasia Kovaleva +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_init.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index f01f07116bd3..8cb0574cfa91 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -1194,6 +1194,9 @@ static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport) + { + struct qla_work_evt *e; + ++ if (vha->host->active_mode == MODE_TARGET) ++ return QLA_FUNCTION_FAILED; ++ + e = qla2x00_alloc_work(vha, QLA_EVT_PRLI); + if (!e) + return QLA_FUNCTION_FAILED; +-- +2.30.2 + diff --git a/queue-5.12/scsi-ufs-core-cancel-rpm_dev_flush_recheck_work-duri.patch b/queue-5.12/scsi-ufs-core-cancel-rpm_dev_flush_recheck_work-duri.patch new file mode 100644 index 00000000000..fb7e63ed94f --- /dev/null +++ b/queue-5.12/scsi-ufs-core-cancel-rpm_dev_flush_recheck_work-duri.patch @@ -0,0 +1,41 @@ +From e44ae56d1ba0490e30ee4868f85e83d53de4114d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 25 Apr 2021 20:48:39 -0700 +Subject: scsi: ufs: core: Cancel rpm_dev_flush_recheck_work during system + suspend + +From: Can Guo + +[ Upstream commit 637822e63b79ee8a729f7ba2645a26cf5a524ee4 ] + +During ufs system suspend, leaving rpm_dev_flush_recheck_work running or +pending is risky because concurrency may happen between system +suspend/resume and runtime resume routine. Fix this by cancelling +rpm_dev_flush_recheck_work synchronously during system suspend. + +Link: https://lore.kernel.org/r/1619408921-30426-3-git-send-email-cang@codeaurora.org +Fixes: 51dd905bd2f6 ("scsi: ufs: Fix WriteBooster flush during runtime suspend") +Reviewed-by: Daejun Park +Signed-off-by: Can Guo +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/ufs/ufshcd.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index fed32517d7d1..4631a609b0e3 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -8978,6 +8978,8 @@ int ufshcd_system_suspend(struct ufs_hba *hba) + if (!hba->is_powered) + return 0; + ++ cancel_delayed_work_sync(&hba->rpm_dev_flush_recheck_work); ++ + if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) == + hba->curr_dev_pwr_mode) && + (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) == +-- +2.30.2 + diff --git a/queue-5.12/scsi-ufs-core-do-not-put-ufs-power-into-lpm-if-link-.patch b/queue-5.12/scsi-ufs-core-do-not-put-ufs-power-into-lpm-if-link-.patch new file mode 100644 index 00000000000..d895aeaa191 --- /dev/null +++ b/queue-5.12/scsi-ufs-core-do-not-put-ufs-power-into-lpm-if-link-.patch @@ -0,0 +1,47 @@ +From 20a66348823c8351d00782d17680413a478308cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 25 Apr 2021 20:48:38 -0700 +Subject: scsi: ufs: core: Do not put UFS power into LPM if link is broken + +From: Can Guo + +[ Upstream commit 23043dd87b153d02eaf676e752d32429be5e5126 ] + +During resume, if link is broken due to AH8 failure, make sure +ufshcd_resume() does not put UFS power back into LPM. + +Link: https://lore.kernel.org/r/1619408921-30426-2-git-send-email-cang@codeaurora.org +Fixes: 4db7a2360597 ("scsi: ufs: Fix concurrency of error handler and other error recovery paths") +Reviewed-by: Daejun Park +Signed-off-by: Can Guo +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/ufs/ufshcd.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index d3d05e997c13..fed32517d7d1 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -8599,7 +8599,7 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba) + } else if (!ufshcd_is_ufs_dev_active(hba)) { + ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); + vcc_off = true; +- if (!ufshcd_is_link_active(hba)) { ++ if (ufshcd_is_link_hibern8(hba) || ufshcd_is_link_off(hba)) { + ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq); + ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2); + } +@@ -8621,7 +8621,7 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) + !hba->dev_info.is_lu_power_on_wp) { + ret = ufshcd_setup_vreg(hba, true); + } else if (!ufshcd_is_ufs_dev_active(hba)) { +- if (!ret && !ufshcd_is_link_active(hba)) { ++ if (!ufshcd_is_link_active(hba)) { + ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); + if (ret) + goto vcc_disable; +-- +2.30.2 + diff --git a/queue-5.12/scsi-ufs-core-narrow-down-fast-path-in-system-suspen.patch b/queue-5.12/scsi-ufs-core-narrow-down-fast-path-in-system-suspen.patch new file mode 100644 index 00000000000..ee9e1effe82 --- /dev/null +++ b/queue-5.12/scsi-ufs-core-narrow-down-fast-path-in-system-suspen.patch @@ -0,0 +1,46 @@ +From dece63d0401d0edec5ad8f2f6029bc68707ca650 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 25 Apr 2021 20:48:40 -0700 +Subject: scsi: ufs: core: Narrow down fast path in system suspend path + +From: Can Guo + +[ Upstream commit ce4f62f9dd8cf43ac044045ed598a0b80ef33890 ] + +If spm_lvl is set to 0 or 1, when system suspend kicks start and HBA is +runtime active, system suspend may just bail without doing anything (the +fast path), leaving other contexts still running, e.g., clock gating and +clock scaling. When system resume kicks start, concurrency can happen +between ufshcd_resume() and these contexts, leading to various stability +issues. + +Add a check against HBA's runtime state and allowing fast path only if HBA +is runtime suspended, otherwise let system suspend go ahead call +ufshcd_suspend(). This will guarantee that these contexts are stopped by +either runtime suspend or system suspend. + +Link: https://lore.kernel.org/r/1619408921-30426-4-git-send-email-cang@codeaurora.org +Fixes: 0b257734344a ("scsi: ufs: optimize system suspend handling") +Reviewed-by: Daejun Park +Signed-off-by: Can Guo +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/ufs/ufshcd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index 4631a609b0e3..0c71a159d08f 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -8984,6 +8984,7 @@ int ufshcd_system_suspend(struct ufs_hba *hba) + hba->curr_dev_pwr_mode) && + (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) == + hba->uic_link_state) && ++ pm_runtime_suspended(hba->dev) && + !hba->dev_info.b_rpm_dev_flush_capable) + goto out; + +-- +2.30.2 + diff --git a/queue-5.12/sctp-do-asoc-update-earlier-in-sctp_sf_do_dupcook_a.patch b/queue-5.12/sctp-do-asoc-update-earlier-in-sctp_sf_do_dupcook_a.patch new file mode 100644 index 00000000000..c9544eaec7c --- /dev/null +++ b/queue-5.12/sctp-do-asoc-update-earlier-in-sctp_sf_do_dupcook_a.patch @@ -0,0 +1,96 @@ +From ef05e9a72ec0612b027541e16f6b5ccca20b350c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 May 2021 04:02:58 +0800 +Subject: sctp: do asoc update earlier in sctp_sf_do_dupcook_a + +From: Xin Long + +[ Upstream commit 35b4f24415c854cd718ccdf38dbea6297f010aae ] + +There's a panic that occurs in a few of envs, the call trace is as below: + + [] general protection fault, ... 0x29acd70f1000a: 0000 [#1] SMP PTI + [] RIP: 0010:sctp_ulpevent_notify_peer_addr_change+0x4b/0x1fa [sctp] + [] sctp_assoc_control_transport+0x1b9/0x210 [sctp] + [] sctp_do_8_2_transport_strike.isra.16+0x15c/0x220 [sctp] + [] sctp_cmd_interpreter.isra.21+0x1231/0x1a10 [sctp] + [] sctp_do_sm+0xc3/0x2a0 [sctp] + [] sctp_generate_timeout_event+0x81/0xf0 [sctp] + +This is caused by a transport use-after-free issue. When processing a +duplicate COOKIE-ECHO chunk in sctp_sf_do_dupcook_a(), both COOKIE-ACK +and SHUTDOWN chunks are allocated with the transort from the new asoc. +However, later in the sideeffect machine, the old asoc is used to send +them out and old asoc's shutdown_last_sent_to is set to the transport +that SHUTDOWN chunk attached to in sctp_cmd_setup_t2(), which actually +belongs to the new asoc. After the new_asoc is freed and the old asoc +T2 timeout, the old asoc's shutdown_last_sent_to that is already freed +would be accessed in sctp_sf_t2_timer_expire(). + +Thanks Alexander and Jere for helping dig into this issue. + +To fix it, this patch is to do the asoc update first, then allocate +the COOKIE-ACK and SHUTDOWN chunks with the 'updated' old asoc. This +would make more sense, as a chunk from an asoc shouldn't be sent out +with another asoc. We had fixed quite a few issues caused by this. + +Fixes: 145cb2f7177d ("sctp: Fix bundling of SHUTDOWN with COOKIE-ACK") +Reported-by: Alexander Sverdlin +Reported-by: syzbot+bbe538efd1046586f587@syzkaller.appspotmail.com +Reported-by: Michal Tesar +Signed-off-by: Xin Long +Acked-by: Marcelo Ricardo Leitner +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/sctp/sm_statefuns.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index af2b7041fa4e..c7138f85f18f 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -1852,20 +1852,35 @@ static enum sctp_disposition sctp_sf_do_dupcook_a( + SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); + sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_ASCONF_QUEUE, SCTP_NULL()); + +- repl = sctp_make_cookie_ack(new_asoc, chunk); ++ /* Update the content of current association. */ ++ if (sctp_assoc_update((struct sctp_association *)asoc, new_asoc)) { ++ struct sctp_chunk *abort; ++ ++ abort = sctp_make_abort(asoc, NULL, sizeof(struct sctp_errhdr)); ++ if (abort) { ++ sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0); ++ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); ++ } ++ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED)); ++ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, ++ SCTP_PERR(SCTP_ERROR_RSRC_LOW)); ++ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); ++ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); ++ goto nomem; ++ } ++ ++ repl = sctp_make_cookie_ack(asoc, chunk); + if (!repl) + goto nomem; + + /* Report association restart to upper layer. */ + ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, +- new_asoc->c.sinit_num_ostreams, +- new_asoc->c.sinit_max_instreams, ++ asoc->c.sinit_num_ostreams, ++ asoc->c.sinit_max_instreams, + NULL, GFP_ATOMIC); + if (!ev) + goto nomem_ev; + +- /* Update the content of current association. */ +- sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); + if ((sctp_state(asoc, SHUTDOWN_PENDING) || + sctp_state(asoc, SHUTDOWN_SENT)) && +-- +2.30.2 + diff --git a/queue-5.12/sctp-fix-a-sctp_mib_currestab-leak-in-sctp_sf_do_dup.patch b/queue-5.12/sctp-fix-a-sctp_mib_currestab-leak-in-sctp_sf_do_dup.patch new file mode 100644 index 00000000000..88fc8fe1e63 --- /dev/null +++ b/queue-5.12/sctp-fix-a-sctp_mib_currestab-leak-in-sctp_sf_do_dup.patch @@ -0,0 +1,52 @@ +From 1e27073b13bf83dcadc8b31444e3504aafb317ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 May 2021 04:41:20 +0800 +Subject: sctp: fix a SCTP_MIB_CURRESTAB leak in sctp_sf_do_dupcook_b + +From: Xin Long + +[ Upstream commit f282df0391267fb2b263da1cc3233aa6fb81defc ] + +Normally SCTP_MIB_CURRESTAB is always incremented once asoc enter into +ESTABLISHED from the state < ESTABLISHED and decremented when the asoc +is being deleted. + +However, in sctp_sf_do_dupcook_b(), the asoc's state can be changed to +ESTABLISHED from the state >= ESTABLISHED where it shouldn't increment +SCTP_MIB_CURRESTAB. Otherwise, one asoc may increment MIB_CURRESTAB +multiple times but only decrement once at the end. + +I was able to reproduce it by using scapy to do the 4-way shakehands, +after that I replayed the COOKIE-ECHO chunk with 'peer_vtag' field +changed to different values, and SCTP_MIB_CURRESTAB was incremented +multiple times and never went back to 0 even when the asoc was freed. + +This patch is to fix it by only incrementing SCTP_MIB_CURRESTAB when +the state < ESTABLISHED in sctp_sf_do_dupcook_b(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Marcelo Ricardo Leitner +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/sctp/sm_statefuns.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index c7138f85f18f..73bb4c6e9201 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -1944,7 +1944,8 @@ static enum sctp_disposition sctp_sf_do_dupcook_b( + sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, + SCTP_STATE(SCTP_STATE_ESTABLISHED)); +- SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); ++ if (asoc->state < SCTP_STATE_ESTABLISHED) ++ SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); + sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); + + repl = sctp_make_cookie_ack(new_asoc, chunk); +-- +2.30.2 + diff --git a/queue-5.12/sctp-fix-out-of-bounds-warning-in-sctp_process_ascon.patch b/queue-5.12/sctp-fix-out-of-bounds-warning-in-sctp_process_ascon.patch new file mode 100644 index 00000000000..07b4780a4a9 --- /dev/null +++ b/queue-5.12/sctp-fix-out-of-bounds-warning-in-sctp_process_ascon.patch @@ -0,0 +1,44 @@ +From e9f347b1a4e013973a1d930f1fa42cf91501f9d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Apr 2021 14:12:36 -0500 +Subject: sctp: Fix out-of-bounds warning in sctp_process_asconf_param() + +From: Gustavo A. R. Silva + +[ Upstream commit e5272ad4aab347dde5610c0aedb786219e3ff793 ] + +Fix the following out-of-bounds warning: + +net/sctp/sm_make_chunk.c:3150:4: warning: 'memcpy' offset [17, 28] from the object at 'addr' is out of the bounds of referenced subobject 'v4' with type 'struct sockaddr_in' at offset 0 [-Warray-bounds] + +This helps with the ongoing efforts to globally enable -Warray-bounds +and get us closer to being able to tighten the FORTIFY_SOURCE routines +on memcpy(). + +Link: https://github.com/KSPP/linux/issues/109 +Reported-by: kernel test robot +Signed-off-by: Gustavo A. R. Silva +Reviewed-by: Kees Cook +Acked-by: Marcelo Ricardo Leitner +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/sctp/sm_make_chunk.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c +index f77484df097b..da4ce0947c3a 100644 +--- a/net/sctp/sm_make_chunk.c ++++ b/net/sctp/sm_make_chunk.c +@@ -3147,7 +3147,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, + * primary. + */ + if (af->is_any(&addr)) +- memcpy(&addr.v4, sctp_source(asconf), sizeof(addr)); ++ memcpy(&addr, sctp_source(asconf), sizeof(addr)); + + if (security_sctp_bind_connect(asoc->ep->base.sk, + SCTP_PARAM_SET_PRIMARY, +-- +2.30.2 + diff --git a/queue-5.12/selftests-mlxsw-fix-mausezahn-invocation-in-erspan-s.patch b/queue-5.12/selftests-mlxsw-fix-mausezahn-invocation-in-erspan-s.patch new file mode 100644 index 00000000000..c11d4ff3cff --- /dev/null +++ b/queue-5.12/selftests-mlxsw-fix-mausezahn-invocation-in-erspan-s.patch @@ -0,0 +1,91 @@ +From 9e33d31adff5230de90949824ef3599c4919bcbc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Apr 2021 14:19:48 +0200 +Subject: selftests: mlxsw: Fix mausezahn invocation in ERSPAN scale test + +From: Petr Machata + +[ Upstream commit 1233898ab758cbcf5f6fea10b8dd16a0b2c24fab ] + +The mirror_gre_scale test creates as many ERSPAN sessions as the underlying +chip supports, and tests that they all work. In order to determine that it +issues a stream of ICMP packets and checks if they are mirrored as +expected. + +However, the mausezahn invocation missed the -6 flag to identify the use of +IPv6 protocol, and was sending ICMP messages over IPv6, as opposed to +ICMP6. It also didn't pass an explicit source IP address, which apparently +worked at some point in the past, but does not anymore. + +To fix these issues, extend the function mirror_test() in mirror_lib by +detecting the IPv6 protocol addresses, and using a different ICMP scheme. +Fix __mirror_gre_test() in the selftest itself to pass a source IP address. + +Signed-off-by: Petr Machata +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + .../drivers/net/mlxsw/mirror_gre_scale.sh | 3 ++- + .../selftests/net/forwarding/mirror_lib.sh | 19 +++++++++++++++++-- + 2 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh +index 6f3a70df63bc..e00435753008 100644 +--- a/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh ++++ b/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh +@@ -120,12 +120,13 @@ __mirror_gre_test() + sleep 5 + + for ((i = 0; i < count; ++i)); do ++ local sip=$(mirror_gre_ipv6_addr 1 $i)::1 + local dip=$(mirror_gre_ipv6_addr 1 $i)::2 + local htun=h3-gt6-$i + local message + + icmp6_capture_install $htun +- mirror_test v$h1 "" $dip $htun 100 10 ++ mirror_test v$h1 $sip $dip $htun 100 10 + icmp6_capture_uninstall $htun + done + } +diff --git a/tools/testing/selftests/net/forwarding/mirror_lib.sh b/tools/testing/selftests/net/forwarding/mirror_lib.sh +index 13db1cb50e57..6406cd76a19d 100644 +--- a/tools/testing/selftests/net/forwarding/mirror_lib.sh ++++ b/tools/testing/selftests/net/forwarding/mirror_lib.sh +@@ -20,6 +20,13 @@ mirror_uninstall() + tc filter del dev $swp1 $direction pref 1000 + } + ++is_ipv6() ++{ ++ local addr=$1; shift ++ ++ [[ -z ${addr//[0-9a-fA-F:]/} ]] ++} ++ + mirror_test() + { + local vrf_name=$1; shift +@@ -29,9 +36,17 @@ mirror_test() + local pref=$1; shift + local expect=$1; shift + ++ if is_ipv6 $dip; then ++ local proto=-6 ++ local type="icmp6 type=128" # Echo request. ++ else ++ local proto= ++ local type="icmp echoreq" ++ fi ++ + local t0=$(tc_rule_stats_get $dev $pref) +- $MZ $vrf_name ${sip:+-A $sip} -B $dip -a own -b bc -q \ +- -c 10 -d 100msec -t icmp type=8 ++ $MZ $proto $vrf_name ${sip:+-A $sip} -B $dip -a own -b bc -q \ ++ -c 10 -d 100msec -t $type + sleep 0.5 + local t1=$(tc_rule_stats_get $dev $pref) + local delta=$((t1 - t0)) +-- +2.30.2 + diff --git a/queue-5.12/selftests-mlxsw-increase-the-tolerance-of-backlog-bu.patch b/queue-5.12/selftests-mlxsw-increase-the-tolerance-of-backlog-bu.patch new file mode 100644 index 00000000000..e065fc558bf --- /dev/null +++ b/queue-5.12/selftests-mlxsw-increase-the-tolerance-of-backlog-bu.patch @@ -0,0 +1,46 @@ +From 090a78d349f23bfe74ff309e9a1041e19ce27c75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Apr 2021 14:19:47 +0200 +Subject: selftests: mlxsw: Increase the tolerance of backlog buildup + +From: Petr Machata + +[ Upstream commit dda7f4fa55839baeb72ae040aeaf9ccf89d3e416 ] + +The intention behind this test is to make sure that qdisc limit is +correctly projected to the HW. However, first, due to rounding in the +qdisc, and then in the driver, the number cannot actually be accurate. And +second, the approach to testing this is to oversubscribe the port with +traffic generated on the same switch. The actual backlog size therefore +fluctuates. + +In practice, this test proved to be noisier than the rest, and spuriously +fails every now and then. Increase the tolerance to 10 % to avoid these +issues. + +Signed-off-by: Petr Machata +Acked-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh +index b0cb1aaffdda..33ddd01689be 100644 +--- a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh ++++ b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh +@@ -507,8 +507,8 @@ do_red_test() + check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0." + local diff=$((limit - backlog)) + pct=$((100 * diff / limit)) +- ((0 <= pct && pct <= 5)) +- check_err $? "backlog $backlog / $limit expected <= 5% distance" ++ ((0 <= pct && pct <= 10)) ++ check_err $? "backlog $backlog / $limit expected <= 10% distance" + log_test "TC $((vlan - 10)): RED backlog > limit" + + stop_traffic +-- +2.30.2 + diff --git a/queue-5.12/selftests-mptcp-launch-mptcp_connect-with-timeout.patch b/queue-5.12/selftests-mptcp-launch-mptcp_connect-with-timeout.patch new file mode 100644 index 00000000000..38ee8d66d72 --- /dev/null +++ b/queue-5.12/selftests-mptcp-launch-mptcp_connect-with-timeout.patch @@ -0,0 +1,281 @@ +From 0ff75d892f3ce48614deb3fe7f6012b31f68b952 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Apr 2021 16:19:45 -0700 +Subject: selftests: mptcp: launch mptcp_connect with timeout + +From: Matthieu Baerts + +[ Upstream commit 5888a61cb4e00695075bbacfd86f3fa73af00413 ] + +'mptcp_connect' already has a timeout for poll() but in some cases, it +is not enough. + +With "timeout" tool, we will force the command to fail if it doesn't +finish on time. Thanks to that, the script will continue and display +details about the current state before marking the test as failed. +Displaying this state is very important to be able to understand the +issue. Best to have our CI reporting the issue than just "the test +hanged". + +Note that in mptcp_connect.sh, we were using a long timeout to validate +the fact we cannot create a socket if a sysctl is set. We don't need +this timeout. + +In diag.sh, we want to send signals to mptcp_connect instances that have +been started in the netns. But we cannot send this signal to 'timeout' +otherwise that will stop the timeout and messages telling us SIGUSR1 has +been received will be printed. Instead of trying to find the right PID +and storing them in an array, we can simply use the output of +'ip netns pids' which is all the PIDs we want to send signal to. + +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/160 +Signed-off-by: Matthieu Baerts +Signed-off-by: Mat Martineau +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/mptcp/diag.sh | 55 ++++++++++++------- + .../selftests/net/mptcp/mptcp_connect.sh | 15 +++-- + .../testing/selftests/net/mptcp/mptcp_join.sh | 22 ++++++-- + .../selftests/net/mptcp/simult_flows.sh | 13 ++++- + 4 files changed, 72 insertions(+), 33 deletions(-) + +diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh +index 39edce4f541c..2674ba20d524 100755 +--- a/tools/testing/selftests/net/mptcp/diag.sh ++++ b/tools/testing/selftests/net/mptcp/diag.sh +@@ -5,8 +5,9 @@ rndh=$(printf %x $sec)-$(mktemp -u XXXXXX) + ns="ns1-$rndh" + ksft_skip=4 + test_cnt=1 ++timeout_poll=100 ++timeout_test=$((timeout_poll * 2 + 1)) + ret=0 +-pids=() + + flush_pids() + { +@@ -14,18 +15,14 @@ flush_pids() + # give it some time + sleep 1.1 + +- for pid in ${pids[@]}; do +- [ -d /proc/$pid ] && kill -SIGUSR1 $pid >/dev/null 2>&1 +- done +- pids=() ++ ip netns pids "${ns}" | xargs --no-run-if-empty kill -SIGUSR1 &>/dev/null + } + + cleanup() + { ++ ip netns pids "${ns}" | xargs --no-run-if-empty kill -SIGKILL &>/dev/null ++ + ip netns del $ns +- for pid in ${pids[@]}; do +- [ -d /proc/$pid ] && kill -9 $pid >/dev/null 2>&1 +- done + } + + ip -Version > /dev/null 2>&1 +@@ -79,39 +76,57 @@ trap cleanup EXIT + ip netns add $ns + ip -n $ns link set dev lo up + +-echo "a" | ip netns exec $ns ./mptcp_connect -p 10000 -l 0.0.0.0 -t 100 >/dev/null & ++echo "a" | \ ++ timeout ${timeout_test} \ ++ ip netns exec $ns \ ++ ./mptcp_connect -p 10000 -l -t ${timeout_poll} \ ++ 0.0.0.0 >/dev/null & + sleep 0.1 +-pids[0]=$! + chk_msk_nr 0 "no msk on netns creation" + +-echo "b" | ip netns exec $ns ./mptcp_connect -p 10000 127.0.0.1 -j -t 100 >/dev/null & ++echo "b" | \ ++ timeout ${timeout_test} \ ++ ip netns exec $ns \ ++ ./mptcp_connect -p 10000 -j -t ${timeout_poll} \ ++ 127.0.0.1 >/dev/null & + sleep 0.1 +-pids[1]=$! + chk_msk_nr 2 "after MPC handshake " + chk_msk_remote_key_nr 2 "....chk remote_key" + chk_msk_fallback_nr 0 "....chk no fallback" + flush_pids + + +-echo "a" | ip netns exec $ns ./mptcp_connect -p 10001 -s TCP -l 0.0.0.0 -t 100 >/dev/null & +-pids[0]=$! ++echo "a" | \ ++ timeout ${timeout_test} \ ++ ip netns exec $ns \ ++ ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} \ ++ 0.0.0.0 >/dev/null & + sleep 0.1 +-echo "b" | ip netns exec $ns ./mptcp_connect -p 10001 127.0.0.1 -j -t 100 >/dev/null & +-pids[1]=$! ++echo "b" | \ ++ timeout ${timeout_test} \ ++ ip netns exec $ns \ ++ ./mptcp_connect -p 10001 -j -t ${timeout_poll} \ ++ 127.0.0.1 >/dev/null & + sleep 0.1 + chk_msk_fallback_nr 1 "check fallback" + flush_pids + + NR_CLIENTS=100 + for I in `seq 1 $NR_CLIENTS`; do +- echo "a" | ip netns exec $ns ./mptcp_connect -p $((I+10001)) -l 0.0.0.0 -t 100 -w 10 >/dev/null & +- pids[$((I*2))]=$! ++ echo "a" | \ ++ timeout ${timeout_test} \ ++ ip netns exec $ns \ ++ ./mptcp_connect -p $((I+10001)) -l -w 10 \ ++ -t ${timeout_poll} 0.0.0.0 >/dev/null & + done + sleep 0.1 + + for I in `seq 1 $NR_CLIENTS`; do +- echo "b" | ip netns exec $ns ./mptcp_connect -p $((I+10001)) 127.0.0.1 -t 100 -w 10 >/dev/null & +- pids[$((I*2 + 1))]=$! ++ echo "b" | \ ++ timeout ${timeout_test} \ ++ ip netns exec $ns \ ++ ./mptcp_connect -p $((I+10001)) -w 10 \ ++ -t ${timeout_poll} 127.0.0.1 >/dev/null & + done + sleep 1.5 + +diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh +index 10a030b53b23..65b3b983efc2 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh +@@ -11,7 +11,8 @@ cin="" + cout="" + ksft_skip=4 + capture=false +-timeout=30 ++timeout_poll=30 ++timeout_test=$((timeout_poll * 2 + 1)) + ipv6=true + ethtool_random_on=true + tc_delay="$((RANDOM%50))" +@@ -273,7 +274,7 @@ check_mptcp_disabled() + ip netns exec ${disabled_ns} sysctl -q net.mptcp.enabled=0 + + local err=0 +- LANG=C ip netns exec ${disabled_ns} ./mptcp_connect -t $timeout -p 10000 -s MPTCP 127.0.0.1 < "$cin" 2>&1 | \ ++ LANG=C ip netns exec ${disabled_ns} ./mptcp_connect -p 10000 -s MPTCP 127.0.0.1 < "$cin" 2>&1 | \ + grep -q "^socket: Protocol not available$" && err=1 + ip netns delete ${disabled_ns} + +@@ -430,14 +431,20 @@ do_transfer() + local stat_cookietx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesSent") + local stat_cookierx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesRecv") + +- ip netns exec ${listener_ns} ./mptcp_connect -t $timeout -l -p $port -s ${srv_proto} $extra_args $local_addr < "$sin" > "$sout" & ++ timeout ${timeout_test} \ ++ ip netns exec ${listener_ns} \ ++ ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ ++ $extra_args $local_addr < "$sin" > "$sout" & + local spid=$! + + wait_local_port_listen "${listener_ns}" "${port}" + + local start + start=$(date +%s%3N) +- ip netns exec ${connector_ns} ./mptcp_connect -t $timeout -p $port -s ${cl_proto} $extra_args $connect_addr < "$cin" > "$cout" & ++ timeout ${timeout_test} \ ++ ip netns exec ${connector_ns} \ ++ ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ ++ $extra_args $connect_addr < "$cin" > "$cout" & + local cpid=$! + + wait $cpid +diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh +index ad32240fbfda..43ed99de7734 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -8,7 +8,8 @@ cin="" + cinsent="" + cout="" + ksft_skip=4 +-timeout=30 ++timeout_poll=30 ++timeout_test=$((timeout_poll * 2 + 1)) + mptcp_connect="" + capture=0 + do_all_tests=1 +@@ -245,17 +246,26 @@ do_transfer() + local_addr="0.0.0.0" + fi + +- ip netns exec ${listener_ns} $mptcp_connect -t $timeout -l -p $port \ +- -s ${srv_proto} ${local_addr} < "$sin" > "$sout" & ++ timeout ${timeout_test} \ ++ ip netns exec ${listener_ns} \ ++ $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ ++ ${local_addr} < "$sin" > "$sout" & + spid=$! + + sleep 1 + + if [ "$test_link_fail" -eq 0 ];then +- ip netns exec ${connector_ns} $mptcp_connect -t $timeout -p $port -s ${cl_proto} $connect_addr < "$cin" > "$cout" & ++ timeout ${timeout_test} \ ++ ip netns exec ${connector_ns} \ ++ $mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ ++ $connect_addr < "$cin" > "$cout" & + else +- ( cat "$cin" ; sleep 2; link_failure $listener_ns ; cat "$cin" ) | tee "$cinsent" | \ +- ip netns exec ${connector_ns} $mptcp_connect -t $timeout -p $port -s ${cl_proto} $connect_addr > "$cout" & ++ ( cat "$cin" ; sleep 2; link_failure $listener_ns ; cat "$cin" ) | \ ++ tee "$cinsent" | \ ++ timeout ${timeout_test} \ ++ ip netns exec ${connector_ns} \ ++ $mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ ++ $connect_addr > "$cout" & + fi + cpid=$! + +diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh +index f039ee57eb3c..3aeef3bcb101 100755 +--- a/tools/testing/selftests/net/mptcp/simult_flows.sh ++++ b/tools/testing/selftests/net/mptcp/simult_flows.sh +@@ -7,7 +7,8 @@ ns2="ns2-$rndh" + ns3="ns3-$rndh" + capture=false + ksft_skip=4 +-timeout=30 ++timeout_poll=30 ++timeout_test=$((timeout_poll * 2 + 1)) + test_cnt=1 + ret=0 + bail=0 +@@ -157,14 +158,20 @@ do_transfer() + sleep 1 + fi + +- ip netns exec ${ns3} ./mptcp_connect -jt $timeout -l -p $port 0.0.0.0 < "$sin" > "$sout" & ++ timeout ${timeout_test} \ ++ ip netns exec ${ns3} \ ++ ./mptcp_connect -jt ${timeout_poll} -l -p $port \ ++ 0.0.0.0 < "$sin" > "$sout" & + local spid=$! + + wait_local_port_listen "${ns3}" "${port}" + + local start + start=$(date +%s%3N) +- ip netns exec ${ns1} ./mptcp_connect -jt $timeout -p $port 10.0.3.3 < "$cin" > "$cout" & ++ timeout ${timeout_test} \ ++ ip netns exec ${ns1} \ ++ ./mptcp_connect -jt ${timeout_poll} -p $port \ ++ 10.0.3.3 < "$cin" > "$cout" & + local cpid=$! + + wait $cpid +-- +2.30.2 + diff --git a/queue-5.12/selftests-powerpc-fix-l1d-flushing-tests-for-power10.patch b/queue-5.12/selftests-powerpc-fix-l1d-flushing-tests-for-power10.patch new file mode 100644 index 00000000000..be7bd548d57 --- /dev/null +++ b/queue-5.12/selftests-powerpc-fix-l1d-flushing-tests-for-power10.patch @@ -0,0 +1,82 @@ +From d5ca11c96604b6684b6c421bd38c1e283f34e9d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Feb 2021 17:02:27 +1000 +Subject: selftests/powerpc: Fix L1D flushing tests for Power10 + +From: Russell Currey + +[ Upstream commit 3a72c94ebfb1f171eba0715998010678a09ec796 ] + +The rfi_flush and entry_flush selftests work by using the PM_LD_MISS_L1 +perf event to count L1D misses. The value of this event has changed +over time: + +- Power7 uses 0x400f0 +- Power8 and Power9 use both 0x400f0 and 0x3e054 +- Power10 uses only 0x3e054 + +Rather than relying on raw values, configure perf to count L1D read +misses in the most explicit way available. + +This fixes the selftests to work on systems without 0x400f0 as +PM_LD_MISS_L1, and should change no behaviour for systems that the tests +already worked on. + +The only potential downside is that referring to a specific perf event +requires PMU support implemented in the kernel for that platform. + +Signed-off-by: Russell Currey +Acked-by: Daniel Axtens +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20210223070227.2916871-1-ruscur@russell.cc +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/powerpc/security/entry_flush.c | 2 +- + tools/testing/selftests/powerpc/security/flush_utils.h | 4 ++++ + tools/testing/selftests/powerpc/security/rfi_flush.c | 2 +- + 3 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/powerpc/security/entry_flush.c b/tools/testing/selftests/powerpc/security/entry_flush.c +index 78cf914fa321..68ce377b205e 100644 +--- a/tools/testing/selftests/powerpc/security/entry_flush.c ++++ b/tools/testing/selftests/powerpc/security/entry_flush.c +@@ -53,7 +53,7 @@ int entry_flush_test(void) + + entry_flush = entry_flush_orig; + +- fd = perf_event_open_counter(PERF_TYPE_RAW, /* L1d miss */ 0x400f0, -1); ++ fd = perf_event_open_counter(PERF_TYPE_HW_CACHE, PERF_L1D_READ_MISS_CONFIG, -1); + FAIL_IF(fd < 0); + + p = (char *)memalign(zero_size, CACHELINE_SIZE); +diff --git a/tools/testing/selftests/powerpc/security/flush_utils.h b/tools/testing/selftests/powerpc/security/flush_utils.h +index 07a5eb301466..7a3d60292916 100644 +--- a/tools/testing/selftests/powerpc/security/flush_utils.h ++++ b/tools/testing/selftests/powerpc/security/flush_utils.h +@@ -9,6 +9,10 @@ + + #define CACHELINE_SIZE 128 + ++#define PERF_L1D_READ_MISS_CONFIG ((PERF_COUNT_HW_CACHE_L1D) | \ ++ (PERF_COUNT_HW_CACHE_OP_READ << 8) | \ ++ (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)) ++ + void syscall_loop(char *p, unsigned long iterations, + unsigned long zero_size); + +diff --git a/tools/testing/selftests/powerpc/security/rfi_flush.c b/tools/testing/selftests/powerpc/security/rfi_flush.c +index 7565fd786640..f73484a6470f 100644 +--- a/tools/testing/selftests/powerpc/security/rfi_flush.c ++++ b/tools/testing/selftests/powerpc/security/rfi_flush.c +@@ -54,7 +54,7 @@ int rfi_flush_test(void) + + rfi_flush = rfi_flush_orig; + +- fd = perf_event_open_counter(PERF_TYPE_RAW, /* L1d miss */ 0x400f0, -1); ++ fd = perf_event_open_counter(PERF_TYPE_HW_CACHE, PERF_L1D_READ_MISS_CONFIG, -1); + FAIL_IF(fd < 0); + + p = (char *)memalign(zero_size, CACHELINE_SIZE); +-- +2.30.2 + diff --git a/queue-5.12/selftests-set-cc-to-clang-in-lib.mk-if-llvm-is-set.patch b/queue-5.12/selftests-set-cc-to-clang-in-lib.mk-if-llvm-is-set.patch new file mode 100644 index 00000000000..04cd2a094cf --- /dev/null +++ b/queue-5.12/selftests-set-cc-to-clang-in-lib.mk-if-llvm-is-set.patch @@ -0,0 +1,42 @@ +From 010fe81188dad552267fdc3679941114f7771922 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Apr 2021 08:34:13 -0700 +Subject: selftests: Set CC to clang in lib.mk if LLVM is set + +From: Yonghong Song + +[ Upstream commit 26e6dd1072763cd5696b75994c03982dde952ad9 ] + +selftests/bpf/Makefile includes lib.mk. With the following command + make -j60 LLVM=1 LLVM_IAS=1 <=== compile kernel + make -j60 -C tools/testing/selftests/bpf LLVM=1 LLVM_IAS=1 V=1 +some files are still compiled with gcc. This patch +fixed lib.mk issue which sets CC to gcc in all cases. + +Signed-off-by: Yonghong Song +Signed-off-by: Alexei Starovoitov +Acked-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20210413153413.3027426-1-yhs@fb.com +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/lib.mk | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk +index be17462fe146..0af84ad48aa7 100644 +--- a/tools/testing/selftests/lib.mk ++++ b/tools/testing/selftests/lib.mk +@@ -1,6 +1,10 @@ + # This mimics the top-level Makefile. We do it explicitly here so that this + # Makefile can operate with or without the kbuild infrastructure. ++ifneq ($(LLVM),) ++CC := clang ++else + CC := $(CROSS_COMPILE)gcc ++endif + + ifeq (0,$(MAKELEVEL)) + ifeq ($(OUTPUT),) +-- +2.30.2 + diff --git a/queue-5.12/series b/queue-5.12/series index c746d7fab5f..f005fa54b85 100644 --- a/queue-5.12/series +++ b/queue-5.12/series @@ -9,3 +9,239 @@ acpi-pm-add-acpi-id-of-alder-lake-fan.patch pm-runtime-fix-unpaired-parent-child_count-for-force_resume.patch cpufreq-intel_pstate-use-hwp-if-enabled-by-platform-firmware.patch kvm-cap-halt-polling-at-kvm-max_halt_poll_ns.patch +ath11k-fix-thermal-temperature-read.patch +alsa-usb-audio-add-pioneer-djm-850-to-quirks-table.patch +fs-dlm-fix-debugfs-dump.patch +fs-dlm-fix-mark-setting-deadlock.patch +fs-dlm-add-errno-handling-to-check-callback.patch +fs-dlm-add-check-if-dlm-is-currently-running.patch +fs-dlm-change-allocation-limits.patch +fs-dlm-check-on-minimum-msglen-size.patch +fs-dlm-flush-swork-on-shutdown.patch +fs-dlm-add-shutdown-hook.patch +tipc-convert-dest-node-s-address-to-network-order.patch +asoc-intel-bytcr_rt5640-enable-jack-detect-support-o.patch +net-mlx5e-use-net_prefetchw-instead-of-prefetchw-in-.patch +net-stmmac-set-fifo-sizes-for-ipq806x.patch +asoc-rsnd-core-check-convert-rate-in-rsnd_hw_params.patch +bluetooth-fix-incorrect-status-handling-in-le-phy-up.patch +i2c-bail-out-early-when-rdwr-parameters-are-wrong.patch +alsa-hdsp-don-t-disable-if-not-enabled.patch +alsa-hdspm-don-t-disable-if-not-enabled.patch +alsa-rme9652-don-t-disable-if-not-enabled.patch +alsa-bebob-enable-to-deliver-midi-messages-for-multi.patch +bluetooth-set-conf_not_complete-as-l2cap_chan-defaul.patch +bluetooth-initialize-skb_queue_head-at-l2cap_chan_cr.patch +net-sched-cls_flower-use-ntohs-for-struct-flow_disse.patch +net-bridge-when-suppression-is-enabled-exclude-rarp-.patch +bluetooth-check-for-zapped-sk-before-connecting.patch +selftests-powerpc-fix-l1d-flushing-tests-for-power10.patch +alsa-hda-hdmi-fix-max-dp-mst-dev_num-for-intel-tgl-p.patch +powerpc-32-statically-initialise-first-emergency-con.patch +net-hns3-remediate-a-potential-overflow-risk-of-bd_n.patch +net-hns3-add-handling-for-xmit-skb-with-recursive-fr.patch +ip6_vti-proper-dev_-hold-put-in-ndo_-un-init-methods.patch +can-dev-can_free_echo_skb-don-t-crash-the-kernel-if-.patch +iommu-arm-smmu-v3-add-a-check-to-avoid-invalid-iotlb.patch +asoc-intel-bytcr_rt5640-add-quirk-for-the-chuwi-hi8-.patch +ice-handle-increasing-tx-or-rx-ring-sizes.patch +bluetooth-btusb-enable-quirk-boolean-flag-for-mediat.patch +asoc-rt5670-add-a-quirk-for-the-dell-venue-10-pro-50.patch +selftests-mptcp-launch-mptcp_connect-with-timeout.patch +i2c-add-i2c_aq_no_rep_start-adapter-quirk.patch +bluetooth-do-not-set-cur_adv_instance-in-adv-param-m.patch +mips-loongson64-use-_cache_uncached-instead-of-_cach.patch +coresight-do-not-scan-for-graph-if-none-is-present.patch +ib-hfi1-correct-oversized-ring-allocation.patch +mac80211-set-priority-and-queue-mapping-for-injected.patch +mac80211-clear-the-beacon-s-crc-after-channel-switch.patch +asoc-soc-compress-lock-pcm_mutex-to-resolve-lockdep-.patch +net-phy-make-phy-pm-ops-a-no-op-if-mac-driver-manage.patch +net-fec-use-mac-managed-phy-pm.patch +pinctrl-samsung-use-int-for-register-masks-in-exynos.patch +rtw88-8822c-add-lc-calibration-for-rtl8822c.patch +mt76-mt7615-fix-key-set-delete-issues.patch +mt76-mt7615-support-loading-eeprom-for-mt7613be.patch +mt76-mt76x0-disable-gtk-offloading.patch +mt76-connac-always-check-return-value-from-mt76_conn.patch +mt76-mt7915-always-check-return-value-from-mt7915_mc.patch +mt76-mt7915-fix-key-set-delete-issue.patch +mt76-mt7915-fix-txpower-init-for-tssi-off-chips.patch +mt76-mt7921-fix-key-set-delete-issue.patch +mt76-mt7915-add-wifi-subsystem-reset.patch +i2c-imx-fix-pm-reference-leak-in-i2c_imx_reg_slave.patch +fuse-invalidate-attrs-when-page-writeback-completes.patch +virtiofs-fix-userns.patch +cuse-prevent-clone.patch +iwlwifi-pcie-make-cfg-vs.-trans_cfg-more-robust.patch +iwlwifi-queue-avoid-memory-leak-in-reset-flow.patch +iwlwifi-trans-pcie-defer-transport-initialisation.patch +powerpc-mm-add-cond_resched-while-removing-hpte-mapp.patch +asoc-rsnd-call-rsnd_ssi_master_clk_start-from-rsnd_s.patch +net-bridge-propagate-error-code-and-extack-from-br_m.patch +revert-iommu-amd-fix-performance-counter-initializat.patch +iommu-amd-remove-performance-counter-pre-initializat.patch +drm-amd-display-force-vsync-flip-when-reconfiguring-.patch +selftests-set-cc-to-clang-in-lib.mk-if-llvm-is-set.patch +kconfig-nconf-stop-endless-search-loops.patch +alsa-hda-realtek-add-quirk-for-lenovo-ideapad-s740.patch +asoc-intel-sof_sdw-add-quirk-for-new-adl-p-rvp.patch +alsa-hda-hdmi-fix-race-in-handling-acomp-eld-notific.patch +i2c-i801-add-support-for-intel-alder-lake-pch-m.patch +sctp-fix-out-of-bounds-warning-in-sctp_process_ascon.patch +flow_dissector-fix-out-of-bounds-warning-in-__skb_fl.patch +powerpc-xive-use-the-ibm-chip-id-property-only-under.patch +powerpc-smp-set-numa-node-before-updating-mask.patch +wilc1000-bring-mac-address-setting-in-line-with-typi.patch +mac80211-properly-drop-the-connection-in-case-of-inv.patch +asoc-rt286-generalize-support-for-alc3263-codec.patch +ethtool-ioctl-fix-out-of-bounds-warning-in-store_lin.patch +net-sched-tapr-prevent-cycle_time-0-in-parse_taprio_.patch +samples-bpf-fix-broken-tracex1-due-to-kprobe-argumen.patch +powerpc-pseries-stop-calling-printk-in-rtas_stop_sel.patch +drm-amd-display-fixed-divide-by-zero-kernel-crash-du.patch +drm-amd-display-add-handling-for-hdcp2-rx-id-list-va.patch +drm-amdgpu-add-mem-sync-flag-for-ib-allocated-by-sa.patch +mt76-mt7615-fix-entering-driver-own-state-on-mt7663.patch +crypto-ccp-free-sev-device-if-sev-init-fails.patch +wl3501_cs-fix-out-of-bounds-warnings-in-wl3501_send_.patch +wl3501_cs-fix-out-of-bounds-warnings-in-wl3501_mgmt_.patch +qtnfmac-fix-possible-buffer-overflow-in-qtnf_event_h.patch +powerpc-iommu-annotate-nested-lock-for-lockdep.patch +iavf-remove-duplicate-free-resources-calls.patch +net-ethernet-mtk_eth_soc-fix-rx-vlan-offload.patch +selftests-mlxsw-increase-the-tolerance-of-backlog-bu.patch +selftests-mlxsw-fix-mausezahn-invocation-in-erspan-s.patch +kbuild-generate-module.symvers-only-when-vmlinux-exi.patch +bnxt_en-add-pci-ids-for-hyper-v-vf-devices.patch +ia64-module-fix-symbolizer-crash-on-fdescr.patch +watchdog-rename-__touch_watchdog-to-a-better-descrip.patch +watchdog-explicitly-update-timestamp-when-reporting-.patch +watchdog-softlockup-report-the-overall-time-of-softl.patch +watchdog-softlockup-remove-logic-that-tried-to-preve.patch +watchdog-fix-barriers-when-printing-backtraces-from-.patch +watchdog-cleanup-handling-of-false-positives.patch +asoc-rt286-make-rt286_set_gpio_-readable-and-writabl.patch +leds-lgm-fix-gpiolib-dependency.patch +thermal-thermal_of-fix-error-return-code-of-thermal_.patch +pci-rcec-fix-rciep-device-to-rcec-association.patch +f2fs-fix-to-allow-migrating-fully-valid-segment.patch +f2fs-fix-panic-during-f2fs_resize_fs.patch +f2fs-fix-a-redundant-call-to-f2fs_balance_fs-if-an-e.patch +rtc-tps65910-include-linux-property.h.patch +remoteproc-qcom_q6v5_mss-validate-p_filesz-in-elf-lo.patch +pci-iproc-fix-return-value-of-iproc_msi_irq_domain_a.patch +pci-brcmstb-fix-error-return-code-in-brcm_pcie_probe.patch +pci-release-of-node-in-pci_scan_device-s-error-path.patch +arm-9064-1-hw_breakpoint-do-not-directly-check-the-e.patch +f2fs-fix-to-align-to-section-for-fallocate-on-pinned.patch +f2fs-fix-to-update-last-i_size-if-fallocate-partiall.patch +pci-endpoint-fix-null-pointer-dereference-for-get_fe.patch +f2fs-fix-to-avoid-touching-checkpointed-data-in-get_.patch +f2fs-fix-to-cover-__allocate_new_section-with-curseg.patch +fs-9p-fix-v9fs_file_open-writeback-fid-error-check.patch +f2fs-fix-to-restrict-mount-condition-on-readonly-blo.patch +f2fs-fix-a-hungtask-problem-in-atomic-write.patch +nfs-subsequent-readdir-calls-should-carry-non-zero-c.patch +nfs-fix-handling-of-cookie-verifier-in-uncached_read.patch +nfs-only-change-the-cookie-verifier-if-the-directory.patch +f2fs-fix-to-avoid-accessing-invalid-fio-in-f2fs_allo.patch +rpmsg-qcom_glink_native-fix-error-return-code-of-qco.patch +nfs-nfs4_bitmask_adjust-must-not-change-the-server-g.patch +nfs-fix-attribute-bitmask-in-_nfs42_proc_fallocate.patch +nfsv4.2-always-flush-out-writes-in-nfs42_proc_falloc.patch +nfs-deal-correctly-with-attribute-generation-counter.patch +pci-endpoint-fix-missing-destroy_workqueue.patch +remoteproc-pru-fixup-interrupt-parent-logic-for-fw-e.patch +remoteproc-pru-fix-wrong-success-return-value-for-fw.patch +remoteproc-pru-fix-and-cleanup-firmware-interrupt-ma.patch +pnfs-flexfiles-fix-incorrect-size-check-in-decode_nf.patch +nfsv4.2-fix-handling-of-sr_eof-in-seek-s-reply.patch +sunrpc-move-fault-injection-call-sites.patch +sunrpc-remove-trace_xprt_transmit_queued.patch +sunrpc-handle-major-timeout-in-xprt_adjust_timeout.patch +nfsv42-copy-offload-should-update-the-file-size-when.patch +thermal-drivers-tsens-fix-missing-put_device-error.patch +nfsv4.x-don-t-return-nfs4err_nomatching_layout-if-we.patch +nfsd-ensure-new-clients-break-delegations.patch +rtc-fsl-ftm-alarm-add-module_table.patch +dmaengine-idxd-fix-potential-null-dereference-on-poi.patch +dmaengine-idxd-fix-dma-device-lifetime.patch +dmaengine-idxd-cleanup-pci-interrupt-vector-allocati.patch +dmaengine-idxd-removal-of-pcim-managed-mmio-mapping.patch +dmaengine-idxd-use-ida-for-device-instance-enumerati.patch +dmaengine-idxd-fix-idxd-conf_dev-struct-device-lifet.patch +dmaengine-idxd-fix-wq-conf_dev-struct-device-lifetim.patch +dmaengine-idxd-fix-engine-conf_dev-lifetime.patch +dmaengine-idxd-fix-group-conf_dev-lifetime.patch +dmaengine-idxd-fix-cdev-setup-and-free-device-lifeti.patch +sunrpc-fix-ternary-sign-expansion-bug-in-tracing.patch +sunrpc-fix-null-pointer-dereference-in-svc_rqst_free.patch +pwm-atmel-fix-duty-cycle-calculation-in-.get_state.patch +xprtrdma-avoid-receive-queue-wrapping.patch +xprtrdma-fix-cwnd-update-ordering.patch +xprtrdma-rpcrdma_mr_pop-already-does-list_del_init.patch +riscv-select-have_dynamic_ftrace-when-fpatchable-fun.patch +swiotlb-fix-the-type-of-index.patch +ceph-fix-inode-leak-on-getattr-error-in-__fh_to_dent.patch +scsi-qla2xxx-prevent-prli-in-target-mode.patch +scsi-ufs-core-do-not-put-ufs-power-into-lpm-if-link-.patch +scsi-ufs-core-cancel-rpm_dev_flush_recheck_work-duri.patch +scsi-ufs-core-narrow-down-fast-path-in-system-suspen.patch +rtc-ds1307-fix-wday-settings-for-rx8130.patch +net-hns3-fix-incorrect-configuration-for-igu_egu_hw_.patch +net-hns3-initialize-the-message-content-in-hclge_get.patch +net-hns3-add-check-for-hns3_nic_state_inited-in-hns3.patch +arm64-stacktrace-restore-terminal-records.patch +net-hns3-fix-for-vxlan-gpe-tx-checksum-bug.patch +net-hns3-use-netif_tx_disable-to-stop-the-transmit-q.patch +net-hns3-disable-phy-loopback-setting-in-hclge_mac_s.patch +sctp-do-asoc-update-earlier-in-sctp_sf_do_dupcook_a.patch +risc-v-fix-error-code-returned-by-riscv_hartid_to_cp.patch +sunrpc-fix-misplaced-barrier-in-call_decode.patch +libbpf-fix-signed-overflow-in-ringbuf_process_ring.patch +block-rnbd-clt-change-queue_depth-type-in-rnbd_clt_s.patch +block-rnbd-clt-check-the-return-value-of-the-functio.patch +ata-ahci_brcm-fix-use-of-bcm7216-reset-controller.patch +pci-brcmstb-use-reset-rearm-instead-of-deassert-asse.patch +ethernet-enic-fix-a-use-after-free-bug-in-enic_hard_.patch +sctp-fix-a-sctp_mib_currestab-leak-in-sctp_sf_do_dup.patch +netfilter-xt_secmark-add-new-revision-to-fix-structu.patch +xsk-fix-for-xp_aligned_validate_desc-when-len-chunk_.patch +powerpc-powernv-memtrace-fix-dcache-flushing.patch +net-stmmac-clear-receive-all-ra-bit-when-promiscuous.patch +drm-radeon-fix-off-by-one-power_state-index-heap-ove.patch +drm-radeon-avoid-power-table-parsing-memory-leaks.patch +arm64-entry-factor-irq-triage-logic-into-macros.patch +arm64-entry-always-set-gic_prio_psr_i_set-during-ent.patch +khugepaged-fix-wrong-result-value-for-trace_mm_colla.patch +mm-hugeltb-handle-the-error-case-in-hugetlb_fix_rese.patch +mm-migrate.c-fix-potential-indeterminate-pte-entry-i.patch +ksm-fix-potential-missing-rmap_item-for-stable_node.patch +mm-gup-check-every-subpage-of-a-compound-page-during.patch +mm-gup-return-an-error-on-migration-failure.patch +mm-gup-check-for-isolation-errors.patch +kfence-await-for-allocation-using-wait_event.patch +ethtool-fix-missing-nlm_f_multi-flag-when-dumping.patch +net-fix-nla_strcmp-to-handle-more-then-one-trailing-.patch +smc-disallow-tcp_ulp-in-smc_setsockopt.patch +netfilter-nfnetlink_osf-fix-a-missing-skb_header_poi.patch +netfilter-nftables-fix-a-memleak-from-userdata-error.patch +can-mcp251xfd-mcp251xfd_probe-fix-an-error-pointer-d.patch +can-mcp251xfd-mcp251xfd_probe-add-missing-can_rx_off.patch +can-mcp251x-fix-resume-from-sleep-before-interface-w.patch +can-m_can-m_can_tx_work_queue-fix-tx_skb-race-condit.patch +sched-fix-out-of-bound-access-in-uclamp.patch +sched-fair-fix-unfairness-caused-by-missing-load-dec.patch +net-ipa-fix-inter-ee-irq-register-definitions.patch +fs-proc-generic.c-fix-incorrect-pde_is_permanent-che.patch +kernel-kexec_file-fix-error-return-code-of-kexec_cal.patch +kernel-resource-make-walk_system_ram_res-find-all-bu.patch +kernel-resource-make-walk_mem_res-find-all-busy-iore.patch +netfilter-nftables-avoid-overflows-in-nft_hash_bucke.patch +i40e-fix-broken-xdp-support.patch +i40e-fix-use-after-free-in-i40e_client_subtask.patch +i40e-fix-the-restart-auto-negotiation-after-fec-modi.patch +i40e-fix-phy-type-identifiers-for-2.5g-and-5g-adapte.patch +i40e-remove-lldp-frame-filters.patch +mptcp-fix-splat-when-closing-unaccepted-socket.patch diff --git a/queue-5.12/smc-disallow-tcp_ulp-in-smc_setsockopt.patch b/queue-5.12/smc-disallow-tcp_ulp-in-smc_setsockopt.patch new file mode 100644 index 00000000000..3498bbed55c --- /dev/null +++ b/queue-5.12/smc-disallow-tcp_ulp-in-smc_setsockopt.patch @@ -0,0 +1,55 @@ +From d7b256987578f5d3c85106835c0caf6f63c07be9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 May 2021 12:40:48 -0700 +Subject: smc: disallow TCP_ULP in smc_setsockopt() + +From: Cong Wang + +[ Upstream commit 8621436671f3a4bba5db57482e1ee604708bf1eb ] + +syzbot is able to setup kTLS on an SMC socket which coincidentally +uses sk_user_data too. Later, kTLS treats it as psock so triggers a +refcnt warning. The root cause is that smc_setsockopt() simply calls +TCP setsockopt() which includes TCP_ULP. I do not think it makes +sense to setup kTLS on top of SMC sockets, so we should just disallow +this setup. + +It is hard to find a commit to blame, but we can apply this patch +since the beginning of TCP_ULP. + +Reported-and-tested-by: syzbot+b54a1ce86ba4a623b7f0@syzkaller.appspotmail.com +Fixes: 734942cc4ea6 ("tcp: ULP infrastructure") +Cc: John Fastabend +Signed-off-by: Karsten Graul +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/smc/af_smc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c +index 47340b3b514f..cb23cca72c24 100644 +--- a/net/smc/af_smc.c ++++ b/net/smc/af_smc.c +@@ -2162,6 +2162,9 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, + struct smc_sock *smc; + int val, rc; + ++ if (level == SOL_TCP && optname == TCP_ULP) ++ return -EOPNOTSUPP; ++ + smc = smc_sk(sk); + + /* generic setsockopts reaching us here always apply to the +@@ -2186,7 +2189,6 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, + if (rc || smc->use_fallback) + goto out; + switch (optname) { +- case TCP_ULP: + case TCP_FASTOPEN: + case TCP_FASTOPEN_CONNECT: + case TCP_FASTOPEN_KEY: +-- +2.30.2 + diff --git a/queue-5.12/sunrpc-fix-misplaced-barrier-in-call_decode.patch b/queue-5.12/sunrpc-fix-misplaced-barrier-in-call_decode.patch new file mode 100644 index 00000000000..2e9364e669b --- /dev/null +++ b/queue-5.12/sunrpc-fix-misplaced-barrier-in-call_decode.patch @@ -0,0 +1,68 @@ +From 246d39451724813128fc13979354447a49707be6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 May 2021 14:10:51 +1000 +Subject: sunrpc: Fix misplaced barrier in call_decode + +From: Baptiste Lepers + +[ Upstream commit f8f7e0fb22b2e75be55f2f0c13e229e75b0eac07 ] + +Fix a misplaced barrier in call_decode. The struct rpc_rqst is modified +as follows by xprt_complete_rqst: + +req->rq_private_buf.len = copied; +/* Ensure all writes are done before we update */ +/* req->rq_reply_bytes_recvd */ +smp_wmb(); +req->rq_reply_bytes_recvd = copied; + +And currently read as follows by call_decode: + +smp_rmb(); // misplaced +if (!req->rq_reply_bytes_recvd) + goto out; +req->rq_rcv_buf.len = req->rq_private_buf.len; + +This patch places the smp_rmb after the if to ensure that +rq_reply_bytes_recvd and rq_private_buf.len are read in order. + +Fixes: 9ba828861c56a ("SUNRPC: Don't try to parse incomplete RPC messages") +Signed-off-by: Baptiste Lepers +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/clnt.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index c2a01125be1a..f555d335e910 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -2456,12 +2456,6 @@ call_decode(struct rpc_task *task) + task->tk_flags &= ~RPC_CALL_MAJORSEEN; + } + +- /* +- * Ensure that we see all writes made by xprt_complete_rqst() +- * before it changed req->rq_reply_bytes_recvd. +- */ +- smp_rmb(); +- + /* + * Did we ever call xprt_complete_rqst()? If not, we should assume + * the message is incomplete. +@@ -2470,6 +2464,11 @@ call_decode(struct rpc_task *task) + if (!req->rq_reply_bytes_recvd) + goto out; + ++ /* Ensure that we see all writes made by xprt_complete_rqst() ++ * before it changed req->rq_reply_bytes_recvd. ++ */ ++ smp_rmb(); ++ + req->rq_rcv_buf.len = req->rq_private_buf.len; + trace_rpc_xdr_recvfrom(task, &req->rq_rcv_buf); + +-- +2.30.2 + diff --git a/queue-5.12/sunrpc-fix-null-pointer-dereference-in-svc_rqst_free.patch b/queue-5.12/sunrpc-fix-null-pointer-dereference-in-svc_rqst_free.patch new file mode 100644 index 00000000000..56e62111aa0 --- /dev/null +++ b/queue-5.12/sunrpc-fix-null-pointer-dereference-in-svc_rqst_free.patch @@ -0,0 +1,39 @@ +From e8e5d7f1bf25c8f452ef4f73a0ab4e290d2da21f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Apr 2021 17:42:58 +0800 +Subject: SUNRPC: Fix null pointer dereference in svc_rqst_free() + +From: Yunjian Wang + +[ Upstream commit b9f83ffaa0c096b4c832a43964fe6bff3acffe10 ] + +When alloc_pages_node() returns null in svc_rqst_alloc(), the +null rq_scratch_page pointer will be dereferenced when calling +put_page() in svc_rqst_free(). Fix it by adding a null check. + +Addresses-Coverity: ("Dereference after null check") +Fixes: 5191955d6fc6 ("SUNRPC: Prepare for xdr_stream-style decoding on the server-side") +Signed-off-by: Yunjian Wang +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + net/sunrpc/svc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c +index d76dc9d95d16..0de918cb3d90 100644 +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -846,7 +846,8 @@ void + svc_rqst_free(struct svc_rqst *rqstp) + { + svc_release_buffer(rqstp); +- put_page(rqstp->rq_scratch_page); ++ if (rqstp->rq_scratch_page) ++ put_page(rqstp->rq_scratch_page); + kfree(rqstp->rq_resp); + kfree(rqstp->rq_argp); + kfree(rqstp->rq_auth_data); +-- +2.30.2 + diff --git a/queue-5.12/sunrpc-fix-ternary-sign-expansion-bug-in-tracing.patch b/queue-5.12/sunrpc-fix-ternary-sign-expansion-bug-in-tracing.patch new file mode 100644 index 00000000000..3c037aad8f8 --- /dev/null +++ b/queue-5.12/sunrpc-fix-ternary-sign-expansion-bug-in-tracing.patch @@ -0,0 +1,42 @@ +From a0d103c650e83fd45c9d62a743dafc68c2ff6750 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Apr 2021 12:14:37 +0300 +Subject: SUNRPC: fix ternary sign expansion bug in tracing + +From: Dan Carpenter + +[ Upstream commit cb579086536f6564f5846f89808ec394ef8b8621 ] + +This code is supposed to pass negative "err" values for tracing but it +passes positive values instead. The problem is that the +trace_svcsock_tcp_send() function takes a long but "err" is an int and +"sent" is a u32. The negative is first type promoted to u32 so it +becomes a high positive then it is promoted to long and it stays +positive. + +Fix this by casting "err" directly to long. + +Fixes: 998024dee197 ("SUNRPC: Add more svcsock tracepoints") +Signed-off-by: Dan Carpenter +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + net/sunrpc/svcsock.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c +index 2e2f007dfc9f..7cde41a936a4 100644 +--- a/net/sunrpc/svcsock.c ++++ b/net/sunrpc/svcsock.c +@@ -1171,7 +1171,7 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp) + tcp_sock_set_cork(svsk->sk_sk, true); + err = svc_tcp_sendmsg(svsk->sk_sock, xdr, marker, &sent); + xdr_free_bvec(xdr); +- trace_svcsock_tcp_send(xprt, err < 0 ? err : sent); ++ trace_svcsock_tcp_send(xprt, err < 0 ? (long)err : sent); + if (err < 0 || sent != (xdr->len + sizeof(marker))) + goto out_close; + if (atomic_dec_and_test(&svsk->sk_sendqlen)) +-- +2.30.2 + diff --git a/queue-5.12/sunrpc-handle-major-timeout-in-xprt_adjust_timeout.patch b/queue-5.12/sunrpc-handle-major-timeout-in-xprt_adjust_timeout.patch new file mode 100644 index 00000000000..c769ba4699f --- /dev/null +++ b/queue-5.12/sunrpc-handle-major-timeout-in-xprt_adjust_timeout.patch @@ -0,0 +1,61 @@ +From 1023be47cd7f3954e258a36f9ecf443741b256ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Apr 2021 21:29:26 -0400 +Subject: SUNRPC: Handle major timeout in xprt_adjust_timeout() + +From: Chris Dion + +[ Upstream commit 09252177d5f924f404551b4b4eded5daa7f04a3a ] + +Currently if a major timeout value is reached, but the minor value has +not been reached, an ETIMEOUT will not be sent back to the caller. +This can occur if the v4 server is not responding to requests and +retrans is configured larger than the default of two. + +For example, A TCP mount with a configured timeout value of 50 and a +retransmission count of 3 to a v4 server which is not responding: + +1. Initial value and increment set to 5s, maxval set to 20s, retries at 3 +2. Major timeout is set to 20s, minor timeout set to 5s initially +3. xport_adjust_timeout() is called after 5s, retry with 10s timeout, + minor timeout is bumped to 10s +4. And again after another 10s, 15s total time with minor timeout set + to 15s +5. After 20s total time xport_adjust_timeout is called as major timeout is + reached, but skipped because the minor timeout is not reached + - After this time the cpu spins continually calling + xport_adjust_timeout() and returning 0 for 10 seconds. + As seen on perf sched: + 39243.913182 [0005] mount.nfs[3794] 4607.938 0.017 9746.863 +6. This continues until the 15s minor timeout condition is reached (in + this case for 10 seconds). After which the ETIMEOUT is processed + back to the caller, the cpu spinning stops, and normal operations + continue + +Fixes: 7de62bc09fe6 ("SUNRPC dont update timeout value on connection reset") +Signed-off-by: Chris Dion +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/xprt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c +index 11ebe8a127b8..20fe31b1b776 100644 +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -698,9 +698,9 @@ int xprt_adjust_timeout(struct rpc_rqst *req) + const struct rpc_timeout *to = req->rq_task->tk_client->cl_timeout; + int status = 0; + +- if (time_before(jiffies, req->rq_minortimeo)) +- return status; + if (time_before(jiffies, req->rq_majortimeo)) { ++ if (time_before(jiffies, req->rq_minortimeo)) ++ return status; + if (to->to_exponential) + req->rq_timeout <<= 1; + else +-- +2.30.2 + diff --git a/queue-5.12/sunrpc-move-fault-injection-call-sites.patch b/queue-5.12/sunrpc-move-fault-injection-call-sites.patch new file mode 100644 index 00000000000..c439479ebf6 --- /dev/null +++ b/queue-5.12/sunrpc-move-fault-injection-call-sites.patch @@ -0,0 +1,85 @@ +From e8c257aedfa81b0bdb1ad1d9d97e1ceb2732ffc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Mar 2021 13:22:14 -0400 +Subject: SUNRPC: Move fault injection call sites + +From: Chuck Lever + +[ Upstream commit 7638e0bfaed1b653d3ca663e560e9ffb44bb1030 ] + +I've hit some crashes that occur in the xprt_rdma_inject_disconnect +path. It appears that, for some provides, rdma_disconnect() can +take so long that the transport can disconnect and release its +hardware resources while rdma_disconnect() is still running, +resulting in a UAF in the provider. + +The transport's fault injection method may depend on the stability +of transport data structures. That means it needs to be invoked +only from contexts that hold the transport write lock. + +Fixes: 4a0682583988 ("SUNRPC: Transport fault injection") +Signed-off-by: Chuck Lever +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/clnt.c | 1 - + net/sunrpc/xprt.c | 6 ++++-- + net/sunrpc/xprtrdma/transport.c | 6 ++++-- + 3 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index 612f0a641f4c..c2a01125be1a 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -1799,7 +1799,6 @@ call_allocate(struct rpc_task *task) + + status = xprt->ops->buf_alloc(task); + trace_rpc_buf_alloc(task, status); +- xprt_inject_disconnect(xprt); + if (status == 0) + return; + if (status != -ENOMEM) { +diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c +index 691ccf8049a4..d616b93751d8 100644 +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -1483,7 +1483,10 @@ bool xprt_prepare_transmit(struct rpc_task *task) + + void xprt_end_transmit(struct rpc_task *task) + { +- xprt_release_write(task->tk_rqstp->rq_xprt, task); ++ struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt; ++ ++ xprt_inject_disconnect(xprt); ++ xprt_release_write(xprt, task); + } + + /** +@@ -1885,7 +1888,6 @@ void xprt_release(struct rpc_task *task) + spin_unlock(&xprt->transport_lock); + if (req->rq_buffer) + xprt->ops->buf_free(task); +- xprt_inject_disconnect(xprt); + xdr_free_bvec(&req->rq_rcv_buf); + xdr_free_bvec(&req->rq_snd_buf); + if (req->rq_cred != NULL) +diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c +index 78d29d1bcc20..09953597d055 100644 +--- a/net/sunrpc/xprtrdma/transport.c ++++ b/net/sunrpc/xprtrdma/transport.c +@@ -262,8 +262,10 @@ xprt_rdma_connect_worker(struct work_struct *work) + * xprt_rdma_inject_disconnect - inject a connection fault + * @xprt: transport context + * +- * If @xprt is connected, disconnect it to simulate spurious connection +- * loss. ++ * If @xprt is connected, disconnect it to simulate spurious ++ * connection loss. Caller must hold @xprt's send lock to ++ * ensure that data structures and hardware resources are ++ * stable during the rdma_disconnect() call. + */ + static void + xprt_rdma_inject_disconnect(struct rpc_xprt *xprt) +-- +2.30.2 + diff --git a/queue-5.12/sunrpc-remove-trace_xprt_transmit_queued.patch b/queue-5.12/sunrpc-remove-trace_xprt_transmit_queued.patch new file mode 100644 index 00000000000..605cc4f8dc0 --- /dev/null +++ b/queue-5.12/sunrpc-remove-trace_xprt_transmit_queued.patch @@ -0,0 +1,63 @@ +From 699dcc677b92aff9d1515e211a55038d9e03a403 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Mar 2021 16:03:08 -0400 +Subject: SUNRPC: Remove trace_xprt_transmit_queued + +From: Chuck Lever + +[ Upstream commit 6cf23783f750634e10daeede48b0f5f5d64ebf3a ] + +This tracepoint can crash when dereferencing snd_task because +when some transports connect, they put a cookie in that field +instead of a pointer to an rpc_task. + +BUG: KASAN: use-after-free in trace_event_raw_event_xprt_writelock_event+0x141/0x18e [sunrpc] +Read of size 2 at addr ffff8881a83bd3a0 by task git/331872 + +CPU: 11 PID: 331872 Comm: git Tainted: G S 5.12.0-rc2-00007-g3ab6e585a7f9 #1453 +Hardware name: Supermicro SYS-6028R-T/X10DRi, BIOS 1.1a 10/16/2015 +Call Trace: + dump_stack+0x9c/0xcf + print_address_description.constprop.0+0x18/0x239 + kasan_report+0x174/0x1b0 + trace_event_raw_event_xprt_writelock_event+0x141/0x18e [sunrpc] + xprt_prepare_transmit+0x8e/0xc1 [sunrpc] + call_transmit+0x4d/0xc6 [sunrpc] + +Fixes: 9ce07ae5eb1d ("SUNRPC: Replace dprintk() call site in xprt_prepare_transmit") +Signed-off-by: Chuck Lever +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + include/trace/events/sunrpc.h | 1 - + net/sunrpc/xprt.c | 2 -- + 2 files changed, 3 deletions(-) + +diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h +index 036eb1f5c133..2f01314de73a 100644 +--- a/include/trace/events/sunrpc.h ++++ b/include/trace/events/sunrpc.h +@@ -1141,7 +1141,6 @@ DECLARE_EVENT_CLASS(xprt_writelock_event, + + DEFINE_WRITELOCK_EVENT(reserve_xprt); + DEFINE_WRITELOCK_EVENT(release_xprt); +-DEFINE_WRITELOCK_EVENT(transmit_queued); + + DECLARE_EVENT_CLASS(xprt_cong_event, + TP_PROTO( +diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c +index d616b93751d8..11ebe8a127b8 100644 +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -1469,8 +1469,6 @@ bool xprt_prepare_transmit(struct rpc_task *task) + struct rpc_xprt *xprt = req->rq_xprt; + + if (!xprt_lock_write(xprt, task)) { +- trace_xprt_transmit_queued(xprt, task); +- + /* Race breaker: someone may have transmitted us */ + if (!test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) + rpc_wake_up_queued_task_set_status(&xprt->sending, +-- +2.30.2 + diff --git a/queue-5.12/swiotlb-fix-the-type-of-index.patch b/queue-5.12/swiotlb-fix-the-type-of-index.patch new file mode 100644 index 00000000000..0882cbe3c31 --- /dev/null +++ b/queue-5.12/swiotlb-fix-the-type-of-index.patch @@ -0,0 +1,38 @@ +From 82f7af8523be33b155d0f5023bbe65bd472fc65c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Apr 2021 16:14:53 +0800 +Subject: swiotlb: Fix the type of index + +From: Claire Chang + +[ Upstream commit 95b079d8215b83b37fa59341fda92fcb9392f14a ] + +Fix the type of index from unsigned int to int since find_slots() might +return -1. + +Fixes: 26a7e094783d ("swiotlb: refactor swiotlb_tbl_map_single") +Reviewed-by: Christoph Hellwig +Signed-off-by: Claire Chang +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Sasha Levin +--- + kernel/dma/swiotlb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c +index c10e855a03bc..fe4c01c14ab2 100644 +--- a/kernel/dma/swiotlb.c ++++ b/kernel/dma/swiotlb.c +@@ -608,7 +608,8 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr, + enum dma_data_direction dir, unsigned long attrs) + { + unsigned int offset = swiotlb_align_offset(dev, orig_addr); +- unsigned int index, i; ++ unsigned int i; ++ int index; + phys_addr_t tlb_addr; + + if (no_iotlb_memory) +-- +2.30.2 + diff --git a/queue-5.12/thermal-drivers-tsens-fix-missing-put_device-error.patch b/queue-5.12/thermal-drivers-tsens-fix-missing-put_device-error.patch new file mode 100644 index 00000000000..d8cf12794f9 --- /dev/null +++ b/queue-5.12/thermal-drivers-tsens-fix-missing-put_device-error.patch @@ -0,0 +1,45 @@ +From 7af3070d56f58b3d1cd7a5bb00e81eadc3ec8aae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Apr 2021 20:54:31 +0800 +Subject: thermal/drivers/tsens: Fix missing put_device error + +From: Guangqing Zhu + +[ Upstream commit f4136863e8899fa0554343201b78b9e197c78a78 ] + +Fixes coccicheck error: + +drivers/thermal/qcom/tsens.c:759:4-10: ERROR: missing put_device; call +of_find_device_by_node on line 715, but without a corresponding object +release within this function. + +Fixes: a7ff82976122 ("drivers: thermal: tsens: Merge tsens-common.c into tsens.c") +Signed-off-by: Guangqing Zhu +Reviewed-by: Bjorn Andersson +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20210404125431.12208-1-zhuguangqing83@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/thermal/qcom/tsens.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c +index d8ce3a687b80..3c4c0516e58a 100644 +--- a/drivers/thermal/qcom/tsens.c ++++ b/drivers/thermal/qcom/tsens.c +@@ -755,8 +755,10 @@ int __init init_common(struct tsens_priv *priv) + for (i = VER_MAJOR; i <= VER_STEP; i++) { + priv->rf[i] = devm_regmap_field_alloc(dev, priv->srot_map, + priv->fields[i]); +- if (IS_ERR(priv->rf[i])) +- return PTR_ERR(priv->rf[i]); ++ if (IS_ERR(priv->rf[i])) { ++ ret = PTR_ERR(priv->rf[i]); ++ goto err_put_device; ++ } + } + ret = regmap_field_read(priv->rf[VER_MINOR], &ver_minor); + if (ret) +-- +2.30.2 + diff --git a/queue-5.12/thermal-thermal_of-fix-error-return-code-of-thermal_.patch b/queue-5.12/thermal-thermal_of-fix-error-return-code-of-thermal_.patch new file mode 100644 index 00000000000..73071af0abb --- /dev/null +++ b/queue-5.12/thermal-thermal_of-fix-error-return-code-of-thermal_.patch @@ -0,0 +1,53 @@ +From 88fc8846cc65e11d190705aa8d8de08936e32d7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Mar 2021 04:24:23 -0800 +Subject: thermal: thermal_of: Fix error return code of + thermal_of_populate_bind_params() + +From: Jia-Ju Bai + +[ Upstream commit 45c7eaeb29d67224db4ba935deb575586a1fda09 ] + +When kcalloc() returns NULL to __tcbp or of_count_phandle_with_args() +returns zero or -ENOENT to count, no error return code of +thermal_of_populate_bind_params() is assigned. +To fix these bugs, ret is assigned with -ENOMEM and -ENOENT in these +cases, respectively. + +Fixes: a92bab8919e3 ("of: thermal: Allow multiple devices to share cooling map") +Reported-by: TOTE Robot +Signed-off-by: Jia-Ju Bai +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20210310122423.3266-1-baijiaju1990@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/thermal/thermal_of.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c +index 69ef12f852b7..5b76f9a1280d 100644 +--- a/drivers/thermal/thermal_of.c ++++ b/drivers/thermal/thermal_of.c +@@ -704,14 +704,17 @@ static int thermal_of_populate_bind_params(struct device_node *np, + + count = of_count_phandle_with_args(np, "cooling-device", + "#cooling-cells"); +- if (!count) { ++ if (count <= 0) { + pr_err("Add a cooling_device property with at least one device\n"); ++ ret = -ENOENT; + goto end; + } + + __tcbp = kcalloc(count, sizeof(*__tcbp), GFP_KERNEL); +- if (!__tcbp) ++ if (!__tcbp) { ++ ret = -ENOMEM; + goto end; ++ } + + for (i = 0; i < count; i++) { + ret = of_parse_phandle_with_args(np, "cooling-device", +-- +2.30.2 + diff --git a/queue-5.12/tipc-convert-dest-node-s-address-to-network-order.patch b/queue-5.12/tipc-convert-dest-node-s-address-to-network-order.patch new file mode 100644 index 00000000000..6c729089c67 --- /dev/null +++ b/queue-5.12/tipc-convert-dest-node-s-address-to-network-order.patch @@ -0,0 +1,41 @@ +From 197b24470904d04bc4523748104fb47bbaf9fa5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Mar 2021 10:33:22 +0700 +Subject: tipc: convert dest node's address to network order + +From: Hoang Le + +[ Upstream commit 1980d37565061ab44bdc2f9e4da477d3b9752e81 ] + +(struct tipc_link_info)->dest is in network order (__be32), so we must +convert the value to network order before assigning. The problem detected +by sparse: + +net/tipc/netlink_compat.c:699:24: warning: incorrect type in assignment (different base types) +net/tipc/netlink_compat.c:699:24: expected restricted __be32 [usertype] dest +net/tipc/netlink_compat.c:699:24: got int + +Acked-by: Jon Maloy +Signed-off-by: Hoang Le +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/tipc/netlink_compat.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c +index 5a1ce64039f7..0749df80454d 100644 +--- a/net/tipc/netlink_compat.c ++++ b/net/tipc/netlink_compat.c +@@ -696,7 +696,7 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg, + if (err) + return err; + +- link_info.dest = nla_get_flag(link[TIPC_NLA_LINK_DEST]); ++ link_info.dest = htonl(nla_get_flag(link[TIPC_NLA_LINK_DEST])); + link_info.up = htonl(nla_get_flag(link[TIPC_NLA_LINK_UP])); + nla_strscpy(link_info.str, link[TIPC_NLA_LINK_NAME], + TIPC_MAX_LINK_NAME); +-- +2.30.2 + diff --git a/queue-5.12/virtiofs-fix-userns.patch b/queue-5.12/virtiofs-fix-userns.patch new file mode 100644 index 00000000000..576c3f7b2d2 --- /dev/null +++ b/queue-5.12/virtiofs-fix-userns.patch @@ -0,0 +1,38 @@ +From ec35e93104d106a56b7870bee0ebc739ed532a95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Apr 2021 10:40:58 +0200 +Subject: virtiofs: fix userns + +From: Miklos Szeredi + +[ Upstream commit 0a7419c68a45d2d066b996be5087aa2d07ce80eb ] + +get_user_ns() is done twice (once in virtio_fs_get_tree() and once in +fuse_conn_init()), resulting in a reference leak. + +Also looks better to use fsc->user_ns (which *should* be the +current_user_ns() at this point). + +Signed-off-by: Miklos Szeredi +Signed-off-by: Sasha Levin +--- + fs/fuse/virtio_fs.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c +index 1e5affed158e..005209b1cd50 100644 +--- a/fs/fuse/virtio_fs.c ++++ b/fs/fuse/virtio_fs.c +@@ -1437,8 +1437,7 @@ static int virtio_fs_get_tree(struct fs_context *fsc) + if (!fm) + goto out_err; + +- fuse_conn_init(fc, fm, get_user_ns(current_user_ns()), +- &virtio_fs_fiq_ops, fs); ++ fuse_conn_init(fc, fm, fsc->user_ns, &virtio_fs_fiq_ops, fs); + fc->release = fuse_free_conn; + fc->delete_stale = true; + fc->auto_submounts = true; +-- +2.30.2 + diff --git a/queue-5.12/watchdog-cleanup-handling-of-false-positives.patch b/queue-5.12/watchdog-cleanup-handling-of-false-positives.patch new file mode 100644 index 00000000000..5daf175349b --- /dev/null +++ b/queue-5.12/watchdog-cleanup-handling-of-false-positives.patch @@ -0,0 +1,160 @@ +From 54442bdc9b81e30e6af89b1d3c5eafdc19a8c5ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 22:54:36 -0700 +Subject: watchdog: cleanup handling of false positives + +From: Petr Mladek + +[ Upstream commit 9bf3bc949f8aeefeacea4b1198db833b722a8e27 ] + +Commit d6ad3e286d2c ("softlockup: Add sched_clock_tick() to avoid kernel +warning on kgdb resume") introduced touch_softlockup_watchdog_sync(). + +It solved a problem when the watchdog was touched in an atomic context, +the timer callback was proceed right after releasing interrupts, and the +local clock has not been updated yet. In this case, sched_clock_tick() +was called in watchdog_timer_fn() before updating the timer. + +So far so good. + +Later commit 5d1c0f4a80a6 ("watchdog: add check for suspended vm in +softlockup detector") added two kvm_check_and_clear_guest_paused() +calls. They touch the watchdog when the guest has been sleeping. + +The code makes my head spin around. + +Scenario 1: + + + guest did sleep: + + PVCLOCK_GUEST_STOPPED is set + + + 1st watchdog_timer_fn() invocation: + + the watchdog is not touched yet + + is_softlockup() returns too big delay + + kvm_check_and_clear_guest_paused(): + + clear PVCLOCK_GUEST_STOPPED + + call touch_softlockup_watchdog_sync() + + set SOFTLOCKUP_DELAY_REPORT + + set softlockup_touch_sync + + return from the timer callback + + + 2nd watchdog_timer_fn() invocation: + + + call sched_clock_tick() even though it is not needed. + The timer callback was invoked again only because the clock + has already been updated in the meantime. + + + call kvm_check_and_clear_guest_paused() that does nothing + because PVCLOCK_GUEST_STOPPED has been cleared already. + + + call update_report_ts() and return. This is fine. Except + that sched_clock_tick() might allow to set it already + during the 1st invocation. + +Scenario 2: + + + guest did sleep + + + 1st watchdog_timer_fn() invocation + + same as in 1st scenario + + + guest did sleep again: + + set PVCLOCK_GUEST_STOPPED again + + + 2nd watchdog_timer_fn() invocation + + SOFTLOCKUP_DELAY_REPORT is set from 1st invocation + + call sched_clock_tick() + + call kvm_check_and_clear_guest_paused() + + clear PVCLOCK_GUEST_STOPPED + + call touch_softlockup_watchdog_sync() + + set SOFTLOCKUP_DELAY_REPORT + + set softlockup_touch_sync + + call update_report_ts() (set real timestamp immediately) + + return from the timer callback + + + 3rd watchdog_timer_fn() invocation + + timestamp is set from 2nd invocation + + softlockup_touch_sync is set but not checked because + the real timestamp is already set + +Make the code more straightforward: + +1. Always call kvm_check_and_clear_guest_paused() at the very + beginning to handle PVCLOCK_GUEST_STOPPED. It touches the watchdog + when the quest did sleep. + +2. Handle the situation when the watchdog has been touched + (SOFTLOCKUP_DELAY_REPORT is set). + + Call sched_clock_tick() when touch_*sync() variant was used. It makes + sure that the timestamp will be up to date even when it has been + touched in atomic context or quest did sleep. + +As a result, kvm_check_and_clear_guest_paused() is called on a single +location. And the right timestamp is always set when returning from the +timer callback. + +Link: https://lkml.kernel.org/r/20210311122130.6788-7-pmladek@suse.com +Signed-off-by: Petr Mladek +Cc: Ingo Molnar +Cc: Laurence Oberman +Cc: Michal Hocko +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Vincent Whitchurch +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/watchdog.c | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +diff --git a/kernel/watchdog.c b/kernel/watchdog.c +index 8cf0678378d2..7c397907d0e9 100644 +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -376,7 +376,14 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + /* .. and repeat */ + hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period)); + +- /* Reset the interval when touched externally by a known slow code. */ ++ /* ++ * If a virtual machine is stopped by the host it can look to ++ * the watchdog like a soft lockup. Check to see if the host ++ * stopped the vm before we process the timestamps. ++ */ ++ kvm_check_and_clear_guest_paused(); ++ ++ /* Reset the interval when touched by known problematic code. */ + if (period_ts == SOFTLOCKUP_DELAY_REPORT) { + if (unlikely(__this_cpu_read(softlockup_touch_sync))) { + /* +@@ -387,10 +394,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + sched_clock_tick(); + } + +- /* Clear the guest paused flag on watchdog reset */ +- kvm_check_and_clear_guest_paused(); + update_report_ts(); +- + return HRTIMER_RESTART; + } + +@@ -402,14 +406,6 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + */ + duration = is_softlockup(touch_ts, period_ts); + if (unlikely(duration)) { +- /* +- * If a virtual machine is stopped by the host it can look to +- * the watchdog like a soft lockup, check to see if the host +- * stopped the vm before we issue the warning +- */ +- if (kvm_check_and_clear_guest_paused()) +- return HRTIMER_RESTART; +- + /* + * Prevent multiple soft-lockup reports if one cpu is already + * engaged in dumping all cpu back traces. +-- +2.30.2 + diff --git a/queue-5.12/watchdog-explicitly-update-timestamp-when-reporting-.patch b/queue-5.12/watchdog-explicitly-update-timestamp-when-reporting-.patch new file mode 100644 index 00000000000..0e805d4c887 --- /dev/null +++ b/queue-5.12/watchdog-explicitly-update-timestamp-when-reporting-.patch @@ -0,0 +1,57 @@ +From a95064e228624e7afdf7095f838d56544ec736bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 22:54:23 -0700 +Subject: watchdog: explicitly update timestamp when reporting softlockup + +From: Petr Mladek + +[ Upstream commit c9ad17c991492f4390f42598f6ab0531f87eed07 ] + +The softlockup situation might stay for a long time or even forever. When +it happens, the softlockup debug messages are printed in regular intervals +defined by get_softlockup_thresh(). + +There is a mystery. The repeated message is printed after the full +interval that is defined by get_softlockup_thresh(). But the timer +callback is called more often as defined by sample_period. The code looks +like the soflockup should get reported in every sample_period when it was +once behind the thresh. + +It works only by chance. The watchdog is touched when printing the stall +report, for example, in printk_stack_address(). + +Make the behavior clear and predictable by explicitly updating the +timestamp in watchdog_timer_fn() when the report gets printed. + +Link: https://lkml.kernel.org/r/20210311122130.6788-3-pmladek@suse.com +Signed-off-by: Petr Mladek +Cc: Ingo Molnar +Cc: Laurence Oberman +Cc: Michal Hocko +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Vincent Whitchurch +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/watchdog.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/watchdog.c b/kernel/watchdog.c +index 8440e62bfec4..8efd2a8d9f10 100644 +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -410,6 +410,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + } + } + ++ /* Start period for the next softlockup warning. */ ++ update_touch_ts(); ++ + pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", + smp_processor_id(), duration, + current->comm, task_pid_nr(current)); +-- +2.30.2 + diff --git a/queue-5.12/watchdog-fix-barriers-when-printing-backtraces-from-.patch b/queue-5.12/watchdog-fix-barriers-when-printing-backtraces-from-.patch new file mode 100644 index 00000000000..efb33649489 --- /dev/null +++ b/queue-5.12/watchdog-fix-barriers-when-printing-backtraces-from-.patch @@ -0,0 +1,76 @@ +From ba03c44de5bfb9fe4ec5f923fe5a77293efef83b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 22:54:33 -0700 +Subject: watchdog: fix barriers when printing backtraces from all CPUs + +From: Petr Mladek + +[ Upstream commit 9f113bf760ca90d709f8f89a733d10abb1f04a83 ] + +Any parallel softlockup reports are skipped when one CPU is already +printing backtraces from all CPUs. + +The exclusive rights are synchronized using one bit in +soft_lockup_nmi_warn. There is also one memory barrier that does not make +much sense. + +Use two barriers on the right location to prevent mixing two reports. + +[pmladek@suse.com: use bit lock operations to prevent multiple soft-lockup reports] + Link: https://lkml.kernel.org/r/YFSVsLGVWMXTvlbk@alley + +Link: https://lkml.kernel.org/r/20210311122130.6788-6-pmladek@suse.com +Signed-off-by: Petr Mladek +Acked-by: Peter Zijlstra (Intel) +Cc: Ingo Molnar +Cc: Laurence Oberman +Cc: Michal Hocko +Cc: Thomas Gleixner +Cc: Vincent Whitchurch +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/watchdog.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +diff --git a/kernel/watchdog.c b/kernel/watchdog.c +index b8d4182d14cc..8cf0678378d2 100644 +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -410,11 +410,12 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + if (kvm_check_and_clear_guest_paused()) + return HRTIMER_RESTART; + ++ /* ++ * Prevent multiple soft-lockup reports if one cpu is already ++ * engaged in dumping all cpu back traces. ++ */ + if (softlockup_all_cpu_backtrace) { +- /* Prevent multiple soft-lockup reports if one cpu is already +- * engaged in dumping cpu back traces +- */ +- if (test_and_set_bit(0, &soft_lockup_nmi_warn)) ++ if (test_and_set_bit_lock(0, &soft_lockup_nmi_warn)) + return HRTIMER_RESTART; + } + +@@ -432,14 +433,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + dump_stack(); + + if (softlockup_all_cpu_backtrace) { +- /* Avoid generating two back traces for current +- * given that one is already made above +- */ + trigger_allbutself_cpu_backtrace(); +- +- clear_bit(0, &soft_lockup_nmi_warn); +- /* Barrier to sync with other cpus */ +- smp_mb__after_atomic(); ++ clear_bit_unlock(0, &soft_lockup_nmi_warn); + } + + add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK); +-- +2.30.2 + diff --git a/queue-5.12/watchdog-rename-__touch_watchdog-to-a-better-descrip.patch b/queue-5.12/watchdog-rename-__touch_watchdog-to-a-better-descrip.patch new file mode 100644 index 00000000000..ad388731d99 --- /dev/null +++ b/queue-5.12/watchdog-rename-__touch_watchdog-to-a-better-descrip.patch @@ -0,0 +1,103 @@ +From d2097bd0c156531445ab97f227e4405fac347d42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 22:54:20 -0700 +Subject: watchdog: rename __touch_watchdog() to a better descriptive name + +From: Petr Mladek + +[ Upstream commit 7c0012f522c802d25be102bafe54f333168e6119 ] + +Patch series "watchdog/softlockup: Report overall time and some cleanup", v2. + +I dug deep into the softlockup watchdog history when time permitted this +year. And reworked the patchset that fixed timestamps and cleaned up the +code[2]. + +I split it into very small steps and did even more code clean up. The +result looks quite strightforward and I am pretty confident with the +changes. + +[1] v2: https://lore.kernel.org/r/20201210160038.31441-1-pmladek@suse.com +[2] v1: https://lore.kernel.org/r/20191024114928.15377-1-pmladek@suse.com + +This patch (of 6): + +There are many touch_*watchdog() functions. They are called in situations +where the watchdog could report false positives or create unnecessary +noise. For example, when CPU is entering idle mode, a virtual machine is +stopped, or a lot of messages are printed in the atomic context. + +These functions set SOFTLOCKUP_RESET instead of a real timestamp. It +allows to call them even in a context where jiffies might be outdated. +For example, in an atomic context. + +The real timestamp is set by __touch_watchdog() that is called from the +watchdog timer callback. + +Rename this callback to update_touch_ts(). It better describes the effect +and clearly distinguish is from the other touch_*watchdog() functions. + +Another motivation is that two timestamps are going to be used. One will +be used for the total softlockup time. The other will be used to measure +time since the last report. The new function name will help to +distinguish which timestamp is being updated. + +Link: https://lkml.kernel.org/r/20210311122130.6788-1-pmladek@suse.com +Link: https://lkml.kernel.org/r/20210311122130.6788-2-pmladek@suse.com +Signed-off-by: Petr Mladek +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: Peter Zijlstra +Cc: Laurence Oberman +Cc: Vincent Whitchurch +Cc: Michal Hocko +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/watchdog.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/kernel/watchdog.c b/kernel/watchdog.c +index 107bc38b1945..8440e62bfec4 100644 +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -236,7 +236,7 @@ static void set_sample_period(void) + } + + /* Commands for resetting the watchdog */ +-static void __touch_watchdog(void) ++static void update_touch_ts(void) + { + __this_cpu_write(watchdog_touch_ts, get_timestamp()); + } +@@ -332,7 +332,7 @@ static DEFINE_PER_CPU(struct cpu_stop_work, softlockup_stop_work); + */ + static int softlockup_fn(void *data) + { +- __touch_watchdog(); ++ update_touch_ts(); + complete(this_cpu_ptr(&softlockup_completion)); + + return 0; +@@ -375,7 +375,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + + /* Clear the guest paused flag on watchdog reset */ + kvm_check_and_clear_guest_paused(); +- __touch_watchdog(); ++ update_touch_ts(); + return HRTIMER_RESTART; + } + +@@ -461,7 +461,7 @@ static void watchdog_enable(unsigned int cpu) + HRTIMER_MODE_REL_PINNED_HARD); + + /* Initialize timestamp */ +- __touch_watchdog(); ++ update_touch_ts(); + /* Enable the perf event */ + if (watchdog_enabled & NMI_WATCHDOG_ENABLED) + watchdog_nmi_enable(cpu); +-- +2.30.2 + diff --git a/queue-5.12/watchdog-softlockup-remove-logic-that-tried-to-preve.patch b/queue-5.12/watchdog-softlockup-remove-logic-that-tried-to-preve.patch new file mode 100644 index 00000000000..50ae0b10a73 --- /dev/null +++ b/queue-5.12/watchdog-softlockup-remove-logic-that-tried-to-preve.patch @@ -0,0 +1,110 @@ +From 3474aece0c570b4f9c43fd80d88520f7670a3f96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 22:54:30 -0700 +Subject: watchdog/softlockup: remove logic that tried to prevent repeated + reports + +From: Petr Mladek + +[ Upstream commit 1bc503cb4a2638fb1c57801a7796aca57845ce63 ] + +The softlockup detector does some gymnastic with the variable +soft_watchdog_warn. It was added by the commit 58687acba59266735ad +("lockup_detector: Combine nmi_watchdog and softlockup detector"). + +The purpose is not completely clear. There are the following clues. They +describe the situation how it looked after the above mentioned commit: + + 1. The variable was checked with a comment "only warn once". + + 2. The variable was set when softlockup was reported. It was cleared + only when the CPU was not longer in the softlockup state. + + 3. watchdog_touch_ts was not explicitly updated when the softlockup + was reported. Without this variable, the report would normally + be printed again during every following watchdog_timer_fn() + invocation. + +The logic has got even more tangled up by the commit ed235875e2ca98 +("kernel/watchdog.c: print traces for all cpus on lockup detection"). +After this commit, soft_watchdog_warn is set only when +softlockup_all_cpu_backtrace is enabled. But multiple reports from all +CPUs are prevented by a new variable soft_lockup_nmi_warn. + +Conclusion: + +The variable probably never worked as intended. In each case, it has not +worked last many years because the softlockup was reported repeatedly +after the full period defined by watchdog_thresh. + +The reason is that watchdog gets touched in many known slow paths, for +example, in printk_stack_address(). This code is called also when +printing the softlockup report. It means that the watchdog timestamp gets +updated after each report. + +Solution: + +Simply remove the logic. People want the periodic report anyway. + +Link: https://lkml.kernel.org/r/20210311122130.6788-5-pmladek@suse.com +Signed-off-by: Petr Mladek +Cc: Ingo Molnar +Cc: Laurence Oberman +Cc: Michal Hocko +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Vincent Whitchurch +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/watchdog.c | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +diff --git a/kernel/watchdog.c b/kernel/watchdog.c +index 6bc5113d3d74..b8d4182d14cc 100644 +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -179,7 +179,6 @@ static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts); + static DEFINE_PER_CPU(unsigned long, watchdog_report_ts); + static DEFINE_PER_CPU(struct hrtimer, watchdog_hrtimer); + static DEFINE_PER_CPU(bool, softlockup_touch_sync); +-static DEFINE_PER_CPU(bool, soft_watchdog_warn); + static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts); + static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved); + static unsigned long soft_lockup_nmi_warn; +@@ -411,19 +410,12 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + if (kvm_check_and_clear_guest_paused()) + return HRTIMER_RESTART; + +- /* only warn once */ +- if (__this_cpu_read(soft_watchdog_warn) == true) +- return HRTIMER_RESTART; +- + if (softlockup_all_cpu_backtrace) { + /* Prevent multiple soft-lockup reports if one cpu is already + * engaged in dumping cpu back traces + */ +- if (test_and_set_bit(0, &soft_lockup_nmi_warn)) { +- /* Someone else will report us. Let's give up */ +- __this_cpu_write(soft_watchdog_warn, true); ++ if (test_and_set_bit(0, &soft_lockup_nmi_warn)) + return HRTIMER_RESTART; +- } + } + + /* Start period for the next softlockup warning. */ +@@ -453,9 +445,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK); + if (softlockup_panic) + panic("softlockup: hung tasks"); +- __this_cpu_write(soft_watchdog_warn, true); +- } else +- __this_cpu_write(soft_watchdog_warn, false); ++ } + + return HRTIMER_RESTART; + } +-- +2.30.2 + diff --git a/queue-5.12/watchdog-softlockup-report-the-overall-time-of-softl.patch b/queue-5.12/watchdog-softlockup-report-the-overall-time-of-softl.patch new file mode 100644 index 00000000000..142fdaf345b --- /dev/null +++ b/queue-5.12/watchdog-softlockup-report-the-overall-time-of-softl.patch @@ -0,0 +1,187 @@ +From 5e163ef3642827f25fd37d08216fe59e3086c0ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Apr 2021 22:54:26 -0700 +Subject: watchdog/softlockup: report the overall time of softlockups + +From: Petr Mladek + +[ Upstream commit fef06efc2ebaa94c8aee299b863e870467dbab8d ] + +The softlockup detector currently shows the time spent since the last +report. As a result it is not clear whether a CPU is infinitely hogged by +a single task or if it is a repeated event. + +The situation can be simulated with a simply busy loop: + + while (true) + cpu_relax(); + +The softlockup detector produces: + +[ 168.277520] watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [cat:4865] +[ 196.277604] watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [cat:4865] +[ 236.277522] watchdog: BUG: soft lockup - CPU#1 stuck for 23s! [cat:4865] + +But it should be, something like: + +[ 480.372418] watchdog: BUG: soft lockup - CPU#2 stuck for 26s! [cat:4943] +[ 508.372359] watchdog: BUG: soft lockup - CPU#2 stuck for 52s! [cat:4943] +[ 548.372359] watchdog: BUG: soft lockup - CPU#2 stuck for 89s! [cat:4943] +[ 576.372351] watchdog: BUG: soft lockup - CPU#2 stuck for 115s! [cat:4943] + +For the better output, add an additional timestamp of the last report. +Only this timestamp is reset when the watchdog is intentionally touched +from slow code paths or when printing the report. + +Link: https://lkml.kernel.org/r/20210311122130.6788-4-pmladek@suse.com +Signed-off-by: Petr Mladek +Cc: Ingo Molnar +Cc: Laurence Oberman +Cc: Michal Hocko +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Vincent Whitchurch +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/watchdog.c | 40 ++++++++++++++++++++++++++++------------ + 1 file changed, 28 insertions(+), 12 deletions(-) + +diff --git a/kernel/watchdog.c b/kernel/watchdog.c +index 8efd2a8d9f10..6bc5113d3d74 100644 +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -154,7 +154,11 @@ static void lockup_detector_update_enable(void) + + #ifdef CONFIG_SOFTLOCKUP_DETECTOR + +-#define SOFTLOCKUP_RESET ULONG_MAX ++/* ++ * Delay the soflockup report when running a known slow code. ++ * It does _not_ affect the timestamp of the last successdul reschedule. ++ */ ++#define SOFTLOCKUP_DELAY_REPORT ULONG_MAX + + #ifdef CONFIG_SMP + int __read_mostly sysctl_softlockup_all_cpu_backtrace; +@@ -169,7 +173,10 @@ unsigned int __read_mostly softlockup_panic = + static bool softlockup_initialized __read_mostly; + static u64 __read_mostly sample_period; + ++/* Timestamp taken after the last successful reschedule. */ + static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts); ++/* Timestamp of the last softlockup report. */ ++static DEFINE_PER_CPU(unsigned long, watchdog_report_ts); + static DEFINE_PER_CPU(struct hrtimer, watchdog_hrtimer); + static DEFINE_PER_CPU(bool, softlockup_touch_sync); + static DEFINE_PER_CPU(bool, soft_watchdog_warn); +@@ -235,10 +242,16 @@ static void set_sample_period(void) + watchdog_update_hrtimer_threshold(sample_period); + } + ++static void update_report_ts(void) ++{ ++ __this_cpu_write(watchdog_report_ts, get_timestamp()); ++} ++ + /* Commands for resetting the watchdog */ + static void update_touch_ts(void) + { + __this_cpu_write(watchdog_touch_ts, get_timestamp()); ++ update_report_ts(); + } + + /** +@@ -252,10 +265,10 @@ static void update_touch_ts(void) + notrace void touch_softlockup_watchdog_sched(void) + { + /* +- * Preemption can be enabled. It doesn't matter which CPU's timestamp +- * gets zeroed here, so use the raw_ operation. ++ * Preemption can be enabled. It doesn't matter which CPU's watchdog ++ * report period gets restarted here, so use the raw_ operation. + */ +- raw_cpu_write(watchdog_touch_ts, SOFTLOCKUP_RESET); ++ raw_cpu_write(watchdog_report_ts, SOFTLOCKUP_DELAY_REPORT); + } + + notrace void touch_softlockup_watchdog(void) +@@ -279,7 +292,7 @@ void touch_all_softlockup_watchdogs(void) + * the softlockup check. + */ + for_each_cpu(cpu, &watchdog_allowed_mask) { +- per_cpu(watchdog_touch_ts, cpu) = SOFTLOCKUP_RESET; ++ per_cpu(watchdog_report_ts, cpu) = SOFTLOCKUP_DELAY_REPORT; + wq_watchdog_touch(cpu); + } + } +@@ -287,16 +300,16 @@ void touch_all_softlockup_watchdogs(void) + void touch_softlockup_watchdog_sync(void) + { + __this_cpu_write(softlockup_touch_sync, true); +- __this_cpu_write(watchdog_touch_ts, SOFTLOCKUP_RESET); ++ __this_cpu_write(watchdog_report_ts, SOFTLOCKUP_DELAY_REPORT); + } + +-static int is_softlockup(unsigned long touch_ts) ++static int is_softlockup(unsigned long touch_ts, unsigned long period_ts) + { + unsigned long now = get_timestamp(); + + if ((watchdog_enabled & SOFT_WATCHDOG_ENABLED) && watchdog_thresh){ + /* Warn about unreasonable delays. */ +- if (time_after(now, touch_ts + get_softlockup_thresh())) ++ if (time_after(now, period_ts + get_softlockup_thresh())) + return now - touch_ts; + } + return 0; +@@ -342,6 +355,7 @@ static int softlockup_fn(void *data) + static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + { + unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts); ++ unsigned long period_ts = __this_cpu_read(watchdog_report_ts); + struct pt_regs *regs = get_irq_regs(); + int duration; + int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace; +@@ -363,7 +377,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + /* .. and repeat */ + hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period)); + +- if (touch_ts == SOFTLOCKUP_RESET) { ++ /* Reset the interval when touched externally by a known slow code. */ ++ if (period_ts == SOFTLOCKUP_DELAY_REPORT) { + if (unlikely(__this_cpu_read(softlockup_touch_sync))) { + /* + * If the time stamp was touched atomically +@@ -375,7 +390,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + + /* Clear the guest paused flag on watchdog reset */ + kvm_check_and_clear_guest_paused(); +- update_touch_ts(); ++ update_report_ts(); ++ + return HRTIMER_RESTART; + } + +@@ -385,7 +401,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + * indicate it is getting cpu time. If it hasn't then + * this is a good indication some task is hogging the cpu + */ +- duration = is_softlockup(touch_ts); ++ duration = is_softlockup(touch_ts, period_ts); + if (unlikely(duration)) { + /* + * If a virtual machine is stopped by the host it can look to +@@ -411,7 +427,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) + } + + /* Start period for the next softlockup warning. */ +- update_touch_ts(); ++ update_report_ts(); + + pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", + smp_processor_id(), duration, +-- +2.30.2 + diff --git a/queue-5.12/wilc1000-bring-mac-address-setting-in-line-with-typi.patch b/queue-5.12/wilc1000-bring-mac-address-setting-in-line-with-typi.patch new file mode 100644 index 00000000000..6efab0f7012 --- /dev/null +++ b/queue-5.12/wilc1000-bring-mac-address-setting-in-line-with-typi.patch @@ -0,0 +1,94 @@ +From 02784b1b5ae2f53661708b7d4f6f6e20f8ca6092 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Mar 2021 19:50:07 +0000 +Subject: wilc1000: Bring MAC address setting in line with typical Linux + behavior + +From: David Mosberger-Tang + +[ Upstream commit a381b78a1598dde34a6e40dae2842024308a6ef2 ] + +Linux network drivers normally disallow changing the MAC address when +the interface is up. This driver has been different in that it allows +to change the MAC address *only* when it's up. This patch brings +wilc1000 behavior more in line with other network drivers. We could +have replaced wilc_set_mac_addr() with eth_mac_addr() but that would +break existing documentation on how to change the MAC address. +Likewise, return -EADDRNOTAVAIL (not -EINVAL) when the specified MAC +address is invalid or unavailable. + +Signed-off-by: David Mosberger-Tang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20210303194846.1823596-1-davidm@egauge.net +Signed-off-by: Sasha Levin +--- + .../net/wireless/microchip/wilc1000/netdev.c | 25 ++++++++++++------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c +index 1b205e7d97a8..37f40039e4ca 100644 +--- a/drivers/net/wireless/microchip/wilc1000/netdev.c ++++ b/drivers/net/wireless/microchip/wilc1000/netdev.c +@@ -575,7 +575,6 @@ static int wilc_mac_open(struct net_device *ndev) + { + struct wilc_vif *vif = netdev_priv(ndev); + struct wilc *wl = vif->wilc; +- unsigned char mac_add[ETH_ALEN] = {0}; + int ret = 0; + struct mgmt_frame_regs mgmt_regs = {}; + +@@ -598,9 +597,12 @@ static int wilc_mac_open(struct net_device *ndev) + + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, + vif->idx); +- wilc_get_mac_address(vif, mac_add); +- netdev_dbg(ndev, "Mac address: %pM\n", mac_add); +- ether_addr_copy(ndev->dev_addr, mac_add); ++ ++ if (is_valid_ether_addr(ndev->dev_addr)) ++ wilc_set_mac_address(vif, ndev->dev_addr); ++ else ++ wilc_get_mac_address(vif, ndev->dev_addr); ++ netdev_dbg(ndev, "Mac address: %pM\n", ndev->dev_addr); + + if (!is_valid_ether_addr(ndev->dev_addr)) { + netdev_err(ndev, "Wrong MAC address\n"); +@@ -639,7 +641,14 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p) + int srcu_idx; + + if (!is_valid_ether_addr(addr->sa_data)) +- return -EINVAL; ++ return -EADDRNOTAVAIL; ++ ++ if (!vif->mac_opened) { ++ eth_commit_mac_addr_change(dev, p); ++ return 0; ++ } ++ ++ /* Verify MAC Address is not already in use: */ + + srcu_idx = srcu_read_lock(&wilc->srcu); + list_for_each_entry_rcu(tmp_vif, &wilc->vif_list, list) { +@@ -647,7 +656,7 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p) + if (ether_addr_equal(addr->sa_data, mac_addr)) { + if (vif != tmp_vif) { + srcu_read_unlock(&wilc->srcu, srcu_idx); +- return -EINVAL; ++ return -EADDRNOTAVAIL; + } + srcu_read_unlock(&wilc->srcu, srcu_idx); + return 0; +@@ -659,9 +668,7 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p) + if (result) + return result; + +- ether_addr_copy(vif->bssid, addr->sa_data); +- ether_addr_copy(vif->ndev->dev_addr, addr->sa_data); +- ++ eth_commit_mac_addr_change(dev, p); + return result; + } + +-- +2.30.2 + diff --git a/queue-5.12/wl3501_cs-fix-out-of-bounds-warnings-in-wl3501_mgmt_.patch b/queue-5.12/wl3501_cs-fix-out-of-bounds-warnings-in-wl3501_mgmt_.patch new file mode 100644 index 00000000000..c9afce52134 --- /dev/null +++ b/queue-5.12/wl3501_cs-fix-out-of-bounds-warnings-in-wl3501_mgmt_.patch @@ -0,0 +1,286 @@ +From 0dc35d57eb70ee81fb664de06d5a8e4f138db3d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Apr 2021 18:45:15 -0500 +Subject: wl3501_cs: Fix out-of-bounds warnings in wl3501_mgmt_join + +From: Gustavo A. R. Silva + +[ Upstream commit bb43e5718d8f1b46e7a77e7b39be3c691f293050 ] + +Fix the following out-of-bounds warnings by adding a new structure +wl3501_req instead of duplicating the same members in structure +wl3501_join_req and wl3501_scan_confirm: + +arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [39, 108] from the object at 'sig' is out of the bounds of referenced subobject 'beacon_period' with type 'short unsigned int' at offset 36 [-Warray-bounds] +arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [25, 95] from the object at 'sig' is out of the bounds of referenced subobject 'beacon_period' with type 'short unsigned int' at offset 22 [-Warray-bounds] + +Refactor the code, accordingly: + +$ pahole -C wl3501_req drivers/net/wireless/wl3501_cs.o +struct wl3501_req { + u16 beacon_period; /* 0 2 */ + u16 dtim_period; /* 2 2 */ + u16 cap_info; /* 4 2 */ + u8 bss_type; /* 6 1 */ + u8 bssid[6]; /* 7 6 */ + struct iw_mgmt_essid_pset ssid; /* 13 34 */ + struct iw_mgmt_ds_pset ds_pset; /* 47 3 */ + struct iw_mgmt_cf_pset cf_pset; /* 50 8 */ + struct iw_mgmt_ibss_pset ibss_pset; /* 58 4 */ + struct iw_mgmt_data_rset bss_basic_rset; /* 62 10 */ + + /* size: 72, cachelines: 2, members: 10 */ + /* last cacheline: 8 bytes */ +}; + +$ pahole -C wl3501_join_req drivers/net/wireless/wl3501_cs.o +struct wl3501_join_req { + u16 next_blk; /* 0 2 */ + u8 sig_id; /* 2 1 */ + u8 reserved; /* 3 1 */ + struct iw_mgmt_data_rset operational_rset; /* 4 10 */ + u16 reserved2; /* 14 2 */ + u16 timeout; /* 16 2 */ + u16 probe_delay; /* 18 2 */ + u8 timestamp[8]; /* 20 8 */ + u8 local_time[8]; /* 28 8 */ + struct wl3501_req req; /* 36 72 */ + + /* size: 108, cachelines: 2, members: 10 */ + /* last cacheline: 44 bytes */ +}; + +$ pahole -C wl3501_scan_confirm drivers/net/wireless/wl3501_cs.o +struct wl3501_scan_confirm { + u16 next_blk; /* 0 2 */ + u8 sig_id; /* 2 1 */ + u8 reserved; /* 3 1 */ + u16 status; /* 4 2 */ + char timestamp[8]; /* 6 8 */ + char localtime[8]; /* 14 8 */ + struct wl3501_req req; /* 22 72 */ + /* --- cacheline 1 boundary (64 bytes) was 30 bytes ago --- */ + u8 rssi; /* 94 1 */ + + /* size: 96, cachelines: 2, members: 8 */ + /* padding: 1 */ + /* last cacheline: 32 bytes */ +}; + +The problem is that the original code is trying to copy data into a +bunch of struct members adjacent to each other in a single call to +memcpy(). Now that a new struct wl3501_req enclosing all those adjacent +members is introduced, memcpy() doesn't overrun the length of +&sig.beacon_period and &this->bss_set[i].beacon_period, because the +address of the new struct object _req_ is used as the destination, +instead. + +This helps with the ongoing efforts to globally enable -Warray-bounds +and get us closer to being able to tighten the FORTIFY_SOURCE routines +on memcpy(). + +Link: https://github.com/KSPP/linux/issues/109 +Reported-by: kernel test robot +Signed-off-by: Gustavo A. R. Silva +Reviewed-by: Kees Cook +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1fbaf516da763b50edac47d792a9145aa4482e29.1618442265.git.gustavoars@kernel.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/wl3501.h | 35 +++++++++++-------------- + drivers/net/wireless/wl3501_cs.c | 44 +++++++++++++++++--------------- + 2 files changed, 38 insertions(+), 41 deletions(-) + +diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h +index aa8222cbea68..59b7b93c5963 100644 +--- a/drivers/net/wireless/wl3501.h ++++ b/drivers/net/wireless/wl3501.h +@@ -379,16 +379,7 @@ struct wl3501_get_confirm { + u8 mib_value[100]; + }; + +-struct wl3501_join_req { +- u16 next_blk; +- u8 sig_id; +- u8 reserved; +- struct iw_mgmt_data_rset operational_rset; +- u16 reserved2; +- u16 timeout; +- u16 probe_delay; +- u8 timestamp[8]; +- u8 local_time[8]; ++struct wl3501_req { + u16 beacon_period; + u16 dtim_period; + u16 cap_info; +@@ -401,6 +392,19 @@ struct wl3501_join_req { + struct iw_mgmt_data_rset bss_basic_rset; + }; + ++struct wl3501_join_req { ++ u16 next_blk; ++ u8 sig_id; ++ u8 reserved; ++ struct iw_mgmt_data_rset operational_rset; ++ u16 reserved2; ++ u16 timeout; ++ u16 probe_delay; ++ u8 timestamp[8]; ++ u8 local_time[8]; ++ struct wl3501_req req; ++}; ++ + struct wl3501_join_confirm { + u16 next_blk; + u8 sig_id; +@@ -443,16 +447,7 @@ struct wl3501_scan_confirm { + u16 status; + char timestamp[8]; + char localtime[8]; +- u16 beacon_period; +- u16 dtim_period; +- u16 cap_info; +- u8 bss_type; +- u8 bssid[ETH_ALEN]; +- struct iw_mgmt_essid_pset ssid; +- struct iw_mgmt_ds_pset ds_pset; +- struct iw_mgmt_cf_pset cf_pset; +- struct iw_mgmt_ibss_pset ibss_pset; +- struct iw_mgmt_data_rset bss_basic_rset; ++ struct wl3501_req req; + u8 rssi; + }; + +diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c +index 70307308635f..672f5d5f3f2c 100644 +--- a/drivers/net/wireless/wl3501_cs.c ++++ b/drivers/net/wireless/wl3501_cs.c +@@ -590,7 +590,7 @@ static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas) + struct wl3501_join_req sig = { + .sig_id = WL3501_SIG_JOIN_REQ, + .timeout = 10, +- .ds_pset = { ++ .req.ds_pset = { + .el = { + .id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET, + .len = 1, +@@ -599,7 +599,7 @@ static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas) + }, + }; + +- memcpy(&sig.beacon_period, &this->bss_set[stas].beacon_period, 72); ++ memcpy(&sig.req, &this->bss_set[stas].req, sizeof(sig.req)); + return wl3501_esbq_exec(this, &sig, sizeof(sig)); + } + +@@ -667,35 +667,37 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr) + if (sig.status == WL3501_STATUS_SUCCESS) { + pr_debug("success"); + if ((this->net_type == IW_MODE_INFRA && +- (sig.cap_info & WL3501_MGMT_CAPABILITY_ESS)) || ++ (sig.req.cap_info & WL3501_MGMT_CAPABILITY_ESS)) || + (this->net_type == IW_MODE_ADHOC && +- (sig.cap_info & WL3501_MGMT_CAPABILITY_IBSS)) || ++ (sig.req.cap_info & WL3501_MGMT_CAPABILITY_IBSS)) || + this->net_type == IW_MODE_AUTO) { + if (!this->essid.el.len) + matchflag = 1; + else if (this->essid.el.len == 3 && + !memcmp(this->essid.essid, "ANY", 3)) + matchflag = 1; +- else if (this->essid.el.len != sig.ssid.el.len) ++ else if (this->essid.el.len != sig.req.ssid.el.len) + matchflag = 0; +- else if (memcmp(this->essid.essid, sig.ssid.essid, ++ else if (memcmp(this->essid.essid, sig.req.ssid.essid, + this->essid.el.len)) + matchflag = 0; + else + matchflag = 1; + if (matchflag) { + for (i = 0; i < this->bss_cnt; i++) { +- if (ether_addr_equal_unaligned(this->bss_set[i].bssid, sig.bssid)) { ++ if (ether_addr_equal_unaligned(this->bss_set[i].req.bssid, ++ sig.req.bssid)) { + matchflag = 0; + break; + } + } + } + if (matchflag && (i < 20)) { +- memcpy(&this->bss_set[i].beacon_period, +- &sig.beacon_period, 73); ++ memcpy(&this->bss_set[i].req, ++ &sig.req, sizeof(sig.req)); + this->bss_cnt++; + this->rssi = sig.rssi; ++ this->bss_set[i].rssi = sig.rssi; + } + } + } else if (sig.status == WL3501_STATUS_TIMEOUT) { +@@ -887,19 +889,19 @@ static void wl3501_mgmt_join_confirm(struct net_device *dev, u16 addr) + if (this->join_sta_bss < this->bss_cnt) { + const int i = this->join_sta_bss; + memcpy(this->bssid, +- this->bss_set[i].bssid, ETH_ALEN); +- this->chan = this->bss_set[i].ds_pset.chan; ++ this->bss_set[i].req.bssid, ETH_ALEN); ++ this->chan = this->bss_set[i].req.ds_pset.chan; + iw_copy_mgmt_info_element(&this->keep_essid.el, +- &this->bss_set[i].ssid.el); ++ &this->bss_set[i].req.ssid.el); + wl3501_mgmt_auth(this); + } + } else { + const int i = this->join_sta_bss; + +- memcpy(&this->bssid, &this->bss_set[i].bssid, ETH_ALEN); +- this->chan = this->bss_set[i].ds_pset.chan; ++ memcpy(&this->bssid, &this->bss_set[i].req.bssid, ETH_ALEN); ++ this->chan = this->bss_set[i].req.ds_pset.chan; + iw_copy_mgmt_info_element(&this->keep_essid.el, +- &this->bss_set[i].ssid.el); ++ &this->bss_set[i].req.ssid.el); + wl3501_online(dev); + } + } else { +@@ -1573,30 +1575,30 @@ static int wl3501_get_scan(struct net_device *dev, struct iw_request_info *info, + for (i = 0; i < this->bss_cnt; ++i) { + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; +- memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].bssid, ETH_ALEN); ++ memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].req.bssid, ETH_ALEN); + current_ev = iwe_stream_add_event(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, IW_EV_ADDR_LEN); + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; +- iwe.u.data.length = this->bss_set[i].ssid.el.len; ++ iwe.u.data.length = this->bss_set[i].req.ssid.el.len; + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, +- this->bss_set[i].ssid.essid); ++ this->bss_set[i].req.ssid.essid); + iwe.cmd = SIOCGIWMODE; +- iwe.u.mode = this->bss_set[i].bss_type; ++ iwe.u.mode = this->bss_set[i].req.bss_type; + current_ev = iwe_stream_add_event(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, IW_EV_UINT_LEN); + iwe.cmd = SIOCGIWFREQ; +- iwe.u.freq.m = this->bss_set[i].ds_pset.chan; ++ iwe.u.freq.m = this->bss_set[i].req.ds_pset.chan; + iwe.u.freq.e = 0; + current_ev = iwe_stream_add_event(info, current_ev, + extra + IW_SCAN_MAX_DATA, + &iwe, IW_EV_FREQ_LEN); + iwe.cmd = SIOCGIWENCODE; +- if (this->bss_set[i].cap_info & WL3501_MGMT_CAPABILITY_PRIVACY) ++ if (this->bss_set[i].req.cap_info & WL3501_MGMT_CAPABILITY_PRIVACY) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; +-- +2.30.2 + diff --git a/queue-5.12/wl3501_cs-fix-out-of-bounds-warnings-in-wl3501_send_.patch b/queue-5.12/wl3501_cs-fix-out-of-bounds-warnings-in-wl3501_send_.patch new file mode 100644 index 00000000000..5fa4752b6e1 --- /dev/null +++ b/queue-5.12/wl3501_cs-fix-out-of-bounds-warnings-in-wl3501_send_.patch @@ -0,0 +1,147 @@ +From fe8cfef9d0dd6ee27fbdb1b425bd1cb5569149e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Apr 2021 18:43:19 -0500 +Subject: wl3501_cs: Fix out-of-bounds warnings in wl3501_send_pkt + +From: Gustavo A. R. Silva + +[ Upstream commit 820aa37638a252b57967bdf4038a514b1ab85d45 ] + +Fix the following out-of-bounds warnings by enclosing structure members +daddr and saddr into new struct addr, in structures wl3501_md_req and +wl3501_md_ind: + +arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [18, 23] from the object at 'sig' is out of the bounds of referenced subobject 'daddr' with type 'u8[6]' {aka 'unsigned char[6]'} at offset 11 [-Warray-bounds] +arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [18, 23] from the object at 'sig' is out of the bounds of referenced subobject 'daddr' with type 'u8[6]' {aka 'unsigned char[6]'} at offset 11 [-Warray-bounds] + +Refactor the code, accordingly: + +$ pahole -C wl3501_md_req drivers/net/wireless/wl3501_cs.o +struct wl3501_md_req { + u16 next_blk; /* 0 2 */ + u8 sig_id; /* 2 1 */ + u8 routing; /* 3 1 */ + u16 data; /* 4 2 */ + u16 size; /* 6 2 */ + u8 pri; /* 8 1 */ + u8 service_class; /* 9 1 */ + struct { + u8 daddr[6]; /* 10 6 */ + u8 saddr[6]; /* 16 6 */ + } addr; /* 10 12 */ + + /* size: 22, cachelines: 1, members: 8 */ + /* last cacheline: 22 bytes */ +}; + +$ pahole -C wl3501_md_ind drivers/net/wireless/wl3501_cs.o +struct wl3501_md_ind { + u16 next_blk; /* 0 2 */ + u8 sig_id; /* 2 1 */ + u8 routing; /* 3 1 */ + u16 data; /* 4 2 */ + u16 size; /* 6 2 */ + u8 reception; /* 8 1 */ + u8 pri; /* 9 1 */ + u8 service_class; /* 10 1 */ + struct { + u8 daddr[6]; /* 11 6 */ + u8 saddr[6]; /* 17 6 */ + } addr; /* 11 12 */ + + /* size: 24, cachelines: 1, members: 9 */ + /* padding: 1 */ + /* last cacheline: 24 bytes */ +}; + +The problem is that the original code is trying to copy data into a +couple of arrays adjacent to each other in a single call to memcpy(). +Now that a new struct _addr_ enclosing those two adjacent arrays +is introduced, memcpy() doesn't overrun the length of &sig.daddr[0] +and &sig.daddr, because the address of the new struct object _addr_ +is used, instead. + +This helps with the ongoing efforts to globally enable -Warray-bounds +and get us closer to being able to tighten the FORTIFY_SOURCE routines +on memcpy(). + +Link: https://github.com/KSPP/linux/issues/109 +Reported-by: kernel test robot +Reviewed-by: Kees Cook +Signed-off-by: Gustavo A. R. Silva +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/d260fe56aed7112bff2be5b4d152d03ad7b78e78.1618442265.git.gustavoars@kernel.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/wl3501.h | 12 ++++++++---- + drivers/net/wireless/wl3501_cs.c | 10 ++++++---- + 2 files changed, 14 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h +index e98e04ee9a2c..aa8222cbea68 100644 +--- a/drivers/net/wireless/wl3501.h ++++ b/drivers/net/wireless/wl3501.h +@@ -471,8 +471,10 @@ struct wl3501_md_req { + u16 size; + u8 pri; + u8 service_class; +- u8 daddr[ETH_ALEN]; +- u8 saddr[ETH_ALEN]; ++ struct { ++ u8 daddr[ETH_ALEN]; ++ u8 saddr[ETH_ALEN]; ++ } addr; + }; + + struct wl3501_md_ind { +@@ -484,8 +486,10 @@ struct wl3501_md_ind { + u8 reception; + u8 pri; + u8 service_class; +- u8 daddr[ETH_ALEN]; +- u8 saddr[ETH_ALEN]; ++ struct { ++ u8 daddr[ETH_ALEN]; ++ u8 saddr[ETH_ALEN]; ++ } addr; + }; + + struct wl3501_md_confirm { +diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c +index 8ca5789c7b37..70307308635f 100644 +--- a/drivers/net/wireless/wl3501_cs.c ++++ b/drivers/net/wireless/wl3501_cs.c +@@ -469,6 +469,7 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len) + struct wl3501_md_req sig = { + .sig_id = WL3501_SIG_MD_REQ, + }; ++ size_t sig_addr_len = sizeof(sig.addr); + u8 *pdata = (char *)data; + int rc = -EIO; + +@@ -484,9 +485,9 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len) + goto out; + } + rc = 0; +- memcpy(&sig.daddr[0], pdata, 12); +- pktlen = len - 12; +- pdata += 12; ++ memcpy(&sig.addr, pdata, sig_addr_len); ++ pktlen = len - sig_addr_len; ++ pdata += sig_addr_len; + sig.data = bf; + if (((*pdata) * 256 + (*(pdata + 1))) > 1500) { + u8 addr4[ETH_ALEN] = { +@@ -980,7 +981,8 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev, + } else { + skb->dev = dev; + skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */ +- skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12); ++ skb_copy_to_linear_data(skb, (unsigned char *)&sig.addr, ++ sizeof(sig.addr)); + wl3501_receive(this, skb->data, pkt_len); + skb_put(skb, pkt_len); + skb->protocol = eth_type_trans(skb, dev); +-- +2.30.2 + diff --git a/queue-5.12/xprtrdma-avoid-receive-queue-wrapping.patch b/queue-5.12/xprtrdma-avoid-receive-queue-wrapping.patch new file mode 100644 index 00000000000..2207757293a --- /dev/null +++ b/queue-5.12/xprtrdma-avoid-receive-queue-wrapping.patch @@ -0,0 +1,42 @@ +From faea797f100e64ab2e6bb103b35e3b5d0aa3215c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Apr 2021 14:02:03 -0400 +Subject: xprtrdma: Avoid Receive Queue wrapping + +From: Chuck Lever + +[ Upstream commit 32e6b68167f1d446111c973d57e6f52aee11897a ] + +Commit e340c2d6ef2a ("xprtrdma: Reduce the doorbell rate (Receive)") +increased the number of Receive WRs that are posted by the client, +but did not increase the size of the Receive Queue allocated during +transport set-up. + +This is usually not an issue because RPCRDMA_BACKWARD_WRS is defined +as (32) when SUNRPC_BACKCHANNEL is defined. In cases where it isn't, +there is a real risk of Receive Queue wrapping. + +Fixes: e340c2d6ef2a ("xprtrdma: Reduce the doorbell rate (Receive)") +Signed-off-by: Chuck Lever +Reviewed-by: Tom Talpey +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/xprtrdma/frwr_ops.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c +index 766a1048a48a..132df9b59ab4 100644 +--- a/net/sunrpc/xprtrdma/frwr_ops.c ++++ b/net/sunrpc/xprtrdma/frwr_ops.c +@@ -257,6 +257,7 @@ int frwr_query_device(struct rpcrdma_ep *ep, const struct ib_device *device) + ep->re_attr.cap.max_send_wr += 1; /* for ib_drain_sq */ + ep->re_attr.cap.max_recv_wr = ep->re_max_requests; + ep->re_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS; ++ ep->re_attr.cap.max_recv_wr += RPCRDMA_MAX_RECV_BATCH; + ep->re_attr.cap.max_recv_wr += 1; /* for ib_drain_rq */ + + ep->re_max_rdma_segs = +-- +2.30.2 + diff --git a/queue-5.12/xprtrdma-fix-cwnd-update-ordering.patch b/queue-5.12/xprtrdma-fix-cwnd-update-ordering.patch new file mode 100644 index 00000000000..068d38b3944 --- /dev/null +++ b/queue-5.12/xprtrdma-fix-cwnd-update-ordering.patch @@ -0,0 +1,100 @@ +From 51a511505cad02947f622dae767aa6c45c366852 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Apr 2021 14:02:41 -0400 +Subject: xprtrdma: Fix cwnd update ordering + +From: Chuck Lever + +[ Upstream commit 35d8b10a25884050bb3b0149b62c3818ec59f77c ] + +After a reconnect, the reply handler is opening the cwnd (and thus +enabling more RPC Calls to be sent) /before/ rpcrdma_post_recvs() +can post enough Receive WRs to receive their replies. This causes an +RNR and the new connection is lost immediately. + +The race is most clearly exposed when KASAN and disconnect injection +are enabled. This slows down rpcrdma_rep_create() enough to allow +the send side to post a bunch of RPC Calls before the Receive +completion handler can invoke ib_post_recv(). + +Fixes: 2ae50ad68cd7 ("xprtrdma: Close window between waking RPC senders and posting Receives") +Signed-off-by: Chuck Lever +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/xprtrdma/rpc_rdma.c | 3 ++- + net/sunrpc/xprtrdma/verbs.c | 10 +++++----- + net/sunrpc/xprtrdma/xprt_rdma.h | 2 +- + 3 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c +index 292f066d006e..21ddd78a8c35 100644 +--- a/net/sunrpc/xprtrdma/rpc_rdma.c ++++ b/net/sunrpc/xprtrdma/rpc_rdma.c +@@ -1430,9 +1430,10 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) + credits = 1; /* don't deadlock */ + else if (credits > r_xprt->rx_ep->re_max_requests) + credits = r_xprt->rx_ep->re_max_requests; ++ rpcrdma_post_recvs(r_xprt, credits + (buf->rb_bc_srv_max_requests << 1), ++ false); + if (buf->rb_credits != credits) + rpcrdma_update_cwnd(r_xprt, credits); +- rpcrdma_post_recvs(r_xprt, false); + + req = rpcr_to_rdmar(rqst); + if (unlikely(req->rl_reply)) +diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c +index ec912cf9c618..f3fffc74ab0f 100644 +--- a/net/sunrpc/xprtrdma/verbs.c ++++ b/net/sunrpc/xprtrdma/verbs.c +@@ -535,7 +535,7 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt) + * outstanding Receives. + */ + rpcrdma_ep_get(ep); +- rpcrdma_post_recvs(r_xprt, true); ++ rpcrdma_post_recvs(r_xprt, 1, true); + + rc = rdma_connect(ep->re_id, &ep->re_remote_cma); + if (rc) +@@ -1364,21 +1364,21 @@ int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) + /** + * rpcrdma_post_recvs - Refill the Receive Queue + * @r_xprt: controlling transport instance +- * @temp: mark Receive buffers to be deleted after use ++ * @needed: current credit grant ++ * @temp: mark Receive buffers to be deleted after one use + * + */ +-void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp) ++void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp) + { + struct rpcrdma_buffer *buf = &r_xprt->rx_buf; + struct rpcrdma_ep *ep = r_xprt->rx_ep; + struct ib_recv_wr *wr, *bad_wr; + struct rpcrdma_rep *rep; +- int needed, count, rc; ++ int count, rc; + + rc = 0; + count = 0; + +- needed = buf->rb_credits + (buf->rb_bc_srv_max_requests << 1); + if (likely(ep->re_receive_count > needed)) + goto out; + needed -= ep->re_receive_count; +diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h +index fe3be985e239..28af11fbe643 100644 +--- a/net/sunrpc/xprtrdma/xprt_rdma.h ++++ b/net/sunrpc/xprtrdma/xprt_rdma.h +@@ -461,7 +461,7 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt); + void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt); + + int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); +-void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp); ++void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp); + + /* + * Buffer calls - xprtrdma/verbs.c +-- +2.30.2 + diff --git a/queue-5.12/xprtrdma-rpcrdma_mr_pop-already-does-list_del_init.patch b/queue-5.12/xprtrdma-rpcrdma_mr_pop-already-does-list_del_init.patch new file mode 100644 index 00000000000..60a27ccd713 --- /dev/null +++ b/queue-5.12/xprtrdma-rpcrdma_mr_pop-already-does-list_del_init.patch @@ -0,0 +1,35 @@ +From c5a5aee1d892ace5b731d9500a26ada326932d44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Apr 2021 14:02:54 -0400 +Subject: xprtrdma: rpcrdma_mr_pop() already does list_del_init() + +From: Chuck Lever + +[ Upstream commit 1363e6388c363d0433f9aa4e2f33efe047572687 ] + +The rpcrdma_mr_pop() earlier in the function has already cleared +out mr_list, so it must not be done again in the error path. + +Fixes: 847568942f93 ("xprtrdma: Remove fr_state") +Signed-off-by: Chuck Lever +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/xprtrdma/frwr_ops.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c +index 132df9b59ab4..aca2228095db 100644 +--- a/net/sunrpc/xprtrdma/frwr_ops.c ++++ b/net/sunrpc/xprtrdma/frwr_ops.c +@@ -576,7 +576,6 @@ void frwr_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) + mr = container_of(frwr, struct rpcrdma_mr, frwr); + bad_wr = bad_wr->next; + +- list_del_init(&mr->mr_list); + frwr_mr_recycle(mr); + } + } +-- +2.30.2 + diff --git a/queue-5.12/xsk-fix-for-xp_aligned_validate_desc-when-len-chunk_.patch b/queue-5.12/xsk-fix-for-xp_aligned_validate_desc-when-len-chunk_.patch new file mode 100644 index 00000000000..8da272390f2 --- /dev/null +++ b/queue-5.12/xsk-fix-for-xp_aligned_validate_desc-when-len-chunk_.patch @@ -0,0 +1,54 @@ +From b1eae71fcd03fd47be441ec10628eb1ab5d03c65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Apr 2021 17:44:24 +0800 +Subject: xsk: Fix for xp_aligned_validate_desc() when len == chunk_size + +From: Xuan Zhuo + +[ Upstream commit ac31565c21937eee9117e43c9cd34f557f6f1cb8 ] + +When desc->len is equal to chunk_size, it is legal. But when the +xp_aligned_validate_desc() got chunk_end from desc->addr + desc->len +pointing to the next chunk during the check, it caused the check to +fail. + +This problem was first introduced in bbff2f321a86 ("xsk: new descriptor +addressing scheme"). Later in 2b43470add8c ("xsk: Introduce AF_XDP buffer +allocation API") this piece of code was moved into the new function called +xp_aligned_validate_desc(). This function was then moved into xsk_queue.h +via 26062b185eee ("xsk: Explicitly inline functions and move definitions"). + +Fixes: bbff2f321a86 ("xsk: new descriptor addressing scheme") +Signed-off-by: Xuan Zhuo +Signed-off-by: Daniel Borkmann +Acked-by: Magnus Karlsson +Link: https://lore.kernel.org/bpf/20210428094424.54435-1-xuanzhuo@linux.alibaba.com +Signed-off-by: Sasha Levin +--- + net/xdp/xsk_queue.h | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h +index 2823b7c3302d..40f359bf2044 100644 +--- a/net/xdp/xsk_queue.h ++++ b/net/xdp/xsk_queue.h +@@ -128,13 +128,12 @@ static inline bool xskq_cons_read_addr_unchecked(struct xsk_queue *q, u64 *addr) + static inline bool xp_aligned_validate_desc(struct xsk_buff_pool *pool, + struct xdp_desc *desc) + { +- u64 chunk, chunk_end; ++ u64 chunk; + +- chunk = xp_aligned_extract_addr(pool, desc->addr); +- chunk_end = xp_aligned_extract_addr(pool, desc->addr + desc->len); +- if (chunk != chunk_end) ++ if (desc->len > pool->chunk_size) + return false; + ++ chunk = xp_aligned_extract_addr(pool, desc->addr); + if (chunk >= pool->addrs_cnt) + return false; + +-- +2.30.2 +