[PATCH 2/3] qla2xxx: Push remaining se_cmd init into qla_tgt_do_work

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

 



From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>

This patch converts qla2xxx/tcm_qla2xxx code to push remaining
se_cmd initilization into qla_tgt_wq processs context from ATIO
interrupt context, and will only obtain qla_hw_data->hardware_lock
from qla_tgt_do_work() context when qla_tgt_sess_put() drops the
last qla_tgt_sess->sess_kref during active I/O shutdown.

It also merges qla_tgt_2*xx_init_cmd() into qla_tgt_do_work(), and
allows qla_tgt_do_work() to handle the creation of new qla_tgt_sess
allocations for ATIO descriptors w/o an active session.

Cc: Christoph Hellwig <hch@xxxxxx>
Cc: Roland Dreier <roland@xxxxxxxxxxxxxxx>
Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
---
 drivers/scsi/qla2xxx/qla_target.c                 |  283 ++++++++-------------
 drivers/scsi/qla2xxx/qla_target.h                 |    5 +-
 drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c |    1 -
 drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c   |   25 +--
 drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h   |    5 +-
 5 files changed, 122 insertions(+), 197 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 3a9aa44..1f70fd0 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -81,8 +81,6 @@ enum fcp_resp_rsp_codes {
 #define FCP_PRI_SHIFT       3   /* priority field starts in bit 3 */
 #define FCP_PRI_RESVD_MASK  0x80        /* reserved bits in priority field */
 
-static void qla_tgt_exec_cmd_work(struct work_struct *work);
-
 /*
  * This driver calls qla2x00_req_pkt() and qla2x00_issue_marker(), which
  * must be called under HW lock and could unlock/lock it inside.
@@ -3023,73 +3021,8 @@ static inline int qla_tgt_get_fcp_task_attr(uint8_t task_codes)
 	return fcp_task_attr;
 }
 
-/* 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_init_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;
-	uint16_t lun;
-
-	/* make it be in network byte order */
-	lun = swab16(le16_to_cpu(atio->u.isp2x.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)) ==
-				(ATIO_EXEC_READ | ATIO_EXEC_WRITE)) {
-		bidi = 1;
-		data_dir = DMA_TO_DEVICE;
-	} else if (atio->u.isp2x.execution_codes & ATIO_EXEC_READ)
-		data_dir = DMA_FROM_DEVICE;
-	else if (atio->u.isp2x.execution_codes & ATIO_EXEC_WRITE)
-		data_dir = DMA_TO_DEVICE;
-	else
-		data_dir = DMA_NONE;
-
-	fcp_task_attr = qla_tgt_get_fcp_task_attr(atio->u.isp2x.task_codes);
-	data_length = le32_to_cpu(atio->u.isp2x.data_length);
-
-	ql_dbg(ql_dbg_tgt_pkt, vha, 0xe207, "qla_target: START q2x command: %p"
-		" lun: 0x%04x (tag %d)\n", cmd, lun, cmd->tag);
-	return vha->hw->tgt_ops->init_cmd(vha, cmd, data_length,
-				fcp_task_attr, data_dir, bidi);
-}
-
-/* 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_init_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;
-
-	cmd->tag = atio->u.isp24.exchange_addr;
-	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;
-		data_dir = DMA_TO_DEVICE;
-	} else if (atio->u.isp24.fcp_cmnd.rddata)
-		data_dir = DMA_FROM_DEVICE;
-	else if (atio->u.isp24.fcp_cmnd.wrdata)
-		data_dir = DMA_TO_DEVICE;
-	else
-		data_dir = DMA_NONE;
-
-	fcp_task_attr = qla_tgt_get_fcp_task_attr(atio->u.isp24.fcp_cmnd.task_attr);
-	data_length = be32_to_cpu(get_unaligned((uint32_t *)
-			&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, cmd->unpacked_lun, cmd->tag);
-
-	return vha->hw->tgt_ops->init_cmd(vha, cmd, data_length,
-				fcp_task_attr, data_dir, bidi);
-}
-
+static struct qla_tgt_sess *qla_tgt_make_local_sess(struct scsi_qla_host *,
+					uint8_t *, uint16_t);
 /*
  * Process context for I/O path into tcm_qla2xxx code
  */
@@ -3098,38 +3031,112 @@ static void qla_tgt_do_work(struct work_struct *work)
 	struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
 	scsi_qla_host_t *vha = cmd->vha;
 	struct qla_hw_data *ha = vha->hw;
-	unsigned char *cdb;
+	struct qla_tgt *tgt = ha->qla_tgt;
+	struct qla_tgt_sess *sess = NULL;
 	atio_from_isp_t *atio = &cmd->atio;
+	unsigned char *cdb;
+	unsigned long flags;
+	uint32_t data_length;
+	int ret, fcp_task_attr, data_dir, bidi = 0;;
 
-	if (IS_FWI2_CAPABLE(ha))
-		cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
-	else
-		cdb = &atio->u.isp2x.cdb[0];
+	if (tgt->tgt_stop)
+		goto out_term;	
 
-	vha->hw->tgt_ops->handle_cmd(cmd, cdb);
-}
+	sess = cmd->sess;
+	if (!sess) {
+		uint8_t *s_id = NULL;
+		uint16_t loop_id = 0;
 
-/* ha->hardware_lock supposed to be held on entry */
-static int qla_tgt_send_cmd_to_target(struct scsi_qla_host *vha,
-	struct qla_tgt_cmd *cmd, struct qla_tgt_sess *sess)
-{
-	struct qla_hw_data *ha = vha->hw;
-	int ret = 0;
+		if (IS_FWI2_CAPABLE(ha))
+			s_id = atio->u.isp24.fcp_hdr.s_id;
+		else
+			loop_id = GET_TARGET_ID(ha, atio);
+
+		mutex_lock(&ha->tgt_mutex);
+		sess = qla_tgt_make_local_sess(vha, s_id, loop_id);
+		/* sess has got an extra creation ref */
+		mutex_unlock(&ha->tgt_mutex);
+
+		if (!sess)
+			goto out_term;
+	}
+
+	if (tgt->tgt_stop)
+		goto out_term;
 
 	cmd->sess = sess;
 	cmd->loop_id = sess->loop_id;
 	cmd->conf_compl_supported = sess->conf_compl_supported;
 
-	if (IS_FWI2_CAPABLE(ha))
-		ret = qla_tgt_24xx_init_cmd(vha, cmd);
-	else
-		ret = qla_tgt_2xxx_init_cmd(vha, cmd);
+	if (IS_FWI2_CAPABLE(ha)) {
+		cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
+		cmd->tag = atio->u.isp24.exchange_addr;
+		cmd->unpacked_lun = scsilun_to_int(
+				(struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun);
 
-	if (!ret) {
-		INIT_WORK(&cmd->work, qla_tgt_do_work);
-		queue_work(qla_tgt_wq, &cmd->work);
+		if (atio->u.isp24.fcp_cmnd.rddata &&
+		    atio->u.isp24.fcp_cmnd.wrdata) {
+			bidi = 1;
+			data_dir = DMA_TO_DEVICE;
+		} else if (atio->u.isp24.fcp_cmnd.rddata)
+			data_dir = DMA_FROM_DEVICE;
+		else if (atio->u.isp24.fcp_cmnd.wrdata)
+			data_dir = DMA_TO_DEVICE;
+		else
+			data_dir = DMA_NONE;
+
+		fcp_task_attr = qla_tgt_get_fcp_task_attr(
+				atio->u.isp24.fcp_cmnd.task_attr);
+		data_length = be32_to_cpu(get_unaligned((uint32_t *)
+				&atio->u.isp24.fcp_cmnd.add_cdb[
+					atio->u.isp24.fcp_cmnd.add_cdb_len]));
+	} else {
+		uint16_t lun;
+
+		cdb = &atio->u.isp2x.cdb[0];
+		cmd->tag = atio->u.isp2x.rx_id;
+		lun = swab16(le16_to_cpu(atio->u.isp2x.lun));
+		cmd->unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
+
+		if ((atio->u.isp2x.execution_codes & (ATIO_EXEC_READ | ATIO_EXEC_WRITE)) ==
+					(ATIO_EXEC_READ | ATIO_EXEC_WRITE)) {
+			bidi = 1;
+			data_dir = DMA_TO_DEVICE;
+		} else if (atio->u.isp2x.execution_codes & ATIO_EXEC_READ)
+			data_dir = DMA_FROM_DEVICE;
+		else if (atio->u.isp2x.execution_codes & ATIO_EXEC_WRITE)
+			data_dir = DMA_TO_DEVICE;
+		else
+			data_dir = DMA_NONE;
+
+		fcp_task_attr = qla_tgt_get_fcp_task_attr(atio->u.isp2x.task_codes);
+		data_length = le32_to_cpu(atio->u.isp2x.data_length);
 	}
-	return ret;
+
+	ql_dbg(ql_dbg_tgt_pkt, vha, 0xe207, "qla_target: START qla command: %p"
+		" lun: 0x%04x (tag %d)\n", cmd, cmd->unpacked_lun, cmd->tag);
+
+	ret = vha->hw->tgt_ops->handle_cmd(vha, cmd, cdb, data_length,
+			fcp_task_attr, data_dir, bidi);
+	if (ret != 0)
+		goto out_term;
+	/*
+	 * Drop extra session reference from qla_tgt_handle_cmd_for_atio*(
+	 */
+	qla_tgt_sess_put(sess);
+	return;
+
+out_term:
+	ql_dbg(ql_dbg_tgt_mgt, vha, 0xe14d, "Terminating work cmd %p", cmd);
+	/*
+	 * cmd has not sent to target yet, so pass NULL as the second argument
+	 */
+	spin_lock_irqsave(&ha->hardware_lock, flags);
+	qla_tgt_send_term_exchange(vha, NULL, &cmd->atio, 1);
+	
+	if (sess)
+		__qla_tgt_sess_put(sess);
+	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 }
 
 /* ha->hardware_lock supposed to be held on entry */
@@ -3188,11 +3195,19 @@ static int qla_tgt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 	if (sess->tearing_down || tgt->tgt_stop)
 		goto out_free_cmd;
 
-	res = qla_tgt_send_cmd_to_target(vha, cmd, sess);
-	if (unlikely(res != 0))
-		goto out_free_cmd;
+	cmd->sess = sess;
+	cmd->loop_id = sess->loop_id;
+	cmd->conf_compl_supported = sess->conf_compl_supported;
+	/*
+	 * Get the extra kref_get() before dropping qla_hw_data->hardware_lock,
+	 * and call qla_tgt_sess_put() -> kref_put() in qla_tgt_do_work() process
+	 * context to drop the extra reference.
+	*/
+	kref_get(&sess->sess_kref);
 
-	return res;
+	INIT_WORK(&cmd->work, qla_tgt_do_work);
+	queue_work(qla_tgt_wq, &cmd->work);
+	return 0;
 
 out_free_cmd:
 	qla_tgt_free_cmd(cmd);
@@ -3204,9 +3219,8 @@ out_sched:
 		res = -EBUSY;
 		goto out_free_cmd;
 	}
-
-	INIT_WORK(&cmd->work, qla_tgt_exec_cmd_work);
-	schedule_work(&cmd->work);
+	INIT_WORK(&cmd->work, qla_tgt_do_work);
+	queue_work(qla_tgt_wq, &cmd->work);
 	return 0;
 }
 
@@ -4567,81 +4581,6 @@ retry:
 	return sess;
 }
 
-static void qla_tgt_exec_cmd_work(struct work_struct *work)
-{
-	struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
-	struct qla_tgt *tgt = cmd->tgt;
-	struct scsi_qla_host *vha = tgt->vha;
-	struct qla_hw_data *ha = vha->hw;
-	struct qla_tgt_sess *sess = NULL;
-	unsigned long flags;
-	uint8_t *s_id = NULL; /* to hide compiler warnings */
-	int rc, loop_id = -1; /* to hide compiler warnings */
-	atio_from_isp_t *a = (atio_from_isp_t *)&cmd->atio;
-
-	spin_lock_irqsave(&ha->hardware_lock, flags);
-
-	if (tgt->tgt_stop)
-		goto out_term;
-
-	if (IS_FWI2_CAPABLE(ha)) {
-		s_id = a->u.isp24.fcp_hdr.s_id;
-		sess = ha->tgt_ops->find_sess_by_s_id(vha, s_id);
-	} else {
-		loop_id = GET_TARGET_ID(ha, a);
-		sess = ha->tgt_ops->find_sess_by_loop_id(vha, loop_id);
-	}
-
-	if (sess) {
-		ql_dbg(ql_dbg_tgt_mgt, vha, 0xe14c, "sess %p found\n", sess);
-		kref_get(&sess->sess_kref);
-	} else {
-		spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-		mutex_lock(&ha->tgt_mutex);
-		sess = qla_tgt_make_local_sess(vha, s_id, loop_id);
-		/* sess has got an extra creation ref */
-		mutex_unlock(&ha->tgt_mutex);
-
-		spin_lock_irqsave(&ha->hardware_lock, flags);
-
-		if (!sess)
-			goto out_term;
-	}
-
-	if (tgt->tgt_stop)
-		goto out_term;
-
-	if (tgt->tm_to_unknown) {
-		/*
-		 * Cmd might be already aborted behind us, so be safe
-		 * and abort it. It should be OK, initiator will retry
-		 * it.
-		 */
-		goto out_term;
-	}
-	rc = qla_tgt_send_cmd_to_target(vha, cmd, sess);
-	if (rc != 0)
-		goto out_term;
-
-	if (sess)
-		qla_tgt_sess_put(sess);
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-	return;
-
-out_term:
-	ql_dbg(ql_dbg_tgt_mgt, vha, 0xe14d, "Terminating work cmd %p", cmd);
-	/*
-	 * cmd has not sent to target yet, so pass NULL as the second
-	 * argument
-	 */
-	qla_tgt_send_term_exchange(vha, NULL, &cmd->atio, 1);
-	if (sess)
-		qla_tgt_sess_put(sess);
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
-}
-
-
 static void qla_tgt_abort_work(struct qla_tgt *tgt,
 	struct qla_tgt_sess_work_param *prm)
 {
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index a9032d6..bb66ca2 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -720,9 +720,8 @@ struct qla_tgt_sess;
  */
 struct qla_tgt_func_tmpl {
 
-	int (*init_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
-			uint32_t, int, int, int);
-	void (*handle_cmd)(struct qla_tgt_cmd *, unsigned char *);
+	int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
+			unsigned char *, uint32_t, int, int, int);
 	int (*handle_data)(struct qla_tgt_cmd *);
 	int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint8_t);
 	void (*free_cmd)(struct qla_tgt_cmd *);
diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c
index a92d982..12df8bb 100644
--- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c
+++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c
@@ -851,7 +851,6 @@ static int tcm_qla2xxx_check_initiator_node_acl(
  * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
  */
 static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
-	.init_cmd		= tcm_qla2xxx_init_cmd,
 	.handle_cmd		= tcm_qla2xxx_handle_cmd,
 	.handle_data		= tcm_qla2xxx_handle_data,
 	.handle_tmr		= tcm_qla2xxx_handle_tmr,
diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
index c1080e2..080d1d0 100644
--- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
+++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c
@@ -601,18 +601,17 @@ int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd)
 }
 
 /*
- * Main entry point for incoming ATIO packets from qla_target.c
- * and qla2xxx LLD code.  Called with qla_hw_data->hardware_lock to
- * setup qla_tgt_cmd->se_cmd
+ * Called from process context in qla_target.c:qla_tgt_do_work() code
  */
-int tcm_qla2xxx_init_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
-			uint32_t data_length, int fcp_task_attr,
+int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
+			unsigned char *cdb, 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;
 	struct se_portal_group *se_tpg;
 	struct qla_tgt_sess *sess;
+	int rc;
 
 	sess = cmd->sess;
 	if (!sess) {
@@ -642,24 +641,13 @@ int tcm_qla2xxx_init_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
 	 */
 	if (bidi)
 		se_cmd->t_tasks_bidi = 1;
-
-	return 0;
-}
-
-/*
- * Called from process context in qla_target.c:qla_tgt_do_work() code
- */
-void tcm_qla2xxx_handle_cmd(struct qla_tgt_cmd *cmd, unsigned char *cdb)
-{
-	struct se_cmd *se_cmd = &cmd->se_cmd;
-	int rc;
 	/*
  	 * 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;
+		return 0;
 	}
 
 	/*
@@ -671,9 +659,10 @@ void tcm_qla2xxx_handle_cmd(struct qla_tgt_cmd *cmd, unsigned char *cdb)
 	if (rc != 0) {
 		transport_send_check_condition_and_sense(se_cmd,
 				se_cmd->scsi_sense_reason, 0);
-		return;
+		return 0;
 	}
 	transport_handle_cdb_direct(se_cmd);
+	return 0;
 }
 
 void tcm_qla2xxx_do_rsp(struct work_struct *work)
diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h
index dc7e48a..e9a2ce2 100644
--- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h
+++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h
@@ -38,9 +38,8 @@ extern int tcm_qla2xxx_write_pending_status(struct se_cmd *);
 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_init_cmd(struct scsi_qla_host *, struct qla_tgt_cmd *,
-                        uint32_t, int, int, int);
-extern void tcm_qla2xxx_handle_cmd(struct qla_tgt_cmd *, unsigned char *);
+extern int tcm_qla2xxx_handle_cmd(struct scsi_qla_host *, struct qla_tgt_cmd *,
+			unsigned char *, 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