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;
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:
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);
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);
+
#include <linux/device.h>
#include <linux/list.h>
#include <linux/types.h>
+#include <linux/workqueue.h>
struct block_device;
struct module;
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.
*/
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 *);