• [PATCH v3 12/19] thunderbolt: Use spinlock in ring serialization

    From Mika Westerberg@21:1/5 to All on Mon Oct 2 12:50:02 2017
    This makes it possible to enqueue frames also from atomic context which
    is needed for example, when networking packets are sent over a
    Thunderbolt cable.

    Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
    Reviewed-by: Michael Jamet <michael.jamet@intel.com>
    Reviewed-by: Yehezkel Bernat <yehezkel.bernat@intel.com>
    Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    ---
    drivers/thunderbolt/nhi.c | 26 ++++++++++++++------------
    include/linux/thunderbolt.h | 2 +-
    2 files changed, 15 insertions(+), 13 deletions(-)

    diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
    index e0a47f7581cb..7d1891ec3c47 100644
    --- a/drivers/thunderbolt/nhi.c
    +++ b/drivers/thunderbolt/nhi.c
    @@ -212,8 +212,10 @@ static void ring_work(struct work_struct *work)
    struct tb_ring *ring = container_of(work, typeof(*ring), work);
    struct ring_frame *frame;
    bool canceled = false;
    + unsigned long flags;
    LIST_HEAD(done);
    - mutex_lock(&ring->lock);
    +
    + spin_lock_irqsave(&ring->lock, flags);

    if (!ring->running) {
    /* Move all frames to done and mark them as canceled. */
    @@ -241,7 +243,8 @@ static void ring_work(struct work_struct *work)
    ring_write_descriptors(ring);

    invoke_callback:
    - mutex_unlock(&ring->lock); /* allow callbacks to schedule new work */
    + /* allow callbacks to schedule new work */
    + spin_unlock_irqrestore(&ring->lock, flags);