--- /dev/null
+From 5359b44a1383f983e16ab3cadd5ad9034fd01616 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Oct 2021 16:22:14 +0200
+Subject: ALSA: pcm: Add more disconnection checks at file ops
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ 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 <tiwai@suse.de>
+Stable-dep-of: 4f9d674377d0 ("ALSA: usb-audio: Notify xrun for low-latency mode")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 7b1202f10d529709dd844abc3fb6540615b148b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Sep 2022 15:55:48 +0200
+Subject: ALSA: pcm: Avoid reference to status->state
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ 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 <perex@perex.cz>
+Link: https://lore.kernel.org/r/20220926135558.26580-2-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 4f9d674377d0 ("ALSA: usb-audio: Notify xrun for low-latency mode")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 800716d64bf4077e0ae0466e8d9ec3aae9b4c55e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Nov 2024 09:04:16 +0100
+Subject: ALSA: usb-audio: Notify xrun for low-latency mode
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ 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 <cdleonard@gmail.com>
+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 <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 57db8cc8b77e88a9c3c309ca2acc5ef6ca7f039a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <houtao1@huawei.com>
+
+[ 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 <toke@redhat.com>
+Signed-off-by: Hou Tao <houtao1@huawei.com>
+Link: https://lore.kernel.org/r/20241206110622.1161752-6-houtao@huaweicloud.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 4ef90a9491853d582921bebfea18d6dda1a93dbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <houtao1@huawei.com>
+
+[ 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 <toke@redhat.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Hou Tao <houtao1@huawei.com>
+Link: https://lore.kernel.org/r/20241206110622.1161752-4-houtao@huaweicloud.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 5ee4bf83edc98d15a79ca40a9b7b2e194eff57df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Nov 2024 12:04:13 +0330
+Subject: bpftool: fix potential NULL pointer dereferencing in prog_dump()
+
+From: Amir Mohammadi <amirmohammadi1999.am@gmail.com>
+
+[ 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 <amiremohamadi@yahoo.com>
+Reviewed-by: Quentin Monnet <qmo@kernel.org>
+Acked-by: John Fastabend <john.fastabend@gmail.com>
+Link: https://lore.kernel.org/r/20241121083413.7214-1-amiremohamadi@yahoo.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 53e67d8d95dcfb27706140da5ecbefbfcd97c989 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <quentin@isovalent.com>
+
+[ 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 <quentin@isovalent.com>
+Tested-by: Niklas Söderlund <niklas.soderlund@corigine.com>
+Acked-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20221025150329.97371-3-quentin@isovalent.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Stable-dep-of: ef3ba8c258ee ("bpftool: fix potential NULL pointer dereferencing in prog_dump()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <stdarg.h>
+ #include <stdint.h>
+ #include <stdlib.h>
+-#include <assert.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <bfd.h>
+@@ -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 <assert.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <linux/err.h>
+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
+
--- /dev/null
+From a19933311378afdc32b2152c080e31c3efda8554 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Nov 2024 15:21:36 +0800
+Subject: drm/sti: Add __iomem for mixer_dbg_mxn's parameter
+
+From: Pei Xiao <xiaopei01@kylinos.cn>
+
+[ 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 <lkp@intel.com>
+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 <xiaopei01@kylinos.cn>
+Acked-by: Raphael Gallais-Pou <rgallaispou@gmail.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/c28f0dcb6a4526721d83ba1f659bba30564d3d54.1732087094.git.xiaopei01@kylinos.cn
+Signed-off-by: Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 46ef5ee4f090e0c83a9c985b6b500049fd777c29 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <mcanal@igalia.com>
+
+[ 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 <mcanal@igalia.com>
+Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241204122831.17015-1-mcanal@igalia.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From e6236f8be97106ce02a7bad5bb9c78a282313f87 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 Nov 2024 22:28:34 +0900
+Subject: ocfs2: free inode when ocfs2_get_init_inode() fails
+
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+
+[ 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 <penguin-kernel@I-love.SAKURA.ne.jp>
+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 <joseph.qi@linux.alibaba.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Jun Piao <piaojun@huawei.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
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
--- /dev/null
+From d930dc84d97667fe468c8cfe0b5f0a3c5f412a57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Nov 2024 16:38:17 +0800
+Subject: spi: mpc52xx: Add cancel_work_sync before module remove
+
+From: Pei Xiao <xiaopei01@kylinos.cn>
+
+[ 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 <xiaopei01@kylinos.cn>
+Link: https://patch.msgid.link/1f16f8ae0e50ca9adb1dc849bf2ac65a40c9ceb9.1732783000.git.xiaopei01@kylinos.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 13a4636ae8239b9f1f030c275f59c536c9e295f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <zijianzhang@bytedance.com>
+
+[ 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:
+<TASK>
+? __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
+</TASK>
+---[ 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 <zijianzhang@bytedance.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: John Fastabend <john.fastabend@gmail.com>
+Link: https://lore.kernel.org/bpf/20241016234838.3167769-3-zijianzhang@bytedance.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 10defcd85ab8d296faf8593e662a93c0f779e8ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <bjorn@rivosinc.com>
+
+[ 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 <bjorn@rivosinc.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Tested-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Reviewed-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
+Reviewed-by: Namhyung Kim <namhyung@kernel.org>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Acked-by: Quentin Monnet <qmo@kernel.org>
+Acked-by: Jiri Olsa <jolsa@kernel.org>
+Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
+Link: https://lore.kernel.org/bpf/20241127101748.165693-1-bjorn@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+