1. 21 Aug, 2017 1 commit
  2. 20 Aug, 2017 3 commits
    • Takashi Sakamoto's avatar
      ALSA: control: use counting semaphore as write lock for ELEM_WRITE operation · 5bbb1ab5
      Takashi Sakamoto authored
      In ALSA control interface, applications can execute two types of request
      for value of members on each element; ELEM_READ and ELEM_WRITE. In ALSA
      control core, these two requests are handled within read lock of a
      counting semaphore, therefore several processes can run to execute these
      two requests at the same time. This has an issue because ELEM_WRITE
      requests have an effect to change state of the target element. Concurrent
      access should be controlled for each of ELEM_READ/ELEM_WRITE case.
      
      This commit uses the counting semaphore as write lock for ELEM_WRITE
      requests, while use it as read lock for ELEM_READ requests. The state of
      a target element is maintained exclusively between ELEM_WRITE/ELEM_READ
      operations.
      
      There's a concern. If the counting semaphore is acquired for read lock
      in implementations of 'struct snd_kcontrol.put()' in each driver, this
      commit shall cause dead lock. As of v4.13-rc5, 'snd-mixer-oss.ko',
      'snd-emu10k1.ko' and 'snd-soc-sst-atom-hifi2-platform.ko' includes codes
      for read locks, but these are not in a call graph from
      'struct snd_kcontrol.put(). Therefore, this commit is safe.
      
      In current implementation, the same solution is applied for the other
      operations to element; e.g. ELEM_LOCK and ELEM_UNLOCK. There's another
      discussion about an overhead to maintain concurrent access to an element
      during operating the other elements on the same card instance, because the
      lock primitive is originally implemented to maintain a list of elements on
      the card instance. There's a substantial difference between
      per-element-list lock and per-element lock.
      
      Here, let me investigate another idea to add per-element lock to maintain
      the concurrent accesses with inquiry/change requests to an element. It's
      not so frequent for applications to operate members on elements, while
      adding a new lock primitive to structure increases memory footprint for
      all of element sets somehow. Experimentally, inquiry operation is more
      frequent than change operation and usage of counting semaphore for the
      inquiry operation brings no blocking to the other inquiry operations. Thus
      the overhead is not so critical for usual applications. For the above
      reasons, in this commit, the per-element lock is not introduced.
      Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
      Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
      5bbb1ab5
    • Takashi Sakamoto's avatar
      ALSA: control: code refactoring for ELEM_READ/ELEM_WRITE operations · becf9e5d
      Takashi Sakamoto authored
      ALSA control core handles ELEM_READ/ELEM_WRITE requests within lock
      acquisition of a counting semaphore. The lock is acquired in helper
      functions in the end of call path before calling implementations of each
      driver.
      
      ioctl(2) with SNDRV_CTL_ELEM_READ
      ...
      ->snd_ctl_ioctl()
        ->snd_ctl_elem_read_user()
          ->snd_ctl_elem_read()
            ->down_read(controls_rwsem)
            ->snd_ctl_find_id()
            ->struct snd_kcontrol.get()
            ->up_read(controls_rwsem)
      
      ioctl(2) with SNDRV_CTL_ELEM_WRITE
      ...
      ->snd_ctl_ioctl()
        ->snd_ctl_elem_write_user()
          ->snd_ctl_elem_write()
            ->down_read(controls_rwsem)
            ->snd_ctl_find_id()
            ->struct snd_kcontrol.put()
            ->up_read(controls_rwsem)
      
      This commit moves the lock acquisition to middle of the call graph to
      simplify the helper functions. As a result:
      
      ioctl(2) with SNDRV_CTL_ELEM_READ
      ...
      ->snd_ctl_ioctl()
        ->snd_ctl_elem_read_user()
          ->down_read(controls_rwsem)
          ->snd_ctl_elem_read()
            ->snd_ctl_find_id()
            ->struct snd_kcontrol.get()
          ->up_read(controls_rwsem)
      
      ioctl(2) with SNDRV_CTL_ELEM_WRITE
      ...
      ->snd_ctl_ioctl()
        ->snd_ctl_elem_write_user()
          ->down_read(controls_rwsem)
          ->snd_ctl_elem_write()
            ->snd_ctl_find_id()
            ->struct snd_kcontrol.put()
          ->up_read(controls_rwsem)
      Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
      Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
      becf9e5d
    • Takashi Sakamoto's avatar
      ALSA: control: queue events within locking of controls_rwsem for ELEM_WRITE operation · 7b42cfaf
      Takashi Sakamoto authored
      Any control event is queued by a call of snd_ctl_notify(). This function
      adds the event to each queue of opened file data corresponding to ALSA
      control character devices. This function acquired two types of lock; a
      counting semaphore for a list of the opened file data and a spinlock for
      card data opened by the file. Typically, this function is called after
      acquiring a counting semaphore for a list of elements in the card data.
      
      In current implementation of a handler for ELEM_WRITE request, the
      function is called after releasing the semaphore for a list of elements
      in the card data. This release is not necessarily needed.
      
      This commit removes the release to call the function within the critical
      section so that later commits are simple.
      Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
      Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
      7b42cfaf
  3. 19 Aug, 2017 13 commits
  4. 18 Aug, 2017 1 commit
    • Stephen Barber's avatar
      ALSA: usb-audio: don't retry snd_usb_ctl_msg after timeout · 5a9a8eca
      Stephen Barber authored
      A few calls to snd_usb_ctl_msg wrap the function in a retry loop. In
      the worst case, the timeout for snd_usb_ctl_msg is 5 seconds, which when
      retried 10 times (for example, if a device is removed) could cause a
      probe to hang for ~50 seconds.
      
      Example stack trace from 3.14 which triggered a hung task timeout:
      Call Trace:
       [<ffffffffa2c1f720>] ? inet6_set_link_af.part.35+0x12/0x12
       [<ffffffffa2c20309>] schedule+0x6e/0x70
       [<ffffffffa2c1f81c>] schedule_timeout+0xfc/0x13c
       [<ffffffffa2667bbc>] ? rcu_read_unlock_sched_notrace+0x17/0x17
       [<ffffffffa2c20d68>] __wait_for_common+0x153/0x190
       [<ffffffffa2c20d68>] ? __wait_for_common+0x153/0x190
       [<ffffffffa26890e5>] ? wake_up_state+0x12/0x12
       [<ffffffffa2c20e0e>] wait_for_completion_timeout+0x1d/0x1f
       [<ffffffffa2a07c70>] usb_start_wait_urb+0x93/0xf1
       [<ffffffffa2a07daf>] usb_control_msg+0xe1/0x11d
       [<ffffffffc02cd254>] snd_usb_ctl_msg+0x9c/0xf1 [snd_usb_audio]
       [<ffffffffc02ce191>] snd_usb_mixer_set_ctl_value+0x124/0xab1 [snd_usb_audio]
       [<ffffffffc02ce230>] snd_usb_mixer_set_ctl_value+0x1c3/0xab1 [snd_usb_audio]
       [<ffffffffc02ce58e>] snd_usb_mixer_set_ctl_value+0x521/0xab1 [snd_usb_audio]
       [<ffffffffc02cee88>] snd_usb_mixer_add_control+0x36a/0x1264 [snd_usb_audio]
       [<ffffffffc02cf323>] snd_usb_mixer_add_control+0x805/0x1264 [snd_usb_audio]
       [<ffffffffa2a06e11>] ? usb_free_urb+0x1a/0x1c
       [<ffffffffc02cfcf7>] snd_usb_mixer_add_control+0x11d9/0x1264 [snd_usb_audio]
       [<ffffffffc02d000f>] snd_usb_create_mixer+0xbc/0x286 [snd_usb_audio]
       [<ffffffffc02cac18>] 0xffffffffc02cac17
       [<ffffffffa2a0aaf1>] usb_probe_interface+0x17c/0x21c
       [<ffffffffa29a65bc>] driver_probe_device+0xae/0x1fa
       [<ffffffffa29a6767>] __device_attach_driver+0x5f/0x66
       [<ffffffffa29a6708>] ? driver_probe_device+0x1fa/0x1fa
       [<ffffffffa29a4a60>] bus_for_each_drv+0x87/0xaa
       [<ffffffffa29a688a>] __device_attach+0x9d/0x101
       [<ffffffffa29a6913>] device_initial_probe+0x13/0x15
       [<ffffffffa29a5ae6>] bus_probe_device+0x33/0x96
       [<ffffffffa29a3d19>] device_add+0x328/0x547
       [<ffffffffa2a09355>] usb_set_configuration+0x624/0x674
       [<ffffffffa2a11949>] generic_probe+0x45/0x77
       [<ffffffffa2a0a962>] usb_probe_device+0x2d/0x40
       [<ffffffffa29a65bc>] driver_probe_device+0xae/0x1fa
       [<ffffffffa29a6767>] __device_attach_driver+0x5f/0x66
       [<ffffffffa29a6708>] ? driver_probe_device+0x1fa/0x1fa
       [<ffffffffa29a4a60>] bus_for_each_drv+0x87/0xaa
       [<ffffffffa29a688a>] __device_attach+0x9d/0x101
       [<ffffffffa29a6913>] device_initial_probe+0x13/0x15
       [<ffffffffa29a5ae6>] bus_probe_device+0x33/0x96
       [<ffffffffa29a3d19>] device_add+0x328/0x547
       [<ffffffffa29030bc>] ? add_device_randomness+0x111/0x130
       [<ffffffffa2a00967>] usb_new_device+0x2a2/0x3c0
       [<ffffffffa2a02ddc>] hub_thread+0xa3d/0xeed
       [<ffffffffa2c2010d>] ? __schedule+0x41e/0x5ac
       [<ffffffffa26957ce>] ? finish_wait+0x62/0x62
       [<ffffffffa2a0239f>] ? usb_reset_device+0x16a/0x16a
       [<ffffffffa267b255>] kthread+0x108/0x110
       [<ffffffffa267b14d>] ? __kthread_parkme+0x67/0x67
       [<ffffffffa2c23b2c>] ret_from_fork+0x7c/0xb0
       [<ffffffffa267b14d>] ? __kthread_parkme+0x67/0x67
      Signed-off-by: default avatarStephen Barber <smbarber@chromium.org>
      Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
      5a9a8eca
  5. 17 Aug, 2017 22 commits