aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-04-28 12:38:32 +0900
committerJens Axboe <jens.axboe@oracle.com>2009-04-28 07:36:56 +0200
commitac2ff946a53e7bd0ae98f4e5d1d6c1b1dced82e5 (patch)
treeab50d2e1bcf5c76bb9e018839d77ff531e7e4c83
parentce8a7424d23a36f043d0de8484f888971c831119 (diff)
mg_disk: fix locking
IRQ and timeout handlers call functions which expect locked queue lock without locking it. Fix it. While at it, convert 0s used as null pointer constant to NULLs. [ Impact: fix locking, cleanup ] Signed-off-by: Tejun Heo <tj@kernel.org> Cc: unsik Kim <donari75@gmail.com>
-rw-r--r--drivers/block/mg_disk.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c
index fb39d9aa3cd..d3e72ad08db 100644
--- a/drivers/block/mg_disk.c
+++ b/drivers/block/mg_disk.c
@@ -160,11 +160,16 @@ static irqreturn_t mg_irq(int irq, void *dev_id)
struct mg_host *host = dev_id;
void (*handler)(struct mg_host *) = host->mg_do_intr;
- host->mg_do_intr = 0;
+ spin_lock(&host->lock);
+
+ host->mg_do_intr = NULL;
del_timer(&host->timer);
if (!handler)
handler = mg_unexpected_intr;
handler(host);
+
+ spin_unlock(&host->lock);
+
return IRQ_HANDLED;
}
@@ -319,7 +324,7 @@ static void mg_read(struct request *req)
remains = req->nr_sectors;
- if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_RD, 0) !=
+ if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_RD, NULL) !=
MG_ERR_NONE)
mg_bad_rw_intr(host);
@@ -363,7 +368,7 @@ static void mg_write(struct request *req)
remains = req->nr_sectors;
- if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_WR, 0) !=
+ if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_WR, NULL) !=
MG_ERR_NONE) {
mg_bad_rw_intr(host);
return;
@@ -521,9 +526,11 @@ void mg_times_out(unsigned long data)
char *name;
struct request *req;
+ spin_lock_irq(&host->lock);
+
req = elv_next_request(host->breq);
if (!req)
- return;
+ goto out_unlock;
host->mg_do_intr = NULL;
@@ -534,6 +541,8 @@ void mg_times_out(unsigned long data)
mg_bad_rw_intr(host);
mg_request(host->breq);
+out_unlock:
+ spin_unlock_irq(&host->lock);
}
static void mg_request_poll(struct request_queue *q)