diff options
| -rw-r--r-- | drivers/block/mtip32xx/mtip32xx.c | 104 | ||||
| -rw-r--r-- | drivers/block/mtip32xx/mtip32xx.h | 1 |
2 files changed, 65 insertions, 40 deletions
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 9bc10e31a143..b74eab70c3d0 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
| @@ -87,6 +87,8 @@ static int mtip_major; | |||
| 87 | static DEFINE_SPINLOCK(rssd_index_lock); | 87 | static DEFINE_SPINLOCK(rssd_index_lock); |
| 88 | static DEFINE_IDA(rssd_index_ida); | 88 | static DEFINE_IDA(rssd_index_ida); |
| 89 | 89 | ||
| 90 | static int mtip_block_initialize(struct driver_data *dd); | ||
| 91 | |||
| 90 | #ifdef CONFIG_COMPAT | 92 | #ifdef CONFIG_COMPAT |
| 91 | struct mtip_compat_ide_task_request_s { | 93 | struct mtip_compat_ide_task_request_s { |
| 92 | __u8 io_ports[8]; | 94 | __u8 io_ports[8]; |
| @@ -1031,7 +1033,8 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) | |||
| 1031 | 1033 | ||
| 1032 | to = jiffies + msecs_to_jiffies(timeout); | 1034 | to = jiffies + msecs_to_jiffies(timeout); |
| 1033 | do { | 1035 | do { |
| 1034 | if (test_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags)) { | 1036 | if (test_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags) && |
| 1037 | test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) { | ||
| 1035 | msleep(20); | 1038 | msleep(20); |
| 1036 | continue; /* svc thd is actively issuing commands */ | 1039 | continue; /* svc thd is actively issuing commands */ |
| 1037 | } | 1040 | } |
| @@ -2410,6 +2413,7 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) | |||
| 2410 | "FTL rebuild complete (%d secs).\n", | 2413 | "FTL rebuild complete (%d secs).\n", |
| 2411 | jiffies_to_msecs(jiffies - start) / 1000); | 2414 | jiffies_to_msecs(jiffies - start) / 1000); |
| 2412 | dd->ftlrebuildflag = 0; | 2415 | dd->ftlrebuildflag = 0; |
| 2416 | mtip_block_initialize(dd); | ||
| 2413 | break; | 2417 | break; |
| 2414 | } | 2418 | } |
| 2415 | ssleep(10); | 2419 | ssleep(10); |
| @@ -2454,8 +2458,8 @@ static int mtip_service_thread(void *data) | |||
| 2454 | if (kthread_should_stop()) | 2458 | if (kthread_should_stop()) |
| 2455 | break; | 2459 | break; |
| 2456 | 2460 | ||
| 2461 | set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags); | ||
| 2457 | if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) { | 2462 | if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) { |
| 2458 | set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags); | ||
| 2459 | slot = 1; | 2463 | slot = 1; |
| 2460 | /* used to restrict the loop to one iteration */ | 2464 | /* used to restrict the loop to one iteration */ |
| 2461 | slot_start = num_cmd_slots; | 2465 | slot_start = num_cmd_slots; |
| @@ -2488,8 +2492,14 @@ static int mtip_service_thread(void *data) | |||
| 2488 | } | 2492 | } |
| 2489 | 2493 | ||
| 2490 | clear_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags); | 2494 | clear_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags); |
| 2491 | clear_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags); | 2495 | } else if (test_bit(MTIP_FLAG_REBUILD_BIT, &port->flags)) { |
| 2496 | mtip_ftl_rebuild_poll(dd); | ||
| 2497 | clear_bit(MTIP_FLAG_REBUILD_BIT, &port->flags); | ||
| 2492 | } | 2498 | } |
| 2499 | clear_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags); | ||
| 2500 | |||
| 2501 | if (test_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &port->flags)) | ||
| 2502 | break; | ||
| 2493 | } | 2503 | } |
| 2494 | return 0; | 2504 | return 0; |
| 2495 | } | 2505 | } |
| @@ -2658,12 +2668,13 @@ static int mtip_hw_init(struct driver_data *dd) | |||
| 2658 | rv = -EFAULT; | 2668 | rv = -EFAULT; |
| 2659 | goto out3; | 2669 | goto out3; |
| 2660 | } | 2670 | } |
| 2661 | mtip_dump_identify(dd->port); | ||
| 2662 | 2671 | ||
| 2663 | if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) == | 2672 | if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) == |
| 2664 | MTIP_FTL_REBUILD_MAGIC) { | 2673 | MTIP_FTL_REBUILD_MAGIC) { |
| 2665 | return mtip_ftl_rebuild_poll(dd); | 2674 | set_bit(MTIP_FLAG_REBUILD_BIT, &dd->port->flags); |
| 2675 | return MTIP_FTL_REBUILD_MAGIC; | ||
| 2666 | } | 2676 | } |
| 2677 | mtip_dump_identify(dd->port); | ||
| 2667 | return rv; | 2678 | return rv; |
| 2668 | 2679 | ||
| 2669 | out3: | 2680 | out3: |
| @@ -3095,40 +3106,24 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) | |||
| 3095 | */ | 3106 | */ |
| 3096 | static int mtip_block_initialize(struct driver_data *dd) | 3107 | static int mtip_block_initialize(struct driver_data *dd) |
| 3097 | { | 3108 | { |
| 3098 | int rv = 0; | 3109 | int rv = 0, wait_for_rebuild = 0; |
| 3099 | sector_t capacity; | 3110 | sector_t capacity; |
| 3100 | unsigned int index = 0; | 3111 | unsigned int index = 0; |
| 3101 | struct kobject *kobj; | 3112 | struct kobject *kobj; |
| 3102 | unsigned char thd_name[16]; | 3113 | unsigned char thd_name[16]; |
| 3103 | 3114 | ||
| 3115 | if (dd->disk) | ||
| 3116 | goto skip_create_disk; /* hw init done, before rebuild */ | ||
| 3117 | |||
| 3104 | /* Initialize the protocol layer. */ | 3118 | /* Initialize the protocol layer. */ |
| 3105 | rv = mtip_hw_init(dd); | 3119 | wait_for_rebuild = mtip_hw_init(dd); |
| 3106 | if (rv < 0) { | 3120 | if (wait_for_rebuild < 0) { |
| 3107 | dev_err(&dd->pdev->dev, | 3121 | dev_err(&dd->pdev->dev, |
| 3108 | "Protocol layer initialization failed\n"); | 3122 | "Protocol layer initialization failed\n"); |
| 3109 | rv = -EINVAL; | 3123 | rv = -EINVAL; |
| 3110 | goto protocol_init_error; | 3124 | goto protocol_init_error; |
| 3111 | } | 3125 | } |
| 3112 | 3126 | ||
| 3113 | /* Allocate the request queue. */ | ||
| 3114 | dd->queue = blk_alloc_queue(GFP_KERNEL); | ||
| 3115 | if (dd->queue == NULL) { | ||
| 3116 | dev_err(&dd->pdev->dev, | ||
| 3117 | "Unable to allocate request queue\n"); | ||
| 3118 | rv = -ENOMEM; | ||
| 3119 | goto block_queue_alloc_init_error; | ||
| 3120 | } | ||
| 3121 | |||
| 3122 | /* Attach our request function to the request queue. */ | ||
| 3123 | blk_queue_make_request(dd->queue, mtip_make_request); | ||
| 3124 | |||
| 3125 | /* Set device limits. */ | ||
| 3126 | set_bit(QUEUE_FLAG_NONROT, &dd->queue->queue_flags); | ||
| 3127 | blk_queue_max_segments(dd->queue, MTIP_MAX_SG); | ||
| 3128 | blk_queue_physical_block_size(dd->queue, 4096); | ||
| 3129 | blk_queue_io_min(dd->queue, 4096); | ||
| 3130 | blk_queue_flush(dd->queue, 0); | ||
| 3131 | |||
| 3132 | dd->disk = alloc_disk(MTIP_MAX_MINORS); | 3127 | dd->disk = alloc_disk(MTIP_MAX_MINORS); |
| 3133 | if (dd->disk == NULL) { | 3128 | if (dd->disk == NULL) { |
| 3134 | dev_err(&dd->pdev->dev, | 3129 | dev_err(&dd->pdev->dev, |
| @@ -3161,11 +3156,39 @@ static int mtip_block_initialize(struct driver_data *dd) | |||
| 3161 | dd->disk->major = dd->major; | 3156 | dd->disk->major = dd->major; |
| 3162 | dd->disk->first_minor = dd->instance * MTIP_MAX_MINORS; | 3157 | dd->disk->first_minor = dd->instance * MTIP_MAX_MINORS; |
| 3163 | dd->disk->fops = &mtip_block_ops; | 3158 | dd->disk->fops = &mtip_block_ops; |
| 3164 | dd->disk->queue = dd->queue; | ||
| 3165 | dd->disk->private_data = dd; | 3159 | dd->disk->private_data = dd; |
| 3166 | dd->queue->queuedata = dd; | ||
| 3167 | dd->index = index; | 3160 | dd->index = index; |
| 3168 | 3161 | ||
| 3162 | /* | ||
| 3163 | * if rebuild pending, start the service thread, and delay the block | ||
| 3164 | * queue creation and add_disk() | ||
| 3165 | */ | ||
| 3166 | if (wait_for_rebuild == MTIP_FTL_REBUILD_MAGIC) | ||
| 3167 | goto start_service_thread; | ||
| 3168 | |||
| 3169 | skip_create_disk: | ||
| 3170 | /* Allocate the request queue. */ | ||
| 3171 | dd->queue = blk_alloc_queue(GFP_KERNEL); | ||
| 3172 | if (dd->queue == NULL) { | ||
| 3173 | dev_err(&dd->pdev->dev, | ||
| 3174 | "Unable to allocate request queue\n"); | ||
| 3175 | rv = -ENOMEM; | ||
| 3176 | goto block_queue_alloc_init_error; | ||
| 3177 | } | ||
| 3178 | |||
| 3179 | /* Attach our request function to the request queue. */ | ||
| 3180 | blk_queue_make_request(dd->queue, mtip_make_request); | ||
| 3181 | |||
| 3182 | dd->disk->queue = dd->queue; | ||
| 3183 | dd->queue->queuedata = dd; | ||
| 3184 | |||
| 3185 | /* Set device limits. */ | ||
| 3186 | set_bit(QUEUE_FLAG_NONROT, &dd->queue->queue_flags); | ||
| 3187 | blk_queue_max_segments(dd->queue, MTIP_MAX_SG); | ||
| 3188 | blk_queue_physical_block_size(dd->queue, 4096); | ||
| 3189 | blk_queue_io_min(dd->queue, 4096); | ||
| 3190 | blk_queue_flush(dd->queue, 0); | ||
| 3191 | |||
| 3169 | /* Set the capacity of the device in 512 byte sectors. */ | 3192 | /* Set the capacity of the device in 512 byte sectors. */ |
| 3170 | if (!(mtip_hw_get_capacity(dd, &capacity))) { | 3193 | if (!(mtip_hw_get_capacity(dd, &capacity))) { |
| 3171 | dev_warn(&dd->pdev->dev, | 3194 | dev_warn(&dd->pdev->dev, |
| @@ -3188,6 +3211,10 @@ static int mtip_block_initialize(struct driver_data *dd) | |||
| 3188 | kobject_put(kobj); | 3211 | kobject_put(kobj); |
| 3189 | } | 3212 | } |
| 3190 | 3213 | ||
| 3214 | if (dd->mtip_svc_handler) | ||
| 3215 | return rv; /* service thread created for handling rebuild */ | ||
| 3216 | |||
| 3217 | start_service_thread: | ||
| 3191 | sprintf(thd_name, "mtip_svc_thd_%02d", index); | 3218 | sprintf(thd_name, "mtip_svc_thd_%02d", index); |
| 3192 | 3219 | ||
| 3193 | dd->mtip_svc_handler = kthread_run(mtip_service_thread, | 3220 | dd->mtip_svc_handler = kthread_run(mtip_service_thread, |
| @@ -3197,18 +3224,19 @@ static int mtip_block_initialize(struct driver_data *dd) | |||
| 3197 | printk(KERN_ERR "mtip32xx: service thread failed to start\n"); | 3224 | printk(KERN_ERR "mtip32xx: service thread failed to start\n"); |
| 3198 | dd->mtip_svc_handler = NULL; | 3225 | dd->mtip_svc_handler = NULL; |
| 3199 | rv = -EFAULT; | 3226 | rv = -EFAULT; |
| 3200 | goto read_capacity_error; | 3227 | goto kthread_run_error; |
| 3201 | } | 3228 | } |
| 3202 | 3229 | ||
| 3203 | return rv; | 3230 | return rv; |
| 3204 | 3231 | ||
| 3205 | read_capacity_error: | 3232 | kthread_run_error: |
| 3206 | /* | 3233 | /* Delete our gendisk. This also removes the device from /dev */ |
| 3207 | * Delete our gendisk structure. This also removes the device | ||
| 3208 | * from /dev | ||
| 3209 | */ | ||
| 3210 | del_gendisk(dd->disk); | 3234 | del_gendisk(dd->disk); |
| 3211 | 3235 | ||
| 3236 | read_capacity_error: | ||
| 3237 | blk_cleanup_queue(dd->queue); | ||
| 3238 | |||
| 3239 | block_queue_alloc_init_error: | ||
| 3212 | disk_index_error: | 3240 | disk_index_error: |
| 3213 | spin_lock(&rssd_index_lock); | 3241 | spin_lock(&rssd_index_lock); |
| 3214 | ida_remove(&rssd_index_ida, index); | 3242 | ida_remove(&rssd_index_ida, index); |
| @@ -3218,11 +3246,7 @@ ida_get_error: | |||
| 3218 | put_disk(dd->disk); | 3246 | put_disk(dd->disk); |
| 3219 | 3247 | ||
| 3220 | alloc_disk_error: | 3248 | alloc_disk_error: |
| 3221 | blk_cleanup_queue(dd->queue); | 3249 | mtip_hw_exit(dd); /* De-initialize the protocol layer. */ |
| 3222 | |||
| 3223 | block_queue_alloc_init_error: | ||
| 3224 | /* De-initialize the protocol layer. */ | ||
| 3225 | mtip_hw_exit(dd); | ||
| 3226 | 3250 | ||
| 3227 | protocol_init_error: | 3251 | protocol_init_error: |
| 3228 | return rv; | 3252 | return rv; |
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 933192abe178..723d7c4946dc 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h | |||
| @@ -121,6 +121,7 @@ | |||
| 121 | #define MTIP_FLAG_EH_ACTIVE_BIT 1 | 121 | #define MTIP_FLAG_EH_ACTIVE_BIT 1 |
| 122 | #define MTIP_FLAG_SVC_THD_ACTIVE_BIT 2 | 122 | #define MTIP_FLAG_SVC_THD_ACTIVE_BIT 2 |
| 123 | #define MTIP_FLAG_ISSUE_CMDS_BIT 4 | 123 | #define MTIP_FLAG_ISSUE_CMDS_BIT 4 |
| 124 | #define MTIP_FLAG_REBUILD_BIT 5 | ||
| 124 | #define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT 8 | 125 | #define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT 8 |
| 125 | 126 | ||
| 126 | /* Register Frame Information Structure (FIS), host to device. */ | 127 | /* Register Frame Information Structure (FIS), host to device. */ |
