summaryrefslogtreecommitdiff
path: root/drivers/scsi/ufs
diff options
context:
space:
mode:
authorGilad Broner <gbroner@codeaurora.org>2015-03-31 16:16:58 +0300
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 10:59:30 -0700
commit2ad7d0f046578eda81aae3ef496cafe39f2a893d (patch)
tree09f9307c75d6727645fb2bb27616ae58a9a26435 /drivers/scsi/ufs
parent877d77d0b9fb67abf4d061143ed351b9bcf8f3d7 (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.c10
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 &&