diff options
author | Gilad Broner <gbroner@codeaurora.org> | 2015-03-31 16:16:58 +0300 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 10:59:30 -0700 |
commit | 2ad7d0f046578eda81aae3ef496cafe39f2a893d (patch) | |
tree | 09f9307c75d6727645fb2bb27616ae58a9a26435 /drivers/scsi/ufs | |
parent | 877d77d0b9fb67abf4d061143ed351b9bcf8f3d7 (diff) |
scsi: ufs: fix spinlock recursion
spin_lock_irq() / spin_unlock_irq() is used so interrupts are
enabled after unlocking the spinlock. However, it is not guaranteed
they were enabled before.
This change uses the proper irqsave / irqrestore variants instead.
Without it, a spinlock recursion on the scsi request completion path
is possible if completion interrupt occurs.
Change-Id: If5a001f195466f85e50df6ce23fd1e10851c5e2b
Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
Diffstat (limited to 'drivers/scsi/ufs')
-rw-r--r-- | drivers/scsi/ufs/ufs_test.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/scsi/ufs/ufs_test.c b/drivers/scsi/ufs/ufs_test.c index 493ce2425995..8953722e8dad 100644 --- a/drivers/scsi/ufs/ufs_test.c +++ b/drivers/scsi/ufs/ufs_test.c @@ -677,16 +677,17 @@ static void scenario_free_end_io_fn(struct request *rq, int err) { struct test_request *test_rq; struct test_iosched *test_iosched = rq->q->elevator->elevator_data; + unsigned long flags; BUG_ON(!rq); test_rq = (struct test_request *)rq->elv.priv[0]; BUG_ON(!test_rq); - spin_lock_irq(&test_iosched->lock); + spin_lock_irqsave(&test_iosched->lock, flags); test_iosched->dispatched_count--; list_del_init(&test_rq->queuelist); __blk_put_request(test_iosched->req_q, test_rq->rq); - spin_unlock_irq(&test_iosched->lock); + spin_unlock_irqrestore(&test_iosched->lock, flags); test_iosched_free_test_req_data_buffer(test_rq); kfree(test_rq); @@ -956,6 +957,7 @@ static void long_test_free_end_io_fn(struct request *rq, int err) struct test_request *test_rq; struct test_iosched *test_iosched = rq->q->elevator->elevator_data; struct ufs_test_data *utd = test_iosched->blk_dev_test_data; + unsigned long flags; if (!rq) { pr_err("%s: error: NULL request", __func__); @@ -966,11 +968,11 @@ static void long_test_free_end_io_fn(struct request *rq, int err) BUG_ON(!test_rq); - spin_lock_irq(&test_iosched->lock); + spin_lock_irqsave(&test_iosched->lock, flags); test_iosched->dispatched_count--; list_del_init(&test_rq->queuelist); __blk_put_request(test_iosched->req_q, test_rq->rq); - spin_unlock_irq(&test_iosched->lock); + spin_unlock_irqrestore(&test_iosched->lock, flags); if (utd->test_stage == UFS_TEST_LONG_SEQUENTIAL_MIXED_STAGE2 && rq_data_dir(rq) == READ && |