• Mikulas Patocka's avatar
    udlfb: fix semaphore value leak · 9d0aa601
    Mikulas Patocka authored
    I observed that the performance of the udl fb driver degrades over time.
    On a freshly booted machine, it takes 6 seconds to do "ls -la /usr/bin";
    after some time of use, the same operation takes 14 seconds.
    
    The reason is that the value of "limit_sem" decays over time.
    
    The udl driver uses a semaphore "limit_set" to specify how many free urbs
    are there on dlfb->urbs.list. If the count is zero, the "down" operation
    will sleep until some urbs are added to the freelist.
    
    In order to avoid some hypothetical deadlock, the driver will not call
    "up" immediately, but it will offload it to a workqueue. The problem is
    that if we call "schedule_delayed_work" on the same work item multiple
    times, the work item may only be executed once.
    
    This is happening:
    * some urb completes
    * dlfb_urb_completion adds it to the free list
    * dlfb_urb_completion calls schedule_delayed_work to schedule the function
      dlfb_release_urb_work to increase the semaphore count
    * as the urb is on the free list, some other task grabs it and submits it
    * the submitted urb completes, dlfb_urb_completion is called again
    * dlfb_urb_completion calls schedule_delayed_work, but the work is already
      scheduled, so it does nothing
    * finally, dlfb_release_urb_work is called, it increases the semaphore
      count by 1, although it should increase it by 2
    
    So, the semaphore count is decreasing over time, and this causes gradual
    performance degradation.
    
    Note that in the current kernel, the "up" function may be called from
    interrupt and it may race with the "down" function called by another
    thread, so we don't have to offload the call of "up" to a workqueue at
    all. This patch removes the workqueue code. The patch also changes
    "down_interruptible" to "down" in dlfb_free_urb_list, so that we will
    clean up the driver properly even if a signal arrives.
    
    With this patch, the performance of udlfb no longer degrades.
    Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
    Cc: stable@vger.kernel.org
    [b.zolnierkie: fix immediatelly -> immediately typo]
    Signed-off-by: default avatarBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
    9d0aa601
udlfb.h 2.74 KB