summaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
authorAsai Thambi S P <asamymuthupa@micron.com>2012-01-04 22:01:32 +0100
committerJens Axboe <axboe@kernel.dk>2012-01-04 22:01:32 +0100
commit62ee8c13e26cffe6483630f59932c3e936dfb586 (patch)
tree7f92cc63e2413b19466255133f1198319dd4ae4f /drivers/block
parent3e54a3d1b83220d748f1a27c8999634be7a83949 (diff)
downloadlinux-3.10-62ee8c13e26cffe6483630f59932c3e936dfb586.tar.gz
linux-3.10-62ee8c13e26cffe6483630f59932c3e936dfb586.tar.bz2
linux-3.10-62ee8c13e26cffe6483630f59932c3e936dfb586.zip
mtip32xx: do rebuild monitoring asynchronously
Earlier, rebuild monitoring was done in the context of probe. Now the service thread takes the responsibility of rebuild monitoring, and probe returns good status. Signed-off-by: Asai Thambi S P <asamymuthupa@micron.com> Signed-off-by: Sam Bradshaw <sbradshaw@micron.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c104
-rw-r--r--drivers/block/mtip32xx/mtip32xx.h1
2 files changed, 65 insertions, 40 deletions
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 9bc10e31a14..b74eab70c3d 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -87,6 +87,8 @@ static int mtip_major;
static DEFINE_SPINLOCK(rssd_index_lock);
static DEFINE_IDA(rssd_index_ida);
+static int mtip_block_initialize(struct driver_data *dd);
+
#ifdef CONFIG_COMPAT
struct mtip_compat_ide_task_request_s {
__u8 io_ports[8];
@@ -1031,7 +1033,8 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
to = jiffies + msecs_to_jiffies(timeout);
do {
- if (test_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags)) {
+ if (test_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags) &&
+ test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
msleep(20);
continue; /* svc thd is actively issuing commands */
}
@@ -2410,6 +2413,7 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
"FTL rebuild complete (%d secs).\n",
jiffies_to_msecs(jiffies - start) / 1000);
dd->ftlrebuildflag = 0;
+ mtip_block_initialize(dd);
break;
}
ssleep(10);
@@ -2454,8 +2458,8 @@ static int mtip_service_thread(void *data)
if (kthread_should_stop())
break;
+ set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
- set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
slot = 1;
/* used to restrict the loop to one iteration */
slot_start = num_cmd_slots;
@@ -2488,8 +2492,14 @@ static int mtip_service_thread(void *data)
}
clear_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags);
- clear_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
+ } else if (test_bit(MTIP_FLAG_REBUILD_BIT, &port->flags)) {
+ mtip_ftl_rebuild_poll(dd);
+ clear_bit(MTIP_FLAG_REBUILD_BIT, &port->flags);
}
+ clear_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
+
+ if (test_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &port->flags))
+ break;
}
return 0;
}
@@ -2658,12 +2668,13 @@ static int mtip_hw_init(struct driver_data *dd)
rv = -EFAULT;
goto out3;
}
- mtip_dump_identify(dd->port);
if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) ==
MTIP_FTL_REBUILD_MAGIC) {
- return mtip_ftl_rebuild_poll(dd);
+ set_bit(MTIP_FLAG_REBUILD_BIT, &dd->port->flags);
+ return MTIP_FTL_REBUILD_MAGIC;
}
+ mtip_dump_identify(dd->port);
return rv;
out3:
@@ -3095,40 +3106,24 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
*/
static int mtip_block_initialize(struct driver_data *dd)
{
- int rv = 0;
+ int rv = 0, wait_for_rebuild = 0;
sector_t capacity;
unsigned int index = 0;
struct kobject *kobj;
unsigned char thd_name[16];
+ if (dd->disk)
+ goto skip_create_disk; /* hw init done, before rebuild */
+
/* Initialize the protocol layer. */
- rv = mtip_hw_init(dd);
- if (rv < 0) {
+ wait_for_rebuild = mtip_hw_init(dd);
+ if (wait_for_rebuild < 0) {
dev_err(&dd->pdev->dev,
"Protocol layer initialization failed\n");
rv = -EINVAL;
goto protocol_init_error;
}
- /* Allocate the request queue. */
- dd->queue = blk_alloc_queue(GFP_KERNEL);
- if (dd->queue == NULL) {
- dev_err(&dd->pdev->dev,
- "Unable to allocate request queue\n");
- rv = -ENOMEM;
- goto block_queue_alloc_init_error;
- }
-
- /* Attach our request function to the request queue. */
- blk_queue_make_request(dd->queue, mtip_make_request);
-
- /* Set device limits. */
- set_bit(QUEUE_FLAG_NONROT, &dd->queue->queue_flags);
- blk_queue_max_segments(dd->queue, MTIP_MAX_SG);
- blk_queue_physical_block_size(dd->queue, 4096);
- blk_queue_io_min(dd->queue, 4096);
- blk_queue_flush(dd->queue, 0);
-
dd->disk = alloc_disk(MTIP_MAX_MINORS);
if (dd->disk == NULL) {
dev_err(&dd->pdev->dev,
@@ -3161,11 +3156,39 @@ static int mtip_block_initialize(struct driver_data *dd)
dd->disk->major = dd->major;
dd->disk->first_minor = dd->instance * MTIP_MAX_MINORS;
dd->disk->fops = &mtip_block_ops;
- dd->disk->queue = dd->queue;
dd->disk->private_data = dd;
- dd->queue->queuedata = dd;
dd->index = index;
+ /*
+ * if rebuild pending, start the service thread, and delay the block
+ * queue creation and add_disk()
+ */
+ if (wait_for_rebuild == MTIP_FTL_REBUILD_MAGIC)
+ goto start_service_thread;
+
+skip_create_disk:
+ /* Allocate the request queue. */
+ dd->queue = blk_alloc_queue(GFP_KERNEL);
+ if (dd->queue == NULL) {
+ dev_err(&dd->pdev->dev,
+ "Unable to allocate request queue\n");
+ rv = -ENOMEM;
+ goto block_queue_alloc_init_error;
+ }
+
+ /* Attach our request function to the request queue. */
+ blk_queue_make_request(dd->queue, mtip_make_request);
+
+ dd->disk->queue = dd->queue;
+ dd->queue->queuedata = dd;
+
+ /* Set device limits. */
+ set_bit(QUEUE_FLAG_NONROT, &dd->queue->queue_flags);
+ blk_queue_max_segments(dd->queue, MTIP_MAX_SG);
+ blk_queue_physical_block_size(dd->queue, 4096);
+ blk_queue_io_min(dd->queue, 4096);
+ blk_queue_flush(dd->queue, 0);
+
/* Set the capacity of the device in 512 byte sectors. */
if (!(mtip_hw_get_capacity(dd, &capacity))) {
dev_warn(&dd->pdev->dev,
@@ -3188,6 +3211,10 @@ static int mtip_block_initialize(struct driver_data *dd)
kobject_put(kobj);
}
+ if (dd->mtip_svc_handler)
+ return rv; /* service thread created for handling rebuild */
+
+start_service_thread:
sprintf(thd_name, "mtip_svc_thd_%02d", index);
dd->mtip_svc_handler = kthread_run(mtip_service_thread,
@@ -3197,18 +3224,19 @@ static int mtip_block_initialize(struct driver_data *dd)
printk(KERN_ERR "mtip32xx: service thread failed to start\n");
dd->mtip_svc_handler = NULL;
rv = -EFAULT;
- goto read_capacity_error;
+ goto kthread_run_error;
}
return rv;
-read_capacity_error:
- /*
- * Delete our gendisk structure. This also removes the device
- * from /dev
- */
+kthread_run_error:
+ /* Delete our gendisk. This also removes the device from /dev */
del_gendisk(dd->disk);
+read_capacity_error:
+ blk_cleanup_queue(dd->queue);
+
+block_queue_alloc_init_error:
disk_index_error:
spin_lock(&rssd_index_lock);
ida_remove(&rssd_index_ida, index);
@@ -3218,11 +3246,7 @@ ida_get_error:
put_disk(dd->disk);
alloc_disk_error:
- blk_cleanup_queue(dd->queue);
-
-block_queue_alloc_init_error:
- /* De-initialize the protocol layer. */
- mtip_hw_exit(dd);
+ mtip_hw_exit(dd); /* De-initialize the protocol layer. */
protocol_init_error:
return rv;
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index 933192abe17..723d7c4946d 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -121,6 +121,7 @@
#define MTIP_FLAG_EH_ACTIVE_BIT 1
#define MTIP_FLAG_SVC_THD_ACTIVE_BIT 2
#define MTIP_FLAG_ISSUE_CMDS_BIT 4
+#define MTIP_FLAG_REBUILD_BIT 5
#define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT 8
/* Register Frame Information Structure (FIS), host to device. */