[PATCH] qla2xxx/tcm_qla2xxx: Add qla_hw_data specific I/O workqueue offload

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>

This patch adds an initial conversion to cmwq using qla_tgt->qla_tgt_wq
for I/O dispatch into qla_hw_data->qla_tgt specific context.  This includes
removal of transport_generic_handle_cdb_map() usage, and moves
transport_lookup_cmd_lun() into tcm_qla2xxx_do_work() process context for
incoming descriptor dispatch.

It passes WQ_UNBOUND during alloc_workqueue() setup, and also keeps all
target_core_mod referenced symbols within tcm_qla2xxx code in order to
avoid an qla2xxx LLD target_core_mod dependency.

Cc: Christoph Hellwig <hch@xxxxxx>
Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
---
 drivers/scsi/qla2xxx/qla_os.c                     |    8 +-
 drivers/scsi/qla2xxx/qla_target.c                 |   76 ++++++++++----------
 drivers/scsi/qla2xxx/qla_target.h                 |    5 +-
 drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c |   19 ++++--
 drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c   |   51 +++++++-------
 drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h   |    2 +-
 6 files changed, 87 insertions(+), 74 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 0a7c9dd..1f760e0 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4,9 +4,6 @@
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
-#include "qla_def.h"
-#include "qla_target.h"
-
 #include <linux/moduleparam.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
@@ -14,12 +11,15 @@
 #include <linux/mutex.h>
 #include <linux/kobject.h>
 #include <linux/slab.h>
-
+#include <linux/workqueue.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsicam.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_fc.h>
 
+#include "qla_def.h"
+#include "qla_target.h"
+
 /*
  * Driver version
  */
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 636ebfa..c9b2337 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -32,6 +32,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/list.h>
+#include <linux/workqueue.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -116,9 +117,6 @@ static int qla_tgt_unreg_sess(struct qla_tgt_sess *sess);
 static struct kmem_cache *qla_tgt_cmd_cachep;
 static struct kmem_cache *qla_tgt_mgmt_cmd_cachep;
 static mempool_t *qla_tgt_mgmt_cmd_mempool;
-
-static DECLARE_RWSEM(qla_tgt_unreg_rwsem);
-
 /*
  * From qla2xxx/qla_iobc.c and used by various qla_target.c logic
  */
@@ -3020,16 +3018,16 @@ static inline int qla_tgt_get_fcp_task_attr(uint8_t task_codes)
 
 /* ha->hardware_lock supposed to be held on entry */
 /* This functions sends the ISP 2xxx command to the tcm_qla2xxx target */
-static int qla_tgt_2xxx_send_cmd_to_tcm(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
+static int qla_tgt_2xxx_send_cmd(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
 {
 	atio_from_isp_t *atio = &cmd->atio;
 	uint32_t data_length;
 	int fcp_task_attr, data_dir, bidi = 0, ret;
-	uint16_t lun, unpacked_lun;
+	uint16_t lun;
 
 	/* make it be in network byte order */
 	lun = swab16(le16_to_cpu(atio->u.isp2x.lun));
-	unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
+	cmd->unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
 	cmd->tag = atio->u.isp2x.rx_id;
 
 	if ((atio->u.isp2x.execution_codes & (ATIO_EXEC_READ | ATIO_EXEC_WRITE)) ==
@@ -3048,24 +3046,21 @@ static int qla_tgt_2xxx_send_cmd_to_tcm(struct scsi_qla_host *vha, struct qla_tg
 
 	ql_dbg(ql_dbg_tgt_pkt, vha, 0xe207, "qla_target: START q2x command: %p"
 		" lun: 0x%04x (tag %d)\n", cmd, lun, cmd->tag);
-	/*
-	 * Dispatch command to tcm_qla2xxx fabric module code
-	 */
-	ret = vha->hw->tgt_ops->handle_cmd(vha, cmd, unpacked_lun, data_length,
+	return vha->hw->tgt_ops->handle_cmd(vha, cmd, data_length,
 				fcp_task_attr, data_dir, bidi);
-	return ret;
 }
 
 /* ha->hardware_lock supposed to be held on entry */
 /* This function sends the ISP 24xx command to the tcm_qla2xxx target */
-static int qla_tgt_24xx_send_cmd_to_tcm(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
+static int qla_tgt_24xx_send_cmd(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
 {
 	atio_from_isp_t *atio = &cmd->atio;
-	uint32_t unpacked_lun, data_length;
+	uint32_t data_length;
 	int fcp_task_attr, data_dir, bidi = 0, ret;
 
 	cmd->tag = atio->u.isp24.exchange_addr;
-	unpacked_lun = scsilun_to_int((struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun);
+	cmd->unpacked_lun = scsilun_to_int(
+				(struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun);
 
 	if (atio->u.isp24.fcp_cmnd.rddata && atio->u.isp24.fcp_cmnd.wrdata) {
 		bidi = 1;
@@ -3082,13 +3077,10 @@ static int qla_tgt_24xx_send_cmd_to_tcm(struct scsi_qla_host *vha, struct qla_tg
 			&atio->u.isp24.fcp_cmnd.add_cdb[atio->u.isp24.fcp_cmnd.add_cdb_len]));
 
 	ql_dbg(ql_dbg_tgt_pkt, vha, 0xe208, "qla_target: START q24 Command %p"
-		" unpacked_lun: 0x%08x (tag %d)\n", cmd, unpacked_lun, cmd->tag);
-	/*
-	 * Dispatch command to tcm_qla2xxx fabric module code
-	 */
-	ret = vha->hw->tgt_ops->handle_cmd(vha, cmd, unpacked_lun, data_length,
+		" unpacked_lun: 0x%08x (tag %d)\n", cmd, cmd->unpacked_lun, cmd->tag);
+
+	return vha->hw->tgt_ops->handle_cmd(vha, cmd, data_length,
 				fcp_task_attr, data_dir, bidi);
-	return ret;
 }
 
 /* ha->hardware_lock supposed to be held on entry */
@@ -3101,8 +3093,10 @@ static int qla_tgt_send_cmd_to_target(struct scsi_qla_host *vha,
 	cmd->loop_id = sess->loop_id;
 	cmd->conf_compl_supported = sess->conf_compl_supported;
 
-	return (IS_FWI2_CAPABLE(ha)) ? qla_tgt_24xx_send_cmd_to_tcm(vha, cmd) :
-			qla_tgt_2xxx_send_cmd_to_tcm(vha, cmd);
+	if (IS_FWI2_CAPABLE(ha))
+		return qla_tgt_24xx_send_cmd(vha, cmd);
+	else
+		return qla_tgt_2xxx_send_cmd(vha, cmd);
 }
 
 /* ha->hardware_lock supposed to be held on entry */
@@ -4859,7 +4853,12 @@ int qla_tgt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
 	INIT_LIST_HEAD(&tgt->srr_imm_list);
 	INIT_WORK(&tgt->srr_work, qla_tgt_handle_srr_work);
 	atomic_set(&tgt->tgt_global_resets_count, 0);
+	
+	tgt->qla_tgt_wq = alloc_workqueue("qla_tgt_wq", WQ_UNBOUND, 0);
+	if (!tgt->qla_tgt_wq)
+		return -ENOMEM;
 
+	printk("Setup tgt->qla_tgt_wq: %p for qla_hw_data: %p\n", tgt->qla_tgt_wq, ha);
 	ha->qla_tgt = tgt;
 
 	if (IS_FWI2_CAPABLE(ha)) {
@@ -4902,6 +4901,7 @@ int qla_tgt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
 			"existing target", vha->vp_idx);
 		return 0;
 	}
+	destroy_workqueue(ha->qla_tgt->qla_tgt_wq);
 
 	ql_dbg(ql_dbg_tgt, vha, 0xe037, "Unregistering target for host %ld(%p)",
 			vha->host_no, ha);
@@ -5393,9 +5393,7 @@ static int __init qla_tgt_parse_ini_mode(void)
 
 int __init qla_tgt_init(void)
 {
-	qla_tgt_cmd_cachep = NULL;
-	qla_tgt_mgmt_cmd_cachep = NULL;
-	qla_tgt_mgmt_cmd_mempool = NULL;
+	int ret;
 
 	if (!qla_tgt_parse_ini_mode()) {
 		printk(KERN_ERR "qla_tgt_parse_ini_mode() failed\n");
@@ -5414,29 +5412,31 @@ int __init qla_tgt_init(void)
 		sizeof(struct qla_tgt_mgmt_cmd), __alignof__(struct qla_tgt_mgmt_cmd),
 			0, NULL);
 	if (!qla_tgt_mgmt_cmd_cachep) {
-		printk(KERN_ERR "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n");
-		kmem_cache_destroy(qla_tgt_cmd_cachep);
-		return -ENOMEM;
+		pr_warn(KERN_ERR "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n");
+		ret = -ENOMEM;
+		goto out;
 	}
 
 	qla_tgt_mgmt_cmd_mempool = mempool_create(25, mempool_alloc_slab,
 				mempool_free_slab, qla_tgt_mgmt_cmd_cachep);
 	if (!qla_tgt_mgmt_cmd_mempool) {
-		printk(KERN_ERR "mempool_create for qla_tgt_mgmt_cmd_mempool failed\n");
-		kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep);
-		kmem_cache_destroy(qla_tgt_cmd_cachep);
-		return -ENOMEM;
+		pr_warn(KERN_ERR "mempool_create for qla_tgt_mgmt_cmd_mempool failed\n");
+		ret = -ENOMEM;
+		goto out_mgmt_cmd_cachep;
 	}
 
 	return 0;
+
+out_mgmt_cmd_cachep:
+	kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep);
+out:
+	kmem_cache_destroy(qla_tgt_cmd_cachep);
+	return ret;
 }
 
 void __exit qla_tgt_exit(void)
 {
-	if (qla_tgt_mgmt_cmd_mempool != NULL)
-		mempool_destroy(qla_tgt_mgmt_cmd_mempool);
-	if (qla_tgt_mgmt_cmd_cachep != NULL)
-		kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep);
-	if (qla_tgt_cmd_cachep != NULL)
-		kmem_cache_destroy(qla_tgt_cmd_cachep);
+	mempool_destroy(qla_tgt_mgmt_cmd_mempool);
+	kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep);
+	kmem_cache_destroy(qla_tgt_cmd_cachep);
 }
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 9188e3e..3fcb912 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -720,7 +720,7 @@ struct qla_tgt_sess;
  */
 struct qla_tgt_func_tmpl {
 
-	int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *, uint32_t,
+	int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
 			uint32_t, int, int, int);
 	int (*handle_data)(struct qla_tgt_cmd *);
 	int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint8_t);
@@ -869,6 +869,7 @@ struct qla_tgt {
 	spinlock_t sess_work_lock;
 	struct list_head sess_works_list;
 	struct work_struct sess_work;
+	struct workqueue_struct *qla_tgt_wq;
 
 	imm_ntfy_from_isp_t link_reinit_iocb;
 	wait_queue_head_t waitQ;
@@ -921,6 +922,7 @@ struct qla_tgt_cmd {
 	atomic_t cmd_free;
 	struct completion cmd_stop_free_comp;
 	struct se_cmd se_cmd;
+	struct work_struct free_work;
 	struct work_struct work;
 	/* Sense buffer that will be mapped into outgoing status */
 	unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
@@ -937,6 +939,7 @@ struct qla_tgt_cmd {
 	int bufflen;		/* cmd buffer length */
 	int offset;
 	uint32_t tag;
+	uint32_t unpacked_lun;
 	dma_addr_t *srr_dma_buffer; /* Used for SRR offsets with pci_map_page() */
 	enum dma_data_direction dma_data_direction;
 
diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c
index 97b6731..f4ee520 100644
--- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c
+++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c
@@ -53,6 +53,7 @@ struct target_fabric_configfs *tcm_qla2xxx_fabric_configfs;
 struct target_fabric_configfs *tcm_qla2xxx_npiv_fabric_configfs;
 
 struct workqueue_struct *tcm_qla2xxx_free_wq;
+struct workqueue_struct *tcm_qla2xxx_cmd_wq;
 
 static int tcm_qla2xxx_setup_nacl_from_rport(
 	struct se_portal_group *se_tpg,
@@ -1221,7 +1222,7 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = {
 	.tpg_alloc_fabric_acl		= tcm_qla2xxx_alloc_fabric_acl,
 	.tpg_release_fabric_acl		= tcm_qla2xxx_release_fabric_acl,
 	.tpg_get_inst_index		= tcm_qla2xxx_tpg_get_inst_index,
-	.new_cmd_map			= tcm_qla2xxx_new_cmd_map,
+	.new_cmd_map			= NULL,
 	.check_stop_free		= tcm_qla2xxx_check_stop_free,
 	.check_release_cmd		= tcm_qla2xxx_check_release_cmd,
 	.release_cmd			= tcm_qla2xxx_release_cmd,
@@ -1402,11 +1403,21 @@ static int tcm_qla2xxx_register_configfs(void)
 
 	tcm_qla2xxx_free_wq = alloc_workqueue("tcm_qla2xxx_free",
 						WQ_MEM_RECLAIM, 0);
-	if (!tcm_qla2xxx_free_wq)
+	if (!tcm_qla2xxx_free_wq) {
+		ret = -ENOMEM;
 		goto out_fabric_npiv;
+	}
+
+	tcm_qla2xxx_cmd_wq = alloc_workqueue("tcm_qla2xxx_cmd", 0, 0);
+	if (!tcm_qla2xxx_cmd_wq) {
+		ret = -ENOMEM;
+		goto out_free_wq;
+	}
 
 	return 0;
 
+out_free_wq:
+	destroy_workqueue(tcm_qla2xxx_free_wq);
 out_fabric_npiv:
 	target_fabric_configfs_deregister(tcm_qla2xxx_npiv_fabric_configfs);
 out_fabric:
@@ -1416,9 +1427,7 @@ out_fabric:
 
 static void tcm_qla2xxx_deregister_configfs(void)
 {
-	if (!tcm_qla2xxx_fabric_configfs)
-		return;
-
+	destroy_workqueue(tcm_qla2xxx_cmd_wq);
 	destroy_workqueue(tcm_qla2xxx_free_wq);
 
 	target_fabric_configfs_deregister(tcm_qla2xxx_fabric_configfs);
diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
index 159423c..a3e4ca3 100644
--- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
+++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
@@ -53,6 +53,7 @@
 #include "tcm_qla2xxx_fabric.h"
 
 extern struct workqueue_struct *tcm_qla2xxx_free_wq;
+extern struct workqueue_struct *tcm_qla2xxx_cmd_wq;
 
 int tcm_qla2xxx_check_true(struct se_portal_group *se_tpg)
 {
@@ -665,13 +666,15 @@ int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd)
 	return 0;
 }
 
+static void tcm_qla2xxx_do_work(struct work_struct *);
+
 /*
  * Main entry point for incoming ATIO packets from qla_target.c
  * and qla2xxx LLD code.  Called with qla_hw_data->hardware_lock held
  */
 int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
-			uint32_t lun, uint32_t data_length,
-			int fcp_task_attr, int data_dir, int bidi)
+			uint32_t data_length, int fcp_task_attr,
+			int data_dir, int bidi)
 {
 	struct se_cmd *se_cmd = &cmd->se_cmd;
 	struct se_session *se_sess;
@@ -706,49 +709,47 @@ int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
 	 */
 	if (bidi)
 		se_cmd->t_tasks_bidi = 1;
-	/*
-	 * Locate the struct se_lun pointer and attach it to struct se_cmd
-	 */
-	if (transport_lookup_cmd_lun(se_cmd, lun) < 0) {
-		/*
-		 * Clear qla_tgt_cmd->locked_rsp as ha->hardware_lock
-		 * is already held here, and we'll end up calling back
-		 * into ->queue_status (tcm_qla2xxx_queue_status())
-		 * and hence qla_tgt_xmit_response().
-		 */
-		cmd->locked_rsp = 0;
 
-		/* NON_EXISTENT_LUN */
-		transport_send_check_condition_and_sense(se_cmd,
-				se_cmd->scsi_sense_reason, 0);
-		return 0;
-	}
-	/*
-	 * Queue up the newly allocated to be processed in TCM thread context.
-	 */
-	transport_generic_handle_cdb_map(se_cmd);
+	INIT_WORK(&cmd->work, tcm_qla2xxx_do_work);
+	queue_work(cmd->tgt->qla_tgt_wq, &cmd->work);
 	return 0;
 }
 
-int tcm_qla2xxx_new_cmd_map(struct se_cmd *se_cmd)
+void tcm_qla2xxx_do_work(struct work_struct *work)
 {
-	struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
+	struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
+	struct se_cmd *se_cmd = &cmd->se_cmd;
 	scsi_qla_host_t *vha = cmd->vha;
 	struct qla_hw_data *ha = vha->hw;
 	unsigned char *cdb;
 	atio_from_isp_t *atio = &cmd->atio;
+	int rc;
 
 	if (IS_FWI2_CAPABLE(ha))
 		cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
 	else
 		cdb = &atio->u.isp2x.cdb[0];
+	/*
+ 	 * Locate se_lun pointer and attach it to struct se_cmd
+ 	 */
+	if (transport_lookup_cmd_lun(se_cmd, cmd->unpacked_lun) < 0) {
+		transport_send_check_condition_and_sense(se_cmd,
+			se_cmd->scsi_sense_reason, 0);
+		return;
+	}
 
 	/*
 	 * Allocate the necessary tasks to complete the received CDB+data
 	 * drivers/target/target_core_transport.c:transport_processing_thread()
 	 * falls through to TRANSPORT_NEW_CMD.
 	 */
-	return transport_generic_allocate_tasks(se_cmd, cdb);
+	rc = transport_generic_allocate_tasks(se_cmd, cdb);
+	if (rc != 0) {
+		transport_send_check_condition_and_sense(se_cmd,
+				se_cmd->scsi_sense_reason, 0);
+		return;
+	}
+	transport_handle_cdb_direct(se_cmd);
 }
 
 /*
diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h
index e807a1e..ea1f5fb 100644
--- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h
+++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h
@@ -40,7 +40,7 @@ extern void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *);
 extern u32 tcm_qla2xxx_get_task_tag(struct se_cmd *);
 extern int tcm_qla2xxx_get_cmd_state(struct se_cmd *);
 extern int tcm_qla2xxx_handle_cmd(struct scsi_qla_host *, struct qla_tgt_cmd *,
-                        uint32_t, uint32_t, int, int, int);
+                        uint32_t, int, int, int);
 extern int tcm_qla2xxx_new_cmd_map(struct se_cmd *);
 extern int tcm_qla2xxx_handle_data(struct qla_tgt_cmd *);
 extern int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *, uint32_t, uint8_t);
-- 
1.7.2.5

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux