]> git.hungrycats.org Git - linux/commitdiff
[PATCH] add per scsi-host workqueues for defered processing
authorJames Smart <james.smart@emulex.com>
Tue, 15 Mar 2005 11:58:52 +0000 (05:58 -0600)
committerJames Bottomley <jejb@titanic.il.steeleye.com>
Tue, 15 Mar 2005 11:58:52 +0000 (05:58 -0600)
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/hosts.c
include/scsi/scsi_host.h
include/scsi/scsi_transport.h

index fb9d659f3c88b1e274de66eb5564c302ddaf5e51..b594def19aba35f1705fa795090b4efce7bd8e59 100644 (file)
@@ -129,6 +129,15 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
                                         GFP_KERNEL)) == NULL)
                goto out_del_classdev;
 
+       if (shost->transportt->create_work_queue) {
+               snprintf(shost->work_q_name, KOBJ_NAME_LEN, "scsi_wq_%d",
+                       shost->host_no);
+               shost->work_q = create_singlethread_workqueue(
+                                       shost->work_q_name);
+               if (!shost->work_q)
+                       goto out_free_shost_data;
+       }
+
        error = scsi_sysfs_add_host(shost);
        if (error)
                goto out_destroy_host;
@@ -137,6 +146,10 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
        return error;
 
  out_destroy_host:
+       if (shost->work_q)
+               destroy_workqueue(shost->work_q);
+ out_free_shost_data:
+       kfree(shost->shost_data);
  out_del_classdev:
        class_device_del(&shost->shost_classdev);
  out_del_gendev:
@@ -160,6 +173,9 @@ static void scsi_host_dev_release(struct device *dev)
                shost->eh_notify = NULL;
        }
 
+       if (shost->work_q)
+               destroy_workqueue(shost->work_q);
+
        scsi_proc_hostdir_rm(shost->hostt);
        scsi_destroy_command_freelist(shost);
        kfree(shost->shost_data);
@@ -403,3 +419,27 @@ int scsi_is_host_device(const struct device *dev)
        return dev->release == scsi_host_dev_release;
 }
 EXPORT_SYMBOL(scsi_is_host_device);
+
+/**
+ * scsi_queue_work - Queue work to the Scsi_Host workqueue.
+ * @shost:     Pointer to Scsi_Host.
+ * @work:      Work to queue for execution.
+ *
+ * Return value:
+ *     0 on success / != 0 for error
+ **/
+int scsi_queue_work(struct Scsi_Host *shost, struct work_struct *work)
+{
+       if (unlikely(!shost->work_q)) {
+               printk(KERN_ERR
+                       "ERROR: Scsi host '%s' attempted to queue scsi-work, "
+                       "when no workqueue created.\n", shost->hostt->name);
+               dump_stack();
+
+               return -EINVAL;
+       }
+
+       return queue_work(shost->work_q, work);
+}
+EXPORT_SYMBOL_GPL(scsi_queue_work);
+
index 8faf83e47a9c3f30a4e39e10be61d556dd678289..7b99edf388743300f5abca4a3072e018cc820893 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/types.h>
+#include <linux/workqueue.h>
 
 struct block_device;
 struct module;
@@ -519,6 +520,12 @@ struct Scsi_Host {
        unsigned ordered_flush:1;
        unsigned ordered_tag:1;
 
+       /*
+        * Optional work queue to be utilized by the transport
+        */
+       char work_q_name[KOBJ_NAME_LEN];
+       struct workqueue_struct *work_q;
+
        /*
         * Host has rejected a command because it was busy.
         */
@@ -582,6 +589,8 @@ static inline struct Scsi_Host *dev_to_shost(struct device *dev)
        return container_of(dev, struct Scsi_Host, shost_gendev);
 }
 
+extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
+
 extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
 extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *);
 extern void scsi_scan_host(struct Scsi_Host *);
index f715a176d82b04b03e9454af5fb5a7eed2ce7835..2dcee7a84752c7089fd9ddfa701efd45589f467b 100644 (file)
@@ -34,6 +34,11 @@ struct scsi_transport_template {
        int     device_size;
        int     target_size;
        int     host_size;
+
+       /*
+        * True if the transport wants to use a host-based work-queue
+        */
+       unsigned int create_work_queue : 1;
 };
 
 #define transport_class_to_shost(tc) \