scsi: add support for a blk-mq based I/O path.
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / hosts.c
index 0632eee826201c7131845350f2ab18d3d830a759..6de80e3528719446e04355037453d0dad911feb5 100644 (file)
@@ -213,9 +213,24 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
                goto fail;
        }
 
+       if (shost_use_blk_mq(shost)) {
+               error = scsi_mq_setup_tags(shost);
+               if (error)
+                       goto fail;
+       }
+
+       /*
+        * Note that we allocate the freelist even for the MQ case for now,
+        * as we need a command set aside for scsi_reset_provider.  Having
+        * the full host freelist and one command available for that is a
+        * little heavy-handed, but avoids introducing a special allocator
+        * just for this.  Eventually the structure of scsi_reset_provider
+        * will need a major overhaul.
+        */
        error = scsi_setup_command_freelist(shost);
        if (error)
-               goto fail;
+               goto out_destroy_tags;
+
 
        if (!shost->shost_gendev.parent)
                shost->shost_gendev.parent = dev ? dev : &platform_bus;
@@ -226,7 +241,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
 
        error = device_add(&shost->shost_gendev);
        if (error)
-               goto out;
+               goto out_destroy_freelist;
 
        pm_runtime_set_active(&shost->shost_gendev);
        pm_runtime_enable(&shost->shost_gendev);
@@ -279,8 +294,11 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
        device_del(&shost->shost_dev);
  out_del_gendev:
        device_del(&shost->shost_gendev);
- out:
+ out_destroy_freelist:
        scsi_destroy_command_freelist(shost);
+ out_destroy_tags:
+       if (shost_use_blk_mq(shost))
+               scsi_mq_destroy_tags(shost);
  fail:
        return error;
 }
@@ -309,8 +327,13 @@ static void scsi_host_dev_release(struct device *dev)
        }
 
        scsi_destroy_command_freelist(shost);
-       if (shost->bqt)
-               blk_free_tags(shost->bqt);
+       if (shost_use_blk_mq(shost)) {
+               if (shost->tag_set.tags)
+                       scsi_mq_destroy_tags(shost);
+       } else {
+               if (shost->bqt)
+                       blk_free_tags(shost->bqt);
+       }
 
        kfree(shost->shost_data);
 
@@ -436,6 +459,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        else
                shost->dma_boundary = 0xffffffff;
 
+       shost->use_blk_mq = scsi_use_blk_mq && !shost->hostt->disable_blk_mq;
+
        device_initialize(&shost->shost_gendev);
        dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
        shost->shost_gendev.bus = &scsi_bus_type;