[SCSI] qla2xxx: Add LLD target-mode infrastructure for >= 24xx series

Add LLD target mode for >= 24xx series HW.  This code was originally based on
external qla2x00t module based on 8.02.01-k4, and has been refactored to
push the bulk of code into mainline qla2xxx.ko LLD -> qla_target.c.

The implementation uses internal workqueues for I/O context submission
into tcm_qla2xxx code, and includes the struct qla_tgt_func_tmpl API for
external interaction to allow qla2xxx LDD to function without direct
target-core dependencies:

It also enables qla_target.c usage within existing qla2xxx LLD code.
This includes:

*) Addition of target mode specific members to existing data
structures in qla_def.h and struct qla_hw_data->tgt_ops using
qla_target.h:struct qla_tgt_func_tmpl

*) Addition of struct qla_tgt_func_tmpl and direct calls into
qla_target.c logic w/ qlt_* prefixed functions.

*) Addition of qla_iocb.c:qla2x00_req_pkt() for ring processing, and
qla2x00_issue_marker() for handling request/response queue processing
for target mode operation

*) Addition of various qla_tgt_mode_enabled() logic checks in
qla24xx_nvram_config(), qla2x00_initialize_adapter(), qla2x00_rff_id(),
qla2x00_abort_isp(), qla24xx_modify_vp_config(), and
qla2x00_vp_abort_isp().

By default the new qlini_mode module parameter is setting initiator-mode
to 'enabled' in order for 'modprobe qla2xxx' to continue to function as
expected in initiator only mode.  Enabling target-mode operation will
currently require a:

    modprobe qla2xxx qlini_mode="disabled"

in order to explictly disabled initiator mode and allow target-mode
to be enabled via tcm_qla2xxx configfs fabric callers.

(nab: Convert to qlini_mode='enabled' by default in qla_target.c)
(joern: Remove loop_id from qla_tgt_make_local_sess() arguments +
        Remove unused s_id + fix s_id endianness bug +
        simplify qla_tgt_abort_work)
(gerard: fix section __exit mismatch in qla_tgt_exit)
(arun: Capture ATIO queue during firmware dump + Send SCR in target mode +
       Target mode review comments)
(roland: Don't create duplicate target sessions to address tearing down
         ACLs with IO in flight + Add missing call to qlt_fc_port_deleted
	 call during qla2x00_schedule_rport_del timeout)

Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 07f4d3c..d5ce92c 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -5,6 +5,7 @@
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
 #include "qla_def.h"
+#include "qla_target.h"
 
 #include <linux/delay.h>
 #include <linux/gfp.h>
@@ -1245,6 +1246,96 @@
 }
 
 /*
+ * qla2x00_get_node_name_list
+ *      Issue get node name list mailbox command, kmalloc()
+ *      and return the resulting list. Caller must kfree() it!
+ *
+ * Input:
+ *      ha = adapter state pointer.
+ *      out_data = resulting list
+ *      out_len = length of the resulting list
+ *
+ * Returns:
+ *      qla2x00 local function return status code.
+ *
+ * Context:
+ *      Kernel context.
+ */
+int
+qla2x00_get_node_name_list(scsi_qla_host_t *vha, void **out_data, int *out_len)
+{
+	struct qla_hw_data *ha = vha->hw;
+	struct qla_port_24xx_data *list = NULL;
+	void *pmap;
+	mbx_cmd_t mc;
+	dma_addr_t pmap_dma;
+	ulong dma_size;
+	int rval, left;
+
+	left = 1;
+	while (left > 0) {
+		dma_size = left * sizeof(*list);
+		pmap = dma_alloc_coherent(&ha->pdev->dev, dma_size,
+					 &pmap_dma, GFP_KERNEL);
+		if (!pmap) {
+			ql_log(ql_log_warn, vha, 0x113f,
+			    "%s(%ld): DMA Alloc failed of %ld\n",
+			    __func__, vha->host_no, dma_size);
+			rval = QLA_MEMORY_ALLOC_FAILED;
+			goto out;
+		}
+
+		mc.mb[0] = MBC_PORT_NODE_NAME_LIST;
+		mc.mb[1] = BIT_1 | BIT_3;
+		mc.mb[2] = MSW(pmap_dma);
+		mc.mb[3] = LSW(pmap_dma);
+		mc.mb[6] = MSW(MSD(pmap_dma));
+		mc.mb[7] = LSW(MSD(pmap_dma));
+		mc.mb[8] = dma_size;
+		mc.out_mb = MBX_0|MBX_1|MBX_2|MBX_3|MBX_6|MBX_7|MBX_8;
+		mc.in_mb = MBX_0|MBX_1;
+		mc.tov = 30;
+		mc.flags = MBX_DMA_IN;
+
+		rval = qla2x00_mailbox_command(vha, &mc);
+		if (rval != QLA_SUCCESS) {
+			if ((mc.mb[0] == MBS_COMMAND_ERROR) &&
+			    (mc.mb[1] == 0xA)) {
+				left += le16_to_cpu(mc.mb[2]) /
+				    sizeof(struct qla_port_24xx_data);
+				goto restart;
+			}
+			goto out_free;
+		}
+
+		left = 0;
+
+		list = kzalloc(dma_size, GFP_KERNEL);
+		if (!list) {
+			ql_log(ql_log_warn, vha, 0x1140,
+			    "%s(%ld): failed to allocate node names list "
+			    "structure.\n", __func__, vha->host_no);
+			rval = QLA_MEMORY_ALLOC_FAILED;
+			goto out_free;
+		}
+
+		memcpy(list, pmap, dma_size);
+restart:
+		dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma);
+	}
+
+	*out_data = list;
+	*out_len = dma_size;
+
+out:
+	return rval;
+
+out_free:
+	dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma);
+	return rval;
+}
+
+/*
  * qla2x00_get_port_database
  *	Issue normal/enhanced get port database mailbox command
  *	and copy device name as necessary.
@@ -1352,6 +1443,13 @@
 			fcport->port_type = FCT_INITIATOR;
 		else
 			fcport->port_type = FCT_TARGET;
+
+		/* Passback COS information. */
+		fcport->supported_classes = (pd24->flags & PDF_CLASS_2) ?
+				FC_COS_CLASS2 : FC_COS_CLASS3;
+
+		if (pd24->prli_svc_param_word_3[0] & BIT_7)
+			fcport->flags |= FCF_CONF_COMP_SUPPORTED;
 	} else {
 		uint64_t zero = 0;
 
@@ -1770,6 +1868,10 @@
 			mb[10] |= BIT_0;	/* Class 2. */
 		if (lg->io_parameter[9] || lg->io_parameter[10])
 			mb[10] |= BIT_1;	/* Class 3. */
+		if (lg->io_parameter[0] & __constant_cpu_to_le32(BIT_7))
+			mb[10] |= BIT_7;	/* Confirmed Completion
+						 * Allowed
+						 */
 	}
 
 	dma_pool_free(ha->s_dma_pool, lg, lg_dma);
@@ -3096,6 +3198,9 @@
 	vpmod->vp_count = 1;
 	vpmod->vp_index1 = vha->vp_idx;
 	vpmod->options_idx1 = BIT_3|BIT_4|BIT_5;
+
+	qlt_modify_vp_config(vha, vpmod);
+
 	memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE);
 	memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE);
 	vpmod->entry_count = 1;
@@ -3235,13 +3340,6 @@
 	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c7,
 	    "Entered %s.\n", __func__);
 
-	/*
-	 * This command is implicitly executed by firmware during login for the
-	 * physical hosts
-	 */
-	if (vp_idx == 0)
-		return QLA_FUNCTION_FAILED;
-
 	mcp->mb[0] = MBC_SEND_CHANGE_REQUEST;
 	mcp->mb[1] = format;
 	mcp->mb[9] = vp_idx;