Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d70c103 authored by Nicholas Bellinger's avatar Nicholas Bellinger Committed by James Bottomley
Browse files

[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: default avatarNicholas A. Bellinger <nab@linux-iscsi.org>
Signed-off-by: default avatarChad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 2c1391d3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
		qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \
        qla_nx.o
        qla_nx.o qla_target.o

obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
+4 −1
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 * See LICENSE.qla2xxx for copyright and licensing details.
 */
#include "qla_def.h"
#include "qla_target.h"

#include <linux/kthread.h>
#include <linux/vmalloc.h>
@@ -1737,6 +1738,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
	fc_host_supported_speeds(vha->host) =
		fc_host_supported_speeds(base_vha->host);

	qlt_vport_create(vha, ha);
	qla24xx_vport_disable(fc_vport, disable);

	if (ha->flags.cpu_affinity_enabled) {
@@ -1951,7 +1953,8 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha)
	fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
	fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
	fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
	fc_host_supported_classes(vha->host) = FC_COS_CLASS3;
	fc_host_supported_classes(vha->host) = ha->tgt.enable_class_2 ?
			(FC_COS_CLASS2|FC_COS_CLASS3) : FC_COS_CLASS3;
	fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports;
	fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count;

+68 −2
Original line number Diff line number Diff line
@@ -11,8 +11,8 @@
 * ----------------------------------------------------------------------
 * |             Level            |   Last Value Used  |     Holes	|
 * ----------------------------------------------------------------------
 * | Module Init and Probe        |       0x0120       | 0x4b,0xba,0xfa |
 * | Mailbox commands             |       0x113e       | 0x111a-0x111b  |
 * | Module Init and Probe        |       0x0122       | 0x4b,0xba,0xfa |
 * | Mailbox commands             |       0x1140       | 0x111a-0x111b  |
 * |                              |                    | 0x112c-0x112e  |
 * |                              |                    | 0x113a         |
 * | Device Discovery             |       0x2086       | 0x2020-0x2022  |
@@ -33,6 +33,9 @@
 * | ISP82XX Specific             |       0xb054       | 0xb024         |
 * | MultiQ                       |       0xc00c       |		|
 * | Misc                         |       0xd010       |		|
 * | Target Mode		  |	  0xe06f       |		|
 * | Target Mode Management	  |	  0xf071       |		|
 * | Target Mode Task Management  |	  0x1000b      |		|
 * ----------------------------------------------------------------------
 */

@@ -379,6 +382,54 @@ qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
	return (char *)iter_reg + ntohl(fcec->size);
}

static inline void *
qla2xxx_copy_atioqueues(struct qla_hw_data *ha, void *ptr,
	uint32_t **last_chain)
{
	struct qla2xxx_mqueue_chain *q;
	struct qla2xxx_mqueue_header *qh;
	uint32_t num_queues;
	int que;
	struct {
		int length;
		void *ring;
	} aq, *aqp;

	if (!ha->tgt.atio_q_length)
		return ptr;

	num_queues = 1;
	aqp = &aq;
	aqp->length = ha->tgt.atio_q_length;
	aqp->ring = ha->tgt.atio_ring;

	for (que = 0; que < num_queues; que++) {
		/* aqp = ha->atio_q_map[que]; */
		q = ptr;
		*last_chain = &q->type;
		q->type = __constant_htonl(DUMP_CHAIN_QUEUE);
		q->chain_size = htonl(
		    sizeof(struct qla2xxx_mqueue_chain) +
		    sizeof(struct qla2xxx_mqueue_header) +
		    (aqp->length * sizeof(request_t)));
		ptr += sizeof(struct qla2xxx_mqueue_chain);

		/* Add header. */
		qh = ptr;
		qh->queue = __constant_htonl(TYPE_ATIO_QUEUE);
		qh->number = htonl(que);
		qh->size = htonl(aqp->length * sizeof(request_t));
		ptr += sizeof(struct qla2xxx_mqueue_header);

		/* Add data. */
		memcpy(ptr, aqp->ring, aqp->length * sizeof(request_t));

		ptr += aqp->length * sizeof(request_t);
	}

	return ptr;
}

static inline void *
qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
{
@@ -874,6 +925,8 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
	struct qla24xx_fw_dump *fw;
	uint32_t	ext_mem_cnt;
	void		*nxt;
	void		*nxt_chain;
	uint32_t	*last_chain = NULL;
	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);

	if (IS_QLA82XX(ha))
@@ -1092,6 +1145,16 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)

	qla24xx_copy_eft(ha, nxt);

	nxt_chain = (void *)ha->fw_dump + ha->chain_offset;
	nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain);
	if (last_chain) {
		ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
		*last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
	}

	/* Adjust valid length. */
	ha->fw_dump_len = (nxt_chain - (void *)ha->fw_dump);

qla24xx_fw_dump_failed_0:
	qla2xxx_dump_post_process(base_vha, rval);

@@ -1400,6 +1463,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
	/* Chain entries -- started with MQ. */
	nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
	nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain);
	nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain);
	if (last_chain) {
		ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
		*last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
@@ -1718,6 +1782,7 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
	/* Chain entries -- started with MQ. */
	nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
	nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain);
	nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain);
	if (last_chain) {
		ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
		*last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
@@ -2219,6 +2284,7 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
	/* Chain entries -- started with MQ. */
	nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain);
	nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain);
	nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain);
	if (last_chain) {
		ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
		*last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
+4 −0
Original line number Diff line number Diff line
@@ -244,6 +244,7 @@ struct qla2xxx_mqueue_header {
	uint32_t queue;
#define TYPE_REQUEST_QUEUE	0x1
#define TYPE_RESPONSE_QUEUE	0x2
#define TYPE_ATIO_QUEUE		0x3
	uint32_t number;
	uint32_t size;
};
@@ -344,3 +345,6 @@ ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...);
				    * more verbosity is required. It might not
				    * be applicable to all the levels.
				    */
#define ql_dbg_tgt	0x00004000 /* Target mode */
#define ql_dbg_tgt_mgt	0x00002000 /* Target mode management */
#define ql_dbg_tgt_tmr	0x00001000 /* Target mode task management */
+67 −2
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@
#define RESPONSE_ENTRY_CNT_2100		64	/* Number of response entries.*/
#define RESPONSE_ENTRY_CNT_2300		512	/* Number of response entries.*/
#define RESPONSE_ENTRY_CNT_MQ		128	/* Number of response entries.*/
#define ATIO_ENTRY_CNT_24XX		4096	/* Number of ATIO entries. */

struct req_que;

@@ -1234,11 +1235,27 @@ typedef struct {
 * ISP queue - response queue entry definition.
 */
typedef struct {
	uint8_t		data[60];
	uint8_t		entry_type;		/* Entry type. */
	uint8_t		entry_count;		/* Entry count. */
	uint8_t		sys_define;		/* System defined. */
	uint8_t		entry_status;		/* Entry Status. */
	uint32_t	handle;			/* System defined handle */
	uint8_t		data[52];
	uint32_t	signature;
#define RESPONSE_PROCESSED	0xDEADDEAD	/* Signature */
} response_t;

/*
 * ISP queue - ATIO queue entry definition.
 */
struct atio {
	uint8_t		entry_type;		/* Entry type. */
	uint8_t		entry_count;		/* Entry count. */
	uint8_t		data[58];
	uint32_t	signature;
#define ATIO_PROCESSED 0xDEADDEAD		/* Signature */
};

typedef union {
	uint16_t extended;
	struct {
@@ -1749,6 +1766,7 @@ static const char * const port_state_str[] = {
#define FCF_LOGIN_NEEDED	BIT_1
#define FCF_FCP2_DEVICE		BIT_2
#define FCF_ASYNC_SENT		BIT_3
#define FCF_CONF_COMP_SUPPORTED BIT_4

/* No loop ID flag. */
#define FC_NO_LOOP_ID		0x1000
@@ -2421,6 +2439,40 @@ struct qlfc_fw {
	uint32_t len;
};

struct qlt_hw_data {
	/* Protected by hw lock */
	uint32_t enable_class_2:1;
	uint32_t enable_explicit_conf:1;
	uint32_t ini_mode_force_reverse:1;
	uint32_t node_name_set:1;

	dma_addr_t atio_dma;	/* Physical address. */
	struct atio *atio_ring;	/* Base virtual address */
	struct atio *atio_ring_ptr;	/* Current address. */
	uint16_t atio_ring_index; /* Current index. */
	uint16_t atio_q_length;

	void *target_lport_ptr;
	struct qla_tgt_func_tmpl *tgt_ops;
	struct qla_tgt *qla_tgt;
	struct qla_tgt_cmd *cmds[MAX_OUTSTANDING_COMMANDS];
	uint16_t current_handle;

	struct qla_tgt_vp_map *tgt_vp_map;
	struct mutex tgt_mutex;
	struct mutex tgt_host_action_mutex;

	int saved_set;
	uint16_t saved_exchange_count;
	uint32_t saved_firmware_options_1;
	uint32_t saved_firmware_options_2;
	uint32_t saved_firmware_options_3;
	uint8_t saved_firmware_options[2];
	uint8_t saved_add_firmware_options[2];

	uint8_t tgt_node_name[WWN_SIZE];
};

/*
 * Qlogic host adapter specific data structure.
*/
@@ -2463,7 +2515,8 @@ struct qla_hw_data {
		uint32_t	isp82xx_reset_hdlr_active:1;
		uint32_t	isp82xx_reset_owner:1;
		uint32_t	isp82xx_no_md_cap:1;
		/* 28 bits */
		uint32_t	host_shutting_down:1;
		/* 30 bits */
	} flags;

	/* This spinlock is used to protect "io transactions", you must
@@ -2864,6 +2917,8 @@ struct qla_hw_data {
	dma_addr_t      md_tmplt_hdr_dma;
	void            *md_dump;
	uint32_t	md_dump_size;

	struct qlt_hw_data tgt;
};

/*
@@ -2921,6 +2976,7 @@ typedef struct scsi_qla_host {
#define FCOE_CTX_RESET_NEEDED	18	/* Initiate FCoE context reset */
#define MPI_RESET_NEEDED	19	/* Initiate MPI FW reset */
#define ISP_QUIESCE_NEEDED	20	/* Driver need some quiescence */
#define SCR_PENDING		21	/* SCR in target mode */

	uint32_t	device_flags;
#define SWITCH_FOUND		BIT_0
@@ -2986,6 +3042,15 @@ typedef struct scsi_qla_host {
	atomic_t	vref_count;
} scsi_qla_host_t;

#define SET_VP_IDX	1
#define SET_AL_PA	2
#define RESET_VP_IDX	3
#define RESET_AL_PA	4
struct qla_tgt_vp_map {
	uint8_t	idx;
	scsi_qla_host_t *vha;
};

/*
 * Macros to help code, maintain, etc.
 */
Loading