From: Sasha Levin Date: Tue, 10 Dec 2024 02:42:09 +0000 (-0500) Subject: Fixes for 5.15 X-Git-Tag: v6.6.65~41 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=60660a96cb1211f8df35fe722e25aae812adcd89;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/alsa-pcm-add-more-disconnection-checks-at-file-ops.patch b/queue-5.15/alsa-pcm-add-more-disconnection-checks-at-file-ops.patch new file mode 100644 index 00000000000..ee985756543 --- /dev/null +++ b/queue-5.15/alsa-pcm-add-more-disconnection-checks-at-file-ops.patch @@ -0,0 +1,116 @@ +From 5359b44a1383f983e16ab3cadd5ad9034fd01616 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Oct 2021 16:22:14 +0200 +Subject: ALSA: pcm: Add more disconnection checks at file ops + +From: Takashi Iwai + +[ Upstream commit 36df2427ac3ea04510368561c8cee22388a7434a ] + +In the case of hot-disconnection of a PCM device, all file operations +except for close should be rejected. This patch adds more sanity +checks in the file operation code paths. + +Link: https://lore.kernel.org/r/20211006142214.3089-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Stable-dep-of: 4f9d674377d0 ("ALSA: usb-audio: Notify xrun for low-latency mode") +Signed-off-by: Sasha Levin +--- + sound/core/pcm_native.c | 25 +++++++++++++++++++++---- + 1 file changed, 21 insertions(+), 4 deletions(-) + +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index 464b99b432d33..0193ac199c270 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -3283,6 +3283,9 @@ static int snd_pcm_common_ioctl(struct file *file, + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + ++ if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ return -EBADFD; ++ + res = snd_power_wait(substream->pcm->card); + if (res < 0) + return res; +@@ -3409,6 +3412,9 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, + snd_pcm_uframes_t *frames = arg; + snd_pcm_sframes_t result; + ++ if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ return -EBADFD; ++ + switch (cmd) { + case SNDRV_PCM_IOCTL_FORWARD: + { +@@ -3451,7 +3457,8 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN || ++ runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + if (!frame_aligned(runtime, count)) + return -EINVAL; +@@ -3475,7 +3482,8 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf, + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN || ++ runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + if (!frame_aligned(runtime, count)) + return -EINVAL; +@@ -3501,7 +3509,8 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to) + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN || ++ runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + if (!iter_is_iovec(to)) + return -EINVAL; +@@ -3537,7 +3546,8 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from) + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN || ++ runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + if (!iter_is_iovec(from)) + return -EINVAL; +@@ -3576,6 +3586,9 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait) + return ok | EPOLLERR; + + runtime = substream->runtime; ++ if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ return ok | EPOLLERR; ++ + poll_wait(file, &runtime->sleep, wait); + + mask = 0; +@@ -3887,6 +3900,8 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) + substream = pcm_file->substream; + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; ++ if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ return -EBADFD; + + offset = area->vm_pgoff << PAGE_SHIFT; + switch (offset) { +@@ -3923,6 +3938,8 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; ++ if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ return -EBADFD; + return fasync_helper(fd, file, on, &runtime->fasync); + } + +-- +2.43.0 + diff --git a/queue-5.15/alsa-pcm-avoid-reference-to-status-state.patch b/queue-5.15/alsa-pcm-avoid-reference-to-status-state.patch new file mode 100644 index 00000000000..873437f4ffa --- /dev/null +++ b/queue-5.15/alsa-pcm-avoid-reference-to-status-state.patch @@ -0,0 +1,826 @@ +From 7b1202f10d529709dd844abc3fb6540615b148b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 15:55:48 +0200 +Subject: ALSA: pcm: Avoid reference to status->state + +From: Takashi Iwai + +[ Upstream commit f0061c18c169f0c32d96b59485c3edee85e343ed ] + +In the PCM core and driver code, there are lots place referring to the +current PCM state via runtime->status->state. This patch introduced a +local PCM state in runtime itself and replaces those references with +runtime->state. It has improvements in two aspects: + +- The reduction of a indirect access leads to more code optimization + +- It avoids a possible (unexpected) modification of the state via mmap + of the status record + +The status->state is updated together with runtime->state, so that +user-space can still read the current state via mmap like before, +too. + +This patch touches only the ALSA core code. The changes in each +driver will follow in later patches. + +Reviewed-by: Jaroslav Kysela +Link: https://lore.kernel.org/r/20220926135558.26580-2-tiwai@suse.de +Signed-off-by: Takashi Iwai +Stable-dep-of: 4f9d674377d0 ("ALSA: usb-audio: Notify xrun for low-latency mode") +Signed-off-by: Sasha Levin +--- + include/sound/pcm.h | 20 +++++- + sound/core/oss/pcm_oss.c | 42 ++++++------- + sound/core/pcm.c | 9 +-- + sound/core/pcm_compat.c | 4 +- + sound/core/pcm_lib.c | 16 ++--- + sound/core/pcm_native.c | 127 ++++++++++++++++++++------------------- + 6 files changed, 118 insertions(+), 100 deletions(-) + +diff --git a/include/sound/pcm.h b/include/sound/pcm.h +index cb9be3632205c..5de4bd872fa80 100644 +--- a/include/sound/pcm.h ++++ b/include/sound/pcm.h +@@ -343,6 +343,8 @@ static inline void snd_pcm_pack_audio_tstamp_report(__u32 *data, __u32 *accuracy + + struct snd_pcm_runtime { + /* -- Status -- */ ++ snd_pcm_state_t state; /* stream state */ ++ snd_pcm_state_t suspended_state; /* suspended stream state */ + struct snd_pcm_substream *trigger_master; + struct timespec64 trigger_tstamp; /* trigger timestamp */ + bool trigger_tstamp_latched; /* trigger timestamp latched in low-level driver/hardware */ +@@ -675,11 +677,25 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, + */ + static inline int snd_pcm_running(struct snd_pcm_substream *substream) + { +- return (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING || +- (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING && ++ return (substream->runtime->state == SNDRV_PCM_STATE_RUNNING || ++ (substream->runtime->state == SNDRV_PCM_STATE_DRAINING && + substream->stream == SNDRV_PCM_STREAM_PLAYBACK)); + } + ++/** ++ * __snd_pcm_set_state - Change the current PCM state ++ * @runtime: PCM runtime to set ++ * @state: the current state to set ++ * ++ * Call within the stream lock ++ */ ++static inline void __snd_pcm_set_state(struct snd_pcm_runtime *runtime, ++ snd_pcm_state_t state) ++{ ++ runtime->state = state; ++ runtime->status->state = state; /* copy for mmap */ ++} ++ + /** + * bytes_to_samples - Unit conversion of the size from bytes to samples + * @runtime: PCM runtime instance +diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c +index ca4a692fe1c36..8a458c167452a 100644 +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -1229,12 +1229,12 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + while (1) { +- if (runtime->status->state == SNDRV_PCM_STATE_XRUN || +- runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { ++ if (runtime->state == SNDRV_PCM_STATE_XRUN || ++ runtime->state == SNDRV_PCM_STATE_SUSPENDED) { + #ifdef OSS_DEBUG + pcm_dbg(substream->pcm, + "pcm_oss: write: recovering from %s\n", +- runtime->status->state == SNDRV_PCM_STATE_XRUN ? ++ runtime->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); + #endif + ret = snd_pcm_oss_prepare(substream); +@@ -1249,7 +1249,7 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const + break; + /* test, if we can't store new data, because the stream */ + /* has not been started */ +- if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) ++ if (runtime->state == SNDRV_PCM_STATE_PREPARED) + return -EAGAIN; + } + return ret; +@@ -1261,18 +1261,18 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p + snd_pcm_sframes_t delay; + int ret; + while (1) { +- if (runtime->status->state == SNDRV_PCM_STATE_XRUN || +- runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { ++ if (runtime->state == SNDRV_PCM_STATE_XRUN || ++ runtime->state == SNDRV_PCM_STATE_SUSPENDED) { + #ifdef OSS_DEBUG + pcm_dbg(substream->pcm, + "pcm_oss: read: recovering from %s\n", +- runtime->status->state == SNDRV_PCM_STATE_XRUN ? ++ runtime->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); + #endif + ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); + if (ret < 0) + break; +- } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { ++ } else if (runtime->state == SNDRV_PCM_STATE_SETUP) { + ret = snd_pcm_oss_prepare(substream); + if (ret < 0) + break; +@@ -1285,7 +1285,7 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p + frames, in_kernel); + mutex_lock(&runtime->oss.params_lock); + if (ret == -EPIPE) { +- if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { ++ if (runtime->state == SNDRV_PCM_STATE_DRAINING) { + ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); + if (ret < 0) + break; +@@ -1304,12 +1304,12 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + while (1) { +- if (runtime->status->state == SNDRV_PCM_STATE_XRUN || +- runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { ++ if (runtime->state == SNDRV_PCM_STATE_XRUN || ++ runtime->state == SNDRV_PCM_STATE_SUSPENDED) { + #ifdef OSS_DEBUG + pcm_dbg(substream->pcm, + "pcm_oss: writev: recovering from %s\n", +- runtime->status->state == SNDRV_PCM_STATE_XRUN ? ++ runtime->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); + #endif + ret = snd_pcm_oss_prepare(substream); +@@ -1322,7 +1322,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void + + /* test, if we can't store new data, because the stream */ + /* has not been started */ +- if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) ++ if (runtime->state == SNDRV_PCM_STATE_PREPARED) + return -EAGAIN; + } + return ret; +@@ -1333,18 +1333,18 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void * + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + while (1) { +- if (runtime->status->state == SNDRV_PCM_STATE_XRUN || +- runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { ++ if (runtime->state == SNDRV_PCM_STATE_XRUN || ++ runtime->state == SNDRV_PCM_STATE_SUSPENDED) { + #ifdef OSS_DEBUG + pcm_dbg(substream->pcm, + "pcm_oss: readv: recovering from %s\n", +- runtime->status->state == SNDRV_PCM_STATE_XRUN ? ++ runtime->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); + #endif + ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); + if (ret < 0) + break; +- } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { ++ } else if (runtime->state == SNDRV_PCM_STATE_SETUP) { + ret = snd_pcm_oss_prepare(substream); + if (ret < 0) + break; +@@ -1627,7 +1627,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) + result = 0; + set_current_state(TASK_INTERRUPTIBLE); + snd_pcm_stream_lock_irq(substream); +- state = runtime->status->state; ++ state = runtime->state; + snd_pcm_stream_unlock_irq(substream); + if (state != SNDRV_PCM_STATE_RUNNING) { + set_current_state(TASK_RUNNING); +@@ -2852,8 +2852,8 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) + struct snd_pcm_runtime *runtime = psubstream->runtime; + poll_wait(file, &runtime->sleep, wait); + snd_pcm_stream_lock_irq(psubstream); +- if (runtime->status->state != SNDRV_PCM_STATE_DRAINING && +- (runtime->status->state != SNDRV_PCM_STATE_RUNNING || ++ if (runtime->state != SNDRV_PCM_STATE_DRAINING && ++ (runtime->state != SNDRV_PCM_STATE_RUNNING || + snd_pcm_oss_playback_ready(psubstream))) + mask |= EPOLLOUT | EPOLLWRNORM; + snd_pcm_stream_unlock_irq(psubstream); +@@ -2863,7 +2863,7 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) + snd_pcm_state_t ostate; + poll_wait(file, &runtime->sleep, wait); + snd_pcm_stream_lock_irq(csubstream); +- ostate = runtime->status->state; ++ ostate = runtime->state; + if (ostate != SNDRV_PCM_STATE_RUNNING || + snd_pcm_oss_capture_ready(csubstream)) + mask |= EPOLLIN | EPOLLRDNORM; +diff --git a/sound/core/pcm.c b/sound/core/pcm.c +index 1ce21677d030b..9df2e819035f2 100644 +--- a/sound/core/pcm.c ++++ b/sound/core/pcm.c +@@ -386,7 +386,7 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, + snd_iprintf(buffer, "closed\n"); + goto unlock; + } +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { ++ if (runtime->state == SNDRV_PCM_STATE_OPEN) { + snd_iprintf(buffer, "no setup\n"); + goto unlock; + } +@@ -423,7 +423,7 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, + snd_iprintf(buffer, "closed\n"); + goto unlock; + } +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { ++ if (runtime->state == SNDRV_PCM_STATE_OPEN) { + snd_iprintf(buffer, "no setup\n"); + goto unlock; + } +@@ -969,7 +969,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, + init_waitqueue_head(&runtime->sleep); + init_waitqueue_head(&runtime->tsleep); + +- runtime->status->state = SNDRV_PCM_STATE_OPEN; ++ __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_OPEN); + mutex_init(&runtime->buffer_mutex); + atomic_set(&runtime->buffer_accessing, 0); + +@@ -1110,7 +1110,8 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) + if (snd_pcm_running(substream)) + snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); + /* to be sure, set the state unconditionally */ +- substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; ++ __snd_pcm_set_state(substream->runtime, ++ SNDRV_PCM_STATE_DISCONNECTED); + wake_up(&substream->runtime->sleep); + wake_up(&substream->runtime->tsleep); + } +diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c +index 7af9fa1331895..21c6fbb4f8c90 100644 +--- a/sound/core/pcm_compat.c ++++ b/sound/core/pcm_compat.c +@@ -299,7 +299,7 @@ static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream, + return -ENOTTY; + if (substream->stream != dir) + return -EINVAL; +- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + + if (get_user(buf, &data32->buf) || +@@ -345,7 +345,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, + return -ENOTTY; + if (substream->stream != dir) + return -EINVAL; +- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + + ch = substream->runtime->channels; +diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c +index 8947c988b6d34..f319e4298b874 100644 +--- a/sound/core/pcm_lib.c ++++ b/sound/core/pcm_lib.c +@@ -185,7 +185,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, + avail = snd_pcm_avail(substream); + if (avail > runtime->avail_max) + runtime->avail_max = avail; +- if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { ++ if (runtime->state == SNDRV_PCM_STATE_DRAINING) { + if (avail >= runtime->buffer_size) { + snd_pcm_drain_done(substream); + return -EPIPE; +@@ -1910,7 +1910,7 @@ static int wait_for_avail(struct snd_pcm_substream *substream, + + snd_pcm_stream_lock_irq(substream); + set_current_state(TASK_INTERRUPTIBLE); +- switch (runtime->status->state) { ++ switch (runtime->state) { + case SNDRV_PCM_STATE_SUSPENDED: + err = -ESTRPIPE; + goto _endloop; +@@ -2098,14 +2098,14 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream) + runtime = substream->runtime; + if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area)) + return -EINVAL; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + return 0; + } + + static int pcm_accessible_state(struct snd_pcm_runtime *runtime) + { +- switch (runtime->status->state) { ++ switch (runtime->state) { + case SNDRV_PCM_STATE_PREPARED: + case SNDRV_PCM_STATE_RUNNING: + case SNDRV_PCM_STATE_PAUSED: +@@ -2209,7 +2209,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, + goto _end_unlock; + + runtime->twake = runtime->control->avail_min ? : 1; +- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) ++ if (runtime->state == SNDRV_PCM_STATE_RUNNING) + snd_pcm_update_hw_ptr(substream); + + /* +@@ -2217,7 +2217,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, + * thread may start capture + */ + if (!is_playback && +- runtime->status->state == SNDRV_PCM_STATE_PREPARED && ++ runtime->state == SNDRV_PCM_STATE_PREPARED && + size >= runtime->start_threshold) { + err = snd_pcm_start(substream); + if (err < 0) +@@ -2231,7 +2231,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, + snd_pcm_uframes_t cont; + if (!avail) { + if (!is_playback && +- runtime->status->state == SNDRV_PCM_STATE_DRAINING) { ++ runtime->state == SNDRV_PCM_STATE_DRAINING) { + snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); + goto _end_unlock; + } +@@ -2283,7 +2283,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, + xfer += frames; + avail -= frames; + if (is_playback && +- runtime->status->state == SNDRV_PCM_STATE_PREPARED && ++ runtime->state == SNDRV_PCM_STATE_PREPARED && + snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { + err = snd_pcm_start(substream); + if (err < 0) +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index 0193ac199c270..56b4a25fc6f0b 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -595,8 +595,8 @@ static void snd_pcm_set_state(struct snd_pcm_substream *substream, + snd_pcm_state_t state) + { + snd_pcm_stream_lock_irq(substream); +- if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) +- substream->runtime->status->state = state; ++ if (substream->runtime->state != SNDRV_PCM_STATE_DISCONNECTED) ++ __snd_pcm_set_state(substream->runtime, state); + snd_pcm_stream_unlock_irq(substream); + } + +@@ -724,7 +724,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, + if (err < 0) + return err; + snd_pcm_stream_lock_irq(substream); +- switch (runtime->status->state) { ++ switch (runtime->state) { + case SNDRV_PCM_STATE_OPEN: + case SNDRV_PCM_STATE_SETUP: + case SNDRV_PCM_STATE_PREPARED: +@@ -889,7 +889,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) + if (result < 0) + return result; + snd_pcm_stream_lock_irq(substream); +- switch (runtime->status->state) { ++ switch (runtime->state) { + case SNDRV_PCM_STATE_SETUP: + case SNDRV_PCM_STATE_PREPARED: + if (atomic_read(&substream->mmap_count)) +@@ -920,7 +920,7 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream, + return -ENXIO; + runtime = substream->runtime; + snd_pcm_stream_lock_irq(substream); +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { ++ if (runtime->state == SNDRV_PCM_STATE_OPEN) { + snd_pcm_stream_unlock_irq(substream); + return -EBADFD; + } +@@ -1013,8 +1013,8 @@ int snd_pcm_status64(struct snd_pcm_substream *substream, + } else + runtime->audio_tstamp_report.valid = 1; + +- status->state = runtime->status->state; +- status->suspended_state = runtime->status->suspended_state; ++ status->state = runtime->state; ++ status->suspended_state = runtime->suspended_state; + if (status->state == SNDRV_PCM_STATE_OPEN) + goto _end; + status->trigger_tstamp_sec = runtime->trigger_tstamp.tv_sec; +@@ -1148,7 +1148,7 @@ static int snd_pcm_channel_info(struct snd_pcm_substream *substream, + channel = info->channel; + runtime = substream->runtime; + snd_pcm_stream_lock_irq(substream); +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { ++ if (runtime->state == SNDRV_PCM_STATE_OPEN) { + snd_pcm_stream_unlock_irq(substream); + return -EBADFD; + } +@@ -1411,7 +1411,7 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream, + snd_pcm_state_t state) + { + struct snd_pcm_runtime *runtime = substream->runtime; +- if (runtime->status->state != SNDRV_PCM_STATE_PREPARED) ++ if (runtime->state != SNDRV_PCM_STATE_PREPARED) + return -EBADFD; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && + !snd_pcm_playback_data(substream)) +@@ -1446,7 +1446,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, + runtime->hw_ptr_jiffies = jiffies; + runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / + runtime->rate; +- runtime->status->state = state; ++ __snd_pcm_set_state(runtime, state); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && + runtime->silence_size > 0) + snd_pcm_playback_silence(substream, ULONG_MAX); +@@ -1487,7 +1487,7 @@ static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, + snd_pcm_state_t state) + { + struct snd_pcm_runtime *runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + runtime->trigger_master = substream; + return 0; +@@ -1508,9 +1508,9 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream, + snd_pcm_state_t state) + { + struct snd_pcm_runtime *runtime = substream->runtime; +- if (runtime->status->state != state) { ++ if (runtime->state != state) { + snd_pcm_trigger_tstamp(substream); +- runtime->status->state = state; ++ __snd_pcm_set_state(runtime, state); + snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP); + } + wake_up(&runtime->sleep); +@@ -1586,9 +1586,9 @@ static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, + if (!(runtime->info & SNDRV_PCM_INFO_PAUSE)) + return -ENOSYS; + if (pause_pushed(state)) { +- if (runtime->status->state != SNDRV_PCM_STATE_RUNNING) ++ if (runtime->state != SNDRV_PCM_STATE_RUNNING) + return -EBADFD; +- } else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED) ++ } else if (runtime->state != SNDRV_PCM_STATE_PAUSED) + return -EBADFD; + runtime->trigger_master = substream; + return 0; +@@ -1630,12 +1630,12 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream, + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_trigger_tstamp(substream); + if (pause_pushed(state)) { +- runtime->status->state = SNDRV_PCM_STATE_PAUSED; ++ __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_PAUSED); + snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MPAUSE); + wake_up(&runtime->sleep); + wake_up(&runtime->tsleep); + } else { +- runtime->status->state = SNDRV_PCM_STATE_RUNNING; ++ __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_RUNNING); + snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MCONTINUE); + } + } +@@ -1670,7 +1670,7 @@ static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, + snd_pcm_state_t state) + { + struct snd_pcm_runtime *runtime = substream->runtime; +- switch (runtime->status->state) { ++ switch (runtime->state) { + case SNDRV_PCM_STATE_SUSPENDED: + return -EBUSY; + /* unresumable PCM state; return -EBUSY for skipping suspend */ +@@ -1701,8 +1701,9 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, + { + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_trigger_tstamp(substream); +- runtime->status->suspended_state = runtime->status->state; +- runtime->status->state = SNDRV_PCM_STATE_SUSPENDED; ++ runtime->suspended_state = runtime->state; ++ runtime->status->suspended_state = runtime->suspended_state; ++ __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SUSPENDED); + snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSUSPEND); + wake_up(&runtime->sleep); + wake_up(&runtime->tsleep); +@@ -1793,8 +1794,8 @@ static int snd_pcm_do_resume(struct snd_pcm_substream *substream, + if (runtime->trigger_master != substream) + return 0; + /* DMA not running previously? */ +- if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING && +- (runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING || ++ if (runtime->suspended_state != SNDRV_PCM_STATE_RUNNING && ++ (runtime->suspended_state != SNDRV_PCM_STATE_DRAINING || + substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) + return 0; + return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME); +@@ -1813,7 +1814,7 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream, + { + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_trigger_tstamp(substream); +- runtime->status->state = runtime->status->suspended_state; ++ __snd_pcm_set_state(runtime, runtime->suspended_state); + snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME); + } + +@@ -1850,7 +1851,7 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream) + int result; + + snd_pcm_stream_lock_irq(substream); +- switch (runtime->status->state) { ++ switch (runtime->state) { + case SNDRV_PCM_STATE_XRUN: + result = 0; /* already there */ + break; +@@ -1873,7 +1874,7 @@ static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, + snd_pcm_state_t state) + { + struct snd_pcm_runtime *runtime = substream->runtime; +- switch (runtime->status->state) { ++ switch (runtime->state) { + case SNDRV_PCM_STATE_RUNNING: + case SNDRV_PCM_STATE_PREPARED: + case SNDRV_PCM_STATE_PAUSED: +@@ -1935,8 +1936,8 @@ static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, + struct snd_pcm_runtime *runtime = substream->runtime; + int f_flags = (__force int)state; + +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN || +- runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN || ++ runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + if (snd_pcm_running(substream)) + return -EBUSY; +@@ -1987,7 +1988,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream, + f_flags = substream->f_flags; + + snd_pcm_stream_lock_irq(substream); +- switch (substream->runtime->status->state) { ++ switch (substream->runtime->state) { + case SNDRV_PCM_STATE_PAUSED: + snd_pcm_pause(substream, false); + fallthrough; +@@ -2011,7 +2012,7 @@ static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, + snd_pcm_state_t state) + { + struct snd_pcm_runtime *runtime = substream->runtime; +- switch (runtime->status->state) { ++ switch (runtime->state) { + case SNDRV_PCM_STATE_OPEN: + case SNDRV_PCM_STATE_DISCONNECTED: + case SNDRV_PCM_STATE_SUSPENDED: +@@ -2026,28 +2027,28 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, + { + struct snd_pcm_runtime *runtime = substream->runtime; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- switch (runtime->status->state) { ++ switch (runtime->state) { + case SNDRV_PCM_STATE_PREPARED: + /* start playback stream if possible */ + if (! snd_pcm_playback_empty(substream)) { + snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); + snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); + } else { +- runtime->status->state = SNDRV_PCM_STATE_SETUP; ++ __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SETUP); + } + break; + case SNDRV_PCM_STATE_RUNNING: +- runtime->status->state = SNDRV_PCM_STATE_DRAINING; ++ __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_DRAINING); + break; + case SNDRV_PCM_STATE_XRUN: +- runtime->status->state = SNDRV_PCM_STATE_SETUP; ++ __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SETUP); + break; + default: + break; + } + } else { + /* stop running stream */ +- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) { ++ if (runtime->state == SNDRV_PCM_STATE_RUNNING) { + snd_pcm_state_t new_state; + + new_state = snd_pcm_capture_avail(runtime) > 0 ? +@@ -2057,7 +2058,7 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, + } + } + +- if (runtime->status->state == SNDRV_PCM_STATE_DRAINING && ++ if (runtime->state == SNDRV_PCM_STATE_DRAINING && + runtime->trigger_master == substream && + (runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER)) + return substream->ops->trigger(substream, +@@ -2098,7 +2099,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, + card = substream->pcm->card; + runtime = substream->runtime; + +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + + if (file) { +@@ -2109,7 +2110,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, + + snd_pcm_stream_lock_irq(substream); + /* resume pause */ +- if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) ++ if (runtime->state == SNDRV_PCM_STATE_PAUSED) + snd_pcm_pause(substream, false); + + /* pre-start/stop - all running streams are changed to DRAINING state */ +@@ -2137,7 +2138,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, + if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) + continue; + runtime = s->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { ++ if (runtime->state == SNDRV_PCM_STATE_DRAINING) { + to_check = runtime; + break; + } +@@ -2176,7 +2177,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, + break; + } + if (tout == 0) { +- if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) ++ if (substream->runtime->state == SNDRV_PCM_STATE_SUSPENDED) + result = -ESTRPIPE; + else { + dev_dbg(substream->pcm->card->dev, +@@ -2208,13 +2209,13 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) + return -ENXIO; + runtime = substream->runtime; + +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN || +- runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN || ++ runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + + snd_pcm_stream_lock_irq(substream); + /* resume pause */ +- if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) ++ if (runtime->state == SNDRV_PCM_STATE_PAUSED) + snd_pcm_pause(substream, false); + + snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); +@@ -2277,8 +2278,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) + snd_pcm_group_init(group); + + down_write(&snd_pcm_link_rwsem); +- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || +- substream->runtime->status->state != substream1->runtime->status->state || ++ if (substream->runtime->state == SNDRV_PCM_STATE_OPEN || ++ substream->runtime->state != substream1->runtime->state || + substream->pcm->nonatomic != substream1->pcm->nonatomic) { + res = -EBADFD; + goto _end; +@@ -2702,7 +2703,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream) + + snd_pcm_drop(substream); + if (substream->hw_opened) { +- if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) ++ if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) + do_hw_free(substream); + substream->ops->close(substream); + substream->hw_opened = 0; +@@ -2899,7 +2900,7 @@ static int snd_pcm_release(struct inode *inode, struct file *file) + */ + static int do_pcm_hwsync(struct snd_pcm_substream *substream) + { +- switch (substream->runtime->status->state) { ++ switch (substream->runtime->state) { + case SNDRV_PCM_STATE_DRAINING: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + return -EBADFD; +@@ -3196,7 +3197,7 @@ static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream, + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_sframes_t result; + +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + if (put_user(0, &_xferi->result)) + return -EFAULT; +@@ -3219,7 +3220,7 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream, + void *bufs; + snd_pcm_sframes_t result; + +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + if (runtime->channels > 128) + return -EINVAL; +@@ -3283,7 +3284,7 @@ static int snd_pcm_common_ioctl(struct file *file, + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + +- if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + + res = snd_power_wait(substream->pcm->card); +@@ -3412,7 +3413,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, + snd_pcm_uframes_t *frames = arg; + snd_pcm_sframes_t result; + +- if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + + switch (cmd) { +@@ -3457,8 +3458,8 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN || +- runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN || ++ runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + if (!frame_aligned(runtime, count)) + return -EINVAL; +@@ -3482,8 +3483,8 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf, + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN || +- runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN || ++ runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + if (!frame_aligned(runtime, count)) + return -EINVAL; +@@ -3509,8 +3510,8 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to) + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN || +- runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN || ++ runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + if (!iter_is_iovec(to)) + return -EINVAL; +@@ -3546,8 +3547,8 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from) + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN || +- runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN || ++ runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + if (!iter_is_iovec(from)) + return -EINVAL; +@@ -3586,7 +3587,7 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait) + return ok | EPOLLERR; + + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return ok | EPOLLERR; + + poll_wait(file, &runtime->sleep, wait); +@@ -3594,7 +3595,7 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait) + mask = 0; + snd_pcm_stream_lock_irq(substream); + avail = snd_pcm_avail(substream); +- switch (runtime->status->state) { ++ switch (runtime->state) { + case SNDRV_PCM_STATE_RUNNING: + case SNDRV_PCM_STATE_PREPARED: + case SNDRV_PCM_STATE_PAUSED: +@@ -3863,7 +3864,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, + return -EINVAL; + } + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ if (runtime->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) + return -ENXIO; +@@ -3900,7 +3901,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) + substream = pcm_file->substream; + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; +- if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + + offset = area->vm_pgoff << PAGE_SHIFT; +@@ -3938,7 +3939,7 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) + if (PCM_RUNTIME_CHECK(substream)) + return -ENXIO; + runtime = substream->runtime; +- if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) ++ if (runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + return -EBADFD; + return fasync_helper(fd, file, on, &runtime->fasync); + } +-- +2.43.0 + diff --git a/queue-5.15/alsa-usb-audio-notify-xrun-for-low-latency-mode.patch b/queue-5.15/alsa-usb-audio-notify-xrun-for-low-latency-mode.patch new file mode 100644 index 00000000000..94840679476 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-notify-xrun-for-low-latency-mode.patch @@ -0,0 +1,78 @@ +From 800716d64bf4077e0ae0466e8d9ec3aae9b4c55e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Nov 2024 09:04:16 +0100 +Subject: ALSA: usb-audio: Notify xrun for low-latency mode + +From: Takashi Iwai + +[ Upstream commit 4f9d674377d090e38d93360bd4df21b67534d622 ] + +The low-latency mode of USB-audio driver uses a similar approach like +the implicit feedback mode but it has an explicit queuing at the +trigger start time. The difference is, however, that no packet will +be handled any longer after all queued packets are handled but no +enough data is fed. In the case of implicit feedback mode, the +capture-side packet handling triggers the re-queuing, and this checks +the XRUN. OTOH, in the low-latency mode, it just stops without XRUN +notification unless any new action is taken from user-space via ack +callback. For example, when you stop the stream in aplay, no XRUN is +reported. + +This patch adds the XRUN check at the packet complete callback in the +case all pending URBs are exhausted. Strictly speaking, this state +doesn't match really with XRUN; in theory the application may queue +immediately after this happens. But such behavior is only for +1-period configuration, which the USB-audio driver doesn't support. +So we may conclude that this situation leads certainly to XRUN. + +A caveat is that the XRUN should be triggered only for the PCM RUNNING +state, and not during DRAINING. This additional state check is put in +notify_xrun(), too. + +Fixes: d5f871f89e21 ("ALSA: usb-audio: Improved lowlatency playback support") +Reported-by: Leonard Crestez +Link: https://lore.kernel.org/25d5b0d8-4efd-4630-9d33-7a9e3fa9dc2b@gmail.com +Link: https://patch.msgid.link/20241128080446.1181-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/endpoint.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index 8188113ca83f2..6b5480b325518 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -402,10 +402,15 @@ static int prepare_inbound_urb(struct snd_usb_endpoint *ep, + static void notify_xrun(struct snd_usb_endpoint *ep) + { + struct snd_usb_substream *data_subs; ++ struct snd_pcm_substream *psubs; + + data_subs = READ_ONCE(ep->data_subs); +- if (data_subs && data_subs->pcm_substream) +- snd_pcm_stop_xrun(data_subs->pcm_substream); ++ if (!data_subs) ++ return; ++ psubs = data_subs->pcm_substream; ++ if (psubs && psubs->runtime && ++ psubs->runtime->state == SNDRV_PCM_STATE_RUNNING) ++ snd_pcm_stop_xrun(psubs); + } + + static struct snd_usb_packet_info * +@@ -556,7 +561,10 @@ static void snd_complete_urb(struct urb *urb) + push_back_to_ready_list(ep, ctx); + clear_bit(ctx->index, &ep->active_mask); + snd_usb_queue_pending_output_urbs(ep, false); +- atomic_dec(&ep->submitted_urbs); /* decrement at last */ ++ /* decrement at last, and check xrun */ ++ if (atomic_dec_and_test(&ep->submitted_urbs) && ++ !snd_usb_endpoint_implicit_feedback_sink(ep)) ++ notify_xrun(ep); + return; + } + +-- +2.43.0 + diff --git a/queue-5.15/bpf-fix-exact-match-conditions-in-trie_get_next_key.patch b/queue-5.15/bpf-fix-exact-match-conditions-in-trie_get_next_key.patch new file mode 100644 index 00000000000..cbc50ed0eac --- /dev/null +++ b/queue-5.15/bpf-fix-exact-match-conditions-in-trie_get_next_key.patch @@ -0,0 +1,60 @@ +From 57db8cc8b77e88a9c3c309ca2acc5ef6ca7f039a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Dec 2024 19:06:18 +0800 +Subject: bpf: Fix exact match conditions in trie_get_next_key() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hou Tao + +[ Upstream commit 27abc7b3fa2e09bbe41e2924d328121546865eda ] + +trie_get_next_key() uses node->prefixlen == key->prefixlen to identify +an exact match, However, it is incorrect because when the target key +doesn't fully match the found node (e.g., node->prefixlen != matchlen), +these two nodes may also have the same prefixlen. It will return +expected result when the passed key exist in the trie. However when a +recently-deleted key or nonexistent key is passed to +trie_get_next_key(), it may skip keys and return incorrect result. + +Fix it by using node->prefixlen == matchlen to identify exact matches. +When the condition is true after the search, it also implies +node->prefixlen equals key->prefixlen, otherwise, the search would +return NULL instead. + +Fixes: b471f2f1de8b ("bpf: implement MAP_GET_NEXT_KEY command for LPM_TRIE map") +Reviewed-by: Toke Høiland-Jørgensen +Signed-off-by: Hou Tao +Link: https://lore.kernel.org/r/20241206110622.1161752-6-houtao@huaweicloud.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/lpm_trie.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c +index 0ab0ad989eaff..37669d6988664 100644 +--- a/kernel/bpf/lpm_trie.c ++++ b/kernel/bpf/lpm_trie.c +@@ -639,7 +639,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key) + struct lpm_trie_node **node_stack = NULL; + int err = 0, stack_ptr = -1; + unsigned int next_bit; +- size_t matchlen; ++ size_t matchlen = 0; + + /* The get_next_key follows postorder. For the 4 node example in + * the top of this file, the trie_get_next_key() returns the following +@@ -678,7 +678,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key) + next_bit = extract_bit(key->data, node->prefixlen); + node = rcu_dereference(node->child[next_bit]); + } +- if (!node || node->prefixlen != key->prefixlen || ++ if (!node || node->prefixlen != matchlen || + (node->flags & LPM_TREE_NODE_FLAG_IM)) + goto find_leftmost; + +-- +2.43.0 + diff --git a/queue-5.15/bpf-handle-bpf_exist-and-bpf_noexist-for-lpm-trie.patch b/queue-5.15/bpf-handle-bpf_exist-and-bpf_noexist-for-lpm-trie.patch new file mode 100644 index 00000000000..9276afd0ffc --- /dev/null +++ b/queue-5.15/bpf-handle-bpf_exist-and-bpf_noexist-for-lpm-trie.patch @@ -0,0 +1,80 @@ +From 4ef90a9491853d582921bebfea18d6dda1a93dbe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Dec 2024 19:06:16 +0800 +Subject: bpf: Handle BPF_EXIST and BPF_NOEXIST for LPM trie +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hou Tao + +[ Upstream commit eae6a075e9537dd69891cf77ca5a88fa8a28b4a1 ] + +Add the currently missing handling for the BPF_EXIST and BPF_NOEXIST +flags. These flags can be specified by users and are relevant since LPM +trie supports exact matches during update. + +Fixes: b95a5c4db09b ("bpf: add a longest prefix match trie map implementation") +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: Daniel Borkmann +Signed-off-by: Hou Tao +Link: https://lore.kernel.org/r/20241206110622.1161752-4-houtao@huaweicloud.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/lpm_trie.c | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c +index 6b2bf71f8de4b..0ab0ad989eaff 100644 +--- a/kernel/bpf/lpm_trie.c ++++ b/kernel/bpf/lpm_trie.c +@@ -366,6 +366,10 @@ static int trie_update_elem(struct bpf_map *map, + * simply assign the @new_node to that slot and be done. + */ + if (!node) { ++ if (flags == BPF_EXIST) { ++ ret = -ENOENT; ++ goto out; ++ } + rcu_assign_pointer(*slot, new_node); + goto out; + } +@@ -374,18 +378,31 @@ static int trie_update_elem(struct bpf_map *map, + * which already has the correct data array set. + */ + if (node->prefixlen == matchlen) { ++ if (!(node->flags & LPM_TREE_NODE_FLAG_IM)) { ++ if (flags == BPF_NOEXIST) { ++ ret = -EEXIST; ++ goto out; ++ } ++ trie->n_entries--; ++ } else if (flags == BPF_EXIST) { ++ ret = -ENOENT; ++ goto out; ++ } ++ + new_node->child[0] = node->child[0]; + new_node->child[1] = node->child[1]; + +- if (!(node->flags & LPM_TREE_NODE_FLAG_IM)) +- trie->n_entries--; +- + rcu_assign_pointer(*slot, new_node); + kfree_rcu(node, rcu); + + goto out; + } + ++ if (flags == BPF_EXIST) { ++ ret = -ENOENT; ++ goto out; ++ } ++ + /* If the new node matches the prefix completely, it must be inserted + * as an ancestor. Simply insert it between @node and *@slot. + */ +-- +2.43.0 + diff --git a/queue-5.15/bpftool-fix-potential-null-pointer-dereferencing-in-.patch b/queue-5.15/bpftool-fix-potential-null-pointer-dereferencing-in-.patch new file mode 100644 index 00000000000..c6e8485242a --- /dev/null +++ b/queue-5.15/bpftool-fix-potential-null-pointer-dereferencing-in-.patch @@ -0,0 +1,54 @@ +From 5ee4bf83edc98d15a79ca40a9b7b2e194eff57df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Nov 2024 12:04:13 +0330 +Subject: bpftool: fix potential NULL pointer dereferencing in prog_dump() + +From: Amir Mohammadi + +[ Upstream commit ef3ba8c258ee368a5343fa9329df85b4bcb9e8b5 ] + +A NULL pointer dereference could occur if ksyms +is not properly checked before usage in the prog_dump() function. + +Fixes: b053b439b72a ("bpf: libbpf: bpftool: Print bpf_line_info during prog dump") +Signed-off-by: Amir Mohammadi +Reviewed-by: Quentin Monnet +Acked-by: John Fastabend +Link: https://lore.kernel.org/r/20241121083413.7214-1-amiremohamadi@yahoo.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/bpf/bpftool/prog.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c +index 75f71c3ad4f62..64142f3d06655 100644 +--- a/tools/bpf/bpftool/prog.c ++++ b/tools/bpf/bpftool/prog.c +@@ -744,11 +744,18 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode, + printf("%s:\n", sym_name); + } + +- if (disasm_print_insn(img, lens[i], opcodes, +- name, disasm_opt, btf, +- prog_linfo, ksyms[i], i, +- linum)) +- goto exit_free; ++ if (ksyms) { ++ if (disasm_print_insn(img, lens[i], opcodes, ++ name, disasm_opt, btf, ++ prog_linfo, ksyms[i], i, ++ linum)) ++ goto exit_free; ++ } else { ++ if (disasm_print_insn(img, lens[i], opcodes, ++ name, disasm_opt, btf, ++ NULL, 0, 0, false)) ++ goto exit_free; ++ } + + img += lens[i]; + +-- +2.43.0 + diff --git a/queue-5.15/bpftool-remove-asserts-from-jit-disassembler.patch b/queue-5.15/bpftool-remove-asserts-from-jit-disassembler.patch new file mode 100644 index 00000000000..db54a66f05e --- /dev/null +++ b/queue-5.15/bpftool-remove-asserts-from-jit-disassembler.patch @@ -0,0 +1,242 @@ +From 53e67d8d95dcfb27706140da5ecbefbfcd97c989 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2022 16:03:23 +0100 +Subject: bpftool: Remove asserts from JIT disassembler +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Quentin Monnet + +[ Upstream commit 55b4de58d0e2aca810ed2b198a0173640300acf8 ] + +The JIT disassembler in bpftool is the only components (with the JSON +writer) using asserts to check the return values of functions. But it +does not do so in a consistent way, and diasm_print_insn() returns no +value, although sometimes the operation failed. + +Remove the asserts, and instead check the return values, print messages +on errors, and propagate the error to the caller from prog.c. + +Remove the inclusion of assert.h from jit_disasm.c, and also from map.c +where it is unused. + +Signed-off-by: Quentin Monnet +Tested-by: Niklas Söderlund +Acked-by: Song Liu +Link: https://lore.kernel.org/r/20221025150329.97371-3-quentin@isovalent.com +Signed-off-by: Alexei Starovoitov +Stable-dep-of: ef3ba8c258ee ("bpftool: fix potential NULL pointer dereferencing in prog_dump()") +Signed-off-by: Sasha Levin +--- + tools/bpf/bpftool/jit_disasm.c | 51 +++++++++++++++++++++++----------- + tools/bpf/bpftool/main.h | 25 +++++++++-------- + tools/bpf/bpftool/map.c | 1 - + tools/bpf/bpftool/prog.c | 15 ++++++---- + 4 files changed, 57 insertions(+), 35 deletions(-) + +diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c +index aaf99a0168c90..fe23c9669a876 100644 +--- a/tools/bpf/bpftool/jit_disasm.c ++++ b/tools/bpf/bpftool/jit_disasm.c +@@ -16,7 +16,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -29,14 +28,18 @@ + #include "json_writer.h" + #include "main.h" + +-static void get_exec_path(char *tpath, size_t size) ++static int get_exec_path(char *tpath, size_t size) + { + const char *path = "/proc/self/exe"; + ssize_t len; + + len = readlink(path, tpath, size - 1); +- assert(len > 0); ++ if (len <= 0) ++ return -1; ++ + tpath[len] = 0; ++ ++ return 0; + } + + static int oper_count; +@@ -97,30 +100,39 @@ static int fprintf_json_styled(void *out, + return r; + } + +-void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, +- const char *arch, const char *disassembler_options, +- const struct btf *btf, +- const struct bpf_prog_linfo *prog_linfo, +- __u64 func_ksym, unsigned int func_idx, +- bool linum) ++int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, ++ const char *arch, const char *disassembler_options, ++ const struct btf *btf, ++ const struct bpf_prog_linfo *prog_linfo, ++ __u64 func_ksym, unsigned int func_idx, ++ bool linum) + { + const struct bpf_line_info *linfo = NULL; + disassembler_ftype disassemble; ++ int count, i, pc = 0, err = -1; + struct disassemble_info info; + unsigned int nr_skip = 0; +- int count, i, pc = 0; + char tpath[PATH_MAX]; + bfd *bfdf; + + if (!len) +- return; ++ return -1; + + memset(tpath, 0, sizeof(tpath)); +- get_exec_path(tpath, sizeof(tpath)); ++ if (get_exec_path(tpath, sizeof(tpath))) { ++ p_err("failed to create disasembler (get_exec_path)"); ++ return -1; ++ } + + bfdf = bfd_openr(tpath, NULL); +- assert(bfdf); +- assert(bfd_check_format(bfdf, bfd_object)); ++ if (!bfdf) { ++ p_err("failed to create disassembler (bfd_openr)"); ++ return -1; ++ } ++ if (!bfd_check_format(bfdf, bfd_object)) { ++ p_err("failed to create disassembler (bfd_check_format)"); ++ goto exit_close; ++ } + + if (json_output) + init_disassemble_info_compat(&info, stdout, +@@ -139,7 +151,7 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, + bfdf->arch_info = inf; + } else { + p_err("No libbfd support for %s", arch); +- return; ++ goto exit_close; + } + } + +@@ -160,7 +172,10 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, + #else + disassemble = disassembler(bfdf); + #endif +- assert(disassemble); ++ if (!disassemble) { ++ p_err("failed to create disassembler"); ++ goto exit_close; ++ } + + if (json_output) + jsonw_start_array(json_wtr); +@@ -224,7 +239,11 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, + if (json_output) + jsonw_end_array(json_wtr); + ++ err = 0; ++ ++exit_close: + bfd_close(bfdf); ++ return err; + } + + int disasm_init(void) +diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h +index 90caa42aac4cf..834f8317b855f 100644 +--- a/tools/bpf/bpftool/main.h ++++ b/tools/bpf/bpftool/main.h +@@ -193,22 +193,23 @@ int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len); + + struct bpf_prog_linfo; + #ifdef HAVE_LIBBFD_SUPPORT +-void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, +- const char *arch, const char *disassembler_options, +- const struct btf *btf, +- const struct bpf_prog_linfo *prog_linfo, +- __u64 func_ksym, unsigned int func_idx, +- bool linum); ++int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, ++ const char *arch, const char *disassembler_options, ++ const struct btf *btf, ++ const struct bpf_prog_linfo *prog_linfo, ++ __u64 func_ksym, unsigned int func_idx, ++ bool linum); + int disasm_init(void); + #else + static inline +-void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, +- const char *arch, const char *disassembler_options, +- const struct btf *btf, +- const struct bpf_prog_linfo *prog_linfo, +- __u64 func_ksym, unsigned int func_idx, +- bool linum) ++int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, ++ const char *arch, const char *disassembler_options, ++ const struct btf *btf, ++ const struct bpf_prog_linfo *prog_linfo, ++ __u64 func_ksym, unsigned int func_idx, ++ bool linum) + { ++ return 0; + } + static inline int disasm_init(void) + { +diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c +index 72ef9ddae2609..c775a677688ae 100644 +--- a/tools/bpf/bpftool/map.c ++++ b/tools/bpf/bpftool/map.c +@@ -1,7 +1,6 @@ + // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) + /* Copyright (C) 2017-2018 Netronome Systems, Inc. */ + +-#include + #include + #include + #include +diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c +index afb28fcc66786..75f71c3ad4f62 100644 +--- a/tools/bpf/bpftool/prog.c ++++ b/tools/bpf/bpftool/prog.c +@@ -744,10 +744,11 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode, + printf("%s:\n", sym_name); + } + +- disasm_print_insn(img, lens[i], opcodes, +- name, disasm_opt, btf, +- prog_linfo, ksyms[i], i, +- linum); ++ if (disasm_print_insn(img, lens[i], opcodes, ++ name, disasm_opt, btf, ++ prog_linfo, ksyms[i], i, ++ linum)) ++ goto exit_free; + + img += lens[i]; + +@@ -760,8 +761,10 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode, + if (json_output) + jsonw_end_array(json_wtr); + } else { +- disasm_print_insn(buf, member_len, opcodes, name, +- disasm_opt, btf, NULL, 0, 0, false); ++ if (disasm_print_insn(buf, member_len, opcodes, name, ++ disasm_opt, btf, NULL, 0, 0, ++ false)) ++ goto exit_free; + } + } else if (visual) { + if (json_output) +-- +2.43.0 + diff --git a/queue-5.15/drm-sti-add-__iomem-for-mixer_dbg_mxn-s-parameter.patch b/queue-5.15/drm-sti-add-__iomem-for-mixer_dbg_mxn-s-parameter.patch new file mode 100644 index 00000000000..ff9665321bf --- /dev/null +++ b/queue-5.15/drm-sti-add-__iomem-for-mixer_dbg_mxn-s-parameter.patch @@ -0,0 +1,41 @@ +From a19933311378afdc32b2152c080e31c3efda8554 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Nov 2024 15:21:36 +0800 +Subject: drm/sti: Add __iomem for mixer_dbg_mxn's parameter + +From: Pei Xiao + +[ Upstream commit 86e8f94789dd6f3e705bfa821e1e416f97a2f863 ] + +Sparse complains about incorrect type in argument 1. +expected void const volatile __iomem *ptr but got void *. +so modify mixer_dbg_mxn's addr parameter. + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202411191809.6V3c826r-lkp@intel.com/ +Fixes: a5f81078a56c ("drm/sti: add debugfs entries for MIXER crtc") +Signed-off-by: Pei Xiao +Acked-by: Raphael Gallais-Pou +Link: https://patchwork.freedesktop.org/patch/msgid/c28f0dcb6a4526721d83ba1f659bba30564d3d54.1732087094.git.xiaopei01@kylinos.cn +Signed-off-by: Raphael Gallais-Pou +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/sti/sti_mixer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c +index 7e5f14646625b..06c1b81912f79 100644 +--- a/drivers/gpu/drm/sti/sti_mixer.c ++++ b/drivers/gpu/drm/sti/sti_mixer.c +@@ -137,7 +137,7 @@ static void mixer_dbg_crb(struct seq_file *s, int val) + } + } + +-static void mixer_dbg_mxn(struct seq_file *s, void *addr) ++static void mixer_dbg_mxn(struct seq_file *s, void __iomem *addr) + { + int i; + +-- +2.43.0 + diff --git a/queue-5.15/drm-v3d-enable-performance-counters-before-clearing-.patch b/queue-5.15/drm-v3d-enable-performance-counters-before-clearing-.patch new file mode 100644 index 00000000000..0445cf1b985 --- /dev/null +++ b/queue-5.15/drm-v3d-enable-performance-counters-before-clearing-.patch @@ -0,0 +1,53 @@ +From 46ef5ee4f090e0c83a9c985b6b500049fd777c29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Dec 2024 09:28:31 -0300 +Subject: drm/v3d: Enable Performance Counters before clearing them +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maíra Canal + +[ Upstream commit c98b10496b2f3c4f576af3482c71aadcfcbf765e ] + +On the Raspberry Pi 5, performance counters are not being cleared +when `v3d_perfmon_start()` is called, even though we write to the +CLR register. As a result, their values accumulate until they +overflow. + +The expected behavior is for performance counters to reset to zero +at the start of a job. When the job finishes and the perfmon is +stopped, the counters should accurately reflect the values for that +specific job. + +To ensure this behavior, the performance counters are now enabled +before being cleared. This allows the CLR register to function as +intended, zeroing the counter values when the job begins. + +Fixes: 26a4dc29b74a ("drm/v3d: Expose performance counters to userspace") +Signed-off-by: Maíra Canal +Reviewed-by: Iago Toral Quiroga +Link: https://patchwork.freedesktop.org/patch/msgid/20241204122831.17015-1-mcanal@igalia.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/v3d/v3d_perfmon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c +index b74b537e620fc..3de4cc692f44d 100644 +--- a/drivers/gpu/drm/v3d/v3d_perfmon.c ++++ b/drivers/gpu/drm/v3d/v3d_perfmon.c +@@ -49,9 +49,9 @@ void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon) + V3D_CORE_WRITE(0, V3D_V4_PCTR_0_SRC_X(source), channel); + } + ++ V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask); + V3D_CORE_WRITE(0, V3D_V4_PCTR_0_CLR, mask); + V3D_CORE_WRITE(0, V3D_PCTR_0_OVERFLOW, mask); +- V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask); + + v3d->active_perfmon = perfmon; + } +-- +2.43.0 + diff --git a/queue-5.15/ocfs2-free-inode-when-ocfs2_get_init_inode-fails.patch b/queue-5.15/ocfs2-free-inode-when-ocfs2_get_init_inode-fails.patch new file mode 100644 index 00000000000..e7e3d8930a7 --- /dev/null +++ b/queue-5.15/ocfs2-free-inode-when-ocfs2_get_init_inode-fails.patch @@ -0,0 +1,50 @@ +From e6236f8be97106ce02a7bad5bb9c78a282313f87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Nov 2024 22:28:34 +0900 +Subject: ocfs2: free inode when ocfs2_get_init_inode() fails + +From: Tetsuo Handa + +[ Upstream commit 965b5dd1894f4525f38c1b5f99b0106a07dbb5db ] + +syzbot is reporting busy inodes after unmount, for commit 9c89fe0af826 +("ocfs2: Handle error from dquot_initialize()") forgot to call iput() when +new_inode() succeeded and dquot_initialize() failed. + +Link: https://lkml.kernel.org/r/e68c0224-b7c6-4784-b4fa-a9fc8c675525@I-love.SAKURA.ne.jp +Fixes: 9c89fe0af826 ("ocfs2: Handle error from dquot_initialize()") +Signed-off-by: Tetsuo Handa +Reported-by: syzbot+0af00f6a2cba2058b5db@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0af00f6a2cba2058b5db +Tested-by: syzbot+0af00f6a2cba2058b5db@syzkaller.appspotmail.com +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Jun Piao +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/ocfs2/namei.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c +index 69aff1d5946d2..272dbc13d3bc2 100644 +--- a/fs/ocfs2/namei.c ++++ b/fs/ocfs2/namei.c +@@ -200,8 +200,10 @@ static struct inode *ocfs2_get_init_inode(struct inode *dir, umode_t mode) + mode = mode_strip_sgid(&init_user_ns, dir, mode); + inode_init_owner(&init_user_ns, inode, dir, mode); + status = dquot_initialize(inode); +- if (status) ++ if (status) { ++ iput(inode); + return ERR_PTR(status); ++ } + + return inode; + } +-- +2.43.0 + diff --git a/queue-5.15/series b/queue-5.15/series index b28d5ddec0b..871f7501538 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -431,3 +431,16 @@ dt_bindings-rs485-correct-delay-values.patch dt-bindings-serial-rs485-fix-rs485-rts-delay-propert.patch serial-amba-pl011-use-port-lock-wrappers.patch serial-amba-pl011-fix-rx-stall-when-dma-is-used.patch +bpftool-remove-asserts-from-jit-disassembler.patch +bpftool-fix-potential-null-pointer-dereferencing-in-.patch +drm-sti-add-__iomem-for-mixer_dbg_mxn-s-parameter.patch +tcp_bpf-fix-the-sk_mem_uncharge-logic-in-tcp_bpf_sen.patch +alsa-pcm-add-more-disconnection-checks-at-file-ops.patch +alsa-pcm-avoid-reference-to-status-state.patch +alsa-usb-audio-notify-xrun-for-low-latency-mode.patch +tools-override-makefile-arch-variable-if-defined-but.patch +spi-mpc52xx-add-cancel_work_sync-before-module-remov.patch +drm-v3d-enable-performance-counters-before-clearing-.patch +ocfs2-free-inode-when-ocfs2_get_init_inode-fails.patch +bpf-handle-bpf_exist-and-bpf_noexist-for-lpm-trie.patch +bpf-fix-exact-match-conditions-in-trie_get_next_key.patch diff --git a/queue-5.15/spi-mpc52xx-add-cancel_work_sync-before-module-remov.patch b/queue-5.15/spi-mpc52xx-add-cancel_work_sync-before-module-remov.patch new file mode 100644 index 00000000000..9546b99907f --- /dev/null +++ b/queue-5.15/spi-mpc52xx-add-cancel_work_sync-before-module-remov.patch @@ -0,0 +1,41 @@ +From d930dc84d97667fe468c8cfe0b5f0a3c5f412a57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Nov 2024 16:38:17 +0800 +Subject: spi: mpc52xx: Add cancel_work_sync before module remove + +From: Pei Xiao + +[ Upstream commit 984836621aad98802d92c4a3047114cf518074c8 ] + +If we remove the module which will call mpc52xx_spi_remove +it will free 'ms' through spi_unregister_controller. +while the work ms->work will be used. The sequence of operations +that may lead to a UAF bug. + +Fix it by ensuring that the work is canceled before proceeding with +the cleanup in mpc52xx_spi_remove. + +Fixes: ca632f556697 ("spi: reorganize drivers") +Signed-off-by: Pei Xiao +Link: https://patch.msgid.link/1f16f8ae0e50ca9adb1dc849bf2ac65a40c9ceb9.1732783000.git.xiaopei01@kylinos.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-mpc52xx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c +index 51041526546dd..fa49e899f2b2e 100644 +--- a/drivers/spi/spi-mpc52xx.c ++++ b/drivers/spi/spi-mpc52xx.c +@@ -521,6 +521,7 @@ static int mpc52xx_spi_remove(struct platform_device *op) + struct mpc52xx_spi *ms = spi_master_get_devdata(master); + int i; + ++ cancel_work_sync(&ms->work); + free_irq(ms->irq0, ms); + free_irq(ms->irq1, ms); + +-- +2.43.0 + diff --git a/queue-5.15/tcp_bpf-fix-the-sk_mem_uncharge-logic-in-tcp_bpf_sen.patch b/queue-5.15/tcp_bpf-fix-the-sk_mem_uncharge-logic-in-tcp_bpf_sen.patch new file mode 100644 index 00000000000..f13bc0f6106 --- /dev/null +++ b/queue-5.15/tcp_bpf-fix-the-sk_mem_uncharge-logic-in-tcp_bpf_sen.patch @@ -0,0 +1,165 @@ +From 13a4636ae8239b9f1f030c275f59c536c9e295f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Oct 2024 23:48:38 +0000 +Subject: tcp_bpf: Fix the sk_mem_uncharge logic in tcp_bpf_sendmsg + +From: Zijian Zhang + +[ Upstream commit ca70b8baf2bd125b2a4d96e76db79375c07d7ff2 ] + +The current sk memory accounting logic in __SK_REDIRECT is pre-uncharging +tosend bytes, which is either msg->sg.size or a smaller value apply_bytes. + +Potential problems with this strategy are as follows: + +- If the actual sent bytes are smaller than tosend, we need to charge some + bytes back, as in line 487, which is okay but seems not clean. + +- When tosend is set to apply_bytes, as in line 417, and (ret < 0), we may + miss uncharging (msg->sg.size - apply_bytes) bytes. + +[...] +415 tosend = msg->sg.size; +416 if (psock->apply_bytes && psock->apply_bytes < tosend) +417 tosend = psock->apply_bytes; +[...] +443 sk_msg_return(sk, msg, tosend); +444 release_sock(sk); +446 origsize = msg->sg.size; +447 ret = tcp_bpf_sendmsg_redir(sk_redir, redir_ingress, +448 msg, tosend, flags); +449 sent = origsize - msg->sg.size; +[...] +454 lock_sock(sk); +455 if (unlikely(ret < 0)) { +456 int free = sk_msg_free_nocharge(sk, msg); +458 if (!cork) +459 *copied -= free; +460 } +[...] +487 if (eval == __SK_REDIRECT) +488 sk_mem_charge(sk, tosend - sent); +[...] + +When running the selftest test_txmsg_redir_wait_sndmem with txmsg_apply, +the following warning will be reported: + +------------[ cut here ]------------ +WARNING: CPU: 6 PID: 57 at net/ipv4/af_inet.c:156 inet_sock_destruct+0x190/0x1a0 +Modules linked in: +CPU: 6 UID: 0 PID: 57 Comm: kworker/6:0 Not tainted 6.12.0-rc1.bm.1-amd64+ #43 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014 +Workqueue: events sk_psock_destroy +RIP: 0010:inet_sock_destruct+0x190/0x1a0 +RSP: 0018:ffffad0a8021fe08 EFLAGS: 00010206 +RAX: 0000000000000011 RBX: ffff9aab4475b900 RCX: ffff9aab481a0800 +RDX: 0000000000000303 RSI: 0000000000000011 RDI: ffff9aab4475b900 +RBP: ffff9aab4475b990 R08: 0000000000000000 R09: ffff9aab40050ec0 +R10: 0000000000000000 R11: ffff9aae6fdb1d01 R12: ffff9aab49c60400 +R13: ffff9aab49c60598 R14: ffff9aab49c60598 R15: dead000000000100 +FS: 0000000000000000(0000) GS:ffff9aae6fd80000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007ffec7e47bd8 CR3: 00000001a1a1c004 CR4: 0000000000770ef0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +PKRU: 55555554 +Call Trace: + +? __warn+0x89/0x130 +? inet_sock_destruct+0x190/0x1a0 +? report_bug+0xfc/0x1e0 +? handle_bug+0x5c/0xa0 +? exc_invalid_op+0x17/0x70 +? asm_exc_invalid_op+0x1a/0x20 +? inet_sock_destruct+0x190/0x1a0 +__sk_destruct+0x25/0x220 +sk_psock_destroy+0x2b2/0x310 +process_scheduled_works+0xa3/0x3e0 +worker_thread+0x117/0x240 +? __pfx_worker_thread+0x10/0x10 +kthread+0xcf/0x100 +? __pfx_kthread+0x10/0x10 +ret_from_fork+0x31/0x40 +? __pfx_kthread+0x10/0x10 +ret_from_fork_asm+0x1a/0x30 + +---[ end trace 0000000000000000 ]--- + +In __SK_REDIRECT, a more concise way is delaying the uncharging after sent +bytes are finalized, and uncharge this value. When (ret < 0), we shall +invoke sk_msg_free. + +Same thing happens in case __SK_DROP, when tosend is set to apply_bytes, +we may miss uncharging (msg->sg.size - apply_bytes) bytes. The same +warning will be reported in selftest. + +[...] +468 case __SK_DROP: +469 default: +470 sk_msg_free_partial(sk, msg, tosend); +471 sk_msg_apply_bytes(psock, tosend); +472 *copied -= (tosend + delta); +473 return -EACCES; +[...] + +So instead of sk_msg_free_partial we can do sk_msg_free here. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Fixes: 8ec95b94716a ("bpf, sockmap: Fix the sk->sk_forward_alloc warning of sk_stream_kill_queues") +Signed-off-by: Zijian Zhang +Signed-off-by: Daniel Borkmann +Acked-by: John Fastabend +Link: https://lore.kernel.org/bpf/20241016234838.3167769-3-zijianzhang@bytedance.com +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 93f6a20f51520..f2ae1e51e59ff 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -396,7 +396,6 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, + cork = true; + psock->cork = NULL; + } +- sk_msg_return(sk, msg, tosend); + release_sock(sk); + + origsize = msg->sg.size; +@@ -408,8 +407,9 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, + sock_put(sk_redir); + + lock_sock(sk); ++ sk_mem_uncharge(sk, sent); + if (unlikely(ret < 0)) { +- int free = sk_msg_free_nocharge(sk, msg); ++ int free = sk_msg_free(sk, msg); + + if (!cork) + *copied -= free; +@@ -423,7 +423,7 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, + break; + case __SK_DROP: + default: +- sk_msg_free_partial(sk, msg, tosend); ++ sk_msg_free(sk, msg); + sk_msg_apply_bytes(psock, tosend); + *copied -= (tosend + delta); + return -EACCES; +@@ -439,11 +439,8 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, + } + if (msg && + msg->sg.data[msg->sg.start].page_link && +- msg->sg.data[msg->sg.start].length) { +- if (eval == __SK_REDIRECT) +- sk_mem_charge(sk, tosend - sent); ++ msg->sg.data[msg->sg.start].length) + goto more_data; +- } + } + return ret; + } +-- +2.43.0 + diff --git a/queue-5.15/tools-override-makefile-arch-variable-if-defined-but.patch b/queue-5.15/tools-override-makefile-arch-variable-if-defined-but.patch new file mode 100644 index 00000000000..c9cd2395ddc --- /dev/null +++ b/queue-5.15/tools-override-makefile-arch-variable-if-defined-but.patch @@ -0,0 +1,59 @@ +From 10defcd85ab8d296faf8593e662a93c0f779e8ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Nov 2024 11:17:46 +0100 +Subject: tools: Override makefile ARCH variable if defined, but empty +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Björn Töpel + +[ Upstream commit 537a2525eaf76ea9b0dca62b994500d8670b39d5 ] + +There are a number of tools (bpftool, selftests), that require a +"bootstrap" build. Here, a bootstrap build is a build host variant of +a target. E.g., assume that you're performing a bpftool cross-build on +x86 to riscv, a bootstrap build would then be an x86 variant of +bpftool. The typical way to perform the host build variant, is to pass +"ARCH=" in a sub-make. However, if a variable has been set with a +command argument, then ordinary assignments in the makefile are +ignored. + +This side-effect results in that ARCH, and variables depending on ARCH +are not set. Workaround by overriding ARCH to the host arch, if ARCH +is empty. + +Fixes: 8859b0da5aac ("tools/bpftool: Fix cross-build") +Signed-off-by: Björn Töpel +Signed-off-by: Daniel Borkmann +Tested-by: Alexandre Ghiti +Reviewed-by: Jean-Philippe Brucker +Reviewed-by: Namhyung Kim +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: Quentin Monnet +Acked-by: Jiri Olsa +Cc: Arnaldo Carvalho de Melo +Link: https://lore.kernel.org/bpf/20241127101748.165693-1-bjorn@kernel.org +Signed-off-by: Sasha Levin +--- + tools/scripts/Makefile.arch | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/scripts/Makefile.arch b/tools/scripts/Makefile.arch +index b10b7a27c33fd..de3f2806b8a89 100644 +--- a/tools/scripts/Makefile.arch ++++ b/tools/scripts/Makefile.arch +@@ -6,8 +6,8 @@ HOSTARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \ + -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ + -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ ) + +-ifndef ARCH +-ARCH := $(HOSTARCH) ++ifeq ($(strip $(ARCH)),) ++override ARCH := $(HOSTARCH) + endif + + SRCARCH := $(ARCH) +-- +2.43.0 +