1. 20 Jun, 2017 8 commits
  2. 19 Jun, 2017 1 commit
    • Takashi Sakamoto's avatar
      ALSA: firewire-lib: Fix stall of process context at packet error · 4a9bfafc
      Takashi Sakamoto authored
      At Linux v3.5, packet processing can be done in process context of ALSA
      PCM application as well as software IRQ context for OHCI 1394. Below is
      an example of the callgraph (some calls are omitted).
      
      ioctl(2) with e.g. HWSYNC
      (sound/core/pcm_native.c)
      ->snd_pcm_common_ioctl1()
        ->snd_pcm_hwsync()
          ->snd_pcm_stream_lock_irq
          (sound/core/pcm_lib.c)
          ->snd_pcm_update_hw_ptr()
            ->snd_pcm_udpate_hw_ptr0()
              ->struct snd_pcm_ops.pointer()
              (sound/firewire/*)
              = Each handler on drivers in ALSA firewire stack
                (sound/firewire/amdtp-stream.c)
                ->amdtp_stream_pcm_pointer()
                  (drivers/firewire/core-iso.c)
                  ->fw_iso_context_flush_completions()
                    ->struct fw_card_driver.flush_iso_completion()
                    (drivers/firewire/ohci.c)
                    = flush_iso_completions()
                      ->struct fw_iso_context.callback.sc
                      (sound/firewire/amdtp-stream.c)
                      = in_stream_callback() or out_stream_callback()
                        ->...
          ->snd_pcm_stream_unlock_irq
      
      When packet queueing error occurs or detecting invalid packets in
      'in_stream_callback()' or 'out_stream_callback()', 'snd_pcm_stop_xrun()'
      is called on local CPU with disabled IRQ.
      
      (sound/firewire/amdtp-stream.c)
      in_stream_callback() or out_stream_callback()
      ->amdtp_stream_pcm_abort()
        ->snd_pcm_stop_xrun()
          ->snd_pcm_stream_lock_irqsave()
          ->snd_pcm_stop()
          ->snd_pcm_stream_unlock_irqrestore()
      
      The process is stalled on the CPU due to attempt to acquire recursive lock.
      
      [  562.630853] INFO: rcu_sched detected stalls on CPUs/tasks:
      [  562.630861]      2-...: (1 GPs behind) idle=37d/140000000000000/0 softirq=38323/38323 fqs=7140
      [  562.630862]      (detected by 3, t=15002 jiffies, g=21036, c=21035, q=5933)
      [  562.630866] Task dump for CPU 2:
      [  562.630867] alsa-source-OXF R  running task        0  6619      1 0x00000008
      [  562.630870] Call Trace:
      [  562.630876]  ? vt_console_print+0x79/0x3e0
      [  562.630880]  ? msg_print_text+0x9d/0x100
      [  562.630883]  ? up+0x32/0x50
      [  562.630885]  ? irq_work_queue+0x8d/0xa0
      [  562.630886]  ? console_unlock+0x2b6/0x4b0
      [  562.630888]  ? vprintk_emit+0x312/0x4a0
      [  562.630892]  ? dev_vprintk_emit+0xbf/0x230
      [  562.630895]  ? do_sys_poll+0x37a/0x550
      [  562.630897]  ? dev_printk_emit+0x4e/0x70
      [  562.630900]  ? __dev_printk+0x3c/0x80
      [  562.630903]  ? _raw_spin_lock+0x20/0x30
      [  562.630909]  ? snd_pcm_stream_lock+0x31/0x50 [snd_pcm]
      [  562.630914]  ? _snd_pcm_stream_lock_irqsave+0x2e/0x40 [snd_pcm]
      [  562.630918]  ? snd_pcm_stop_xrun+0x16/0x70 [snd_pcm]
      [  562.630922]  ? in_stream_callback+0x3e6/0x450 [snd_firewire_lib]
      [  562.630925]  ? handle_ir_packet_per_buffer+0x8e/0x1a0 [firewire_ohci]
      [  562.630928]  ? ohci_flush_iso_completions+0xa3/0x130 [firewire_ohci]
      [  562.630932]  ? fw_iso_context_flush_completions+0x15/0x20 [firewire_core]
      [  562.630935]  ? amdtp_stream_pcm_pointer+0x2d/0x40 [snd_firewire_lib]
      [  562.630938]  ? pcm_capture_pointer+0x19/0x20 [snd_oxfw]
      [  562.630943]  ? snd_pcm_update_hw_ptr0+0x47/0x3d0 [snd_pcm]
      [  562.630945]  ? poll_select_copy_remaining+0x150/0x150
      [  562.630947]  ? poll_select_copy_remaining+0x150/0x150
      [  562.630952]  ? snd_pcm_update_hw_ptr+0x10/0x20 [snd_pcm]
      [  562.630956]  ? snd_pcm_hwsync+0x45/0xb0 [snd_pcm]
      [  562.630960]  ? snd_pcm_common_ioctl1+0x1ff/0xc90 [snd_pcm]
      [  562.630962]  ? futex_wake+0x90/0x170
      [  562.630966]  ? snd_pcm_capture_ioctl1+0x136/0x260 [snd_pcm]
      [  562.630970]  ? snd_pcm_capture_ioctl+0x27/0x40 [snd_pcm]
      [  562.630972]  ? do_vfs_ioctl+0xa3/0x610
      [  562.630974]  ? vfs_read+0x11b/0x130
      [  562.630976]  ? SyS_ioctl+0x79/0x90
      [  562.630978]  ? entry_SYSCALL_64_fastpath+0x1e/0xad
      
      This commit fixes the above bug. This assumes two cases:
      1. Any error is detected in software IRQ context of OHCI 1394 context.
      In this case, PCM substream should be aborted in packet handler. On the
      other hand, it should not be done in any process context. TO distinguish
      these two context, use 'in_interrupt()' macro.
      2. Any error is detect in process context of ALSA PCM application.
      In this case, PCM substream should not be aborted in packet handler
      because PCM substream lock is acquired. The task to abort PCM substream
      should be done in ALSA PCM core. For this purpose, SNDRV_PCM_POS_XRUN is
      returned at 'struct snd_pcm_ops.pointer()'.
      Suggested-by: default avatarClemens Ladisch <clemens@ladisch.de>
      Fixes: e9148ddd("ALSA: firewire-lib: flush completed packets when reading PCM position")
      Cc: <stable@vger.kernel.org> # 4.9+
      Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
      Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
      4a9bfafc
  3. 16 Jun, 2017 6 commits
  4. 14 Jun, 2017 10 commits
  5. 13 Jun, 2017 1 commit
  6. 12 Jun, 2017 4 commits
    • Takashi Sakamoto's avatar
      ALSA: pcm: use %s instead of %c for format of PCM buffer tracepoints · f5abd532
      Takashi Sakamoto authored
      As long as I know, in userspace, '%c' format on printing format for
      tracepoint is replaced with '>c<' by existent tracing program; i.g.
      'perf-trace' and 'trace-cmd'. This is inconvenient.
      
      This commit replaces the format with '%s'. The length of letters in the
      format string is not changed, thus this commit doesn't increase object
      size.
      
      In theory, I should work for improvements of these tracing programs, but
      here I'd like to save my time to work for the other projects.
      Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
      Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
      f5abd532
    • Takashi Sakamoto's avatar
      ALSA: pcm: add 'applptr' event of tracepoint · fccf5388
      Takashi Sakamoto authored
      In design of ALSA PCM core, status and control data for runtime of ALSA
      PCM substream are shared between kernel/user spaces by page frame
      mapping with read-only attribute. Both of hardware-side and
      application-side position on PCM buffer are maintained as a part of
      the status data. In a view of ALSA PCM application, these two positions
      can be updated by executing ioctl(2) with some commands.
      
      There's an event of tracepoint for hardware-side position; 'hwptr'.
      On the other hand, no events for application-side position. This commit
      adds a new event for this purpose; 'applptr'. When the application-side
      position is changed in kernel space, this event is probed with useful
      information for developers.
      
      I note that the event is not probed for all of ALSA PCM applications, When
      applications are written by read/write programming scenario, the event is
      surely probed. The applications execute ioctl(2) with
      SNDRV_PCM_IOCTL_[READ|WRITE][N/I]_FRAMES to read/write any PCM frame, then
      ALSA PCM core updates the application-side position in kernel land.
      However, when applications are written by mmap programming scenario, if
      maintaining the application side position in kernel space accurately,
      applications should voluntarily execute ioctl(2) with
      SNDRV_PCM_IOCTL_SYNC_PTR to commit the number of handled PCM frames. If
      not voluntarily, the application-side position is not changed, thus the
      added event is not probed.
      
      There's a loophole, using architectures to which ALSA PCM core judges
      non cache coherent. In this case, the status and control data is not mapped
      into processe's VMA for any applications. Userland library, alsa-lib, is
      programmed for this case. It executes ioctl(2) with
      SNDRV_PCM_IOCTL_SYNC_PTR command every time to requiring the status and
      control data.
      
      ARM is such an architecture. Below is an example with serial sound interface
      (ssi) on i.mx6 quad core SoC. I use v4.1 kernel released by fsl-community
      with patches from VIA Tech. Inc. for VAB820, and my backport patches for
      relevant features for this patchset. I use Ubuntu 17.04 from
      ports.ubuntu.com as user land for armhf architecture.
      
      $ aplay -v -M -D hw:imx6vab820sgtl5,0 /dev/urandom -f S16_LE -r 48000 --period-size=128 --buffer-size=256
      Playing raw data '/dev/urandom' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
      Hardware PCM card 0 'imx6-vab820-sgtl5000' device 0 subdevice 0
      Its setup is:
        stream       : PLAYBACK
        access       : MMAP_INTERLEAVED
        format       : S16_LE
        subformat    : STD
        channels     : 1
        rate         : 48000
        exact rate   : 48000 (48000/1)
        msbits       : 16
        buffer_size  : 256
        period_size  : 128
        period_time  : 2666
        tstamp_mode  : NONE
        tstamp_type  : MONOTONIC
        period_step  : 1
        avail_min    : 128
        period_event : 0
        start_threshold  : 256
        stop_threshold   : 256
        silence_threshold: 0
        silence_size : 0
        boundary     : 1073741824
        appl_ptr     : 0
        hw_ptr       : 0
      mmap_area[0] = 0x76f98000,0,16 (16)
      
      $ trace-cmd record -e snd_pcm:hwptr -e snd_pcm:applptr
      $ trace-cmd report
      ...
      60.208495: applptr: pcmC0D0p/sub0: prev=1792, curr=1792, avail=0, period=128, buf=256
      60.208633: applptr: pcmC0D0p/sub0: prev=1792, curr=1792, avail=0, period=128, buf=256
      60.210022: hwptr:   pcmC0D0p/sub0: IRQ: pos=128, old=1536, base=1536, period=128, buf=256
      60.210202: applptr: pcmC0D0p/sub0: prev=1792, curr=1792, avail=128, period=128, buf=256
      60.210344: hwptr:   pcmC0D0p/sub0: POS: pos=128, old=1664, base=1536, period=128, buf=256
      60.210348: applptr: pcmC0D0p/sub0: prev=1792, curr=1792, avail=128, period=128, buf=256
      60.210486: applptr: pcmC0D0p/sub0: prev=1792, curr=1792, avail=128, period=128, buf=256
      60.210626: applptr: pcmC0D0p/sub0: prev=1792, curr=1920, avail=0, period=128, buf=256
      60.211002: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=0, period=128, buf=256
      60.211142: hwptr:   pcmC0D0p/sub0: POS: pos=128, old=1664, base=1536, period=128, buf=256
      60.211146: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=0, period=128, buf=256
      60.211287: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=0, period=128, buf=256
      60.212690: hwptr:   pcmC0D0p/sub0: IRQ: pos=0, old=1664, base=1536, period=128, buf=256
      60.212866: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=128, period=128, buf=256
      60.212999: hwptr:   pcmC0D0p/sub0: POS: pos=0, old=1792, base=1792, period=128, buf=256
      60.213003: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=128, period=128, buf=256
      60.213135: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=128, period=128, buf=256
      60.213276: applptr: pcmC0D0p/sub0: prev=1920, curr=2048, avail=0, period=128, buf=256
      60.213654: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=0, period=128, buf=256
      60.213796: hwptr:   pcmC0D0p/sub0: POS: pos=0, old=1792, base=1792, period=128, buf=256
      60.213800: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=0, period=128, buf=256
      60.213937: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=0, period=128, buf=256
      60.215356: hwptr:   pcmC0D0p/sub0: IRQ: pos=128, old=1792, base=1792, period=128, buf=256
      60.215542: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=128, period=128, buf=256
      60.215679: hwptr:   pcmC0D0p/sub0: POS: pos=128, old=1920, base=1792, period=128, buf=256
      60.215683: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=128, period=128, buf=256
      60.215813: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=128, period=128, buf=256
      60.215947: applptr: pcmC0D0p/sub0: prev=2048, curr=2176, avail=0, period=128, buf=256
      ...
      
      We can surely see 'applptr' event is probed even if the application run
      for mmap programming scenario ('-M' option and 'hw' plugin). Below is a
      result of strace:
      
      02:44:15.886382 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.887203 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}])
      02:44:15.887471 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.887637 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.887805 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.887969 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.888132 read(3, "..."..., 256) = 256
      02:44:15.889040 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.889221 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.889431 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.889606 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}])
      02:44:15.889833 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.889998 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.890164 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.891048 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.891228 read(3, "..."..., 256) = 256
      02:44:15.891497 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.891661 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.891829 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      02:44:15.891991 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}])
      02:44:15.893007 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
      
      We can see 7 calls of ioctl(2) with SNDRV_PCM_IOCTL_SYNC_PTR per loop with
      call of poll(2). 128 PCM frames are transferred per loop of one poll(2),
      because the PCM substream is configured with S16_LE format and 1 channel
      (2 byte * 1 * 128 = 256 bytes). This equals to the size of period of PCM
      buffer. Comparing to the probed data, one of the 7 calls of ioctl(2) is
      actually used to commit the number of copied PCM frames to kernel space.
      The other calls are just used to check runtime status of PCM substream;
      e.g. XRUN.
      
      The tracepoint event is useful to investigate this case. I note that below
      modules are related to the above sample.
      
       * snd-soc-dummy.ko
       * snd-soc-imx-sgtl5000.ko
       * snd-soc-fsl-ssi.ko
       * snd-soc-imx-pcm-dma.ko
       * snd-soc-sgtl5000.ko
      
      My additional note is lock acquisition. The event is probed under acquiring
      PCM stream lock. This means that calculation in the event is free from
      any hardware events.
      Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
      Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
      fccf5388
    • Takashi Sakamoto's avatar
      ALSA: pcm: unify codes to operate application-side position on PCM buffer · 66e01a5c
      Takashi Sakamoto authored
      In a series of recent work, ALSA PCM core got some arrangements to handle
      application-side position on PCM buffer. However, relevant codes still
      disperse to two translation units
      
      This commit unifies these codes into a helper function.
      Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
      Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
      66e01a5c
    • Takashi Iwai's avatar
      ALSA: seq: Allow the modular sequencer registration · 111b0cdb
      Takashi Iwai authored
      Many drivers bind the sequencer stuff in off-load by another driver
      module, so that it's loaded only on demand.  In the current code, this
      mechanism doesn't work when the driver is built-in while the sequencer
      is module.  We check with IS_REACHABLE() and enable only when the
      sequencer is in the same level of build.
      
      However, this is basically a overshoot.  The binder code
      (snd-seq-device) is an individual module from the sequencer core
      (snd-seq), and we just have to make the former a built-in while
      keeping the latter a module for allowing the scenario like the above.
      
      This patch achieves that by rewriting Kconfig slightly.  Now, a driver
      that provides the manual sequencer device binding should select
      CONFIG_SND_SEQ_DEVICE in a way as
      	select SND_SEQ_DEVICE if SND_SEQUENCER != n
      
      Note that the "!=n" is needed here to avoid the influence of the
      sequencer core is module while the driver is built-in.
      
      Also, since rawmidi.o may be linked with snd_seq_device.o when
      built-in, we have to shuffle the code to make the linker happy.
      (the kernel linker isn't smart enough yet to handle such a case.)
      That is, snd_seq_device.c is moved to sound/core from sound/core/seq,
      as well as Makefile.
      
      Last but not least, the patch replaces the code using IS_REACHABLE()
      with IS_ENABLED(), since now the condition meets always when enabled.
      Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
      111b0cdb
  7. 11 Jun, 2017 2 commits
  8. 09 Jun, 2017 8 commits