scsi: core: Complain if scsi_target_block() fails
[linux-2.6-block.git] / drivers / scsi / scsi_lib.c
index 9381171c2fc02741df68aa59b9e8a024f608356a..d47d637e6be256c8fa0d0309398c5c212d7ee258 100644 (file)
@@ -1666,10 +1666,11 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
                blk_mq_start_request(req);
        }
 
+       cmd->flags &= SCMD_PRESERVED_FLAGS;
        if (sdev->simple_tags)
                cmd->flags |= SCMD_TAGGED;
-       else
-               cmd->flags &= ~SCMD_TAGGED;
+       if (bd->last)
+               cmd->flags |= SCMD_LAST;
 
        scsi_init_cmd_errh(cmd);
        cmd->scsi_done = scsi_mq_done;
@@ -1807,10 +1808,37 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
 }
 EXPORT_SYMBOL_GPL(__scsi_init_queue);
 
+static const struct blk_mq_ops scsi_mq_ops_no_commit = {
+       .get_budget     = scsi_mq_get_budget,
+       .put_budget     = scsi_mq_put_budget,
+       .queue_rq       = scsi_queue_rq,
+       .complete       = scsi_softirq_done,
+       .timeout        = scsi_timeout,
+#ifdef CONFIG_BLK_DEBUG_FS
+       .show_rq        = scsi_show_rq,
+#endif
+       .init_request   = scsi_mq_init_request,
+       .exit_request   = scsi_mq_exit_request,
+       .initialize_rq_fn = scsi_initialize_rq,
+       .busy           = scsi_mq_lld_busy,
+       .map_queues     = scsi_map_queues,
+};
+
+
+static void scsi_commit_rqs(struct blk_mq_hw_ctx *hctx)
+{
+       struct request_queue *q = hctx->queue;
+       struct scsi_device *sdev = q->queuedata;
+       struct Scsi_Host *shost = sdev->host;
+
+       shost->hostt->commit_rqs(shost, hctx->queue_num);
+}
+
 static const struct blk_mq_ops scsi_mq_ops = {
        .get_budget     = scsi_mq_get_budget,
        .put_budget     = scsi_mq_put_budget,
        .queue_rq       = scsi_queue_rq,
+       .commit_rqs     = scsi_commit_rqs,
        .complete       = scsi_softirq_done,
        .timeout        = scsi_timeout,
 #ifdef CONFIG_BLK_DEBUG_FS
@@ -1846,7 +1874,10 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)
                        sizeof(struct scatterlist) * SCSI_INLINE_PROT_SG_CNT;
 
        memset(&shost->tag_set, 0, sizeof(shost->tag_set));
-       shost->tag_set.ops = &scsi_mq_ops;
+       if (shost->hostt->commit_rqs)
+               shost->tag_set.ops = &scsi_mq_ops;
+       else
+               shost->tag_set.ops = &scsi_mq_ops_no_commit;
        shost->tag_set.nr_hw_queues = shost->nr_hw_queues ? : 1;
        shost->tag_set.queue_depth = shost->can_queue;
        shost->tag_set.cmd_size = cmd_size;
@@ -2676,6 +2707,14 @@ void scsi_start_queue(struct scsi_device *sdev)
 int scsi_internal_device_unblock_nowait(struct scsi_device *sdev,
                                        enum scsi_device_state new_state)
 {
+       switch (new_state) {
+       case SDEV_RUNNING:
+       case SDEV_TRANSPORT_OFFLINE:
+               break;
+       default:
+               return -EINVAL;
+       }
+
        /*
         * Try to transition the scsi device to SDEV_RUNNING or one of the
         * offlined states and goose the device queue if successful.
@@ -2733,7 +2772,12 @@ static int scsi_internal_device_unblock(struct scsi_device *sdev,
 static void
 device_block(struct scsi_device *sdev, void *data)
 {
-       scsi_internal_device_block(sdev);
+       int ret;
+
+       ret = scsi_internal_device_block(sdev);
+
+       WARN_ONCE(ret, "scsi_internal_device_block(%s) failed: ret = %d\n",
+                 dev_name(&sdev->sdev_gendev), ret);
 }
 
 static int