1. 19 12月, 2020 1 次提交
  2. 26 10月, 2020 1 次提交
  3. 09 7月, 2020 1 次提交
  4. 16 6月, 2020 1 次提交
    • T
      ALSA: pcm: Use dma_mmap_coherent() on x86, too · d955dab3
      Takashi Iwai 提交于
      We avoided the explicit use of dma_mmap_coherent() on x86 because of a
      spurious warning in x86 APT code in the past.  However, this blindly
      assumes that the pages allocated via dma_alloc_coherent() on x86 are
      the ones convertible via virt_to_page() (that is used in the default
      mmap handler), and it's no longer true; with the indirect DMA ops,
      this can be handled differently.  The only certain way for doing mmap
      such pages is the dma_mmap_coherent(), and the warning seems already
      gone in the recent code, so let's use it consistently.
      
      Link: https://lore.kernel.org/r/20200615160045.2703-2-tiwai@suse.deSigned-off-by: NTakashi Iwai <tiwai@suse.de>
      d955dab3
  5. 09 6月, 2020 1 次提交
  6. 08 6月, 2020 1 次提交
    • M
      ALSA: pcm: fix snd_pcm_link() lockdep splat · e18035cf
      Michał Mirosław 提交于
      Add and use snd_pcm_stream_lock_nested() in snd_pcm_link/unlink
      implementation.  The code is fine, but generates a lockdep complaint:
      
      ============================================
      WARNING: possible recursive locking detected
      5.7.1mq+ #381 Tainted: G           O
      --------------------------------------------
      pulseaudio/4180 is trying to acquire lock:
      ffff888402d6f508 (&group->lock){-...}-{2:2}, at: snd_pcm_common_ioctl+0xda8/0xee0 [snd_pcm]
      
      but task is already holding lock:
      ffff8883f7a8cf18 (&group->lock){-...}-{2:2}, at: snd_pcm_common_ioctl+0xe4e/0xee0 [snd_pcm]
      
      other info that might help us debug this:
       Possible unsafe locking scenario:
      
             CPU0
             ----
        lock(&group->lock);
        lock(&group->lock);
      
       *** DEADLOCK ***
      
       May be due to missing lock nesting notation
      
      2 locks held by pulseaudio/4180:
       #0: ffffffffa1a05190 (snd_pcm_link_rwsem){++++}-{3:3}, at: snd_pcm_common_ioctl+0xca0/0xee0 [snd_pcm]
       #1: ffff8883f7a8cf18 (&group->lock){-...}-{2:2}, at: snd_pcm_common_ioctl+0xe4e/0xee0 [snd_pcm]
      [...]
      
      Cc: stable@vger.kernel.org
      Fixes: f57f3df0 ("ALSA: pcm: More fine-grained PCM link locking")
      Signed-off-by: NMichał Mirosław <mirq-linux@rere.qmqm.pl>
      Link: https://lore.kernel.org/r/37252c65941e58473b1219ca9fab03d48f47e3e3.1591610330.git.mirq-linux@rere.qmqm.plSigned-off-by: NTakashi Iwai <tiwai@suse.de>
      e18035cf
  7. 26 4月, 2020 1 次提交
  8. 14 2月, 2020 1 次提交
  9. 13 2月, 2020 1 次提交
  10. 10 2月, 2020 2 次提交
  11. 31 1月, 2020 1 次提交
    • T
      ALSA: pcm: Fix sparse warnings wrt snd_pcm_state_t · cb639a42
      Takashi Iwai 提交于
      Since we have a bitwise definition of snd_pcm_state_t and use it for
      certain struct fields, a few new (and years old) sparse warnings came
      up.  This patch is an attempt to cover them.
      
      - The state fields in snd_pcm_mmap_status* and co are all defined as
        snd_pcm_state_t type now
      
      - The PCM action callbacks take snd_pcm_state_t argument as well;
        some actions taking special values got the explicit cast and
        comments
      
      - For the PCM action that doesn't need an extra argument receives
        ACTION_ARG_IGNORE instead of ambiguous 0
      
      While we're at it, the boolean argument is also properly changed to
      bool and true/false, as well as a slight refactoring of PCM pause
      helper function to make easier to read.
      
      No functional changes, just shutting up chatty sparse.
      
      Fixes: 46b770f7 ("ALSA: uapi: Fix sparse warning")
      Reported-by: Nkbuild test robot <lkp@intel.com>
      Link: https://lore.kernel.org/r/20200131152214.11698-1-tiwai@suse.deSigned-off-by: NTakashi Iwai <tiwai@suse.de>
      cb639a42
  12. 30 1月, 2020 1 次提交
    • T
      ALSA: pcm: Fix memory leak at closing a stream without hw_free · 66f2d19f
      Takashi Iwai 提交于
      ALSA PCM core recently introduced a new managed PCM buffer allocation
      mode that does allocate / free automatically at hw_params and
      hw_free.  However, it overlooked the code path directly calling
      hw_free PCM ops at releasing the PCM substream, and it may result in a
      memory leak as spotted by syzkaller when no buffer preallocation is
      used (e.g. vmalloc buffer).
      
      This patch papers over it with a slight refactoring.  The hw_free ops
      call and relevant tasks are unified in a new helper function, and call
      it from both places.
      
      Fixes: 0dba808e ("ALSA: pcm: Introduce managed buffer allocation mode")
      Reported-by: syzbot+30edd0f34bfcdc548ac4@syzkaller.appspotmail.com
      Cc: <stable@vger.kernel.org>
      Link: https://lore.kernel.org/r/20200129195907.12197-1-tiwai@suse.deSigned-off-by: NTakashi Iwai <tiwai@suse.de>
      66f2d19f
  13. 17 1月, 2020 1 次提交
  14. 15 12月, 2019 1 次提交
  15. 13 12月, 2019 2 次提交
    • A
      ALSA: add new 32-bit layout for snd_pcm_mmap_status/control · 80fe7430
      Arnd Bergmann 提交于
      The snd_pcm_mmap_status and snd_pcm_mmap_control interfaces are one of the
      trickiest areas to get right when moving to 64-bit time_t in user space.
      
      The snd_pcm_mmap_status structure layout is incompatible with user space
      that uses a 64-bit time_t, so we need a new layout for it. Since the
      SNDRV_PCM_IOCTL_SYNC_PTR ioctl combines it with snd_pcm_mmap_control
      into snd_pcm_sync_ptr, we need to change those two as well.
      
      Both structures are also exported via an mmap() operation on certain
      architectures, and this suffers from incompatibility between 32-bit
      and 64-bit user space. As we have to change both structures anyway,
      this is a good opportunity to fix the mmap() problem as well, so let's
      standardize on the existing 64-bit layout of the structure where possible.
      
      The downside is that we lose mmap() support for existing 32-bit x86 and
      powerpc applications, adding that would introduce very noticeable runtime
      overhead and complexity. My assumption here is that not too many people
      will miss the removed feature, given that:
      
      - Almost all x86 and powerpc users these days are on 64-bit kernels,
      the majority of today's 32-bit users are on architectures that never
      supported mmap (ARM, MIPS, ...).
      - It never worked in compat mode (it was intentionally disabled there)
      - The application already needs to work with a fallback to
      SNDRV_PCM_IOCTL_SYNC_PTR, which will keep working with both the old
      and new structure layout.
      
      Both the ioctl() and mmap() based interfaces are changed at the same
      time, as they are based on the same structures. Unlike other interfaces,
      we change the uapi header to export both the traditional structure and
      a version that is portable between 32-bit and 64-bit user space code
      and that corresponds to the existing 64-bit layout. We further check the
      __USE_TIME_BITS64 macro that will be defined by future C library versions
      whenever we use the new time_t definition, so any existing user space
      source code will not see any changes until it gets rebuilt against a new
      C library. However, the new structures are all visible in addition to the
      old ones, allowing applications to explicitly request the new structures.
      
      In order to detect the difference between the old snd_pcm_mmap_status and
      the new __snd_pcm_mmap_status64 structure from the ioctl command number,
      we rely on one quirk in the structure definition: snd_pcm_mmap_status
      must be aligned to alignof(time_t), which leads the compiler to insert
      four bytes of padding in struct snd_pcm_sync_ptr after 'flags' and a
      corresponding change in the size of snd_pcm_sync_ptr itself. On x86-32
      (and only there), the compiler doesn't use 64-bit alignment in structure,
      so I'm adding an explicit pad in the structure that has no effect on the
      existing 64-bit architectures but ensures that the layout matches for x86.
      
      The snd_pcm_uframes_t type compatibility requires another hack: we can't
      easily make that 64 bit wide, so I leave the type as 'unsigned long',
      but add padding before and after it, to ensure that the data is properly
      aligned to the respective 64-bit field in the in-kernel structure.
      
      For the SNDRV_PCM_MMAP_OFFSET_STATUS/CONTROL constants that are used
      as the virtual file offset in the mmap() function, we also have to
      introduce new constants that depend on hte __USE_TIME_BITS64 macro:
      The existing macros are renamed to SNDRV_PCM_MMAP_OFFSET_STATUS_OLD
      and SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD, they continue to work fine on
      64-bit architectures, but stop working on native 32-bit user space.
      The replacement _NEW constants are now used by default for user space
      built with __USE_TIME_BITS64, those now work on all new kernels for x86,
      ppc and alpha (32 and 64 bit, native and compat). It might be a good idea
      for a future alsa-lib to support both the _OLD and _NEW macros and use
      the corresponding structures directly. Unmodified alsa-lib source code
      will retain the current behavior, so it will no longer be able to use
      mmap() for the status/control structures on 32-bit systems, until either
      the C library gets updated to 64-bit time_t or alsa-lib gets updated to
      support both mmap() layouts.
      
      Co-developed-with: Baolin Wang <baolin.wang@linaro.org>
      Signed-off-by: NBaolin Wang <baolin.wang@linaro.org>
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      80fe7430
    • A
      ALSA: move snd_pcm_ioctl_sync_ptr_compat into pcm_native.c · 09d94175
      Arnd Bergmann 提交于
      This is a preparation patch, moving the compat handler for
      snd_pcm_ioctl_sync_ptr_compat from pcm_compat.c to pcm_native.c.
      No other changes are indented.
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Signed-off-by: NBaolin Wang <baolin.wang@linaro.org>
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      09d94175
  16. 12 12月, 2019 2 次提交
    • B
      ALSA: Avoid using timespec for struct snd_pcm_status · 3ddee7f8
      Baolin Wang 提交于
      The struct snd_pcm_status will use 'timespec' type variables to record
      timestamp, which is not year 2038 safe on 32bits system.
      
      Userspace will use SNDRV_PCM_IOCTL_STATUS and SNDRV_PCM_IOCTL_STATUS_EXT
      as commands to issue ioctl() to fill the 'snd_pcm_status' structure in
      userspace. The command number is always defined through _IOR/_IOW/IORW,
      so when userspace changes the definition of 'struct timespec' to use
      64-bit types, the command number also changes.
      
      Thus in the kernel, we now need to define two versions of each such ioctl
      and corresponding ioctl commands to handle 32bit time_t and 64bit time_t
      in native mode:
      struct snd_pcm_status32 {
      	......
      
      	s32 trigger_tstamp_sec;
      	s32 trigger_tstamp_nsec;
      
      	......
      
      	s32 audio_tstamp_sec;
      	s32 audio_tstamp_nsec;
      
      	......
      };
      
      struct snd_pcm_status64 {
      	......
      
      	s32 trigger_tstamp_sec;
      	s32 trigger_tstamp_nsec;
      
      	......
      
      	s32 audio_tstamp_sec;
      	s32 audio_tstamp_nsec;
      
      	......
      };
      
      Moreover in compat file, we renamed or introduced new structures to handle
      32bit/64bit time_t in compatible mode. The 'struct snd_pcm_status32' and
      snd_pcm_status_user32() are used to handle 32bit time_t in compat mode.
      'struct compat_snd_pcm_status64' and snd_pcm_status_user_compat64() are used
      to handle 64bit time_t.
      
      The implicit padding before timespec is made explicit to avoid incompatible
      structure layout between 32-bit and 64-bit x86 due to the different
      alignment requirements, and the snd_pcm_status structure is now hidden
      from the kernel to avoid relying on the timespec definitio definitionn
      
      Finally we can replace SNDRV_PCM_IOCTL_STATUS and SNDRV_PCM_IOCTL_STATUS_EXT
      with new commands and introduce new functions to fill new 'struct snd_pcm_status64'
      instead of using unsafe 'struct snd_pcm_status'. Then in future, the new
      commands can be matched when userspace changes 'timespec' to 64bit type
      to make a size change of 'struct snd_pcm_status'. When glibc changes time_t
      to 64-bit, any recompiled program will issue ioctl commands that the kernel
      does not understand without this patch.
      Signed-off-by: NBaolin Wang <baolin.wang@linaro.org>
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      3ddee7f8
    • B
      ALSA: Replace timespec with timespec64 · fcae40c9
      Baolin Wang 提交于
      Since timespec is not year 2038 safe on 32bit system, and we need to
      convert all timespec variables to timespec64 type for sound subsystem.
      
      This patch is used to do preparation for following patches, that will
      convert all structures defined in uapi/sound/asound.h to use 64-bit
      time_t.
      Signed-off-by: NBaolin Wang <baolin.wang@linaro.org>
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      fcae40c9
  17. 21 11月, 2019 4 次提交
    • T
      ALSA: pcm: Add card sync_irq field · fabb26dc
      Takashi Iwai 提交于
      Many PCI and other drivers performs snd_pcm_period_elapsed() simply in
      its interrupt handler, so the sync_stop operation is just to call
      synchronize_irq().  Instead of putting this call multiple times,
      introduce the common card->sync_irq field.  When this field is set,
      PCM core performs synchronize_irq() for sync-stop operation.  Each
      driver just needs to copy its local IRQ number to card->sync_irq, and
      that's all we need.
      
      Link: https://lore.kernel.org/r/20191117085308.23915-8-tiwai@suse.deSigned-off-by: NTakashi Iwai <tiwai@suse.de>
      fabb26dc
    • T
      ALSA: pcm: Add the support for sync-stop operation · 1e850bee
      Takashi Iwai 提交于
      The standard programming model of a PCM sound driver is to process
      snd_pcm_period_elapsed() from an interrupt handler.  When a running
      stream is stopped, PCM core calls the trigger-STOP PCM ops, sets the
      stream state to SETUP, and moves on to the next step.  This is
      performed in an atomic manner -- this could be called from the interrupt
      context, after all.
      
      The problem is that, if the stream goes further and reaches to the
      CLOSE state immediately, the stream might be still being processed in
      snd_pcm_period_elapsed() in the interrupt context, and hits a NULL
      dereference.  Such a crash happens because of the atomic operation,
      and we can't wait until the stream-stop finishes.
      
      For addressing such a problem, this commit adds a new PCM ops,
      sync_stop.  This gets called at the appropriate places that need a
      sync with the stream-stop, i.e. at hw_params, prepare and hw_free.
      
      Some drivers already have a similar mechanism implemented locally, and
      we'll refactor the code later.
      
      Link: https://lore.kernel.org/r/20191117085308.23915-7-tiwai@suse.deSigned-off-by: NTakashi Iwai <tiwai@suse.de>
      1e850bee
    • T
      ALSA: pcm: Allow NULL ioctl ops · fc033cbf
      Takashi Iwai 提交于
      Currently PCM ioctl ops is a mandatory field but almost all drivers
      simply pass snd_pcm_lib_ioctl.  For simplicity, allow to set NULL in
      the field and call snd_pcm_lib_ioctl() as default.
      
      Link: https://lore.kernel.org/r/20191117085308.23915-4-tiwai@suse.deSigned-off-by: NTakashi Iwai <tiwai@suse.de>
      fc033cbf
    • T
      ALSA: pcm: Introduce managed buffer allocation mode · 0dba808e
      Takashi Iwai 提交于
      This patch adds the support for the feature to automatically allocate
      and free PCM buffers, so called "managed buffer allocation" mode.
      It's set up via new PCM helpers, snd_pcm_set_managed_buffer() and
      snd_pcm_set_managed_buffer_all(), both of which correspond to the
      existing preallocator helpers, snd_pcm_lib_preallocate_pages() and
      snd_pcm_lib_preallocate_pages_for_all().  When the new helper is used,
      it not only performs the pre-allocation of buffers, but also it
      manages to call snd_pcm_lib_malloc_pages() before the PCM hw_params
      ops and snd_lib_pcm_free() after the PCM hw_free ops inside PCM core,
      respectively.  This allows drivers to drop the explicit calls of the
      memory allocation / release functions, and it will be a good amount of
      code reduction in the end of this patch series.
      
      When the PCM substream is set to the managed buffer allocation mode,
      the managed_buffer_alloc flag is set in the substream object.  Since
      some drivers want to know when a buffer is newly allocated or
      re-allocated at hw_params callback (e.g. want to set up the additional
      stuff for the given buffer only at allocation time), now PCM core
      turns on buffer_changed flag when the buffer has changed.
      
      The standard conversions to use the new API will be straightforward:
      - Replace snd_pcm_lib_preallocate*() calls with the corresponding
        snd_pcm_set_managed_buffer*(); the arguments should be unchanged
      - Drop superfluous snd_pcm_lib_malloc() and snd_pcm_lib_free() calls;
        the check of snd_pcm_lib_malloc() returns should be replaced with
        the check of runtime->buffer_changed flag.
      - If hw_params or hw_free becomes empty, drop them from PCM ops
      
      Link: https://lore.kernel.org/r/20191117085308.23915-2-tiwai@suse.deSigned-off-by: NTakashi Iwai <tiwai@suse.de>
      0dba808e
  18. 10 11月, 2019 1 次提交
  19. 06 11月, 2019 1 次提交
    • T
      ALSA: pcm: Handle special page mapping in the default mmap handler · 7e8edae3
      Takashi Iwai 提交于
      When a driver needs to deal with a special buffer like a SG or a
      vmalloc buffer, it has to set up the PCM page ops explicitly for the
      corresponding helper function.  This is rather error-prone and many
      people forgot or incorrectly used it.
      
      For simplifying the call patterns and avoiding such a potential bug,
      this patch enhances the PCM default mmap handler to check the
      (pre-)allocated buffer type and handles the page gracefully depending
      on the buffer type.  If the PCM page ops is given, the ops is still
      used in a higher priority.  The new code path is only for the default
      (NULL page ops) case.
      
      Link: https://lore.kernel.org/r/20191105080138.1260-4-tiwai@suse.deSigned-off-by: NTakashi Iwai <tiwai@suse.de>
      7e8edae3
  20. 04 11月, 2019 1 次提交
    • T
      ALSA: pcm: Fix missing check of the new non-cached buffer type · 6111fd23
      Takashi Iwai 提交于
      The check for the mmap support via hw_support_mmap() function misses
      the case where the device is with SNDRV_DMA_TYPE_DEV_UC, which should
      have been treated equally as SNDRV_DMA_TYPE_DEV.  Let's fix it.
      
      Note that this bug doesn't hit any practical problem, because
      SNDRV_DMA_TYPE_DEV_UC is used only for x86-specific drivers
      (snd-hda-intel and snd-intel8x0) for the specific platforms that need
      the non-cached buffers.  And, on such platforms, hw_support_mmap()
      already returns true in anyway.  That's the reason I didn't put
      Cc-to-stable mark here.  This is only for any theoretical future
      extension.
      
      Fixes: 425da159 ("ALSA: pcm: use dma_can_mmap() to check if a device supports dma_mmap_*")
      Fixes: 42e748a0 ("ALSA: memalloc: Add non-cached buffer type")
      Link: https://lore.kernel.org/r/20191104101115.27311-1-tiwai@suse.deSigned-off-by: NTakashi Iwai <tiwai@suse.de>
      6111fd23
  21. 04 9月, 2019 1 次提交
  22. 28 8月, 2019 1 次提交
  23. 30 7月, 2019 1 次提交
  24. 19 7月, 2019 1 次提交
    • T
      ALSA: pcm: Fix refcount_inc() on zero usage · 0e279dce
      Takashi Iwai 提交于
      The recent rewrite of PCM link lock management introduced the refcount
      in snd_pcm_group object, managed by the kernel refcount_t API.  This
      caused unexpected kernel warnings when the kernel is built with
      CONFIG_REFCOUNT_FULL=y.  As the warning line indicates, the problem is
      obviously that we start with refcount=0 and do refcount_inc() for
      adding each PCM link, while refcount_t API doesn't like refcount_inc()
      performed on zero.
      
      For adapting the proper refcount_t usage, this patch changes the logic
      slightly:
      - The initial refcount is 1, assuming the single list entry
      - The refcount is incremented / decremented at each PCM link addition
        and deletion
      - ... which allows us concentrating only on the refcount as a release
        condition
      
      Fixes: f57f3df0 ("ALSA: pcm: More fine-grained PCM link locking")
      BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=204221Reported-and-tested-by: NDuncan Overbruck <kernel@duncano.de>
      Cc: <stable@vger.kernel.org>
      Signed-off-by: NTakashi Iwai <tiwai@suse.de>
      0e279dce
  25. 31 5月, 2019 1 次提交
  26. 25 3月, 2019 1 次提交
    • T
      ALSA: pcm: Don't suspend stream in unrecoverable PCM state · 113ce081
      Takashi Iwai 提交于
      Currently PCM core sets each opened stream forcibly to SUSPENDED state
      via snd_pcm_suspend_all() call, and the user-space is responsible for
      re-triggering the resume manually either via snd_pcm_resume() or
      prepare call.  The scheme works fine usually, but there are corner
      cases where the stream can't be resumed by that call: the streams
      still in OPEN state before finishing hw_params.  When they are
      suspended, user-space cannot perform resume or prepare because they
      haven't been set up yet.  The only possible recovery is to re-open the
      device, which isn't nice at all.  Similarly, when a stream is in
      DISCONNECTED state, it makes no sense to change it to SUSPENDED
      state.  Ditto for in SETUP state; which you can re-prepare directly.
      
      So, this patch addresses these issues by filtering the PCM streams to
      be suspended by checking the PCM state.  When a stream is in either
      OPEN, SETUP or DISCONNECTED as well as already SUSPENDED, the suspend
      action is skipped.
      
      To be noted, this problem was originally reported for the PCM runtime
      PM on HD-audio.  And, the runtime PM problem itself was already
      addressed (although not intended) by the code refactoring commits
      3d21ef0b ("ALSA: pcm: Suspend streams globally via device type PM
      ops") and 17bc4815 ("ALSA: pci: Remove superfluous
      snd_pcm_suspend*() calls").  These commits eliminated the
      snd_pcm_suspend*() calls from the runtime PM suspend callback code
      path, hence the racy OPEN state won't appear while runtime PM.
      (FWIW, the race window is between snd_pcm_open_substream() and the
      first power up in azx_pcm_open().)
      
      Although the runtime PM issue was already "fixed", the same problem is
      still present for the system PM, hence this patch is still needed.
      And for stable trees, this patch alone should suffice for fixing the
      runtime PM problem, too.
      Reported-and-tested-by: NJon Hunter <jonathanh@nvidia.com>
      Cc: <stable@vger.kernel.org>
      Signed-off-by: NTakashi Iwai <tiwai@suse.de>
      113ce081
  27. 12 2月, 2019 1 次提交
  28. 31 1月, 2019 1 次提交
  29. 24 1月, 2019 1 次提交
  30. 23 1月, 2019 3 次提交
    • T
      ALSA: pcm: Cleanup snd_pcm_stream_lock() & co · ef2056b8
      Takashi Iwai 提交于
      After the previous code refactoring, the PCM stream locking code
      became nothing but the PCM group lock with self_group object.  Use the
      existing helper function for simplifying the code.
      Signed-off-by: NTakashi Iwai <tiwai@suse.de>
      ef2056b8
    • T
      ALSA: pcm: Remove down_write() hack for snd_pcm_link_rwsem · ecb41f0f
      Takashi Iwai 提交于
      Remove the hackish down_write_nonfifo() that was introduced as a
      workaround of rwsem deadlock.
      
      It used to be a problem for non-atomic PCM streams that take the rwsem
      for the locking and hit the high lock contention.  Since the current
      PCM locking refactoring, we'll no longer hit it as the hot code-paths
      don't take global locks.
      Signed-off-by: NTakashi Iwai <tiwai@suse.de>
      ecb41f0f
    • T
      ALSA: pcm: More fine-grained PCM link locking · f57f3df0
      Takashi Iwai 提交于
      We have currently two global locks, a rwlock and a rwsem, that are
      used for managing linking the PCM streams.  Due to these global locks,
      once when a linked stream is used, the lock granularity suffers a
      lot.
      
      This patch attempts to eliminate the former global lock for atomic
      ops.  The latter rwsem needs remaining because of the loosy way of the
      loop calls in snd_pcm_action_nonatomic(), as well as for avoiding the
      deadlock at linking.  However, these are used far rarely, actually
      only by two actions (prepare and  reset), where both are no timing
      critical ones.  So this can be still seen as a good improvement.
      
      The basic strategy to eliminate the rwlock is to assure group->lock at
      adding or removing a stream to / from the group.  Since we already
      takes the group lock whenever taking the all substream locks under the
      group, this shouldn't be a big problem.  The reference to group
      pointer in snd_pcm_substream object is protected by the stream lock
      itself.
      
      However, there are still pitfalls: a race window at re-locking and the
      lifecycle of group object.  The former is a small race window for
      dereferencing the substream group object opened while snd_pcm_action()
      performs re-locking to avoid ABBA deadlocks.  This includes the unlink
      of group during that window, too.  And the latter is the kfree
      performed after all streams are removed from the group while it's
      still dereferenced.
      
      For addressing these corner cases, two new tricks are introduced:
      - After re-locking, the group assigned to the stream is checked again;
        if the group is changed, we retry the whole procedure.
      - Introduce a refcount to snd_pcm_group object, so that it's freed
        only when it's empty and really no one refers to it.
      
      (Some readers might wonder why not RCU for the latter.  RCU in this
      case would cost more than refcounting, unfortunately.  We take the
      group lock sooner or later, hence the performance improvement by RCU
      would be negligible.  Meanwhile, because we need to deal with
      schedulable context depending on the pcm->nonatomic flag, it'll become
      dynamic RCU/SRCU switch, and the grace period may become too long.)
      
      Along with these changes, there are a significant amount of code
      refactoring.  The complex group re-lock & ref code is factored out to
      snd_pcm_stream_group_ref() function, for example.
      Signed-off-by: NTakashi Iwai <tiwai@suse.de>
      f57f3df0
  31. 21 1月, 2019 2 次提交