From: Sasha Levin Date: Sun, 9 Apr 2023 12:31:03 +0000 (-0400) Subject: Fixes for 6.1 X-Git-Tag: v5.15.107~57 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3674b3e81f4dc6d008b790029c0b54763f528e65;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/alsa-hda-hdmi-preserve-the-previous-pcm-device-upon-.patch b/queue-6.1/alsa-hda-hdmi-preserve-the-previous-pcm-device-upon-.patch new file mode 100644 index 00000000000..f9c607035f0 --- /dev/null +++ b/queue-6.1/alsa-hda-hdmi-preserve-the-previous-pcm-device-upon-.patch @@ -0,0 +1,93 @@ +From c92d80279c6411d649e8ebd5d3110441c2f9ef2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Mar 2023 16:22:17 +0200 +Subject: ALSA: hda/hdmi: Preserve the previous PCM device upon re-enablement + +From: Takashi Iwai + +[ Upstream commit f785f5ee968f7045268b8be6b0abc850c4a4277c ] + +When a DRM driver turns on or off the screen with the audio +capability, it notifies the ELD to HD-audio HDMI codec driver via +component ops. HDMI codec driver, in turn, attaches or detaches the +PCM stream for the given port on the fly. + +The problem is that, since the recent code change, the HDMI driver +always treats the PCM stream assignment dynamically; this ended up the +confusion of the PCM device appearance. e.g. when a screen goes once +off and on again, it may appear on a different PCM device before the +screen-off. Although the application should treat such a change, it +doesn't seem working gracefully with the current pipewire (maybe +PulseAudio, too). + +As a workaround, this patch changes the HDMI codec driver behavior +slightly to be more consistent. Now it remembers the previous PCM +slot for the given port and try to assign to it. That is, if a port +is re-enabled, the driver tries to use the same PCM slot that was +assigned to that port previously. If it conflicts, a new slot is +searched and used like before, instead. + +Note that multiple monitor connections are the only typical case where +the PCM slot preservation is effective. As long as only a single +monitor is connected, the behavior isn't changed, and the first PCM +slot is still assigned always. + +Fixes: ef6f5494faf6 ("ALSA: hda/hdmi: Use only dynamic PCM device allocation") +Reviewed-by: Jaroslav Kysela +Link: https://bugzilla.kernel.org/show_bug.cgi?id=217259 +Link: https://lore.kernel.org/r/20230331142217.19791-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_hdmi.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index 9ea633fe93393..4ffa3a59f419f 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -81,6 +81,7 @@ struct hdmi_spec_per_pin { + struct delayed_work work; + struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/ + int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */ ++ int prev_pcm_idx; /* previously assigned pcm index */ + int repoll_count; + bool setup; /* the stream has been set up by prepare callback */ + bool silent_stream; +@@ -1380,9 +1381,17 @@ static void hdmi_attach_hda_pcm(struct hdmi_spec *spec, + /* pcm already be attached to the pin */ + if (per_pin->pcm) + return; ++ /* try the previously used slot at first */ ++ idx = per_pin->prev_pcm_idx; ++ if (idx >= 0) { ++ if (!test_bit(idx, &spec->pcm_bitmap)) ++ goto found; ++ per_pin->prev_pcm_idx = -1; /* no longer valid, clear it */ ++ } + idx = hdmi_find_pcm_slot(spec, per_pin); + if (idx == -EBUSY) + return; ++ found: + per_pin->pcm_idx = idx; + per_pin->pcm = get_hdmi_pcm(spec, idx); + set_bit(idx, &spec->pcm_bitmap); +@@ -1398,6 +1407,7 @@ static void hdmi_detach_hda_pcm(struct hdmi_spec *spec, + return; + idx = per_pin->pcm_idx; + per_pin->pcm_idx = -1; ++ per_pin->prev_pcm_idx = idx; /* remember the previous index */ + per_pin->pcm = NULL; + if (idx >= 0 && idx < spec->pcm_used) + clear_bit(idx, &spec->pcm_bitmap); +@@ -1924,6 +1934,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) + + per_pin->pcm = NULL; + per_pin->pcm_idx = -1; ++ per_pin->prev_pcm_idx = -1; + per_pin->pin_nid = pin_nid; + per_pin->pin_nid_idx = spec->num_nids; + per_pin->dev_id = i; +-- +2.39.2 + diff --git a/queue-6.1/arm64-compat-work-around-uninitialized-variable-warn.patch b/queue-6.1/arm64-compat-work-around-uninitialized-variable-warn.patch new file mode 100644 index 00000000000..ea6470cc3d1 --- /dev/null +++ b/queue-6.1/arm64-compat-work-around-uninitialized-variable-warn.patch @@ -0,0 +1,93 @@ +From 2145f2a242da6850b2bf93ef2f35a1366f5fbbd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Apr 2023 12:36:25 +0200 +Subject: arm64: compat: Work around uninitialized variable warning + +From: Ard Biesheuvel + +[ Upstream commit 32d85999680601d01b2a36713c9ffd7397c8688b ] + +Dan reports that smatch complains about a potential uninitialized +variable being used in the compat alignment fixup code. + +The logic is not wrong per se, but we do end up using an uninitialized +variable if reading the instruction that triggered the alignment fault +from user space faults, even if the fault ensures that the uninitialized +value doesn't propagate any further. + +Given that we just give up and return 1 if any fault occurs when reading +the instruction, let's get rid of the 'success handling' pattern that +captures the fault in a variable and aborts later, and instead, just +return 1 immediately if any of the get_user() calls result in an +exception. + +Fixes: 3fc24ef32d3b ("arm64: compat: Implement misalignment fixups for multiword loads") +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Link: https://lore.kernel.org/r/202304021214.gekJ8yRc-lkp@intel.com/ +Signed-off-by: Ard Biesheuvel +Link: https://lore.kernel.org/r/20230404103625.2386382-1-ardb@kernel.org +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/kernel/compat_alignment.c | 32 ++++++++++++---------------- + 1 file changed, 14 insertions(+), 18 deletions(-) + +diff --git a/arch/arm64/kernel/compat_alignment.c b/arch/arm64/kernel/compat_alignment.c +index 5edec2f49ec98..deff21bfa6800 100644 +--- a/arch/arm64/kernel/compat_alignment.c ++++ b/arch/arm64/kernel/compat_alignment.c +@@ -314,36 +314,32 @@ int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs) + int (*handler)(unsigned long addr, u32 instr, struct pt_regs *regs); + unsigned int type; + u32 instr = 0; +- u16 tinstr = 0; + int isize = 4; + int thumb2_32b = 0; +- int fault; + + instrptr = instruction_pointer(regs); + + if (compat_thumb_mode(regs)) { + __le16 __user *ptr = (__le16 __user *)(instrptr & ~1); ++ u16 tinstr, tinst2; + +- fault = alignment_get_thumb(regs, ptr, &tinstr); +- if (!fault) { +- if (IS_T32(tinstr)) { +- /* Thumb-2 32-bit */ +- u16 tinst2; +- fault = alignment_get_thumb(regs, ptr + 1, &tinst2); +- instr = ((u32)tinstr << 16) | tinst2; +- thumb2_32b = 1; +- } else { +- isize = 2; +- instr = thumb2arm(tinstr); +- } ++ if (alignment_get_thumb(regs, ptr, &tinstr)) ++ return 1; ++ ++ if (IS_T32(tinstr)) { /* Thumb-2 32-bit */ ++ if (alignment_get_thumb(regs, ptr + 1, &tinst2)) ++ return 1; ++ instr = ((u32)tinstr << 16) | tinst2; ++ thumb2_32b = 1; ++ } else { ++ isize = 2; ++ instr = thumb2arm(tinstr); + } + } else { +- fault = alignment_get_arm(regs, (__le32 __user *)instrptr, &instr); ++ if (alignment_get_arm(regs, (__le32 __user *)instrptr, &instr)) ++ return 1; + } + +- if (fault) +- return 1; +- + switch (CODING_BITS(instr)) { + case 0x00000000: /* 3.13.4 load/store instruction extensions */ + if (LDSTHD_I_BIT(instr)) +-- +2.39.2 + diff --git a/queue-6.1/asoc-codecs-lpass-fix-the-order-or-clks-turn-off-dur.patch b/queue-6.1/asoc-codecs-lpass-fix-the-order-or-clks-turn-off-dur.patch new file mode 100644 index 00000000000..c6550a75174 --- /dev/null +++ b/queue-6.1/asoc-codecs-lpass-fix-the-order-or-clks-turn-off-dur.patch @@ -0,0 +1,84 @@ +From ad0f668ac53be74d79656947739d08660259bed5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Mar 2023 11:01:25 +0000 +Subject: ASoC: codecs: lpass: fix the order or clks turn off during suspend + +From: Srinivas Kandagatla + +[ Upstream commit a4a3203426f4b67535d6442ddc5dca8878a0678f ] + +The order in which clocks are stopped matters as some of the clock +like NPL are derived from MCLK. + +Without this patch, Dragonboard RB5 DSP would crash with below error: + qcom_q6v5_pas 17300000.remoteproc: fatal error received: + ABT_dal.c:278:ABTimeout: AHB Bus hang is detected, + Number of bus hang detected := 2 , addr0 = 0x3370000 , addr1 = 0x0!!! + +Turn off fsgen first, followed by npl and then finally mclk, which is exactly +the opposite order of enable sequence. + +Fixes: 1dc3459009c3 ("ASoC: codecs: lpass: register mclk after runtime pm") +Reported-by: Amit Pundir +Signed-off-by: Srinivas Kandagatla +Tested-by: Amit Pundir +Link: https://lore.kernel.org/r/20230323110125.23790-1-srinivas.kandagatla@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/lpass-rx-macro.c | 4 ++-- + sound/soc/codecs/lpass-tx-macro.c | 4 ++-- + sound/soc/codecs/lpass-wsa-macro.c | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c +index 8621cfabcf5b6..1639f3b66facb 100644 +--- a/sound/soc/codecs/lpass-rx-macro.c ++++ b/sound/soc/codecs/lpass-rx-macro.c +@@ -3667,9 +3667,9 @@ static int __maybe_unused rx_macro_runtime_suspend(struct device *dev) + regcache_cache_only(rx->regmap, true); + regcache_mark_dirty(rx->regmap); + +- clk_disable_unprepare(rx->mclk); +- clk_disable_unprepare(rx->npl); + clk_disable_unprepare(rx->fsgen); ++ clk_disable_unprepare(rx->npl); ++ clk_disable_unprepare(rx->mclk); + + return 0; + } +diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c +index e5611f655beda..d1d9d8d2df2d2 100644 +--- a/sound/soc/codecs/lpass-tx-macro.c ++++ b/sound/soc/codecs/lpass-tx-macro.c +@@ -1946,9 +1946,9 @@ static int __maybe_unused tx_macro_runtime_suspend(struct device *dev) + regcache_cache_only(tx->regmap, true); + regcache_mark_dirty(tx->regmap); + +- clk_disable_unprepare(tx->mclk); +- clk_disable_unprepare(tx->npl); + clk_disable_unprepare(tx->fsgen); ++ clk_disable_unprepare(tx->npl); ++ clk_disable_unprepare(tx->mclk); + + return 0; + } +diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c +index c012033fb69ed..8ed48c86ccb33 100644 +--- a/sound/soc/codecs/lpass-wsa-macro.c ++++ b/sound/soc/codecs/lpass-wsa-macro.c +@@ -2502,9 +2502,9 @@ static int __maybe_unused wsa_macro_runtime_suspend(struct device *dev) + regcache_cache_only(wsa->regmap, true); + regcache_mark_dirty(wsa->regmap); + +- clk_disable_unprepare(wsa->mclk); +- clk_disable_unprepare(wsa->npl); + clk_disable_unprepare(wsa->fsgen); ++ clk_disable_unprepare(wsa->npl); ++ clk_disable_unprepare(wsa->mclk); + + return 0; + } +-- +2.39.2 + diff --git a/queue-6.1/asoc-sof-ipc4-ensure-dsp-is-in-d0i0-during-sof_ipc4_.patch b/queue-6.1/asoc-sof-ipc4-ensure-dsp-is-in-d0i0-during-sof_ipc4_.patch new file mode 100644 index 00000000000..5b9bb9da433 --- /dev/null +++ b/queue-6.1/asoc-sof-ipc4-ensure-dsp-is-in-d0i0-during-sof_ipc4_.patch @@ -0,0 +1,59 @@ +From 0f6ae42630079ca67f2767fdf324eb7e61fec80c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Mar 2023 10:55:38 +0200 +Subject: ASoC: SOF: ipc4: Ensure DSP is in D0I0 during sof_ipc4_set_get_data() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ranjani Sridharan + +[ Upstream commit e51f49512d98783b90799c9cc2002895ec3aa0eb ] + +The set_get_data() IPC op bypasses the check for the no_pm flag as done +with the regular IPC tx_msg op. Since set_get_data should be performed +when the DSP is in D0I0, set the DSP power state to D0I0 before sending +the IPC's in sof_ipc4_set_get_data(). + +Fixes: ceb89acc4dc8 ("ASoC: SOF: ipc4: Add support for mandatory message handling functionality") +Signed-off-by: Ranjani Sridharan +Reviewed-by: Bard Liao +Reviewed-by: Péter Ujfalusi +Reviewed-by: Pierre-Louis Bossart +Signed-off-by: Peter Ujfalusi +Link: https://lore.kernel.org/r/20230322085538.10214-1-peter.ujfalusi@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sof/ipc4.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c +index 6eaa18e27e5af..c08f3960ddd96 100644 +--- a/sound/soc/sof/ipc4.c ++++ b/sound/soc/sof/ipc4.c +@@ -392,6 +392,9 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_ + static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, + size_t payload_bytes, bool set) + { ++ const struct sof_dsp_power_state target_state = { ++ .state = SOF_DSP_PM_D0, ++ }; + size_t payload_limit = sdev->ipc->max_payload_size; + struct sof_ipc4_msg *ipc4_msg = data; + struct sof_ipc4_msg tx = {{ 0 }}; +@@ -422,6 +425,11 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, + + tx.extension |= SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(1); + ++ /* ensure the DSP is in D0i0 before sending IPC */ ++ ret = snd_sof_dsp_set_power_state(sdev, &target_state); ++ if (ret < 0) ++ return ret; ++ + /* Serialise IPC TX */ + mutex_lock(&sdev->ipc->tx_mutex); + +-- +2.39.2 + diff --git a/queue-6.1/drivers-vmbus-check-for-channel-allocation-before-lo.patch b/queue-6.1/drivers-vmbus-check-for-channel-allocation-before-lo.patch new file mode 100644 index 00000000000..dbe1c232bb5 --- /dev/null +++ b/queue-6.1/drivers-vmbus-check-for-channel-allocation-before-lo.patch @@ -0,0 +1,48 @@ +From 0e915617f61fb14dc06a72aa97a02e9ade9b91c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Feb 2023 22:44:11 +0200 +Subject: Drivers: vmbus: Check for channel allocation before looking up relids + +From: Mohammed Gamal + +[ Upstream commit 1eb65c8687316c65140b48fad27133d583178e15 ] + +relid2channel() assumes vmbus channel array to be allocated when called. +However, in cases such as kdump/kexec, not all relids will be reset by the host. +When the second kernel boots and if the guest receives a vmbus interrupt during +vmbus driver initialization before vmbus_connect() is called, before it finishes, +or if it fails, the vmbus interrupt service routine is called which in turn calls +relid2channel() and can cause a null pointer dereference. + +Print a warning and error out in relid2channel() for a channel id that's invalid +in the second kernel. + +Fixes: 8b6a877c060e ("Drivers: hv: vmbus: Replace the per-CPU channel lists with a global array of channels") + +Signed-off-by: Mohammed Gamal +Reviewed-by: Dexuan Cui +Link: https://lore.kernel.org/r/20230217204411.212709-1-mgamal@redhat.com +Signed-off-by: Wei Liu +Signed-off-by: Sasha Levin +--- + drivers/hv/connection.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +index 9dc27e5d367a2..da51b50787dff 100644 +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -409,6 +409,10 @@ void vmbus_disconnect(void) + */ + struct vmbus_channel *relid2channel(u32 relid) + { ++ if (vmbus_connection.channels == NULL) { ++ pr_warn_once("relid2channel: relid=%d: No channels mapped!\n", relid); ++ return NULL; ++ } + if (WARN_ON(relid >= MAX_CHANNEL_RELIDS)) + return NULL; + return READ_ONCE(vmbus_connection.channels[relid]); +-- +2.39.2 + diff --git a/queue-6.1/ethtool-reset-lanes-when-lanes-is-omitted.patch b/queue-6.1/ethtool-reset-lanes-when-lanes-is-omitted.patch new file mode 100644 index 00000000000..e1c988588af --- /dev/null +++ b/queue-6.1/ethtool-reset-lanes-when-lanes-is-omitted.patch @@ -0,0 +1,93 @@ +From 691a58d09ff79de9914f6d3521717c3ff694c822 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 14:20:53 -0700 +Subject: ethtool: reset #lanes when lanes is omitted + +From: Andy Roulin + +[ Upstream commit e847c7675e19ef344913724dc68f83df31ad6a17 ] + +If the number of lanes was forced and then subsequently the user +omits this parameter, the ksettings->lanes is reset. The driver +should then reset the number of lanes to the device's default +for the specified speed. + +However, although the ksettings->lanes is set to 0, the mod variable +is not set to true to indicate the driver and userspace should be +notified of the changes. + +The consequence is that the same ethtool operation will produce +different results based on the initial state. + +If the initial state is: +$ ethtool swp1 | grep -A 3 'Speed: ' + Speed: 500000Mb/s + Lanes: 2 + Duplex: Full + Auto-negotiation: on + +then executing 'ethtool -s swp1 speed 50000 autoneg off' will yield: +$ ethtool swp1 | grep -A 3 'Speed: ' + Speed: 500000Mb/s + Lanes: 2 + Duplex: Full + Auto-negotiation: off + +While if the initial state is: +$ ethtool swp1 | grep -A 3 'Speed: ' + Speed: 500000Mb/s + Lanes: 1 + Duplex: Full + Auto-negotiation: off + +executing the same 'ethtool -s swp1 speed 50000 autoneg off' results in: +$ ethtool swp1 | grep -A 3 'Speed: ' + Speed: 500000Mb/s + Lanes: 1 + Duplex: Full + Auto-negotiation: off + +This patch fixes this behavior. Omitting lanes will always results in +the driver choosing the default lane width for the chosen speed. In this +scenario, regardless of the initial state, the end state will be, e.g., + +$ ethtool swp1 | grep -A 3 'Speed: ' + Speed: 500000Mb/s + Lanes: 2 + Duplex: Full + Auto-negotiation: off + +Fixes: 012ce4dd3102 ("ethtool: Extend link modes settings uAPI with lanes") +Signed-off-by: Andy Roulin +Reviewed-by: Danielle Ratson +Reviewed-by: Ido Schimmel +Link: https://lore.kernel.org/r/ac238d6b-8726-8156-3810-6471291dbc7f@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ethtool/linkmodes.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/net/ethtool/linkmodes.c b/net/ethtool/linkmodes.c +index 126e06c713a3a..2d91f2a8c7626 100644 +--- a/net/ethtool/linkmodes.c ++++ b/net/ethtool/linkmodes.c +@@ -282,11 +282,12 @@ static int ethnl_update_linkmodes(struct genl_info *info, struct nlattr **tb, + "lanes configuration not supported by device"); + return -EOPNOTSUPP; + } +- } else if (!lsettings->autoneg) { +- /* If autoneg is off and lanes parameter is not passed from user, +- * set the lanes parameter to 0. ++ } else if (!lsettings->autoneg && ksettings->lanes) { ++ /* If autoneg is off and lanes parameter is not passed from user but ++ * it was defined previously then set the lanes parameter to 0. + */ + ksettings->lanes = 0; ++ *mod = true; + } + + ret = ethnl_update_bitset(ksettings->link_modes.advertising, +-- +2.39.2 + diff --git a/queue-6.1/gpio-davinci-add-irq-chip-flag-to-skip-set-wake.patch b/queue-6.1/gpio-davinci-add-irq-chip-flag-to-skip-set-wake.patch new file mode 100644 index 00000000000..7081a36c387 --- /dev/null +++ b/queue-6.1/gpio-davinci-add-irq-chip-flag-to-skip-set-wake.patch @@ -0,0 +1,37 @@ +From e8bb27039820308c8942f70c1d4690e736017a17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 12:54:43 +0530 +Subject: gpio: davinci: Add irq chip flag to skip set wake + +From: Dhruva Gole + +[ Upstream commit 7b75c4703609a3ebaf67271813521bc0281e1ec1 ] + +Add the IRQCHIP_SKIP_SET_WAKE flag since there are no special IRQ Wake +bits that can be set to enable wakeup IRQ. + +Fixes: 3d9edf09d452 ("[ARM] 4457/2: davinci: GPIO support") +Signed-off-by: Dhruva Gole +Reviewed-by: Linus Walleij +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-davinci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c +index 7aff8a65002c9..69f3d864f69d3 100644 +--- a/drivers/gpio/gpio-davinci.c ++++ b/drivers/gpio/gpio-davinci.c +@@ -328,7 +328,7 @@ static struct irq_chip gpio_irqchip = { + .irq_enable = gpio_irq_enable, + .irq_disable = gpio_irq_disable, + .irq_set_type = gpio_irq_type, +- .flags = IRQCHIP_SET_TYPE_MASKED, ++ .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE, + }; + + static void gpio_irq_handler(struct irq_desc *desc) +-- +2.39.2 + diff --git a/queue-6.1/gpio-davinci-do-not-clear-the-bank-intr-enable-bit-i.patch b/queue-6.1/gpio-davinci-do-not-clear-the-bank-intr-enable-bit-i.patch new file mode 100644 index 00000000000..bd667079fa1 --- /dev/null +++ b/queue-6.1/gpio-davinci-do-not-clear-the-bank-intr-enable-bit-i.patch @@ -0,0 +1,43 @@ +From 558da05a58ac760f020e15adbaaf40d019965040 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 12:54:42 +0530 +Subject: gpio: davinci: Do not clear the bank intr enable bit in save_context + +From: Dhruva Gole + +[ Upstream commit fe092498cb9638418c96675be320c74a16306b48 ] + +The interrupt enable bits might be set if we want to use the GPIO as +wakeup source. Clearing this will mean disabling of interrupts in the GPIO +banks that we may want to wakeup from. +Thus remove the line that was clearing this bit from the driver's save +context function. + +Cc: Devarsh Thakkar +Fixes: 0651a730924b ("gpio: davinci: Add support for system suspend/resume PM") +Signed-off-by: Dhruva Gole +Reviewed-by: Linus Walleij +Acked-by: Keerthy +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-davinci.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c +index 59c4c48d8296b..7aff8a65002c9 100644 +--- a/drivers/gpio/gpio-davinci.c ++++ b/drivers/gpio/gpio-davinci.c +@@ -645,9 +645,6 @@ static void davinci_gpio_save_context(struct davinci_gpio_controller *chips, + context->set_falling = readl_relaxed(&g->set_falling); + } + +- /* Clear Bank interrupt enable bit */ +- writel_relaxed(0, base + BINTEN); +- + /* Clear all interrupt status registers */ + writel_relaxed(GENMASK(31, 0), &g->intstat); + } +-- +2.39.2 + diff --git a/queue-6.1/gpio-gpio_regmap-select-regmap-instead-of-depending-.patch b/queue-6.1/gpio-gpio_regmap-select-regmap-instead-of-depending-.patch new file mode 100644 index 00000000000..2f7d12c8a90 --- /dev/null +++ b/queue-6.1/gpio-gpio_regmap-select-regmap-instead-of-depending-.patch @@ -0,0 +1,47 @@ +From 4fbc152c6a8d96e8f33cd1b9007544e66aec3369 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 25 Feb 2023 21:39:48 -0800 +Subject: gpio: GPIO_REGMAP: select REGMAP instead of depending on it + +From: Randy Dunlap + +[ Upstream commit d49765b5f4320a402fbc4ed5edfd73d87640f27c ] + +REGMAP is a hidden (not user visible) symbol. Users cannot set it +directly thru "make *config", so drivers should select it instead of +depending on it if they need it. + +Consistently using "select" or "depends on" can also help reduce +Kconfig circular dependency issues. + +Therefore, change the use of "depends on REGMAP" to "select REGMAP". + +Fixes: ebe363197e52 ("gpio: add a reusable generic gpio_chip using regmap") +Signed-off-by: Randy Dunlap +Cc: Michael Walle +Cc: Linus Walleij +Cc: Bartosz Golaszewski +Cc: linux-gpio@vger.kernel.org +Acked-by: Michael Walle +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index a01af11806164..e3af86f06c630 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -100,7 +100,7 @@ config GPIO_GENERIC + tristate + + config GPIO_REGMAP +- depends on REGMAP ++ select REGMAP + tristate + + # put drivers in the right section, in alphabetical order +-- +2.39.2 + diff --git a/queue-6.1/gve-secure-enough-bytes-in-the-first-tx-desc-for-all.patch b/queue-6.1/gve-secure-enough-bytes-in-the-first-tx-desc-for-all.patch new file mode 100644 index 00000000000..d2f9f091765 --- /dev/null +++ b/queue-6.1/gve-secure-enough-bytes-in-the-first-tx-desc-for-all.patch @@ -0,0 +1,73 @@ +From 97b276094f248177717f4a8b9070abd0345053a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 10:28:09 -0700 +Subject: gve: Secure enough bytes in the first TX desc for all TCP pkts + +From: Shailend Chand + +[ Upstream commit 3ce9345580974863c060fa32971537996a7b2d57 ] + +Non-GSO TCP packets whose SKBs' linear portion did not include the +entire TCP header were not populating the first Tx descriptor with +as many bytes as the vNIC expected. This change ensures that all +TCP packets populate the first descriptor with the correct number of +bytes. + +Fixes: 893ce44df565 ("gve: Add basic driver framework for Compute Engine Virtual NIC") +Signed-off-by: Shailend Chand +Link: https://lore.kernel.org/r/20230403172809.2939306-1-shailend@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/google/gve/gve.h | 2 ++ + drivers/net/ethernet/google/gve/gve_tx.c | 12 +++++------- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h +index 160735484465a..458149a77ebe6 100644 +--- a/drivers/net/ethernet/google/gve/gve.h ++++ b/drivers/net/ethernet/google/gve/gve.h +@@ -47,6 +47,8 @@ + + #define GVE_RX_BUFFER_SIZE_DQO 2048 + ++#define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182 ++ + /* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */ + struct gve_rx_desc_queue { + struct gve_rx_desc *desc_ring; /* the descriptor ring */ +diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c +index 4888bf05fbedb..5e11b82367545 100644 +--- a/drivers/net/ethernet/google/gve/gve_tx.c ++++ b/drivers/net/ethernet/google/gve/gve_tx.c +@@ -284,8 +284,8 @@ static inline int gve_skb_fifo_bytes_required(struct gve_tx_ring *tx, + int bytes; + int hlen; + +- hlen = skb_is_gso(skb) ? skb_checksum_start_offset(skb) + +- tcp_hdrlen(skb) : skb_headlen(skb); ++ hlen = skb_is_gso(skb) ? skb_checksum_start_offset(skb) + tcp_hdrlen(skb) : ++ min_t(int, GVE_GQ_TX_MIN_PKT_DESC_BYTES, skb->len); + + pad_bytes = gve_tx_fifo_pad_alloc_one_frag(&tx->tx_fifo, + hlen); +@@ -454,13 +454,11 @@ static int gve_tx_add_skb_copy(struct gve_priv *priv, struct gve_tx_ring *tx, st + pkt_desc = &tx->desc[idx]; + + l4_hdr_offset = skb_checksum_start_offset(skb); +- /* If the skb is gso, then we want the tcp header in the first segment +- * otherwise we want the linear portion of the skb (which will contain +- * the checksum because skb->csum_start and skb->csum_offset are given +- * relative to skb->head) in the first segment. ++ /* If the skb is gso, then we want the tcp header alone in the first segment ++ * otherwise we want the minimum required by the gVNIC spec. + */ + hlen = is_gso ? l4_hdr_offset + tcp_hdrlen(skb) : +- skb_headlen(skb); ++ min_t(int, GVE_GQ_TX_MIN_PKT_DESC_BYTES, skb->len); + + info->skb = skb; + /* We don't want to split the header, so if necessary, pad to the end +-- +2.39.2 + diff --git a/queue-6.1/ice-fix-wrong-fallback-logic-for-fdir.patch b/queue-6.1/ice-fix-wrong-fallback-logic-for-fdir.patch new file mode 100644 index 00000000000..9073a8b22a7 --- /dev/null +++ b/queue-6.1/ice-fix-wrong-fallback-logic-for-fdir.patch @@ -0,0 +1,59 @@ +From 88dd0e96712cadc92d937aed37738fb0947c4cf9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Mar 2023 10:24:15 +0800 +Subject: ice: fix wrong fallback logic for FDIR + +From: Simei Su + +[ Upstream commit b4a01ace20f5c93c724abffc0a83ec84f514b98d ] + +When adding a FDIR filter, if ice_vc_fdir_set_irq_ctx returns failure, +the inserted fdir entry will not be removed and if ice_vc_fdir_write_fltr +returns failure, the fdir context info for irq handler will not be cleared +which may lead to inconsistent or memory leak issue. This patch refines +failure cases to resolve this issue. + +Fixes: 1f7ea1cd6a37 ("ice: Enable FDIR Configure for AVF") +Signed-off-by: Simei Su +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +index a2645ff3100e4..f4ef76e37098c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +@@ -1871,7 +1871,7 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg) + v_ret = VIRTCHNL_STATUS_SUCCESS; + stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; + dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id); +- goto err_free_conf; ++ goto err_rem_entry; + } + + ret = ice_vc_fdir_write_fltr(vf, conf, true, is_tun); +@@ -1880,15 +1880,16 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg) + stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE; + dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n", + vf->vf_id, ret); +- goto err_rem_entry; ++ goto err_clr_irq; + } + + exit: + kfree(stat); + return ret; + +-err_rem_entry: ++err_clr_irq: + ice_vc_fdir_clear_irq_ctx(vf); ++err_rem_entry: + ice_vc_fdir_remove_entry(vf, conf, conf->flow_id); + err_free_conf: + devm_kfree(dev, conf); +-- +2.39.2 + diff --git a/queue-6.1/ice-reset-fdir-counter-in-fdir-init-stage.patch b/queue-6.1/ice-reset-fdir-counter-in-fdir-init-stage.patch new file mode 100644 index 00000000000..eca412aff32 --- /dev/null +++ b/queue-6.1/ice-reset-fdir-counter-in-fdir-init-stage.patch @@ -0,0 +1,61 @@ +From 0cc3fb3fa82fc7a6af6be441926ac800b2ca5d8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Mar 2023 10:49:11 +0000 +Subject: ice: Reset FDIR counter in FDIR init stage + +From: Lingyu Liu + +[ Upstream commit 83c911dc5e0e8e6eaa6431c06972a8f159bfe2fc ] + +Reset the FDIR counters when FDIR inits. Without this patch, +when VF initializes or resets, all the FDIR counters are not +cleaned, which may cause unexpected behaviors for future FDIR +rule create (e.g., rule conflict). + +Fixes: 1f7ea1cd6a37 ("ice: Enable FDIR Configure for AVF") +Signed-off-by: Junfeng Guo +Signed-off-by: Lingyu Liu +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + .../net/ethernet/intel/ice/ice_virtchnl_fdir.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +index f4ef76e37098c..7f72604079723 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +@@ -541,6 +541,21 @@ static void ice_vc_fdir_rem_prof_all(struct ice_vf *vf) + } + } + ++/** ++ * ice_vc_fdir_reset_cnt_all - reset all FDIR counters for this VF FDIR ++ * @fdir: pointer to the VF FDIR structure ++ */ ++static void ice_vc_fdir_reset_cnt_all(struct ice_vf_fdir *fdir) ++{ ++ enum ice_fltr_ptype flow; ++ ++ for (flow = ICE_FLTR_PTYPE_NONF_NONE; ++ flow < ICE_FLTR_PTYPE_MAX; flow++) { ++ fdir->fdir_fltr_cnt[flow][0] = 0; ++ fdir->fdir_fltr_cnt[flow][1] = 0; ++ } ++} ++ + /** + * ice_vc_fdir_has_prof_conflict + * @vf: pointer to the VF structure +@@ -1998,6 +2013,7 @@ void ice_vf_fdir_init(struct ice_vf *vf) + spin_lock_init(&fdir->ctx_lock); + fdir->ctx_irq.flags = 0; + fdir->ctx_done.flags = 0; ++ ice_vc_fdir_reset_cnt_all(fdir); + } + + /** +-- +2.39.2 + diff --git a/queue-6.1/icmp-guard-against-too-small-mtu.patch b/queue-6.1/icmp-guard-against-too-small-mtu.patch new file mode 100644 index 00000000000..350b1784317 --- /dev/null +++ b/queue-6.1/icmp-guard-against-too-small-mtu.patch @@ -0,0 +1,86 @@ +From 531a15e1fd7a2c54bb78320a476c74749ad04e1a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Mar 2023 17:45:02 +0000 +Subject: icmp: guard against too small mtu + +From: Eric Dumazet + +[ Upstream commit 7d63b67125382ff0ffdfca434acbc94a38bd092b ] + +syzbot was able to trigger a panic [1] in icmp_glue_bits(), or +more exactly in skb_copy_and_csum_bits() + +There is no repro yet, but I think the issue is that syzbot +manages to lower device mtu to a small value, fooling __icmp_send() + +__icmp_send() must make sure there is enough room for the +packet to include at least the headers. + +We might in the future refactor skb_copy_and_csum_bits() and its +callers to no longer crash when something bad happens. + +[1] +kernel BUG at net/core/skbuff.c:3343 ! +invalid opcode: 0000 [#1] PREEMPT SMP KASAN +CPU: 0 PID: 15766 Comm: syz-executor.0 Not tainted 6.3.0-rc4-syzkaller-00039-gffe78bbd5121 #0 +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.14.0-2 04/01/2014 +RIP: 0010:skb_copy_and_csum_bits+0x798/0x860 net/core/skbuff.c:3343 +Code: f0 c1 c8 08 41 89 c6 e9 73 ff ff ff e8 61 48 d4 f9 e9 41 fd ff ff 48 8b 7c 24 48 e8 52 48 d4 f9 e9 c3 fc ff ff e8 c8 27 84 f9 <0f> 0b 48 89 44 24 28 e8 3c 48 d4 f9 48 8b 44 24 28 e9 9d fb ff ff +RSP: 0018:ffffc90000007620 EFLAGS: 00010246 +RAX: 0000000000000000 RBX: 00000000000001e8 RCX: 0000000000000100 +RDX: ffff8880276f6280 RSI: ffffffff87fdd138 RDI: 0000000000000005 +RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000000 +R10: 00000000000001e8 R11: 0000000000000001 R12: 000000000000003c +R13: 0000000000000000 R14: ffff888028244868 R15: 0000000000000b0e +FS: 00007fbc81f1c700(0000) GS:ffff88802ca00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000001b2df43000 CR3: 00000000744db000 CR4: 0000000000150ef0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + +icmp_glue_bits+0x7b/0x210 net/ipv4/icmp.c:353 +__ip_append_data+0x1d1b/0x39f0 net/ipv4/ip_output.c:1161 +ip_append_data net/ipv4/ip_output.c:1343 [inline] +ip_append_data+0x115/0x1a0 net/ipv4/ip_output.c:1322 +icmp_push_reply+0xa8/0x440 net/ipv4/icmp.c:370 +__icmp_send+0xb80/0x1430 net/ipv4/icmp.c:765 +ipv4_send_dest_unreach net/ipv4/route.c:1239 [inline] +ipv4_link_failure+0x5a9/0x9e0 net/ipv4/route.c:1246 +dst_link_failure include/net/dst.h:423 [inline] +arp_error_report+0xcb/0x1c0 net/ipv4/arp.c:296 +neigh_invalidate+0x20d/0x560 net/core/neighbour.c:1079 +neigh_timer_handler+0xc77/0xff0 net/core/neighbour.c:1166 +call_timer_fn+0x1a0/0x580 kernel/time/timer.c:1700 +expire_timers+0x29b/0x4b0 kernel/time/timer.c:1751 +__run_timers kernel/time/timer.c:2022 [inline] + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+d373d60fddbdc915e666@syzkaller.appspotmail.com +Signed-off-by: Eric Dumazet +Link: https://lore.kernel.org/r/20230330174502.1915328-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index d5d745c3e345b..2b09ef70752f9 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -746,6 +746,11 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, + room = 576; + room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen; + room -= sizeof(struct icmphdr); ++ /* Guard against tiny mtu. We need to include at least one ++ * IP network header for this message to make any sense. ++ */ ++ if (room <= (int)sizeof(struct iphdr)) ++ goto ende; + + icmp_param.data_len = skb_in->len - icmp_param.offset; + if (icmp_param.data_len > room) +-- +2.39.2 + diff --git a/queue-6.1/ipv6-fix-an-uninit-variable-access-bug-in-__ip6_make.patch b/queue-6.1/ipv6-fix-an-uninit-variable-access-bug-in-__ip6_make.patch new file mode 100644 index 00000000000..742d9ded13a --- /dev/null +++ b/queue-6.1/ipv6-fix-an-uninit-variable-access-bug-in-__ip6_make.patch @@ -0,0 +1,101 @@ +From 13595a2cba10ce391349efef1e9be9f01a1a22df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 15:34:17 +0800 +Subject: ipv6: Fix an uninit variable access bug in __ip6_make_skb() + +From: Ziyang Xuan + +[ Upstream commit ea30388baebcce37fd594d425a65037ca35e59e8 ] + +Syzbot reported a bug as following: + +===================================================== +BUG: KMSAN: uninit-value in arch_atomic64_inc arch/x86/include/asm/atomic64_64.h:88 [inline] +BUG: KMSAN: uninit-value in arch_atomic_long_inc include/linux/atomic/atomic-long.h:161 [inline] +BUG: KMSAN: uninit-value in atomic_long_inc include/linux/atomic/atomic-instrumented.h:1429 [inline] +BUG: KMSAN: uninit-value in __ip6_make_skb+0x2f37/0x30f0 net/ipv6/ip6_output.c:1956 + arch_atomic64_inc arch/x86/include/asm/atomic64_64.h:88 [inline] + arch_atomic_long_inc include/linux/atomic/atomic-long.h:161 [inline] + atomic_long_inc include/linux/atomic/atomic-instrumented.h:1429 [inline] + __ip6_make_skb+0x2f37/0x30f0 net/ipv6/ip6_output.c:1956 + ip6_finish_skb include/net/ipv6.h:1122 [inline] + ip6_push_pending_frames+0x10e/0x550 net/ipv6/ip6_output.c:1987 + rawv6_push_pending_frames+0xb12/0xb90 net/ipv6/raw.c:579 + rawv6_sendmsg+0x297e/0x2e60 net/ipv6/raw.c:922 + inet_sendmsg+0x101/0x180 net/ipv4/af_inet.c:827 + sock_sendmsg_nosec net/socket.c:714 [inline] + sock_sendmsg net/socket.c:734 [inline] + ____sys_sendmsg+0xa8e/0xe70 net/socket.c:2476 + ___sys_sendmsg+0x2a1/0x3f0 net/socket.c:2530 + __sys_sendmsg net/socket.c:2559 [inline] + __do_sys_sendmsg net/socket.c:2568 [inline] + __se_sys_sendmsg net/socket.c:2566 [inline] + __x64_sys_sendmsg+0x367/0x540 net/socket.c:2566 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +Uninit was created at: + slab_post_alloc_hook mm/slab.h:766 [inline] + slab_alloc_node mm/slub.c:3452 [inline] + __kmem_cache_alloc_node+0x71f/0xce0 mm/slub.c:3491 + __do_kmalloc_node mm/slab_common.c:967 [inline] + __kmalloc_node_track_caller+0x114/0x3b0 mm/slab_common.c:988 + kmalloc_reserve net/core/skbuff.c:492 [inline] + __alloc_skb+0x3af/0x8f0 net/core/skbuff.c:565 + alloc_skb include/linux/skbuff.h:1270 [inline] + __ip6_append_data+0x51c1/0x6bb0 net/ipv6/ip6_output.c:1684 + ip6_append_data+0x411/0x580 net/ipv6/ip6_output.c:1854 + rawv6_sendmsg+0x2882/0x2e60 net/ipv6/raw.c:915 + inet_sendmsg+0x101/0x180 net/ipv4/af_inet.c:827 + sock_sendmsg_nosec net/socket.c:714 [inline] + sock_sendmsg net/socket.c:734 [inline] + ____sys_sendmsg+0xa8e/0xe70 net/socket.c:2476 + ___sys_sendmsg+0x2a1/0x3f0 net/socket.c:2530 + __sys_sendmsg net/socket.c:2559 [inline] + __do_sys_sendmsg net/socket.c:2568 [inline] + __se_sys_sendmsg net/socket.c:2566 [inline] + __x64_sys_sendmsg+0x367/0x540 net/socket.c:2566 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +It is because icmp6hdr does not in skb linear region under the scenario +of SOCK_RAW socket. Access icmp6_hdr(skb)->icmp6_type directly will +trigger the uninit variable access bug. + +Use a local variable icmp6_type to carry the correct value in different +scenarios. + +Fixes: 14878f75abd5 ("[IPV6]: Add ICMPMsgStats MIB (RFC 4293) [rev 2]") +Reported-by: syzbot+8257f4dcef79de670baf@syzkaller.appspotmail.com +Link: https://syzkaller.appspot.com/bug?id=3d605ec1d0a7f2a269a1a6936ac7f2b85975ee9c +Signed-off-by: Ziyang Xuan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_output.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index c314fdde0097c..95a55c6630add 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1965,8 +1965,13 @@ struct sk_buff *__ip6_make_skb(struct sock *sk, + IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); + if (proto == IPPROTO_ICMPV6) { + struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); ++ u8 icmp6_type; + +- ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type); ++ if (sk->sk_socket->type == SOCK_RAW && !inet_sk(sk)->hdrincl) ++ icmp6_type = fl6->fl6_icmp_type; ++ else ++ icmp6_type = icmp6_hdr(skb)->icmp6_type; ++ ICMP6MSGOUT_INC_STATS(net, idev, icmp6_type); + ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); + } + +-- +2.39.2 + diff --git a/queue-6.1/kvm-s390-pv-fix-external-interruption-loop-not-alway.patch b/queue-6.1/kvm-s390-pv-fix-external-interruption-loop-not-alway.patch new file mode 100644 index 00000000000..8f99fde2909 --- /dev/null +++ b/queue-6.1/kvm-s390-pv-fix-external-interruption-loop-not-alway.patch @@ -0,0 +1,100 @@ +From bbb8dc8e54dfa03ff8628faa460f2177f22808cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Feb 2023 09:55:20 +0100 +Subject: KVM: s390: pv: fix external interruption loop not always detected + +From: Nico Boehr + +[ Upstream commit 21f27df854008b86349a203bf97fef79bb11f53e ] + +To determine whether the guest has caused an external interruption loop +upon code 20 (external interrupt) intercepts, the ext_new_psw needs to +be inspected to see whether external interrupts are enabled. + +Under non-PV, ext_new_psw can simply be taken from guest lowcore. Under +PV, KVM can only access the encrypted guest lowcore and hence the +ext_new_psw must not be taken from guest lowcore. + +handle_external_interrupt() incorrectly did that and hence was not able +to reliably tell whether an external interruption loop is happening or +not. False negatives cause spurious failures of my kvm-unit-test +for extint loops[1] under PV. + +Since code 20 is only caused under PV if and only if the guest's +ext_new_psw is enabled for external interrupts, false positive detection +of a external interruption loop can not happen. + +Fix this issue by instead looking at the guest PSW in the state +description. Since the PSW swap for external interrupt is done by the +ultravisor before the intercept is caused, this reliably tells whether +the guest is enabled for external interrupts in the ext_new_psw. + +Also update the comments to explain better what is happening. + +[1] https://lore.kernel.org/kvm/20220812062151.1980937-4-nrb@linux.ibm.com/ + +Signed-off-by: Nico Boehr +Reviewed-by: Janosch Frank +Reviewed-by: Christian Borntraeger +Fixes: 201ae986ead7 ("KVM: s390: protvirt: Implement interrupt injection") +Link: https://lore.kernel.org/r/20230213085520.100756-2-nrb@linux.ibm.com +Message-Id: <20230213085520.100756-2-nrb@linux.ibm.com> +Signed-off-by: Janosch Frank +Signed-off-by: Sasha Levin +--- + arch/s390/kvm/intercept.c | 32 ++++++++++++++++++++++++-------- + 1 file changed, 24 insertions(+), 8 deletions(-) + +diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c +index 88112065d9411..ee7478a601442 100644 +--- a/arch/s390/kvm/intercept.c ++++ b/arch/s390/kvm/intercept.c +@@ -271,10 +271,18 @@ static int handle_prog(struct kvm_vcpu *vcpu) + * handle_external_interrupt - used for external interruption interceptions + * @vcpu: virtual cpu + * +- * This interception only occurs if the CPUSTAT_EXT_INT bit was set, or if +- * the new PSW does not have external interrupts disabled. In the first case, +- * we've got to deliver the interrupt manually, and in the second case, we +- * drop to userspace to handle the situation there. ++ * This interception occurs if: ++ * - the CPUSTAT_EXT_INT bit was already set when the external interrupt ++ * occurred. In this case, the interrupt needs to be injected manually to ++ * preserve interrupt priority. ++ * - the external new PSW has external interrupts enabled, which will cause an ++ * interruption loop. We drop to userspace in this case. ++ * ++ * The latter case can be detected by inspecting the external mask bit in the ++ * external new psw. ++ * ++ * Under PV, only the latter case can occur, since interrupt priorities are ++ * handled in the ultravisor. + */ + static int handle_external_interrupt(struct kvm_vcpu *vcpu) + { +@@ -285,10 +293,18 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu) + + vcpu->stat.exit_external_interrupt++; + +- rc = read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &newpsw, sizeof(psw_t)); +- if (rc) +- return rc; +- /* We can not handle clock comparator or timer interrupt with bad PSW */ ++ if (kvm_s390_pv_cpu_is_protected(vcpu)) { ++ newpsw = vcpu->arch.sie_block->gpsw; ++ } else { ++ rc = read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &newpsw, sizeof(psw_t)); ++ if (rc) ++ return rc; ++ } ++ ++ /* ++ * Clock comparator or timer interrupt with external interrupt enabled ++ * will cause interrupt loop. Drop to userspace. ++ */ + if ((eic == EXT_IRQ_CLK_COMP || eic == EXT_IRQ_CPU_TIMER) && + (newpsw.mask & PSW_MASK_EXT)) + return -EOPNOTSUPP; +-- +2.39.2 + diff --git a/queue-6.1/l2tp-generate-correct-module-alias-strings.patch b/queue-6.1/l2tp-generate-correct-module-alias-strings.patch new file mode 100644 index 00000000000..c0a226bd8b3 --- /dev/null +++ b/queue-6.1/l2tp-generate-correct-module-alias-strings.patch @@ -0,0 +1,82 @@ +From d29789d4b0a57365d1efba7d16d659a02540b4c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Mar 2023 11:54:42 +0200 +Subject: l2tp: generate correct module alias strings + +From: Andrea Righi + +[ Upstream commit 154e07c164859fc90bf4e8143f2f6c1af9f3a35e ] + +Commit 65b32f801bfb ("uapi: move IPPROTO_L2TP to in.h") moved the +definition of IPPROTO_L2TP from a define to an enum, but since +__stringify doesn't work properly with enums, we ended up breaking the +modalias strings for the l2tp modules: + + $ modinfo l2tp_ip l2tp_ip6 | grep alias + alias: net-pf-2-proto-IPPROTO_L2TP + alias: net-pf-2-proto-2-type-IPPROTO_L2TP + alias: net-pf-10-proto-IPPROTO_L2TP + alias: net-pf-10-proto-2-type-IPPROTO_L2TP + +Use the resolved number directly in MODULE_ALIAS_*() macros (as we +already do with SOCK_DGRAM) to fix the alias strings: + +$ modinfo l2tp_ip l2tp_ip6 | grep alias +alias: net-pf-2-proto-115 +alias: net-pf-2-proto-115-type-2 +alias: net-pf-10-proto-115 +alias: net-pf-10-proto-115-type-2 + +Moreover, fix the ordering of the parameters passed to +MODULE_ALIAS_NET_PF_PROTO_TYPE() by switching proto and type. + +Fixes: 65b32f801bfb ("uapi: move IPPROTO_L2TP to in.h") +Link: https://lore.kernel.org/lkml/ZCQt7hmodtUaBlCP@righiandr-XPS-13-7390 +Signed-off-by: Guillaume Nault +Signed-off-by: Andrea Righi +Reviewed-by: Wojciech Drewek +Tested-by: Wojciech Drewek +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/l2tp/l2tp_ip.c | 8 ++++---- + net/l2tp/l2tp_ip6.c | 8 ++++---- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c +index 4db5a554bdbd9..41a74fc84ca13 100644 +--- a/net/l2tp/l2tp_ip.c ++++ b/net/l2tp/l2tp_ip.c +@@ -677,8 +677,8 @@ MODULE_AUTHOR("James Chapman "); + MODULE_DESCRIPTION("L2TP over IP"); + MODULE_VERSION("1.0"); + +-/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like +- * enums ++/* Use the values of SOCK_DGRAM (2) as type and IPPROTO_L2TP (115) as protocol, ++ * because __stringify doesn't like enums + */ +-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP); +-MODULE_ALIAS_NET_PF_PROTO(PF_INET, IPPROTO_L2TP); ++MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 115, 2); ++MODULE_ALIAS_NET_PF_PROTO(PF_INET, 115); +diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c +index 9dbd801ddb98c..9db7f4f5a4414 100644 +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -808,8 +808,8 @@ MODULE_AUTHOR("Chris Elston "); + MODULE_DESCRIPTION("L2TP IP encapsulation for IPv6"); + MODULE_VERSION("1.0"); + +-/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like +- * enums ++/* Use the values of SOCK_DGRAM (2) as type and IPPROTO_L2TP (115) as protocol, ++ * because __stringify doesn't like enums + */ +-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 2, IPPROTO_L2TP); +-MODULE_ALIAS_NET_PF_PROTO(PF_INET6, IPPROTO_L2TP); ++MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 115, 2); ++MODULE_ALIAS_NET_PF_PROTO(PF_INET6, 115); +-- +2.39.2 + diff --git a/queue-6.1/net-don-t-let-netpoll-invoke-napi-if-in-xmit-context.patch b/queue-6.1/net-don-t-let-netpoll-invoke-napi-if-in-xmit-context.patch new file mode 100644 index 00000000000..9c6f7842ea1 --- /dev/null +++ b/queue-6.1/net-don-t-let-netpoll-invoke-napi-if-in-xmit-context.patch @@ -0,0 +1,80 @@ +From 8bdfdd8a498ee55b98fefa71d16c820196f98b96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Mar 2023 19:21:44 -0700 +Subject: net: don't let netpoll invoke NAPI if in xmit context + +From: Jakub Kicinski + +[ Upstream commit 275b471e3d2daf1472ae8fa70dc1b50c9e0b9e75 ] + +Commit 0db3dc73f7a3 ("[NETPOLL]: tx lock deadlock fix") narrowed +down the region under netif_tx_trylock() inside netpoll_send_skb(). +(At that point in time netif_tx_trylock() would lock all queues of +the device.) Taking the tx lock was problematic because driver's +cleanup method may take the same lock. So the change made us hold +the xmit lock only around xmit, and expected the driver to take +care of locking within ->ndo_poll_controller(). + +Unfortunately this only works if netpoll isn't itself called with +the xmit lock already held. Netpoll code is careful and uses +trylock(). The drivers, however, may be using plain lock(). +Printing while holding the xmit lock is going to result in rare +deadlocks. + +Luckily we record the xmit lock owners, so we can scan all the queues, +the same way we scan NAPI owners. If any of the xmit locks is held +by the local CPU we better not attempt any polling. + +It would be nice if we could narrow down the check to only the NAPIs +and the queue we're trying to use. I don't see a way to do that now. + +Reported-by: Roman Gushchin +Fixes: 0db3dc73f7a3 ("[NETPOLL]: tx lock deadlock fix") +Signed-off-by: Jakub Kicinski +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/core/netpoll.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/net/core/netpoll.c b/net/core/netpoll.c +index 9be762e1d0428..4ac8d0ad9f6fc 100644 +--- a/net/core/netpoll.c ++++ b/net/core/netpoll.c +@@ -137,6 +137,20 @@ static void queue_process(struct work_struct *work) + } + } + ++static int netif_local_xmit_active(struct net_device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < dev->num_tx_queues; i++) { ++ struct netdev_queue *txq = netdev_get_tx_queue(dev, i); ++ ++ if (READ_ONCE(txq->xmit_lock_owner) == smp_processor_id()) ++ return 1; ++ } ++ ++ return 0; ++} ++ + static void poll_one_napi(struct napi_struct *napi) + { + int work; +@@ -183,7 +197,10 @@ void netpoll_poll_dev(struct net_device *dev) + if (!ni || down_trylock(&ni->dev_lock)) + return; + +- if (!netif_running(dev)) { ++ /* Some drivers will take the same locks in poll and xmit, ++ * we can't poll if local CPU is already in xmit. ++ */ ++ if (!netif_running(dev) || netif_local_xmit_active(dev)) { + up(&ni->dev_lock); + return; + } +-- +2.39.2 + diff --git a/queue-6.1/net-dsa-mv88e6xxx-reset-mv88e6393x-force-wd-event-bi.patch b/queue-6.1/net-dsa-mv88e6xxx-reset-mv88e6393x-force-wd-event-bi.patch new file mode 100644 index 00000000000..27dca4aab90 --- /dev/null +++ b/queue-6.1/net-dsa-mv88e6xxx-reset-mv88e6393x-force-wd-event-bi.patch @@ -0,0 +1,91 @@ +From cdc0c58818f88853f0ba72a18cb62d2f0f509633 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Mar 2023 10:40:13 +0200 +Subject: net: dsa: mv88e6xxx: Reset mv88e6393x force WD event bit + +From: Gustav Ekelund + +[ Upstream commit 089b91a0155c4de1209a07ff2a7dd299ff3ece47 ] + +The force watchdog event bit is not cleared during SW reset in the +mv88e6393x switch. This is a different behavior compared to mv886390 which +clears the force WD event bit as advertised. This causes a force WD event +to be handled over and over again as the SW reset following the event never +clears the force WD event bit. + +Explicitly clear the watchdog event register to 0 in irq_action when +handling an event to prevent the switch from sending continuous interrupts. +Marvell aren't aware of any other stuck bits apart from the force WD +bit. + +Fixes: de776d0d316f ("net: dsa: mv88e6xxx: add support for mv88e6393x family" +Signed-off-by: Gustav Ekelund +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/chip.c | 2 +- + drivers/net/dsa/mv88e6xxx/global2.c | 20 ++++++++++++++++++++ + drivers/net/dsa/mv88e6xxx/global2.h | 1 + + 3 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 8cf27e2654fcf..f1d9ee2a78b0f 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -5514,7 +5514,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { + * .port_set_upstream_port method. + */ + .set_egress_port = mv88e6393x_set_egress_port, +- .watchdog_ops = &mv88e6390_watchdog_ops, ++ .watchdog_ops = &mv88e6393x_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, + .reset = mv88e6352_g1_reset, +diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c +index fa65ecd9cb853..ec49939968fac 100644 +--- a/drivers/net/dsa/mv88e6xxx/global2.c ++++ b/drivers/net/dsa/mv88e6xxx/global2.c +@@ -931,6 +931,26 @@ const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = { + .irq_free = mv88e6390_watchdog_free, + }; + ++static int mv88e6393x_watchdog_action(struct mv88e6xxx_chip *chip, int irq) ++{ ++ mv88e6390_watchdog_action(chip, irq); ++ ++ /* Fix for clearing the force WD event bit. ++ * Unreleased erratum on mv88e6393x. ++ */ ++ mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL, ++ MV88E6390_G2_WDOG_CTL_UPDATE | ++ MV88E6390_G2_WDOG_CTL_PTR_EVENT); ++ ++ return IRQ_HANDLED; ++} ++ ++const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops = { ++ .irq_action = mv88e6393x_watchdog_action, ++ .irq_setup = mv88e6390_watchdog_setup, ++ .irq_free = mv88e6390_watchdog_free, ++}; ++ + static irqreturn_t mv88e6xxx_g2_watchdog_thread_fn(int irq, void *dev_id) + { + struct mv88e6xxx_chip *chip = dev_id; +diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h +index 7536b8b0ad011..c05fad5c9f19d 100644 +--- a/drivers/net/dsa/mv88e6xxx/global2.h ++++ b/drivers/net/dsa/mv88e6xxx/global2.h +@@ -363,6 +363,7 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, + extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; + extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops; + extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops; ++extern const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops; + + extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops; + extern const struct mv88e6xxx_avb_ops mv88e6352_avb_ops; +-- +2.39.2 + diff --git a/queue-6.1/net-ethernet-ti-am65-cpsw-fix-mdio-cleanup-in-probe.patch b/queue-6.1/net-ethernet-ti-am65-cpsw-fix-mdio-cleanup-in-probe.patch new file mode 100644 index 00000000000..3a2c92067a7 --- /dev/null +++ b/queue-6.1/net-ethernet-ti-am65-cpsw-fix-mdio-cleanup-in-probe.patch @@ -0,0 +1,57 @@ +From 254428d77272f3fae56c94099c0c4bae670db1bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 14:33:21 +0530 +Subject: net: ethernet: ti: am65-cpsw: Fix mdio cleanup in probe + +From: Siddharth Vadapalli + +[ Upstream commit c6b486fb33680ad5a3a6390ce693c835caaae3f7 ] + +In the am65_cpsw_nuss_probe() function's cleanup path, the call to +of_platform_device_destroy() for the common->mdio_dev device is invoked +unconditionally. It is possible that either the MDIO node is not present +in the device-tree, or the MDIO node is disabled in the device-tree. In +both these cases, the MDIO device is not created, resulting in a NULL +pointer dereference when the of_platform_device_destroy() function is +invoked on the common->mdio_dev device on the cleanup path. + +Fix this by ensuring that the common->mdio_dev device exists, before +attempting to invoke of_platform_device_destroy(). + +Fixes: a45cfcc69a25 ("net: ethernet: ti: am65-cpsw-nuss: use of_platform_device_create() for mdio") +Signed-off-by: Siddharth Vadapalli +Reviewed-by: Roger Quadros +Link: https://lore.kernel.org/r/20230403090321.835877-1-s-vadapalli@ti.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/am65-cpsw-nuss.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +index 8ff1c84a23ce7..25466cbdc16bd 100644 +--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +@@ -2819,7 +2819,8 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev) + am65_cpsw_nuss_phylink_cleanup(common); + am65_cpts_release(common->cpts); + err_of_clear: +- of_platform_device_destroy(common->mdio_dev, NULL); ++ if (common->mdio_dev) ++ of_platform_device_destroy(common->mdio_dev, NULL); + err_pm_clear: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +@@ -2848,7 +2849,8 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev) + am65_cpsw_nuss_phylink_cleanup(common); + am65_cpts_release(common->cpts); + +- of_platform_device_destroy(common->mdio_dev, NULL); ++ if (common->mdio_dev) ++ of_platform_device_destroy(common->mdio_dev, NULL); + + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); +-- +2.39.2 + diff --git a/queue-6.1/net-phylink-add-phylink_expects_phy-method.patch b/queue-6.1/net-phylink-add-phylink_expects_phy-method.patch new file mode 100644 index 00000000000..211bdf5f073 --- /dev/null +++ b/queue-6.1/net-phylink-add-phylink_expects_phy-method.patch @@ -0,0 +1,71 @@ +From 11bbc1533099efc1917228397beb8db7d60bc7d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Mar 2023 17:14:02 +0800 +Subject: net: phylink: add phylink_expects_phy() method + +From: Michael Sit Wei Hong + +[ Upstream commit 653a180957a85c3fc30320cc7e84f5dc913a64f8 ] + +Provide phylink_expects_phy() to allow MAC drivers to check if it +is expecting a PHY to attach to. Since fixed-linked setups do not +need to attach to a PHY. + +Provides a boolean value as to if the MAC should expect a PHY. +Returns true if a PHY is expected. + +Reviewed-by: Russell King (Oracle) +Signed-off-by: Michael Sit Wei Hong +Signed-off-by: David S. Miller +Stable-dep-of: fe2cfbc96803 ("net: stmmac: check if MAC needs to attach to a PHY") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/phylink.c | 19 +++++++++++++++++++ + include/linux/phylink.h | 1 + + 2 files changed, 20 insertions(+) + +diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c +index a202ce6611fde..4073e8243df3f 100644 +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1552,6 +1552,25 @@ void phylink_destroy(struct phylink *pl) + } + EXPORT_SYMBOL_GPL(phylink_destroy); + ++/** ++ * phylink_expects_phy() - Determine if phylink expects a phy to be attached ++ * @pl: a pointer to a &struct phylink returned from phylink_create() ++ * ++ * When using fixed-link mode, or in-band mode with 1000base-X or 2500base-X, ++ * no PHY is needed. ++ * ++ * Returns true if phylink will be expecting a PHY. ++ */ ++bool phylink_expects_phy(struct phylink *pl) ++{ ++ if (pl->cfg_link_an_mode == MLO_AN_FIXED || ++ (pl->cfg_link_an_mode == MLO_AN_INBAND && ++ phy_interface_mode_is_8023z(pl->link_config.interface))) ++ return false; ++ return true; ++} ++EXPORT_SYMBOL_GPL(phylink_expects_phy); ++ + static void phylink_phy_change(struct phy_device *phydev, bool up) + { + struct phylink *pl = phydev->phylink; +diff --git a/include/linux/phylink.h b/include/linux/phylink.h +index 3f01ac8017e06..6d62c9ea2e040 100644 +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -566,6 +566,7 @@ struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, + phy_interface_t iface, + const struct phylink_mac_ops *mac_ops); + void phylink_destroy(struct phylink *); ++bool phylink_expects_phy(struct phylink *pl); + + int phylink_connect_phy(struct phylink *, struct phy_device *); + int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags); +-- +2.39.2 + diff --git a/queue-6.1/net-qrtr-do-not-do-del_server-broadcast-after-del_cl.patch b/queue-6.1/net-qrtr-do-not-do-del_server-broadcast-after-del_cl.patch new file mode 100644 index 00000000000..1d808494467 --- /dev/null +++ b/queue-6.1/net-qrtr-do-not-do-del_server-broadcast-after-del_cl.patch @@ -0,0 +1,94 @@ +From 9598a329f1db27a8656c7c5f0be70dc84f4f6fc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 12:28:51 +0530 +Subject: net: qrtr: Do not do DEL_SERVER broadcast after DEL_CLIENT + +From: Sricharan Ramabadhran + +[ Upstream commit 839349d13905927d8a567ca4d21d88c82028e31d ] + +On the remote side, when QRTR socket is removed, af_qrtr will call +qrtr_port_remove() which broadcasts the DEL_CLIENT packet to all neighbours +including local NS. NS upon receiving the DEL_CLIENT packet, will remove +the lookups associated with the node:port and broadcasts the DEL_SERVER +packet. + +But on the host side, due to the arrival of the DEL_CLIENT packet, the NS +would've already deleted the server belonging to that port. So when the +remote's NS again broadcasts the DEL_SERVER for that port, it throws below +error message on the host: + +"failed while handling packet from 2:-2" + +So fix this error by not broadcasting the DEL_SERVER packet when the +DEL_CLIENT packet gets processed." + +Fixes: 0c2204a4ad71 ("net: qrtr: Migrate nameservice to kernel from userspace") +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Ram Kumar Dharuman +Signed-off-by: Sricharan Ramabadhran +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/qrtr/ns.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c +index e595079c2cafe..3e40a1ba48f79 100644 +--- a/net/qrtr/ns.c ++++ b/net/qrtr/ns.c +@@ -273,7 +273,7 @@ static struct qrtr_server *server_add(unsigned int service, + return NULL; + } + +-static int server_del(struct qrtr_node *node, unsigned int port) ++static int server_del(struct qrtr_node *node, unsigned int port, bool bcast) + { + struct qrtr_lookup *lookup; + struct qrtr_server *srv; +@@ -286,7 +286,7 @@ static int server_del(struct qrtr_node *node, unsigned int port) + radix_tree_delete(&node->servers, port); + + /* Broadcast the removal of local servers */ +- if (srv->node == qrtr_ns.local_node) ++ if (srv->node == qrtr_ns.local_node && bcast) + service_announce_del(&qrtr_ns.bcast_sq, srv); + + /* Announce the service's disappearance to observers */ +@@ -372,7 +372,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) + } + slot = radix_tree_iter_resume(slot, &iter); + rcu_read_unlock(); +- server_del(node, srv->port); ++ server_del(node, srv->port, true); + rcu_read_lock(); + } + rcu_read_unlock(); +@@ -458,10 +458,13 @@ static int ctrl_cmd_del_client(struct sockaddr_qrtr *from, + kfree(lookup); + } + +- /* Remove the server belonging to this port */ ++ /* Remove the server belonging to this port but don't broadcast ++ * DEL_SERVER. Neighbours would've already removed the server belonging ++ * to this port due to the DEL_CLIENT broadcast from qrtr_port_remove(). ++ */ + node = node_get(node_id); + if (node) +- server_del(node, port); ++ server_del(node, port, false); + + /* Advertise the removal of this client to all local servers */ + local_node = node_get(qrtr_ns.local_node); +@@ -566,7 +569,7 @@ static int ctrl_cmd_del_server(struct sockaddr_qrtr *from, + if (!node) + return -ENOENT; + +- return server_del(node, port); ++ return server_del(node, port, true); + } + + static int ctrl_cmd_new_lookup(struct sockaddr_qrtr *from, +-- +2.39.2 + diff --git a/queue-6.1/net-qrtr-fix-a-refcount-bug-in-qrtr_recvmsg.patch b/queue-6.1/net-qrtr-fix-a-refcount-bug-in-qrtr_recvmsg.patch new file mode 100644 index 00000000000..cd748553f53 --- /dev/null +++ b/queue-6.1/net-qrtr-fix-a-refcount-bug-in-qrtr_recvmsg.patch @@ -0,0 +1,77 @@ +From 31a221be48a9c06a80da67d8ad4e32039a23a994 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Mar 2023 09:25:32 +0800 +Subject: net: qrtr: Fix a refcount bug in qrtr_recvmsg() + +From: Ziyang Xuan + +[ Upstream commit 44d807320000db0d0013372ad39b53e12d52f758 ] + +Syzbot reported a bug as following: + +refcount_t: addition on 0; use-after-free. +... +RIP: 0010:refcount_warn_saturate+0x17c/0x1f0 lib/refcount.c:25 +... +Call Trace: + + __refcount_add include/linux/refcount.h:199 [inline] + __refcount_inc include/linux/refcount.h:250 [inline] + refcount_inc include/linux/refcount.h:267 [inline] + kref_get include/linux/kref.h:45 [inline] + qrtr_node_acquire net/qrtr/af_qrtr.c:202 [inline] + qrtr_node_lookup net/qrtr/af_qrtr.c:398 [inline] + qrtr_send_resume_tx net/qrtr/af_qrtr.c:1003 [inline] + qrtr_recvmsg+0x85f/0x990 net/qrtr/af_qrtr.c:1070 + sock_recvmsg_nosec net/socket.c:1017 [inline] + sock_recvmsg+0xe2/0x160 net/socket.c:1038 + qrtr_ns_worker+0x170/0x1700 net/qrtr/ns.c:688 + process_one_work+0x991/0x15c0 kernel/workqueue.c:2390 + worker_thread+0x669/0x1090 kernel/workqueue.c:2537 + +It occurs in the concurrent scenario of qrtr_recvmsg() and +qrtr_endpoint_unregister() as following: + + cpu0 cpu1 +qrtr_recvmsg qrtr_endpoint_unregister +qrtr_send_resume_tx qrtr_node_release +qrtr_node_lookup mutex_lock(&qrtr_node_lock) +spin_lock_irqsave(&qrtr_nodes_lock, ) refcount_dec_and_test(&node->ref) [node->ref == 0] +radix_tree_lookup [node != NULL] __qrtr_node_release +qrtr_node_acquire spin_lock_irqsave(&qrtr_nodes_lock, ) +kref_get(&node->ref) [WARNING] ... + mutex_unlock(&qrtr_node_lock) + +Use qrtr_node_lock to protect qrtr_node_lookup() implementation, this +is actually improving the protection of node reference. + +Fixes: 0a7e0d0ef054 ("net: qrtr: Migrate node lookup tree to spinlock") +Reported-by: syzbot+a7492efaa5d61b51db23@syzkaller.appspotmail.com +Link: https://syzkaller.appspot.com/bug?extid=a7492efaa5d61b51db23 +Signed-off-by: Ziyang Xuan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/qrtr/af_qrtr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c +index 5c2fb992803b7..3a70255c8d02f 100644 +--- a/net/qrtr/af_qrtr.c ++++ b/net/qrtr/af_qrtr.c +@@ -393,10 +393,12 @@ static struct qrtr_node *qrtr_node_lookup(unsigned int nid) + struct qrtr_node *node; + unsigned long flags; + ++ mutex_lock(&qrtr_node_lock); + spin_lock_irqsave(&qrtr_nodes_lock, flags); + node = radix_tree_lookup(&qrtr_nodes, nid); + node = qrtr_node_acquire(node); + spin_unlock_irqrestore(&qrtr_nodes_lock, flags); ++ mutex_unlock(&qrtr_node_lock); + + return node; + } +-- +2.39.2 + diff --git a/queue-6.1/net-stmmac-check-fwnode-for-phy-device-before-scanni.patch b/queue-6.1/net-stmmac-check-fwnode-for-phy-device-before-scanni.patch new file mode 100644 index 00000000000..51b8c466e01 --- /dev/null +++ b/queue-6.1/net-stmmac-check-fwnode-for-phy-device-before-scanni.patch @@ -0,0 +1,80 @@ +From 3e4f76b2afb2e8bf1c304ddc60b779025d81dfd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Apr 2023 10:45:41 +0800 +Subject: net: stmmac: check fwnode for phy device before scanning for phy + +From: Michael Sit Wei Hong + +[ Upstream commit 8fbc10b995a506e173f1080dfa2764f232a65e02 ] + +Some DT devices already have phy device configured in the DT/ACPI. +Current implementation scans for a phy unconditionally even though +there is a phy listed in the DT/ACPI and already attached. + +We should check the fwnode if there is any phy device listed in +fwnode and decide whether to scan for a phy to attach to. + +Fixes: fe2cfbc96803 ("net: stmmac: check if MAC needs to attach to a PHY") +Reported-by: Martin Blumenstingl +Link: https://lore.kernel.org/lkml/20230403212434.296975-1-martin.blumenstingl@googlemail.com/ +Tested-by: Guenter Roeck +Tested-by: Shahab Vahedi +Tested-by: Marek Szyprowski +Tested-by: Martin Blumenstingl +Suggested-by: Russell King (Oracle) +Signed-off-by: Michael Sit Wei Hong +Link: https://lore.kernel.org/r/20230406024541.3556305-1-michael.wei.hong.sit@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 3f35399657da2..05607c1ab3319 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1132,22 +1132,26 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv) + static int stmmac_init_phy(struct net_device *dev) + { + struct stmmac_priv *priv = netdev_priv(dev); ++ struct fwnode_handle *phy_fwnode; + struct fwnode_handle *fwnode; +- bool phy_needed; + int ret; + ++ if (!phylink_expects_phy(priv->phylink)) ++ return 0; ++ + fwnode = of_fwnode_handle(priv->plat->phylink_node); + if (!fwnode) + fwnode = dev_fwnode(priv->device); + + if (fwnode) +- ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0); ++ phy_fwnode = fwnode_get_phy_node(fwnode); ++ else ++ phy_fwnode = NULL; + +- phy_needed = phylink_expects_phy(priv->phylink); + /* Some DT bindings do not set-up the PHY handle. Let's try to + * manually parse it + */ +- if (!fwnode || phy_needed || ret) { ++ if (!phy_fwnode || IS_ERR(phy_fwnode)) { + int addr = priv->plat->phy_addr; + struct phy_device *phydev; + +@@ -1163,6 +1167,9 @@ static int stmmac_init_phy(struct net_device *dev) + } + + ret = phylink_connect_phy(priv->phylink, phydev); ++ } else { ++ fwnode_handle_put(phy_fwnode); ++ ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0); + } + + if (!priv->plat->pmt) { +-- +2.39.2 + diff --git a/queue-6.1/net-stmmac-check-if-mac-needs-to-attach-to-a-phy.patch b/queue-6.1/net-stmmac-check-if-mac-needs-to-attach-to-a-phy.patch new file mode 100644 index 00000000000..eb1a2f920eb --- /dev/null +++ b/queue-6.1/net-stmmac-check-if-mac-needs-to-attach-to-a-phy.patch @@ -0,0 +1,53 @@ +From 56fdcffec86f460b2061205d7e83f8d6ba18e2ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Mar 2023 17:14:03 +0800 +Subject: net: stmmac: check if MAC needs to attach to a PHY + +From: Michael Sit Wei Hong + +[ Upstream commit fe2cfbc9680356a3d9f8adde8a38e715831e32f5 ] + +After the introduction of the fixed-link support, the MAC driver +no longer attempt to scan for a PHY to attach to. This causes the +non fixed-link setups to stop working. + +Using the phylink_expects_phy() to check and determine if the MAC +should expect and attach a PHY. + +Fixes: ab21cf920928 ("net: stmmac: make mdio register skips PHY scanning for fixed-link") +Signed-off-by: Michael Sit Wei Hong +Signed-off-by: Lai Peter Jun Ann +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 93321437f0933..3a5abfb1a890f 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1133,6 +1133,7 @@ static int stmmac_init_phy(struct net_device *dev) + { + struct stmmac_priv *priv = netdev_priv(dev); + struct fwnode_handle *fwnode; ++ bool phy_needed; + int ret; + + fwnode = of_fwnode_handle(priv->plat->phylink_node); +@@ -1142,10 +1143,11 @@ static int stmmac_init_phy(struct net_device *dev) + if (fwnode) + ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0); + ++ phy_needed = phylink_expects_phy(priv->phylink); + /* Some DT bindings do not set-up the PHY handle. Let's try to + * manually parse it + */ +- if (!fwnode || ret) { ++ if (!fwnode || phy_needed || ret) { + int addr = priv->plat->phy_addr; + struct phy_device *phydev; + +-- +2.39.2 + diff --git a/queue-6.1/net-stmmac-fix-up-rx-flow-hash-indirection-table-whe.patch b/queue-6.1/net-stmmac-fix-up-rx-flow-hash-indirection-table-whe.patch new file mode 100644 index 00000000000..090a7f21402 --- /dev/null +++ b/queue-6.1/net-stmmac-fix-up-rx-flow-hash-indirection-table-whe.patch @@ -0,0 +1,86 @@ +From cf9595e2d5daf0775507b6ee26adef113ff79ca9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 14:11:20 +0200 +Subject: net: stmmac: fix up RX flow hash indirection table when setting + channels + +From: Corinna Vinschen + +[ Upstream commit 218c597325f4faf7b7a6049233a30d7842b5b2dc ] + +stmmac_reinit_queues() fails to fix up the RX hash. Even if the number +of channels gets restricted, the output of `ethtool -x' indicates that +all RX queues are used: + + $ ethtool -l enp0s29f2 + Channel parameters for enp0s29f2: + Pre-set maximums: + RX: 8 + TX: 8 + Other: n/a + Combined: n/a + Current hardware settings: + RX: 8 + TX: 8 + Other: n/a + Combined: n/a + $ ethtool -x enp0s29f2 + RX flow hash indirection table for enp0s29f2 with 8 RX ring(s): + 0: 0 1 2 3 4 5 6 7 + 8: 0 1 2 3 4 5 6 7 + [...] + $ ethtool -L enp0s29f2 rx 3 + $ ethtool -x enp0s29f2 + RX flow hash indirection table for enp0s29f2 with 3 RX ring(s): + 0: 0 1 2 3 4 5 6 7 + 8: 0 1 2 3 4 5 6 7 + [...] + +Fix this by setting the indirection table according to the number +of specified queues. The result is now as expected: + + $ ethtool -L enp0s29f2 rx 3 + $ ethtool -x enp0s29f2 + RX flow hash indirection table for enp0s29f2 with 3 RX ring(s): + 0: 0 1 2 0 1 2 0 1 + 8: 2 0 1 2 0 1 2 0 + [...] + +Tested on Intel Elkhart Lake. + +Fixes: 0366f7e06a6b ("net: stmmac: add ethtool support for get/set channels") +Signed-off-by: Corinna Vinschen +Link: https://lore.kernel.org/r/20230403121120.489138-1-vinschen@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 3a5abfb1a890f..3f35399657da2 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -6946,7 +6946,7 @@ static void stmmac_napi_del(struct net_device *dev) + int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt) + { + struct stmmac_priv *priv = netdev_priv(dev); +- int ret = 0; ++ int ret = 0, i; + + if (netif_running(dev)) + stmmac_release(dev); +@@ -6955,6 +6955,10 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt) + + priv->plat->rx_queues_to_use = rx_cnt; + priv->plat->tx_queues_to_use = tx_cnt; ++ if (!netif_is_rxfh_configured(dev)) ++ for (i = 0; i < ARRAY_SIZE(priv->rss.table); i++) ++ priv->rss.table[i] = ethtool_rxfh_indir_default(i, ++ rx_cnt); + + stmmac_napi_add(dev); + +-- +2.39.2 + diff --git a/queue-6.1/net-stmmac-remove-redundant-fixup-to-support-fixed-l.patch b/queue-6.1/net-stmmac-remove-redundant-fixup-to-support-fixed-l.patch new file mode 100644 index 00000000000..aa74042ce53 --- /dev/null +++ b/queue-6.1/net-stmmac-remove-redundant-fixup-to-support-fixed-l.patch @@ -0,0 +1,43 @@ +From d8237a3d60ea3f70944189b546d4a0e519705b4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Mar 2023 17:14:04 +0800 +Subject: net: stmmac: remove redundant fixup to support fixed-link mode + +From: Michael Sit Wei Hong + +[ Upstream commit 6fc21a6ed5953b1dd3a41ce7be1ea57f5ef8c081 ] + +Currently, intel_speed_mode_2500() will fix-up xpcs_an_inband +to 1 if the underlying controller has a max speed of 1000Mbps. +The value has been initialized and modified if it is +a fixed-linked setup earlier. + +This patch removes the fix-up to allow for fixed-linked setup +support. In stmmac_phy_setup(), ovr_an_inband is set based on +the value of xpcs_an_inband. Which in turn will return an +error in phylink_parse_mode() where MLO_AN_FIXED and +ovr_an_inband are both set. + +Fixes: c82386310d95 ("stmmac: intel: prepare to support 1000BASE-X phy interface setting") +Signed-off-by: Michael Sit Wei Hong +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +index 13aa919633b47..ab9f876b6df7e 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +@@ -251,7 +251,6 @@ static void intel_speed_mode_2500(struct net_device *ndev, void *intel_data) + priv->plat->mdio_bus_data->xpcs_an_inband = false; + } else { + priv->plat->max_speed = 1000; +- priv->plat->mdio_bus_data->xpcs_an_inband = true; + } + } + +-- +2.39.2 + diff --git a/queue-6.1/netlink-annotate-lockless-accesses-to-nlk-max_recvms.patch b/queue-6.1/netlink-annotate-lockless-accesses-to-nlk-max_recvms.patch new file mode 100644 index 00000000000..94f8b30fdbe --- /dev/null +++ b/queue-6.1/netlink-annotate-lockless-accesses-to-nlk-max_recvms.patch @@ -0,0 +1,111 @@ +From 6b1da1c18ca1fda19a3531dada852085d10ca1ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 21:46:43 +0000 +Subject: netlink: annotate lockless accesses to nlk->max_recvmsg_len + +From: Eric Dumazet + +[ Upstream commit a1865f2e7d10dde00d35a2122b38d2e469ae67ed ] + +syzbot reported a data-race in data-race in netlink_recvmsg() [1] + +Indeed, netlink_recvmsg() can be run concurrently, +and netlink_dump() also needs protection. + +[1] +BUG: KCSAN: data-race in netlink_recvmsg / netlink_recvmsg + +read to 0xffff888141840b38 of 8 bytes by task 23057 on cpu 0: +netlink_recvmsg+0xea/0x730 net/netlink/af_netlink.c:1988 +sock_recvmsg_nosec net/socket.c:1017 [inline] +sock_recvmsg net/socket.c:1038 [inline] +__sys_recvfrom+0x1ee/0x2e0 net/socket.c:2194 +__do_sys_recvfrom net/socket.c:2212 [inline] +__se_sys_recvfrom net/socket.c:2208 [inline] +__x64_sys_recvfrom+0x78/0x90 net/socket.c:2208 +do_syscall_x64 arch/x86/entry/common.c:50 [inline] +do_syscall_64+0x41/0xc0 arch/x86/entry/common.c:80 +entry_SYSCALL_64_after_hwframe+0x63/0xcd + +write to 0xffff888141840b38 of 8 bytes by task 23037 on cpu 1: +netlink_recvmsg+0x114/0x730 net/netlink/af_netlink.c:1989 +sock_recvmsg_nosec net/socket.c:1017 [inline] +sock_recvmsg net/socket.c:1038 [inline] +____sys_recvmsg+0x156/0x310 net/socket.c:2720 +___sys_recvmsg net/socket.c:2762 [inline] +do_recvmmsg+0x2e5/0x710 net/socket.c:2856 +__sys_recvmmsg net/socket.c:2935 [inline] +__do_sys_recvmmsg net/socket.c:2958 [inline] +__se_sys_recvmmsg net/socket.c:2951 [inline] +__x64_sys_recvmmsg+0xe2/0x160 net/socket.c:2951 +do_syscall_x64 arch/x86/entry/common.c:50 [inline] +do_syscall_64+0x41/0xc0 arch/x86/entry/common.c:80 +entry_SYSCALL_64_after_hwframe+0x63/0xcd + +value changed: 0x0000000000000000 -> 0x0000000000001000 + +Reported by Kernel Concurrency Sanitizer on: +CPU: 1 PID: 23037 Comm: syz-executor.2 Not tainted 6.3.0-rc4-syzkaller-00195-g5a57b48fdfcb #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/02/2023 + +Fixes: 9063e21fb026 ("netlink: autosize skb lengthes") +Reported-by: syzbot +Signed-off-by: Eric Dumazet +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/20230403214643.768555-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/netlink/af_netlink.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index e506712967918..99622c64081c4 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -1941,7 +1941,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + struct scm_cookie scm; + struct sock *sk = sock->sk; + struct netlink_sock *nlk = nlk_sk(sk); +- size_t copied; ++ size_t copied, max_recvmsg_len; + struct sk_buff *skb, *data_skb; + int err, ret; + +@@ -1974,9 +1974,10 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + #endif + + /* Record the max length of recvmsg() calls for future allocations */ +- nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len); +- nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len, +- SKB_WITH_OVERHEAD(32768)); ++ max_recvmsg_len = max(READ_ONCE(nlk->max_recvmsg_len), len); ++ max_recvmsg_len = min_t(size_t, max_recvmsg_len, ++ SKB_WITH_OVERHEAD(32768)); ++ WRITE_ONCE(nlk->max_recvmsg_len, max_recvmsg_len); + + copied = data_skb->len; + if (len < copied) { +@@ -2225,6 +2226,7 @@ static int netlink_dump(struct sock *sk) + struct netlink_ext_ack extack = {}; + struct netlink_callback *cb; + struct sk_buff *skb = NULL; ++ size_t max_recvmsg_len; + struct module *module; + int err = -ENOBUFS; + int alloc_min_size; +@@ -2247,8 +2249,9 @@ static int netlink_dump(struct sock *sk) + cb = &nlk->cb; + alloc_min_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE); + +- if (alloc_min_size < nlk->max_recvmsg_len) { +- alloc_size = nlk->max_recvmsg_len; ++ max_recvmsg_len = READ_ONCE(nlk->max_recvmsg_len); ++ if (alloc_min_size < max_recvmsg_len) { ++ alloc_size = max_recvmsg_len; + skb = alloc_skb(alloc_size, + (GFP_KERNEL & ~__GFP_DIRECT_RECLAIM) | + __GFP_NOWARN | __GFP_NORETRY); +-- +2.39.2 + diff --git a/queue-6.1/nfsd-avoid-calling-opdesc-with-ops-opnum-op_illegal.patch b/queue-6.1/nfsd-avoid-calling-opdesc-with-ops-opnum-op_illegal.patch new file mode 100644 index 00000000000..77971d4a846 --- /dev/null +++ b/queue-6.1/nfsd-avoid-calling-opdesc-with-ops-opnum-op_illegal.patch @@ -0,0 +1,54 @@ +From c1afbec71e9ade82d4fa143bc29a6b3c51b8b1db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Mar 2023 16:31:19 -0400 +Subject: NFSD: Avoid calling OPDESC() with ops->opnum == OP_ILLEGAL + +From: Chuck Lever + +[ Upstream commit 804d8e0a6e54427268790472781e03bc243f4ee3 ] + +OPDESC() simply indexes into nfsd4_ops[] by the op's operation +number, without range checking that value. It assumes callers are +careful to avoid calling it with an out-of-bounds opnum value. + +nfsd4_decode_compound() is not so careful, and can invoke OPDESC() +with opnum set to OP_ILLEGAL, which is 10044 -- well beyond the end +of nfsd4_ops[]. + +Reported-by: Jeff Layton +Fixes: f4f9ef4a1b0a ("nfsd4: opdesc will be useful outside nfs4proc.c") +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4xdr.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index 8377e14b8fba9..405087bda8cc1 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -2417,10 +2417,12 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) + for (i = 0; i < argp->opcnt; i++) { + op = &argp->ops[i]; + op->replay = NULL; ++ op->opdesc = NULL; + + if (xdr_stream_decode_u32(argp->xdr, &op->opnum) < 0) + return false; + if (nfsd4_opnum_in_range(argp, op)) { ++ op->opdesc = OPDESC(op); + op->status = nfsd4_dec_ops[op->opnum](argp, &op->u); + if (op->status != nfs_ok) + trace_nfsd_compound_decode_err(argp->rqstp, +@@ -2431,7 +2433,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) + op->opnum = OP_ILLEGAL; + op->status = nfserr_op_illegal; + } +- op->opdesc = OPDESC(op); ++ + /* + * We'll try to cache the result in the DRC if any one + * op in the compound wants to be cached: +-- +2.39.2 + diff --git a/queue-6.1/nfsd-call-op_release-even-when-op_func-returns-an-er.patch b/queue-6.1/nfsd-call-op_release-even-when-op_func-returns-an-er.patch new file mode 100644 index 00000000000..c3bf0f7fd83 --- /dev/null +++ b/queue-6.1/nfsd-call-op_release-even-when-op_func-returns-an-er.patch @@ -0,0 +1,82 @@ +From a9136aa8fc31c52b7bbe1bce510a676dbf6a4be1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Mar 2023 06:21:37 -0400 +Subject: nfsd: call op_release, even when op_func returns an error + +From: Jeff Layton + +[ Upstream commit 15a8b55dbb1ba154d82627547c5761cac884d810 ] + +For ops with "trivial" replies, nfsd4_encode_operation will shortcut +most of the encoding work and skip to just marshalling up the status. +One of the things it skips is calling op_release. This could cause a +memory leak in the layoutget codepath if there is an error at an +inopportune time. + +Have the compound processing engine always call op_release, even when +op_func sets an error in op->status. With this change, we also need +nfsd4_block_get_device_info_scsi to set the gd_device pointer to NULL +on error to avoid a double free. + +Reported-by: Zhi Li +Link: https://bugzilla.redhat.com/show_bug.cgi?id=2181403 +Fixes: 34b1744c91cc ("nfsd4: define ->op_release for compound ops") +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/blocklayout.c | 1 + + fs/nfsd/nfs4xdr.c | 11 +++++------ + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c +index b6d01d51a7465..e7e6e78d965db 100644 +--- a/fs/nfsd/blocklayout.c ++++ b/fs/nfsd/blocklayout.c +@@ -296,6 +296,7 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb, + + out_free_dev: + kfree(dev); ++ gdp->gd_device = NULL; + return ret; + } + +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index 405087bda8cc1..8f5b41dc07734 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -5353,10 +5353,8 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) + __be32 *p; + + p = xdr_reserve_space(xdr, 8); +- if (!p) { +- WARN_ON_ONCE(1); +- return; +- } ++ if (!p) ++ goto release; + *p++ = cpu_to_be32(op->opnum); + post_err_offset = xdr->buf->len; + +@@ -5371,8 +5369,6 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) + op->status = encoder(resp, op->status, &op->u); + if (op->status) + trace_nfsd_compound_encode_err(rqstp, op->opnum, op->status); +- if (opdesc && opdesc->op_release) +- opdesc->op_release(&op->u); + xdr_commit_encode(xdr); + + /* nfsd4_check_resp_size guarantees enough room for error status */ +@@ -5413,6 +5409,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) + } + status: + *p = op->status; ++release: ++ if (opdesc && opdesc->op_release) ++ opdesc->op_release(&op->u); + } + + /* +-- +2.39.2 + diff --git a/queue-6.1/nfsd-callback-request-does-not-use-correct-credentia.patch b/queue-6.1/nfsd-callback-request-does-not-use-correct-credentia.patch new file mode 100644 index 00000000000..897085aaea0 --- /dev/null +++ b/queue-6.1/nfsd-callback-request-does-not-use-correct-credentia.patch @@ -0,0 +1,43 @@ +From b39e8b6bfd04a56c8c9bc2d4c1ddeb0ba6ab0ede Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Apr 2023 13:22:08 -0700 +Subject: NFSD: callback request does not use correct credential for AUTH_SYS + +From: Dai Ngo + +[ Upstream commit 7de82c2f36fb26aa78440bbf0efcf360b691d98b ] + +Currently callback request does not use the credential specified in +CREATE_SESSION if the security flavor for the back channel is AUTH_SYS. + +Problem was discovered by pynfs 4.1 DELEG5 and DELEG7 test with error: +DELEG5 st_delegation.testCBSecParms : FAILURE + expected callback with uid, gid == 17, 19, got 0, 0 + +Signed-off-by: Dai Ngo +Reviewed-by: Jeff Layton +Fixes: 8276c902bbe9 ("SUNRPC: remove uid and gid from struct auth_cred") +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4callback.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index 6253cbe5f81b4..39989c14c8a1e 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -874,8 +874,8 @@ static const struct cred *get_backchannel_cred(struct nfs4_client *clp, struct r + if (!kcred) + return NULL; + +- kcred->uid = ses->se_cb_sec.uid; +- kcred->gid = ses->se_cb_sec.gid; ++ kcred->fsuid = ses->se_cb_sec.uid; ++ kcred->fsgid = ses->se_cb_sec.gid; + return kcred; + } + } +-- +2.39.2 + diff --git a/queue-6.1/ping-fix-potentail-null-deref-for-proc-net-icmp.patch b/queue-6.1/ping-fix-potentail-null-deref-for-proc-net-icmp.patch new file mode 100644 index 00000000000..aa00932f2d5 --- /dev/null +++ b/queue-6.1/ping-fix-potentail-null-deref-for-proc-net-icmp.patch @@ -0,0 +1,63 @@ +From 1ca45f0d89bbd2c3b97e1ea61dc5779023beb841 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 12:49:59 -0700 +Subject: ping: Fix potentail NULL deref for /proc/net/icmp. + +From: Kuniyuki Iwashima + +[ Upstream commit ab5fb73ffa01072b4d8031cc05801fa1cb653bee ] + +After commit dbca1596bbb0 ("ping: convert to RCU lookups, get rid +of rwlock"), we use RCU for ping sockets, but we should use spinlock +for /proc/net/icmp to avoid a potential NULL deref mentioned in +the previous patch. + +Let's go back to using spinlock there. + +Note we can convert ping sockets to use hlist instead of hlist_nulls +because we do not use SLAB_TYPESAFE_BY_RCU for ping sockets. + +Fixes: dbca1596bbb0 ("ping: convert to RCU lookups, get rid of rwlock") +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/ping.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 409ec2a1f95b0..5178a3f3cb537 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -1089,13 +1089,13 @@ static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos) + } + + void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family) +- __acquires(RCU) ++ __acquires(ping_table.lock) + { + struct ping_iter_state *state = seq->private; + state->bucket = 0; + state->family = family; + +- rcu_read_lock(); ++ spin_lock(&ping_table.lock); + + return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN; + } +@@ -1121,9 +1121,9 @@ void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos) + EXPORT_SYMBOL_GPL(ping_seq_next); + + void ping_seq_stop(struct seq_file *seq, void *v) +- __releases(RCU) ++ __releases(ping_table.lock) + { +- rcu_read_unlock(); ++ spin_unlock(&ping_table.lock); + } + EXPORT_SYMBOL_GPL(ping_seq_stop); + +-- +2.39.2 + diff --git a/queue-6.1/platform-x86-think-lmi-clean-up-display-of-current_v.patch b/queue-6.1/platform-x86-think-lmi-clean-up-display-of-current_v.patch new file mode 100644 index 00000000000..b359742e908 --- /dev/null +++ b/queue-6.1/platform-x86-think-lmi-clean-up-display-of-current_v.patch @@ -0,0 +1,60 @@ +From 1d295c33eaa6b115fa8168be21769cc7e8160d44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Apr 2023 21:31:20 -0400 +Subject: platform/x86: think-lmi: Clean up display of current_value on + Thinkstation + +From: Mark Pearson + +[ Upstream commit 7065655216d4d034d71164641f3bec0b189ad6fa ] + +On ThinkStations on retrieving the attribute value the BIOS appends the +possible values to the string. +Clean up the display in the current_value_show function so the options +part is not displayed. + +Fixes: a40cd7ef22fb ("platform/x86: think-lmi: Add WMI interface support on Lenovo platforms") +Reported by Mario Limoncello +Link: https://github.com/fwupd/fwupd/issues/5077#issuecomment-1488730526 +Signed-off-by: Mark Pearson +Link: https://lore.kernel.org/r/20230403013120.2105-2-mpearson-lenovo@squebb.ca +Tested-by: Mario Limonciello +Tested-by: Mirsad Goran Todorovac +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/think-lmi.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c +index 70c4ee254c43a..336b9029d1515 100644 +--- a/drivers/platform/x86/think-lmi.c ++++ b/drivers/platform/x86/think-lmi.c +@@ -920,7 +920,7 @@ static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *at + static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) + { + struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj); +- char *item, *value; ++ char *item, *value, *p; + int ret; + + ret = tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID); +@@ -931,9 +931,12 @@ static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *a + value = strpbrk(item, ","); + if (!value || value == item || !strlen(value + 1)) + ret = -EINVAL; +- else ++ else { ++ /* On Workstations remove the Options part after the value */ ++ p = strchrnul(value, ';'); ++ *p = '\0'; + ret = sysfs_emit(buf, "%s\n", value + 1); +- ++ } + kfree(item); + + return ret; +-- +2.39.2 + diff --git a/queue-6.1/platform-x86-think-lmi-fix-memory-leak-when-showing-.patch b/queue-6.1/platform-x86-think-lmi-fix-memory-leak-when-showing-.patch new file mode 100644 index 00000000000..c0af09137b2 --- /dev/null +++ b/queue-6.1/platform-x86-think-lmi-fix-memory-leak-when-showing-.patch @@ -0,0 +1,51 @@ +From 1b52a76dd40a373ae8e690194452c58a2eedd5e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Mar 2023 23:33:19 +0200 +Subject: platform/x86: think-lmi: Fix memory leak when showing current + settings + +From: Armin Wolf + +[ Upstream commit a3c4c053014585dcf20f4df954791b74d8a8afcd ] + +When retriving a item string with tlmi_setting(), the result has to be +freed using kfree(). In current_value_show() however, malformed +item strings are not freed, causing a memory leak. +Fix this by eliminating the early return responsible for this. + +Reported-by: Mirsad Goran Todorovac +Link: https://lore.kernel.org/platform-driver-x86/01e920bc-5882-ba0c-dd15-868bf0eca0b8@alu.unizg.hr/T/#t +Tested-by: Mirsad Goran Todorovac +Fixes: 0fdf10e5fc96 ("platform/x86: think-lmi: Split current_value to reflect only the value") +Signed-off-by: Armin Wolf +Link: https://lore.kernel.org/r/20230331213319.41040-1-W_Armin@gmx.de +Tested-by: Mario Limonciello +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/think-lmi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c +index 74af3e593b2ca..4e738ec5e6fb8 100644 +--- a/drivers/platform/x86/think-lmi.c ++++ b/drivers/platform/x86/think-lmi.c +@@ -930,10 +930,12 @@ static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *a + /* validate and split from `item,value` -> `value` */ + value = strpbrk(item, ","); + if (!value || value == item || !strlen(value + 1)) +- return -EINVAL; ++ ret = -EINVAL; ++ else ++ ret = sysfs_emit(buf, "%s\n", value + 1); + +- ret = sysfs_emit(buf, "%s\n", value + 1); + kfree(item); ++ + return ret; + } + +-- +2.39.2 + diff --git a/queue-6.1/platform-x86-think-lmi-fix-memory-leaks-when-parsing.patch b/queue-6.1/platform-x86-think-lmi-fix-memory-leaks-when-parsing.patch new file mode 100644 index 00000000000..d53ff7f033b --- /dev/null +++ b/queue-6.1/platform-x86-think-lmi-fix-memory-leaks-when-parsing.patch @@ -0,0 +1,58 @@ +From 1026fbf943ad0904ce9b38ebf9e98be24e5dea43 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Apr 2023 21:31:19 -0400 +Subject: platform/x86: think-lmi: Fix memory leaks when parsing ThinkStation + WMI strings + +From: Mark Pearson + +[ Upstream commit e7d796fccdc8d17c2d21817ebe4c7bf5bbfe5433 ] + +My previous commit introduced a memory leak where the item allocated +from tlmi_setting was not freed. +This commit also renames it to avoid confusion with the similarly name +variable in the same function. + +Fixes: 8a02d70679fc ("platform/x86: think-lmi: Add possible_values for ThinkStation") +Reported-by: Mirsad Todorovac +Link: https://lore.kernel.org/lkml/df26ff45-8933-f2b3-25f4-6ee51ccda7d8@gmx.de/T/ +Signed-off-by: Mark Pearson +Link: https://lore.kernel.org/r/20230403013120.2105-1-mpearson-lenovo@squebb.ca +Tested-by: Mario Limonciello +Tested-by: Mirsad Goran Todorovac +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/think-lmi.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c +index 4e738ec5e6fb8..70c4ee254c43a 100644 +--- a/drivers/platform/x86/think-lmi.c ++++ b/drivers/platform/x86/think-lmi.c +@@ -1459,10 +1459,10 @@ static int tlmi_analyze(void) + * name string. + * Try and pull that out if it's available. + */ +- char *item, *optstart, *optend; ++ char *optitem, *optstart, *optend; + +- if (!tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID)) { +- optstart = strstr(item, "[Optional:"); ++ if (!tlmi_setting(setting->index, &optitem, LENOVO_BIOS_SETTING_GUID)) { ++ optstart = strstr(optitem, "[Optional:"); + if (optstart) { + optstart += strlen("[Optional:"); + optend = strstr(optstart, "]"); +@@ -1471,6 +1471,7 @@ static int tlmi_analyze(void) + kstrndup(optstart, optend - optstart, + GFP_KERNEL); + } ++ kfree(optitem); + } + } + /* +-- +2.39.2 + diff --git a/queue-6.1/pwm-cros-ec-explicitly-set-.polarity-in-.get_state.patch b/queue-6.1/pwm-cros-ec-explicitly-set-.polarity-in-.get_state.patch new file mode 100644 index 00000000000..e99c960e31c --- /dev/null +++ b/queue-6.1/pwm-cros-ec-explicitly-set-.polarity-in-.get_state.patch @@ -0,0 +1,40 @@ +From 22adb19df69c6227ea0b0e30d114b418f47d4f16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Mar 2023 22:45:41 +0100 +Subject: pwm: cros-ec: Explicitly set .polarity 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 30006b77c7e130e01d1ab2148cc8abf73dfcc4bf ] + +The driver only supports normal polarity. Complete the implementation of +.get_state() by setting .polarity accordingly. + +Reviewed-by: Guenter Roeck +Fixes: 1f0d3bb02785 ("pwm: Add ChromeOS EC PWM driver") +Link: https://lore.kernel.org/r/20230228135508.1798428-3-u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-cros-ec.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c +index 11684edc06207..e55bc36ed4972 100644 +--- a/drivers/pwm/pwm-cros-ec.c ++++ b/drivers/pwm/pwm-cros-ec.c +@@ -198,6 +198,7 @@ static int cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + + state->enabled = (ret > 0); + state->period = EC_PWM_MAX_DUTY; ++ state->polarity = PWM_POLARITY_NORMAL; + + /* + * Note that "disabled" and "duty cycle == 0" are treated the same. If +-- +2.39.2 + diff --git a/queue-6.1/pwm-hibvt-explicitly-set-.polarity-in-.get_state.patch b/queue-6.1/pwm-hibvt-explicitly-set-.polarity-in-.get_state.patch new file mode 100644 index 00000000000..44940cbb06c --- /dev/null +++ b/queue-6.1/pwm-hibvt-explicitly-set-.polarity-in-.get_state.patch @@ -0,0 +1,40 @@ +From 7fe8cd36d0e42b05c2856939e335171a85d80930 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Mar 2023 22:45:40 +0100 +Subject: pwm: hibvt: Explicitly set .polarity 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 6f57937980142715e927697a6ffd2050f38ed6f6 ] + +The driver only both polarities. Complete the implementation of +.get_state() by setting .polarity according to the configured hardware +state. + +Fixes: d09f00810850 ("pwm: Add PWM driver for HiSilicon BVT SOCs") +Link: https://lore.kernel.org/r/20230228135508.1798428-2-u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-hibvt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pwm/pwm-hibvt.c b/drivers/pwm/pwm-hibvt.c +index 12c05c155cab0..1b9274c5ad872 100644 +--- a/drivers/pwm/pwm-hibvt.c ++++ b/drivers/pwm/pwm-hibvt.c +@@ -146,6 +146,7 @@ static int hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + + value = readl(base + PWM_CTRL_ADDR(pwm->hwpwm)); + state->enabled = (PWM_ENABLE_MASK & value); ++ state->polarity = (PWM_POLARITY_MASK & value) ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL; + + return 0; + } +-- +2.39.2 + diff --git a/queue-6.1/pwm-iqs620a-explicitly-set-.polarity-in-.get_state.patch b/queue-6.1/pwm-iqs620a-explicitly-set-.polarity-in-.get_state.patch new file mode 100644 index 00000000000..0d80a49efb2 --- /dev/null +++ b/queue-6.1/pwm-iqs620a-explicitly-set-.polarity-in-.get_state.patch @@ -0,0 +1,40 @@ +From 453f289fa592f8f645a86f6f276bd43250d446de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Mar 2023 22:45:42 +0100 +Subject: pwm: iqs620a: Explicitly set .polarity 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 b20b097128d9145fadcea1cbb45c4d186cb57466 ] + +The driver only supports normal polarity. Complete the implementation of +.get_state() by setting .polarity accordingly. + +Fixes: 6f0841a8197b ("pwm: Add support for Azoteq IQS620A PWM generator") +Reviewed-by: Jeff LaBundy +Link: https://lore.kernel.org/r/20230228135508.1798428-4-u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-iqs620a.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c +index 15aae53db5abb..aeb19a274accf 100644 +--- a/drivers/pwm/pwm-iqs620a.c ++++ b/drivers/pwm/pwm-iqs620a.c +@@ -126,6 +126,7 @@ static int iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + mutex_unlock(&iqs620_pwm->lock); + + state->period = IQS620_PWM_PERIOD_NS; ++ state->polarity = PWM_POLARITY_NORMAL; + + return 0; + } +-- +2.39.2 + diff --git a/queue-6.1/pwm-make-.get_state-callback-return-an-error-code.patch b/queue-6.1/pwm-make-.get_state-callback-return-an-error-code.patch new file mode 100644 index 00000000000..0a8d057515b --- /dev/null +++ b/queue-6.1/pwm-make-.get_state-callback-return-an-error-code.patch @@ -0,0 +1,978 @@ +From bdfd629eb0c51a7595aa1903fcb8342206bc3bb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 19:35:26 +0100 +Subject: pwm: Make .get_state() callback return an error code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 6c452cff79f8bf1c0146fda598d32061cfd25443 ] + +.get_state() might fail in some cases. To make it possible that a driver +signals such a failure change the prototype of .get_state() to return an +error code. + +This patch was created using coccinelle and the following semantic patch: + +@p1@ +identifier getstatefunc; +identifier driver; +@@ + struct pwm_ops driver = { + ..., + .get_state = getstatefunc + ,... + }; + +@p2@ +identifier p1.getstatefunc; +identifier chip, pwm, state; +@@ +-void ++int + getstatefunc(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) + { + ... +- return; ++ return 0; + ... + } + +plus the actual change of the prototype in include/linux/pwm.h (plus some +manual fixing of indentions and empty lines). + +So for now all drivers return success unconditionally. They are adapted +in the following patches to make the changes easier reviewable. + +Reviewed-by: Heiko Stuebner +Reviewed-by: Baolin Wang +Reviewed-by: Tzung-Bi Shih +Reviewed-by: Neil Armstrong +Reviewed-by: Nobuhiro Iwamatsu +Reviewed-by: Andre Przywara +Reviewed-by: Dave Stevenson +Acked-by: Douglas Anderson +Acked-by: Jernej Skrabec +Acked-by: Pavel Machek +Acked-by: Conor Dooley +Link: https://lore.kernel.org/r/20221130152148.2769768-2-u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Stable-dep-of: 6f5793798014 ("pwm: hibvt: Explicitly set .polarity in .get_state()") +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-mvebu.c | 9 ++++++--- + drivers/gpu/drm/bridge/ti-sn65dsi86.c | 14 ++++++++------ + drivers/leds/rgb/leds-qcom-lpg.c | 14 ++++++++------ + drivers/pwm/pwm-atmel.c | 6 ++++-- + drivers/pwm/pwm-bcm-iproc.c | 8 +++++--- + drivers/pwm/pwm-crc.c | 10 ++++++---- + drivers/pwm/pwm-cros-ec.c | 8 +++++--- + drivers/pwm/pwm-dwc.c | 6 ++++-- + drivers/pwm/pwm-hibvt.c | 6 ++++-- + drivers/pwm/pwm-imx-tpm.c | 8 +++++--- + drivers/pwm/pwm-imx27.c | 8 +++++--- + drivers/pwm/pwm-intel-lgm.c | 6 ++++-- + drivers/pwm/pwm-iqs620a.c | 6 ++++-- + drivers/pwm/pwm-keembay.c | 6 ++++-- + drivers/pwm/pwm-lpss.c | 6 ++++-- + drivers/pwm/pwm-meson.c | 8 +++++--- + drivers/pwm/pwm-mtk-disp.c | 12 +++++++----- + drivers/pwm/pwm-pca9685.c | 8 +++++--- + drivers/pwm/pwm-raspberrypi-poe.c | 8 +++++--- + drivers/pwm/pwm-rockchip.c | 12 +++++++----- + drivers/pwm/pwm-sifive.c | 6 ++++-- + drivers/pwm/pwm-sl28cpld.c | 8 +++++--- + drivers/pwm/pwm-sprd.c | 8 +++++--- + drivers/pwm/pwm-stm32-lp.c | 8 +++++--- + drivers/pwm/pwm-sun4i.c | 12 +++++++----- + drivers/pwm/pwm-sunplus.c | 6 ++++-- + drivers/pwm/pwm-visconti.c | 6 ++++-- + drivers/pwm/pwm-xilinx.c | 8 +++++--- + include/linux/pwm.h | 4 ++-- + 29 files changed, 146 insertions(+), 89 deletions(-) + +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index 1bb317b8dccea..91a4232ee58c2 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -657,9 +657,10 @@ static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) + spin_unlock_irqrestore(&mvpwm->lock, flags); + } + +-static void mvebu_pwm_get_state(struct pwm_chip *chip, +- struct pwm_device *pwm, +- struct pwm_state *state) { ++static int mvebu_pwm_get_state(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ struct pwm_state *state) ++{ + + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; +@@ -693,6 +694,8 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, + state->enabled = false; + + spin_unlock_irqrestore(&mvpwm->lock, flags); ++ ++ return 0; + } + + static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, +diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c +index eb24322df721a..aeca9c066bf29 100644 +--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c ++++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c +@@ -1500,8 +1500,8 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return ret; + } + +-static void ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct ti_sn65dsi86 *pdata = pwm_chip_to_ti_sn_bridge(chip); + unsigned int pwm_en_inv; +@@ -1512,19 +1512,19 @@ static void ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + + ret = regmap_read(pdata->regmap, SN_PWM_EN_INV_REG, &pwm_en_inv); + if (ret) +- return; ++ return 0; + + ret = ti_sn65dsi86_read_u16(pdata, SN_BACKLIGHT_SCALE_REG, &scale); + if (ret) +- return; ++ return 0; + + ret = ti_sn65dsi86_read_u16(pdata, SN_BACKLIGHT_REG, &backlight); + if (ret) +- return; ++ return 0; + + ret = regmap_read(pdata->regmap, SN_PWM_PRE_DIV_REG, &pre_div); + if (ret) +- return; ++ return 0; + + state->enabled = FIELD_GET(SN_PWM_EN_MASK, pwm_en_inv); + if (FIELD_GET(SN_PWM_INV_MASK, pwm_en_inv)) +@@ -1539,6 +1539,8 @@ static void ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + + if (state->duty_cycle > state->period) + state->duty_cycle = state->period; ++ ++ return 0; + } + + static const struct pwm_ops ti_sn_pwm_ops = { +diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c +index c1a56259226fb..f1c2419334e6f 100644 +--- a/drivers/leds/rgb/leds-qcom-lpg.c ++++ b/drivers/leds/rgb/leds-qcom-lpg.c +@@ -972,8 +972,8 @@ static int lpg_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return ret; + } + +-static void lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct lpg *lpg = container_of(chip, struct lpg, pwm); + struct lpg_channel *chan = &lpg->channels[pwm->hwpwm]; +@@ -986,20 +986,20 @@ static void lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + + ret = regmap_read(lpg->map, chan->base + LPG_SIZE_CLK_REG, &val); + if (ret) +- return; ++ return 0; + + refclk = lpg_clk_rates[val & PWM_CLK_SELECT_MASK]; + if (refclk) { + ret = regmap_read(lpg->map, chan->base + LPG_PREDIV_CLK_REG, &val); + if (ret) +- return; ++ return 0; + + pre_div = lpg_pre_divs[FIELD_GET(PWM_FREQ_PRE_DIV_MASK, val)]; + m = FIELD_GET(PWM_FREQ_EXP_MASK, val); + + ret = regmap_bulk_read(lpg->map, chan->base + PWM_VALUE_REG, &pwm_value, sizeof(pwm_value)); + if (ret) +- return; ++ return 0; + + state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * LPG_RESOLUTION * pre_div * (1 << m), refclk); + state->duty_cycle = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * pwm_value * pre_div * (1 << m), refclk); +@@ -1010,13 +1010,15 @@ static void lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + + ret = regmap_read(lpg->map, chan->base + PWM_ENABLE_CONTROL_REG, &val); + if (ret) +- return; ++ return 0; + + state->enabled = FIELD_GET(LPG_ENABLE_CONTROL_OUTPUT, val); + state->polarity = PWM_POLARITY_NORMAL; + + if (state->duty_cycle > state->period) + state->duty_cycle = state->period; ++ ++ return 0; + } + + static const struct pwm_ops lpg_pwm_ops = { +diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c +index 8e00a4286145b..cdbc23649032c 100644 +--- a/drivers/pwm/pwm-atmel.c ++++ b/drivers/pwm/pwm-atmel.c +@@ -356,8 +356,8 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return 0; + } + +-static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); + u32 sr, cmr; +@@ -396,6 +396,8 @@ static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + state->polarity = PWM_POLARITY_INVERSED; + else + state->polarity = PWM_POLARITY_NORMAL; ++ ++ return 0; + } + + static const struct pwm_ops atmel_pwm_ops = { +diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c +index 7251037d4dd56..97ec131eb7c1b 100644 +--- a/drivers/pwm/pwm-bcm-iproc.c ++++ b/drivers/pwm/pwm-bcm-iproc.c +@@ -68,8 +68,8 @@ static void iproc_pwmc_disable(struct iproc_pwmc *ip, unsigned int channel) + ndelay(400); + } + +-static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct iproc_pwmc *ip = to_iproc_pwmc(chip); + u64 tmp, multi, rate; +@@ -91,7 +91,7 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + if (rate == 0) { + state->period = 0; + state->duty_cycle = 0; +- return; ++ return 0; + } + + value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET); +@@ -107,6 +107,8 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + value = readl(ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm)); + tmp = (value & IPROC_PWM_PERIOD_MAX) * multi; + state->duty_cycle = div64_u64(tmp, rate); ++ ++ return 0; + } + + static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm, +diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c +index 7b357d1cf6421..4099850117ba4 100644 +--- a/drivers/pwm/pwm-crc.c ++++ b/drivers/pwm/pwm-crc.c +@@ -121,8 +121,8 @@ static int crc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return 0; + } + +-static void crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct crystalcove_pwm *crc_pwm = to_crc_pwm(chip); + struct device *dev = crc_pwm->chip.dev; +@@ -132,13 +132,13 @@ static void crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + error = regmap_read(crc_pwm->regmap, PWM0_CLK_DIV, &clk_div_reg); + if (error) { + dev_err(dev, "Error reading PWM0_CLK_DIV %d\n", error); +- return; ++ return 0; + } + + error = regmap_read(crc_pwm->regmap, PWM0_DUTY_CYCLE, &duty_cycle_reg); + if (error) { + dev_err(dev, "Error reading PWM0_DUTY_CYCLE %d\n", error); +- return; ++ return 0; + } + + clk_div = (clk_div_reg & ~PWM_OUTPUT_ENABLE) + 1; +@@ -149,6 +149,8 @@ static void crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + DIV_ROUND_UP_ULL(duty_cycle_reg * state->period, PWM_MAX_LEVEL); + state->polarity = PWM_POLARITY_NORMAL; + state->enabled = !!(clk_div_reg & PWM_OUTPUT_ENABLE); ++ ++ return 0; + } + + static const struct pwm_ops crc_pwm_ops = { +diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c +index 7f10f56c3eb66..11684edc06207 100644 +--- a/drivers/pwm/pwm-cros-ec.c ++++ b/drivers/pwm/pwm-cros-ec.c +@@ -183,8 +183,8 @@ static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return 0; + } + +-static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip); + struct cros_ec_pwm *channel = pwm_get_chip_data(pwm); +@@ -193,7 +193,7 @@ static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + ret = cros_ec_pwm_get_duty(ec_pwm, pwm->hwpwm); + if (ret < 0) { + dev_err(chip->dev, "error getting initial duty: %d\n", ret); +- return; ++ return 0; + } + + state->enabled = (ret > 0); +@@ -212,6 +212,8 @@ static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + state->duty_cycle = channel->duty_cycle; + else + state->duty_cycle = ret; ++ ++ return 0; + } + + static struct pwm_device * +diff --git a/drivers/pwm/pwm-dwc.c b/drivers/pwm/pwm-dwc.c +index 7568300bb11e5..bd2308812096d 100644 +--- a/drivers/pwm/pwm-dwc.c ++++ b/drivers/pwm/pwm-dwc.c +@@ -163,8 +163,8 @@ static int dwc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return 0; + } + +-static void dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct dwc_pwm *dwc = to_dwc_pwm(chip); + u64 duty, period; +@@ -188,6 +188,8 @@ static void dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + state->polarity = PWM_POLARITY_INVERSED; + + pm_runtime_put_sync(chip->dev); ++ ++ return 0; + } + + static const struct pwm_ops dwc_pwm_ops = { +diff --git a/drivers/pwm/pwm-hibvt.c b/drivers/pwm/pwm-hibvt.c +index 333f1b18ff4e6..12c05c155cab0 100644 +--- a/drivers/pwm/pwm-hibvt.c ++++ b/drivers/pwm/pwm-hibvt.c +@@ -128,8 +128,8 @@ static void hibvt_pwm_set_polarity(struct pwm_chip *chip, + PWM_POLARITY_MASK, (0x0 << PWM_POLARITY_SHIFT)); + } + +-static void hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip); + void __iomem *base; +@@ -146,6 +146,8 @@ static void hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + + value = readl(base + PWM_CTRL_ADDR(pwm->hwpwm)); + state->enabled = (PWM_ENABLE_MASK & value); ++ ++ return 0; + } + + static int hibvt_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, +diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c +index e5e7b7c339a8f..ed1aad96fff04 100644 +--- a/drivers/pwm/pwm-imx-tpm.c ++++ b/drivers/pwm/pwm-imx-tpm.c +@@ -132,9 +132,9 @@ static int pwm_imx_tpm_round_state(struct pwm_chip *chip, + return 0; + } + +-static void pwm_imx_tpm_get_state(struct pwm_chip *chip, +- struct pwm_device *pwm, +- struct pwm_state *state) ++static int pwm_imx_tpm_get_state(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip); + u32 rate, val, prescale; +@@ -164,6 +164,8 @@ static void pwm_imx_tpm_get_state(struct pwm_chip *chip, + + /* get channel status */ + state->enabled = FIELD_GET(PWM_IMX_TPM_CnSC_ELS, val) ? true : false; ++ ++ return 0; + } + + /* this function is supposed to be called with mutex hold */ +diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c +index ea91a2f81a9fc..3a22c2fddc452 100644 +--- a/drivers/pwm/pwm-imx27.c ++++ b/drivers/pwm/pwm-imx27.c +@@ -118,8 +118,8 @@ static void pwm_imx27_clk_disable_unprepare(struct pwm_imx27_chip *imx) + clk_disable_unprepare(imx->clk_ipg); + } + +-static void pwm_imx27_get_state(struct pwm_chip *chip, +- struct pwm_device *pwm, struct pwm_state *state) ++static int pwm_imx27_get_state(struct pwm_chip *chip, ++ struct pwm_device *pwm, struct pwm_state *state) + { + struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); + u32 period, prescaler, pwm_clk, val; +@@ -128,7 +128,7 @@ static void pwm_imx27_get_state(struct pwm_chip *chip, + + ret = pwm_imx27_clk_prepare_enable(imx); + if (ret < 0) +- return; ++ return 0; + + val = readl(imx->mmio_base + MX3_PWMCR); + +@@ -170,6 +170,8 @@ static void pwm_imx27_get_state(struct pwm_chip *chip, + state->duty_cycle = DIV_ROUND_UP_ULL(tmp, pwm_clk); + + pwm_imx27_clk_disable_unprepare(imx); ++ ++ return 0; + } + + static void pwm_imx27_sw_reset(struct pwm_chip *chip) +diff --git a/drivers/pwm/pwm-intel-lgm.c b/drivers/pwm/pwm-intel-lgm.c +index b66c350740870..0cd7dd548e82f 100644 +--- a/drivers/pwm/pwm-intel-lgm.c ++++ b/drivers/pwm/pwm-intel-lgm.c +@@ -86,8 +86,8 @@ static int lgm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return lgm_pwm_enable(chip, 1); + } + +-static void lgm_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int lgm_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct lgm_pwm_chip *pc = to_lgm_pwm_chip(chip); + u32 duty, val; +@@ -100,6 +100,8 @@ static void lgm_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + regmap_read(pc->regmap, LGM_PWM_FAN_CON0, &val); + duty = FIELD_GET(LGM_PWM_FAN_DC_MSK, val); + state->duty_cycle = DIV_ROUND_UP(duty * pc->period, LGM_PWM_MAX_DUTY_CYCLE); ++ ++ return 0; + } + + static const struct pwm_ops lgm_pwm_ops = { +diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c +index 54bd95a5cab0c..15aae53db5abb 100644 +--- a/drivers/pwm/pwm-iqs620a.c ++++ b/drivers/pwm/pwm-iqs620a.c +@@ -104,8 +104,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return ret; + } + +-static void iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct iqs620_pwm_private *iqs620_pwm; + +@@ -126,6 +126,8 @@ static void iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + mutex_unlock(&iqs620_pwm->lock); + + state->period = IQS620_PWM_PERIOD_NS; ++ ++ return 0; + } + + static int iqs620_pwm_notifier(struct notifier_block *notifier, +diff --git a/drivers/pwm/pwm-keembay.c b/drivers/pwm/pwm-keembay.c +index 733811b057219..ac02d8bb4a0b5 100644 +--- a/drivers/pwm/pwm-keembay.c ++++ b/drivers/pwm/pwm-keembay.c +@@ -89,8 +89,8 @@ static void keembay_pwm_disable(struct keembay_pwm *priv, int ch) + KMB_PWM_LEADIN_OFFSET(ch)); + } + +-static void keembay_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int keembay_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct keembay_pwm *priv = to_keembay_pwm_dev(chip); + unsigned long long high, low; +@@ -113,6 +113,8 @@ static void keembay_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + state->duty_cycle = DIV_ROUND_UP_ULL(high, clk_rate); + state->period = DIV_ROUND_UP_ULL(high + low, clk_rate); + state->polarity = PWM_POLARITY_NORMAL; ++ ++ return 0; + } + + static int keembay_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, +diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c +index accdef5dd58e7..81ac297b8ba50 100644 +--- a/drivers/pwm/pwm-lpss.c ++++ b/drivers/pwm/pwm-lpss.c +@@ -205,8 +205,8 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return ret; + } + +-static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct pwm_lpss_chip *lpwm = to_lpwm(chip); + unsigned long base_unit_range; +@@ -236,6 +236,8 @@ static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + state->enabled = !!(ctrl & PWM_ENABLE); + + pm_runtime_put(chip->dev); ++ ++ return 0; + } + + static const struct pwm_ops pwm_lpss_ops = { +diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c +index 57112f438c6dd..16d79ca5d8f53 100644 +--- a/drivers/pwm/pwm-meson.c ++++ b/drivers/pwm/pwm-meson.c +@@ -318,8 +318,8 @@ static unsigned int meson_pwm_cnt_to_ns(struct pwm_chip *chip, + return cnt * fin_ns * (channel->pre_div + 1); + } + +-static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct meson_pwm *meson = to_meson_pwm(chip); + struct meson_pwm_channel_data *channel_data; +@@ -327,7 +327,7 @@ static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + u32 value, tmp; + + if (!state) +- return; ++ return 0; + + channel = &meson->channels[pwm->hwpwm]; + channel_data = &meson_pwm_per_channel_data[pwm->hwpwm]; +@@ -357,6 +357,8 @@ static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + state->period = 0; + state->duty_cycle = 0; + } ++ ++ return 0; + } + + static const struct pwm_ops meson_pwm_ops = { +diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c +index 3fbb4bae93a4e..ccf0ccdef29df 100644 +--- a/drivers/pwm/pwm-mtk-disp.c ++++ b/drivers/pwm/pwm-mtk-disp.c +@@ -172,9 +172,9 @@ static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return 0; + } + +-static void mtk_disp_pwm_get_state(struct pwm_chip *chip, +- struct pwm_device *pwm, +- struct pwm_state *state) ++static int mtk_disp_pwm_get_state(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); + u64 rate, period, high_width; +@@ -184,14 +184,14 @@ static void mtk_disp_pwm_get_state(struct pwm_chip *chip, + err = clk_prepare_enable(mdp->clk_main); + if (err < 0) { + dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err)); +- return; ++ return 0; + } + + err = clk_prepare_enable(mdp->clk_mm); + if (err < 0) { + dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err)); + clk_disable_unprepare(mdp->clk_main); +- return; ++ return 0; + } + + rate = clk_get_rate(mdp->clk_main); +@@ -212,6 +212,8 @@ static void mtk_disp_pwm_get_state(struct pwm_chip *chip, + state->polarity = PWM_POLARITY_NORMAL; + clk_disable_unprepare(mdp->clk_mm); + clk_disable_unprepare(mdp->clk_main); ++ ++ return 0; + } + + static const struct pwm_ops mtk_disp_pwm_ops = { +diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c +index f230c10d28bb2..41be244e7dd3d 100644 +--- a/drivers/pwm/pwm-pca9685.c ++++ b/drivers/pwm/pwm-pca9685.c +@@ -431,8 +431,8 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return ret; + } + +-static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct pca9685 *pca = to_pca(chip); + unsigned long long duty; +@@ -458,12 +458,14 @@ static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + */ + state->duty_cycle = 0; + state->enabled = false; +- return; ++ return 0; + } + + state->enabled = true; + duty = pca9685_pwm_get_duty(pca, pwm->hwpwm); + state->duty_cycle = DIV_ROUND_DOWN_ULL(duty * state->period, PCA9685_COUNTER_RANGE); ++ ++ return 0; + } + + static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +diff --git a/drivers/pwm/pwm-raspberrypi-poe.c b/drivers/pwm/pwm-raspberrypi-poe.c +index 6ff73029f367f..2939b71a7ba7b 100644 +--- a/drivers/pwm/pwm-raspberrypi-poe.c ++++ b/drivers/pwm/pwm-raspberrypi-poe.c +@@ -82,9 +82,9 @@ static int raspberrypi_pwm_get_property(struct rpi_firmware *firmware, + return 0; + } + +-static void raspberrypi_pwm_get_state(struct pwm_chip *chip, +- struct pwm_device *pwm, +- struct pwm_state *state) ++static int raspberrypi_pwm_get_state(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct raspberrypi_pwm *rpipwm = raspberrypi_pwm_from_chip(chip); + +@@ -93,6 +93,8 @@ static void raspberrypi_pwm_get_state(struct pwm_chip *chip, + RPI_PWM_MAX_DUTY); + state->enabled = !!(rpipwm->duty_cycle); + state->polarity = PWM_POLARITY_NORMAL; ++ ++ return 0; + } + + static int raspberrypi_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, +diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c +index a5af859217c19..3ec7d17569034 100644 +--- a/drivers/pwm/pwm-rockchip.c ++++ b/drivers/pwm/pwm-rockchip.c +@@ -57,9 +57,9 @@ static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) + return container_of(c, struct rockchip_pwm_chip, chip); + } + +-static void rockchip_pwm_get_state(struct pwm_chip *chip, +- struct pwm_device *pwm, +- struct pwm_state *state) ++static int rockchip_pwm_get_state(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); + u32 enable_conf = pc->data->enable_conf; +@@ -70,11 +70,11 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, + + ret = clk_enable(pc->pclk); + if (ret) +- return; ++ return 0; + + ret = clk_enable(pc->clk); + if (ret) +- return; ++ return 0; + + clk_rate = clk_get_rate(pc->clk); + +@@ -96,6 +96,8 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, + + clk_disable(pc->clk); + clk_disable(pc->pclk); ++ ++ return 0; + } + + static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, +diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c +index 89d53a0f91e65..393a4b97fc19e 100644 +--- a/drivers/pwm/pwm-sifive.c ++++ b/drivers/pwm/pwm-sifive.c +@@ -105,8 +105,8 @@ static void pwm_sifive_update_clock(struct pwm_sifive_ddata *ddata, + "New real_period = %u ns\n", ddata->real_period); + } + +-static void pwm_sifive_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int pwm_sifive_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct pwm_sifive_ddata *ddata = pwm_sifive_chip_to_ddata(chip); + u32 duty, val; +@@ -123,6 +123,8 @@ static void pwm_sifive_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + state->duty_cycle = + (u64)duty * ddata->real_period >> PWM_SIFIVE_CMPWIDTH; + state->polarity = PWM_POLARITY_INVERSED; ++ ++ return 0; + } + + static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm, +diff --git a/drivers/pwm/pwm-sl28cpld.c b/drivers/pwm/pwm-sl28cpld.c +index 589aeaaa6ac86..e64900ad4ba1e 100644 +--- a/drivers/pwm/pwm-sl28cpld.c ++++ b/drivers/pwm/pwm-sl28cpld.c +@@ -87,9 +87,9 @@ struct sl28cpld_pwm { + #define sl28cpld_pwm_from_chip(_chip) \ + container_of(_chip, struct sl28cpld_pwm, pwm_chip) + +-static void sl28cpld_pwm_get_state(struct pwm_chip *chip, +- struct pwm_device *pwm, +- struct pwm_state *state) ++static int sl28cpld_pwm_get_state(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct sl28cpld_pwm *priv = sl28cpld_pwm_from_chip(chip); + unsigned int reg; +@@ -115,6 +115,8 @@ static void sl28cpld_pwm_get_state(struct pwm_chip *chip, + * the PWM core. + */ + state->duty_cycle = min(state->duty_cycle, state->period); ++ ++ return 0; + } + + static int sl28cpld_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, +diff --git a/drivers/pwm/pwm-sprd.c b/drivers/pwm/pwm-sprd.c +index 7004f55bbf115..bda8bc5af9768 100644 +--- a/drivers/pwm/pwm-sprd.c ++++ b/drivers/pwm/pwm-sprd.c +@@ -65,8 +65,8 @@ static void sprd_pwm_write(struct sprd_pwm_chip *spc, u32 hwid, + writel_relaxed(val, spc->base + offset); + } + +-static void sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct sprd_pwm_chip *spc = + container_of(chip, struct sprd_pwm_chip, chip); +@@ -83,7 +83,7 @@ static void sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + if (ret) { + dev_err(spc->dev, "failed to enable pwm%u clocks\n", + pwm->hwpwm); +- return; ++ return 0; + } + + val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_ENABLE); +@@ -113,6 +113,8 @@ static void sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + /* Disable PWM clocks if the PWM channel is not in enable state. */ + if (!state->enabled) + clk_bulk_disable_unprepare(SPRD_PWM_CHN_CLKS_NUM, chn->clks); ++ ++ return 0; + } + + static int sprd_pwm_config(struct sprd_pwm_chip *spc, struct pwm_device *pwm, +diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c +index 61a1c87cd5016..31a185c6b8da4 100644 +--- a/drivers/pwm/pwm-stm32-lp.c ++++ b/drivers/pwm/pwm-stm32-lp.c +@@ -157,9 +157,9 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return ret; + } + +-static void stm32_pwm_lp_get_state(struct pwm_chip *chip, +- struct pwm_device *pwm, +- struct pwm_state *state) ++static int stm32_pwm_lp_get_state(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip); + unsigned long rate = clk_get_rate(priv->clk); +@@ -185,6 +185,8 @@ static void stm32_pwm_lp_get_state(struct pwm_chip *chip, + tmp = prd - val; + tmp = (tmp << presc) * NSEC_PER_SEC; + state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate); ++ ++ return 0; + } + + static const struct pwm_ops stm32_pwm_lp_ops = { +diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c +index c8445b0a33392..37d75e252d4e7 100644 +--- a/drivers/pwm/pwm-sun4i.c ++++ b/drivers/pwm/pwm-sun4i.c +@@ -108,9 +108,9 @@ static inline void sun4i_pwm_writel(struct sun4i_pwm_chip *chip, + writel(val, chip->base + offset); + } + +-static void sun4i_pwm_get_state(struct pwm_chip *chip, +- struct pwm_device *pwm, +- struct pwm_state *state) ++static int sun4i_pwm_get_state(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); + u64 clk_rate, tmp; +@@ -132,7 +132,7 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip, + state->duty_cycle = DIV_ROUND_UP_ULL(state->period, 2); + state->polarity = PWM_POLARITY_NORMAL; + state->enabled = true; +- return; ++ return 0; + } + + if ((PWM_REG_PRESCAL(val, pwm->hwpwm) == PWM_PRESCAL_MASK) && +@@ -142,7 +142,7 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip, + prescaler = prescaler_table[PWM_REG_PRESCAL(val, pwm->hwpwm)]; + + if (prescaler == 0) +- return; ++ return 0; + + if (val & BIT_CH(PWM_ACT_STATE, pwm->hwpwm)) + state->polarity = PWM_POLARITY_NORMAL; +@@ -162,6 +162,8 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip, + + tmp = (u64)prescaler * NSEC_PER_SEC * PWM_REG_PRD(val); + state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate); ++ ++ return 0; + } + + static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm, +diff --git a/drivers/pwm/pwm-sunplus.c b/drivers/pwm/pwm-sunplus.c +index e776fd16512de..d6ebe9f03b354 100644 +--- a/drivers/pwm/pwm-sunplus.c ++++ b/drivers/pwm/pwm-sunplus.c +@@ -124,8 +124,8 @@ static int sunplus_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return 0; + } + +-static void sunplus_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int sunplus_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct sunplus_pwm *priv = to_sunplus_pwm(chip); + u32 mode0, dd_freq, duty; +@@ -155,6 +155,8 @@ static void sunplus_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + } + + state->polarity = PWM_POLARITY_NORMAL; ++ ++ return 0; + } + + static const struct pwm_ops sunplus_pwm_ops = { +diff --git a/drivers/pwm/pwm-visconti.c b/drivers/pwm/pwm-visconti.c +index 927c4cbb1daf0..e3fb79b3e2a7a 100644 +--- a/drivers/pwm/pwm-visconti.c ++++ b/drivers/pwm/pwm-visconti.c +@@ -103,8 +103,8 @@ static int visconti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + return 0; + } + +-static void visconti_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state) ++static int visconti_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) + { + struct visconti_pwm_chip *priv = visconti_pwm_from_chip(chip); + u32 period, duty, pwmc0, pwmc0_clk; +@@ -122,6 +122,8 @@ static void visconti_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm + state->polarity = PWM_POLARITY_NORMAL; + + state->enabled = true; ++ ++ return 0; + } + + static const struct pwm_ops visconti_pwm_ops = { +diff --git a/drivers/pwm/pwm-xilinx.c b/drivers/pwm/pwm-xilinx.c +index 4dab2b86c4276..f7a50fdcd9a52 100644 +--- a/drivers/pwm/pwm-xilinx.c ++++ b/drivers/pwm/pwm-xilinx.c +@@ -169,9 +169,9 @@ static int xilinx_pwm_apply(struct pwm_chip *chip, struct pwm_device *unused, + return 0; + } + +-static void xilinx_pwm_get_state(struct pwm_chip *chip, +- struct pwm_device *unused, +- struct pwm_state *state) ++static int xilinx_pwm_get_state(struct pwm_chip *chip, ++ struct pwm_device *unused, ++ struct pwm_state *state) + { + struct xilinx_timer_priv *priv = xilinx_pwm_chip_to_priv(chip); + u32 tlr0, tlr1, tcsr0, tcsr1; +@@ -191,6 +191,8 @@ static void xilinx_pwm_get_state(struct pwm_chip *chip, + */ + if (state->period == state->duty_cycle) + state->duty_cycle = 0; ++ ++ return 0; + } + + static const struct pwm_ops xilinx_pwm_ops = { +diff --git a/include/linux/pwm.h b/include/linux/pwm.h +index d70c6e5a839d6..4de09163c968a 100644 +--- a/include/linux/pwm.h ++++ b/include/linux/pwm.h +@@ -276,8 +276,8 @@ struct pwm_ops { + struct pwm_capture *result, unsigned long timeout); + int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state); +- void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, +- struct pwm_state *state); ++ int (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state); + struct module *owner; + }; + +-- +2.39.2 + diff --git a/queue-6.1/pwm-meson-explicitly-set-.polarity-in-.get_state.patch b/queue-6.1/pwm-meson-explicitly-set-.polarity-in-.get_state.patch new file mode 100644 index 00000000000..8a376adac38 --- /dev/null +++ b/queue-6.1/pwm-meson-explicitly-set-.polarity-in-.get_state.patch @@ -0,0 +1,67 @@ +From 162e87a9ef1152bdeb86d4b14c6ebb3bc56676f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Mar 2023 22:45:44 +0100 +Subject: pwm: meson: Explicitly set .polarity 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 8caa81eb950cb2e9d2d6959b37d853162d197f57 ] + +The driver only supports normal polarity. Complete the implementation of +.get_state() by setting .polarity accordingly. + +This fixes a regression that was possible since commit c73a3107624d +("pwm: Handle .get_state() failures") which stopped to zero-initialize +the state passed to the .get_state() callback. This was reported at +https://forum.odroid.com/viewtopic.php?f=177&t=46360 . While this was an +unintended side effect, the real issue is the driver's callback not +setting the polarity. + +There is a complicating fact, that the .apply() callback fakes support +for inversed polarity. This is not (and cannot) be matched by +.get_state(). As fixing this isn't easy, only point it out in a comment +to prevent authors of other drivers from copying that approach. + +Fixes: c375bcbaabdb ("pwm: meson: Read the full hardware state in meson_pwm_get_state()") +Reported-by: Munehisa Kamata +Acked-by: Martin Blumenstingl +Link: https://lore.kernel.org/r/20230310191405.2606296-1-u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-meson.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c +index 16d79ca5d8f53..5cd7b90872c62 100644 +--- a/drivers/pwm/pwm-meson.c ++++ b/drivers/pwm/pwm-meson.c +@@ -162,6 +162,12 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, + duty = state->duty_cycle; + period = state->period; + ++ /* ++ * Note this is wrong. The result is an output wave that isn't really ++ * inverted and so is wrongly identified by .get_state as normal. ++ * Fixing this needs some care however as some machines might rely on ++ * this. ++ */ + if (state->polarity == PWM_POLARITY_INVERSED) + duty = period - duty; + +@@ -358,6 +364,8 @@ static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + state->duty_cycle = 0; + } + ++ state->polarity = PWM_POLARITY_NORMAL; ++ + return 0; + } + +-- +2.39.2 + diff --git a/queue-6.1/pwm-sprd-explicitly-set-.polarity-in-.get_state.patch b/queue-6.1/pwm-sprd-explicitly-set-.polarity-in-.get_state.patch new file mode 100644 index 00000000000..fb0bc8b2596 --- /dev/null +++ b/queue-6.1/pwm-sprd-explicitly-set-.polarity-in-.get_state.patch @@ -0,0 +1,39 @@ +From c233b6ec807c8d5091b1d7e6dface8dfcff61028 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Mar 2023 22:45:43 +0100 +Subject: pwm: sprd: Explicitly set .polarity 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 2be4dcf6627e1bcbbef8e6ba1811f5127d39202c ] + +The driver only supports normal polarity. Complete the implementation of +.get_state() by setting .polarity accordingly. + +Fixes: 8aae4b02e8a6 ("pwm: sprd: Add Spreadtrum PWM support") +Link: https://lore.kernel.org/r/20230228135508.1798428-5-u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-sprd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pwm/pwm-sprd.c b/drivers/pwm/pwm-sprd.c +index bda8bc5af9768..87d5cb7f67d67 100644 +--- a/drivers/pwm/pwm-sprd.c ++++ b/drivers/pwm/pwm-sprd.c +@@ -109,6 +109,7 @@ static int sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + duty = val & SPRD_PWM_DUTY_MSK; + tmp = (prescale + 1) * NSEC_PER_SEC * duty; + state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate); ++ state->polarity = PWM_POLARITY_NORMAL; + + /* Disable PWM clocks if the PWM channel is not in enable state. */ + if (!state->enabled) +-- +2.39.2 + diff --git a/queue-6.1/raw-fix-null-deref-in-raw_get_next.patch b/queue-6.1/raw-fix-null-deref-in-raw_get_next.patch new file mode 100644 index 00000000000..9775146433d --- /dev/null +++ b/queue-6.1/raw-fix-null-deref-in-raw_get_next.patch @@ -0,0 +1,348 @@ +From 7c0fc4acb71386b776de5de42f683e2930488249 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Apr 2023 12:49:58 -0700 +Subject: raw: Fix NULL deref in raw_get_next(). + +From: Kuniyuki Iwashima + +[ Upstream commit 0a78cf7264d29abeca098eae0b188a10aabc8a32 ] + +Dae R. Jeong reported a NULL deref in raw_get_next() [0]. + +It seems that the repro was running these sequences in parallel so +that one thread was iterating on a socket that was being freed in +another netns. + + unshare(0x40060200) + r0 = syz_open_procfs(0x0, &(0x7f0000002080)='net/raw\x00') + socket$inet_icmp_raw(0x2, 0x3, 0x1) + pread64(r0, &(0x7f0000000000)=""/10, 0xa, 0x10000000007f) + +After commit 0daf07e52709 ("raw: convert raw sockets to RCU"), we +use RCU and hlist_nulls_for_each_entry() to iterate over SOCK_RAW +sockets. However, we should use spinlock for slow paths to avoid +the NULL deref. + +Also, SOCK_RAW does not use SLAB_TYPESAFE_BY_RCU, and the slab object +is not reused during iteration in the grace period. In fact, the +lockless readers do not check the nulls marker with get_nulls_value(). +So, SOCK_RAW should use hlist instead of hlist_nulls. + +Instead of adding an unnecessary barrier by sk_nulls_for_each_rcu(), +let's convert hlist_nulls to hlist and use sk_for_each_rcu() for +fast paths and sk_for_each() and spinlock for /proc/net/raw. + +[0]: +general protection fault, probably for non-canonical address 0xdffffc0000000005: 0000 [#1] PREEMPT SMP KASAN +KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f] +CPU: 2 PID: 20952 Comm: syz-executor.0 Not tainted 6.2.0-g048ec869bafd-dirty #7 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 +RIP: 0010:read_pnet include/net/net_namespace.h:383 [inline] +RIP: 0010:sock_net include/net/sock.h:649 [inline] +RIP: 0010:raw_get_next net/ipv4/raw.c:974 [inline] +RIP: 0010:raw_get_idx net/ipv4/raw.c:986 [inline] +RIP: 0010:raw_seq_start+0x431/0x800 net/ipv4/raw.c:995 +Code: ef e8 33 3d 94 f7 49 8b 6d 00 4c 89 ef e8 b7 65 5f f7 49 89 ed 49 83 c5 98 0f 84 9a 00 00 00 48 83 c5 c8 48 89 e8 48 c1 e8 03 <42> 80 3c 30 00 74 08 48 89 ef e8 00 3d 94 f7 4c 8b 7d 00 48 89 ef +RSP: 0018:ffffc9001154f9b0 EFLAGS: 00010206 +RAX: 0000000000000005 RBX: 1ffff1100302c8fd RCX: 0000000000000000 +RDX: 0000000000000028 RSI: ffffc9001154f988 RDI: ffffc9000f77a338 +RBP: 0000000000000029 R08: ffffffff8a50ffb4 R09: fffffbfff24b6bd9 +R10: fffffbfff24b6bd9 R11: 0000000000000000 R12: ffff88801db73b78 +R13: fffffffffffffff9 R14: dffffc0000000000 R15: 0000000000000030 +FS: 00007f843ae8e700(0000) GS:ffff888063700000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000055bb9614b35f CR3: 000000003c672000 CR4: 00000000003506e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + + seq_read_iter+0x4c6/0x10f0 fs/seq_file.c:225 + seq_read+0x224/0x320 fs/seq_file.c:162 + pde_read fs/proc/inode.c:316 [inline] + proc_reg_read+0x23f/0x330 fs/proc/inode.c:328 + vfs_read+0x31e/0xd30 fs/read_write.c:468 + ksys_pread64 fs/read_write.c:665 [inline] + __do_sys_pread64 fs/read_write.c:675 [inline] + __se_sys_pread64 fs/read_write.c:672 [inline] + __x64_sys_pread64+0x1e9/0x280 fs/read_write.c:672 + do_syscall_x64 arch/x86/entry/common.c:51 [inline] + do_syscall_64+0x4e/0xa0 arch/x86/entry/common.c:82 + entry_SYSCALL_64_after_hwframe+0x63/0xcd +RIP: 0033:0x478d29 +Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f843ae8dbe8 EFLAGS: 00000246 ORIG_RAX: 0000000000000011 +RAX: ffffffffffffffda RBX: 0000000000791408 RCX: 0000000000478d29 +RDX: 000000000000000a RSI: 0000000020000000 RDI: 0000000000000003 +RBP: 00000000f477909a R08: 0000000000000000 R09: 0000000000000000 +R10: 000010000000007f R11: 0000000000000246 R12: 0000000000791740 +R13: 0000000000791414 R14: 0000000000791408 R15: 00007ffc2eb48a50 + +Modules linked in: +---[ end trace 0000000000000000 ]--- +RIP: 0010:read_pnet include/net/net_namespace.h:383 [inline] +RIP: 0010:sock_net include/net/sock.h:649 [inline] +RIP: 0010:raw_get_next net/ipv4/raw.c:974 [inline] +RIP: 0010:raw_get_idx net/ipv4/raw.c:986 [inline] +RIP: 0010:raw_seq_start+0x431/0x800 net/ipv4/raw.c:995 +Code: ef e8 33 3d 94 f7 49 8b 6d 00 4c 89 ef e8 b7 65 5f f7 49 89 ed 49 83 c5 98 0f 84 9a 00 00 00 48 83 c5 c8 48 89 e8 48 c1 e8 03 <42> 80 3c 30 00 74 08 48 89 ef e8 00 3d 94 f7 4c 8b 7d 00 48 89 ef +RSP: 0018:ffffc9001154f9b0 EFLAGS: 00010206 +RAX: 0000000000000005 RBX: 1ffff1100302c8fd RCX: 0000000000000000 +RDX: 0000000000000028 RSI: ffffc9001154f988 RDI: ffffc9000f77a338 +RBP: 0000000000000029 R08: ffffffff8a50ffb4 R09: fffffbfff24b6bd9 +R10: fffffbfff24b6bd9 R11: 0000000000000000 R12: ffff88801db73b78 +R13: fffffffffffffff9 R14: dffffc0000000000 R15: 0000000000000030 +FS: 00007f843ae8e700(0000) GS:ffff888063700000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f92ff166000 CR3: 000000003c672000 CR4: 00000000003506e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + +Fixes: 0daf07e52709 ("raw: convert raw sockets to RCU") +Reported-by: syzbot +Reported-by: Dae R. Jeong +Link: https://lore.kernel.org/netdev/ZCA2mGV_cmq7lIfV@dragonet/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/raw.h | 4 ++-- + net/ipv4/raw.c | 36 +++++++++++++++++++----------------- + net/ipv4/raw_diag.c | 10 ++++------ + net/ipv6/raw.c | 10 ++++------ + 4 files changed, 29 insertions(+), 31 deletions(-) + +diff --git a/include/net/raw.h b/include/net/raw.h +index 2c004c20ed996..3af5289fdead9 100644 +--- a/include/net/raw.h ++++ b/include/net/raw.h +@@ -37,7 +37,7 @@ int raw_rcv(struct sock *, struct sk_buff *); + struct raw_hashinfo { + spinlock_t lock; + +- struct hlist_nulls_head ht[RAW_HTABLE_SIZE] ____cacheline_aligned; ++ struct hlist_head ht[RAW_HTABLE_SIZE] ____cacheline_aligned; + }; + + static inline u32 raw_hashfunc(const struct net *net, u32 proto) +@@ -51,7 +51,7 @@ static inline void raw_hashinfo_init(struct raw_hashinfo *hashinfo) + + spin_lock_init(&hashinfo->lock); + for (i = 0; i < RAW_HTABLE_SIZE; i++) +- INIT_HLIST_NULLS_HEAD(&hashinfo->ht[i], i); ++ INIT_HLIST_HEAD(&hashinfo->ht[i]); + } + + #ifdef CONFIG_PROC_FS +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index 2a53a0bf29232..af03aa8a8e513 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -91,12 +91,12 @@ EXPORT_SYMBOL_GPL(raw_v4_hashinfo); + int raw_hash_sk(struct sock *sk) + { + struct raw_hashinfo *h = sk->sk_prot->h.raw_hash; +- struct hlist_nulls_head *hlist; ++ struct hlist_head *hlist; + + hlist = &h->ht[raw_hashfunc(sock_net(sk), inet_sk(sk)->inet_num)]; + + spin_lock(&h->lock); +- __sk_nulls_add_node_rcu(sk, hlist); ++ sk_add_node_rcu(sk, hlist); + sock_set_flag(sk, SOCK_RCU_FREE); + spin_unlock(&h->lock); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); +@@ -110,7 +110,7 @@ void raw_unhash_sk(struct sock *sk) + struct raw_hashinfo *h = sk->sk_prot->h.raw_hash; + + spin_lock(&h->lock); +- if (__sk_nulls_del_node_init_rcu(sk)) ++ if (sk_del_node_init_rcu(sk)) + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); + spin_unlock(&h->lock); + } +@@ -163,16 +163,15 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb) + static int raw_v4_input(struct net *net, struct sk_buff *skb, + const struct iphdr *iph, int hash) + { +- struct hlist_nulls_head *hlist; +- struct hlist_nulls_node *hnode; + int sdif = inet_sdif(skb); ++ struct hlist_head *hlist; + int dif = inet_iif(skb); + int delivered = 0; + struct sock *sk; + + hlist = &raw_v4_hashinfo.ht[hash]; + rcu_read_lock(); +- sk_nulls_for_each(sk, hnode, hlist) { ++ sk_for_each_rcu(sk, hlist) { + if (!raw_v4_match(net, sk, iph->protocol, + iph->saddr, iph->daddr, dif, sdif)) + continue; +@@ -264,10 +263,9 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) + void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) + { + struct net *net = dev_net(skb->dev); +- struct hlist_nulls_head *hlist; +- struct hlist_nulls_node *hnode; + int dif = skb->dev->ifindex; + int sdif = inet_sdif(skb); ++ struct hlist_head *hlist; + const struct iphdr *iph; + struct sock *sk; + int hash; +@@ -276,7 +274,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) + hlist = &raw_v4_hashinfo.ht[hash]; + + rcu_read_lock(); +- sk_nulls_for_each(sk, hnode, hlist) { ++ sk_for_each_rcu(sk, hlist) { + iph = (const struct iphdr *)skb->data; + if (!raw_v4_match(net, sk, iph->protocol, + iph->daddr, iph->saddr, dif, sdif)) +@@ -948,14 +946,13 @@ static struct sock *raw_get_first(struct seq_file *seq, int bucket) + { + struct raw_hashinfo *h = pde_data(file_inode(seq->file)); + struct raw_iter_state *state = raw_seq_private(seq); +- struct hlist_nulls_head *hlist; +- struct hlist_nulls_node *hnode; ++ struct hlist_head *hlist; + struct sock *sk; + + for (state->bucket = bucket; state->bucket < RAW_HTABLE_SIZE; + ++state->bucket) { + hlist = &h->ht[state->bucket]; +- sk_nulls_for_each(sk, hnode, hlist) { ++ sk_for_each(sk, hlist) { + if (sock_net(sk) == seq_file_net(seq)) + return sk; + } +@@ -968,7 +965,7 @@ static struct sock *raw_get_next(struct seq_file *seq, struct sock *sk) + struct raw_iter_state *state = raw_seq_private(seq); + + do { +- sk = sk_nulls_next(sk); ++ sk = sk_next(sk); + } while (sk && sock_net(sk) != seq_file_net(seq)); + + if (!sk) +@@ -987,9 +984,12 @@ static struct sock *raw_get_idx(struct seq_file *seq, loff_t pos) + } + + void *raw_seq_start(struct seq_file *seq, loff_t *pos) +- __acquires(RCU) ++ __acquires(&h->lock) + { +- rcu_read_lock(); ++ struct raw_hashinfo *h = pde_data(file_inode(seq->file)); ++ ++ spin_lock(&h->lock); ++ + return *pos ? raw_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; + } + EXPORT_SYMBOL_GPL(raw_seq_start); +@@ -1008,9 +1008,11 @@ void *raw_seq_next(struct seq_file *seq, void *v, loff_t *pos) + EXPORT_SYMBOL_GPL(raw_seq_next); + + void raw_seq_stop(struct seq_file *seq, void *v) +- __releases(RCU) ++ __releases(&h->lock) + { +- rcu_read_unlock(); ++ struct raw_hashinfo *h = pde_data(file_inode(seq->file)); ++ ++ spin_unlock(&h->lock); + } + EXPORT_SYMBOL_GPL(raw_seq_stop); + +diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c +index 999321834b94a..da3591a66a169 100644 +--- a/net/ipv4/raw_diag.c ++++ b/net/ipv4/raw_diag.c +@@ -57,8 +57,7 @@ static bool raw_lookup(struct net *net, struct sock *sk, + static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 *r) + { + struct raw_hashinfo *hashinfo = raw_get_hashinfo(r); +- struct hlist_nulls_head *hlist; +- struct hlist_nulls_node *hnode; ++ struct hlist_head *hlist; + struct sock *sk; + int slot; + +@@ -68,7 +67,7 @@ static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 + rcu_read_lock(); + for (slot = 0; slot < RAW_HTABLE_SIZE; slot++) { + hlist = &hashinfo->ht[slot]; +- sk_nulls_for_each(sk, hnode, hlist) { ++ sk_for_each_rcu(sk, hlist) { + if (raw_lookup(net, sk, r)) { + /* + * Grab it and keep until we fill +@@ -142,9 +141,8 @@ static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, + struct raw_hashinfo *hashinfo = raw_get_hashinfo(r); + struct net *net = sock_net(skb->sk); + struct inet_diag_dump_data *cb_data; +- struct hlist_nulls_head *hlist; +- struct hlist_nulls_node *hnode; + int num, s_num, slot, s_slot; ++ struct hlist_head *hlist; + struct sock *sk = NULL; + struct nlattr *bc; + +@@ -161,7 +159,7 @@ static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, + num = 0; + + hlist = &hashinfo->ht[slot]; +- sk_nulls_for_each(sk, hnode, hlist) { ++ sk_for_each_rcu(sk, hlist) { + struct inet_sock *inet = inet_sk(sk); + + if (!net_eq(sock_net(sk), net)) +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 350fb81eda143..9ee1506e23ab1 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -141,10 +141,9 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister); + static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) + { + struct net *net = dev_net(skb->dev); +- struct hlist_nulls_head *hlist; +- struct hlist_nulls_node *hnode; + const struct in6_addr *saddr; + const struct in6_addr *daddr; ++ struct hlist_head *hlist; + struct sock *sk; + bool delivered = false; + __u8 hash; +@@ -155,7 +154,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) + hash = raw_hashfunc(net, nexthdr); + hlist = &raw_v6_hashinfo.ht[hash]; + rcu_read_lock(); +- sk_nulls_for_each(sk, hnode, hlist) { ++ sk_for_each_rcu(sk, hlist) { + int filtered; + + if (!raw_v6_match(net, sk, nexthdr, daddr, saddr, +@@ -333,15 +332,14 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + u8 type, u8 code, int inner_offset, __be32 info) + { + struct net *net = dev_net(skb->dev); +- struct hlist_nulls_head *hlist; +- struct hlist_nulls_node *hnode; ++ struct hlist_head *hlist; + struct sock *sk; + int hash; + + hash = raw_hashfunc(net, nexthdr); + hlist = &raw_v6_hashinfo.ht[hash]; + rcu_read_lock(); +- sk_nulls_for_each(sk, hnode, hlist) { ++ sk_for_each_rcu(sk, hlist) { + /* Note: ipv6_hdr(skb) != skb->data */ + const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data; + +-- +2.39.2 + diff --git a/queue-6.1/raw-use-net_hash_mix-in-hash-function.patch b/queue-6.1/raw-use-net_hash_mix-in-hash-function.patch new file mode 100644 index 00000000000..794f6cfd1ed --- /dev/null +++ b/queue-6.1/raw-use-net_hash_mix-in-hash-function.patch @@ -0,0 +1,139 @@ +From 894ff41cf7d488d1ffdfbfc8c3e0c6e28e7f078e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Feb 2023 09:41:00 +0000 +Subject: raw: use net_hash_mix() in hash function + +From: Eric Dumazet + +[ Upstream commit 6579f5bacc2c4cbc5ef6abb45352416939d1f844 ] + +Some applications seem to rely on RAW sockets. + +If they use private netns, we can avoid piling all RAW +sockets bound to a given protocol into a single bucket. + +Also place (struct raw_hashinfo).lock into its own +cache line to limit false sharing. + +Alternative would be to have per-netns hashtables, +but this seems too expensive for most netns +where RAW sockets are not used. + +Signed-off-by: Eric Dumazet +Signed-off-by: Jakub Kicinski +Stable-dep-of: 0a78cf7264d2 ("raw: Fix NULL deref in raw_get_next().") +Signed-off-by: Sasha Levin +--- + include/net/raw.h | 13 +++++++++++-- + net/ipv4/raw.c | 13 +++++++------ + net/ipv6/raw.c | 4 ++-- + 3 files changed, 20 insertions(+), 10 deletions(-) + +diff --git a/include/net/raw.h b/include/net/raw.h +index 5e665934ebc7c..2c004c20ed996 100644 +--- a/include/net/raw.h ++++ b/include/net/raw.h +@@ -15,6 +15,8 @@ + + #include + #include ++#include ++#include + #include + + extern struct proto raw_prot; +@@ -29,13 +31,20 @@ int raw_local_deliver(struct sk_buff *, int); + + int raw_rcv(struct sock *, struct sk_buff *); + +-#define RAW_HTABLE_SIZE MAX_INET_PROTOS ++#define RAW_HTABLE_LOG 8 ++#define RAW_HTABLE_SIZE (1U << RAW_HTABLE_LOG) + + struct raw_hashinfo { + spinlock_t lock; +- struct hlist_nulls_head ht[RAW_HTABLE_SIZE]; ++ ++ struct hlist_nulls_head ht[RAW_HTABLE_SIZE] ____cacheline_aligned; + }; + ++static inline u32 raw_hashfunc(const struct net *net, u32 proto) ++{ ++ return hash_32(net_hash_mix(net) ^ proto, RAW_HTABLE_LOG); ++} ++ + static inline void raw_hashinfo_init(struct raw_hashinfo *hashinfo) + { + int i; +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index 006c1f0ed8b47..2a53a0bf29232 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -93,7 +93,7 @@ int raw_hash_sk(struct sock *sk) + struct raw_hashinfo *h = sk->sk_prot->h.raw_hash; + struct hlist_nulls_head *hlist; + +- hlist = &h->ht[inet_sk(sk)->inet_num & (RAW_HTABLE_SIZE - 1)]; ++ hlist = &h->ht[raw_hashfunc(sock_net(sk), inet_sk(sk)->inet_num)]; + + spin_lock(&h->lock); + __sk_nulls_add_node_rcu(sk, hlist); +@@ -160,9 +160,9 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb) + * RFC 1122: SHOULD pass TOS value up to the transport layer. + * -> It does. And not only TOS, but all IP header. + */ +-static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) ++static int raw_v4_input(struct net *net, struct sk_buff *skb, ++ const struct iphdr *iph, int hash) + { +- struct net *net = dev_net(skb->dev); + struct hlist_nulls_head *hlist; + struct hlist_nulls_node *hnode; + int sdif = inet_sdif(skb); +@@ -193,9 +193,10 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) + + int raw_local_deliver(struct sk_buff *skb, int protocol) + { +- int hash = protocol & (RAW_HTABLE_SIZE - 1); ++ struct net *net = dev_net(skb->dev); + +- return raw_v4_input(skb, ip_hdr(skb), hash); ++ return raw_v4_input(net, skb, ip_hdr(skb), ++ raw_hashfunc(net, protocol)); + } + + static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) +@@ -271,7 +272,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) + struct sock *sk; + int hash; + +- hash = protocol & (RAW_HTABLE_SIZE - 1); ++ hash = raw_hashfunc(net, protocol); + hlist = &raw_v4_hashinfo.ht[hash]; + + rcu_read_lock(); +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 8ffeac7456567..350fb81eda143 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -152,7 +152,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) + saddr = &ipv6_hdr(skb)->saddr; + daddr = saddr + 1; + +- hash = nexthdr & (RAW_HTABLE_SIZE - 1); ++ hash = raw_hashfunc(net, nexthdr); + hlist = &raw_v6_hashinfo.ht[hash]; + rcu_read_lock(); + sk_nulls_for_each(sk, hnode, hlist) { +@@ -338,7 +338,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + struct sock *sk; + int hash; + +- hash = nexthdr & (RAW_HTABLE_SIZE - 1); ++ hash = raw_hashfunc(net, nexthdr); + hlist = &raw_v6_hashinfo.ht[hash]; + rcu_read_lock(); + sk_nulls_for_each(sk, hnode, hlist) { +-- +2.39.2 + diff --git a/queue-6.1/sctp-check-send-stream-number-after-wait_for_sndbuf.patch b/queue-6.1/sctp-check-send-stream-number-after-wait_for_sndbuf.patch new file mode 100644 index 00000000000..1df9282d275 --- /dev/null +++ b/queue-6.1/sctp-check-send-stream-number-after-wait_for_sndbuf.patch @@ -0,0 +1,66 @@ +From 9f81b336211eb8c418d9f508c7bf4358692d2c9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Apr 2023 19:09:57 -0400 +Subject: sctp: check send stream number after wait_for_sndbuf + +From: Xin Long + +[ Upstream commit 2584024b23552c00d95b50255e47bd18d306d31a ] + +This patch fixes a corner case where the asoc out stream count may change +after wait_for_sndbuf. + +When the main thread in the client starts a connection, if its out stream +count is set to N while the in stream count in the server is set to N - 2, +another thread in the client keeps sending the msgs with stream number +N - 1, and waits for sndbuf before processing INIT_ACK. + +However, after processing INIT_ACK, the out stream count in the client is +shrunk to N - 2, the same to the in stream count in the server. The crash +occurs when the thread waiting for sndbuf is awake and sends the msg in a +non-existing stream(N - 1), the call trace is as below: + + KASAN: null-ptr-deref in range [0x0000000000000038-0x000000000000003f] + Call Trace: + + sctp_cmd_send_msg net/sctp/sm_sideeffect.c:1114 [inline] + sctp_cmd_interpreter net/sctp/sm_sideeffect.c:1777 [inline] + sctp_side_effects net/sctp/sm_sideeffect.c:1199 [inline] + sctp_do_sm+0x197d/0x5310 net/sctp/sm_sideeffect.c:1170 + sctp_primitive_SEND+0x9f/0xc0 net/sctp/primitive.c:163 + sctp_sendmsg_to_asoc+0x10eb/0x1a30 net/sctp/socket.c:1868 + sctp_sendmsg+0x8d4/0x1d90 net/sctp/socket.c:2026 + inet_sendmsg+0x9d/0xe0 net/ipv4/af_inet.c:825 + sock_sendmsg_nosec net/socket.c:722 [inline] + sock_sendmsg+0xde/0x190 net/socket.c:745 + +The fix is to add an unlikely check for the send stream number after the +thread wakes up from the wait_for_sndbuf. + +Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations") +Reported-by: syzbot+47c24ca20a2fa01f082e@syzkaller.appspotmail.com +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/sctp/socket.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 83628c347744b..507b2ad5ef7c7 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -1829,6 +1829,10 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, + err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len); + if (err) + goto err; ++ if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt)) { ++ err = -EINVAL; ++ goto err; ++ } + } + + if (sctp_state(asoc, CLOSED)) { +-- +2.39.2 + diff --git a/queue-6.1/series b/queue-6.1/series index c9dda8f7623..eda125275f6 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -6,3 +6,50 @@ kvm-arm64-pmu-align-chained-counter-implementation-w.patch kvm-arm64-pmu-distinguish-between-64bit-counter-and-.patch kvm-arm64-pmu-sanitise-pmcr_el0.lp-on-first-vcpu-run.patch kvm-arm64-pmu-don-t-save-pmcr_el0.-c-p-for-the-vcpu.patch +gpio-gpio_regmap-select-regmap-instead-of-depending-.patch +drivers-vmbus-check-for-channel-allocation-before-lo.patch +asoc-sof-ipc4-ensure-dsp-is-in-d0i0-during-sof_ipc4_.patch +pwm-make-.get_state-callback-return-an-error-code.patch +pwm-hibvt-explicitly-set-.polarity-in-.get_state.patch +pwm-cros-ec-explicitly-set-.polarity-in-.get_state.patch +pwm-iqs620a-explicitly-set-.polarity-in-.get_state.patch +pwm-sprd-explicitly-set-.polarity-in-.get_state.patch +pwm-meson-explicitly-set-.polarity-in-.get_state.patch +asoc-codecs-lpass-fix-the-order-or-clks-turn-off-dur.patch +kvm-s390-pv-fix-external-interruption-loop-not-alway.patch +wifi-mac80211-fix-the-size-calculation-of-ieee80211_.patch +wifi-mac80211-fix-invalid-drv_sta_pre_rcu_remove-cal.patch +net-qrtr-fix-a-refcount-bug-in-qrtr_recvmsg.patch +net-phylink-add-phylink_expects_phy-method.patch +net-stmmac-check-if-mac-needs-to-attach-to-a-phy.patch +net-stmmac-remove-redundant-fixup-to-support-fixed-l.patch +l2tp-generate-correct-module-alias-strings.patch +wifi-brcmfmac-fix-sdio-suspend-resume-regression.patch +nfsd-avoid-calling-opdesc-with-ops-opnum-op_illegal.patch +nfsd-call-op_release-even-when-op_func-returns-an-er.patch +icmp-guard-against-too-small-mtu.patch +alsa-hda-hdmi-preserve-the-previous-pcm-device-upon-.patch +net-don-t-let-netpoll-invoke-napi-if-in-xmit-context.patch +net-dsa-mv88e6xxx-reset-mv88e6393x-force-wd-event-bi.patch +sctp-check-send-stream-number-after-wait_for_sndbuf.patch +net-qrtr-do-not-do-del_server-broadcast-after-del_cl.patch +ipv6-fix-an-uninit-variable-access-bug-in-__ip6_make.patch +platform-x86-think-lmi-fix-memory-leak-when-showing-.patch +platform-x86-think-lmi-fix-memory-leaks-when-parsing.patch +platform-x86-think-lmi-clean-up-display-of-current_v.patch +gpio-davinci-do-not-clear-the-bank-intr-enable-bit-i.patch +gpio-davinci-add-irq-chip-flag-to-skip-set-wake.patch +net-ethernet-ti-am65-cpsw-fix-mdio-cleanup-in-probe.patch +net-stmmac-fix-up-rx-flow-hash-indirection-table-whe.patch +sunrpc-only-free-unix-grouplist-after-rcu-settles.patch +nfsd-callback-request-does-not-use-correct-credentia.patch +ice-fix-wrong-fallback-logic-for-fdir.patch +ice-reset-fdir-counter-in-fdir-init-stage.patch +raw-use-net_hash_mix-in-hash-function.patch +raw-fix-null-deref-in-raw_get_next.patch +ping-fix-potentail-null-deref-for-proc-net-icmp.patch +ethtool-reset-lanes-when-lanes-is-omitted.patch +netlink-annotate-lockless-accesses-to-nlk-max_recvms.patch +gve-secure-enough-bytes-in-the-first-tx-desc-for-all.patch +arm64-compat-work-around-uninitialized-variable-warn.patch +net-stmmac-check-fwnode-for-phy-device-before-scanni.patch diff --git a/queue-6.1/sunrpc-only-free-unix-grouplist-after-rcu-settles.patch b/queue-6.1/sunrpc-only-free-unix-grouplist-after-rcu-settles.patch new file mode 100644 index 00000000000..31a41ed13db --- /dev/null +++ b/queue-6.1/sunrpc-only-free-unix-grouplist-after-rcu-settles.patch @@ -0,0 +1,58 @@ +From 8086c147b76495ecc7ad21072d695fbcac176516 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Mar 2023 14:24:27 -0400 +Subject: sunrpc: only free unix grouplist after RCU settles + +From: Jeff Layton + +[ Upstream commit 5085e41f9e83a1bec51da1f20b54f2ec3a13a3fe ] + +While the unix_gid object is rcu-freed, the group_info list that it +contains is not. Ensure that we only put the group list reference once +we are really freeing the unix_gid object. + +Reported-by: Zhi Li +Link: https://bugzilla.redhat.com/show_bug.cgi?id=2183056 +Signed-off-by: Jeff Layton +Fixes: fd5d2f78261b ("SUNRPC: Make server side AUTH_UNIX use lockless lookups") +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + net/sunrpc/svcauth_unix.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c +index b1efc34db6ed8..609ade4fb49ed 100644 +--- a/net/sunrpc/svcauth_unix.c ++++ b/net/sunrpc/svcauth_unix.c +@@ -416,14 +416,23 @@ static int unix_gid_hash(kuid_t uid) + return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS); + } + +-static void unix_gid_put(struct kref *kref) ++static void unix_gid_free(struct rcu_head *rcu) + { +- struct cache_head *item = container_of(kref, struct cache_head, ref); +- struct unix_gid *ug = container_of(item, struct unix_gid, h); ++ struct unix_gid *ug = container_of(rcu, struct unix_gid, rcu); ++ struct cache_head *item = &ug->h; ++ + if (test_bit(CACHE_VALID, &item->flags) && + !test_bit(CACHE_NEGATIVE, &item->flags)) + put_group_info(ug->gi); +- kfree_rcu(ug, rcu); ++ kfree(ug); ++} ++ ++static void unix_gid_put(struct kref *kref) ++{ ++ struct cache_head *item = container_of(kref, struct cache_head, ref); ++ struct unix_gid *ug = container_of(item, struct unix_gid, h); ++ ++ call_rcu(&ug->rcu, unix_gid_free); + } + + static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew) +-- +2.39.2 + diff --git a/queue-6.1/wifi-brcmfmac-fix-sdio-suspend-resume-regression.patch b/queue-6.1/wifi-brcmfmac-fix-sdio-suspend-resume-regression.patch new file mode 100644 index 00000000000..5f00fa7b04b --- /dev/null +++ b/queue-6.1/wifi-brcmfmac-fix-sdio-suspend-resume-regression.patch @@ -0,0 +1,162 @@ +From ed45018ca8bbdd5476e63f3de0cf25bf673ead1a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Mar 2023 13:22:52 +0100 +Subject: wifi: brcmfmac: Fix SDIO suspend/resume regression + +From: Hans de Goede + +[ Upstream commit e4efa515d58f1363d8a27e548f9c5769d3121e03 ] + +After commit 92cadedd9d5f ("brcmfmac: Avoid keeping power to SDIO card +unless WOWL is used"), the wifi adapter by default is turned off on suspend +and then re-probed on resume. + +In at least 2 model x86/acpi tablets with brcmfmac43430a1 wifi adapters, +the newly added re-probe on resume fails like this: + + brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout + ieee80211 phy1: brcmf_bus_started: failed: -110 + ieee80211 phy1: brcmf_attach: dongle is not responding: err=-110 + brcmfmac: brcmf_sdio_firmware_callback: brcmf_attach failed + +It seems this specific brcmfmac model does not like being reprobed without +it actually being turned off first. + +And the adapter is not being turned off during suspend because of +commit f0992ace680c ("brcmfmac: prohibit ACPI power management for brcmfmac +driver"). + +Now that the driver is being reprobed on resume, the disabling of ACPI +pm is no longer necessary, except when WOWL is used (in which case there +is no-reprobe). + +Move the dis-/en-abling of ACPI pm to brcmf_sdio_wowl_config(), this fixes +the brcmfmac43430a1 suspend/resume regression and should help save some +power when suspended. + +This change means that the code now also may re-enable ACPI pm when WOWL +gets disabled. ACPI pm should only be re-enabled if it was enabled by +the ACPI core originally. Add a brcmf_sdiod_acpi_save_power_manageable() +to save the original state for this. + +This has been tested on the following devices: + +Asus T100TA brcmfmac43241b4-sdio +Acer Iconia One 7 B1-750 brcmfmac43340-sdio +Chuwi Hi8 brcmfmac43430a0-sdio +Chuwi Hi8 brcmfmac43430a1-sdio + +(the Asus T100TA is the device for which the prohibiting of ACPI pm + was originally added) + +Fixes: 92cadedd9d5f ("brcmfmac: Avoid keeping power to SDIO card unless WOWL is used") +Cc: Ulf Hansson +Signed-off-by: Hans de Goede +Reviewed-by: Ulf Hansson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230320122252.240070-1-hdegoede@redhat.com +Signed-off-by: Sasha Levin +--- + .../broadcom/brcm80211/brcmfmac/bcmsdh.c | 36 +++++++++++++------ + .../broadcom/brcm80211/brcmfmac/sdio.h | 2 ++ + 2 files changed, 28 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +index d0daef674e728..e300278ea38c6 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -991,15 +991,34 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { + MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); + + +-static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev, +- int val) ++static void brcmf_sdiod_acpi_save_power_manageable(struct brcmf_sdio_dev *sdiodev) + { + #if IS_ENABLED(CONFIG_ACPI) + struct acpi_device *adev; + +- adev = ACPI_COMPANION(dev); ++ adev = ACPI_COMPANION(&sdiodev->func1->dev); + if (adev) +- adev->flags.power_manageable = 0; ++ sdiodev->func1_power_manageable = adev->flags.power_manageable; ++ ++ adev = ACPI_COMPANION(&sdiodev->func2->dev); ++ if (adev) ++ sdiodev->func2_power_manageable = adev->flags.power_manageable; ++#endif ++} ++ ++static void brcmf_sdiod_acpi_set_power_manageable(struct brcmf_sdio_dev *sdiodev, ++ int enable) ++{ ++#if IS_ENABLED(CONFIG_ACPI) ++ struct acpi_device *adev; ++ ++ adev = ACPI_COMPANION(&sdiodev->func1->dev); ++ if (adev) ++ adev->flags.power_manageable = enable ? sdiodev->func1_power_manageable : 0; ++ ++ adev = ACPI_COMPANION(&sdiodev->func2->dev); ++ if (adev) ++ adev->flags.power_manageable = enable ? sdiodev->func2_power_manageable : 0; + #endif + } + +@@ -1009,7 +1028,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, + int err; + struct brcmf_sdio_dev *sdiodev; + struct brcmf_bus *bus_if; +- struct device *dev; + + brcmf_dbg(SDIO, "Enter\n"); + brcmf_dbg(SDIO, "Class=%x\n", func->class); +@@ -1017,14 +1035,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, + brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); + brcmf_dbg(SDIO, "Function#: %d\n", func->num); + +- dev = &func->dev; +- + /* Set MMC_QUIRK_LENIENT_FN0 for this card */ + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + +- /* prohibit ACPI power management for this device */ +- brcmf_sdiod_acpi_set_power_manageable(dev, 0); +- + /* Consume func num 1 but dont do anything with it. */ + if (func->num == 1) + return 0; +@@ -1055,6 +1068,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, + dev_set_drvdata(&sdiodev->func1->dev, bus_if); + sdiodev->dev = &sdiodev->func1->dev; + ++ brcmf_sdiod_acpi_save_power_manageable(sdiodev); + brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN); + + brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n"); +@@ -1120,6 +1134,8 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled) + + if (sdiodev->settings->bus.sdio.oob_irq_supported || + pm_caps & MMC_PM_WAKE_SDIO_IRQ) { ++ /* Stop ACPI from turning off the device when wowl is enabled */ ++ brcmf_sdiod_acpi_set_power_manageable(sdiodev, !enabled); + sdiodev->wowl_enabled = enabled; + brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled); + return; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +index b76d34d36bde6..0d18ed15b4032 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -188,6 +188,8 @@ struct brcmf_sdio_dev { + char nvram_name[BRCMF_FW_NAME_LEN]; + char clm_name[BRCMF_FW_NAME_LEN]; + bool wowl_enabled; ++ bool func1_power_manageable; ++ bool func2_power_manageable; + enum brcmf_sdiod_state state; + struct brcmf_sdiod_freezer *freezer; + const struct firmware *clm_fw; +-- +2.39.2 + diff --git a/queue-6.1/wifi-mac80211-fix-invalid-drv_sta_pre_rcu_remove-cal.patch b/queue-6.1/wifi-mac80211-fix-invalid-drv_sta_pre_rcu_remove-cal.patch new file mode 100644 index 00000000000..7882e4023ac --- /dev/null +++ b/queue-6.1/wifi-mac80211-fix-invalid-drv_sta_pre_rcu_remove-cal.patch @@ -0,0 +1,40 @@ +From 0e2d02c7d9b4073b686231e85de24eea1196f888 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Mar 2023 13:09:24 +0100 +Subject: wifi: mac80211: fix invalid drv_sta_pre_rcu_remove calls for + non-uploaded sta + +From: Felix Fietkau + +[ Upstream commit 12b220a6171faf10638ab683a975cadcf1a352d6 ] + +Avoid potential data corruption issues caused by uninitialized driver +private data structures. + +Reported-by: Brian Coverstone +Fixes: 6a9d1b91f34d ("mac80211: add pre-RCU-sync sta removal driver operation") +Signed-off-by: Felix Fietkau +Link: https://lore.kernel.org/r/20230324120924.38412-3-nbd@nbd.name +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/sta_info.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index 3603cbc167570..30efa26f977f6 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -1242,7 +1242,8 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta) + list_del_rcu(&sta->list); + sta->removed = true; + +- drv_sta_pre_rcu_remove(local, sta->sdata, sta); ++ if (sta->uploaded) ++ drv_sta_pre_rcu_remove(local, sta->sdata, sta); + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + rcu_access_pointer(sdata->u.vlan.sta) == sta) +-- +2.39.2 + diff --git a/queue-6.1/wifi-mac80211-fix-the-size-calculation-of-ieee80211_.patch b/queue-6.1/wifi-mac80211-fix-the-size-calculation-of-ieee80211_.patch new file mode 100644 index 00000000000..d51b2896522 --- /dev/null +++ b/queue-6.1/wifi-mac80211-fix-the-size-calculation-of-ieee80211_.patch @@ -0,0 +1,37 @@ +From 9ee3ee385212e59bab480aa726481ccf44985fc2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Mar 2023 01:07:41 +0800 +Subject: wifi: mac80211: fix the size calculation of + ieee80211_ie_len_eht_cap() + +From: Ryder Lee + +[ Upstream commit dd01579e5ed922dcfcb8fec53fa03b81c7649a04 ] + +Here should return the size of ieee80211_eht_cap_elem_fixed, so fix it. + +Fixes: 820acc810fb6 ("mac80211: Add EHT capabilities to association/probe request") +Signed-off-by: Ryder Lee +Link: https://lore.kernel.org/r/06c13635fc03bcff58a647b8e03e9f01a74294bd.1679935259.git.ryder.lee@mediatek.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index ed53c51bbc321..0785d9393e718 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -4785,7 +4785,7 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype) + &eht_cap->eht_cap_elem, + is_ap); + return 2 + 1 + +- sizeof(he_cap->he_cap_elem) + n + ++ sizeof(eht_cap->eht_cap_elem) + n + + ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0], + eht_cap->eht_cap_elem.phy_cap_info); + return 0; +-- +2.39.2 +