summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/Kconfig1
-rw-r--r--drivers/scsi/qla2xxx/Makefile2
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c161
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h17
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h182
-rw-r--r--drivers/scsi/qla2xxx/qla_dfs.c145
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h35
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h40
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c275
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c606
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h60
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c116
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c229
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c125
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c44
-rw-r--r--drivers/scsi/qla2xxx/qla_nvme.c761
-rw-r--r--drivers/scsi/qla2xxx/qla_nvme.h132
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.h17
-rw-r--r--drivers/scsi/qla2xxx/qla_nx2.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c368
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c1438
-rw-r--r--drivers/scsi/qla2xxx/qla_target.h58
-rw-r--r--drivers/scsi/qla2xxx/qla_tmpl.c16
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h4
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c36
28 files changed, 3641 insertions, 1245 deletions
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index de952935b5d2..036cc3f217b1 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -2,6 +2,7 @@ config SCSI_QLA_FC
tristate "QLogic QLA2XXX Fibre Channel Support"
depends on PCI && SCSI
depends on SCSI_FC_ATTRS
+ depends on NVME_FC || !NVME_FC
select FW_LOADER
select BTREE
---help---
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index 44def6bb4bb0..0b767a0bb308 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -1,6 +1,6 @@
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_mr.o qla_nx2.o qla_target.o qla_tmpl.o
+ qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o
obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
obj-$(CONFIG_TCM_QLA2XXX) += tcm_qla2xxx.o
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 7c8d6c54ab70..08a1feb3a195 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -769,7 +769,7 @@ qla2x00_issue_logo(struct file *filp, struct kobject *kobj,
did.b.area = (type & 0x0000ff00) >> 8;
did.b.al_pa = (type & 0x000000ff);
- ql_log(ql_log_info, vha, 0x70e3, "portid=%02x%02x%02x done\n",
+ ql_log(ql_log_info, vha, 0xd04d, "portid=%02x%02x%02x done\n",
did.b.domain, did.b.area, did.b.al_pa);
ql_log(ql_log_info, vha, 0x70e4, "%s: %d\n", __func__, type);
@@ -929,7 +929,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
iter->name, ret);
else
ql_dbg(ql_dbg_init, vha, 0x00f4,
- "Successfully created sysfs %s binary attribure.\n",
+ "Successfully created sysfs %s binary attribute.\n",
iter->name);
}
}
@@ -2096,7 +2096,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
}
if (qos) {
- qpair = qla2xxx_create_qpair(vha, qos, vha->vp_idx);
+ qpair = qla2xxx_create_qpair(vha, qos, vha->vp_idx, true);
if (!qpair)
ql_log(ql_log_warn, vha, 0x7084,
"Can't create qpair for VP[%d]\n",
@@ -2289,7 +2289,7 @@ 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) = ha->tgt.enable_class_2 ?
+ fc_host_supported_classes(vha->host) = ha->base_qpair->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;
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index ca3420de5a01..2ea0ef93f5cb 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -293,7 +293,7 @@ qla2x00_process_els(struct bsg_job *bsg_job)
if (bsg_job->request_payload.sg_cnt > 1 ||
bsg_job->reply_payload.sg_cnt > 1) {
ql_dbg(ql_dbg_user, vha, 0x7002,
- "Multiple SG's are not suppored for ELS requests, "
+ "Multiple SG's are not supported for ELS requests, "
"request_sg_cnt=%x reply_sg_cnt=%x.\n",
bsg_job->request_payload.sg_cnt,
bsg_job->reply_payload.sg_cnt);
@@ -2135,7 +2135,7 @@ qla8044_serdes_op(struct bsg_job *bsg_job)
bsg_reply->reply_payload_rcv_len = sizeof(sr);
break;
default:
- ql_dbg(ql_dbg_user, vha, 0x70cf,
+ ql_dbg(ql_dbg_user, vha, 0x7020,
"Unknown serdes cmd %x.\n", sr.cmd);
rval = -EINVAL;
break;
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 88748a6ab73f..26751d34bcf2 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -15,9 +15,10 @@
* | | | 0x015b-0x0160 |
* | | | 0x016e |
* | Mailbox commands | 0x1199 | 0x1193 |
- * | Device Discovery | 0x2004 | 0x2016 |
- * | | | 0x2011-0x2012, |
- * | | | 0x2099-0x20a4 |
+ * | Device Discovery | 0x2134 | 0x210e-0x2116 |
+ * | | | 0x211a |
+ * | | | 0x211c-0x2128 |
+ * | | | 0x212a-0x2130 |
* | Queue Command and IO tracing | 0x3074 | 0x300b |
* | | | 0x3027-0x3028 |
* | | | 0x303d-0x3041 |
@@ -59,10 +60,10 @@
* | | | 0xb13c-0xb140 |
* | | | 0xb149 |
* | MultiQ | 0xc010 | |
- * | Misc | 0xd301 | 0xd031-0xd0ff |
+ * | Misc | 0xd302 | 0xd031-0xd0ff |
* | | | 0xd101-0xd1fe |
* | | | 0xd214-0xd2fe |
- * | Target Mode | 0xe080 | |
+ * | Target Mode | 0xe081 | |
* | Target Mode Management | 0xf09b | 0xf002 |
* | | | 0xf046-0xf049 |
* | Target Mode Task Management | 0x1000d | |
@@ -498,6 +499,50 @@ qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
}
static inline void *
+qla25xx_copy_exlogin(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
+{
+ struct qla2xxx_offld_chain *c = ptr;
+
+ if (!ha->exlogin_buf)
+ return ptr;
+
+ *last_chain = &c->type;
+
+ c->type = cpu_to_be32(DUMP_CHAIN_EXLOGIN);
+ c->chain_size = cpu_to_be32(sizeof(struct qla2xxx_offld_chain) +
+ ha->exlogin_size);
+ c->size = cpu_to_be32(ha->exlogin_size);
+ c->addr = cpu_to_be64(ha->exlogin_buf_dma);
+
+ ptr += sizeof(struct qla2xxx_offld_chain);
+ memcpy(ptr, ha->exlogin_buf, ha->exlogin_size);
+
+ return (char *)ptr + cpu_to_be32(c->size);
+}
+
+static inline void *
+qla81xx_copy_exchoffld(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
+{
+ struct qla2xxx_offld_chain *c = ptr;
+
+ if (!ha->exchoffld_buf)
+ return ptr;
+
+ *last_chain = &c->type;
+
+ c->type = cpu_to_be32(DUMP_CHAIN_EXCHG);
+ c->chain_size = cpu_to_be32(sizeof(struct qla2xxx_offld_chain) +
+ ha->exchoffld_size);
+ c->size = cpu_to_be32(ha->exchoffld_size);
+ c->addr = cpu_to_be64(ha->exchoffld_buf_dma);
+
+ ptr += sizeof(struct qla2xxx_offld_chain);
+ memcpy(ptr, ha->exchoffld_buf, ha->exchoffld_size);
+
+ return (char *)ptr + cpu_to_be32(c->size);
+}
+
+static inline void *
qla2xxx_copy_atioqueues(struct qla_hw_data *ha, void *ptr,
uint32_t **last_chain)
{
@@ -1606,6 +1651,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
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);
+ nxt_chain = qla25xx_copy_exlogin(ha, nxt_chain, &last_chain);
if (last_chain) {
ha->fw_dump->version |= htonl(DUMP_CHAIN_VARIANT);
*last_chain |= htonl(DUMP_CHAIN_LAST);
@@ -1932,6 +1978,8 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
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);
+ nxt_chain = qla25xx_copy_exlogin(ha, nxt_chain, &last_chain);
+ nxt_chain = qla81xx_copy_exchoffld(ha, nxt_chain, &last_chain);
if (last_chain) {
ha->fw_dump->version |= htonl(DUMP_CHAIN_VARIANT);
*last_chain |= htonl(DUMP_CHAIN_LAST);
@@ -2443,6 +2491,8 @@ copy_queue:
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);
+ nxt_chain = qla25xx_copy_exlogin(ha, nxt_chain, &last_chain);
+ nxt_chain = qla81xx_copy_exchoffld(ha, nxt_chain, &last_chain);
if (last_chain) {
ha->fw_dump->version |= htonl(DUMP_CHAIN_VARIANT);
*last_chain |= htonl(DUMP_CHAIN_LAST);
@@ -2713,3 +2763,104 @@ ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id,
buf + cnt, min(16U, size - cnt), false);
}
}
+
+/*
+ * This function is for formatting and logging log messages.
+ * It is to be used when vha is available. It formats the message
+ * and logs it to the messages file. All the messages will be logged
+ * irrespective of value of ql2xextended_error_logging.
+ * parameters:
+ * level: The level of the log messages to be printed in the
+ * messages file.
+ * vha: Pointer to the scsi_qla_host_t
+ * id: This is a unique id for the level. It identifies the
+ * part of the code from where the message originated.
+ * msg: The message to be displayed.
+ */
+void
+ql_log_qp(uint32_t level, struct qla_qpair *qpair, int32_t id,
+ const char *fmt, ...)
+{
+ va_list va;
+ struct va_format vaf;
+ char pbuf[128];
+
+ if (level > ql_errlev)
+ return;
+
+ if (qpair != NULL) {
+ const struct pci_dev *pdev = qpair->pdev;
+ /* <module-name> <msg-id>:<host> Message */
+ snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: ",
+ QL_MSGHDR, dev_name(&(pdev->dev)), id);
+ } else {
+ snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ",
+ QL_MSGHDR, "0000:00:00.0", id);
+ }
+ pbuf[sizeof(pbuf) - 1] = 0;
+
+ va_start(va, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &va;
+
+ switch (level) {
+ case ql_log_fatal: /* FATAL LOG */
+ pr_crit("%s%pV", pbuf, &vaf);
+ break;
+ case ql_log_warn:
+ pr_err("%s%pV", pbuf, &vaf);
+ break;
+ case ql_log_info:
+ pr_warn("%s%pV", pbuf, &vaf);
+ break;
+ default:
+ pr_info("%s%pV", pbuf, &vaf);
+ break;
+ }
+
+ va_end(va);
+}
+
+/*
+ * This function is for formatting and logging debug information.
+ * It is to be used when vha is available. It formats the message
+ * and logs it to the messages file.
+ * parameters:
+ * level: The level of the debug messages to be printed.
+ * If ql2xextended_error_logging value is correctly set,
+ * this message will appear in the messages file.
+ * vha: Pointer to the scsi_qla_host_t.
+ * id: This is a unique identifier for the level. It identifies the
+ * part of the code from where the message originated.
+ * msg: The message to be displayed.
+ */
+void
+ql_dbg_qp(uint32_t level, struct qla_qpair *qpair, int32_t id,
+ const char *fmt, ...)
+{
+ va_list va;
+ struct va_format vaf;
+
+ if (!ql_mask_match(level))
+ return;
+
+ va_start(va, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &va;
+
+ if (qpair != NULL) {
+ const struct pci_dev *pdev = qpair->pdev;
+ /* <module-name> <pci-name> <msg-id>:<host> Message */
+ pr_warn("%s [%s]-%04x: %pV",
+ QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset,
+ &vaf);
+ } else {
+ pr_warn("%s [%s]-%04x: : %pV",
+ QL_MSGHDR, "0000:00:00.0", id + ql_dbg_offset, &vaf);
+ }
+
+ va_end(va);
+
+}
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index c6bffe929fe7..8877aa97d829 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -232,6 +232,15 @@ struct qla2xxx_fce_chain {
uint32_t eregs[8];
};
+/* used by exchange off load and extended login offload */
+struct qla2xxx_offld_chain {
+ uint32_t type;
+ uint32_t chain_size;
+
+ uint32_t size;
+ u64 addr;
+};
+
struct qla2xxx_mq_chain {
uint32_t type;
uint32_t chain_size;
@@ -258,6 +267,8 @@ struct qla2xxx_mqueue_chain {
#define DUMP_CHAIN_FCE 0x7FFFFAF0
#define DUMP_CHAIN_MQ 0x7FFFFAF1
#define DUMP_CHAIN_QUEUE 0x7FFFFAF2
+#define DUMP_CHAIN_EXLOGIN 0x7FFFFAF3
+#define DUMP_CHAIN_EXCHG 0x7FFFFAF4
#define DUMP_CHAIN_LAST 0x80000000
struct qla2xxx_fw_dump {
@@ -313,12 +324,18 @@ void __attribute__((format (printf, 4, 5)))
ql_dbg(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...);
void __attribute__((format (printf, 4, 5)))
ql_dbg_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...);
+void __attribute__((format (printf, 4, 5)))
+ql_dbg_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...);
+
void __attribute__((format (printf, 4, 5)))
ql_log(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...);
void __attribute__((format (printf, 4, 5)))
ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...);
+void __attribute__((format (printf, 4, 5)))
+ql_log_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...);
+
/* Debug Levels */
/* The 0x40000000 is the max value any debug level can have
* as ql2xextended_error_logging is of type signed int
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index eddbc1218a39..0730b10b4280 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -37,6 +37,7 @@
#include "qla_bsg.h"
#include "qla_nx.h"
#include "qla_nx2.h"
+#include "qla_nvme.h"
#define QLA2XXX_DRIVER_NAME "qla2xxx"
#define QLA2XXX_APIDEV "ql2xapidev"
#define QLA2XXX_MANUFACTURER "QLogic Corporation"
@@ -252,6 +253,8 @@
#define NPH_F_PORT 0x7fe /* FFFFFE */
#define NPH_IP_BROADCAST 0x7ff /* FFFFFF */
+#define NPH_SNS_LID(ha) (IS_FWI2_CAPABLE(ha) ? NPH_SNS : SIMPLE_NAME_SERVER)
+
#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */
#include "qla_fw.h"
@@ -284,7 +287,7 @@ struct name_list_extended {
#define RESPONSE_ENTRY_CNT_MQ 128 /* Number of response entries.*/
#define ATIO_ENTRY_CNT_24XX 4096 /* Number of ATIO entries. */
#define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/
-#define EXTENDED_EXCH_ENTRY_CNT 32768 /* Entries for offload case */
+#define FW_DEF_EXCHANGES_CNT 2048
struct req_que;
struct qla_tgt_sess;
@@ -341,6 +344,7 @@ struct srb_iocb {
#define SRB_LOGIN_RETRIED BIT_0
#define SRB_LOGIN_COND_PLOGI BIT_1
#define SRB_LOGIN_SKIP_PRLI BIT_2
+#define SRB_LOGIN_NVME_PRLI BIT_3
uint16_t data[2];
u32 iop[2];
} logio;
@@ -409,6 +413,21 @@ struct srb_iocb {
struct {
struct imm_ntfy_from_isp *ntfy;
} nack;
+ struct {
+ __le16 comp_status;
+ uint16_t rsp_pyld_len;
+ uint8_t aen_op;
+ void *desc;
+
+ /* These are only used with ls4 requests */
+ int cmd_len;
+ int rsp_len;
+ dma_addr_t cmd_dma;
+ dma_addr_t rsp_dma;
+ enum nvmefc_fcp_datadir dir;
+ uint32_t dl;
+ uint32_t timeout_sec;
+ } nvme;
} u;
struct timer_list timer;
@@ -434,9 +453,24 @@ struct srb_iocb {
#define SRB_NACK_PLOGI 16
#define SRB_NACK_PRLI 17
#define SRB_NACK_LOGO 18
+#define SRB_NVME_CMD 19
+#define SRB_NVME_LS 20
+#define SRB_PRLI_CMD 21
+
+enum {
+ TYPE_SRB,
+ TYPE_TGT_CMD,
+};
typedef struct srb {
+ /*
+ * Do not move cmd_type field, it needs to
+ * line up with qla_tgt_cmd->cmd_type
+ */
+ uint8_t cmd_type;
+ uint8_t pad[3];
atomic_t ref_count;
+ wait_queue_head_t nvme_ls_waitQ;
struct fc_port *fcport;
struct scsi_qla_host *vha;
uint32_t handle;
@@ -1075,6 +1109,7 @@ struct mbx_cmd_32 {
#define MBX_1 BIT_1
#define MBX_0 BIT_0
+#define RNID_TYPE_PORT_LOGIN 0x7
#define RNID_TYPE_SET_VERSION 0x9
#define RNID_TYPE_ASIC_TEMP 0xC
@@ -2139,6 +2174,7 @@ typedef struct {
uint8_t fabric_port_name[WWN_SIZE];
uint16_t fp_speed;
uint8_t fc4_type;
+ uint8_t fc4f_nvme; /* nvme fc4 feature bits */
} sw_info_t;
/* FCP-4 types */
@@ -2167,7 +2203,8 @@ typedef enum {
FCT_SWITCH,
FCT_BROADCAST,
FCT_INITIATOR,
- FCT_TARGET
+ FCT_TARGET,
+ FCT_NVME
} fc_port_type_t;
enum qla_sess_deletion {
@@ -2224,10 +2261,12 @@ enum fcport_mgt_event {
FCME_RSCN,
FCME_GIDPN_DONE,
FCME_PLOGI_DONE, /* Initiator side sent LLIOCB */
+ FCME_PRLI_DONE,
FCME_GNL_DONE,
FCME_GPSC_DONE,
FCME_GPDB_DONE,
FCME_GPNID_DONE,
+ FCME_GFFID_DONE,
FCME_DELETE_DONE,
};
@@ -2261,6 +2300,17 @@ typedef struct fc_port {
unsigned int login_pause:1;
unsigned int login_succ:1;
+ struct work_struct nvme_del_work;
+ atomic_t nvme_ref_count;
+ wait_queue_head_t nvme_waitQ;
+ uint32_t nvme_prli_service_param;
+#define NVME_PRLI_SP_CONF BIT_7
+#define NVME_PRLI_SP_INITIATOR BIT_5
+#define NVME_PRLI_SP_TARGET BIT_4
+#define NVME_PRLI_SP_DISCOVERY BIT_3
+ uint8_t nvme_flag;
+#define NVME_FLAG_REGISTERED 4
+
struct fc_port *conflict;
unsigned char logout_completed;
int generation;
@@ -2293,6 +2343,7 @@ typedef struct fc_port {
u32 supported_classes;
uint8_t fc4_type;
+ uint8_t fc4f_nvme;
uint8_t scan_state;
unsigned long last_queue_full;
@@ -2300,6 +2351,8 @@ typedef struct fc_port {
uint16_t port_id;
+ struct nvme_fc_remote_port *nvme_remote_port;
+
unsigned long retry_delay_timestamp;
struct qla_tgt_sess *tgt_session;
struct ct_sns_desc ct_desc;
@@ -2732,7 +2785,7 @@ struct ct_sns_req {
struct {
uint8_t reserved;
- uint8_t port_name[3];
+ uint8_t port_id[3];
} gff_id;
struct {
@@ -2814,6 +2867,7 @@ struct ct_sns_rsp {
} gpsc;
#define GFF_FCP_SCSI_OFFSET 7
+#define GFF_NVME_OFFSET 23 /* type = 28h */
struct {
uint8_t fc4_features[128];
} gff_id;
@@ -3039,6 +3093,7 @@ enum qla_work_type {
QLA_EVT_GPNID_DONE,
QLA_EVT_NEW_SESS,
QLA_EVT_GPDB,
+ QLA_EVT_PRLI,
QLA_EVT_GPSC,
QLA_EVT_UPD_FCPORT,
QLA_EVT_GNL,
@@ -3169,6 +3224,21 @@ struct qla_tc_param {
#define QLA_PRECONFIG_VPORTS 32
#define QLA_MAX_VPORTS_QLA24XX 128
#define QLA_MAX_VPORTS_QLA25XX 256
+
+struct qla_tgt_counters {
+ uint64_t qla_core_sbt_cmd;
+ uint64_t core_qla_que_buf;
+ uint64_t qla_core_ret_ctio;
+ uint64_t core_qla_snd_status;
+ uint64_t qla_core_ret_sta_ctio;
+ uint64_t core_qla_free_cmd;
+ uint64_t num_q_full_sent;
+ uint64_t num_alloc_iocb_failed;
+ uint64_t num_term_xchg_sent;
+};
+
+struct qla_qpair;
+
/* Response queue data structure */
struct rsp_que {
dma_addr_t dma;
@@ -3188,6 +3258,7 @@ struct rsp_que {
struct qla_msix_entry *msix;
struct req_que *req;
srb_t *status_srb; /* status continuation entry */
+ struct qla_qpair *qpair;
dma_addr_t dma_fx00;
response_t *ring_fx00;
@@ -3228,6 +3299,15 @@ struct req_que {
struct qla_qpair {
spinlock_t qp_lock;
atomic_t ref_count;
+ uint32_t lun_cnt;
+ /*
+ * For qpair 0, qp_lock_ptr will point at hardware_lock due to
+ * legacy code. For other Qpair(s), it will point at qp_lock.
+ */
+ spinlock_t *qp_lock_ptr;
+ struct scsi_qla_host *vha;
+ u32 chip_reset;
+
/* distill these fields down to 'online=0/1'
* ha->flags.eeh_busy
* ha->flags.pci_channel_io_perm_failure
@@ -3237,14 +3317,18 @@ struct qla_qpair {
/* move vha->flags.difdix_supported here */
uint32_t difdix_supported:1;
uint32_t delete_in_progress:1;
+ uint32_t fw_started:1;
+ uint32_t enable_class_2:1;
+ uint32_t enable_explicit_conf:1;
+ uint32_t use_shadow_reg:1;
uint16_t id; /* qp number used with FW */
- uint16_t num_active_cmd; /* cmds down at firmware */
- cpumask_t cpu_mask; /* CPU mask for cpu affinity operation */
uint16_t vp_idx; /* vport ID */
-
mempool_t *srb_mempool;
+ struct pci_dev *pdev;
+ void (*reqq_start_iocbs)(struct qla_qpair *);
+
/* to do: New driver: move queues to here instead of pointers */
struct req_que *req;
struct rsp_que *rsp;
@@ -3253,7 +3337,9 @@ struct qla_qpair {
struct qla_hw_data *hw;
struct work_struct q_work;
struct list_head qp_list_elem; /* vha->qp_list */
- struct scsi_qla_host *vha;
+ struct list_head hints_list;
+ uint16_t cpuid;
+ struct qla_tgt_counters tgt_counters;
};
/* Place holder for FW buffer parameters */
@@ -3272,8 +3358,6 @@ struct scsi_qlt_host {
struct qlt_hw_data {
/* Protected by hw lock */
- uint32_t enable_class_2:1;
- uint32_t enable_explicit_conf:1;
uint32_t node_name_set:1;
dma_addr_t atio_dma; /* Physical address. */
@@ -3285,9 +3369,6 @@ struct qlt_hw_data {
uint32_t __iomem *atio_q_out;
struct qla_tgt_func_tmpl *tgt_ops;
- struct qla_tgt_cmd *cmds[DEFAULT_OUTSTANDING_COMMANDS];
- uint16_t current_handle;
-
struct qla_tgt_vp_map *tgt_vp_map;
int saved_set;
@@ -3302,6 +3383,7 @@ struct qlt_hw_data {
struct dentry *dfs_tgt_sess;
struct dentry *dfs_tgt_port_database;
+ struct dentry *dfs_naqp;
struct list_head q_full_list;
uint32_t num_pend_cmds;
@@ -3310,7 +3392,8 @@ struct qlt_hw_data {
spinlock_t q_full_lock;
uint32_t leak_exchg_thresh_hold;
spinlock_t sess_lock;
- int rspq_vector_cpuid;
+ int num_act_qpairs;
+#define DEFAULT_NAQP 2
spinlock_t atio_lock ____cacheline_aligned;
struct btree_head32 host_map;
};
@@ -3591,6 +3674,10 @@ struct qla_hw_data {
#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha))
#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_FAWWN_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define IS_EXCHG_OFFLD_CAPABLE(ha) \
+ (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define IS_EXLOGIN_OFFLD_CAPABLE(ha) \
+ (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
/* HBA serial number */
uint8_t serial0;
@@ -3927,24 +4014,11 @@ struct qla_hw_data {
struct work_struct board_disable;
struct mr_data_fx00 mr;
- uint32_t chip_reset;
struct qlt_hw_data tgt;
int allow_cna_fw_dump;
};
-struct qla_tgt_counters {
- uint64_t qla_core_sbt_cmd;
- uint64_t core_qla_que_buf;
- uint64_t qla_core_ret_ctio;
- uint64_t core_qla_snd_status;
- uint64_t qla_core_ret_sta_ctio;
- uint64_t core_qla_free_cmd;
- uint64_t num_q_full_sent;
- uint64_t num_alloc_iocb_failed;
- uint64_t num_term_xchg_sent;
-};
-
/*
* Qlogic scsi host structure
*/
@@ -3973,6 +4047,9 @@ typedef struct scsi_qla_host {
uint32_t fw_tgt_reported:1;
uint32_t bbcr_enable:1;
uint32_t qpairs_available:1;
+ uint32_t qpairs_req_created:1;
+ uint32_t qpairs_rsp_created:1;
+ uint32_t nvme_enabled:1;
} flags;
atomic_t loop_state;
@@ -4017,7 +4094,6 @@ typedef struct scsi_qla_host {
#define PFLG_DISCONNECTED 0 /* PCI device removed */
#define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */
#define PFLG_DRIVER_PROBING 2 /* PCI driver .probe */
-#define PCI_ERR 30
uint32_t device_flags;
#define SWITCH_FOUND BIT_0
@@ -4052,6 +4128,13 @@ typedef struct scsi_qla_host {
uint8_t port_name[WWN_SIZE];
uint8_t fabric_node_name[WWN_SIZE];
+ struct nvme_fc_local_port *nvme_local_port;
+ atomic_t nvme_ref_count;
+ wait_queue_head_t nvme_waitQ;
+ struct list_head nvme_rport_list;
+ atomic_t nvme_active_aen_cnt;
+ uint16_t nvme_last_rptd_aen;
+
uint16_t fcoe_vlan_id;
uint16_t fcoe_fcf_idx;
uint8_t fcoe_vn_port_mac[6];
@@ -4108,10 +4191,8 @@ typedef struct scsi_qla_host {
struct fc_host_statistics fc_host_stat;
struct qla_statistics qla_stats;
struct bidi_statistics bidi_stats;
-
atomic_t vref_count;
struct qla8044_reset_template reset_tmplt;
- struct qla_tgt_counters tgt_counters;
uint16_t bbcr;
struct name_list_extended gnl;
/* Count of active session/fcport */
@@ -4156,6 +4237,26 @@ struct qla2_sgx {
srb_t *sp;
};
+#define QLA_FW_STARTED(_ha) { \
+ int i; \
+ _ha->flags.fw_started = 1; \
+ _ha->base_qpair->fw_started = 1; \
+ for (i = 0; i < _ha->max_qpairs; i++) { \
+ if (_ha->queue_pair_map[i]) \
+ _ha->queue_pair_map[i]->fw_started = 1; \
+ } \
+}
+
+#define QLA_FW_STOPPED(_ha) { \
+ int i; \
+ _ha->flags.fw_started = 0; \
+ _ha->base_qpair->fw_started = 0; \
+ for (i = 0; i < _ha->max_qpairs; i++) { \
+ if (_ha->queue_pair_map[i]) \
+ _ha->queue_pair_map[i]->fw_started = 0; \
+ } \
+}
+
/*
* Macros to help code, maintain, etc.
*/
@@ -4199,6 +4300,25 @@ struct qla2_sgx {
#define QLA_QPAIR_MARK_NOT_BUSY(__qpair) \
atomic_dec(&__qpair->ref_count); \
+
+#define QLA_ENA_CONF(_ha) {\
+ int i;\
+ _ha->base_qpair->enable_explicit_conf = 1; \
+ for (i = 0; i < _ha->max_qpairs; i++) { \
+ if (_ha->queue_pair_map[i]) \
+ _ha->queue_pair_map[i]->enable_explicit_conf = 1; \
+ } \
+}
+
+#define QLA_DIS_CONF(_ha) {\
+ int i;\
+ _ha->base_qpair->enable_explicit_conf = 0; \
+ for (i = 0; i < _ha->max_qpairs; i++) { \
+ if (_ha->queue_pair_map[i]) \
+ _ha->queue_pair_map[i]->enable_explicit_conf = 0; \
+ } \
+}
+
/*
* qla2x00 local function return status codes
*/
@@ -4253,6 +4373,10 @@ enum nexus_wait_type {
WAIT_LUN,
};
+#define USER_CTRL_IRQ(_ha) (ql2xuctrlirq && QLA_TGT_MODE_ENABLED() && \
+ (IS_QLA27XX(_ha) || IS_QLA83XX(_ha)))
+
+#include "qla_target.h"
#include "qla_gbl.h"
#include "qla_dbg.h"
#include "qla_inline.h"
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 989e17b0758c..d231e7156134 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -70,7 +70,7 @@ qla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused)
qla2x00_gid_list_size(ha),
&gid_list_dma, GFP_KERNEL);
if (!gid_list) {
- ql_dbg(ql_dbg_user, vha, 0x705c,
+ ql_dbg(ql_dbg_user, vha, 0x7018,
"DMA allocation failed for %u\n",
qla2x00_gid_list_size(ha));
return 0;
@@ -164,26 +164,56 @@ static int
qla_dfs_tgt_counters_show(struct seq_file *s, void *unused)
{
struct scsi_qla_host *vha = s->private;
+ struct qla_qpair *qpair = vha->hw->base_qpair;
+ uint64_t qla_core_sbt_cmd, core_qla_que_buf, qla_core_ret_ctio,
+ core_qla_snd_status, qla_core_ret_sta_ctio, core_qla_free_cmd,
+ num_q_full_sent, num_alloc_iocb_failed, num_term_xchg_sent;
+ u16 i;
+
+ qla_core_sbt_cmd = qpair->tgt_counters.qla_core_sbt_cmd;
+ core_qla_que_buf = qpair->tgt_counters.core_qla_que_buf;
+ qla_core_ret_ctio = qpair->tgt_counters.qla_core_ret_ctio;
+ core_qla_snd_status = qpair->tgt_counters.core_qla_snd_status;
+ qla_core_ret_sta_ctio = qpair->tgt_counters.qla_core_ret_sta_ctio;
+ core_qla_free_cmd = qpair->tgt_counters.core_qla_free_cmd;
+ num_q_full_sent = qpair->tgt_counters.num_q_full_sent;
+ num_alloc_iocb_failed = qpair->tgt_counters.num_alloc_iocb_failed;
+ num_term_xchg_sent = qpair->tgt_counters.num_term_xchg_sent;
+
+ for (i = 0; i < vha->hw->max_qpairs; i++) {
+ qpair = vha->hw->queue_pair_map[i];
+ qla_core_sbt_cmd += qpair->tgt_counters.qla_core_sbt_cmd;
+ core_qla_que_buf += qpair->tgt_counters.core_qla_que_buf;
+ qla_core_ret_ctio += qpair->tgt_counters.qla_core_ret_ctio;
+ core_qla_snd_status += qpair->tgt_counters.core_qla_snd_status;
+ qla_core_ret_sta_ctio +=
+ qpair->tgt_counters.qla_core_ret_sta_ctio;
+ core_qla_free_cmd += qpair->tgt_counters.core_qla_free_cmd;
+ num_q_full_sent += qpair->tgt_counters.num_q_full_sent;
+ num_alloc_iocb_failed +=
+ qpair->tgt_counters.num_alloc_iocb_failed;
+ num_term_xchg_sent += qpair->tgt_counters.num_term_xchg_sent;
+ }
seq_puts(s, "Target Counters\n");
seq_printf(s, "qla_core_sbt_cmd = %lld\n",
- vha->tgt_counters.qla_core_sbt_cmd);
+ qla_core_sbt_cmd);
seq_printf(s, "qla_core_ret_sta_ctio = %lld\n",
- vha->tgt_counters.qla_core_ret_sta_ctio);
+ qla_core_ret_sta_ctio);
seq_printf(s, "qla_core_ret_ctio = %lld\n",
- vha->tgt_counters.qla_core_ret_ctio);
+ qla_core_ret_ctio);
seq_printf(s, "core_qla_que_buf = %lld\n",
- vha->tgt_counters.core_qla_que_buf);
+ core_qla_que_buf);
seq_printf(s, "core_qla_snd_status = %lld\n",
- vha->tgt_counters.core_qla_snd_status);
+ core_qla_snd_status);
seq_printf(s, "core_qla_free_cmd = %lld\n",
- vha->tgt_counters.core_qla_free_cmd);
+ core_qla_free_cmd);
seq_printf(s, "num alloc iocb failed = %lld\n",
- vha->tgt_counters.num_alloc_iocb_failed);
+ num_alloc_iocb_failed);
seq_printf(s, "num term exchange sent = %lld\n",
- vha->tgt_counters.num_term_xchg_sent);
+ num_term_xchg_sent);
seq_printf(s, "num Q full sent = %lld\n",
- vha->tgt_counters.num_q_full_sent);
+ num_q_full_sent);
/* DIF stats */
seq_printf(s, "DIF Inp Bytes = %lld\n",
@@ -314,6 +344,81 @@ static const struct file_operations dfs_fce_ops = {
.release = qla2x00_dfs_fce_release,
};
+static int
+qla_dfs_naqp_show(struct seq_file *s, void *unused)
+{
+ struct scsi_qla_host *vha = s->private;
+ struct qla_hw_data *ha = vha->hw;
+
+ seq_printf(s, "%d\n", ha->tgt.num_act_qpairs);
+ return 0;
+}
+
+static int
+qla_dfs_naqp_open(struct inode *inode, struct file *file)
+{
+ struct scsi_qla_host *vha = inode->i_private;
+
+ return single_open(file, qla_dfs_naqp_show, vha);
+}
+
+static ssize_t
+qla_dfs_naqp_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *pos)
+{
+ struct seq_file *s = file->private_data;
+ struct scsi_qla_host *vha = s->private;
+ struct qla_hw_data *ha = vha->hw;
+ char *buf;
+ int rc = 0;
+ unsigned long num_act_qp;
+
+ if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha))) {
+ pr_err("host%ld: this adapter does not support Multi Q.",
+ vha->host_no);
+ return -EINVAL;
+ }
+
+ if (!vha->flags.qpairs_available) {
+ pr_err("host%ld: Driver is not setup with Multi Q.",
+ vha->host_no);
+ return -EINVAL;
+ }
+ buf = memdup_user_nul(buffer, count);
+ if (IS_ERR(buf)) {
+ pr_err("host%ld: fail to copy user buffer.",
+ vha->host_no);
+ return PTR_ERR(buf);
+ }
+
+ num_act_qp = simple_strtoul(buf, NULL, 0);
+
+ if (num_act_qp >= vha->hw->max_qpairs) {
+ pr_err("User set invalid number of qpairs %lu. Max = %d",
+ num_act_qp, vha->hw->max_qpairs);
+ rc = -EINVAL;
+ goto out_free;
+ }
+
+ if (num_act_qp != ha->tgt.num_act_qpairs) {
+ ha->tgt.num_act_qpairs = num_act_qp;
+ qlt_clr_qp_table(vha);
+ }
+ rc = count;
+out_free:
+ kfree(buf);
+ return rc;
+}
+
+static const struct file_operations dfs_naqp_ops = {
+ .open = qla_dfs_naqp_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = qla_dfs_naqp_write,
+};
+
+
int
qla2x00_dfs_setup(scsi_qla_host_t *vha)
{
@@ -370,7 +475,7 @@ create_nodes:
ha->tgt.dfs_tgt_port_database = debugfs_create_file("tgt_port_database",
S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_port_database_ops);
if (!ha->tgt.dfs_tgt_port_database) {
- ql_log(ql_log_warn, vha, 0xffff,
+ ql_log(ql_log_warn, vha, 0xd03f,
"Unable to create debugFS tgt_port_database node.\n");
goto out;
}
@@ -386,11 +491,20 @@ create_nodes:
ha->tgt.dfs_tgt_sess = debugfs_create_file("tgt_sess",
S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_sess_ops);
if (!ha->tgt.dfs_tgt_sess) {
- ql_log(ql_log_warn, vha, 0xffff,
- "Unable to create debugFS tgt_sess node.\n");
+ ql_log(ql_log_warn, vha, 0xd040,
+ "Unable to create debugFS tgt_sess node.\n");
goto out;
}
+ if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) {
+ ha->tgt.dfs_naqp = debugfs_create_file("naqp",
+ 0400, ha->dfs_dir, vha, &dfs_naqp_ops);
+ if (!ha->tgt.dfs_naqp) {
+ ql_log(ql_log_warn, vha, 0xd011,
+ "Unable to create debugFS naqp node.\n");
+ goto out;
+ }
+ }
out:
return 0;
}
@@ -400,6 +514,11 @@ qla2x00_dfs_remove(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
+ if (ha->tgt.dfs_naqp) {
+ debugfs_remove(ha->tgt.dfs_naqp);
+ ha->tgt.dfs_naqp = NULL;
+ }
+
if (ha->tgt.dfs_tgt_sess) {
debugfs_remove(ha->tgt.dfs_tgt_sess);
ha->tgt.dfs_tgt_sess = NULL;
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 1f808928763b..b9c9886e8b1d 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -7,6 +7,9 @@
#ifndef __QLA_FW_H
#define __QLA_FW_H
+#include <linux/nvme.h>
+#include <linux/nvme-fc.h>
+
#define MBS_CHECKSUM_ERROR 0x4010
#define MBS_INVALID_PRODUCT_KEY 0x4020
@@ -37,6 +40,12 @@ struct port_database_24xx {
#define PDF_CLASS_2 BIT_4
#define PDF_HARD_ADDR BIT_1
+ /*
+ * for NVMe, the login_state field has been
+ * split into nibbles.
+ * The lower nibble is for FCP.
+ * The upper nibble is for NVMe.
+ */
uint8_t current_login_state;
uint8_t last_login_state;
#define PDS_PLOGI_PENDING 0x03
@@ -69,7 +78,11 @@ struct port_database_24xx {
uint8_t port_name[WWN_SIZE];
uint8_t node_name[WWN_SIZE];
- uint8_t reserved_3[24];
+ uint8_t reserved_3[4];
+ uint16_t prli_nvme_svc_param_word_0; /* Bits 15-0 of word 0 */
+ uint16_t prli_nvme_svc_param_word_3; /* Bits 15-0 of word 3 */
+ uint16_t nvme_first_burst_size;
+ uint8_t reserved_4[14];
};
/*
@@ -593,9 +606,14 @@ struct sts_entry_24xx {
uint32_t residual_len; /* FW calc residual transfer length. */
- uint16_t reserved_1;
+ union {
+ uint16_t reserved_1;
+ uint16_t nvme_rsp_pyld_len;
+ };
+
uint16_t state_flags; /* State flags. */
#define SF_TRANSFERRED_DATA BIT_11
+#define SF_NVME_ERSP BIT_6
#define SF_FCP_RSP_DMA BIT_0
uint16_t retry_delay;
@@ -605,8 +623,16 @@ struct sts_entry_24xx {
uint32_t rsp_residual_count; /* FCP RSP residual count. */
uint32_t sense_len; /* FCP SENSE length. */
- uint32_t rsp_data_len; /* FCP response data length. */
- uint8_t data[28]; /* FCP response/sense information. */
+
+ union {
+ struct {
+ uint32_t rsp_data_len; /* FCP response data length */
+ uint8_t data[28]; /* FCP rsp/sense information */
+ };
+ struct nvme_fc_ersp_iu nvme_ersp;
+ uint8_t nvme_ersp_data[32];
+ };
+
/*
* If DIF Error is set in comp_status, these additional fields are
* defined:
@@ -819,6 +845,7 @@ struct logio_entry_24xx {
#define LCF_CLASS_2 BIT_8 /* Enable class 2 during PLOGI. */
#define LCF_FREE_NPORT BIT_7 /* Release NPORT handle after LOGO. */
#define LCF_EXPL_LOGO BIT_6 /* Perform an explicit LOGO. */
+#define LCF_NVME_PRLI BIT_6 /* Perform NVME FC4 PRLI */
#define LCF_SKIP_PRLI BIT_5 /* Skip PRLI after PLOGI. */
#define LCF_IMPL_LOGO_ALL BIT_5 /* Implicit LOGO to all ports. */
#define LCF_COND_PLOGI BIT_4 /* PLOGI only if not logged-in. */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 5b2451745e9f..cadb6e3baacc 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -10,6 +10,17 @@
#include <linux/interrupt.h>
/*
+ * Global functions prototype in qla_nvme.c source file.
+ */
+extern void qla_nvme_register_hba(scsi_qla_host_t *);
+extern int qla_nvme_register_remote(scsi_qla_host_t *, fc_port_t *);
+extern void qla_nvme_delete(scsi_qla_host_t *);
+extern void qla_nvme_abort(struct qla_hw_data *, srb_t *sp);
+extern void qla24xx_nvme_ls4_iocb(scsi_qla_host_t *, struct pt_ls4_request *,
+ struct req_que *);
+extern void qla24xx_async_gffid_sp_done(void *, int);
+
+/*
* Global Function Prototypes in qla_init.c source file.
*/
extern int qla2x00_initialize_adapter(scsi_qla_host_t *);
@@ -77,8 +88,7 @@ struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
enum qla_work_type);
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
int qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e);
-extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
-extern void *qla2x00_alloc_iocbs_ready(struct scsi_qla_host *, srb_t *);
+extern void *qla2x00_alloc_iocbs_ready(struct qla_qpair *, srb_t *);
extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
extern fc_port_t *
@@ -96,10 +106,11 @@ qla2x00_alloc_outstanding_cmds(struct qla_hw_data *, struct req_que *);
extern int qla2x00_init_rings(scsi_qla_host_t *);
extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *);
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
- int, int);
+ int, int, bool);
extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);
void qla2x00_fcport_event_handler(scsi_qla_host_t *, struct event_arg *);
int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
+int qla24xx_async_prli(struct scsi_qla_host *, fc_port_t *);
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
struct imm_ntfy_from_isp *, int);
int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
@@ -137,8 +148,11 @@ extern int ql2xmdcapmask;
extern int ql2xmdenable;
extern int ql2xexlogins;
extern int ql2xexchoffld;
+extern int ql2xiniexchg;
extern int ql2xfwholdabts;
extern int ql2xmvasynctoatio;
+extern int ql2xuctrlirq;
+extern int ql2xnvmeenable;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -254,7 +268,8 @@ extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t);
extern int qla2xxx_dif_start_scsi_mq(srb_t *);
extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *);
-extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *);
+extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
+extern void *__qla2x00_alloc_iocbs(struct qla_qpair *, srb_t *);
extern int qla2x00_issue_marker(scsi_qla_host_t *, int);
extern int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *, srb_t *,
uint32_t *, uint16_t, struct qla_tc_param *);
@@ -604,7 +619,7 @@ extern int qla2x00_gpn_id(scsi_qla_host_t *, sw_info_t *);
extern int qla2x00_gnn_id(scsi_qla_host_t *, sw_info_t *);
extern void qla2x00_gff_id(scsi_qla_host_t *, sw_info_t *);
extern int qla2x00_rft_id(scsi_qla_host_t *);
-extern int qla2x00_rff_id(scsi_qla_host_t *);
+extern int qla2x00_rff_id(scsi_qla_host_t *, u8);
extern int qla2x00_rnn_id(scsi_qla_host_t *);
extern int qla2x00_rsnn_nn(scsi_qla_host_t *);
extern void *qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
@@ -630,7 +645,8 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);
int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
-
+void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea);
+int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport);
/*
* Global Function Prototypes in qla_attr.c source file.
*/
@@ -662,9 +678,9 @@ extern int qla25xx_request_irq(struct qla_hw_data *, struct qla_qpair *,
extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *);
extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *);
extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t,
- uint16_t, int, uint8_t);
+ uint16_t, int, uint8_t, bool);
extern int qla25xx_create_rsp_que(struct qla_hw_data *, uint16_t, uint8_t,
- uint16_t, struct qla_qpair *);
+ uint16_t, struct qla_qpair *, bool);
extern void qla2x00_init_response_q_entries(struct rsp_que *);
extern int qla25xx_delete_req_que(struct scsi_qla_host *, struct req_que *);
@@ -833,14 +849,13 @@ extern irqreturn_t qla8044_intr_handler(int, void *);
extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t);
extern int qla8044_abort_isp(scsi_qla_host_t *);
extern int qla8044_check_fw_alive(struct scsi_qla_host *);
-
-extern void qlt_host_reset_handler(struct qla_hw_data *ha);
extern int qla_get_exlogin_status(scsi_qla_host_t *, uint16_t *,
uint16_t *);
extern int qla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr);
extern int qla_get_exchoffld_status(scsi_qla_host_t *, uint16_t *, uint16_t *);
-extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *, dma_addr_t);
-extern void qlt_handle_abts_recv(struct scsi_qla_host *, response_t *);
+extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *);
+extern void qlt_handle_abts_recv(struct scsi_qla_host *, struct rsp_que *,
+ response_t *);
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
struct imm_ntfy_from_isp *, int);
@@ -856,5 +871,6 @@ void qla24xx_delete_sess_fn(struct work_struct *);
void qlt_unknown_atio_work_fn(struct work_struct *);
void qlt_update_host_map(struct scsi_qla_host *, port_id_t);
void qlt_remove_target_resources(struct qla_hw_data *);
+void qlt_clr_qp_table(struct scsi_qla_host *vha);
#endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 9bc9aa9e164a..b323a7c71eda 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -124,6 +124,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
int rval;
uint16_t comp_status;
struct qla_hw_data *ha = vha->hw;
+ bool lid_is_sns = false;
rval = QLA_FUNCTION_FAILED;
if (ms_pkt->entry_status != 0) {
@@ -155,6 +156,25 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
} else
rval = QLA_SUCCESS;
break;
+ case CS_PORT_LOGGED_OUT:
+ if (IS_FWI2_CAPABLE(ha)) {
+ if (le16_to_cpu(ms_pkt->loop_id.extended) ==
+ NPH_SNS)
+ lid_is_sns = true;
+ } else {
+ if (le16_to_cpu(ms_pkt->loop_id.extended) ==
+ SIMPLE_NAME_SERVER)
+ lid_is_sns = true;
+ }
+ if (lid_is_sns) {
+ ql_dbg(ql_dbg_async, vha, 0x502b,
+ "%s failed, Name server has logged out",
+ routine);
+ rval = QLA_NOT_LOGGED_IN;
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ }
+ break;
default:
ql_dbg(ql_dbg_disc, vha, 0x2033,
"%s failed, completion status (%x) on port_id: "
@@ -530,6 +550,8 @@ qla2x00_rft_id(scsi_qla_host_t *vha)
ct_req->req.rft_id.fc4_types[2] = 0x01; /* FCP-3 */
+ if (vha->flags.nvme_enabled)
+ ct_req->req.rft_id.fc4_types[6] = 1; /* NVMe type 28h */
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
sizeof(ms_iocb_entry_t));
@@ -555,7 +577,7 @@ qla2x00_rft_id(scsi_qla_host_t *vha)
* Returns 0 on success.
*/
int
-qla2x00_rff_id(scsi_qla_host_t *vha)
+qla2x00_rff_id(scsi_qla_host_t *vha, u8 type)
{
int rval;
struct qla_hw_data *ha = vha->hw;
@@ -593,7 +615,7 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
qlt_rff_id(vha, ct_req);
- ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */
+ ct_req->req.rff_id.fc4_type = type; /* SCSI - FCP */
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
@@ -2004,7 +2026,7 @@ qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- ql_dbg(ql_dbg_disc, vha, 0x20b1,
+ ql_dbg(ql_dbg_disc, vha, 0x201b,
"Vendor Identifier = %s.\n", eiter->a.vendor_identifier);
/* Update MS request size. */
@@ -2144,6 +2166,13 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
eiter->a.fc4_types[2],
eiter->a.fc4_types[1]);
+ if (vha->flags.nvme_enabled) {
+ eiter->a.fc4_types[6] = 1; /* NVMe type 28h */
+ ql_dbg(ql_dbg_disc, vha, 0x211f,
+ "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",
+ eiter->a.fc4_types[6]);
+ }
+
/* Supported speed. */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
@@ -2216,7 +2245,7 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
}
size += 4 + 4;
- ql_dbg(ql_dbg_disc, vha, 0x20bc,
+ ql_dbg(ql_dbg_disc, vha, 0x2017,
"Current_Speed = %x.\n", eiter->a.cur_speed);
/* Max frame size. */
@@ -2261,7 +2290,7 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen;
- ql_dbg(ql_dbg_disc, vha, 0x203d,
+ ql_dbg(ql_dbg_disc, vha, 0x201a,
"HostName=%s.\n", eiter->a.host_name);
/* Node Name */
@@ -2341,6 +2370,15 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
"Port Active FC4 Type = %02x %02x.\n",
eiter->a.port_fc4_type[2], eiter->a.port_fc4_type[1]);
+ if (vha->flags.nvme_enabled) {
+ eiter->a.port_fc4_type[4] = 0;
+ eiter->a.port_fc4_type[5] = 0;
+ eiter->a.port_fc4_type[6] = 1; /* NVMe type 28h */
+ ql_dbg(ql_dbg_disc, vha, 0x2120,
+ "NVME Port Active FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",
+ eiter->a.port_fc4_type[6]);
+ }
+
/* Port State */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_PORT_STATE);
@@ -2368,13 +2406,13 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
eiter->len = cpu_to_be16(4 + 4);
size += 4 + 4;
- ql_dbg(ql_dbg_disc, vha, 0x20c8,
+ ql_dbg(ql_dbg_disc, vha, 0x201c,
"Port Id = %x.\n", eiter->a.port_id);
/* Update MS request size. */
qla2x00_update_ms_fdmi_iocb(vha, size + 16);
- ql_dbg(ql_dbg_disc, vha, 0x203e,
+ ql_dbg(ql_dbg_disc, vha, 0x2018,
"RPA portname= %8phN size=%d.\n", ct_req->req.rpa.port_name, size);
ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ca,
entries, size);
@@ -2734,6 +2772,10 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
list[i].fc4_type = FC4_TYPE_FCP_SCSI;
else
list[i].fc4_type = FC4_TYPE_OTHER;
+
+ list[i].fc4f_nvme =
+ ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
+ list[i].fc4f_nvme &= 0xf;
}
/* Last device exit. */
@@ -2747,13 +2789,13 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
{
fc_port_t *fcport = ea->fcport;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %8phC login state %d \n",
- __func__, fcport->port_name, fcport->fw_login_state);
+ ql_dbg(ql_dbg_disc, vha, 0x201d,
+ "%s %8phC login state %d\n",
+ __func__, fcport->port_name, fcport->fw_login_state);
if (ea->sp->gen2 != fcport->login_gen) {
/* PLOGI/PRLI/LOGO came in while cmd was out.*/
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x201e,
"%s %8phC generation changed rscn %d|%d login %d|%d \n",
__func__, fcport->port_name, fcport->last_rscn_gen,
fcport->rscn_gen, fcport->last_login_gen, fcport->login_gen);
@@ -2777,7 +2819,7 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
if (atomic_read(&fcport->state) ==
FCS_ONLINE)
break;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x201f,
"%s %d %8phC post gnl\n",
__func__, __LINE__, fcport->port_name);
qla24xx_post_gnl_work(vha, fcport);
@@ -2786,14 +2828,14 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
} else { /* fcport->d_id.b24 != ea->id.b24 */
fcport->d_id.b24 = ea->id.b24;
if (fcport->deleted == QLA_SESS_DELETED) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x2021,
"%s %d %8phC post del sess\n",
__func__, __LINE__, fcport->port_name);
qlt_schedule_sess_for_deletion_lock(fcport);
}
}
} else { /* ea->sp->gen1 != fcport->rscn_gen */
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x2022,
"%s %d %8phC post gidpn\n",
__func__, __LINE__, fcport->port_name);
/* rscn came in while cmd was out */
@@ -2803,18 +2845,18 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
/* cable pulled */
if (ea->sp->gen1 == fcport->rscn_gen) {
if (ea->sp->gen2 == fcport->login_gen) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x2042,
"%s %d %8phC post del sess\n", __func__,
__LINE__, fcport->port_name);
qlt_schedule_sess_for_deletion_lock(fcport);
} else {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x2045,
"%s %d %8phC login\n", __func__, __LINE__,
fcport->port_name);
qla24xx_fcport_handle_login(vha, fcport);
}
} else {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x2049,
"%s %d %8phC post gidpn\n", __func__, __LINE__,
fcport->port_name);
qla24xx_post_gidpn_work(vha, fcport);
@@ -2841,7 +2883,7 @@ static void qla2x00_async_gidpn_sp_done(void *s, int res)
ea.rc = res;
ea.event = FCME_GIDPN_DONE;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x204f,
"Async done-%s res %x, WWPN %8phC ID %3phC \n",
sp->name, res, fcport->port_name, id);
@@ -2897,11 +2939,11 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
if (rval != QLA_SUCCESS)
goto done_free_sp;
- ql_dbg(ql_dbg_disc, vha, 0x206f,
- "Async-%s - %8phC hdl=%x loopid=%x portid %02x%02x%02x.\n",
- sp->name, fcport->port_name,
- sp->handle, fcport->loop_id, fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa);
+ ql_dbg(ql_dbg_disc, vha, 0x20a4,
+ "Async-%s - %8phC hdl=%x loopid=%x portid %02x%02x%02x.\n",
+ sp->name, fcport->port_name,
+ sp->handle, fcport->loop_id, fcport->d_id.b.domain,
+ fcport->d_id.b.area, fcport->d_id.b.al_pa);
return rval;
done_free_sp:
@@ -2952,7 +2994,7 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x2053,
"Async done-%s res %x, WWPN %8phC \n",
sp->name, res, fcport->port_name);
@@ -2965,10 +3007,9 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
if ((ct_rsp->header.reason_code ==
CT_REASON_INVALID_COMMAND_CODE) ||
(ct_rsp->header.reason_code ==
- CT_REASON_COMMAND_UNSUPPORTED)) {
- ql_dbg(ql_dbg_disc, vha, 0x205a,
- "GPSC command unsupported, disabling "
- "query.\n");
+ CT_REASON_COMMAND_UNSUPPORTED)) {
+ ql_dbg(ql_dbg_disc, vha, 0x2019,
+ "GPSC command unsupported, disabling query.\n");
ha->flags.gpsc_supported = 0;
res = QLA_SUCCESS;
}
@@ -2997,12 +3038,11 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
break;
}
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n",
- sp->name,
- fcport->fabric_port_name,
- be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
- be16_to_cpu(ct_rsp->rsp.gpsc.speed));
+ ql_dbg(ql_dbg_disc, vha, 0x2054,
+ "Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n",
+ sp->name, fcport->fabric_port_name,
+ be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
+ be16_to_cpu(ct_rsp->rsp.gpsc.speed));
}
done:
memset(&ea, 0, sizeof(ea));
@@ -3058,11 +3098,11 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
if (rval != QLA_SUCCESS)
goto done_free_sp;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x.\n",
- sp->name, fcport->port_name, sp->handle,
- fcport->loop_id, fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa);
+ ql_dbg(ql_dbg_disc, vha, 0x205e,
+ "Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x.\n",
+ sp->name, fcport->port_name, sp->handle,
+ fcport->loop_id, fcport->d_id.b.domain,
+ fcport->d_id.b.area, fcport->d_id.b.al_pa);
return rval;
done_free_sp:
@@ -3118,21 +3158,32 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
if (fcport) {
/* cable moved. just plugged in */
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post del sess\n",
- __func__, __LINE__, fcport->port_name);
-
fcport->rscn_gen++;
fcport->d_id = ea->id;
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->flags |= FCF_FABRIC_DEVICE;
- qlt_schedule_sess_for_deletion_lock(fcport);
+ switch (fcport->disc_state) {
+ case DSC_DELETED:
+ ql_dbg(ql_dbg_disc, vha, 0x210d,
+ "%s %d %8phC login\n", __func__, __LINE__,
+ fcport->port_name);
+ qla24xx_fcport_handle_login(vha, fcport);
+ break;
+ case DSC_DELETE_PEND:
+ break;
+ default:
+ ql_dbg(ql_dbg_disc, vha, 0x2064,
+ "%s %d %8phC post del sess\n",
+ __func__, __LINE__, fcport->port_name);
+ qlt_schedule_sess_for_deletion_lock(fcport);
+ break;
+ }
} else {
/* create new fcport */
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post new sess\n",
- __func__, __LINE__, ea->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x2065,
+ "%s %d %8phC post new sess\n",
+ __func__, __LINE__, ea->port_name);
qla24xx_post_newsess_work(vha, &ea->id, ea->port_name, NULL);
}
@@ -3149,10 +3200,10 @@ static void qla2x00_async_gpnid_sp_done(void *s, int res)
struct event_arg ea;
struct qla_work_evt *e;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async done-%s res %x ID %3phC. %8phC\n",
- sp->name, res, ct_req->req.port_id.port_id,
- ct_rsp->rsp.gpn_id.port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x2066,
+ "Async done-%s res %x ID %3phC. %8phC\n",
+ sp->name, res, ct_req->req.port_id.port_id,
+ ct_rsp->rsp.gpn_id.port_name);
memset(&ea, 0, sizeof(ea));
memcpy(ea.port_name, ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
@@ -3214,8 +3265,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
GFP_KERNEL);
if (!sp->u.iocb_cmd.u.ctarg.req) {
- ql_log(ql_log_warn, vha, 0xffff,
- "Failed to allocate ct_sns request.\n");
+ ql_log(ql_log_warn, vha, 0xd041,
+ "Failed to allocate ct_sns request.\n");
goto done_free_sp;
}
@@ -3223,8 +3274,8 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
GFP_KERNEL);
if (!sp->u.iocb_cmd.u.ctarg.rsp) {
- ql_log(ql_log_warn, vha, 0xffff,
- "Failed to allocate ct_sns request.\n");
+ ql_log(ql_log_warn, vha, 0xd042,
+ "Failed to allocate ct_sns request.\n");
goto done_free_sp;
}
@@ -3251,9 +3302,9 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
if (rval != QLA_SUCCESS)
goto done_free_sp;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s hdl=%x ID %3phC.\n", sp->name,
- sp->handle, ct_req->req.port_id.port_id);
+ ql_dbg(ql_dbg_disc, vha, 0x2067,
+ "Async-%s hdl=%x ID %3phC.\n", sp->name,
+ sp->handle, ct_req->req.port_id.port_id);
return rval;
done_free_sp:
@@ -3276,3 +3327,111 @@ done_free_sp:
done:
return rval;
}
+
+void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+ fc_port_t *fcport = ea->fcport;
+
+ qla24xx_post_gnl_work(vha, fcport);
+}
+
+void qla24xx_async_gffid_sp_done(void *s, int res)
+{
+ struct srb *sp = s;
+ struct scsi_qla_host *vha = sp->vha;
+ fc_port_t *fcport = sp->fcport;
+ struct ct_sns_rsp *ct_rsp;
+ struct event_arg ea;
+
+ ql_dbg(ql_dbg_disc, vha, 0x2133,
+ "Async done-%s res %x ID %x. %8phC\n",
+ sp->name, res, fcport->d_id.b24, fcport->port_name);
+
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
+ /*
+ * FC-GS-7, 5.2.3.12 FC-4 Features - format
+ * The format of the FC-4 Features object, as defined by the FC-4,
+ * Shall be an array of 4-bit values, one for each type code value
+ */
+ if (!res) {
+ if (ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET] & 0xf) {
+ /* w1 b00:03 */
+ fcport->fc4_type =
+ ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
+ fcport->fc4_type &= 0xf;
+ }
+
+ if (ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET] & 0xf) {
+ /* w5 [00:03]/28h */
+ fcport->fc4f_nvme =
+ ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
+ fcport->fc4f_nvme &= 0xf;
+ }
+ }
+
+ memset(&ea, 0, sizeof(ea));
+ ea.sp = sp;
+ ea.fcport = sp->fcport;
+ ea.rc = res;
+ ea.event = FCME_GFFID_DONE;
+
+ qla2x00_fcport_event_handler(vha, &ea);
+ sp->free(sp);
+}
+
+/* Get FC4 Feature with Nport ID. */
+int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
+{
+ int rval = QLA_FUNCTION_FAILED;
+ struct ct_sns_req *ct_req;
+ srb_t *sp;
+
+ if (!vha->flags.online)
+ return rval;
+
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ return rval;
+
+ fcport->flags |= FCF_ASYNC_SENT;
+ sp->type = SRB_CT_PTHRU_CMD;
+ sp->name = "gffid";
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
+
+ qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+ /* CT_IU preamble */
+ ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFF_ID_CMD,
+ GFF_ID_RSP_SIZE);
+
+ ct_req->req.gff_id.port_id[0] = fcport->d_id.b.domain;
+ ct_req->req.gff_id.port_id[1] = fcport->d_id.b.area;
+ ct_req->req.gff_id.port_id[2] = fcport->d_id.b.al_pa;
+
+ sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
+ sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
+ sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
+ sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
+ sp->u.iocb_cmd.u.ctarg.req_size = GFF_ID_REQ_SIZE;
+ sp->u.iocb_cmd.u.ctarg.rsp_size = GFF_ID_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+ sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+ sp->done = qla24xx_async_gffid_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+ goto done_free_sp;
+
+ ql_dbg(ql_dbg_disc, vha, 0x2132,
+ "Async-%s hdl=%x %8phC.\n", sp->name,
+ sp->handle, fcport->port_name);
+
+ return rval;
+done_free_sp:
+ sp->free(sp);
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 0391fc317003..072ad1aa5505 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -37,8 +37,11 @@ static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
static int qla84xx_init_chip(scsi_qla_host_t *);
static int qla25xx_init_queues(struct qla_hw_data *);
static int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
+static int qla24xx_post_prli_work(struct scsi_qla_host*, fc_port_t *);
static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
struct event_arg *);
+static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
+ struct event_arg *);
/* SRB Extensions ---------------------------------------------------------- */
@@ -141,7 +144,7 @@ qla2x00_async_login_sp_done(void *ptr, int res)
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct event_arg ea;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20dd,
"%s %8phC res %d \n", __func__, sp->fcport->port_name, res);
sp->fcport->flags &= ~FCF_ASYNC_SENT;
@@ -191,6 +194,10 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
lio->timeout = qla2x00_async_iocb_timeout;
sp->done = qla2x00_async_login_sp_done;
lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
+
+ if (fcport->fc4f_nvme)
+ lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
+
if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
lio->u.logio.flags |= SRB_LOGIN_RETRIED;
rval = qla2x00_start_sp(sp);
@@ -327,38 +334,38 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
u16 i, n, found = 0, loop_id;
port_id_t id;
u64 wwn;
- u8 opt = 0;
+ u8 opt = 0, current_login_state;
fcport = ea->fcport;
if (ea->rc) { /* rval */
if (fcport->login_retry == 0) {
fcport->login_retry = vha->hw->login_retry_count;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "GNL failed Port login retry %8phN, retry cnt=%d.\n",
- fcport->port_name, fcport->login_retry);
+ ql_dbg(ql_dbg_disc, vha, 0x20de,
+ "GNL failed Port login retry %8phN, retry cnt=%d.\n",
+ fcport->port_name, fcport->login_retry);
}
return;
}
if (fcport->last_rscn_gen != fcport->rscn_gen) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20df,
"%s %8phC rscn gen changed rscn %d|%d \n",
__func__, fcport->port_name,
fcport->last_rscn_gen, fcport->rscn_gen);
qla24xx_post_gidpn_work(vha, fcport);
return;
} else if (fcport->last_login_gen != fcport->login_gen) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %8phC login gen changed login %d|%d \n",
- __func__, fcport->port_name,
- fcport->last_login_gen, fcport->login_gen);
+ ql_dbg(ql_dbg_disc, vha, 0x20e0,
+ "%s %8phC login gen changed login %d|%d\n",
+ __func__, fcport->port_name,
+ fcport->last_login_gen, fcport->login_gen);
return;
}
n = ea->data[0] / sizeof(struct get_name_list_extended);
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20e1,
"%s %d %8phC n %d %02x%02x%02x lid %d \n",
__func__, __LINE__, fcport->port_name, n,
fcport->d_id.b.domain, fcport->d_id.b.area,
@@ -380,20 +387,20 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
loop_id = le16_to_cpu(e->nport_handle);
loop_id = (loop_id & 0x7fff);
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s found %8phC CLS [%d|%d] ID[%02x%02x%02x|%02x%02x%02x] lid[%d|%d]\n",
- __func__, fcport->port_name,
- e->current_login_state, fcport->fw_login_state,
- id.b.domain, id.b.area, id.b.al_pa,
- fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa, loop_id, fcport->loop_id);
+ ql_dbg(ql_dbg_disc, vha, 0x20e2,
+ "%s found %8phC CLS [%d|%d] ID[%02x%02x%02x|%02x%02x%02x] lid[%d|%d]\n",
+ __func__, fcport->port_name,
+ e->current_login_state, fcport->fw_login_state,
+ id.b.domain, id.b.area, id.b.al_pa,
+ fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa, loop_id, fcport->loop_id);
if ((id.b24 != fcport->d_id.b24) ||
((fcport->loop_id != FC_NO_LOOP_ID) &&
(fcport->loop_id != loop_id))) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post del sess\n",
- __func__, __LINE__, fcport->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x20e3,
+ "%s %d %8phC post del sess\n",
+ __func__, __LINE__, fcport->port_name);
qlt_schedule_sess_for_deletion(fcport, 1);
return;
}
@@ -414,24 +421,28 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
fcport->login_pause = 1;
}
- switch (e->current_login_state) {
+ if (fcport->fc4f_nvme)
+ current_login_state = e->current_login_state >> 4;
+ else
+ current_login_state = e->current_login_state & 0xf;
+
+ switch (current_login_state) {
case DSC_LS_PRLI_COMP:
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post gpdb\n",
- __func__, __LINE__, fcport->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x20e4,
+ "%s %d %8phC post gpdb\n",
+ __func__, __LINE__, fcport->port_name);
opt = PDO_FORCE_ADISC;
qla24xx_post_gpdb_work(vha, fcport, opt);
break;
-
case DSC_LS_PORT_UNAVAIL:
default:
if (fcport->loop_id == FC_NO_LOOP_ID) {
qla2x00_find_new_loop_id(vha, fcport);
fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
}
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC \n",
- __func__, __LINE__, fcport->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x20e5,
+ "%s %d %8phC\n",
+ __func__, __LINE__, fcport->port_name);
qla24xx_fcport_handle_login(vha, fcport);
break;
}
@@ -456,7 +467,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
qla2x00_find_fcport_by_wwpn(vha,
e->port_name, 0);
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20e6,
"%s %d %8phC post del sess\n",
__func__, __LINE__,
conflict_fcport->port_name);
@@ -487,7 +498,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
u64 wwn;
struct list_head h;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20e7,
"Async done-%s res %x mb[1]=%x mb[2]=%x \n",
sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1],
sp->u.iocb_cmd.u.mbx.in_mb[2]);
@@ -512,7 +523,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
set_bit(loop_id, vha->hw->loop_id_map);
wwn = wwn_to_u64(e->port_name);
- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x20e8,
"%s %8phC %02x:%02x:%02x state %d/%d lid %x \n",
__func__, (void *)&wwn, e->port_id[2], e->port_id[1],
e->port_id[0], e->current_login_state, e->last_login_state,
@@ -551,7 +562,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
if (!vha->flags.online)
goto done;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20d9,
"Async-gnlist WWPN %8phC \n", fcport->port_name);
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
@@ -598,9 +609,9 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
if (rval != QLA_SUCCESS)
goto done_free_sp;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s - OUT WWPN %8phC hndl %x\n",
- sp->name, fcport->port_name, sp->handle);
+ ql_dbg(ql_dbg_disc, vha, 0x20da,
+ "Async-%s - OUT WWPN %8phC hndl %x\n",
+ sp->name, fcport->port_name, sp->handle);
return rval;
@@ -635,7 +646,7 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
int rval = QLA_SUCCESS;
struct event_arg ea;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20db,
"Async done-%s res %x, WWPN %8phC mb[1]=%x mb[2]=%x \n",
sp->name, res, fcport->port_name, mb[1], mb[2]);
@@ -665,6 +676,104 @@ gpd_error_out:
sp->free(sp);
}
+static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+ struct qla_work_evt *e;
+
+ e = qla2x00_alloc_work(vha, QLA_EVT_PRLI);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.fcport.fcport = fcport;
+
+ return qla2x00_post_work(vha, e);
+}
+
+static void
+qla2x00_async_prli_sp_done(void *ptr, int res)
+{
+ srb_t *sp = ptr;
+ struct scsi_qla_host *vha = sp->vha;
+ struct srb_iocb *lio = &sp->u.iocb_cmd;
+ struct event_arg ea;
+
+ ql_dbg(ql_dbg_disc, vha, 0x2129,
+ "%s %8phC res %d \n", __func__,
+ sp->fcport->port_name, res);
+
+ sp->fcport->flags &= ~FCF_ASYNC_SENT;
+
+ if (!test_bit(UNLOADING, &vha->dpc_flags)) {
+ memset(&ea, 0, sizeof(ea));
+ ea.event = FCME_PRLI_DONE;
+ ea.fcport = sp->fcport;
+ ea.data[0] = lio->u.logio.data[0];
+ ea.data[1] = lio->u.logio.data[1];
+ ea.iop[0] = lio->u.logio.iop[0];
+ ea.iop[1] = lio->u.logio.iop[1];
+ ea.sp = sp;
+
+ qla2x00_fcport_event_handler(vha, &ea);
+ }
+
+ sp->free(sp);
+}
+
+int
+qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+ srb_t *sp;
+ struct srb_iocb *lio;
+ int rval = QLA_FUNCTION_FAILED;
+
+ if (!vha->flags.online)
+ return rval;
+
+ if (fcport->fw_login_state == DSC_LS_PLOGI_PEND ||
+ fcport->fw_login_state == DSC_LS_PLOGI_COMP ||
+ fcport->fw_login_state == DSC_LS_PRLI_PEND)
+ return rval;
+
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ return rval;
+
+ fcport->flags |= FCF_ASYNC_SENT;
+ fcport->logout_completed = 0;
+
+ sp->type = SRB_PRLI_CMD;
+ sp->name = "prli";
+ qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+ lio = &sp->u.iocb_cmd;
+ lio->timeout = qla2x00_async_iocb_timeout;
+ sp->done = qla2x00_async_prli_sp_done;
+ lio->u.logio.flags = 0;
+
+ if (fcport->fc4f_nvme)
+ lio->u.logio.flags |= SRB_LOGIN_NVME_PRLI;
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ fcport->flags |= FCF_LOGIN_NEEDED;
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+ goto done_free_sp;
+ }
+
+ ql_dbg(ql_dbg_disc, vha, 0x211b,
+ "Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d.\n",
+ fcport->port_name, sp->handle, fcport->loop_id,
+ fcport->d_id.b24, fcport->login_retry);
+
+ return rval;
+
+done_free_sp:
+ sp->free(sp);
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ return rval;
+}
+
static int qla24xx_post_gpdb_work(struct scsi_qla_host *vha, fc_port_t *fcport,
u8 opt)
{
@@ -701,8 +810,8 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
if (pd == NULL) {
- ql_log(ql_log_warn, vha, 0xffff,
- "Failed to allocate port database structure.\n");
+ ql_log(ql_log_warn, vha, 0xd043,
+ "Failed to allocate port database structure.\n");
goto done_free_sp;
}
memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
@@ -734,9 +843,9 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
if (rval != QLA_SUCCESS)
goto done_free_sp;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s %8phC hndl %x opt %x\n",
- sp->name, fcport->port_name, sp->handle, opt);
+ ql_dbg(ql_dbg_disc, vha, 0x20dc,
+ "Async-%s %8phC hndl %x opt %x\n",
+ sp->name, fcport->port_name, sp->handle, opt);
return rval;
@@ -760,27 +869,27 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
fcport->flags &= ~FCF_ASYNC_SENT;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20d2,
"%s %8phC DS %d LS %d rval %d\n", __func__, fcport->port_name,
fcport->disc_state, fcport->fw_login_state, rval);
if (ea->sp->gen2 != fcport->login_gen) {
/* target side must have changed it. */
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20d3,
"%s %8phC generation changed rscn %d|%d login %d|%d \n",
__func__, fcport->port_name, fcport->last_rscn_gen,
fcport->rscn_gen, fcport->last_login_gen,
fcport->login_gen);
return;
} else if (ea->sp->gen1 != fcport->rscn_gen) {
- ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d %8phC post gidpn\n",
+ ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
__func__, __LINE__, fcport->port_name);
qla24xx_post_gidpn_work(vha, fcport);
return;
}
if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d %8phC post del sess\n",
+ ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC post del sess\n",
__func__, __LINE__, fcport->port_name);
qlt_schedule_sess_for_deletion_lock(fcport);
return;
@@ -797,14 +906,14 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
if (!IS_IIDMA_CAPABLE(vha->hw) ||
!vha->hw->flags.gpsc_supported) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20d6,
"%s %d %8phC post upd_fcport fcp_cnt %d\n",
__func__, __LINE__, fcport->port_name,
vha->fcport_count);
qla24xx_post_upd_fcport_work(vha, fcport);
} else {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20d7,
"%s %d %8phC post gpsc fcp_cnt %d\n",
__func__, __LINE__, fcport->port_name,
vha->fcport_count);
@@ -823,7 +932,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
if (fcport->scan_state != QLA_FCPORT_FOUND)
return 0;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20d8,
"%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d\n",
__func__, fcport->port_name, fcport->disc_state,
fcport->fw_login_state, fcport->login_pause, fcport->flags,
@@ -854,14 +963,14 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
switch (fcport->disc_state) {
case DSC_DELETED:
if (fcport->loop_id == FC_NO_LOOP_ID) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post gnl\n",
- __func__, __LINE__, fcport->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x20bd,
+ "%s %d %8phC post gnl\n",
+ __func__, __LINE__, fcport->port_name);
qla24xx_async_gnl(vha, fcport);
} else {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post login\n",
- __func__, __LINE__, fcport->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x20bf,
+ "%s %d %8phC post login\n",
+ __func__, __LINE__, fcport->port_name);
fcport->disc_state = DSC_LOGIN_PEND;
qla2x00_post_async_login_work(vha, fcport, NULL);
}
@@ -878,16 +987,16 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
if (fcport->flags & FCF_FCP2_DEVICE) {
u8 opt = PDO_FORCE_ADISC;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post gpdb\n",
- __func__, __LINE__, fcport->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x20c9,
+ "%s %d %8phC post gpdb\n",
+ __func__, __LINE__, fcport->port_name);
fcport->disc_state = DSC_GPDB;
qla24xx_post_gpdb_work(vha, fcport, opt);
} else {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post login \n",
- __func__, __LINE__, fcport->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x20cf,
+ "%s %d %8phC post login\n",
+ __func__, __LINE__, fcport->port_name);
fcport->disc_state = DSC_LOGIN_PEND;
qla2x00_post_async_login_work(vha, fcport, NULL);
}
@@ -895,18 +1004,18 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
break;
case DSC_LOGIN_FAILED:
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post gidpn \n",
- __func__, __LINE__, fcport->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x20d0,
+ "%s %d %8phC post gidpn\n",
+ __func__, __LINE__, fcport->port_name);
qla24xx_post_gidpn_work(vha, fcport);
break;
case DSC_LOGIN_COMPLETE:
/* recheck login state */
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post gpdb \n",
- __func__, __LINE__, fcport->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x20d1,
+ "%s %d %8phC post gpdb\n",
+ __func__, __LINE__, fcport->port_name);
qla24xx_post_gpdb_work(vha, fcport, PDO_FORCE_ADISC);
break;
@@ -923,10 +1032,10 @@ void qla24xx_handle_rscn_event(fc_port_t *fcport, struct event_arg *ea)
{
fcport->rscn_gen++;
- ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
- "%s %8phC DS %d LS %d\n",
- __func__, fcport->port_name, fcport->disc_state,
- fcport->fw_login_state);
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x210c,
+ "%s %8phC DS %d LS %d\n",
+ __func__, fcport->port_name, fcport->disc_state,
+ fcport->fw_login_state);
if (fcport->flags & FCF_ASYNC_SENT)
return;
@@ -993,14 +1102,14 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
return;
}
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl %x\n",
- __func__, fcport->port_name, fcport->disc_state,
- fcport->fw_login_state, fcport->login_pause,
- fcport->deleted, fcport->conflict,
- fcport->last_rscn_gen, fcport->rscn_gen,
- fcport->last_login_gen, fcport->login_gen,
- fcport->flags);
+ ql_dbg(ql_dbg_disc, vha, 0x2102,
+ "%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl %x\n",
+ __func__, fcport->port_name, fcport->disc_state,
+ fcport->fw_login_state, fcport->login_pause,
+ fcport->deleted, fcport->conflict,
+ fcport->last_rscn_gen, fcport->rscn_gen,
+ fcport->last_login_gen, fcport->login_gen,
+ fcport->flags);
if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
(fcport->fw_login_state == DSC_LS_PRLI_PEND))
@@ -1023,7 +1132,7 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
}
if (fcport->last_rscn_gen != fcport->rscn_gen) {
- ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d %8phC post gidpn\n",
+ ql_dbg(ql_dbg_disc, vha, 0x20e9, "%s %d %8phC post gidpn\n",
__func__, __LINE__, fcport->port_name);
qla24xx_async_gidpn(vha, fcport);
@@ -1041,6 +1150,20 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
switch (ea->event) {
case FCME_RELOGIN:
+ case FCME_RSCN:
+ case FCME_GIDPN_DONE:
+ case FCME_GPSC_DONE:
+ case FCME_GPNID_DONE:
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
+ test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))
+ return;
+ break;
+ default:
+ break;
+ }
+
+ switch (ea->event) {
+ case FCME_RELOGIN:
if (test_bit(UNLOADING, &vha->dpc_flags))
return;
@@ -1056,10 +1179,10 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
/* cable moved */
rc = qla24xx_post_gpnid_work(vha, &ea->id);
if (rc) {
- ql_log(ql_log_warn, vha, 0xffff,
- "RSCN GPNID work failed %02x%02x%02x\n",
- ea->id.b.domain, ea->id.b.area,
- ea->id.b.al_pa);
+ ql_log(ql_log_warn, vha, 0xd044,
+ "RSCN GPNID work failed %02x%02x%02x\n",
+ ea->id.b.domain, ea->id.b.area,
+ ea->id.b.al_pa);
}
} else {
ea->fcport = fcport;
@@ -1070,14 +1193,14 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
case RSCN_DOM_ADDR:
if (ea->id.b.rsvd_1 == RSCN_AREA_ADDR) {
mask = 0xffff00;
- ql_log(ql_dbg_async, vha, 0xffff,
- "RSCN: Area 0x%06x was affected\n",
- ea->id.b24);
+ ql_dbg(ql_dbg_async, vha, 0x5044,
+ "RSCN: Area 0x%06x was affected\n",
+ ea->id.b24);
} else {
mask = 0xff0000;
- ql_log(ql_dbg_async, vha, 0xffff,
- "RSCN: Domain 0x%06x was affected\n",
- ea->id.b24);
+ ql_dbg(ql_dbg_async, vha, 0x507a,
+ "RSCN: Domain 0x%06x was affected\n",
+ ea->id.b24);
}
rid = ea->id.b24 & mask;
@@ -1092,9 +1215,9 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
break;
case RSCN_FAB_ADDR:
default:
- ql_log(ql_log_warn, vha, 0xffff,
- "RSCN: Fabric was affected. Addr format %d\n",
- ea->id.b.rsvd_1);
+ ql_log(ql_log_warn, vha, 0xd045,
+ "RSCN: Fabric was affected. Addr format %d\n",
+ ea->id.b.rsvd_1);
qla2x00_mark_all_devices_lost(vha, 1);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
@@ -1112,12 +1235,18 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
case FCME_PLOGI_DONE: /* Initiator side sent LLIOCB */
qla24xx_handle_plogi_done_event(vha, ea);
break;
+ case FCME_PRLI_DONE:
+ qla24xx_handle_prli_done_event(vha, ea);
+ break;
case FCME_GPDB_DONE:
qla24xx_handle_gpdb_event(vha, ea);
break;
case FCME_GPNID_DONE:
qla24xx_handle_gpnid_event(vha, ea);
break;
+ case FCME_GFFID_DONE:
+ qla24xx_handle_gffid_event(vha, ea);
+ break;
case FCME_DELETE_DONE:
qla24xx_handle_delete_done_event(vha, ea);
break;
@@ -1294,6 +1423,27 @@ qla24xx_async_abort_command(srb_t *sp)
}
static void
+qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
+{
+ switch (ea->data[0]) {
+ case MBS_COMMAND_COMPLETE:
+ ql_dbg(ql_dbg_disc, vha, 0x2118,
+ "%s %d %8phC post gpdb\n",
+ __func__, __LINE__, ea->fcport->port_name);
+
+ ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
+ ea->fcport->logout_on_delete = 1;
+ qla24xx_post_gpdb_work(vha, ea->fcport, 0);
+ break;
+ default:
+ ql_dbg(ql_dbg_disc, vha, 0x2119,
+ "%s %d %8phC unhandle event of %x\n",
+ __func__, __LINE__, ea->fcport->port_name, ea->data[0]);
+ break;
+ }
+}
+
+static void
qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
{
port_id_t cid; /* conflict Nport id */
@@ -1305,15 +1455,22 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
* force a relogin attempt via implicit LOGO, PLOGI, and PRLI
* requests.
*/
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post gpdb\n",
- __func__, __LINE__, ea->fcport->port_name);
- ea->fcport->chip_reset = vha->hw->chip_reset;
- ea->fcport->logout_on_delete = 1;
- qla24xx_post_gpdb_work(vha, ea->fcport, 0);
+ if (ea->fcport->fc4f_nvme) {
+ ql_dbg(ql_dbg_disc, vha, 0x2117,
+ "%s %d %8phC post prli\n",
+ __func__, __LINE__, ea->fcport->port_name);
+ qla24xx_post_prli_work(vha, ea->fcport);
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0x20ea,
+ "%s %d %8phC post gpdb\n",
+ __func__, __LINE__, ea->fcport->port_name);
+ ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
+ ea->fcport->logout_on_delete = 1;
+ qla24xx_post_gpdb_work(vha, ea->fcport, 0);
+ }
break;
case MBS_COMMAND_ERROR:
- ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d %8phC cmd error %x\n",
+ ql_dbg(ql_dbg_disc, vha, 0x20eb, "%s %d %8phC cmd error %x\n",
__func__, __LINE__, ea->fcport->port_name, ea->data[1]);
ea->fcport->flags &= ~FCF_ASYNC_SENT;
@@ -1330,10 +1487,10 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
cid.b.al_pa = ea->iop[1] & 0xff;
cid.b.rsvd_1 = 0;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC LoopID 0x%x in use post gnl\n",
- __func__, __LINE__, ea->fcport->port_name,
- ea->fcport->loop_id);
+ ql_dbg(ql_dbg_disc, vha, 0x20ec,
+ "%s %d %8phC LoopID 0x%x in use post gnl\n",
+ __func__, __LINE__, ea->fcport->port_name,
+ ea->fcport->loop_id);
if (IS_SW_RESV_ADDR(cid)) {
set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
@@ -1344,11 +1501,11 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
qla24xx_post_gnl_work(vha, ea->fcport);
break;
case MBS_PORT_ID_USED:
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC NPortId %02x%02x%02x inuse post gidpn\n",
- __func__, __LINE__, ea->fcport->port_name,
- ea->fcport->d_id.b.domain, ea->fcport->d_id.b.area,
- ea->fcport->d_id.b.al_pa);
+ ql_dbg(ql_dbg_disc, vha, 0x20ed,
+ "%s %d %8phC NPortId %02x%02x%02x inuse post gidpn\n",
+ __func__, __LINE__, ea->fcport->port_name,
+ ea->fcport->d_id.b.domain, ea->fcport->d_id.b.area,
+ ea->fcport->d_id.b.al_pa);
qla2x00_clear_loop_id(ea->fcport);
qla24xx_post_gidpn_work(vha, ea->fcport);
@@ -2524,6 +2681,13 @@ cont_alloc:
ha->chain_offset = dump_size;
dump_size += mq_size + fce_size;
+ if (ha->exchoffld_buf)
+ dump_size += sizeof(struct qla2xxx_offld_chain) +
+ ha->exchoffld_size;
+ if (ha->exlogin_buf)
+ dump_size += sizeof(struct qla2xxx_offld_chain) +
+ ha->exlogin_size;
+
allocate:
ha->fw_dump = vmalloc(dump_size);
if (!ha->fw_dump) {
@@ -2709,7 +2873,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
if (ql2xexlogins)
ha->flags.exlogins_enabled = 1;
- if (ql2xexchoffld)
+ if (qla_is_exch_offld_enabled(vha))
ha->flags.exchoffld_enabled = 1;
rval = qla2x00_execute_fw(vha, srisc_address);
@@ -2946,7 +3110,8 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
}
/* Move PUREX, ABTS RX & RIDA to ATIOQ */
- if (ql2xmvasynctoatio) {
+ if (ql2xmvasynctoatio &&
+ (IS_QLA83XX(ha) || IS_QLA27XX(ha))) {
if (qla_tgt_mode_enabled(vha) ||
qla_dual_mode_enabled(vha))
ha->fw_options[2] |= BIT_11;
@@ -2954,11 +3119,25 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
ha->fw_options[2] &= ~BIT_11;
}
- ql_dbg(ql_dbg_init, vha, 0xffff,
- "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
- __func__, ha->fw_options[1], ha->fw_options[2],
- ha->fw_options[3], vha->host->active_mode);
- qla2x00_set_fw_options(vha, ha->fw_options);
+ if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ /*
+ * Tell FW to track each exchange to prevent
+ * driver from using stale exchange.
+ */
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha))
+ ha->fw_options[2] |= BIT_4;
+ else
+ ha->fw_options[2] &= ~BIT_4;
+ }
+
+ ql_dbg(ql_dbg_init, vha, 0x00e8,
+ "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
+ __func__, ha->fw_options[1], ha->fw_options[2],
+ ha->fw_options[3], vha->host->active_mode);
+
+ if (ha->fw_options[1] || ha->fw_options[2] || ha->fw_options[3])
+ qla2x00_set_fw_options(vha, ha->fw_options);
/* Update Serial Link options. */
if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
@@ -3036,7 +3215,7 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
icb->rid = cpu_to_le16(rid);
if (ha->flags.msix_enabled) {
msix = &ha->msix_entries[1];
- ql_dbg(ql_dbg_init, vha, 0x00fd,
+ ql_dbg(ql_dbg_init, vha, 0x0019,
"Registering vector 0x%x for base que.\n",
msix->entry);
icb->msix = cpu_to_le16(msix->entry);
@@ -3166,7 +3345,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
/* FA-WWPN Status */
ha->flags.fawwpn_enabled =
(mid_init_cb->init_cb.firmware_options_1 & BIT_6) != 0;
- ql_dbg(ql_dbg_init, vha, 0x0141, "FA-WWPN Support: %s.\n",
+ ql_dbg(ql_dbg_init, vha, 0x00bc, "FA-WWPN Support: %s.\n",
(ha->flags.fawwpn_enabled) ? "enabled" : "disabled");
}
@@ -3178,7 +3357,7 @@ next_check:
} else {
ql_dbg(ql_dbg_init, vha, 0x00d3,
"Init Firmware -- success.\n");
- ha->flags.fw_started = 1;
+ QLA_FW_STARTED(ha);
}
return (rval);
@@ -3840,10 +4019,10 @@ qla2x00_rport_del(void *data)
fcport->drport = NULL;
spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
if (rport) {
- ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
- "%s %8phN. rport %p roles %x \n",
- __func__, fcport->port_name, rport,
- rport->roles);
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x210b,
+ "%s %8phN. rport %p roles %x\n",
+ __func__, fcport->port_name, rport,
+ rport->roles);
fc_remote_port_delete(rport);
}
@@ -3883,7 +4062,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
fcport->logout_on_delete = 1;
if (!fcport->ct_desc.ct_sns) {
- ql_log(ql_log_warn, vha, 0xffff,
+ ql_log(ql_log_warn, vha, 0xd049,
"Failed to allocate ct_sns request.\n");
kfree(fcport);
fcport = NULL;
@@ -3985,7 +4164,7 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {
if (LOOP_TRANSITION(vha)) {
- ql_dbg(ql_dbg_disc, vha, 0x201e,
+ ql_dbg(ql_dbg_disc, vha, 0x2099,
"Needs RSCN update and loop transition.\n");
rval = QLA_FUNCTION_FAILED;
}
@@ -4085,7 +4264,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
if (rval != QLA_SUCCESS)
goto cleanup_allocation;
- ql_dbg(ql_dbg_disc, vha, 0x2017,
+ ql_dbg(ql_dbg_disc, vha, 0x2011,
"Entries in ID list (%d).\n", entries);
ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075,
(uint8_t *)ha->gid_list,
@@ -4094,7 +4273,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
/* Allocate temporary fcport for any new fcports discovered. */
new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (new_fcport == NULL) {
- ql_log(ql_log_warn, vha, 0x2018,
+ ql_log(ql_log_warn, vha, 0x2012,
"Memory allocation failed for fcport.\n");
rval = QLA_MEMORY_ALLOC_FAILED;
goto cleanup_allocation;
@@ -4109,7 +4288,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
fcport->port_type != FCT_BROADCAST &&
(fcport->flags & FCF_FABRIC_DEVICE) == 0) {
- ql_dbg(ql_dbg_disc, vha, 0x2019,
+ ql_dbg(ql_dbg_disc, vha, 0x2096,
"Marking port lost loop_id=0x%04x.\n",
fcport->loop_id);
@@ -4154,11 +4333,11 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
rval2 = qla2x00_get_port_database(vha, new_fcport, 0);
if (rval2 != QLA_SUCCESS) {
- ql_dbg(ql_dbg_disc, vha, 0x201a,
+ ql_dbg(ql_dbg_disc, vha, 0x2097,
"Failed to retrieve fcport information "
"-- get_port_database=%x, loop_id=0x%04x.\n",
rval2, new_fcport->loop_id);
- ql_dbg(ql_dbg_disc, vha, 0x201b,
+ ql_dbg(ql_dbg_disc, vha, 0x2105,
"Scheduling resync.\n");
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
continue;
@@ -4207,7 +4386,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (new_fcport == NULL) {
- ql_log(ql_log_warn, vha, 0x201c,
+ ql_log(ql_log_warn, vha, 0xd031,
"Failed to allocate memory for fcport.\n");
rval = QLA_MEMORY_ALLOC_FAILED;
goto cleanup_allocation;
@@ -4230,7 +4409,7 @@ cleanup_allocation:
kfree(new_fcport);
if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_disc, vha, 0x201d,
+ ql_dbg(ql_dbg_disc, vha, 0x2098,
"Configure local loop error exit: rval=%x.\n", rval);
}
@@ -4300,10 +4479,10 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
if (fcport->port_type == FCT_TARGET)
rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %8phN. rport %p is %s mode \n",
- __func__, fcport->port_name, rport,
- (fcport->port_type == FCT_TARGET) ? "tgt" : "ini");
+ ql_dbg(ql_dbg_disc, vha, 0x20ee,
+ "%s %8phN. rport %p is %s mode\n",
+ __func__, fcport->port_name, rport,
+ (fcport->port_type == FCT_TARGET) ? "tgt" : "ini");
fc_remote_port_rolechg(rport, rport_ids.roles);
}
@@ -4331,7 +4510,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
if (IS_SW_RESV_ADDR(fcport->d_id))
return;
- ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %8phC \n",
+ ql_dbg(ql_dbg_disc, vha, 0x20ef, "%s %8phC\n",
__func__, fcport->port_name);
if (IS_QLAFX00(vha->hw)) {
@@ -4344,6 +4523,11 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
fcport->deleted = 0;
fcport->logout_on_delete = 1;
+ if (fcport->fc4f_nvme) {
+ qla_nvme_register_remote(vha, fcport);
+ return;
+ }
+
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
qla2x00_iidma_fcport(vha, fcport);
qla24xx_update_fcport_fcp_prio(vha, fcport);
@@ -4398,7 +4582,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
loop_id = SNS_FL_PORT;
rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_node_name, 1);
if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_disc, vha, 0x201f,
+ ql_dbg(ql_dbg_disc, vha, 0x20a0,
"MBX_GET_PORT_NAME failed, No FL Port.\n");
vha->device_flags &= ~SWITCH_FOUND;
@@ -4436,7 +4620,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
return rval;
}
if (mb[0] != MBS_COMMAND_COMPLETE) {
- ql_dbg(ql_dbg_disc, vha, 0x2042,
+ ql_dbg(ql_dbg_disc, vha, 0x20a1,
"Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x mb[2]=%x "
"mb[6]=%x mb[7]=%x.\n", loop_id, mb[0], mb[1],
mb[2], mb[6], mb[7]);
@@ -4446,22 +4630,39 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) {
if (qla2x00_rft_id(vha)) {
/* EMPTY */
- ql_dbg(ql_dbg_disc, vha, 0x2045,
+ ql_dbg(ql_dbg_disc, vha, 0x20a2,
"Register FC-4 TYPE failed.\n");
+ if (test_bit(LOOP_RESYNC_NEEDED,
+ &vha->dpc_flags))
+ break;
}
- if (qla2x00_rff_id(vha)) {
+ if (qla2x00_rff_id(vha, FC4_TYPE_FCP_SCSI)) {
/* EMPTY */
- ql_dbg(ql_dbg_disc, vha, 0x2049,
+ ql_dbg(ql_dbg_disc, vha, 0x209a,
"Register FC-4 Features failed.\n");
+ if (test_bit(LOOP_RESYNC_NEEDED,
+ &vha->dpc_flags))
+ break;
+ }
+ if (vha->flags.nvme_enabled) {
+ if (qla2x00_rff_id(vha, FC_TYPE_NVME)) {
+ ql_dbg(ql_dbg_disc, vha, 0x2049,
+ "Register NVME FC Type Features failed.\n");
+ }
}
if (qla2x00_rnn_id(vha)) {
/* EMPTY */
- ql_dbg(ql_dbg_disc, vha, 0x204f,
+ ql_dbg(ql_dbg_disc, vha, 0x2104,
"Register Node Name failed.\n");
+ if (test_bit(LOOP_RESYNC_NEEDED,
+ &vha->dpc_flags))
+ break;
} else if (qla2x00_rsnn_nn(vha)) {
/* EMPTY */
- ql_dbg(ql_dbg_disc, vha, 0x2053,
- "Register Symobilic Node Name failed.\n");
+ ql_dbg(ql_dbg_disc, vha, 0x209b,
+ "Register Symbolic Node Name failed.\n");
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ break;
}
}
@@ -4482,6 +4683,9 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
break;
} while (0);
+ if (!vha->nvme_local_port && vha->flags.nvme_enabled)
+ qla_nvme_register_hba(vha);
+
if (rval)
ql_dbg(ql_dbg_disc, vha, 0x2068,
"Configure fabric error exit rval=%d.\n", rval);
@@ -4527,30 +4731,41 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
swl = ha->swl;
if (!swl) {
/*EMPTY*/
- ql_dbg(ql_dbg_disc, vha, 0x2054,
+ ql_dbg(ql_dbg_disc, vha, 0x209c,
"GID_PT allocations failed, fallback on GA_NXT.\n");
} else {
memset(swl, 0, ha->max_fibre_devices * sizeof(sw_info_t));
if (qla2x00_gid_pt(vha, swl) != QLA_SUCCESS) {
swl = NULL;
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ return rval;
} else if (qla2x00_gpn_id(vha, swl) != QLA_SUCCESS) {
swl = NULL;
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ return rval;
} else if (qla2x00_gnn_id(vha, swl) != QLA_SUCCESS) {
swl = NULL;
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ return rval;
} else if (qla2x00_gfpn_id(vha, swl) != QLA_SUCCESS) {
swl = NULL;
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ return rval;
}
/* If other queries succeeded probe for FC-4 type */
- if (swl)
+ if (swl) {
qla2x00_gff_id(vha, swl);
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ return rval;
+ }
}
swl_idx = 0;
/* Allocate temporary fcport for any new fcports discovered. */
new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (new_fcport == NULL) {
- ql_log(ql_log_warn, vha, 0x205e,
+ ql_log(ql_log_warn, vha, 0x209d,
"Failed to allocate memory for fcport.\n");
return (QLA_MEMORY_ALLOC_FAILED);
}
@@ -4588,6 +4803,16 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
new_fcport->fp_speed = swl[swl_idx].fp_speed;
new_fcport->fc4_type = swl[swl_idx].fc4_type;
+ new_fcport->nvme_flag = 0;
+ if (vha->flags.nvme_enabled &&
+ swl[swl_idx].fc4f_nvme) {
+ new_fcport->fc4f_nvme =
+ swl[swl_idx].fc4f_nvme;
+ ql_log(ql_log_info, vha, 0x2131,
+ "FOUND: NVME port %8phC as FC Type 28h\n",
+ new_fcport->port_name);
+ }
+
if (swl[swl_idx].d_id.b.rsvd_1 != 0) {
last_dev = 1;
}
@@ -4597,7 +4822,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
/* Send GA_NXT to the switch */
rval = qla2x00_ga_nxt(vha, new_fcport);
if (rval != QLA_SUCCESS) {
- ql_log(ql_log_warn, vha, 0x2064,
+ ql_log(ql_log_warn, vha, 0x209e,
"SNS scan failed -- assuming "
"zero-entry result.\n");
rval = QLA_SUCCESS;
@@ -4610,7 +4835,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
wrap.b24 = new_fcport->d_id.b24;
first_dev = 0;
} else if (new_fcport->d_id.b24 == wrap.b24) {
- ql_dbg(ql_dbg_disc, vha, 0x2065,
+ ql_dbg(ql_dbg_disc, vha, 0x209f,
"Device wrap (%02x%02x%02x).\n",
new_fcport->d_id.b.domain,
new_fcport->d_id.b.area,
@@ -4722,7 +4947,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
nxt_d_id.b24 = new_fcport->d_id.b24;
new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (new_fcport == NULL) {
- ql_log(ql_log_warn, vha, 0x2066,
+ ql_log(ql_log_warn, vha, 0xd032,
"Memory allocation failed for fcport.\n");
return (QLA_MEMORY_ALLOC_FAILED);
}
@@ -4753,7 +4978,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
(fcport->flags & FCF_FCP2_DEVICE) == 0 &&
fcport->port_type != FCT_INITIATOR &&
fcport->port_type != FCT_BROADCAST) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20f0,
"%s %d %8phC post del sess\n",
__func__, __LINE__,
fcport->port_name);
@@ -5473,6 +5698,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
struct scsi_qla_host *vp;
unsigned long flags;
fc_port_t *fcport;
+ u16 i;
/* For ISP82XX, driver waits for completion of the commands.
* online flag should be set.
@@ -5498,7 +5724,12 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
ha->current_topology = 0;
ha->flags.fw_started = 0;
ha->flags.fw_init_done = 0;
- ha->chip_reset++;
+ ha->base_qpair->chip_reset++;
+ for (i = 0; i < ha->max_qpairs; i++) {
+ if (ha->queue_pair_map[i])
+ ha->queue_pair_map[i]->chip_reset =
+ ha->base_qpair->chip_reset;
+ }
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
@@ -6353,8 +6584,8 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
"-> template size %x bytes\n", dlen);
if (dlen > risc_size * sizeof(*dcode)) {
ql_log(ql_log_warn, vha, 0x0167,
- "Failed fwdump template exceeds array by %x bytes\n",
- (uint32_t)(dlen - risc_size * sizeof(*dcode)));
+ "Failed fwdump template exceeds array by %zx bytes\n",
+ (size_t)(dlen - risc_size * sizeof(*dcode)));
goto default_template;
}
ha->fw_dump_template_len = dlen;
@@ -6655,8 +6886,8 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
"-> template size %x bytes\n", dlen);
if (dlen > risc_size * sizeof(*fwcode)) {
ql_log(ql_log_warn, vha, 0x0177,
- "Failed fwdump template exceeds array by %x bytes\n",
- (uint32_t)(dlen - risc_size * sizeof(*fwcode)));
+ "Failed fwdump template exceeds array by %zx bytes\n",
+ (size_t)(dlen - risc_size * sizeof(*fwcode)));
goto default_template;
}
ha->fw_dump_template_len = dlen;
@@ -6790,7 +7021,7 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
ret = qla2x00_stop_firmware(vha);
}
- ha->flags.fw_started = 0;
+ QLA_FW_STOPPED(ha);
ha->flags.fw_init_done = 0;
}
@@ -7322,16 +7553,31 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha)
ha->fw_options[2] &= ~BIT_11;
}
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha)) {
+ /* FW auto send SCSI status during */
+ ha->fw_options[1] |= BIT_8;
+ ha->fw_options[10] |= (u16)SAM_STAT_BUSY << 8;
+
+ /* FW perform Exchange validation */
+ ha->fw_options[2] |= BIT_4;
+ } else {
+ ha->fw_options[1] &= ~BIT_8;
+ ha->fw_options[10] &= 0x00ff;
+
+ ha->fw_options[2] &= ~BIT_4;
+ }
+
if (ql2xetsenable) {
/* Enable ETS Burst. */
memset(ha->fw_options, 0, sizeof(ha->fw_options));
ha->fw_options[2] |= BIT_9;
}
- ql_dbg(ql_dbg_init, vha, 0xffff,
- "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
- __func__, ha->fw_options[1], ha->fw_options[2],
- ha->fw_options[3], vha->host->active_mode);
+ ql_dbg(ql_dbg_init, vha, 0x00e9,
+ "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
+ __func__, ha->fw_options[1], ha->fw_options[2],
+ ha->fw_options[3], vha->host->active_mode);
qla2x00_set_fw_options(vha, ha->fw_options);
}
@@ -7512,7 +7758,8 @@ qla24xx_update_all_fcp_prio(scsi_qla_host_t *vha)
return ret;
}
-struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int vp_idx)
+struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
+ int vp_idx, bool startqp)
{
int rsp_id = 0;
int req_id = 0;
@@ -7539,6 +7786,9 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
qpair->hw = vha->hw;
qpair->vha = vha;
+ qpair->qp_lock_ptr = &qpair->qp_lock;
+ spin_lock_init(&qpair->qp_lock);
+ qpair->use_shadow_reg = IS_SHADOW_REG_CAPABLE(ha) ? 1 : 0;
/* Assign available que pair id */
mutex_lock(&ha->mq_lock);
@@ -7554,13 +7804,18 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
ha->queue_pair_map[qpair_id] = qpair;
qpair->id = qpair_id;
qpair->vp_idx = vp_idx;
+ INIT_LIST_HEAD(&qpair->hints_list);
+ qpair->chip_reset = ha->base_qpair->chip_reset;
+ qpair->enable_class_2 = ha->base_qpair->enable_class_2;
+ qpair->enable_explicit_conf =
+ ha->base_qpair->enable_explicit_conf;
for (i = 0; i < ha->msix_count; i++) {
msix = &ha->msix_entries[i];
if (msix->in_use)
continue;
qpair->msix = msix;
- ql_log(ql_dbg_multiq, vha, 0xc00f,
+ ql_dbg(ql_dbg_multiq, vha, 0xc00f,
"Vector %x selected for qpair\n", msix->vector);
break;
}
@@ -7572,11 +7827,14 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
qpair->msix->in_use = 1;
list_add_tail(&qpair->qp_list_elem, &vha->qp_list);
+ qpair->pdev = ha->pdev;
+ if (IS_QLA27XX(ha) || IS_QLA83XX(ha))
+ qpair->reqq_start_iocbs = qla_83xx_start_iocbs;
mutex_unlock(&ha->mq_lock);
/* Create response queue first */
- rsp_id = qla25xx_create_rsp_que(ha, 0, 0, 0, qpair);
+ rsp_id = qla25xx_create_rsp_que(ha, 0, 0, 0, qpair, startqp);
if (!rsp_id) {
ql_log(ql_log_warn, vha, 0x0185,
"Failed to create response queue.\n");
@@ -7586,7 +7844,8 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
qpair->rsp = ha->rsp_q_map[rsp_id];
/* Create request queue */
- req_id = qla25xx_create_req_que(ha, 0, vp_idx, 0, rsp_id, qos);
+ req_id = qla25xx_create_req_que(ha, 0, vp_idx, 0, rsp_id, qos,
+ startqp);
if (!req_id) {
ql_log(ql_log_warn, vha, 0x0186,
"Failed to create request queue.\n");
@@ -7595,6 +7854,9 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
qpair->req = ha->req_q_map[req_id];
qpair->rsp->req = qpair->req;
+ qpair->rsp->qpair = qpair;
+ /* init qpair to this cpu. Will adjust at run time. */
+ qla_cpu_update(qpair, smp_processor_id());
if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) {
if (ha->fw_attributes & BIT_4)
@@ -7603,7 +7865,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
qpair->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
if (!qpair->srb_mempool) {
- ql_log(ql_log_warn, vha, 0x0191,
+ ql_log(ql_log_warn, vha, 0xd036,
"Failed to create srb mempool for qpair %d\n",
qpair->id);
goto fail_mempool;
@@ -7645,9 +7907,12 @@ fail_qid_map:
int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
{
- int ret;
+ int ret = QLA_FUNCTION_FAILED;
struct qla_hw_data *ha = qpair->hw;
+ if (!vha->flags.qpairs_req_created && !vha->flags.qpairs_rsp_created)
+ goto fail;
+
qpair->delete_in_progress = 1;
while (atomic_read(&qpair->ref_count))
msleep(500);
@@ -7664,8 +7929,11 @@ int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
clear_bit(qpair->id, ha->qpair_qid_map);
ha->num_qpairs--;
list_del(&qpair->qp_list_elem);
- if (list_empty(&vha->qp_list))
+ if (list_empty(&vha->qp_list)) {
vha->flags.qpairs_available = 0;
+ vha->flags.qpairs_req_created = 0;
+ vha->flags.qpairs_rsp_created = 0;
+ }
mempool_destroy(qpair->srb_mempool);
kfree(qpair);
mutex_unlock(&ha->mq_lock);
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index c61a6a871c8e..9a2c86eacf44 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -250,6 +250,7 @@ qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
memset(sp, 0, sizeof(*sp));
sp->fcport = fcport;
+ sp->cmd_type = TYPE_SRB;
sp->iocbs = 1;
sp->vha = vha;
done:
@@ -307,3 +308,62 @@ qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t retry_delay)
fcport->retry_delay_timestamp = jiffies +
(retry_delay * HZ / 10);
}
+
+static inline bool
+qla_is_exch_offld_enabled(struct scsi_qla_host *vha)
+{
+ if (qla_ini_mode_enabled(vha) &&
+ (ql2xiniexchg > FW_DEF_EXCHANGES_CNT))
+ return true;
+ else if (qla_tgt_mode_enabled(vha) &&
+ (ql2xexchoffld > FW_DEF_EXCHANGES_CNT))
+ return true;
+ else if (qla_dual_mode_enabled(vha) &&
+ ((ql2xiniexchg + ql2xexchoffld) > FW_DEF_EXCHANGES_CNT))
+ return true;
+ else
+ return false;
+}
+
+static inline void
+qla_cpu_update(struct qla_qpair *qpair, uint16_t cpuid)
+{
+ qpair->cpuid = cpuid;
+
+ if (!list_empty(&qpair->hints_list)) {
+ struct qla_qpair_hint *h;
+
+ list_for_each_entry(h, &qpair->hints_list, hint_elem)
+ h->cpuid = qpair->cpuid;
+ }
+}
+
+static inline struct qla_qpair_hint *
+qla_qpair_to_hint(struct qla_tgt *tgt, struct qla_qpair *qpair)
+{
+ struct qla_qpair_hint *h;
+ u16 i;
+
+ for (i = 0; i < tgt->ha->max_qpairs + 1; i++) {
+ h = &tgt->qphints[i];
+ if (h->qpair == qpair)
+ return h;
+ }
+
+ return NULL;
+}
+
+static inline void
+qla_83xx_start_iocbs(struct qla_qpair *qpair)
+{
+ struct req_que *req = qpair->req;
+
+ req->ring_index++;
+ if (req->ring_index == req->length) {
+ req->ring_index = 0;
+ req->ring_ptr = req->ring;
+ } else
+ req->ring_ptr++;
+
+ WRT_REG_DWORD(req->req_q_in, req->ring_index);
+}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index ea027f6a7fd4..a36c485fae50 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -464,7 +464,9 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req)
req->ring_ptr++;
/* Set chip new ring index. */
- if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (ha->mqenable || IS_QLA27XX(ha)) {
+ WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ } else if (IS_QLA83XX(ha)) {
WRT_REG_DWORD(req->req_q_in, req->ring_index);
RD_REG_DWORD_RELAXED(&ha->iobase->isp24.hccr);
} else if (IS_QLAFX00(ha)) {
@@ -1768,6 +1770,9 @@ qla2xxx_start_scsi_mq(srb_t *sp)
struct qla_hw_data *ha = vha->hw;
struct qla_qpair *qpair = sp->qpair;
+ /* Acquire qpair specific lock */
+ spin_lock_irqsave(&qpair->qp_lock, flags);
+
/* Setup qpair pointers */
rsp = qpair->rsp;
req = qpair->req;
@@ -1777,15 +1782,14 @@ qla2xxx_start_scsi_mq(srb_t *sp)
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
- QLA_SUCCESS)
+ if (__qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+ QLA_SUCCESS) {
+ spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_FUNCTION_FAILED;
+ }
vha->marker_needed = 0;
}
- /* Acquire qpair specific lock */
- spin_lock_irqsave(&qpair->qp_lock, flags);
-
/* Check for room in outstanding command list. */
handle = req->current_outstanding_cmd;
for (index = 1; index < req->num_outstanding_cmds; index++) {
@@ -1940,6 +1944,8 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
return qla2xxx_start_scsi_mq(sp);
}
+ spin_lock_irqsave(&qpair->qp_lock, flags);
+
/* Setup qpair pointers */
rsp = qpair->rsp;
req = qpair->req;
@@ -1949,15 +1955,14 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
- QLA_SUCCESS)
+ if (__qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+ QLA_SUCCESS) {
+ spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_FUNCTION_FAILED;
+ }
vha->marker_needed = 0;
}
- /* Acquire ring specific lock */
- spin_lock_irqsave(&qpair->qp_lock, flags);
-
/* Check for room in outstanding command list. */
handle = req->current_outstanding_cmd;
for (index = 1; index < req->num_outstanding_cmds; index++) {
@@ -2107,20 +2112,13 @@ queuing_error:
/* Generic Control-SRB manipulation functions. */
/* hardware_lock assumed to be held. */
-void *
-qla2x00_alloc_iocbs_ready(scsi_qla_host_t *vha, srb_t *sp)
-{
- if (qla2x00_reset_active(vha))
- return NULL;
-
- return qla2x00_alloc_iocbs(vha, sp);
-}
void *
-qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp)
+__qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp)
{
+ scsi_qla_host_t *vha = qpair->vha;
struct qla_hw_data *ha = vha->hw;
- struct req_que *req = ha->req_q_map[0];
+ struct req_que *req = qpair->req;
device_reg_t *reg = ISP_QUE_REG(ha, req->id);
uint32_t index, handle;
request_t *pkt;
@@ -2194,10 +2192,44 @@ skip_cmd_array:
}
queuing_error:
- vha->tgt_counters.num_alloc_iocb_failed++;
+ qpair->tgt_counters.num_alloc_iocb_failed++;
return pkt;
}
+void *
+qla2x00_alloc_iocbs_ready(struct qla_qpair *qpair, srb_t *sp)
+{
+ scsi_qla_host_t *vha = qpair->vha;
+
+ if (qla2x00_reset_active(vha))
+ return NULL;
+
+ return __qla2x00_alloc_iocbs(qpair, sp);
+}
+
+void *
+qla2x00_alloc_iocbs(struct scsi_qla_host *vha, srb_t *sp)
+{
+ return __qla2x00_alloc_iocbs(vha->hw->base_qpair, sp);
+}
+
+static void
+qla24xx_prli_iocb(srb_t *sp, struct logio_entry_24xx *logio)
+{
+ struct srb_iocb *lio = &sp->u.iocb_cmd;
+
+ logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
+ logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI);
+ if (lio->u.logio.flags & SRB_LOGIN_NVME_PRLI)
+ logio->control_flags |= LCF_NVME_PRLI;
+
+ logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+ logio->port_id[0] = sp->fcport->d_id.b.al_pa;
+ logio->port_id[1] = sp->fcport->d_id.b.area;
+ logio->port_id[2] = sp->fcport->d_id.b.domain;
+ logio->vp_index = sp->vha->vp_idx;
+}
+
static void
qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio)
{
@@ -2205,6 +2237,7 @@ qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio)
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI);
+
if (lio->u.logio.flags & SRB_LOGIN_COND_PLOGI)
logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI);
if (lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI)
@@ -3125,6 +3158,39 @@ static void qla2x00_send_notify_ack_iocb(srb_t *sp,
nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
}
+/*
+ * Build NVME LS request
+ */
+static int
+qla_nvme_ls(srb_t *sp, struct pt_ls4_request *cmd_pkt)
+{
+ struct srb_iocb *nvme;
+ int rval = QLA_SUCCESS;
+
+ nvme = &sp->u.iocb_cmd;
+ cmd_pkt->entry_type = PT_LS4_REQUEST;
+ cmd_pkt->entry_count = 1;
+ cmd_pkt->control_flags = CF_LS4_ORIGINATOR << CF_LS4_SHIFT;
+
+ cmd_pkt->timeout = cpu_to_le16(nvme->u.nvme.timeout_sec);
+ cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+ cmd_pkt->vp_index = sp->fcport->vha->vp_idx;
+
+ cmd_pkt->tx_dseg_count = 1;
+ cmd_pkt->tx_byte_count = nvme->u.nvme.cmd_len;
+ cmd_pkt->dseg0_len = nvme->u.nvme.cmd_len;
+ cmd_pkt->dseg0_address[0] = cpu_to_le32(LSD(nvme->u.nvme.cmd_dma));
+ cmd_pkt->dseg0_address[1] = cpu_to_le32(MSD(nvme->u.nvme.cmd_dma));
+
+ cmd_pkt->rx_dseg_count = 1;
+ cmd_pkt->rx_byte_count = nvme->u.nvme.rsp_len;
+ cmd_pkt->dseg1_len = nvme->u.nvme.rsp_len;
+ cmd_pkt->dseg1_address[0] = cpu_to_le32(LSD(nvme->u.nvme.rsp_dma));
+ cmd_pkt->dseg1_address[1] = cpu_to_le32(MSD(nvme->u.nvme.rsp_dma));
+
+ return rval;
+}
+
int
qla2x00_start_sp(srb_t *sp)
{
@@ -3150,6 +3216,9 @@ qla2x00_start_sp(srb_t *sp)
qla24xx_login_iocb(sp, pkt) :
qla2x00_login_iocb(sp, pkt);
break;
+ case SRB_PRLI_CMD:
+ qla24xx_prli_iocb(sp, pkt);
+ break;
case SRB_LOGOUT_CMD:
IS_FWI2_CAPABLE(ha) ?
qla24xx_logout_iocb(sp, pkt) :
@@ -3178,6 +3247,9 @@ qla2x00_start_sp(srb_t *sp)
case SRB_FXIOCB_BCMD:
qlafx00_fxdisc_iocb(sp, pkt);
break;
+ case SRB_NVME_LS:
+ qla_nvme_ls(sp, pkt);
+ break;
case SRB_ABT_CMD:
IS_QLAFX00(ha) ?
qlafx00_abort_iocb(sp, pkt) :
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 2572121b765b..6c6e624a5aa6 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -9,6 +9,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/cpu.h>
#include <linux/t10-pi.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_bsg_fc.h>
@@ -17,7 +18,7 @@
static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, void *);
static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *);
-static void qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
+static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
sts_entry_t *);
/**
@@ -431,8 +432,7 @@ qla83xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb)
"Register: 0x%x%x.\n", mb[7], mb[3]);
if (err_level == ERR_LEVEL_NON_FATAL) {
ql_log(ql_log_warn, vha, 0x5063,
- "Not a fatal error, f/w has recovered "
- "iteself.\n");
+ "Not a fatal error, f/w has recovered itself.\n");
} else if (err_level == ERR_LEVEL_RECOVERABLE_FATAL) {
ql_log(ql_log_fatal, vha, 0x5064,
"Recoverable Fatal error: Chip reset "
@@ -709,7 +709,7 @@ skip_rio:
ha->isp_ops->fw_dump(vha, 1);
ha->flags.fw_init_done = 0;
- ha->flags.fw_started = 0;
+ QLA_FW_STOPPED(ha);
if (IS_FWI2_CAPABLE(ha)) {
if (mb[1] == 0 && mb[2] == 0) {
@@ -829,7 +829,7 @@ skip_rio:
fc_host_port_name(vha->host) =
wwn_to_u64(vha->port_name);
ql_dbg(ql_dbg_init + ql_dbg_verbose,
- vha, 0x0144, "LOOP DOWN detected,"
+ vha, 0x00d8, "LOOP DOWN detected,"
"restore WWPN %016llx\n",
wwn_to_u64(vha->port_name));
}
@@ -973,6 +973,23 @@ skip_rio:
if (mb[1] == 0xffff)
goto global_port_update;
+ if (mb[1] == NPH_SNS_LID(ha)) {
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ break;
+ }
+
+ /* use handle_cnt for loop id/nport handle */
+ if (IS_FWI2_CAPABLE(ha))
+ handle_cnt = NPH_SNS;
+ else
+ handle_cnt = SIMPLE_NAME_SERVER;
+ if (mb[1] == handle_cnt) {
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ break;
+ }
+
/* Port logout */
fcport = qla2x00_find_fcport_by_loopid(vha, mb[1]);
if (!fcport)
@@ -1701,7 +1718,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
case LSC_SCODE_NOXCB:
vha->hw->exch_starvation++;
if (vha->hw->exch_starvation > 5) {
- ql_log(ql_log_warn, vha, 0xffff,
+ ql_log(ql_log_warn, vha, 0xd046,
"Exchange starvation. Resetting RISC\n");
vha->hw->exch_starvation = 0;
@@ -1781,6 +1798,79 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
sp->done(sp, 0);
}
+static void
+qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
+{
+ const char func[] = "NVME-IOCB";
+ fc_port_t *fcport;
+ srb_t *sp;
+ struct srb_iocb *iocb;
+ struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk;
+ uint16_t state_flags;
+ struct nvmefc_fcp_req *fd;
+ uint16_t ret = 0;
+ struct srb_iocb *nvme;
+
+ sp = qla2x00_get_sp_from_handle(vha, func, req, tsk);
+ if (!sp)
+ return;
+
+ iocb = &sp->u.iocb_cmd;
+ fcport = sp->fcport;
+ iocb->u.nvme.comp_status = le16_to_cpu(sts->comp_status);
+ state_flags = le16_to_cpu(sts->state_flags);
+ fd = iocb->u.nvme.desc;
+ nvme = &sp->u.iocb_cmd;
+
+ if (unlikely(nvme->u.nvme.aen_op))
+ atomic_dec(&sp->vha->nvme_active_aen_cnt);
+
+ /*
+ * State flags: Bit 6 and 0.
+ * If 0 is set, we don't care about 6.
+ * both cases resp was dma'd to host buffer
+ * if both are 0, that is good path case.
+ * if six is set and 0 is clear, we need to
+ * copy resp data from status iocb to resp buffer.
+ */
+ if (!(state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP))) {
+ iocb->u.nvme.rsp_pyld_len = 0;
+ } else if ((state_flags & SF_FCP_RSP_DMA)) {
+ iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len);
+ } else if (state_flags & SF_NVME_ERSP) {
+ uint32_t *inbuf, *outbuf;
+ uint16_t iter;
+
+ inbuf = (uint32_t *)&sts->nvme_ersp_data;
+ outbuf = (uint32_t *)fd->rspaddr;
+ iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len);
+ iter = iocb->u.nvme.rsp_pyld_len >> 2;
+ for (; iter; iter--)
+ *outbuf++ = swab32(*inbuf++);
+ } else { /* unhandled case */
+ ql_log(ql_log_warn, fcport->vha, 0x503a,
+ "NVME-%s error. Unhandled state_flags of %x\n",
+ sp->name, state_flags);
+ }
+
+ fd->transferred_length = fd->payload_length -
+ le32_to_cpu(sts->residual_len);
+
+ if (sts->entry_status) {
+ ql_log(ql_log_warn, fcport->vha, 0x5038,
+ "NVME-%s error - hdl=%x entry-status(%x).\n",
+ sp->name, sp->handle, sts->entry_status);
+ ret = QLA_FUNCTION_FAILED;
+ } else if (sts->comp_status != cpu_to_le16(CS_COMPLETE)) {
+ ql_log(ql_log_warn, fcport->vha, 0x5039,
+ "NVME-%s error - hdl=%x completion status(%x) resid=%x ox_id=%x\n",
+ sp->name, sp->handle, sts->comp_status,
+ le32_to_cpu(sts->residual_len), sts->ox_id);
+ ret = QLA_FUNCTION_FAILED;
+ }
+ sp->done(sp, ret);
+}
+
/**
* qla2x00_process_response_queue() - Process response queue entries.
* @ha: SCSI driver HA context
@@ -2263,6 +2353,20 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
return;
}
+ if (sp->cmd_type != TYPE_SRB) {
+ req->outstanding_cmds[handle] = NULL;
+ ql_dbg(ql_dbg_io, vha, 0x3015,
+ "Unknown sp->cmd_type %x %p).\n",
+ sp->cmd_type, sp);
+ return;
+ }
+
+ /* NVME completion. */
+ if (sp->type == SRB_NVME_CMD) {
+ qla24xx_nvme_iocb_entry(vha, req, pkt);
+ return;
+ }
+
if (unlikely((state_flags & BIT_1) && (sp->type == SRB_BIDI_CMD))) {
qla25xx_process_bidir_status_iocb(vha, pkt, req, handle);
return;
@@ -2374,8 +2478,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
((unsigned)(scsi_bufflen(cp) - resid) <
cp->underflow)) {
ql_dbg(ql_dbg_io, fcport->vha, 0x301a,
- "Mid-layer underflow "
- "detected (0x%x of 0x%x bytes).\n",
+ "Mid-layer underflow detected (0x%x of 0x%x bytes).\n",
resid, scsi_bufflen(cp));
res = DID_ERROR << 16;
@@ -2408,8 +2511,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
if (scsi_status & SS_RESIDUAL_UNDER) {
if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) {
ql_dbg(ql_dbg_io, fcport->vha, 0x301d,
- "Dropped frame(s) detected "
- "(0x%x of 0x%x bytes).\n",
+ "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
resid, scsi_bufflen(cp));
res = DID_ERROR << 16 | lscsi_status;
@@ -2420,8 +2522,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
((unsigned)(scsi_bufflen(cp) - resid) <
cp->underflow)) {
ql_dbg(ql_dbg_io, fcport->vha, 0x301e,
- "Mid-layer underflow "
- "detected (0x%x of 0x%x bytes).\n",
+ "Mid-layer underflow detected (0x%x of 0x%x bytes).\n",
resid, scsi_bufflen(cp));
res = DID_ERROR << 16;
@@ -2435,9 +2536,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
*/
ql_dbg(ql_dbg_io, fcport->vha, 0x301f,
- "Dropped frame(s) detected (0x%x "
- "of 0x%x bytes).\n", resid,
- scsi_bufflen(cp));
+ "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
+ resid, scsi_bufflen(cp));
res = DID_ERROR << 16 | lscsi_status;
goto check_scsi_status;
@@ -2619,8 +2719,9 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
* qla2x00_error_entry() - Process an error entry.
* @ha: SCSI driver HA context
* @pkt: Entry pointer
+ * return : 1=allow further error analysis. 0=no additional error analysis.
*/
-static void
+static int
qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
{
srb_t *sp;
@@ -2631,7 +2732,8 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
int res = DID_ERROR << 16;
ql_dbg(ql_dbg_async, vha, 0x502a,
- "type of error status in response: 0x%x\n", pkt->entry_status);
+ "iocb type %xh with error status %xh, handle %xh, rspq id %d\n",
+ pkt->entry_type, pkt->entry_status, pkt->handle, rsp->id);
if (que >= ha->max_req_queues || !ha->req_q_map[que])
goto fatal;
@@ -2641,18 +2743,35 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
if (pkt->entry_status & RF_BUSY)
res = DID_BUS_BUSY << 16;
- if (pkt->entry_type == NOTIFY_ACK_TYPE &&
- pkt->handle == QLA_TGT_SKIP_HANDLE)
- return;
+ if ((pkt->handle & ~QLA_TGT_HANDLE_MASK) == QLA_TGT_SKIP_HANDLE)
+ return 0;
- sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
- if (sp) {
- sp->done(sp, res);
- return;
+ switch (pkt->entry_type) {
+ case NOTIFY_ACK_TYPE:
+ case STATUS_TYPE:
+ case STATUS_CONT_TYPE:
+ case LOGINOUT_PORT_IOCB_TYPE:
+ case CT_IOCB_TYPE:
+ case ELS_IOCB_TYPE:
+ case ABORT_IOCB_TYPE:
+ case MBX_IOCB_TYPE:
+ sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+ if (sp) {
+ sp->done(sp, res);
+ return 0;
+ }
+ break;
+
+ case ABTS_RESP_24XX:
+ case CTIO_TYPE7:
+ case CTIO_CRC2:
+ default:
+ return 1;
}
fatal:
ql_log(ql_log_warn, vha, 0x5030,
"Error entry - invalid handle/queue (%04x).\n", que);
+ return 0;
}
/**
@@ -2708,6 +2827,21 @@ qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
sp->done(sp, 0);
}
+void qla24xx_nvme_ls4_iocb(scsi_qla_host_t *vha, struct pt_ls4_request *pkt,
+ struct req_que *req)
+{
+ srb_t *sp;
+ const char func[] = "LS4_IOCB";
+ uint16_t comp_status;
+
+ sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+ if (!sp)
+ return;
+
+ comp_status = le16_to_cpu(pkt->status);
+ sp->done(sp, comp_status);
+}
+
/**
* qla24xx_process_response_queue() - Process response queue entries.
* @ha: SCSI driver HA context
@@ -2721,6 +2855,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
if (!ha->flags.fw_started)
return;
+ if (rsp->qpair->cpuid != smp_processor_id())
+ qla_cpu_update(rsp->qpair, smp_processor_id());
+
while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
@@ -2733,9 +2870,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
}
if (pkt->entry_status != 0) {
- qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt);
-
- if (qlt_24xx_process_response_error(vha, pkt))
+ if (qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt))
goto process_err;
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
@@ -2768,7 +2903,8 @@ process_err:
case ABTS_RECV_24XX:
if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
/* ensure that the ATIO queue is empty */
- qlt_handle_abts_recv(vha, (response_t *)pkt);
+ qlt_handle_abts_recv(vha, rsp,
+ (response_t *)pkt);
break;
} else {
/* drop through */
@@ -2777,11 +2913,16 @@ process_err:
case ABTS_RESP_24XX:
case CTIO_TYPE7:
case CTIO_CRC2:
- qlt_response_pkt_all_vps(vha, (response_t *)pkt);
+ qlt_response_pkt_all_vps(vha, rsp, (response_t *)pkt);
+ break;
+ case PT_LS4_REQUEST:
+ qla24xx_nvme_ls4_iocb(vha, (struct pt_ls4_request *)pkt,
+ rsp->req);
break;
case NOTIFY_ACK_TYPE:
if (pkt->handle == QLA_TGT_SKIP_HANDLE)
- qlt_response_pkt_all_vps(vha, (response_t *)pkt);
+ qlt_response_pkt_all_vps(vha, rsp,
+ (response_t *)pkt);
else
qla24xxx_nack_iocb_entry(vha, rsp->req,
(struct nack_to_isp *)pkt);
@@ -3156,10 +3297,10 @@ struct qla_init_msix_entry {
};
static const struct qla_init_msix_entry msix_entries[] = {
- { "qla2xxx (default)", qla24xx_msix_default },
- { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
- { "qla2xxx (atio_q)", qla83xx_msix_atio_q },
- { "qla2xxx (qpair_multiq)", qla2xxx_msix_rsp_q },
+ { "default", qla24xx_msix_default },
+ { "rsp_q", qla24xx_msix_rsp_q },
+ { "atio_q", qla83xx_msix_atio_q },
+ { "qpair_multiq", qla2xxx_msix_rsp_q },
};
static const struct qla_init_msix_entry qla82xx_msix_entries[] = {
@@ -3183,9 +3324,14 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
min_vecs++;
}
- ret = pci_alloc_irq_vectors_affinity(ha->pdev, min_vecs,
- ha->msix_count, PCI_IRQ_MSIX | PCI_IRQ_AFFINITY,
- &desc);
+ if (USER_CTRL_IRQ(ha)) {
+ /* user wants to control IRQ setting for target mode */
+ ret = pci_alloc_irq_vectors(ha->pdev, min_vecs,
+ ha->msix_count, PCI_IRQ_MSIX);
+ } else
+ ret = pci_alloc_irq_vectors_affinity(ha->pdev, min_vecs,
+ ha->msix_count, PCI_IRQ_MSIX | PCI_IRQ_AFFINITY,
+ &desc);
if (ret < 0) {
ql_log(ql_log_fatal, vha, 0x00c7,
@@ -3239,7 +3385,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
qentry->handle = rsp;
rsp->msix = qentry;
scnprintf(qentry->name, sizeof(qentry->name),
- "%s", msix_entries[i].name);
+ "qla2xxx%lu_%s", vha->host_no, msix_entries[i].name);
if (IS_P3P_TYPE(ha))
ret = request_irq(qentry->vector,
qla82xx_msix_entries[i].handler,
@@ -3247,7 +3393,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
else
ret = request_irq(qentry->vector,
msix_entries[i].handler,
- 0, msix_entries[i].name, rsp);
+ 0, qentry->name, rsp);
if (ret)
goto msix_register_fail;
qentry->have_irq = 1;
@@ -3263,11 +3409,12 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
rsp->msix = qentry;
qentry->handle = rsp;
scnprintf(qentry->name, sizeof(qentry->name),
- "%s", msix_entries[QLA_ATIO_VECTOR].name);
+ "qla2xxx%lu_%s", vha->host_no,
+ msix_entries[QLA_ATIO_VECTOR].name);
qentry->in_use = 1;
ret = request_irq(qentry->vector,
msix_entries[QLA_ATIO_VECTOR].handler,
- 0, msix_entries[QLA_ATIO_VECTOR].name, rsp);
+ 0, qentry->name, rsp);
qentry->have_irq = 1;
}
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index cba1fc5e8be9..7c6d1a404011 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -124,8 +124,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
}
/* if PCI error, then avoid mbx processing.*/
- if (test_bit(PCI_ERR, &base_vha->dpc_flags)) {
- ql_log(ql_log_warn, vha, 0x1191,
+ if (test_bit(PFLG_DISCONNECTED, &base_vha->dpc_flags) &&
+ test_bit(UNLOADING, &base_vha->dpc_flags)) {
+ ql_log(ql_log_warn, vha, 0xd04e,
"PCI error, exiting.\n");
return QLA_FUNCTION_TIMEOUT;
}
@@ -169,7 +170,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
*/
if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) {
/* Timeout occurred. Return error. */
- ql_log(ql_log_warn, vha, 0x1005,
+ ql_log(ql_log_warn, vha, 0xd035,
"Cmd access timeout, cmd=0x%x, Exiting.\n",
mcp->mb[0]);
return QLA_FUNCTION_TIMEOUT;
@@ -317,7 +318,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
mcp->mb[0] = MBS_LINK_DOWN_ERROR;
ha->mcp = NULL;
rval = QLA_FUNCTION_FAILED;
- ql_log(ql_log_warn, vha, 0x1015,
+ ql_log(ql_log_warn, vha, 0xd048,
"FW hung = %d.\n", ha->flags.isp82xx_fw_hung);
goto premature_exit;
}
@@ -359,7 +360,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
host_status = RD_REG_DWORD(&reg->isp24.host_status);
hccr = RD_REG_DWORD(&reg->isp24.hccr);
- ql_log(ql_log_warn, vha, 0x1119,
+ ql_log(ql_log_warn, vha, 0xd04c,
"MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
"mb[0-3]=[0x%x 0x%x 0x%x 0x%x] mb7 0x%x host_status 0x%x hccr 0x%x\n",
command, ictrl, jiffies, mb[0], mb[1], mb[2], mb[3],
@@ -384,8 +385,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
* then only PCI ERR flag would be set.
* we will do premature exit for above case.
*/
- if (test_bit(UNLOADING, &base_vha->dpc_flags))
- set_bit(PCI_ERR, &base_vha->dpc_flags);
ha->flags.mbox_busy = 0;
rval = QLA_FUNCTION_TIMEOUT;
goto premature_exit;
@@ -561,6 +560,8 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
}
#define EXTENDED_BB_CREDITS BIT_0
+#define NVME_ENABLE_FLAG BIT_3
+
/*
* qla2x00_execute_fw
* Start adapter firmware.
@@ -602,6 +603,9 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
} else
mcp->mb[4] = 0;
+ if (ql2xnvmeenable && IS_QLA27XX(ha))
+ mcp->mb[4] |= NVME_ENABLE_FLAG;
+
if (ha->flags.exlogins_enabled)
mcp->mb[4] |= ENABLE_EXTENDED_LOGIN;
@@ -822,7 +826,7 @@ qla_get_exchoffld_status(scsi_qla_host_t *vha, uint16_t *buf_sz,
*/
#define CONFIG_XCHOFFLD_MEM 0x3
int
-qla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr)
+qla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha)
{
int rval;
mbx_cmd_t mc;
@@ -835,12 +839,12 @@ qla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr)
memset(mcp->mb, 0 , sizeof(mcp->mb));
mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
mcp->mb[1] = CONFIG_XCHOFFLD_MEM;
- mcp->mb[2] = MSW(phys_addr);
- mcp->mb[3] = LSW(phys_addr);
- mcp->mb[6] = MSW(MSD(phys_addr));
- mcp->mb[7] = LSW(MSD(phys_addr));
- mcp->mb[8] = MSW(ha->exlogin_size);
- mcp->mb[9] = LSW(ha->exlogin_size);
+ mcp->mb[2] = MSW(ha->exchoffld_buf_dma);
+ mcp->mb[3] = LSW(ha->exchoffld_buf_dma);
+ mcp->mb[6] = MSW(MSD(ha->exchoffld_buf_dma));
+ mcp->mb[7] = LSW(MSD(ha->exchoffld_buf_dma));
+ mcp->mb[8] = MSW(ha->exchoffld_size);
+ mcp->mb[9] = LSW(ha->exchoffld_size);
mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_11|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
@@ -942,6 +946,22 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1191,
"%s: Firmware supports Exchange Offload 0x%x\n",
__func__, ha->fw_attributes_h);
+
+ /* bit 26 of fw_attributes */
+ if ((ha->fw_attributes_h & 0x400) && ql2xnvmeenable) {
+ struct init_cb_24xx *icb;
+
+ icb = (struct init_cb_24xx *)ha->init_cb;
+ /*
+ * fw supports nvme and driver load
+ * parameter requested nvme
+ */
+ vha->flags.nvme_enabled = 1;
+ icb->firmware_options_2 &= cpu_to_le32(~0xf);
+ ha->zio_mode = 0;
+ ha->zio_timer = 0;
+ }
+
}
if (IS_QLA27XX(ha)) {
@@ -1049,6 +1069,8 @@ qla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts)
mcp->in_mb = MBX_0;
if (IS_FWI2_CAPABLE(vha->hw)) {
mcp->in_mb |= MBX_1;
+ mcp->mb[10] = fwopts[10];
+ mcp->out_mb |= MBX_10;
} else {
mcp->mb[10] = fwopts[10];
mcp->mb[11] = fwopts[11];
@@ -3213,7 +3235,7 @@ qla8044_write_serdes_word(scsi_qla_host_t *vha, uint32_t addr, uint32_t data)
if (!IS_QLA8044(vha->hw))
return QLA_FUNCTION_FAILED;
- ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1186,
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x11a0,
"Entered %s.\n", __func__);
mcp->mb[0] = MBC_SET_GET_ETH_SERDES_REG;
@@ -3229,7 +3251,7 @@ qla8044_write_serdes_word(scsi_qla_host_t *vha, uint32_t addr, uint32_t data)
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_mbx, vha, 0x1187,
+ ql_dbg(ql_dbg_mbx, vha, 0x11a1,
"Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1188,
@@ -3713,12 +3735,12 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
set_bit(VP_DPC_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
} else if (rptid_entry->format == 2) {
- ql_dbg(ql_dbg_async, vha, 0xffff,
+ ql_dbg(ql_dbg_async, vha, 0x505f,
"RIDA: format 2/N2N Primary port id %02x%02x%02x.\n",
rptid_entry->port_id[2], rptid_entry->port_id[1],
rptid_entry->port_id[0]);
- ql_dbg(ql_dbg_async, vha, 0xffff,
+ ql_dbg(ql_dbg_async, vha, 0x5075,
"N2N: Remote WWPN %8phC.\n",
rptid_entry->u.f2.port_name);
@@ -3871,7 +3893,7 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
rval = QLA_FUNCTION_FAILED;
} else if (vce->comp_status != cpu_to_le16(CS_COMPLETE)) {
ql_dbg(ql_dbg_mbx, vha, 0x10c5,
- "Failed to complet IOCB -- completion status (%x).\n",
+ "Failed to complete IOCB -- completion status (%x).\n",
le16_to_cpu(vce->comp_status));
rval = QLA_FUNCTION_FAILED;
} else {
@@ -5790,7 +5812,7 @@ qla26xx_dport_diagnostics(scsi_qla_host_t *vha,
if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
return QLA_FUNCTION_FAILED;
- ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1192,
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f,
"Entered %s.\n", __func__);
dd_dma = dma_map_single(&vha->hw->pdev->dev,
@@ -5872,13 +5894,13 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_mbx, vha, 0xffff,
+ ql_dbg(ql_dbg_mbx, vha, 0x1018,
"%s: %s Failed submission. %x.\n",
__func__, sp->name, rval);
goto done_free_sp;
}
- ql_dbg(ql_dbg_mbx, vha, 0xffff, "MB:%s hndl %x submitted\n",
+ ql_dbg(ql_dbg_mbx, vha, 0x113f, "MB:%s hndl %x submitted\n",
sp->name, sp->handle);
wait_for_completion(&c->u.mbx.comp);
@@ -5887,16 +5909,16 @@ int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
rval = c->u.mbx.rc;
switch (rval) {
case QLA_FUNCTION_TIMEOUT:
- ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s: %s Timeout. %x.\n",
+ ql_dbg(ql_dbg_mbx, vha, 0x1140, "%s: %s Timeout. %x.\n",
__func__, sp->name, rval);
break;
case QLA_SUCCESS:
- ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s: %s done.\n",
+ ql_dbg(ql_dbg_mbx, vha, 0x119d, "%s: %s done.\n",
__func__, sp->name);
sp->free(sp);
break;
default:
- ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s: %s Failed. %x.\n",
+ ql_dbg(ql_dbg_mbx, vha, 0x119e, "%s: %s Failed. %x.\n",
__func__, sp->name, rval);
sp->free(sp);
break;
@@ -5927,8 +5949,8 @@ int qla24xx_gpdb_wait(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma);
if (pd == NULL) {
- ql_log(ql_log_warn, vha, 0xffff,
- "Failed to allocate port database structure.\n");
+ ql_log(ql_log_warn, vha, 0xd047,
+ "Failed to allocate port database structure.\n");
goto done_free_sp;
}
memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
@@ -5945,14 +5967,14 @@ int qla24xx_gpdb_wait(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
rval = qla24xx_send_mb_cmd(vha, &mc);
if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_mbx, vha, 0xffff,
+ ql_dbg(ql_dbg_mbx, vha, 0x1193,
"%s: %8phC fail\n", __func__, fcport->port_name);
goto done_free_sp;
}
rval = __qla24xx_parse_gpdb(vha, fcport, pd);
- ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s: %8phC done\n",
+ ql_dbg(ql_dbg_mbx, vha, 0x1197, "%s: %8phC done\n",
__func__, fcport->port_name);
done_free_sp:
@@ -5967,14 +5989,22 @@ int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
{
int rval = QLA_SUCCESS;
uint64_t zero = 0;
+ u8 current_login_state, last_login_state;
+
+ if (fcport->fc4f_nvme) {
+ current_login_state = pd->current_login_state >> 4;
+ last_login_state = pd->last_login_state >> 4;
+ } else {
+ current_login_state = pd->current_login_state & 0xf;
+ last_login_state = pd->last_login_state & 0xf;
+ }
/* Check for logged in state. */
- if (pd->current_login_state != PDS_PRLI_COMPLETE &&
- pd->last_login_state != PDS_PRLI_COMPLETE) {
- ql_dbg(ql_dbg_mbx, vha, 0xffff,
- "Unable to verify login-state (%x/%x) for "
- "loop_id %x.\n", pd->current_login_state,
- pd->last_login_state, fcport->loop_id);
+ if (current_login_state != PDS_PRLI_COMPLETE &&
+ last_login_state != PDS_PRLI_COMPLETE) {
+ ql_dbg(ql_dbg_mbx, vha, 0x119a,
+ "Unable to verify login-state (%x/%x) for loop_id %x.\n",
+ current_login_state, last_login_state, fcport->loop_id);
rval = QLA_FUNCTION_FAILED;
goto gpd_error_out;
}
@@ -5997,12 +6027,17 @@ int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
fcport->d_id.b.al_pa = pd->port_id[2];
fcport->d_id.b.rsvd_1 = 0;
- /* If not target must be initiator or unknown type. */
- if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
- fcport->port_type = FCT_INITIATOR;
- else
- fcport->port_type = FCT_TARGET;
-
+ if (fcport->fc4f_nvme) {
+ fcport->nvme_prli_service_param =
+ pd->prli_nvme_svc_param_word_3;
+ fcport->port_type = FCT_NVME;
+ } else {
+ /* If not target must be initiator or unknown type. */
+ if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
+ fcport->port_type = FCT_INITIATOR;
+ else
+ fcport->port_type = FCT_TARGET;
+ }
/* Passback COS information. */
fcport->supported_classes = (pd->flags & PDF_CLASS_2) ?
FC_COS_CLASS2 : FC_COS_CLASS3;
@@ -6040,12 +6075,12 @@ int qla24xx_gidlist_wait(struct scsi_qla_host *vha,
rval = qla24xx_send_mb_cmd(vha, &mc);
if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_mbx, vha, 0xffff,
- "%s: fail\n", __func__);
+ ql_dbg(ql_dbg_mbx, vha, 0x119b,
+ "%s: fail\n", __func__);
} else {
*entries = mc.mb[1];
- ql_dbg(ql_dbg_mbx, vha, 0xffff,
- "%s: done\n", __func__);
+ ql_dbg(ql_dbg_mbx, vha, 0x119c,
+ "%s: done\n", __func__);
}
done:
return rval;
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 09a490c98763..f0605cd196fb 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -640,11 +640,12 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
int
qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
- uint8_t vp_idx, uint16_t rid, int rsp_que, uint8_t qos)
+ uint8_t vp_idx, uint16_t rid, int rsp_que, uint8_t qos, bool startqp)
{
int ret = 0;
struct req_que *req = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+ struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
uint16_t que_id = 0;
device_reg_t *reg;
uint32_t cnt;
@@ -731,14 +732,17 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
req->ring_ptr, req->ring_index, req->cnt,
req->id, req->max_q_depth);
- ret = qla25xx_init_req_que(base_vha, req);
- if (ret != QLA_SUCCESS) {
- ql_log(ql_log_fatal, base_vha, 0x00df,
- "%s failed.\n", __func__);
- mutex_lock(&ha->mq_lock);
- clear_bit(que_id, ha->req_qid_map);
- mutex_unlock(&ha->mq_lock);
- goto que_failed;
+ if (startqp) {
+ ret = qla25xx_init_req_que(base_vha, req);
+ if (ret != QLA_SUCCESS) {
+ ql_log(ql_log_fatal, base_vha, 0x00df,
+ "%s failed.\n", __func__);
+ mutex_lock(&ha->mq_lock);
+ clear_bit(que_id, ha->req_qid_map);
+ mutex_unlock(&ha->mq_lock);
+ goto que_failed;
+ }
+ vha->flags.qpairs_req_created = 1;
}
return req->id;
@@ -765,11 +769,12 @@ static void qla_do_work(struct work_struct *work)
/* create response queue */
int
qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
- uint8_t vp_idx, uint16_t rid, struct qla_qpair *qpair)
+ uint8_t vp_idx, uint16_t rid, struct qla_qpair *qpair, bool startqp)
{
int ret = 0;
struct rsp_que *rsp = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+ struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
uint16_t que_id = 0;
device_reg_t *reg;
@@ -843,14 +848,17 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
if (ret)
goto que_failed;
- ret = qla25xx_init_rsp_que(base_vha, rsp);
- if (ret != QLA_SUCCESS) {
- ql_log(ql_log_fatal, base_vha, 0x00e7,
- "%s failed.\n", __func__);
- mutex_lock(&ha->mq_lock);
- clear_bit(que_id, ha->rsp_qid_map);
- mutex_unlock(&ha->mq_lock);
- goto que_failed;
+ if (startqp) {
+ ret = qla25xx_init_rsp_que(base_vha, rsp);
+ if (ret != QLA_SUCCESS) {
+ ql_log(ql_log_fatal, base_vha, 0x00e7,
+ "%s failed.\n", __func__);
+ mutex_lock(&ha->mq_lock);
+ clear_bit(que_id, ha->rsp_qid_map);
+ mutex_unlock(&ha->mq_lock);
+ goto que_failed;
+ }
+ vha->flags.qpairs_rsp_created = 1;
}
rsp->req = NULL;
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
new file mode 100644
index 000000000000..f3710a75fe1f
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -0,0 +1,761 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c) 2003-2017 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#include "qla_nvme.h"
+#include "qla_def.h"
+#include <linux/scatterlist.h>
+#include <linux/delay.h>
+#include <linux/nvme.h>
+#include <linux/nvme-fc.h>
+
+static struct nvme_fc_port_template qla_nvme_fc_transport;
+
+static void qla_nvme_unregister_remote_port(struct work_struct *);
+
+int qla_nvme_register_remote(scsi_qla_host_t *vha, fc_port_t *fcport)
+{
+ struct nvme_rport *rport;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_NVME_FC))
+ return 0;
+
+ if (fcport->nvme_flag & NVME_FLAG_REGISTERED)
+ return 0;
+
+ if (!vha->flags.nvme_enabled) {
+ ql_log(ql_log_info, vha, 0x2100,
+ "%s: Not registering target since Host NVME is not enabled\n",
+ __func__);
+ return 0;
+ }
+
+ if (!(fcport->nvme_prli_service_param &
+ (NVME_PRLI_SP_TARGET | NVME_PRLI_SP_DISCOVERY)))
+ return 0;
+
+ INIT_WORK(&fcport->nvme_del_work, qla_nvme_unregister_remote_port);
+ rport = kzalloc(sizeof(*rport), GFP_KERNEL);
+ if (!rport) {
+ ql_log(ql_log_warn, vha, 0x2101,
+ "%s: unable to alloc memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ rport->req.port_name = wwn_to_u64(fcport->port_name);
+ rport->req.node_name = wwn_to_u64(fcport->node_name);
+ rport->req.port_role = 0;
+
+ if (fcport->nvme_prli_service_param & NVME_PRLI_SP_INITIATOR)
+ rport->req.port_role = FC_PORT_ROLE_NVME_INITIATOR;
+
+ if (fcport->nvme_prli_service_param & NVME_PRLI_SP_TARGET)
+ rport->req.port_role |= FC_PORT_ROLE_NVME_TARGET;
+
+ if (fcport->nvme_prli_service_param & NVME_PRLI_SP_DISCOVERY)
+ rport->req.port_role |= FC_PORT_ROLE_NVME_DISCOVERY;
+
+ rport->req.port_id = fcport->d_id.b24;
+
+ ql_log(ql_log_info, vha, 0x2102,
+ "%s: traddr=pn-0x%016llx:nn-0x%016llx PortID:%06x\n",
+ __func__, rport->req.port_name, rport->req.node_name,
+ rport->req.port_id);
+
+ ret = nvme_fc_register_remoteport(vha->nvme_local_port, &rport->req,
+ &fcport->nvme_remote_port);
+ if (ret) {
+ ql_log(ql_log_warn, vha, 0x212e,
+ "Failed to register remote port. Transport returned %d\n",
+ ret);
+ return ret;
+ }
+
+ fcport->nvme_remote_port->private = fcport;
+ fcport->nvme_flag |= NVME_FLAG_REGISTERED;
+ atomic_set(&fcport->nvme_ref_count, 1);
+ init_waitqueue_head(&fcport->nvme_waitQ);
+ rport->fcport = fcport;
+ list_add_tail(&rport->list, &vha->nvme_rport_list);
+ return 0;
+}
+
+/* Allocate a queue for NVMe traffic */
+static int qla_nvme_alloc_queue(struct nvme_fc_local_port *lport, unsigned int qidx,
+ u16 qsize, void **handle)
+{
+ struct scsi_qla_host *vha;
+ struct qla_hw_data *ha;
+ struct qla_qpair *qpair;
+
+ if (!qidx)
+ qidx++;
+
+ vha = (struct scsi_qla_host *)lport->private;
+ ha = vha->hw;
+
+ ql_log(ql_log_info, vha, 0x2104,
+ "%s: handle %p, idx =%d, qsize %d\n",
+ __func__, handle, qidx, qsize);
+
+ if (qidx > qla_nvme_fc_transport.max_hw_queues) {
+ ql_log(ql_log_warn, vha, 0x212f,
+ "%s: Illegal qidx=%d. Max=%d\n",
+ __func__, qidx, qla_nvme_fc_transport.max_hw_queues);
+ return -EINVAL;
+ }
+
+ if (ha->queue_pair_map[qidx]) {
+ *handle = ha->queue_pair_map[qidx];
+ ql_log(ql_log_info, vha, 0x2121,
+ "Returning existing qpair of %p for idx=%x\n",
+ *handle, qidx);
+ return 0;
+ }
+
+ ql_log(ql_log_warn, vha, 0xffff,
+ "allocating q for idx=%x w/o cpu mask\n", qidx);
+ qpair = qla2xxx_create_qpair(vha, 5, vha->vp_idx, true);
+ if (qpair == NULL) {
+ ql_log(ql_log_warn, vha, 0x2122,
+ "Failed to allocate qpair\n");
+ return -EINVAL;
+ }
+ *handle = qpair;
+
+ return 0;
+}
+
+static void qla_nvme_sp_ls_done(void *ptr, int res)
+{
+ srb_t *sp = ptr;
+ struct srb_iocb *nvme;
+ struct nvmefc_ls_req *fd;
+ struct nvme_private *priv;
+
+ if (atomic_read(&sp->ref_count) == 0) {
+ ql_log(ql_log_warn, sp->fcport->vha, 0x2123,
+ "SP reference-count to ZERO on LS_done -- sp=%p.\n", sp);
+ return;
+ }
+
+ if (!atomic_dec_and_test(&sp->ref_count))
+ return;
+
+ if (res)
+ res = -EINVAL;
+
+ nvme = &sp->u.iocb_cmd;
+ fd = nvme->u.nvme.desc;
+ priv = fd->private;
+ priv->comp_status = res;
+ schedule_work(&priv->ls_work);
+ /* work schedule doesn't need the sp */
+ qla2x00_rel_sp(sp);
+}
+
+static void qla_nvme_sp_done(void *ptr, int res)
+{
+ srb_t *sp = ptr;
+ struct srb_iocb *nvme;
+ struct nvmefc_fcp_req *fd;
+
+ nvme = &sp->u.iocb_cmd;
+ fd = nvme->u.nvme.desc;
+
+ if (!atomic_dec_and_test(&sp->ref_count))
+ return;
+
+ if (!(sp->fcport->nvme_flag & NVME_FLAG_REGISTERED))
+ goto rel;
+
+ if (unlikely(nvme->u.nvme.comp_status || res))
+ fd->status = -EINVAL;
+ else
+ fd->status = 0;
+
+ fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len;
+ fd->done(fd);
+rel:
+ qla2xxx_rel_qpair_sp(sp->qpair, sp);
+}
+
+static void qla_nvme_ls_abort(struct nvme_fc_local_port *lport,
+ struct nvme_fc_remote_port *rport, struct nvmefc_ls_req *fd)
+{
+ struct nvme_private *priv = fd->private;
+ fc_port_t *fcport = rport->private;
+ srb_t *sp = priv->sp;
+ int rval;
+ struct qla_hw_data *ha = fcport->vha->hw;
+
+ rval = ha->isp_ops->abort_command(sp);
+ if (rval != QLA_SUCCESS)
+ ql_log(ql_log_warn, fcport->vha, 0x2125,
+ "%s: failed to abort LS command for SP:%p rval=%x\n",
+ __func__, sp, rval);
+
+ ql_dbg(ql_dbg_io, fcport->vha, 0x212b,
+ "%s: aborted sp:%p on fcport:%p\n", __func__, sp, fcport);
+}
+
+static void qla_nvme_ls_complete(struct work_struct *work)
+{
+ struct nvme_private *priv =
+ container_of(work, struct nvme_private, ls_work);
+ struct nvmefc_ls_req *fd = priv->fd;
+
+ fd->done(fd, priv->comp_status);
+}
+
+static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
+ struct nvme_fc_remote_port *rport, struct nvmefc_ls_req *fd)
+{
+ fc_port_t *fcport = (fc_port_t *)rport->private;
+ struct srb_iocb *nvme;
+ struct nvme_private *priv = fd->private;
+ struct scsi_qla_host *vha;
+ int rval = QLA_FUNCTION_FAILED;
+ struct qla_hw_data *ha;
+ srb_t *sp;
+
+ if (!(fcport->nvme_flag & NVME_FLAG_REGISTERED))
+ return rval;
+
+ vha = fcport->vha;
+ ha = vha->hw;
+ /* Alloc SRB structure */
+ sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
+ if (!sp)
+ return rval;
+
+ sp->type = SRB_NVME_LS;
+ sp->name = "nvme_ls";
+ sp->done = qla_nvme_sp_ls_done;
+ atomic_set(&sp->ref_count, 1);
+ init_waitqueue_head(&sp->nvme_ls_waitQ);
+ nvme = &sp->u.iocb_cmd;
+ priv->sp = sp;
+ priv->fd = fd;
+ INIT_WORK(&priv->ls_work, qla_nvme_ls_complete);
+ nvme->u.nvme.desc = fd;
+ nvme->u.nvme.dir = 0;
+ nvme->u.nvme.dl = 0;
+ nvme->u.nvme.cmd_len = fd->rqstlen;
+ nvme->u.nvme.rsp_len = fd->rsplen;
+ nvme->u.nvme.rsp_dma = fd->rspdma;
+ nvme->u.nvme.timeout_sec = fd->timeout;
+ nvme->u.nvme.cmd_dma = dma_map_single(&ha->pdev->dev, fd->rqstaddr,
+ fd->rqstlen, DMA_TO_DEVICE);
+ dma_sync_single_for_device(&ha->pdev->dev, nvme->u.nvme.cmd_dma,
+ fd->rqstlen, DMA_TO_DEVICE);
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x700e,
+ "qla2x00_start_sp failed = %d\n", rval);
+ atomic_dec(&sp->ref_count);
+ wake_up(&sp->nvme_ls_waitQ);
+ return rval;
+ }
+
+ return rval;
+}
+
+static void qla_nvme_fcp_abort(struct nvme_fc_local_port *lport,
+ struct nvme_fc_remote_port *rport, void *hw_queue_handle,
+ struct nvmefc_fcp_req *fd)
+{
+ struct nvme_private *priv = fd->private;
+ srb_t *sp = priv->sp;
+ int rval;
+ fc_port_t *fcport = rport->private;
+ struct qla_hw_data *ha = fcport->vha->hw;
+
+ rval = ha->isp_ops->abort_command(sp);
+ if (!rval)
+ ql_log(ql_log_warn, fcport->vha, 0x2127,
+ "%s: failed to abort command for SP:%p rval=%x\n",
+ __func__, sp, rval);
+
+ ql_dbg(ql_dbg_io, fcport->vha, 0x2126,
+ "%s: aborted sp:%p on fcport:%p\n", __func__, sp, fcport);
+}
+
+static void qla_nvme_poll(struct nvme_fc_local_port *lport, void *hw_queue_handle)
+{
+ struct scsi_qla_host *vha = lport->private;
+ unsigned long flags;
+ struct qla_qpair *qpair = (struct qla_qpair *)hw_queue_handle;
+
+ /* Acquire ring specific lock */
+ spin_lock_irqsave(&qpair->qp_lock, flags);
+ qla24xx_process_response_queue(vha, qpair->rsp);
+ spin_unlock_irqrestore(&qpair->qp_lock, flags);
+}
+
+static int qla2x00_start_nvme_mq(srb_t *sp)
+{
+ unsigned long flags;
+ uint32_t *clr_ptr;
+ uint32_t index;
+ uint32_t handle;
+ struct cmd_nvme *cmd_pkt;
+ uint16_t cnt, i;
+ uint16_t req_cnt;
+ uint16_t tot_dsds;
+ uint16_t avail_dsds;
+ uint32_t *cur_dsd;
+ struct req_que *req = NULL;
+ struct scsi_qla_host *vha = sp->fcport->vha;
+ struct qla_hw_data *ha = vha->hw;
+ struct qla_qpair *qpair = sp->qpair;
+ struct srb_iocb *nvme = &sp->u.iocb_cmd;
+ struct scatterlist *sgl, *sg;
+ struct nvmefc_fcp_req *fd = nvme->u.nvme.desc;
+ uint32_t rval = QLA_SUCCESS;
+
+ /* Setup qpair pointers */
+ req = qpair->req;
+ tot_dsds = fd->sg_cnt;
+
+ /* Acquire qpair specific lock */
+ spin_lock_irqsave(&qpair->qp_lock, flags);
+
+ /* Check for room in outstanding command list. */
+ handle = req->current_outstanding_cmd;
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
+ handle++;
+ if (handle == req->num_outstanding_cmds)
+ handle = 1;
+ if (!req->outstanding_cmds[handle])
+ break;
+ }
+
+ if (index == req->num_outstanding_cmds) {
+ rval = -1;
+ goto queuing_error;
+ }
+ req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+ if (req->cnt < (req_cnt + 2)) {
+ cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
+ RD_REG_DWORD_RELAXED(req->req_q_out);
+
+ if (req->ring_index < cnt)
+ req->cnt = cnt - req->ring_index;
+ else
+ req->cnt = req->length - (req->ring_index - cnt);
+
+ if (req->cnt < (req_cnt + 2)){
+ rval = -1;
+ goto queuing_error;
+ }
+ }
+
+ if (unlikely(!fd->sqid)) {
+ struct nvme_fc_cmd_iu *cmd = fd->cmdaddr;
+ if (cmd->sqe.common.opcode == nvme_admin_async_event) {
+ nvme->u.nvme.aen_op = 1;
+ atomic_inc(&vha->nvme_active_aen_cnt);
+ }
+ }
+
+ /* Build command packet. */
+ req->current_outstanding_cmd = handle;
+ req->outstanding_cmds[handle] = sp;
+ sp->handle = handle;
+ req->cnt -= req_cnt;
+
+ cmd_pkt = (struct cmd_nvme *)req->ring_ptr;
+ cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
+
+ /* Zero out remaining portion of packet. */
+ clr_ptr = (uint32_t *)cmd_pkt + 2;
+ memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
+
+ cmd_pkt->entry_status = 0;
+
+ /* Update entry type to indicate Command NVME IOCB */
+ cmd_pkt->entry_type = COMMAND_NVME;
+
+ /* No data transfer how do we check buffer len == 0?? */
+ if (fd->io_dir == NVMEFC_FCP_READ) {
+ cmd_pkt->control_flags =
+ cpu_to_le16(CF_READ_DATA | CF_NVME_ENABLE);
+ vha->qla_stats.input_bytes += fd->payload_length;
+ vha->qla_stats.input_requests++;
+ } else if (fd->io_dir == NVMEFC_FCP_WRITE) {
+ cmd_pkt->control_flags =
+ cpu_to_le16(CF_WRITE_DATA | CF_NVME_ENABLE);
+ vha->qla_stats.output_bytes += fd->payload_length;
+ vha->qla_stats.output_requests++;
+ } else if (fd->io_dir == 0) {
+ cmd_pkt->control_flags = cpu_to_le16(CF_NVME_ENABLE);
+ }
+
+ /* Set NPORT-ID */
+ cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+ cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
+ cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
+ cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
+ cmd_pkt->vp_index = sp->fcport->vha->vp_idx;
+
+ /* NVME RSP IU */
+ cmd_pkt->nvme_rsp_dsd_len = cpu_to_le16(fd->rsplen);
+ cmd_pkt->nvme_rsp_dseg_address[0] = cpu_to_le32(LSD(fd->rspdma));
+ cmd_pkt->nvme_rsp_dseg_address[1] = cpu_to_le32(MSD(fd->rspdma));
+
+ /* NVME CNMD IU */
+ cmd_pkt->nvme_cmnd_dseg_len = cpu_to_le16(fd->cmdlen);
+ cmd_pkt->nvme_cmnd_dseg_address[0] = cpu_to_le32(LSD(fd->cmddma));
+ cmd_pkt->nvme_cmnd_dseg_address[1] = cpu_to_le32(MSD(fd->cmddma));
+
+ cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
+ cmd_pkt->byte_count = cpu_to_le32(fd->payload_length);
+
+ /* One DSD is available in the Command Type NVME IOCB */
+ avail_dsds = 1;
+ cur_dsd = (uint32_t *)&cmd_pkt->nvme_data_dseg_address[0];
+ sgl = fd->first_sgl;
+
+ /* Load data segments */
+ for_each_sg(sgl, sg, tot_dsds, i) {
+ dma_addr_t sle_dma;
+ cont_a64_entry_t *cont_pkt;
+
+ /* Allocate additional continuation packets? */
+ if (avail_dsds == 0) {
+ /*
+ * Five DSDs are available in the Continuation
+ * Type 1 IOCB.
+ */
+
+ /* Adjust ring index */
+ req->ring_index++;
+ if (req->ring_index == req->length) {
+ req->ring_index = 0;
+ req->ring_ptr = req->ring;
+ } else {
+ req->ring_ptr++;
+ }
+ cont_pkt = (cont_a64_entry_t *)req->ring_ptr;
+ *((uint32_t *)(&cont_pkt->entry_type)) =
+ cpu_to_le32(CONTINUE_A64_TYPE);
+
+ cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
+ avail_dsds = 5;
+ }
+
+ sle_dma = sg_dma_address(sg);
+ *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
+ *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
+ *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ avail_dsds--;
+ }
+
+ /* Set total entry count. */
+ cmd_pkt->entry_count = (uint8_t)req_cnt;
+ wmb();
+
+ /* Adjust ring index. */
+ req->ring_index++;
+ if (req->ring_index == req->length) {
+ req->ring_index = 0;
+ req->ring_ptr = req->ring;
+ } else {
+ req->ring_ptr++;
+ }
+
+ /* Set chip new ring index. */
+ WRT_REG_DWORD(req->req_q_in, req->ring_index);
+
+queuing_error:
+ spin_unlock_irqrestore(&qpair->qp_lock, flags);
+ return rval;
+}
+
+/* Post a command */
+static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
+ struct nvme_fc_remote_port *rport, void *hw_queue_handle,
+ struct nvmefc_fcp_req *fd)
+{
+ fc_port_t *fcport;
+ struct srb_iocb *nvme;
+ struct scsi_qla_host *vha;
+ int rval = QLA_FUNCTION_FAILED;
+ srb_t *sp;
+ struct qla_qpair *qpair = (struct qla_qpair *)hw_queue_handle;
+ struct nvme_private *priv;
+
+ if (!fd) {
+ ql_log(ql_log_warn, NULL, 0x2134, "NO NVMe FCP request\n");
+ return rval;
+ }
+
+ priv = fd->private;
+ fcport = (fc_port_t *)rport->private;
+ if (!fcport) {
+ ql_log(ql_log_warn, NULL, 0x210e, "No fcport ptr\n");
+ return rval;
+ }
+
+ vha = fcport->vha;
+ if ((!qpair) || (!(fcport->nvme_flag & NVME_FLAG_REGISTERED)))
+ return -EBUSY;
+
+ /* Alloc SRB structure */
+ sp = qla2xxx_get_qpair_sp(qpair, fcport, GFP_ATOMIC);
+ if (!sp)
+ return -EIO;
+
+ atomic_set(&sp->ref_count, 1);
+ init_waitqueue_head(&sp->nvme_ls_waitQ);
+ priv->sp = sp;
+ sp->type = SRB_NVME_CMD;
+ sp->name = "nvme_cmd";
+ sp->done = qla_nvme_sp_done;
+ sp->qpair = qpair;
+ nvme = &sp->u.iocb_cmd;
+ nvme->u.nvme.desc = fd;
+
+ rval = qla2x00_start_nvme_mq(sp);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x212d,
+ "qla2x00_start_nvme_mq failed = %d\n", rval);
+ atomic_dec(&sp->ref_count);
+ wake_up(&sp->nvme_ls_waitQ);
+ return -EIO;
+ }
+
+ return rval;
+}
+
+static void qla_nvme_localport_delete(struct nvme_fc_local_port *lport)
+{
+ struct scsi_qla_host *vha = lport->private;
+
+ atomic_dec(&vha->nvme_ref_count);
+ wake_up_all(&vha->nvme_waitQ);
+
+ ql_log(ql_log_info, vha, 0x210f,
+ "localport delete of %p completed.\n", vha->nvme_local_port);
+ vha->nvme_local_port = NULL;
+}
+
+static void qla_nvme_remoteport_delete(struct nvme_fc_remote_port *rport)
+{
+ fc_port_t *fcport;
+ struct nvme_rport *r_port, *trport;
+
+ fcport = (fc_port_t *)rport->private;
+ fcport->nvme_remote_port = NULL;
+ fcport->nvme_flag &= ~NVME_FLAG_REGISTERED;
+ atomic_dec(&fcport->nvme_ref_count);
+ wake_up_all(&fcport->nvme_waitQ);
+
+ list_for_each_entry_safe(r_port, trport,
+ &fcport->vha->nvme_rport_list, list) {
+ if (r_port->fcport == fcport) {
+ list_del(&r_port->list);
+ break;
+ }
+ }
+ kfree(r_port);
+
+ ql_log(ql_log_info, fcport->vha, 0x2110,
+ "remoteport_delete of %p completed.\n", fcport);
+}
+
+static struct nvme_fc_port_template qla_nvme_fc_transport = {
+ .localport_delete = qla_nvme_localport_delete,
+ .remoteport_delete = qla_nvme_remoteport_delete,
+ .create_queue = qla_nvme_alloc_queue,
+ .delete_queue = NULL,
+ .ls_req = qla_nvme_ls_req,
+ .ls_abort = qla_nvme_ls_abort,
+ .fcp_io = qla_nvme_post_cmd,
+ .fcp_abort = qla_nvme_fcp_abort,
+ .poll_queue = qla_nvme_poll,
+ .max_hw_queues = 8,
+ .max_sgl_segments = 128,
+ .max_dif_sgl_segments = 64,
+ .dma_boundary = 0xFFFFFFFF,
+ .local_priv_sz = 8,
+ .remote_priv_sz = 0,
+ .lsrqst_priv_sz = sizeof(struct nvme_private),
+ .fcprqst_priv_sz = sizeof(struct nvme_private),
+};
+
+#define NVME_ABORT_POLLING_PERIOD 2
+static int qla_nvme_wait_on_command(srb_t *sp)
+{
+ int ret = QLA_SUCCESS;
+
+ wait_event_timeout(sp->nvme_ls_waitQ, (atomic_read(&sp->ref_count) > 1),
+ NVME_ABORT_POLLING_PERIOD*HZ);
+
+ if (atomic_read(&sp->ref_count) > 1)
+ ret = QLA_FUNCTION_FAILED;
+
+ return ret;
+}
+
+static int qla_nvme_wait_on_rport_del(fc_port_t *fcport)
+{
+ int ret = QLA_SUCCESS;
+
+ wait_event_timeout(fcport->nvme_waitQ,
+ atomic_read(&fcport->nvme_ref_count),
+ NVME_ABORT_POLLING_PERIOD*HZ);
+
+ if (atomic_read(&fcport->nvme_ref_count)) {
+ ret = QLA_FUNCTION_FAILED;
+ ql_log(ql_log_info, fcport->vha, 0x2111,
+ "timed out waiting for fcport=%p to delete\n", fcport);
+ }
+
+ return ret;
+}
+
+void qla_nvme_abort(struct qla_hw_data *ha, srb_t *sp)
+{
+ int rval;
+
+ rval = ha->isp_ops->abort_command(sp);
+ if (!rval) {
+ if (!qla_nvme_wait_on_command(sp))
+ ql_log(ql_log_warn, NULL, 0x2112,
+ "nvme_wait_on_command timed out waiting on sp=%p\n",
+ sp);
+ }
+}
+
+static void qla_nvme_abort_all(fc_port_t *fcport)
+{
+ int que, cnt;
+ unsigned long flags;
+ srb_t *sp;
+ struct qla_hw_data *ha = fcport->vha->hw;
+ struct req_que *req;
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ for (que = 0; que < ha->max_req_queues; que++) {
+ req = ha->req_q_map[que];
+ if (!req)
+ continue;
+ if (!req->outstanding_cmds)
+ continue;
+ for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
+ sp = req->outstanding_cmds[cnt];
+ if ((sp) && ((sp->type == SRB_NVME_CMD) ||
+ (sp->type == SRB_NVME_LS)) &&
+ (sp->fcport == fcport)) {
+ atomic_inc(&sp->ref_count);
+ spin_unlock_irqrestore(&ha->hardware_lock,
+ flags);
+ qla_nvme_abort(ha, sp);
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ req->outstanding_cmds[cnt] = NULL;
+ sp->done(sp, 1);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+static void qla_nvme_unregister_remote_port(struct work_struct *work)
+{
+ struct fc_port *fcport = container_of(work, struct fc_port,
+ nvme_del_work);
+ struct nvme_rport *rport, *trport;
+
+ if (!IS_ENABLED(CONFIG_NVME_FC))
+ return;
+
+ list_for_each_entry_safe(rport, trport,
+ &fcport->vha->nvme_rport_list, list) {
+ if (rport->fcport == fcport) {
+ ql_log(ql_log_info, fcport->vha, 0x2113,
+ "%s: fcport=%p\n", __func__, fcport);
+ nvme_fc_unregister_remoteport(
+ fcport->nvme_remote_port);
+ }
+ }
+}
+
+void qla_nvme_delete(scsi_qla_host_t *vha)
+{
+ struct nvme_rport *rport, *trport;
+ fc_port_t *fcport;
+ int nv_ret;
+
+ if (!IS_ENABLED(CONFIG_NVME_FC))
+ return;
+
+ list_for_each_entry_safe(rport, trport, &vha->nvme_rport_list, list) {
+ fcport = rport->fcport;
+
+ ql_log(ql_log_info, fcport->vha, 0x2114, "%s: fcport=%p\n",
+ __func__, fcport);
+
+ nvme_fc_unregister_remoteport(fcport->nvme_remote_port);
+ qla_nvme_wait_on_rport_del(fcport);
+ qla_nvme_abort_all(fcport);
+ }
+
+ if (vha->nvme_local_port) {
+ nv_ret = nvme_fc_unregister_localport(vha->nvme_local_port);
+ if (nv_ret == 0)
+ ql_log(ql_log_info, vha, 0x2116,
+ "unregistered localport=%p\n",
+ vha->nvme_local_port);
+ else
+ ql_log(ql_log_info, vha, 0x2115,
+ "Unregister of localport failed\n");
+ }
+}
+
+void qla_nvme_register_hba(scsi_qla_host_t *vha)
+{
+ struct nvme_fc_port_template *tmpl;
+ struct qla_hw_data *ha;
+ struct nvme_fc_port_info pinfo;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_NVME_FC))
+ return;
+
+ ha = vha->hw;
+ tmpl = &qla_nvme_fc_transport;
+
+ WARN_ON(vha->nvme_local_port);
+ WARN_ON(ha->max_req_queues < 3);
+
+ qla_nvme_fc_transport.max_hw_queues =
+ min((uint8_t)(qla_nvme_fc_transport.max_hw_queues),
+ (uint8_t)(ha->max_req_queues - 2));
+
+ pinfo.node_name = wwn_to_u64(vha->node_name);
+ pinfo.port_name = wwn_to_u64(vha->port_name);
+ pinfo.port_role = FC_PORT_ROLE_NVME_INITIATOR;
+ pinfo.port_id = vha->d_id.b24;
+
+ ql_log(ql_log_info, vha, 0xffff,
+ "register_localport: host-traddr=pn-0x%llx:nn-0x%llx on portID:%x\n",
+ pinfo.port_name, pinfo.node_name, pinfo.port_id);
+ qla_nvme_fc_transport.dma_boundary = vha->host->dma_boundary;
+
+ ret = nvme_fc_register_localport(&pinfo, tmpl,
+ get_device(&ha->pdev->dev), &vha->nvme_local_port);
+ if (ret) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "register_localport failed: ret=%x\n", ret);
+ return;
+ }
+ atomic_set(&vha->nvme_ref_count, 1);
+ vha->nvme_local_port->private = vha;
+ init_waitqueue_head(&vha->nvme_waitQ);
+}
diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h
new file mode 100644
index 000000000000..dfe56f207b28
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_nvme.h
@@ -0,0 +1,132 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c) 2003-2017 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#ifndef __QLA_NVME_H
+#define __QLA_NVME_H
+
+#include <linux/blk-mq.h>
+#include <uapi/scsi/fc/fc_fs.h>
+#include <uapi/scsi/fc/fc_els.h>
+#include <linux/nvme-fc-driver.h>
+
+#define NVME_ATIO_CMD_OFF 32
+#define NVME_FIRST_PACKET_CMDLEN (64 - NVME_ATIO_CMD_OFF)
+#define Q2T_NVME_NUM_TAGS 2048
+#define QLA_MAX_FC_SEGMENTS 64
+
+struct srb;
+struct nvme_private {
+ struct srb *sp;
+ struct nvmefc_ls_req *fd;
+ struct work_struct ls_work;
+ int comp_status;
+};
+
+struct nvme_rport {
+ struct nvme_fc_port_info req;
+ struct list_head list;
+ struct fc_port *fcport;
+};
+
+#define COMMAND_NVME 0x88 /* Command Type FC-NVMe IOCB */
+struct cmd_nvme {
+ 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 handle. */
+ uint16_t nport_handle; /* N_PORT handle. */
+ uint16_t timeout; /* Command timeout. */
+
+ uint16_t dseg_count; /* Data segment count. */
+ uint16_t nvme_rsp_dsd_len; /* NVMe RSP DSD length */
+
+ uint64_t rsvd;
+
+ uint16_t control_flags; /* Control Flags */
+#define CF_NVME_ENABLE BIT_9
+#define CF_DIF_SEG_DESCR_ENABLE BIT_3
+#define CF_DATA_SEG_DESCR_ENABLE BIT_2
+#define CF_READ_DATA BIT_1
+#define CF_WRITE_DATA BIT_0
+
+ uint16_t nvme_cmnd_dseg_len; /* Data segment length. */
+ uint32_t nvme_cmnd_dseg_address[2]; /* Data segment address. */
+ uint32_t nvme_rsp_dseg_address[2]; /* Data segment address. */
+
+ uint32_t byte_count; /* Total byte count. */
+
+ uint8_t port_id[3]; /* PortID of destination port. */
+ uint8_t vp_index;
+
+ uint32_t nvme_data_dseg_address[2]; /* Data segment address. */
+ uint32_t nvme_data_dseg_len; /* Data segment length. */
+};
+
+#define PT_LS4_REQUEST 0x89 /* Link Service pass-through IOCB (request) */
+struct pt_ls4_request {
+ uint8_t entry_type;
+ uint8_t entry_count;
+ uint8_t sys_define;
+ uint8_t entry_status;
+ uint32_t handle;
+ uint16_t status;
+ uint16_t nport_handle;
+ uint16_t tx_dseg_count;
+ uint8_t vp_index;
+ uint8_t rsvd;
+ uint16_t timeout;
+ uint16_t control_flags;
+#define CF_LS4_SHIFT 13
+#define CF_LS4_ORIGINATOR 0
+#define CF_LS4_RESPONDER 1
+#define CF_LS4_RESPONDER_TERM 2
+
+ uint16_t rx_dseg_count;
+ uint16_t rsvd2;
+ uint32_t exchange_address;
+ uint32_t rsvd3;
+ uint32_t rx_byte_count;
+ uint32_t tx_byte_count;
+ uint32_t dseg0_address[2];
+ uint32_t dseg0_len;
+ uint32_t dseg1_address[2];
+ uint32_t dseg1_len;
+};
+
+#define PT_LS4_UNSOL 0x56 /* pass-up unsolicited rec FC-NVMe request */
+struct pt_ls4_rx_unsol {
+ uint8_t entry_type;
+ uint8_t entry_count;
+ uint16_t rsvd0;
+ uint16_t rsvd1;
+ uint8_t vp_index;
+ uint8_t rsvd2;
+ uint16_t rsvd3;
+ uint16_t nport_handle;
+ uint16_t frame_size;
+ uint16_t rsvd4;
+ uint32_t exchange_address;
+ uint8_t d_id[3];
+ uint8_t r_ctl;
+ uint8_t s_id[3];
+ uint8_t cs_ctl;
+ uint8_t f_ctl[3];
+ uint8_t type;
+ uint16_t seq_cnt;
+ uint8_t df_ctl;
+ uint8_t seq_id;
+ uint16_t rx_id;
+ uint16_t ox_id;
+ uint32_t param;
+ uint32_t desc0;
+#define PT_LS4_PAYLOAD_OFFSET 0x2c
+#define PT_LS4_FIRST_PACKET_LEN 20
+ uint32_t desc_len;
+ uint32_t payload[3];
+};
+#endif
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 0a1723cc08cf..a77c33987703 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -782,7 +782,7 @@ qla82xx_pci_mem_write_direct(struct qla_hw_data *ha,
(qla82xx_pci_is_same_window(ha, off + size - 1) == 0)) {
write_unlock_irqrestore(&ha->hw_lock, flags);
ql_log(ql_log_fatal, vha, 0xb009,
- "%s out of bount memory "
+ "%s out of bound memory "
"access, offset is 0x%llx.\n",
QLA2XXX_DRIVER_NAME, off);
return -1;
@@ -4250,7 +4250,7 @@ qla82xx_md_collect(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_p3p, vha, 0xb040,
"[%s]: data ptr[%d]: %p, entry_hdr: %p\n"
- "entry_type: 0x%x, captrue_mask: 0x%x\n",
+ "entry_type: 0x%x, capture_mask: 0x%x\n",
__func__, i, data_ptr, entry_hdr,
entry_hdr->entry_type,
entry_hdr->d_ctrl.entry_capture_mask);
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 77624eac95a4..71a41093530e 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -7,6 +7,8 @@
#ifndef __QLA_NX_H
#define __QLA_NX_H
+#include <linux/io-64-nonatomic-lo-hi.h>
+
/*
* Following are the states of the Phantom. Phantom will set them and
* Host will read to check if the fields are correct.
@@ -819,21 +821,6 @@ struct qla82xx_uri_data_desc{
#define MIU_TEST_AGT_WRDATA_UPPER_LO (0x0b0)
#define MIU_TEST_AGT_WRDATA_UPPER_HI (0x0b4)
-#ifndef readq
-static inline u64 readq(void __iomem *addr)
-{
- return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
-}
-#endif
-
-#ifndef writeq
-static inline void writeq(u64 val, void __iomem *addr)
-{
- writel(((u32) (val)), (addr));
- writel(((u32) (val >> 32)), (addr + 4));
-}
-#endif
-
/* Request and response queue size */
#define REQUEST_ENTRY_CNT_82XX 128 /* Number of request entries. */
#define RESPONSE_ENTRY_CNT_82XX 128 /* Number of response entries.*/
diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c
index dc1ec9b61027..0aa9c38bf347 100644
--- a/drivers/scsi/qla2xxx/qla_nx2.c
+++ b/drivers/scsi/qla2xxx/qla_nx2.c
@@ -1572,7 +1572,7 @@ qla8044_read_reset_template(struct scsi_qla_host *vha)
/* Copy rest of the template */
if (qla8044_read_flash_data(vha, p_buff, addr, tmplt_hdr_def_size)) {
ql_log(ql_log_fatal, vha, 0xb0bd,
- "%s: Failed to read reset tempelate\n", __func__);
+ "%s: Failed to read reset template\n", __func__);
goto exit_read_template_error;
}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 79f050256c55..df57655779ed 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -120,7 +120,11 @@ MODULE_PARM_DESC(ql2xmaxqdepth,
"Maximum queue depth to set for each LUN. "
"Default is 32.");
+#if (IS_ENABLED(CONFIG_NVME_FC))
+int ql2xenabledif;
+#else
int ql2xenabledif = 2;
+#endif
module_param(ql2xenabledif, int, S_IRUGO);
MODULE_PARM_DESC(ql2xenabledif,
" Enable T10-CRC-DIF:\n"
@@ -129,6 +133,16 @@ MODULE_PARM_DESC(ql2xenabledif,
" 1 -- Enable DIF for all types\n"
" 2 -- Enable DIF for all types, except Type 0.\n");
+#if (IS_ENABLED(CONFIG_NVME_FC))
+int ql2xnvmeenable = 1;
+#else
+int ql2xnvmeenable;
+#endif
+module_param(ql2xnvmeenable, int, 0644);
+MODULE_PARM_DESC(ql2xnvmeenable,
+ "Enables NVME support. "
+ "0 - no NVMe. Default is Y");
+
int ql2xenablehba_err_chk = 2;
module_param(ql2xenablehba_err_chk, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xenablehba_err_chk,
@@ -224,11 +238,15 @@ MODULE_PARM_DESC(ql2xexlogins,
"Number of extended Logins. "
"0 (Default)- Disabled.");
-int ql2xexchoffld = 0;
-module_param(ql2xexchoffld, uint, S_IRUGO|S_IWUSR);
+int ql2xexchoffld = 1024;
+module_param(ql2xexchoffld, uint, 0644);
MODULE_PARM_DESC(ql2xexchoffld,
- "Number of exchanges to offload. "
- "0 (Default)- Disabled.");
+ "Number of target exchanges.");
+
+int ql2xiniexchg = 1024;
+module_param(ql2xiniexchg, uint, 0644);
+MODULE_PARM_DESC(ql2xiniexchg,
+ "Number of initiator exchanges.");
int ql2xfwholdabts = 0;
module_param(ql2xfwholdabts, int, S_IRUGO);
@@ -263,6 +281,7 @@ static void qla2x00_clear_drv_active(struct qla_hw_data *);
static void qla2x00_free_device(scsi_qla_host_t *);
static void qla83xx_disable_laser(scsi_qla_host_t *vha);
static int qla2xxx_map_queues(struct Scsi_Host *shost);
+static void qla2x00_destroy_deferred_work(struct qla_hw_data *);
struct scsi_host_template qla2xxx_driver_template = {
.module = THIS_MODULE,
@@ -347,6 +366,28 @@ int qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
struct qla_qpair *qpair);
/* -------------------------------------------------------------------------- */
+static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req,
+ struct rsp_que *rsp)
+{
+ struct qla_hw_data *ha = vha->hw;
+ rsp->qpair = ha->base_qpair;
+ rsp->req = req;
+ ha->base_qpair->req = req;
+ ha->base_qpair->rsp = rsp;
+ ha->base_qpair->vha = vha;
+ ha->base_qpair->qp_lock_ptr = &ha->hardware_lock;
+ ha->base_qpair->use_shadow_reg = IS_SHADOW_REG_CAPABLE(ha) ? 1 : 0;
+ ha->base_qpair->msix = &ha->msix_entries[QLA_MSIX_RSP_Q];
+ INIT_LIST_HEAD(&ha->base_qpair->hints_list);
+ ha->base_qpair->enable_class_2 = ql2xenableclass2;
+ /* init qpair to this cpu. Will adjust at run time. */
+ qla_cpu_update(rsp->qpair, smp_processor_id());
+ ha->base_qpair->pdev = ha->pdev;
+
+ if (IS_QLA27XX(ha) || IS_QLA83XX(ha))
+ ha->base_qpair->reqq_start_iocbs = qla_83xx_start_iocbs;
+}
+
static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
struct rsp_que *rsp)
{
@@ -367,6 +408,15 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
goto fail_rsp_map;
}
+ ha->base_qpair = kzalloc(sizeof(struct qla_qpair), GFP_KERNEL);
+ if (ha->base_qpair == NULL) {
+ ql_log(ql_log_warn, vha, 0x00e0,
+ "Failed to allocate base queue pair memory.\n");
+ goto fail_base_qpair;
+ }
+
+ qla_init_base_qpair(vha, req, rsp);
+
if (ql2xmqsupport && ha->max_qpairs) {
ha->queue_pair_map = kcalloc(ha->max_qpairs, sizeof(struct qla_qpair *),
GFP_KERNEL);
@@ -375,14 +425,6 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
"Unable to allocate memory for queue pair ptrs.\n");
goto fail_qpair_map;
}
- ha->base_qpair = kzalloc(sizeof(struct qla_qpair), GFP_KERNEL);
- if (ha->base_qpair == NULL) {
- ql_log(ql_log_warn, vha, 0x0182,
- "Failed to allocate base queue pair memory.\n");
- goto fail_base_qpair;
- }
- ha->base_qpair->req = req;
- ha->base_qpair->rsp = rsp;
}
/*
@@ -395,9 +437,10 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
set_bit(0, ha->req_qid_map);
return 1;
-fail_base_qpair:
- kfree(ha->queue_pair_map);
fail_qpair_map:
+ kfree(ha->base_qpair);
+ ha->base_qpair = NULL;
+fail_base_qpair:
kfree(ha->rsp_q_map);
ha->rsp_q_map = NULL;
fail_rsp_map:
@@ -447,6 +490,15 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
int cnt;
unsigned long flags;
+ if (ha->queue_pair_map) {
+ kfree(ha->queue_pair_map);
+ ha->queue_pair_map = NULL;
+ }
+ if (ha->base_qpair) {
+ kfree(ha->base_qpair);
+ ha->base_qpair = NULL;
+ }
+
spin_lock_irqsave(&ha->hardware_lock, flags);
for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
if (!test_bit(cnt, ha->req_qid_map))
@@ -658,8 +710,10 @@ qla2x00_sp_free_dma(void *ptr)
}
end:
- CMD_SP(cmd) = NULL;
- qla2x00_rel_sp(sp);
+ if ((sp->type != SRB_NVME_CMD) && (sp->type != SRB_NVME_LS)) {
+ CMD_SP(cmd) = NULL;
+ qla2x00_rel_sp(sp);
+ }
}
void
@@ -1062,9 +1116,9 @@ static inline int test_fcport_count(scsi_qla_host_t *vha)
int res;
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- ql_dbg(ql_dbg_init, vha, 0xffff,
- "tgt %p, fcport_count=%d\n",
- vha, vha->fcport_count);
+ ql_dbg(ql_dbg_init, vha, 0x00ec,
+ "tgt %p, fcport_count=%d\n",
+ vha, vha->fcport_count);
res = (vha->fcport_count == 0);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
@@ -1645,8 +1699,9 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
srb_t *sp;
struct qla_hw_data *ha = vha->hw;
struct req_que *req;
-
- qlt_host_reset_handler(ha);
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ struct qla_tgt_cmd *cmd;
+ uint8_t trace = 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
for (que = 0; que < ha->max_req_queues; que++) {
@@ -1658,27 +1713,65 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (sp) {
- /* Don't abort commands in adapter during EEH
- * recovery as it's not accessible/responding.
- */
- if (GET_CMD_SP(sp) && !ha->flags.eeh_busy &&
- (sp->type == SRB_SCSI_CMD)) {
- /* Get a reference to the sp and drop the lock.
- * The reference ensures this sp->done() call
- * - and not the call in qla2xxx_eh_abort() -
- * ends the SCSI command (with result 'res').
- */
- sp_get(sp);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- status = qla2xxx_eh_abort(GET_CMD_SP(sp));
- spin_lock_irqsave(&ha->hardware_lock, flags);
- /* Get rid of extra reference if immediate exit
- * from ql2xxx_eh_abort */
- if (status == FAILED && (qla2x00_isp_reg_stat(ha)))
- atomic_dec(&sp->ref_count);
- }
req->outstanding_cmds[cnt] = NULL;
- sp->done(sp, res);
+ if (sp->cmd_type == TYPE_SRB) {
+ if ((sp->type == SRB_NVME_CMD) ||
+ (sp->type == SRB_NVME_LS)) {
+ sp_get(sp);
+ spin_unlock_irqrestore(
+ &ha->hardware_lock, flags);
+ qla_nvme_abort(ha, sp);
+ spin_lock_irqsave(
+ &ha->hardware_lock, flags);
+ } else if (GET_CMD_SP(sp) &&
+ !ha->flags.eeh_busy &&
+ (sp->type == SRB_SCSI_CMD)) {
+ /*
+ * Don't abort commands in
+ * adapter during EEH
+ * recovery as it's not
+ * accessible/responding.
+ *
+ * Get a reference to the sp
+ * and drop the lock. The
+ * reference ensures this
+ * sp->done() call and not the
+ * call in qla2xxx_eh_abort()
+ * ends the SCSI command (with
+ * result 'res').
+ */
+ sp_get(sp);
+ spin_unlock_irqrestore(
+ &ha->hardware_lock, flags);
+ status = qla2xxx_eh_abort(
+ GET_CMD_SP(sp));
+ spin_lock_irqsave(
+ &ha->hardware_lock, flags);
+ /*
+ * Get rid of extra reference
+ * if immediate exit from
+ * ql2xxx_eh_abort
+ */
+ if (status == FAILED &&
+ (qla2x00_isp_reg_stat(ha)))
+ atomic_dec(
+ &sp->ref_count);
+ }
+ sp->done(sp, res);
+ } else {
+ if (!vha->hw->tgt.tgt_ops || !tgt ||
+ qla_ini_mode_enabled(vha)) {
+ if (!trace)
+ ql_dbg(ql_dbg_tgt_mgt,
+ vha, 0xf003,
+ "HOST-ABORT-HNDLR: dpc_flags=%lx. Target mode disabled\n",
+ vha->dpc_flags);
+ continue;
+ }
+ cmd = (struct qla_tgt_cmd *)sp;
+ qlt_abort_cmd_on_host_reset(cmd->vha,
+ cmd);
+ }
}
}
}
@@ -1957,7 +2050,7 @@ qla83xx_iospace_config(struct qla_hw_data *ha)
/* Read MSIX vector size of the board */
pci_read_config_word(ha->pdev,
QLA_83XX_PCI_MSIX_CONTROL, &msix);
- ha->msix_count = msix + 1;
+ ha->msix_count = (msix & PCI_MSIX_FLAGS_QSIZE) + 1;
/*
* By default, driver uses at least two msix vectors
* (default & rspq)
@@ -1975,7 +2068,7 @@ qla83xx_iospace_config(struct qla_hw_data *ha)
/* Queue pairs is the max value minus
* the base queue pair */
ha->max_qpairs = ha->max_req_queues - 1;
- ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0190,
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x00e3,
"Max no of queues pairs: %d.\n", ha->max_qpairs);
}
ql_log_pci(ql_log_info, ha->pdev, 0x011c,
@@ -2653,7 +2746,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ql_dbg_pci(ql_dbg_init, pdev, 0x000a,
"Memory allocated for ha=%p.\n", ha);
ha->pdev = pdev;
- ha->tgt.enable_class_2 = ql2xenableclass2;
INIT_LIST_HEAD(&ha->tgt.q_full_list);
spin_lock_init(&ha->tgt.q_full_lock);
spin_lock_init(&ha->tgt.sess_lock);
@@ -3073,12 +3165,26 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
host->can_queue, base_vha->req,
base_vha->mgmt_svr_loop_id, host->sg_tablesize);
- if (ha->mqenable && qla_ini_mode_enabled(base_vha)) {
+ if (ha->mqenable) {
+ bool mq = false;
+ bool startit = false;
ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1);
- /* Create start of day qpairs for Block MQ */
- if (shost_use_blk_mq(host)) {
+
+ if (QLA_TGT_MODE_ENABLED()) {
+ mq = true;
+ startit = false;
+ }
+
+ if ((ql2x_ini_mode == QLA2XXX_INI_MODE_ENABLED) &&
+ shost_use_blk_mq(host)) {
+ mq = true;
+ startit = true;
+ }
+
+ if (mq) {
+ /* Create start of day qpairs for Block MQ */
for (i = 0; i < ha->max_qpairs; i++)
- qla2xxx_create_qpair(base_vha, 5, 0);
+ qla2xxx_create_qpair(base_vha, 5, 0, startit);
}
}
@@ -3451,6 +3557,9 @@ qla2x00_remove_one(struct pci_dev *pdev)
return;
set_bit(UNLOADING, &base_vha->dpc_flags);
+
+ qla_nvme_delete(base_vha);
+
dma_free_coherent(&ha->pdev->dev,
base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
@@ -3601,10 +3710,10 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
} else {
int now;
if (rport) {
- ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
- "%s %8phN. rport %p roles %x \n",
- __func__, fcport->port_name, rport,
- rport->roles);
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x2109,
+ "%s %8phN. rport %p roles %x\n",
+ __func__, fcport->port_name, rport,
+ rport->roles);
fc_remote_port_delete(rport);
}
qlt_do_generation_tick(vha, &now);
@@ -3649,7 +3758,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
if (fcport->login_retry == 0) {
fcport->login_retry = vha->hw->login_retry_count;
- ql_dbg(ql_dbg_disc, vha, 0x2067,
+ ql_dbg(ql_dbg_disc, vha, 0x20a3,
"Port login retry %8phN, lid 0x%04x retry cnt=%d.\n",
fcport->port_name, fcport->loop_id, fcport->login_retry);
}
@@ -3673,8 +3782,8 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
{
fc_port_t *fcport;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Mark all dev lost\n");
+ ql_dbg(ql_dbg_disc, vha, 0x20f1,
+ "Mark all dev lost\n");
list_for_each_entry(fcport, &vha->vp_fcports, list) {
fcport->scan_state = 0;
@@ -3986,6 +4095,9 @@ qla2x00_set_exlogins_buffer(scsi_qla_host_t *vha)
if (!ql2xexlogins)
return QLA_SUCCESS;
+ if (!IS_EXLOGIN_OFFLD_CAPABLE(ha))
+ return QLA_SUCCESS;
+
ql_log(ql_log_info, vha, 0xd021, "EXLOGIN count: %d.\n", ql2xexlogins);
max_cnt = 0;
rval = qla_get_exlogin_status(vha, &size, &max_cnt);
@@ -3996,27 +4108,33 @@ qla2x00_set_exlogins_buffer(scsi_qla_host_t *vha)
}
temp = (ql2xexlogins > max_cnt) ? max_cnt : ql2xexlogins;
- ha->exlogin_size = (size * temp);
- ql_log(ql_log_info, vha, 0xd024,
- "EXLOGIN: max_logins=%d, portdb=0x%x, total=%d.\n",
- max_cnt, size, temp);
-
- ql_log(ql_log_info, vha, 0xd025, "EXLOGIN: requested size=0x%x\n",
- ha->exlogin_size);
-
- /* Get consistent memory for extended logins */
- ha->exlogin_buf = dma_alloc_coherent(&ha->pdev->dev,
- ha->exlogin_size, &ha->exlogin_buf_dma, GFP_KERNEL);
- if (!ha->exlogin_buf) {
- ql_log_pci(ql_log_fatal, ha->pdev, 0xd02a,
+ temp *= size;
+
+ if (temp != ha->exlogin_size) {
+ qla2x00_free_exlogin_buffer(ha);
+ ha->exlogin_size = temp;
+
+ ql_log(ql_log_info, vha, 0xd024,
+ "EXLOGIN: max_logins=%d, portdb=0x%x, total=%d.\n",
+ max_cnt, size, temp);
+
+ ql_log(ql_log_info, vha, 0xd025,
+ "EXLOGIN: requested size=0x%x\n", ha->exlogin_size);
+
+ /* Get consistent memory for extended logins */
+ ha->exlogin_buf = dma_alloc_coherent(&ha->pdev->dev,
+ ha->exlogin_size, &ha->exlogin_buf_dma, GFP_KERNEL);
+ if (!ha->exlogin_buf) {
+ ql_log_pci(ql_log_fatal, ha->pdev, 0xd02a,
"Failed to allocate memory for exlogin_buf_dma.\n");
- return -ENOMEM;
+ return -ENOMEM;
+ }
}
/* Now configure the dma buffer */
rval = qla_set_exlogin_mem_cfg(vha, ha->exlogin_buf_dma);
if (rval) {
- ql_log(ql_log_fatal, vha, 0x00cf,
+ ql_log(ql_log_fatal, vha, 0xd033,
"Setup extended login buffer ****FAILED****.\n");
qla2x00_free_exlogin_buffer(ha);
}
@@ -4041,19 +4159,50 @@ qla2x00_free_exlogin_buffer(struct qla_hw_data *ha)
}
}
+static void
+qla2x00_number_of_exch(scsi_qla_host_t *vha, u32 *ret_cnt, u16 max_cnt)
+{
+ u32 temp;
+ *ret_cnt = FW_DEF_EXCHANGES_CNT;
+
+ if (qla_ini_mode_enabled(vha)) {
+ if (ql2xiniexchg > max_cnt)
+ ql2xiniexchg = max_cnt;
+
+ if (ql2xiniexchg > FW_DEF_EXCHANGES_CNT)
+ *ret_cnt = ql2xiniexchg;
+ } else if (qla_tgt_mode_enabled(vha)) {
+ if (ql2xexchoffld > max_cnt)
+ ql2xexchoffld = max_cnt;
+
+ if (ql2xexchoffld > FW_DEF_EXCHANGES_CNT)
+ *ret_cnt = ql2xexchoffld;
+ } else if (qla_dual_mode_enabled(vha)) {
+ temp = ql2xiniexchg + ql2xexchoffld;
+ if (temp > max_cnt) {
+ ql2xiniexchg -= (temp - max_cnt)/2;
+ ql2xexchoffld -= (((temp - max_cnt)/2) + 1);
+ temp = max_cnt;
+ }
+
+ if (temp > FW_DEF_EXCHANGES_CNT)
+ *ret_cnt = temp;
+ }
+}
+
int
qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
{
int rval;
- uint16_t size, max_cnt, temp;
+ u16 size, max_cnt;
+ u32 temp;
struct qla_hw_data *ha = vha->hw;
- /* Return if we don't need to alloacate any extended logins */
- if (!ql2xexchoffld)
+ if (!ha->flags.exchoffld_enabled)
return QLA_SUCCESS;
- ql_log(ql_log_info, vha, 0xd014,
- "Exchange offload count: %d.\n", ql2xexlogins);
+ if (!IS_EXCHG_OFFLD_CAPABLE(ha))
+ return QLA_SUCCESS;
max_cnt = 0;
rval = qla_get_exchoffld_status(vha, &size, &max_cnt);
@@ -4063,30 +4212,45 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
return rval;
}
- temp = (ql2xexchoffld > max_cnt) ? max_cnt : ql2xexchoffld;
- ha->exchoffld_size = (size * temp);
- ql_log(ql_log_info, vha, 0xd016,
- "Exchange offload: max_count=%d, buffers=0x%x, total=%d.\n",
- max_cnt, size, temp);
-
- ql_log(ql_log_info, vha, 0xd017,
- "Exchange Buffers requested size = 0x%x\n", ha->exchoffld_size);
+ qla2x00_number_of_exch(vha, &temp, max_cnt);
+ temp *= size;
- /* Get consistent memory for extended logins */
- ha->exchoffld_buf = dma_alloc_coherent(&ha->pdev->dev,
- ha->exchoffld_size, &ha->exchoffld_buf_dma, GFP_KERNEL);
- if (!ha->exchoffld_buf) {
- ql_log_pci(ql_log_fatal, ha->pdev, 0xd013,
- "Failed to allocate memory for exchoffld_buf_dma.\n");
- return -ENOMEM;
+ if (temp != ha->exchoffld_size) {
+ qla2x00_free_exchoffld_buffer(ha);
+ ha->exchoffld_size = temp;
+
+ ql_log(ql_log_info, vha, 0xd016,
+ "Exchange offload: max_count=%d, buffers=0x%x, total=%d.\n",
+ max_cnt, size, temp);
+
+ ql_log(ql_log_info, vha, 0xd017,
+ "Exchange Buffers requested size = 0x%x\n",
+ ha->exchoffld_size);
+
+ /* Get consistent memory for extended logins */
+ ha->exchoffld_buf = dma_alloc_coherent(&ha->pdev->dev,
+ ha->exchoffld_size, &ha->exchoffld_buf_dma, GFP_KERNEL);
+ if (!ha->exchoffld_buf) {
+ ql_log_pci(ql_log_fatal, ha->pdev, 0xd013,
+ "Failed to allocate memory for exchoffld_buf_dma.\n");
+ return -ENOMEM;
+ }
}
/* Now configure the dma buffer */
- rval = qla_set_exchoffld_mem_cfg(vha, ha->exchoffld_buf_dma);
+ rval = qla_set_exchoffld_mem_cfg(vha);
if (rval) {
ql_log(ql_log_fatal, vha, 0xd02e,
"Setup exchange offload buffer ****FAILED****.\n");
qla2x00_free_exchoffld_buffer(ha);
+ } else {
+ /* re-adjust number of target exchange */
+ struct init_cb_81xx *icb = (struct init_cb_81xx *)ha->init_cb;
+
+ if (qla_ini_mode_enabled(vha))
+ icb->exchange_count = 0;
+ else
+ icb->exchange_count = cpu_to_le16(ql2xexchoffld);
}
return rval;
@@ -4292,6 +4456,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
INIT_LIST_HEAD(&vha->plogi_ack_list);
INIT_LIST_HEAD(&vha->qp_list);
INIT_LIST_HEAD(&vha->gnl.fcports);
+ INIT_LIST_HEAD(&vha->nvme_rport_list);
spin_lock_init(&vha->work_lock);
spin_lock_init(&vha->cmd_list_lock);
@@ -4303,7 +4468,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
vha->gnl.l = dma_alloc_coherent(&ha->pdev->dev,
vha->gnl.size, &vha->gnl.ldma, GFP_KERNEL);
if (!vha->gnl.l) {
- ql_log(ql_log_fatal, vha, 0xffff,
+ ql_log(ql_log_fatal, vha, 0xd04a,
"Alloc failed for name list.\n");
scsi_remove_host(vha->host);
return NULL;
@@ -4581,6 +4746,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
qla24xx_async_gpdb(vha, e->u.fcport.fcport,
e->u.fcport.opt);
break;
+ case QLA_EVT_PRLI:
+ qla24xx_async_prli(vha, e->u.fcport.fcport);
+ break;
case QLA_EVT_GPSC:
qla24xx_async_gpsc(vha, e->u.fcport.fcport);
break;
@@ -4620,7 +4788,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
fcport->login_retry--;
if (fcport->flags & FCF_FABRIC_DEVICE) {
- ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x2108,
"%s %8phC DS %d LS %d\n", __func__,
fcport->port_name, fcport->disc_state,
fcport->fw_login_state);
@@ -5800,6 +5968,8 @@ qla2x00_timer(scsi_qla_host_t *vha)
sp = req->outstanding_cmds[index];
if (!sp)
continue;
+ if (sp->cmd_type != TYPE_SRB)
+ continue;
if (sp->type != SRB_SCSI_CMD)
continue;
sfcp = sp->fcport;
@@ -5851,6 +6021,18 @@ qla2x00_timer(scsi_qla_host_t *vha)
if (!list_empty(&vha->work_list))
start_dpc++;
+ /*
+ * FC-NVME
+ * see if the active AEN count has changed from what was last reported.
+ */
+ if (atomic_read(&vha->nvme_active_aen_cnt) != vha->nvme_last_rptd_aen) {
+ vha->nvme_last_rptd_aen =
+ atomic_read(&vha->nvme_active_aen_cnt);
+ ql_log(ql_log_info, vha, 0x3002,
+ "reporting new aen count of %d to the fw\n",
+ vha->nvme_last_rptd_aen);
+ }
+
/* Schedule the DPC routine if needed */
if ((test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index e766d8412384..2a0173e5d10e 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -59,13 +59,20 @@ MODULE_PARM_DESC(qlini_mode,
"when ready "
"\"enabled\" (default) - initiator mode will always stay enabled.");
-static int ql_dm_tgt_ex_pct = 50;
+static int ql_dm_tgt_ex_pct = 0;
module_param(ql_dm_tgt_ex_pct, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql_dm_tgt_ex_pct,
"For Dual Mode (qlini_mode=dual), this parameter determines "
"the percentage of exchanges/cmds FW will allocate resources "
"for Target mode.");
+int ql2xuctrlirq = 1;
+module_param(ql2xuctrlirq, int, 0644);
+MODULE_PARM_DESC(ql2xuctrlirq,
+ "User to control IRQ placement via smp_affinity."
+ "Valid with qlini_mode=disabled."
+ "1(default): enable");
+
int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
static int temp_sam_status = SAM_STAT_BUSY;
@@ -110,18 +117,17 @@ enum fcp_resp_rsp_codes {
/* Predefs for callbacks handed to qla2xxx LLD */
static void qlt_24xx_atio_pkt(struct scsi_qla_host *ha,
struct atio_from_isp *pkt, uint8_t);
-static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt);
+static void qlt_response_pkt(struct scsi_qla_host *ha, struct rsp_que *rsp,
+ response_t *pkt);
static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun,
int fn, void *iocb, int flags);
-static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd
+static void qlt_send_term_exchange(struct qla_qpair *, struct qla_tgt_cmd
*cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort);
-static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha,
- struct qla_tgt_cmd *cmd);
static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
struct atio_from_isp *atio, uint16_t status, int qfull);
static void qlt_disable_vha(struct scsi_qla_host *vha);
static void qlt_clear_tgt_db(struct qla_tgt *tgt);
-static void qlt_send_notify_ack(struct scsi_qla_host *vha,
+static void qlt_send_notify_ack(struct qla_qpair *qpair,
struct imm_ntfy_from_isp *ntfy,
uint32_t add_flags, uint16_t resp_code, int resp_code_valid,
uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan);
@@ -132,6 +138,8 @@ static struct fc_port *qlt_create_sess(struct scsi_qla_host *vha,
void qlt_unreg_sess(struct fc_port *sess);
static void qlt_24xx_handle_abts(struct scsi_qla_host *,
struct abts_recv_from_24xx *);
+static void qlt_send_busy(struct qla_qpair *, struct atio_from_isp *,
+ uint16_t);
/*
* Global Variables
@@ -200,8 +208,8 @@ struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha,
host = btree_lookup32(&vha->hw->tgt.host_map, key);
if (!host)
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
- "Unable to find host %06x\n", key);
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005,
+ "Unable to find host %06x\n", key);
return host;
}
@@ -245,26 +253,22 @@ static inline void qlt_decr_num_pend_cmds(struct scsi_qla_host *vha)
static void qlt_queue_unknown_atio(scsi_qla_host_t *vha,
- struct atio_from_isp *atio, uint8_t ha_locked)
+ struct atio_from_isp *atio, uint8_t ha_locked)
{
struct qla_tgt_sess_op *u;
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
unsigned long flags;
if (tgt->tgt_stop) {
- ql_dbg(ql_dbg_async, vha, 0xffff,
- "qla_target(%d): dropping unknown ATIO_TYPE7, "
- "because tgt is being stopped", vha->vp_idx);
+ ql_dbg(ql_dbg_async, vha, 0x502c,
+ "qla_target(%d): dropping unknown ATIO_TYPE7, because tgt is being stopped",
+ vha->vp_idx);
goto out_term;
}
u = kzalloc(sizeof(*u), GFP_ATOMIC);
- if (u == NULL) {
- ql_dbg(ql_dbg_async, vha, 0xffff,
- "Alloc of struct unknown_atio (size %zd) failed", sizeof(*u));
- /* It should be harmless and on the next retry should work well */
+ if (u == NULL)
goto out_term;
- }
u->vha = vha;
memcpy(&u->atio, atio, sizeof(*atio));
@@ -280,7 +284,7 @@ out:
return;
out_term:
- qlt_send_term_exchange(vha, NULL, atio, ha_locked, 0);
+ qlt_send_term_exchange(vha->hw->base_qpair, NULL, atio, ha_locked, 0);
goto out;
}
@@ -295,29 +299,28 @@ static void qlt_try_to_dequeue_unknown_atios(struct scsi_qla_host *vha,
list_for_each_entry_safe(u, t, &vha->unknown_atio_list, cmd_list) {
if (u->aborted) {
- ql_dbg(ql_dbg_async, vha, 0xffff,
- "Freeing unknown %s %p, because of Abort",
+ ql_dbg(ql_dbg_async, vha, 0x502e,
+ "Freeing unknown %s %p, because of Abort\n",
"ATIO_TYPE7", u);
- qlt_send_term_exchange(vha, NULL, &u->atio,
- ha_locked, 0);
+ qlt_send_term_exchange(vha->hw->base_qpair, NULL,
+ &u->atio, ha_locked, 0);
goto abort;
}
host = qlt_find_host_by_d_id(vha, u->atio.u.isp24.fcp_hdr.d_id);
if (host != NULL) {
- ql_dbg(ql_dbg_async, vha, 0xffff,
- "Requeuing unknown ATIO_TYPE7 %p", u);
+ ql_dbg(ql_dbg_async, vha, 0x502f,
+ "Requeuing unknown ATIO_TYPE7 %p\n", u);
qlt_24xx_atio_pkt(host, &u->atio, ha_locked);
} else if (tgt->tgt_stop) {
- ql_dbg(ql_dbg_async, vha, 0xffff,
- "Freeing unknown %s %p, because tgt is being stopped",
- "ATIO_TYPE7", u);
- qlt_send_term_exchange(vha, NULL, &u->atio,
- ha_locked, 0);
+ ql_dbg(ql_dbg_async, vha, 0x503a,
+ "Freeing unknown %s %p, because tgt is being stopped\n",
+ "ATIO_TYPE7", u);
+ qlt_send_term_exchange(vha->hw->base_qpair, NULL,
+ &u->atio, ha_locked, 0);
} else {
- ql_dbg(ql_dbg_async, vha, 0xffff,
- "u %p, vha %p, host %p, sched again..", u,
- vha, host);
+ ql_dbg(ql_dbg_async, vha, 0x503d,
+ "Reschedule u %p, vha %p, host %p\n", u, vha, host);
if (!queued) {
queued = 1;
schedule_delayed_work(&vha->unknown_atio_work,
@@ -380,6 +383,8 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
struct imm_ntfy_from_isp *entry =
(struct imm_ntfy_from_isp *)atio;
+ qlt_issue_marker(vha, ha_locked);
+
if ((entry->u.isp24.vp_index != 0xFF) &&
(entry->u.isp24.nport_handle != 0xFFFF)) {
host = qlt_find_host_by_vp_idx(vha,
@@ -411,7 +416,7 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
unsigned long flags;
if (unlikely(!host)) {
- ql_dbg(ql_dbg_tgt, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt, vha, 0xe00a,
"qla_target(%d): Response pkt (ABTS_RECV_24XX) "
"received, with unknown vp_index %d\n",
vha->vp_idx, entry->vp_index);
@@ -437,7 +442,8 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
return false;
}
-void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
+void qlt_response_pkt_all_vps(struct scsi_qla_host *vha,
+ struct rsp_que *rsp, response_t *pkt)
{
switch (pkt->entry_type) {
case CTIO_CRC2:
@@ -456,7 +462,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
vha->vp_idx, entry->vp_index);
break;
}
- qlt_response_pkt(host, pkt);
+ qlt_response_pkt(host, rsp, pkt);
break;
}
@@ -474,7 +480,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
vha->vp_idx, entry->u.isp24.vp_index);
break;
}
- qlt_response_pkt(host, pkt);
+ qlt_response_pkt(host, rsp, pkt);
break;
}
@@ -496,7 +502,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
break;
}
}
- qlt_response_pkt(host, pkt);
+ qlt_response_pkt(host, rsp, pkt);
break;
}
@@ -513,7 +519,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
"vp_index %d\n", vha->vp_idx, entry->vp_index);
break;
}
- qlt_response_pkt(host, pkt);
+ qlt_response_pkt(host, rsp, pkt);
break;
}
@@ -530,12 +536,12 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
"vp_index %d\n", vha->vp_idx, entry->vp_index);
break;
}
- qlt_response_pkt(host, pkt);
+ qlt_response_pkt(host, rsp, pkt);
break;
}
default:
- qlt_response_pkt(vha, pkt);
+ qlt_response_pkt(vha, rsp, pkt);
break;
}
@@ -565,13 +571,13 @@ void qla2x00_async_nack_sp_done(void *s, int res)
struct scsi_qla_host *vha = sp->vha;
unsigned long flags;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async done-%s res %x %8phC type %d\n",
- sp->name, res, sp->fcport->port_name, sp->type);
+ ql_dbg(ql_dbg_disc, vha, 0x20f2,
+ "Async done-%s res %x %8phC type %d\n",
+ sp->name, res, sp->fcport->port_name, sp->type);
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
sp->fcport->flags &= ~FCF_ASYNC_SENT;
- sp->fcport->chip_reset = vha->hw->chip_reset;
+ sp->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
switch (sp->type) {
case SRB_NACK_PLOGI:
@@ -593,19 +599,19 @@ void qla2x00_async_nack_sp_done(void *s, int res)
if (!IS_IIDMA_CAPABLE(vha->hw) ||
!vha->hw->flags.gpsc_supported) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post upd_fcport fcp_cnt %d\n",
- __func__, __LINE__,
- sp->fcport->port_name,
- vha->fcport_count);
+ ql_dbg(ql_dbg_disc, vha, 0x20f3,
+ "%s %d %8phC post upd_fcport fcp_cnt %d\n",
+ __func__, __LINE__,
+ sp->fcport->port_name,
+ vha->fcport_count);
qla24xx_post_upd_fcport_work(vha, sp->fcport);
} else {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post gpsc fcp_cnt %d\n",
- __func__, __LINE__,
- sp->fcport->port_name,
- vha->fcport_count);
+ ql_dbg(ql_dbg_disc, vha, 0x20f5,
+ "%s %d %8phC post gpsc fcp_cnt %d\n",
+ __func__, __LINE__,
+ sp->fcport->port_name,
+ vha->fcport_count);
qla24xx_post_gpsc_work(vha, sp->fcport);
}
@@ -664,9 +670,9 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
if (rval != QLA_SUCCESS)
goto done_free_sp;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s %8phC hndl %x %s\n",
- sp->name, fcport->port_name, sp->handle, c);
+ ql_dbg(ql_dbg_disc, vha, 0x20f4,
+ "Async-%s %8phC hndl %x %s\n",
+ sp->name, fcport->port_name, sp->handle, c);
return rval;
@@ -688,7 +694,7 @@ void qla24xx_do_nack_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
t = qlt_create_sess(vha, e->u.nack.fcport, 0);
mutex_unlock(&vha->vha_tgt.tgt_mutex);
if (t) {
- ql_log(ql_log_info, vha, 0xffff,
+ ql_log(ql_log_info, vha, 0xd034,
"%s create sess success %p", __func__, t);
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
/* create sess has an extra kref */
@@ -757,7 +763,7 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
}
if (!kref_get_unless_zero(&sess->sess_kref)) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x2107,
"%s: kref_get fail sess %8phC \n",
__func__, sess->port_name);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
@@ -957,7 +963,6 @@ static void qlt_free_session_done(struct work_struct *work)
sess->logout_on_delete, sess->keep_nport_handle,
sess->send_els_logo);
-
if (!IS_SW_RESV_ADDR(sess->d_id)) {
if (sess->send_els_logo) {
qlt_port_logo_t logo;
@@ -1026,7 +1031,7 @@ static void qlt_free_session_done(struct work_struct *work)
sess->login_succ = 0;
}
- if (sess->chip_reset != sess->vha->hw->chip_reset)
+ if (sess->chip_reset != ha->base_qpair->chip_reset)
qla2x00_clear_loop_id(sess);
if (sess->conflict) {
@@ -1098,7 +1103,7 @@ void qlt_unreg_sess(struct fc_port *sess)
{
struct scsi_qla_host *vha = sess->vha;
- ql_dbg(ql_dbg_disc, sess->vha, 0xffff,
+ ql_dbg(ql_dbg_disc, sess->vha, 0x210a,
"%s sess %p for deletion %8phC\n",
__func__, sess, sess->port_name);
@@ -1112,6 +1117,9 @@ void qlt_unreg_sess(struct fc_port *sess)
sess->last_rscn_gen = sess->rscn_gen;
sess->last_login_gen = sess->login_gen;
+ if (sess->nvme_flag & NVME_FLAG_REGISTERED)
+ schedule_work(&sess->nvme_del_work);
+
INIT_WORK(&sess->free_work, qlt_free_session_done);
schedule_work(&sess->free_work);
}
@@ -1156,7 +1164,7 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
static void qla24xx_chk_fcp_state(struct fc_port *sess)
{
- if (sess->chip_reset != sess->vha->hw->chip_reset) {
+ if (sess->chip_reset != sess->vha->hw->base_qpair->chip_reset) {
sess->logout_on_delete = 0;
sess->logo_ack_needed = 0;
sess->fw_login_state = DSC_LS_PORT_UNAVAIL;
@@ -1288,7 +1296,7 @@ static struct fc_port *qlt_create_sess(
if (fcport->se_sess) {
if (!kref_get_unless_zero(&sess->sess_kref)) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20f6,
"%s: kref_get_unless_zero failed for %8phC\n",
__func__, sess->port_name);
return NULL;
@@ -1310,7 +1318,7 @@ static struct fc_port *qlt_create_sess(
if (ha->tgt.tgt_ops->check_initiator_node_acl(vha,
&fcport->port_name[0], sess) < 0) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf015,
"(%d) %8phC check_initiator_node_acl failed\n",
vha->vp_idx, fcport->port_name);
return NULL;
@@ -1321,7 +1329,7 @@ static struct fc_port *qlt_create_sess(
* fc_port access across ->tgt.sess_lock reaquire.
*/
if (!kref_get_unless_zero(&sess->sess_kref)) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20f7,
"%s: kref_get_unless_zero failed for %8phC\n",
__func__, sess->port_name);
return NULL;
@@ -1432,6 +1440,8 @@ int qlt_stop_phase1(struct qla_tgt *tgt)
if (npiv_vports) {
mutex_unlock(&qla_tgt_mutex);
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf021,
+ "NPIV is in use. Can not stop target\n");
return -EPERM;
}
}
@@ -1442,7 +1452,7 @@ int qlt_stop_phase1(struct qla_tgt *tgt)
return -EPERM;
}
- ql_dbg(ql_dbg_tgt, vha, 0xe003, "Stopping target for host %ld(%p)\n",
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xe003, "Stopping target for host %ld(%p)\n",
vha->host_no, vha);
/*
* Mutex needed to sync with qla_tgt_fc_port_[added,deleted].
@@ -1485,9 +1495,7 @@ EXPORT_SYMBOL(qlt_stop_phase1);
/* Called by tcm_qla2xxx configfs code */
void qlt_stop_phase2(struct qla_tgt *tgt)
{
- struct qla_hw_data *ha = tgt->ha;
- scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
- unsigned long flags;
+ scsi_qla_host_t *vha = tgt->vha;
if (tgt->tgt_stopped) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04f,
@@ -1495,24 +1503,19 @@ void qlt_stop_phase2(struct qla_tgt *tgt)
dump_stack();
return;
}
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00b,
- "Waiting for %d IRQ commands to complete (tgt %p)",
- tgt->irq_cmd_count, tgt);
+ if (!tgt->tgt_stop) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00b,
+ "%s: phase1 stop is not completed\n", __func__);
+ dump_stack();
+ return;
+ }
mutex_lock(&vha->vha_tgt.tgt_mutex);
- spin_lock_irqsave(&ha->hardware_lock, flags);
- while ((tgt->irq_cmd_count != 0) || (tgt->atio_irq_cmd_count != 0)) {
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- udelay(2);
- spin_lock_irqsave(&ha->hardware_lock, flags);
- }
tgt->tgt_stop = 0;
tgt->tgt_stopped = 1;
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
mutex_unlock(&vha->vha_tgt.tgt_mutex);
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00c, "Stop of tgt %p finished",
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00c, "Stop of tgt %p finished\n",
tgt);
}
EXPORT_SYMBOL(qlt_stop_phase2);
@@ -1521,10 +1524,36 @@ EXPORT_SYMBOL(qlt_stop_phase2);
static void qlt_release(struct qla_tgt *tgt)
{
scsi_qla_host_t *vha = tgt->vha;
+ void *node;
+ u64 key = 0;
+ u16 i;
+ struct qla_qpair_hint *h;
+
+ if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stop &&
+ !tgt->tgt_stopped)
+ qlt_stop_phase1(tgt);
if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stopped)
qlt_stop_phase2(tgt);
+ for (i = 0; i < vha->hw->max_qpairs + 1; i++) {
+ unsigned long flags;
+
+ h = &tgt->qphints[i];
+ if (h->qpair) {
+ spin_lock_irqsave(h->qpair->qp_lock_ptr, flags);
+ list_del(&h->hint_elem);
+ spin_unlock_irqrestore(h->qpair->qp_lock_ptr, flags);
+ h->qpair = NULL;
+ }
+ }
+ kfree(tgt->qphints);
+
+ btree_for_each_safe64(&tgt->lun_qpair_map, key, node)
+ btree_remove64(&tgt->lun_qpair_map, key);
+
+ btree_destroy64(&tgt->lun_qpair_map);
+
vha->vha_tgt.qla_tgt = NULL;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00d,
@@ -1568,11 +1597,12 @@ static int qlt_sched_sess_work(struct qla_tgt *tgt, int type,
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
-static void qlt_send_notify_ack(struct scsi_qla_host *vha,
+static void qlt_send_notify_ack(struct qla_qpair *qpair,
struct imm_ntfy_from_isp *ntfy,
uint32_t add_flags, uint16_t resp_code, int resp_code_valid,
uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan)
{
+ struct scsi_qla_host *vha = qpair->vha;
struct qla_hw_data *ha = vha->hw;
request_t *pkt;
struct nack_to_isp *nack;
@@ -1582,11 +1612,7 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt, vha, 0xe004, "Sending NOTIFY_ACK (ha=%p)\n", ha);
- /* Send marker if required */
- if (qlt_issue_marker(vha, 1) != QLA_SUCCESS)
- return;
-
- pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL);
+ pkt = (request_t *)__qla2x00_alloc_iocbs(qpair, NULL);
if (!pkt) {
ql_dbg(ql_dbg_tgt, vha, 0xe049,
"qla_target(%d): %s failed: unable to allocate "
@@ -1627,16 +1653,17 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha,
/* Memory Barrier */
wmb();
- qla2x00_start_iocbs(vha, vha->req);
+ qla2x00_start_iocbs(vha, qpair->req);
}
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
-static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha,
+static void qlt_24xx_send_abts_resp(struct qla_qpair *qpair,
struct abts_recv_from_24xx *abts, uint32_t status,
bool ids_reversed)
{
+ struct scsi_qla_host *vha = qpair->vha;
struct qla_hw_data *ha = vha->hw;
struct abts_resp_to_24xx *resp;
uint32_t f_ctl;
@@ -1646,11 +1673,8 @@ static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha,
"Sending task mgmt ABTS response (ha=%p, atio=%p, status=%x\n",
ha, abts, status);
- /* Send marker if required */
- if (qlt_issue_marker(vha, 1) != QLA_SUCCESS)
- return;
-
- resp = (struct abts_resp_to_24xx *)qla2x00_alloc_iocbs_ready(vha, NULL);
+ resp = (struct abts_resp_to_24xx *)qla2x00_alloc_iocbs_ready(qpair,
+ NULL);
if (!resp) {
ql_dbg(ql_dbg_tgt, vha, 0xe04a,
"qla_target(%d): %s failed: unable to allocate "
@@ -1706,7 +1730,10 @@ static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha,
/* Memory Barrier */
wmb();
- qla2x00_start_iocbs(vha, vha->req);
+ if (qpair->reqq_start_iocbs)
+ qpair->reqq_start_iocbs(qpair);
+ else
+ qla2x00_start_iocbs(vha, qpair->req);
}
/*
@@ -1719,11 +1746,9 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt, vha, 0xe007,
"Sending retry TERM EXCH CTIO7 (ha=%p)\n", vha->hw);
- /* Send marker if required */
- if (qlt_issue_marker(vha, 1) != QLA_SUCCESS)
- return;
- ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs_ready(vha, NULL);
+ ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs_ready(
+ vha->hw->base_qpair, NULL);
if (ctio == NULL) {
ql_dbg(ql_dbg_tgt, vha, 0xe04b,
"qla_target(%d): %s failed: unable to allocate "
@@ -1754,7 +1779,8 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha,
wmb();
qla2x00_start_iocbs(vha, vha->req);
- qlt_24xx_send_abts_resp(vha, (struct abts_recv_from_24xx *)entry,
+ qlt_24xx_send_abts_resp(vha->hw->base_qpair,
+ (struct abts_recv_from_24xx *)entry,
FCP_TMF_CMPL, true);
}
@@ -1762,13 +1788,13 @@ static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag)
{
struct qla_tgt_sess_op *op;
struct qla_tgt_cmd *cmd;
+ unsigned long flags;
- spin_lock(&vha->cmd_list_lock);
-
+ spin_lock_irqsave(&vha->cmd_list_lock, flags);
list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
if (tag == op->atio.u.isp24.exchange_addr) {
op->aborted = true;
- spin_unlock(&vha->cmd_list_lock);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
return 1;
}
}
@@ -1776,7 +1802,7 @@ static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag)
list_for_each_entry(op, &vha->unknown_atio_list, cmd_list) {
if (tag == op->atio.u.isp24.exchange_addr) {
op->aborted = true;
- spin_unlock(&vha->cmd_list_lock);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
return 1;
}
}
@@ -1784,12 +1810,12 @@ static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag)
list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
if (tag == cmd->atio.u.isp24.exchange_addr) {
cmd->aborted = 1;
- spin_unlock(&vha->cmd_list_lock);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
return 1;
}
}
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
- spin_unlock(&vha->cmd_list_lock);
return 0;
}
@@ -1799,17 +1825,18 @@ static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag)
* for the same lun)
*/
static void abort_cmds_for_lun(struct scsi_qla_host *vha,
- uint32_t lun, uint8_t *s_id)
+ u64 lun, uint8_t *s_id)
{
struct qla_tgt_sess_op *op;
struct qla_tgt_cmd *cmd;
uint32_t key;
+ unsigned long flags;
key = sid_to_key(s_id);
- spin_lock(&vha->cmd_list_lock);
+ spin_lock_irqsave(&vha->cmd_list_lock, flags);
list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
uint32_t op_key;
- uint32_t op_lun;
+ u64 op_lun;
op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
op_lun = scsilun_to_int(
@@ -1831,7 +1858,7 @@ static void abort_cmds_for_lun(struct scsi_qla_host *vha,
list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
uint32_t cmd_key;
- uint32_t cmd_lun;
+ u64 cmd_lun;
cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
cmd_lun = scsilun_to_int(
@@ -1839,7 +1866,7 @@ static void abort_cmds_for_lun(struct scsi_qla_host *vha,
if (cmd_key == key && cmd_lun == lun)
cmd->aborted = 1;
}
- spin_unlock(&vha->cmd_list_lock);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
}
/* ha->hardware_lock supposed to be held on entry */
@@ -1849,18 +1876,15 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
struct qla_hw_data *ha = vha->hw;
struct se_session *se_sess = sess->se_sess;
struct qla_tgt_mgmt_cmd *mcmd;
+ struct qla_tgt_cmd *cmd;
struct se_cmd *se_cmd;
- u32 lun = 0;
int rc;
bool found_lun = false;
unsigned long flags;
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) {
- struct qla_tgt_cmd *cmd =
- container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
if (se_cmd->tag == abts->exchange_addr_to_abort) {
- lun = cmd->unpacked_lun;
found_lun = true;
break;
}
@@ -1871,7 +1895,8 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
if (!found_lun) {
if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) {
/* send TASK_ABORT response immediately */
- qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_CMPL, false);
+ qlt_24xx_send_abts_resp(ha->base_qpair, abts,
+ FCP_TMF_CMPL, false);
return 0;
} else {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081,
@@ -1894,12 +1919,14 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
}
memset(mcmd, 0, sizeof(*mcmd));
+ cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
mcmd->sess = sess;
memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts));
- mcmd->reset_count = vha->hw->chip_reset;
+ mcmd->reset_count = ha->base_qpair->chip_reset;
mcmd->tmr_func = QLA_TGT_ABTS;
+ mcmd->qpair = ha->base_qpair;
- rc = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, mcmd->tmr_func,
+ rc = ha->tgt.tgt_ops->handle_tmr(mcmd, cmd->unpacked_lun, mcmd->tmr_func,
abts->exchange_addr_to_abort);
if (rc != 0) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052,
@@ -1929,7 +1956,8 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf053,
"qla_target(%d): ABTS: Abort Sequence not "
"supported\n", vha->vp_idx);
- qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false);
+ qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED,
+ false);
return;
}
@@ -1937,7 +1965,8 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf010,
"qla_target(%d): ABTS: Unknown Exchange "
"Address received\n", vha->vp_idx);
- qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false);
+ qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED,
+ false);
return;
}
@@ -1963,8 +1992,8 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
if (rc != 0) {
- qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED,
- false);
+ qlt_24xx_send_abts_resp(ha->base_qpair, abts,
+ FCP_TMF_REJECTED, false);
}
return;
}
@@ -1972,7 +2001,8 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
if (sess->deleted) {
- qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false);
+ qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED,
+ false);
return;
}
@@ -1981,7 +2011,8 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054,
"qla_target(%d): __qlt_24xx_handle_abts() failed: %d\n",
vha->vp_idx, rc);
- qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false);
+ qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED,
+ false);
return;
}
}
@@ -1989,9 +2020,10 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
-static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha,
+static void qlt_24xx_send_task_mgmt_ctio(struct qla_qpair *qpair,
struct qla_tgt_mgmt_cmd *mcmd, uint32_t resp_code)
{
+ struct scsi_qla_host *ha = qpair->vha;
struct atio_from_isp *atio = &mcmd->orig_iocb.atio;
struct ctio7_to_24xx *ctio;
uint16_t temp;
@@ -2000,11 +2032,8 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha,
"Sending task mgmt CTIO7 (ha=%p, atio=%p, resp_code=%x\n",
ha, atio, resp_code);
- /* Send marker if required */
- if (qlt_issue_marker(ha, 1) != QLA_SUCCESS)
- return;
- ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(ha, NULL);
+ ctio = (struct ctio7_to_24xx *)__qla2x00_alloc_iocbs(qpair, NULL);
if (ctio == NULL) {
ql_dbg(ql_dbg_tgt, ha, 0xe04c,
"qla_target(%d): %s failed: unable to allocate "
@@ -2022,8 +2051,9 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha,
ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
ctio->exchange_addr = atio->u.isp24.exchange_addr;
- ctio->u.status1.flags = (atio->u.isp24.attr << 9) |
- cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS);
+ temp = (atio->u.isp24.attr << 9)|
+ CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS;
+ ctio->u.status1.flags = cpu_to_le16(temp);
temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
ctio->u.status1.ox_id = cpu_to_le16(temp);
ctio->u.status1.scsi_status =
@@ -2033,7 +2063,10 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha,
/* Memory Barrier */
wmb();
- qla2x00_start_iocbs(ha, ha->req);
+ if (qpair->reqq_start_iocbs)
+ qpair->reqq_start_iocbs(qpair);
+ else
+ qla2x00_start_iocbs(ha, qpair->req);
}
void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd)
@@ -2046,12 +2079,13 @@ EXPORT_SYMBOL(qlt_free_mcmd);
* ha->hardware_lock supposed to be held on entry. Might drop it, then
* reacquire
*/
-void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
+void qlt_send_resp_ctio(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd,
uint8_t scsi_status, uint8_t sense_key, uint8_t asc, uint8_t ascq)
{
struct atio_from_isp *atio = &cmd->atio;
struct ctio7_to_24xx *ctio;
uint16_t temp;
+ struct scsi_qla_host *vha = cmd->vha;
ql_dbg(ql_dbg_tgt_dif, vha, 0x3066,
"Sending response CTIO7 (vha=%p, atio=%p, scsi_status=%02x, "
@@ -2076,8 +2110,9 @@ void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
ctio->exchange_addr = atio->u.isp24.exchange_addr;
- ctio->u.status1.flags = (atio->u.isp24.attr << 9) |
- cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS);
+ temp = (atio->u.isp24.attr << 9) |
+ CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS;
+ ctio->u.status1.flags = cpu_to_le16(temp);
temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
ctio->u.status1.ox_id = cpu_to_le16(temp);
ctio->u.status1.scsi_status =
@@ -2101,7 +2136,11 @@ void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
/* Memory Barrier */
wmb();
- qla2x00_start_iocbs(vha, vha->req);
+ if (qpair->reqq_start_iocbs)
+ qpair->reqq_start_iocbs(qpair);
+ else
+ qla2x00_start_iocbs(vha, qpair->req);
+
out:
return;
}
@@ -2112,14 +2151,15 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
struct scsi_qla_host *vha = mcmd->sess->vha;
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
+ struct qla_qpair *qpair = mcmd->qpair;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf013,
"TM response mcmd (%p) status %#x state %#x",
mcmd, mcmd->fc_tm_rsp, mcmd->flags);
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
- if (!vha->flags.online || mcmd->reset_count != ha->chip_reset) {
+ if (!vha->flags.online || mcmd->reset_count != qpair->chip_reset) {
/*
* Either the port is not online or this request was from
* previous life, just abort the processing.
@@ -2127,9 +2167,9 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
ql_dbg(ql_dbg_async, vha, 0xe100,
"RESET-TMR online/active/old-count/new-count = %d/%d/%d/%d.\n",
vha->flags.online, qla2x00_reset_active(vha),
- mcmd->reset_count, ha->chip_reset);
+ mcmd->reset_count, qpair->chip_reset);
ha->tgt.tgt_ops->free_mcmd(mcmd);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
return;
}
@@ -2140,21 +2180,21 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
ELS_PRLO ||
mcmd->orig_iocb.imm_ntfy.u.isp24.status_subcode ==
ELS_TPRLO) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x2106,
"TM response logo %phC status %#x state %#x",
mcmd->sess->port_name, mcmd->fc_tm_rsp,
mcmd->flags);
qlt_schedule_sess_for_deletion_lock(mcmd->sess);
} else {
- qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy,
- 0, 0, 0, 0, 0, 0);
+ qlt_send_notify_ack(vha->hw->base_qpair,
+ &mcmd->orig_iocb.imm_ntfy, 0, 0, 0, 0, 0, 0);
}
} else {
if (mcmd->orig_iocb.atio.u.raw.entry_type == ABTS_RECV_24XX)
- qlt_24xx_send_abts_resp(vha, &mcmd->orig_iocb.abts,
+ qlt_24xx_send_abts_resp(qpair, &mcmd->orig_iocb.abts,
mcmd->fc_tm_rsp, false);
else
- qlt_24xx_send_task_mgmt_ctio(vha, mcmd,
+ qlt_24xx_send_task_mgmt_ctio(qpair, mcmd,
mcmd->fc_tm_rsp);
}
/*
@@ -2166,7 +2206,7 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
* qlt_xmit_tm_rsp() returns here..
*/
ha->tgt.tgt_ops->free_mcmd(mcmd);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
}
EXPORT_SYMBOL(qlt_xmit_tm_rsp);
@@ -2178,7 +2218,7 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm)
BUG_ON(cmd->sg_cnt == 0);
prm->sg = (struct scatterlist *)cmd->sg;
- prm->seg_cnt = pci_map_sg(prm->tgt->ha->pdev, cmd->sg,
+ prm->seg_cnt = pci_map_sg(cmd->qpair->pdev, cmd->sg,
cmd->sg_cnt, cmd->dma_data_direction);
if (unlikely(prm->seg_cnt == 0))
goto out_err;
@@ -2190,10 +2230,10 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm)
* If greater than four sg entries then we need to allocate
* the continuation entries
*/
- if (prm->seg_cnt > prm->tgt->datasegs_per_cmd)
+ if (prm->seg_cnt > QLA_TGT_DATASEGS_PER_CMD_24XX)
prm->req_cnt += DIV_ROUND_UP(prm->seg_cnt -
- prm->tgt->datasegs_per_cmd,
- prm->tgt->datasegs_per_cont);
+ QLA_TGT_DATASEGS_PER_CMD_24XX,
+ QLA_TGT_DATASEGS_PER_CONT_24XX);
} else {
/* DIF */
if ((cmd->se_cmd.prot_op == TARGET_PROT_DIN_INSERT) ||
@@ -2205,7 +2245,7 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm)
if (cmd->prot_sg_cnt) {
prm->prot_sg = cmd->prot_sg;
- prm->prot_seg_cnt = pci_map_sg(prm->tgt->ha->pdev,
+ prm->prot_seg_cnt = pci_map_sg(cmd->qpair->pdev,
cmd->prot_sg, cmd->prot_sg_cnt,
cmd->dma_data_direction);
if (unlikely(prm->prot_seg_cnt == 0))
@@ -2225,7 +2265,7 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm)
return 0;
out_err:
- ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe04d,
+ ql_dbg_qp(ql_dbg_tgt, prm->cmd->qpair, 0xe04d,
"qla_target(%d): PCI mapping failed: sg_cnt=%d",
0, prm->cmd->sg_cnt);
return -1;
@@ -2233,53 +2273,50 @@ out_err:
static void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
{
- struct qla_hw_data *ha = vha->hw;
-
+ struct qla_hw_data *ha;
+ struct qla_qpair *qpair;
if (!cmd->sg_mapped)
return;
- pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
+ qpair = cmd->qpair;
+
+ pci_unmap_sg(qpair->pdev, cmd->sg, cmd->sg_cnt,
+ cmd->dma_data_direction);
cmd->sg_mapped = 0;
if (cmd->prot_sg_cnt)
- pci_unmap_sg(ha->pdev, cmd->prot_sg, cmd->prot_sg_cnt,
+ pci_unmap_sg(qpair->pdev, cmd->prot_sg, cmd->prot_sg_cnt,
cmd->dma_data_direction);
if (!cmd->ctx)
return;
-
+ ha = vha->hw;
if (cmd->ctx_dsd_alloced)
qla2x00_clean_dsd_pool(ha, cmd->ctx);
dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma);
}
-static int qlt_check_reserve_free_req(struct scsi_qla_host *vha,
+static int qlt_check_reserve_free_req(struct qla_qpair *qpair,
uint32_t req_cnt)
{
- uint32_t cnt, cnt_in;
+ uint32_t cnt;
+ struct req_que *req = qpair->req;
- if (vha->req->cnt < (req_cnt + 2)) {
- cnt = (uint16_t)RD_REG_DWORD(vha->req->req_q_out);
- cnt_in = (uint16_t)RD_REG_DWORD(vha->req->req_q_in);
+ if (req->cnt < (req_cnt + 2)) {
+ cnt = (uint16_t)(qpair->use_shadow_reg ? *req->out_ptr :
+ RD_REG_DWORD_RELAXED(req->req_q_out));
- if (vha->req->ring_index < cnt)
- vha->req->cnt = cnt - vha->req->ring_index;
+ if (req->ring_index < cnt)
+ req->cnt = cnt - req->ring_index;
else
- vha->req->cnt = vha->req->length -
- (vha->req->ring_index - cnt);
-
- if (unlikely(vha->req->cnt < (req_cnt + 2))) {
- ql_dbg(ql_dbg_io, vha, 0x305a,
- "qla_target(%d): There is no room in the request ring: vha->req->ring_index=%d, vha->req->cnt=%d, req_cnt=%d Req-out=%d Req-in=%d Req-Length=%d\n",
- vha->vp_idx, vha->req->ring_index,
- vha->req->cnt, req_cnt, cnt, cnt_in,
- vha->req->length);
+ req->cnt = req->length - (req->ring_index - cnt);
+
+ if (unlikely(req->cnt < (req_cnt + 2)))
return -EAGAIN;
- }
}
- vha->req->cnt -= req_cnt;
+ req->cnt -= req_cnt;
return 0;
}
@@ -2287,67 +2324,73 @@ static int qlt_check_reserve_free_req(struct scsi_qla_host *vha,
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
-static inline void *qlt_get_req_pkt(struct scsi_qla_host *vha)
+static inline void *qlt_get_req_pkt(struct req_que *req)
{
/* Adjust ring index. */
- vha->req->ring_index++;
- if (vha->req->ring_index == vha->req->length) {
- vha->req->ring_index = 0;
- vha->req->ring_ptr = vha->req->ring;
+ req->ring_index++;
+ if (req->ring_index == req->length) {
+ req->ring_index = 0;
+ req->ring_ptr = req->ring;
} else {
- vha->req->ring_ptr++;
+ req->ring_ptr++;
}
- return (cont_entry_t *)vha->req->ring_ptr;
+ return (cont_entry_t *)req->ring_ptr;
}
/* ha->hardware_lock supposed to be held on entry */
-static inline uint32_t qlt_make_handle(struct scsi_qla_host *vha)
+static inline uint32_t qlt_make_handle(struct qla_qpair *qpair)
{
- struct qla_hw_data *ha = vha->hw;
uint32_t h;
+ int index;
+ uint8_t found = 0;
+ struct req_que *req = qpair->req;
+
+ h = req->current_outstanding_cmd;
+
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
+ h++;
+ if (h == req->num_outstanding_cmds)
+ h = 1;
- h = ha->tgt.current_handle;
- /* always increment cmd handle */
- do {
- ++h;
- if (h > DEFAULT_OUTSTANDING_COMMANDS)
- h = 1; /* 0 is QLA_TGT_NULL_HANDLE */
- if (h == ha->tgt.current_handle) {
- ql_dbg(ql_dbg_io, vha, 0x305b,
- "qla_target(%d): Ran out of "
- "empty cmd slots in ha %p\n", vha->vp_idx, ha);
- h = QLA_TGT_NULL_HANDLE;
+ if (h == QLA_TGT_SKIP_HANDLE)
+ continue;
+
+ if (!req->outstanding_cmds[h]) {
+ found = 1;
break;
}
- } while ((h == QLA_TGT_NULL_HANDLE) ||
- (h == QLA_TGT_SKIP_HANDLE) ||
- (ha->tgt.cmds[h-1] != NULL));
+ }
- if (h != QLA_TGT_NULL_HANDLE)
- ha->tgt.current_handle = h;
+ if (found) {
+ req->current_outstanding_cmd = h;
+ } else {
+ ql_dbg(ql_dbg_io, qpair->vha, 0x305b,
+ "qla_target(%d): Ran out of empty cmd slots\n",
+ qpair->vha->vp_idx);
+ h = QLA_TGT_NULL_HANDLE;
+ }
return h;
}
/* ha->hardware_lock supposed to be held on entry */
-static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm,
- struct scsi_qla_host *vha)
+static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair,
+ struct qla_tgt_prm *prm)
{
uint32_t h;
struct ctio7_to_24xx *pkt;
- struct qla_hw_data *ha = vha->hw;
struct atio_from_isp *atio = &prm->cmd->atio;
uint16_t temp;
- pkt = (struct ctio7_to_24xx *)vha->req->ring_ptr;
+ pkt = (struct ctio7_to_24xx *)qpair->req->ring_ptr;
prm->pkt = pkt;
memset(pkt, 0, sizeof(*pkt));
pkt->entry_type = CTIO_TYPE7;
pkt->entry_count = (uint8_t)prm->req_cnt;
- pkt->vp_index = vha->vp_idx;
+ pkt->vp_index = prm->cmd->vp_idx;
- h = qlt_make_handle(vha);
+ h = qlt_make_handle(qpair);
if (unlikely(h == QLA_TGT_NULL_HANDLE)) {
/*
* CTIO type 7 from the firmware doesn't provide a way to
@@ -2356,16 +2399,18 @@ static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm,
*/
return -EAGAIN;
} else
- ha->tgt.cmds[h - 1] = prm->cmd;
+ qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd;
- pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK;
- pkt->nport_handle = prm->cmd->loop_id;
+ pkt->handle = MAKE_HANDLE(qpair->req->id, h);
+ pkt->handle |= CTIO_COMPLETION_HANDLE_MARK;
+ pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
pkt->exchange_addr = atio->u.isp24.exchange_addr;
- pkt->u.status0.flags |= (atio->u.isp24.attr << 9);
+ temp = atio->u.isp24.attr << 9;
+ pkt->u.status0.flags |= cpu_to_le16(temp);
temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
pkt->u.status0.ox_id = cpu_to_le16(temp);
pkt->u.status0.relative_offset = cpu_to_le32(prm->cmd->offset);
@@ -2377,17 +2422,16 @@ static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm,
* ha->hardware_lock supposed to be held on entry. We have already made sure
* that there is sufficient amount of request entries to not drop it.
*/
-static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm,
- struct scsi_qla_host *vha)
+static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm)
{
int cnt;
uint32_t *dword_ptr;
- int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr;
/* Build continuation packets */
while (prm->seg_cnt > 0) {
cont_a64_entry_t *cont_pkt64 =
- (cont_a64_entry_t *)qlt_get_req_pkt(vha);
+ (cont_a64_entry_t *)qlt_get_req_pkt(
+ prm->cmd->qpair->req);
/*
* Make sure that from cont_pkt64 none of
@@ -2401,30 +2445,18 @@ static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm,
cont_pkt64->entry_count = 1;
cont_pkt64->sys_define = 0;
- if (enable_64bit_addressing) {
- cont_pkt64->entry_type = CONTINUE_A64_TYPE;
- dword_ptr =
- (uint32_t *)&cont_pkt64->dseg_0_address;
- } else {
- cont_pkt64->entry_type = CONTINUE_TYPE;
- dword_ptr =
- (uint32_t *)&((cont_entry_t *)
- cont_pkt64)->dseg_0_address;
- }
+ cont_pkt64->entry_type = CONTINUE_A64_TYPE;
+ dword_ptr = (uint32_t *)&cont_pkt64->dseg_0_address;
/* Load continuation entry data segments */
for (cnt = 0;
- cnt < prm->tgt->datasegs_per_cont && prm->seg_cnt;
+ cnt < QLA_TGT_DATASEGS_PER_CONT_24XX && prm->seg_cnt;
cnt++, prm->seg_cnt--) {
*dword_ptr++ =
cpu_to_le32(pci_dma_lo32
(sg_dma_address(prm->sg)));
- if (enable_64bit_addressing) {
- *dword_ptr++ =
- cpu_to_le32(pci_dma_hi32
- (sg_dma_address
- (prm->sg)));
- }
+ *dword_ptr++ = cpu_to_le32(pci_dma_hi32
+ (sg_dma_address(prm->sg)));
*dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
prm->sg = sg_next(prm->sg);
@@ -2436,12 +2468,10 @@ static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm,
* ha->hardware_lock supposed to be held on entry. We have already made sure
* that there is sufficient amount of request entries to not drop it.
*/
-static void qlt_load_data_segments(struct qla_tgt_prm *prm,
- struct scsi_qla_host *vha)
+static void qlt_load_data_segments(struct qla_tgt_prm *prm)
{
int cnt;
uint32_t *dword_ptr;
- int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr;
struct ctio7_to_24xx *pkt24 = (struct ctio7_to_24xx *)prm->pkt;
pkt24->u.status0.transfer_length = cpu_to_le32(prm->cmd->bufflen);
@@ -2464,21 +2494,20 @@ static void qlt_load_data_segments(struct qla_tgt_prm *prm,
/* Load command entry data segments */
for (cnt = 0;
- (cnt < prm->tgt->datasegs_per_cmd) && prm->seg_cnt;
+ (cnt < QLA_TGT_DATASEGS_PER_CMD_24XX) && prm->seg_cnt;
cnt++, prm->seg_cnt--) {
*dword_ptr++ =
cpu_to_le32(pci_dma_lo32(sg_dma_address(prm->sg)));
- if (enable_64bit_addressing) {
- *dword_ptr++ =
- cpu_to_le32(pci_dma_hi32(
- sg_dma_address(prm->sg)));
- }
+
+ *dword_ptr++ = cpu_to_le32(pci_dma_hi32(
+ sg_dma_address(prm->sg)));
+
*dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
prm->sg = sg_next(prm->sg);
}
- qlt_load_cont_data_segments(prm, vha);
+ qlt_load_cont_data_segments(prm);
}
static inline int qlt_has_data(struct qla_tgt_cmd *cmd)
@@ -2498,35 +2527,35 @@ static void qlt_print_dif_err(struct qla_tgt_prm *prm)
/* ASCQ */
switch (prm->sense_buffer[13]) {
case 1:
- ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xe00b,
"BE detected Guard TAG ERR: lba[0x%llx|%lld] len[0x%x] "
"se_cmd=%p tag[%x]",
cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
cmd->atio.u.isp24.exchange_addr);
break;
case 2:
- ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xe00c,
"BE detected APP TAG ERR: lba[0x%llx|%lld] len[0x%x] "
"se_cmd=%p tag[%x]",
cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
cmd->atio.u.isp24.exchange_addr);
break;
case 3:
- ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xe00f,
"BE detected REF TAG ERR: lba[0x%llx|%lld] len[0x%x] "
"se_cmd=%p tag[%x]",
cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
cmd->atio.u.isp24.exchange_addr);
break;
default:
- ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xe010,
"BE detected Dif ERR: lba[%llx|%lld] len[%x] "
"se_cmd=%p tag[%x]",
cmd->lba, cmd->lba, cmd->num_blks, &cmd->se_cmd,
cmd->atio.u.isp24.exchange_addr);
break;
}
- ql_dump_buffer(ql_dbg_tgt_dif, vha, 0xffff, cmd->cdb, 16);
+ ql_dump_buffer(ql_dbg_tgt_dif, vha, 0xe011, cmd->cdb, 16);
}
}
@@ -2537,24 +2566,23 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
struct qla_tgt_prm *prm, int xmit_type, uint8_t scsi_status,
uint32_t *full_req_cnt)
{
- struct qla_tgt *tgt = cmd->tgt;
- struct scsi_qla_host *vha = tgt->vha;
- struct qla_hw_data *ha = vha->hw;
struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct qla_qpair *qpair = cmd->qpair;
prm->cmd = cmd;
- prm->tgt = tgt;
+ prm->tgt = cmd->tgt;
+ prm->pkt = NULL;
prm->rq_result = scsi_status;
prm->sense_buffer = &cmd->sense_buffer[0];
prm->sense_buffer_len = TRANSPORT_SENSE_BUFFER;
prm->sg = NULL;
prm->seg_cnt = -1;
prm->req_cnt = 1;
+ prm->residual = 0;
prm->add_status_pkt = 0;
-
- /* Send marker if required */
- if (qlt_issue_marker(vha, 0) != QLA_SUCCESS)
- return -EFAULT;
+ prm->prot_sg = NULL;
+ prm->prot_seg_cnt = 0;
+ prm->tot_dsds = 0;
if ((xmit_type & QLA_TGT_XMIT_DATA) && qlt_has_data(cmd)) {
if (qlt_pci_map_calc_cnt(prm) != 0)
@@ -2565,7 +2593,7 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
prm->residual = se_cmd->residual_count;
- ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x305c,
+ ql_dbg_qp(ql_dbg_io + ql_dbg_verbose, qpair, 0x305c,
"Residual underflow: %d (tag %lld, op %x, bufflen %d, rq_result %x)\n",
prm->residual, se_cmd->tag,
se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0,
@@ -2573,7 +2601,7 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
prm->rq_result |= SS_RESIDUAL_UNDER;
} else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
prm->residual = se_cmd->residual_count;
- ql_dbg(ql_dbg_io, vha, 0x305d,
+ ql_dbg_qp(ql_dbg_io, qpair, 0x305d,
"Residual overflow: %d (tag %lld, op %x, bufflen %d, rq_result %x)\n",
prm->residual, se_cmd->tag, se_cmd->t_task_cdb ?
se_cmd->t_task_cdb[0] : 0, cmd->bufflen, prm->rq_result);
@@ -2587,7 +2615,7 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
*/
if (qlt_has_data(cmd)) {
if (QLA_TGT_SENSE_VALID(prm->sense_buffer) ||
- (IS_FWI2_CAPABLE(ha) &&
+ (IS_FWI2_CAPABLE(cmd->vha->hw) &&
(prm->rq_result != 0))) {
prm->add_status_pkt = 1;
(*full_req_cnt)++;
@@ -2598,17 +2626,17 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
return 0;
}
-static inline int qlt_need_explicit_conf(struct qla_hw_data *ha,
- struct qla_tgt_cmd *cmd, int sending_sense)
+static inline int qlt_need_explicit_conf(struct qla_tgt_cmd *cmd,
+ int sending_sense)
{
- if (ha->tgt.enable_class_2)
+ if (cmd->qpair->enable_class_2)
return 0;
if (sending_sense)
return cmd->conf_compl_supported;
else
- return ha->tgt.enable_explicit_conf &&
- cmd->conf_compl_supported;
+ return cmd->qpair->enable_explicit_conf &&
+ cmd->conf_compl_supported;
}
static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
@@ -2617,7 +2645,7 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
prm->sense_buffer_len = min_t(uint32_t, prm->sense_buffer_len,
(uint32_t)sizeof(ctio->u.status1.sense_data));
ctio->u.status0.flags |= cpu_to_le16(CTIO7_FLAGS_SEND_STATUS);
- if (qlt_need_explicit_conf(prm->tgt->ha, prm->cmd, 0)) {
+ if (qlt_need_explicit_conf(prm->cmd, 0)) {
ctio->u.status0.flags |= cpu_to_le16(
CTIO7_FLAGS_EXPLICIT_CONFORM |
CTIO7_FLAGS_CONFORM_REQ);
@@ -2627,9 +2655,9 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
if (QLA_TGT_SENSE_VALID(prm->sense_buffer)) {
int i;
- if (qlt_need_explicit_conf(prm->tgt->ha, prm->cmd, 1)) {
+ if (qlt_need_explicit_conf(prm->cmd, 1)) {
if ((prm->rq_result & SS_SCSI_STATUS_BYTE) != 0) {
- ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe017,
+ ql_dbg_qp(ql_dbg_tgt, prm->cmd->qpair, 0xe017,
"Skipping EXPLICIT_CONFORM and "
"CTIO7_FLAGS_CONFORM_REQ for FCP READ w/ "
"non GOOD status\n");
@@ -2797,7 +2825,7 @@ qla_tgt_set_dif_tags(struct qla_tgt_cmd *cmd, struct crc_context *ctx,
}
static inline int
-qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
+qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm)
{
uint32_t *cur_dsd;
uint32_t transfer_length = 0;
@@ -2816,16 +2844,17 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
struct atio_from_isp *atio = &prm->cmd->atio;
struct qla_tc_param tc;
uint16_t t16;
+ scsi_qla_host_t *vha = cmd->vha;
ha = vha->hw;
- pkt = (struct ctio_crc2_to_fw *)vha->req->ring_ptr;
+ pkt = (struct ctio_crc2_to_fw *)qpair->req->ring_ptr;
prm->pkt = pkt;
memset(pkt, 0, sizeof(*pkt));
- ql_dbg(ql_dbg_tgt, vha, 0xe071,
+ ql_dbg_qp(ql_dbg_tgt, cmd->qpair, 0xe071,
"qla_target(%d):%s: se_cmd[%p] CRC2 prot_op[0x%x] cmd prot sg:cnt[%p:%x] lba[%llu]\n",
- vha->vp_idx, __func__, se_cmd, se_cmd->prot_op,
+ cmd->vp_idx, __func__, se_cmd, se_cmd->prot_op,
prm->prot_sg, prm->prot_seg_cnt, se_cmd->t_task_lba);
if ((se_cmd->prot_op == TARGET_PROT_DIN_INSERT) ||
@@ -2888,9 +2917,9 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
/* Update entry type to indicate Command Type CRC_2 IOCB */
pkt->entry_type = CTIO_CRC2;
pkt->entry_count = 1;
- pkt->vp_index = vha->vp_idx;
+ pkt->vp_index = cmd->vp_idx;
- h = qlt_make_handle(vha);
+ h = qlt_make_handle(qpair);
if (unlikely(h == QLA_TGT_NULL_HANDLE)) {
/*
* CTIO type 7 from the firmware doesn't provide a way to
@@ -2899,9 +2928,10 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
*/
return -EAGAIN;
} else
- ha->tgt.cmds[h-1] = prm->cmd;
+ qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd;
- pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK;
+ pkt->handle = MAKE_HANDLE(qpair->req->id, h);
+ pkt->handle |= CTIO_COMPLETION_HANDLE_MARK;
pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
@@ -3005,7 +3035,7 @@ qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
crc_queuing_error:
/* Cleanup will be performed by the caller */
- vha->hw->tgt.cmds[h - 1] = NULL;
+ qpair->req->outstanding_cmds[h] = NULL;
return QLA_FUNCTION_FAILED;
}
@@ -3018,33 +3048,28 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
uint8_t scsi_status)
{
struct scsi_qla_host *vha = cmd->vha;
- struct qla_hw_data *ha = vha->hw;
+ struct qla_qpair *qpair = cmd->qpair;
struct ctio7_to_24xx *pkt;
struct qla_tgt_prm prm;
uint32_t full_req_cnt = 0;
unsigned long flags = 0;
int res;
- spin_lock_irqsave(&ha->hardware_lock, flags);
if (cmd->sess && cmd->sess->deleted) {
cmd->state = QLA_TGT_STATE_PROCESSED;
if (cmd->sess->logout_completed)
/* no need to terminate. FW already freed exchange. */
qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
else
- qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ qlt_send_term_exchange(qpair, cmd, &cmd->atio, 0, 0);
return 0;
}
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
- memset(&prm, 0, sizeof(prm));
- ql_dbg(ql_dbg_tgt, cmd->vha, 0xe018,
- "is_send_status=%d, cmd->bufflen=%d, cmd->sg_cnt=%d, cmd->dma_data_direction=%d se_cmd[%p]\n",
+ ql_dbg_qp(ql_dbg_tgt, qpair, 0xe018,
+ "is_send_status=%d, cmd->bufflen=%d, cmd->sg_cnt=%d, cmd->dma_data_direction=%d se_cmd[%p] qp %d\n",
(xmit_type & QLA_TGT_XMIT_STATUS) ?
1 : 0, cmd->bufflen, cmd->sg_cnt, cmd->dma_data_direction,
- &cmd->se_cmd);
+ &cmd->se_cmd, qpair->id);
res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
&full_req_cnt);
@@ -3052,39 +3077,39 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
return res;
}
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
if (xmit_type == QLA_TGT_XMIT_STATUS)
- vha->tgt_counters.core_qla_snd_status++;
+ qpair->tgt_counters.core_qla_snd_status++;
else
- vha->tgt_counters.core_qla_que_buf++;
+ qpair->tgt_counters.core_qla_que_buf++;
- if (!ha->flags.fw_started || cmd->reset_count != ha->chip_reset) {
+ if (!qpair->fw_started || cmd->reset_count != qpair->chip_reset) {
/*
* Either the port is not online or this request was from
* previous life, just abort the processing.
*/
cmd->state = QLA_TGT_STATE_PROCESSED;
qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
- ql_dbg(ql_dbg_async, vha, 0xe101,
+ ql_dbg_qp(ql_dbg_async, qpair, 0xe101,
"RESET-RSP online/active/old-count/new-count = %d/%d/%d/%d.\n",
vha->flags.online, qla2x00_reset_active(vha),
- cmd->reset_count, ha->chip_reset);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ cmd->reset_count, qpair->chip_reset);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
return 0;
}
/* Does F/W have an IOCBs for this request */
- res = qlt_check_reserve_free_req(vha, full_req_cnt);
+ res = qlt_check_reserve_free_req(qpair, full_req_cnt);
if (unlikely(res))
goto out_unmap_unlock;
if (cmd->se_cmd.prot_op && (xmit_type & QLA_TGT_XMIT_DATA))
- res = qlt_build_ctio_crc2_pkt(&prm, vha);
+ res = qlt_build_ctio_crc2_pkt(qpair, &prm);
else
- res = qlt_24xx_build_ctio_pkt(&prm, vha);
+ res = qlt_24xx_build_ctio_pkt(qpair, &prm);
if (unlikely(res != 0)) {
- vha->req->cnt += full_req_cnt;
+ qpair->req->cnt += full_req_cnt;
goto out_unmap_unlock;
}
@@ -3096,7 +3121,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
CTIO7_FLAGS_STATUS_MODE_0);
if (cmd->se_cmd.prot_op == TARGET_PROT_NORMAL)
- qlt_load_data_segments(&prm, vha);
+ qlt_load_data_segments(&prm);
if (prm.add_status_pkt == 0) {
if (xmit_type & QLA_TGT_XMIT_STATUS) {
@@ -3106,7 +3131,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
cpu_to_le32(prm.residual);
pkt->u.status0.flags |= cpu_to_le16(
CTIO7_FLAGS_SEND_STATUS);
- if (qlt_need_explicit_conf(ha, cmd, 0)) {
+ if (qlt_need_explicit_conf(cmd, 0)) {
pkt->u.status0.flags |=
cpu_to_le16(
CTIO7_FLAGS_EXPLICIT_CONFORM |
@@ -3121,9 +3146,10 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
* req_pkt().
*/
struct ctio7_to_24xx *ctio =
- (struct ctio7_to_24xx *)qlt_get_req_pkt(vha);
+ (struct ctio7_to_24xx *)qlt_get_req_pkt(
+ qpair->req);
- ql_dbg(ql_dbg_io, vha, 0x305e,
+ ql_dbg_qp(ql_dbg_tgt, qpair, 0x305e,
"Building additional status packet 0x%p.\n",
ctio);
@@ -3150,7 +3176,6 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
*/
qlt_24xx_init_ctio_to_isp((struct ctio7_to_24xx *)ctio,
&prm);
- pr_debug("Status CTIO7: %p\n", ctio);
}
} else
qlt_24xx_init_ctio_to_isp(pkt, &prm);
@@ -3161,14 +3186,17 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
/* Memory Barrier */
wmb();
- qla2x00_start_iocbs(vha, vha->req);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ if (qpair->reqq_start_iocbs)
+ qpair->reqq_start_iocbs(qpair);
+ else
+ qla2x00_start_iocbs(vha, qpair->req);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
return 0;
out_unmap_unlock:
qlt_unmap_sg(vha, cmd);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
return res;
}
@@ -3178,11 +3206,11 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
{
struct ctio7_to_24xx *pkt;
struct scsi_qla_host *vha = cmd->vha;
- struct qla_hw_data *ha = vha->hw;
struct qla_tgt *tgt = cmd->tgt;
struct qla_tgt_prm prm;
- unsigned long flags;
+ unsigned long flags = 0;
int res = 0;
+ struct qla_qpair *qpair = cmd->qpair;
memset(&prm, 0, sizeof(prm));
prm.cmd = cmd;
@@ -3190,17 +3218,11 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
prm.sg = NULL;
prm.req_cnt = 1;
- /* Send marker if required */
- if (qlt_issue_marker(vha, 0) != QLA_SUCCESS)
- return -EIO;
-
/* Calculate number of entries and segments required */
if (qlt_pci_map_calc_cnt(&prm) != 0)
return -EAGAIN;
- spin_lock_irqsave(&ha->hardware_lock, flags);
-
- if (!ha->flags.fw_started || (cmd->reset_count != ha->chip_reset) ||
+ if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) ||
(cmd->sess && cmd->sess->deleted)) {
/*
* Either the port is not online or this request was from
@@ -3208,25 +3230,25 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
*/
cmd->state = QLA_TGT_STATE_NEED_DATA;
qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
- ql_dbg(ql_dbg_async, vha, 0xe102,
+ ql_dbg_qp(ql_dbg_async, qpair, 0xe102,
"RESET-XFR online/active/old-count/new-count = %d/%d/%d/%d.\n",
vha->flags.online, qla2x00_reset_active(vha),
- cmd->reset_count, ha->chip_reset);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ cmd->reset_count, qpair->chip_reset);
return 0;
}
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
/* Does F/W have an IOCBs for this request */
- res = qlt_check_reserve_free_req(vha, prm.req_cnt);
+ res = qlt_check_reserve_free_req(qpair, prm.req_cnt);
if (res != 0)
goto out_unlock_free_unmap;
if (cmd->se_cmd.prot_op)
- res = qlt_build_ctio_crc2_pkt(&prm, vha);
+ res = qlt_build_ctio_crc2_pkt(qpair, &prm);
else
- res = qlt_24xx_build_ctio_pkt(&prm, vha);
+ res = qlt_24xx_build_ctio_pkt(qpair, &prm);
if (unlikely(res != 0)) {
- vha->req->cnt += prm.req_cnt;
+ qpair->req->cnt += prm.req_cnt;
goto out_unlock_free_unmap;
}
@@ -3235,21 +3257,24 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
CTIO7_FLAGS_STATUS_MODE_0);
if (cmd->se_cmd.prot_op == TARGET_PROT_NORMAL)
- qlt_load_data_segments(&prm, vha);
+ qlt_load_data_segments(&prm);
cmd->state = QLA_TGT_STATE_NEED_DATA;
cmd->cmd_sent_to_fw = 1;
/* Memory Barrier */
wmb();
- qla2x00_start_iocbs(vha, vha->req);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ if (qpair->reqq_start_iocbs)
+ qpair->reqq_start_iocbs(qpair);
+ else
+ qla2x00_start_iocbs(vha, qpair->req);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
return res;
out_unlock_free_unmap:
qlt_unmap_sg(vha, cmd);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
return res;
}
@@ -3260,7 +3285,7 @@ EXPORT_SYMBOL(qlt_rdy_to_xfer);
* it is assumed either hardware_lock or qpair lock is held.
*/
static void
-qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd,
+qlt_handle_dif_error(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd,
struct ctio_crc_from_fw *sts)
{
uint8_t *ap = &sts->actual_dif[0];
@@ -3268,6 +3293,7 @@ qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd,
uint64_t lba = cmd->se_cmd.t_task_lba;
uint8_t scsi_status, sense_key, asc, ascq;
unsigned long flags;
+ struct scsi_qla_host *vha = cmd->vha;
cmd->trc_flags |= TRC_DIF_ERR;
@@ -3286,15 +3312,12 @@ qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd,
/* check appl tag */
if (cmd->e_app_tag != cmd->a_app_tag) {
- ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
- "App Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] "
- "Ref[%x|%x], App[%x|%x], "
- "Guard [%x|%x] cmd=%p ox_id[%04x]",
- cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
- cmd->a_ref_tag, cmd->e_ref_tag,
- cmd->a_app_tag, cmd->e_app_tag,
- cmd->a_guard, cmd->e_guard,
- cmd, cmd->atio.u.isp24.fcp_hdr.ox_id);
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xe00d,
+ "App Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] Ref[%x|%x], App[%x|%x], Guard [%x|%x] cmd=%p ox_id[%04x]",
+ cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
+ cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag,
+ cmd->e_app_tag, cmd->a_guard, cmd->e_guard, cmd,
+ cmd->atio.u.isp24.fcp_hdr.ox_id);
cmd->dif_err_code = DIF_ERR_APP;
scsi_status = SAM_STAT_CHECK_CONDITION;
@@ -3305,15 +3328,12 @@ qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd,
/* check ref tag */
if (cmd->e_ref_tag != cmd->a_ref_tag) {
- ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
- "Ref Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] "
- "Ref[%x|%x], App[%x|%x], "
- "Guard[%x|%x] cmd=%p ox_id[%04x] ",
- cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
- cmd->a_ref_tag, cmd->e_ref_tag,
- cmd->a_app_tag, cmd->e_app_tag,
- cmd->a_guard, cmd->e_guard,
- cmd, cmd->atio.u.isp24.fcp_hdr.ox_id);
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xe00e,
+ "Ref Tag ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] Ref[%x|%x], App[%x|%x], Guard[%x|%x] cmd=%p ox_id[%04x] ",
+ cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
+ cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag,
+ cmd->e_app_tag, cmd->a_guard, cmd->e_guard, cmd,
+ cmd->atio.u.isp24.fcp_hdr.ox_id);
cmd->dif_err_code = DIF_ERR_REF;
scsi_status = SAM_STAT_CHECK_CONDITION;
@@ -3325,15 +3345,13 @@ qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd,
/* check guard */
if (cmd->e_guard != cmd->a_guard) {
- ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
- "Guard ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] "
- "Ref[%x|%x], App[%x|%x], "
- "Guard [%x|%x] cmd=%p ox_id[%04x]",
- cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
- cmd->a_ref_tag, cmd->e_ref_tag,
- cmd->a_app_tag, cmd->e_app_tag,
- cmd->a_guard, cmd->e_guard,
- cmd, cmd->atio.u.isp24.fcp_hdr.ox_id);
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xe012,
+ "Guard ERR: cdb[%x] lba[%llx %llx] blks[%x] [Actual|Expected] Ref[%x|%x], App[%x|%x], Guard [%x|%x] cmd=%p ox_id[%04x]",
+ cmd->cdb[0], lba, (lba+cmd->num_blks), cmd->num_blks,
+ cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag,
+ cmd->e_app_tag, cmd->a_guard, cmd->e_guard, cmd,
+ cmd->atio.u.isp24.fcp_hdr.ox_id);
+
cmd->dif_err_code = DIF_ERR_GRD;
scsi_status = SAM_STAT_CHECK_CONDITION;
sense_key = ABORTED_COMMAND;
@@ -3356,7 +3374,8 @@ out:
}
spin_unlock_irqrestore(&cmd->cmd_lock, flags);
- qlt_send_resp_ctio(vha, cmd, scsi_status, sense_key, asc, ascq);
+ qlt_send_resp_ctio(qpair, cmd, scsi_status, sense_key, asc,
+ ascq);
/* assume scsi status gets out on the wire.
* Will not wait for completion.
*/
@@ -3422,9 +3441,6 @@ static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
unsigned long flags = 0;
int rc;
- if (qlt_issue_marker(vha, ha_locked) < 0)
- return;
-
if (ha_locked) {
rc = __qlt_send_term_imm_notif(vha, imm);
@@ -3451,21 +3467,24 @@ done:
spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
}
-/* If hardware_lock held on entry, might drop it, then reaquire */
-/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */
-static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
+/*
+ * If hardware_lock held on entry, might drop it, then reaquire
+ * This function sends the appropriate CTIO to ISP 2xxx or 24xx
+ */
+static int __qlt_send_term_exchange(struct qla_qpair *qpair,
struct qla_tgt_cmd *cmd,
struct atio_from_isp *atio)
{
+ struct scsi_qla_host *vha = qpair->vha;
struct ctio7_to_24xx *ctio24;
struct qla_hw_data *ha = vha->hw;
request_t *pkt;
int ret = 0;
uint16_t temp;
- ql_dbg(ql_dbg_tgt, vha, 0xe01c, "Sending TERM EXCH CTIO (ha=%p)\n", ha);
+ ql_dbg(ql_dbg_tgt, vha, 0xe009, "Sending TERM EXCH CTIO (ha=%p)\n", ha);
- pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL);
+ pkt = (request_t *)qla2x00_alloc_iocbs_ready(qpair, NULL);
if (pkt == NULL) {
ql_dbg(ql_dbg_tgt, vha, 0xe050,
"qla_target(%d): %s failed: unable to allocate "
@@ -3483,7 +3502,7 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
ret = 1;
}
- vha->tgt_counters.num_term_xchg_sent++;
+ qpair->tgt_counters.num_term_xchg_sent++;
pkt->entry_count = 1;
pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
@@ -3496,9 +3515,9 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
ctio24->exchange_addr = atio->u.isp24.exchange_addr;
- ctio24->u.status1.flags = (atio->u.isp24.attr << 9) |
- cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 |
- CTIO7_FLAGS_TERMINATE);
+ temp = (atio->u.isp24.attr << 9) | CTIO7_FLAGS_STATUS_MODE_1 |
+ CTIO7_FLAGS_TERMINATE;
+ ctio24->u.status1.flags = cpu_to_le16(temp);
temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
ctio24->u.status1.ox_id = cpu_to_le16(temp);
@@ -3511,28 +3530,35 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
/* Memory Barrier */
wmb();
- qla2x00_start_iocbs(vha, vha->req);
+ if (qpair->reqq_start_iocbs)
+ qpair->reqq_start_iocbs(qpair);
+ else
+ qla2x00_start_iocbs(vha, qpair->req);
return ret;
}
-static void qlt_send_term_exchange(struct scsi_qla_host *vha,
+static void qlt_send_term_exchange(struct qla_qpair *qpair,
struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked,
int ul_abort)
{
+ struct scsi_qla_host *vha;
unsigned long flags = 0;
int rc;
- if (qlt_issue_marker(vha, ha_locked) < 0)
- return;
+ /* why use different vha? NPIV */
+ if (cmd)
+ vha = cmd->vha;
+ else
+ vha = qpair->vha;
if (ha_locked) {
- rc = __qlt_send_term_exchange(vha, cmd, atio);
+ rc = __qlt_send_term_exchange(qpair, cmd, atio);
if (rc == -ENOMEM)
qlt_alloc_qfull_cmd(vha, atio, 0, 0);
goto done;
}
- spin_lock_irqsave(&vha->hw->hardware_lock, flags);
- rc = __qlt_send_term_exchange(vha, cmd, atio);
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ rc = __qlt_send_term_exchange(qpair, cmd, atio);
if (rc == -ENOMEM)
qlt_alloc_qfull_cmd(vha, atio, 0, 0);
@@ -3544,7 +3570,7 @@ done:
}
if (!ha_locked)
- spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
return;
}
@@ -3616,17 +3642,17 @@ int qlt_abort_cmd(struct qla_tgt_cmd *cmd)
* 1) XFER Rdy completion + CMD_T_ABORT
* 2) TCM TMR - drain_state_list
*/
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
- "multiple abort. %p transport_state %x, t_state %x,"
- " se_cmd_flags %x \n", cmd, cmd->se_cmd.transport_state,
- cmd->se_cmd.t_state,cmd->se_cmd.se_cmd_flags);
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf016,
+ "multiple abort. %p transport_state %x, t_state %x, "
+ "se_cmd_flags %x\n", cmd, cmd->se_cmd.transport_state,
+ cmd->se_cmd.t_state, cmd->se_cmd.se_cmd_flags);
return EIO;
}
cmd->aborted = 1;
cmd->trc_flags |= TRC_ABORT;
spin_unlock_irqrestore(&cmd->cmd_lock, flags);
- qlt_send_term_exchange(vha, cmd, &cmd->atio, 0, 1);
+ qlt_send_term_exchange(cmd->qpair, cmd, &cmd->atio, 0, 1);
return 0;
}
EXPORT_SYMBOL(qlt_abort_cmd);
@@ -3665,13 +3691,14 @@ EXPORT_SYMBOL(qlt_free_cmd);
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
-static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio,
+static int qlt_term_ctio_exchange(struct qla_qpair *qpair, void *ctio,
struct qla_tgt_cmd *cmd, uint32_t status)
{
int term = 0;
+ struct scsi_qla_host *vha = qpair->vha;
if (cmd->se_cmd.prot_op)
- ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xe013,
"Term DIF cmd: lba[0x%llx|%lld] len[0x%x] "
"se_cmd=%p tag[%x] op %#x/%s",
cmd->lba, cmd->lba,
@@ -3688,55 +3715,53 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio,
term = 1;
if (term)
- qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
+ qlt_term_ctio_exchange(qpair, ctio, cmd, status);
return term;
}
-/* ha->hardware_lock supposed to be held on entry */
-static inline struct qla_tgt_cmd *qlt_get_cmd(struct scsi_qla_host *vha,
- uint32_t handle)
-{
- struct qla_hw_data *ha = vha->hw;
-
- handle--;
- if (ha->tgt.cmds[handle] != NULL) {
- struct qla_tgt_cmd *cmd = ha->tgt.cmds[handle];
- ha->tgt.cmds[handle] = NULL;
- return cmd;
- } else
- return NULL;
-}
/* ha->hardware_lock supposed to be held on entry */
static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha,
- uint32_t handle, void *ctio)
+ struct rsp_que *rsp, uint32_t handle, void *ctio)
{
struct qla_tgt_cmd *cmd = NULL;
+ struct req_que *req;
+ int qid = GET_QID(handle);
+ uint32_t h = handle & ~QLA_TGT_HANDLE_MASK;
- /* Clear out internal marks */
- handle &= ~(CTIO_COMPLETION_HANDLE_MARK |
- CTIO_INTERMEDIATE_HANDLE_MARK);
+ if (unlikely(h == QLA_TGT_SKIP_HANDLE))
+ return NULL;
- if (handle != QLA_TGT_NULL_HANDLE) {
- if (unlikely(handle == QLA_TGT_SKIP_HANDLE))
- return NULL;
+ if (qid == rsp->req->id) {
+ req = rsp->req;
+ } else if (vha->hw->req_q_map[qid]) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0x1000a,
+ "qla_target(%d): CTIO completion with different QID %d handle %x\n",
+ vha->vp_idx, rsp->id, handle);
+ req = vha->hw->req_q_map[qid];
+ } else {
+ return NULL;
+ }
+
+ h &= QLA_CMD_HANDLE_MASK;
- /* handle-1 is actually used */
- if (unlikely(handle > DEFAULT_OUTSTANDING_COMMANDS)) {
+ if (h != QLA_TGT_NULL_HANDLE) {
+ if (unlikely(h > req->num_outstanding_cmds)) {
ql_dbg(ql_dbg_tgt, vha, 0xe052,
"qla_target(%d): Wrong handle %x received\n",
vha->vp_idx, handle);
return NULL;
}
- cmd = qlt_get_cmd(vha, handle);
+
+ cmd = (struct qla_tgt_cmd *)req->outstanding_cmds[h];
if (unlikely(cmd == NULL)) {
- ql_dbg(ql_dbg_tgt, vha, 0xe053,
- "qla_target(%d): Suspicious: unable to "
- "find the command with handle %x\n", vha->vp_idx,
- handle);
+ ql_dbg(ql_dbg_async, vha, 0xe053,
+ "qla_target(%d): Suspicious: unable to find the command with handle %x req->id %d rsp->id %d\n",
+ vha->vp_idx, handle, req->id, rsp->id);
return NULL;
}
+ req->outstanding_cmds[h] = NULL;
} else if (ctio != NULL) {
/* We can't get loop ID from CTIO7 */
ql_dbg(ql_dbg_tgt, vha, 0xe054,
@@ -3749,33 +3774,30 @@ static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha,
}
/* hardware_lock should be held by caller. */
-static void
+void
qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
{
struct qla_hw_data *ha = vha->hw;
- uint32_t handle;
if (cmd->sg_mapped)
qlt_unmap_sg(vha, cmd);
- handle = qlt_make_handle(vha);
-
/* TODO: fix debug message type and ids. */
if (cmd->state == QLA_TGT_STATE_PROCESSED) {
ql_dbg(ql_dbg_io, vha, 0xff00,
- "HOST-ABORT: handle=%d, state=PROCESSED.\n", handle);
+ "HOST-ABORT: state=PROCESSED.\n");
} else if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
cmd->write_data_transferred = 0;
cmd->state = QLA_TGT_STATE_DATA_IN;
ql_dbg(ql_dbg_io, vha, 0xff01,
- "HOST-ABORT: handle=%d, state=DATA_IN.\n", handle);
+ "HOST-ABORT: state=DATA_IN.\n");
ha->tgt.tgt_ops->handle_data(cmd);
return;
} else {
ql_dbg(ql_dbg_io, vha, 0xff03,
- "HOST-ABORT: handle=%d, state=BAD(%d).\n", handle,
+ "HOST-ABORT: state=BAD(%d).\n",
cmd->state);
dump_stack();
}
@@ -3784,51 +3806,16 @@ qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
ha->tgt.tgt_ops->free_cmd(cmd);
}
-void
-qlt_host_reset_handler(struct qla_hw_data *ha)
-{
- struct qla_tgt_cmd *cmd;
- unsigned long flags;
- scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
- scsi_qla_host_t *vha = NULL;
- struct qla_tgt *tgt = base_vha->vha_tgt.qla_tgt;
- uint32_t i;
-
- if (!base_vha->hw->tgt.tgt_ops)
- return;
-
- if (!tgt || qla_ini_mode_enabled(base_vha)) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf003,
- "Target mode disabled\n");
- return;
- }
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xff10,
- "HOST-ABORT-HNDLR: base_vha->dpc_flags=%lx.\n",
- base_vha->dpc_flags);
-
- spin_lock_irqsave(&ha->hardware_lock, flags);
- for (i = 1; i < DEFAULT_OUTSTANDING_COMMANDS + 1; i++) {
- cmd = qlt_get_cmd(base_vha, i);
- if (!cmd)
- continue;
- /* ha->tgt.cmds entry is cleared by qlt_get_cmd. */
- vha = cmd->vha;
- qlt_abort_cmd_on_host_reset(vha, cmd);
- }
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-}
-
-
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
-static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
- uint32_t status, void *ctio)
+static void qlt_do_ctio_completion(struct scsi_qla_host *vha,
+ struct rsp_que *rsp, uint32_t handle, uint32_t status, void *ctio)
{
struct qla_hw_data *ha = vha->hw;
struct se_cmd *se_cmd;
struct qla_tgt_cmd *cmd;
+ struct qla_qpair *qpair = rsp->qpair;
if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) {
/* That could happen only in case of an error/reset/abort */
@@ -3840,7 +3827,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
return;
}
- cmd = qlt_ctio_to_cmd(vha, handle, ctio);
+ cmd = qlt_ctio_to_cmd(vha, rsp, handle, ctio);
if (cmd == NULL)
return;
@@ -3885,7 +3872,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
*/
cmd->sess->logout_on_delete = 0;
cmd->sess->send_els_logo = 1;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20f8,
"%s %d %8phC post del sess\n",
__func__, __LINE__, cmd->sess->port_name);
@@ -3904,7 +3891,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
*((u64 *)&crc->actual_dif[0]),
*((u64 *)&crc->expected_dif[0]));
- qlt_handle_dif_error(vha, cmd, ctio);
+ qlt_handle_dif_error(qpair, cmd, ctio);
return;
}
default:
@@ -3924,7 +3911,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
if ((cmd->state != QLA_TGT_STATE_NEED_DATA) &&
(!cmd->aborted)) {
cmd->trc_flags |= TRC_CTIO_ERR;
- if (qlt_term_ctio_exchange(vha, ctio, cmd, status))
+ if (qlt_term_ctio_exchange(qpair, ctio, cmd, status))
return;
}
}
@@ -4000,18 +3987,16 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
{
scsi_qla_host_t *vha = cmd->vha;
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
struct fc_port *sess = cmd->sess;
struct atio_from_isp *atio = &cmd->atio;
unsigned char *cdb;
unsigned long flags;
uint32_t data_length;
int ret, fcp_task_attr, data_dir, bidi = 0;
+ struct qla_qpair *qpair = cmd->qpair;
cmd->cmd_in_wq = 0;
cmd->trc_flags |= TRC_DO_WORK;
- if (tgt->tgt_stop)
- goto out_term;
if (cmd->aborted) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf082,
@@ -4023,8 +4008,6 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
spin_lock_init(&cmd->cmd_lock);
cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
cmd->se_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) {
@@ -4062,12 +4045,12 @@ out_term:
* argument to qlt_send_term_exchange() and free the memory here.
*/
cmd->trc_flags |= TRC_DO_WORK_ERR;
- spin_lock_irqsave(&ha->hardware_lock, flags);
- qlt_send_term_exchange(vha, NULL, &cmd->atio, 1, 0);
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ qlt_send_term_exchange(qpair, NULL, &cmd->atio, 1, 0);
qlt_decr_num_pend_cmds(vha);
percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
@@ -4087,6 +4070,110 @@ static void qlt_do_work(struct work_struct *work)
__qlt_do_work(cmd);
}
+void qlt_clr_qp_table(struct scsi_qla_host *vha)
+{
+ unsigned long flags;
+ struct qla_hw_data *ha = vha->hw;
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ void *node;
+ u64 key = 0;
+
+ ql_log(ql_log_info, vha, 0x706c,
+ "User update Number of Active Qpairs %d\n",
+ ha->tgt.num_act_qpairs);
+
+ spin_lock_irqsave(&ha->tgt.atio_lock, flags);
+
+ btree_for_each_safe64(&tgt->lun_qpair_map, key, node)
+ btree_remove64(&tgt->lun_qpair_map, key);
+
+ ha->base_qpair->lun_cnt = 0;
+ for (key = 0; key < ha->max_qpairs; key++)
+ if (ha->queue_pair_map[key])
+ ha->queue_pair_map[key]->lun_cnt = 0;
+
+ spin_unlock_irqrestore(&ha->tgt.atio_lock, flags);
+}
+
+static void qlt_assign_qpair(struct scsi_qla_host *vha,
+ struct qla_tgt_cmd *cmd)
+{
+ struct qla_qpair *qpair, *qp;
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ struct qla_qpair_hint *h;
+
+ if (vha->flags.qpairs_available) {
+ h = btree_lookup64(&tgt->lun_qpair_map, cmd->unpacked_lun);
+ if (unlikely(!h)) {
+ /* spread lun to qpair ratio evently */
+ int lcnt = 0, rc;
+ struct scsi_qla_host *base_vha =
+ pci_get_drvdata(vha->hw->pdev);
+
+ qpair = vha->hw->base_qpair;
+ if (qpair->lun_cnt == 0) {
+ qpair->lun_cnt++;
+ h = qla_qpair_to_hint(tgt, qpair);
+ BUG_ON(!h);
+ rc = btree_insert64(&tgt->lun_qpair_map,
+ cmd->unpacked_lun, h, GFP_ATOMIC);
+ if (rc) {
+ qpair->lun_cnt--;
+ ql_log(ql_log_info, vha, 0xd037,
+ "Unable to insert lun %llx into lun_qpair_map\n",
+ cmd->unpacked_lun);
+ }
+ goto out;
+ } else {
+ lcnt = qpair->lun_cnt;
+ }
+
+ h = NULL;
+ list_for_each_entry(qp, &base_vha->qp_list,
+ qp_list_elem) {
+ if (qp->lun_cnt == 0) {
+ qp->lun_cnt++;
+ h = qla_qpair_to_hint(tgt, qp);
+ BUG_ON(!h);
+ rc = btree_insert64(&tgt->lun_qpair_map,
+ cmd->unpacked_lun, h, GFP_ATOMIC);
+ if (rc) {
+ qp->lun_cnt--;
+ ql_log(ql_log_info, vha, 0xd038,
+ "Unable to insert lun %llx into lun_qpair_map\n",
+ cmd->unpacked_lun);
+ }
+ qpair = qp;
+ goto out;
+ } else {
+ if (qp->lun_cnt < lcnt) {
+ lcnt = qp->lun_cnt;
+ qpair = qp;
+ continue;
+ }
+ }
+ }
+ BUG_ON(!qpair);
+ qpair->lun_cnt++;
+ h = qla_qpair_to_hint(tgt, qpair);
+ BUG_ON(!h);
+ rc = btree_insert64(&tgt->lun_qpair_map,
+ cmd->unpacked_lun, h, GFP_ATOMIC);
+ if (rc) {
+ qpair->lun_cnt--;
+ ql_log(ql_log_info, vha, 0xd039,
+ "Unable to insert lun %llx into lun_qpair_map\n",
+ cmd->unpacked_lun);
+ }
+ }
+ } else {
+ h = &tgt->qphints[0];
+ }
+out:
+ cmd->qpair = h->qpair;
+ cmd->se_cmd.cpuid = h->cpuid;
+}
+
static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
struct fc_port *sess,
struct atio_from_isp *atio)
@@ -4101,7 +4188,7 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
memset(cmd, 0, sizeof(struct qla_tgt_cmd));
-
+ cmd->cmd_type = TYPE_TGT_CMD;
memcpy(&cmd->atio, atio, sizeof(*atio));
cmd->state = QLA_TGT_STATE_NEW;
cmd->tgt = vha->vha_tgt.qla_tgt;
@@ -4115,14 +4202,15 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
cmd->trc_flags = 0;
cmd->jiffies_at_alloc = get_jiffies_64();
- cmd->reset_count = vha->hw->chip_reset;
+ cmd->unpacked_lun = scsilun_to_int(
+ (struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun);
+ qlt_assign_qpair(vha, cmd);
+ cmd->reset_count = vha->hw->base_qpair->chip_reset;
+ cmd->vp_idx = vha->vp_idx;
return cmd;
}
-static void qlt_send_busy(struct scsi_qla_host *, struct atio_from_isp *,
- uint16_t);
-
static void qlt_create_sess_from_atio(struct work_struct *work)
{
struct qla_tgt_sess_op *op = container_of(work,
@@ -4168,10 +4256,15 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
*/
cmd = qlt_get_tag(vha, sess, &op->atio);
if (!cmd) {
- spin_lock_irqsave(&ha->hardware_lock, flags);
- qlt_send_busy(vha, &op->atio, SAM_STAT_BUSY);
+ struct qla_qpair *qpair = ha->base_qpair;
+
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ qlt_send_busy(qpair, &op->atio, SAM_STAT_BUSY);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
kfree(op);
return;
}
@@ -4184,9 +4277,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
kfree(op);
return;
out_term:
- spin_lock_irqsave(&ha->hardware_lock, flags);
- qlt_send_term_exchange(vha, NULL, &op->atio, 1, 0);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ qlt_send_term_exchange(vha->hw->base_qpair, NULL, &op->atio, 0, 0);
kfree(op);
}
@@ -4216,9 +4307,9 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
memcpy(&op->atio, atio, sizeof(*atio));
op->vha = vha;
- spin_lock(&vha->cmd_list_lock);
+ spin_lock_irqsave(&vha->cmd_list_lock, flags);
list_add_tail(&op->cmd_list, &vha->qla_sess_op_cmd_list);
- spin_unlock(&vha->cmd_list_lock);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
INIT_WORK(&op->work, qlt_create_sess_from_atio);
queue_work(qla_tgt_wq, &op->work);
@@ -4228,7 +4319,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
/* Another WWN used to have our s_id. Our PLOGI scheduled its
* session deletion, but it's still in sess_del_work wq */
if (sess->deleted) {
- ql_dbg(ql_dbg_io, vha, 0x3061,
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf002,
"New command while old session %p is being deleted\n",
sess);
return -EFAULT;
@@ -4238,7 +4329,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
* Do kref_get() before returning + dropping qla_hw_data->hardware_lock.
*/
if (!kref_get_unless_zero(&sess->sess_kref)) {
- ql_dbg(ql_dbg_tgt, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
"%s: kref_get fail, %8phC oxid %x \n",
__func__, sess->port_name,
be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id));
@@ -4257,15 +4348,15 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
cmd->cmd_in_wq = 1;
cmd->trc_flags |= TRC_NEW_CMD;
- cmd->se_cmd.cpuid = ha->msix_count ?
- ha->tgt.rspq_vector_cpuid : WORK_CPU_UNBOUND;
spin_lock_irqsave(&vha->cmd_list_lock, flags);
list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list);
spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
INIT_WORK(&cmd->work, qlt_do_work);
- if (ha->msix_count) {
+ if (vha->flags.qpairs_available) {
+ queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq, &cmd->work);
+ } else if (ha->msix_count) {
if (cmd->atio.u.isp24.fcp_cmnd.rddata)
queue_work_on(smp_processor_id(), qla_tgt_wq,
&cmd->work);
@@ -4275,8 +4366,8 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
} else {
queue_work(qla_tgt_wq, &cmd->work);
}
- return 0;
+ return 0;
}
/* ha->hardware_lock supposed to be held on entry */
@@ -4306,7 +4397,8 @@ static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun,
}
mcmd->tmr_func = fn;
mcmd->flags = flags;
- mcmd->reset_count = vha->hw->chip_reset;
+ mcmd->reset_count = ha->base_qpair->chip_reset;
+ mcmd->qpair = ha->base_qpair;
switch (fn) {
case QLA_TGT_LUN_RESET:
@@ -4333,13 +4425,12 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
struct qla_hw_data *ha = vha->hw;
struct qla_tgt *tgt;
struct fc_port *sess;
- uint32_t lun, unpacked_lun;
+ u64 unpacked_lun;
int fn;
unsigned long flags;
tgt = vha->vha_tgt.qla_tgt;
- lun = a->u.isp24.fcp_cmnd.lun;
fn = a->u.isp24.fcp_cmnd.task_mgmt_flags;
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
@@ -4347,7 +4438,8 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
a->u.isp24.fcp_hdr.s_id);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
- unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
+ unpacked_lun =
+ scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun);
if (!sess) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf024,
@@ -4370,7 +4462,7 @@ static int __qlt_abort_task(struct scsi_qla_host *vha,
struct atio_from_isp *a = (struct atio_from_isp *)iocb;
struct qla_hw_data *ha = vha->hw;
struct qla_tgt_mgmt_cmd *mcmd;
- uint32_t lun, unpacked_lun;
+ u64 unpacked_lun;
int rc;
mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC);
@@ -4386,10 +4478,11 @@ static int __qlt_abort_task(struct scsi_qla_host *vha,
memcpy(&mcmd->orig_iocb.imm_ntfy, iocb,
sizeof(mcmd->orig_iocb.imm_ntfy));
- lun = a->u.isp24.fcp_cmnd.lun;
- unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
- mcmd->reset_count = vha->hw->chip_reset;
+ unpacked_lun =
+ scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun);
+ mcmd->reset_count = ha->base_qpair->chip_reset;
mcmd->tmr_func = QLA_TGT_2G_ABORT_TASK;
+ mcmd->qpair = ha->base_qpair;
rc = ha->tgt.tgt_ops->handle_tmr(mcmd, unpacked_lun, mcmd->tmr_func,
le16_to_cpu(iocb->u.isp2x.seq_id));
@@ -4493,7 +4586,7 @@ qlt_find_sess_invalidate_other(scsi_qla_host_t *vha, uint64_t wwn,
* Another wwn used to have our s_id/loop_id
* kill the session, but don't free the loop_id
*/
- ql_dbg(ql_dbg_tgt_tmr, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_tmr, vha, 0xf01b,
"Invalidating sess %p loop_id %d wwn %llx.\n",
other_sess, other_sess->loop_id, other_wwn);
@@ -4529,12 +4622,13 @@ static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id)
struct qla_tgt_cmd *cmd;
uint32_t key;
int count = 0;
+ unsigned long flags;
key = (((u32)s_id->b.domain << 16) |
((u32)s_id->b.area << 8) |
((u32)s_id->b.al_pa));
- spin_lock(&vha->cmd_list_lock);
+ spin_lock_irqsave(&vha->cmd_list_lock, flags);
list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
@@ -4559,7 +4653,7 @@ static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id)
count++;
}
}
- spin_unlock(&vha->cmd_list_lock);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
return count;
}
@@ -4672,9 +4766,9 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
sess->keep_nport_handle = ((sess->loop_id == loop_id) &&
(sess->d_id.b24 == port_id.b24));
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post del sess\n",
- __func__, __LINE__, sess->port_name);
+ ql_dbg(ql_dbg_disc, vha, 0x20f9,
+ "%s %d %8phC post del sess\n",
+ __func__, __LINE__, sess->port_name);
qlt_schedule_sess_for_deletion_lock(sess);
@@ -4744,7 +4838,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
/* Make session global (not used in fabric mode) */
if (ha->current_topology != ISP_CFG_F) {
if (sess) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20fa,
"%s %d %8phC post nack\n",
__func__, __LINE__, sess->port_name);
qla24xx_post_nack_work(vha, sess, iocb,
@@ -4757,7 +4851,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
}
} else {
if (sess) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20fb,
"%s %d %8phC post nack\n",
__func__, __LINE__, sess->port_name);
qla24xx_post_nack_work(vha, sess, iocb,
@@ -4791,7 +4885,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS);
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20fc,
"%s: logo %llx res %d sess %p ",
__func__, wwn, res, sess);
if (res == 0) {
@@ -4815,15 +4909,15 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
{
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
if (tgt->link_reinit_iocb_pending) {
- qlt_send_notify_ack(vha, &tgt->link_reinit_iocb,
- 0, 0, 0, 0, 0, 0);
+ qlt_send_notify_ack(ha->base_qpair,
+ &tgt->link_reinit_iocb, 0, 0, 0, 0, 0, 0);
tgt->link_reinit_iocb_pending = 0;
}
sess = qla2x00_find_fcport_by_wwpn(vha,
iocb->u.isp24.port_name, 1);
if (sess) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20fd,
"sess %p lid %d|%d DS %d LS %d\n",
sess, sess->loop_id, loop_id,
sess->disc_state, sess->fw_login_state);
@@ -4879,8 +4973,8 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha,
le16_to_cpu(iocb->u.isp24.nport_handle),
iocb->u.isp24.status_subcode);
if (tgt->link_reinit_iocb_pending) {
- qlt_send_notify_ack(vha, &tgt->link_reinit_iocb,
- 0, 0, 0, 0, 0, 0);
+ qlt_send_notify_ack(ha->base_qpair,
+ &tgt->link_reinit_iocb, 0, 0, 0, 0, 0, 0);
}
memcpy(&tgt->link_reinit_iocb, iocb, sizeof(*iocb));
tgt->link_reinit_iocb_pending = 1;
@@ -4974,33 +5068,36 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha,
}
if (send_notify_ack)
- qlt_send_notify_ack(vha, iocb, add_flags, 0, 0, 0, 0, 0);
+ qlt_send_notify_ack(ha->base_qpair, iocb, add_flags, 0, 0, 0,
+ 0, 0);
}
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
* This function sends busy to ISP 2xxx or 24xx.
*/
-static int __qlt_send_busy(struct scsi_qla_host *vha,
+static int __qlt_send_busy(struct qla_qpair *qpair,
struct atio_from_isp *atio, uint16_t status)
{
+ struct scsi_qla_host *vha = qpair->vha;
struct ctio7_to_24xx *ctio24;
struct qla_hw_data *ha = vha->hw;
request_t *pkt;
struct fc_port *sess = NULL;
unsigned long flags;
+ u16 temp;
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
atio->u.isp24.fcp_hdr.s_id);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
if (!sess) {
- qlt_send_term_exchange(vha, NULL, atio, 1, 0);
+ qlt_send_term_exchange(qpair, NULL, atio, 1, 0);
return 0;
}
/* Sending marker isn't necessary, since we called from ISR */
- pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL);
+ pkt = (request_t *)__qla2x00_alloc_iocbs(qpair, NULL);
if (!pkt) {
ql_dbg(ql_dbg_io, vha, 0x3063,
"qla_target(%d): %s failed: unable to allocate "
@@ -5008,7 +5105,7 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
return -ENOMEM;
}
- vha->tgt_counters.num_q_full_sent++;
+ qpair->tgt_counters.num_q_full_sent++;
pkt->entry_count = 1;
pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
@@ -5021,10 +5118,10 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
ctio24->exchange_addr = atio->u.isp24.exchange_addr;
- ctio24->u.status1.flags = (atio->u.isp24.attr << 9) |
- cpu_to_le16(
+ temp = (atio->u.isp24.attr << 9) |
CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS |
- CTIO7_FLAGS_DONT_RET_CTIO);
+ CTIO7_FLAGS_DONT_RET_CTIO;
+ ctio24->u.status1.flags = cpu_to_le16(temp);
/*
* CTIO from fw w/o se_cmd doesn't provide enough info to retry it,
* if the explicit conformation is used.
@@ -5033,7 +5130,10 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
ctio24->u.status1.scsi_status = cpu_to_le16(status);
/* Memory Barrier */
wmb();
- qla2x00_start_iocbs(vha, vha->req);
+ if (qpair->reqq_start_iocbs)
+ qpair->reqq_start_iocbs(qpair);
+ else
+ qla2x00_start_iocbs(vha, qpair->req);
return 0;
}
@@ -5052,6 +5152,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
struct se_session *se_sess;
struct qla_tgt_cmd *cmd;
int tag;
+ unsigned long flags;
if (unlikely(tgt->tgt_stop)) {
ql_dbg(ql_dbg_io, vha, 0x300a,
@@ -5110,8 +5211,9 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
cmd->tgt = vha->vha_tgt.qla_tgt;
cmd->vha = vha;
- cmd->reset_count = vha->hw->chip_reset;
+ cmd->reset_count = ha->base_qpair->chip_reset;
cmd->q_full = 1;
+ cmd->qpair = ha->base_qpair;
if (qfull) {
cmd->q_full = 1;
@@ -5120,6 +5222,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
} else
cmd->term_exchg = 1;
+ spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags);
list_add_tail(&cmd->cmd_list, &vha->hw->tgt.q_full_list);
vha->hw->tgt.num_qfull_cmds_alloc++;
@@ -5127,35 +5230,41 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
vha->qla_stats.stat_max_qfull_cmds_alloc)
vha->qla_stats.stat_max_qfull_cmds_alloc =
vha->hw->tgt.num_qfull_cmds_alloc;
+ spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
}
int
-qlt_free_qfull_cmds(struct scsi_qla_host *vha)
+qlt_free_qfull_cmds(struct qla_qpair *qpair)
{
+ struct scsi_qla_host *vha = qpair->vha;
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
struct qla_tgt_cmd *cmd, *tcmd;
- struct list_head free_list;
+ struct list_head free_list, q_full_list;
int rc = 0;
if (list_empty(&ha->tgt.q_full_list))
return 0;
INIT_LIST_HEAD(&free_list);
+ INIT_LIST_HEAD(&q_full_list);
- spin_lock_irqsave(&vha->hw->hardware_lock, flags);
-
+ spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags);
if (list_empty(&ha->tgt.q_full_list)) {
- spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+ spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
return 0;
}
- list_for_each_entry_safe(cmd, tcmd, &ha->tgt.q_full_list, cmd_list) {
+ list_splice_init(&vha->hw->tgt.q_full_list, &q_full_list);
+ spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
+
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ list_for_each_entry_safe(cmd, tcmd, &q_full_list, cmd_list) {
if (cmd->q_full)
/* cmd->state is a borrowed field to hold status */
- rc = __qlt_send_busy(vha, &cmd->atio, cmd->state);
+ rc = __qlt_send_busy(qpair, &cmd->atio, cmd->state);
else if (cmd->term_exchg)
- rc = __qlt_send_term_exchange(vha, NULL, &cmd->atio);
+ rc = __qlt_send_term_exchange(qpair, NULL, &cmd->atio);
if (rc == -ENOMEM)
break;
@@ -5179,7 +5288,7 @@ qlt_free_qfull_cmds(struct scsi_qla_host *vha)
/* piggy back on hardware_lock for protection */
vha->hw->tgt.num_qfull_cmds_alloc--;
}
- spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
cmd = NULL;
@@ -5190,23 +5299,31 @@ qlt_free_qfull_cmds(struct scsi_qla_host *vha)
*/
qlt_free_cmd(cmd);
}
+
+ if (!list_empty(&q_full_list)) {
+ spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags);
+ list_splice(&q_full_list, &vha->hw->tgt.q_full_list);
+ spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
+ }
+
return rc;
}
static void
-qlt_send_busy(struct scsi_qla_host *vha,
- struct atio_from_isp *atio, uint16_t status)
+qlt_send_busy(struct qla_qpair *qpair, struct atio_from_isp *atio,
+ uint16_t status)
{
int rc = 0;
+ struct scsi_qla_host *vha = qpair->vha;
- rc = __qlt_send_busy(vha, atio, status);
+ rc = __qlt_send_busy(qpair, atio, status);
if (rc == -ENOMEM)
qlt_alloc_qfull_cmd(vha, atio, status, 1);
}
static int
-qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha,
- struct atio_from_isp *atio, bool ha_locked)
+qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, struct qla_qpair *qpair,
+ struct atio_from_isp *atio, uint8_t ha_locked)
{
struct qla_hw_data *ha = vha->hw;
uint16_t status;
@@ -5218,7 +5335,7 @@ qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha,
if (!ha_locked)
spin_lock_irqsave(&ha->hardware_lock, flags);
status = temp_sam_status;
- qlt_send_busy(vha, atio, status);
+ qlt_send_busy(qpair, atio, status);
if (!ha_locked)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -5257,16 +5374,17 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
"sending QUEUE_FULL\n", vha->vp_idx);
if (!ha_locked)
spin_lock_irqsave(&ha->hardware_lock, flags);
- qlt_send_busy(vha, atio, SAM_STAT_TASK_SET_FULL);
+ qlt_send_busy(ha->base_qpair, atio,
+ SAM_STAT_TASK_SET_FULL);
if (!ha_locked)
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(&ha->hardware_lock,
+ flags);
break;
}
-
-
if (likely(atio->u.isp24.fcp_cmnd.task_mgmt_flags == 0)) {
- rc = qlt_chk_qfull_thresh_hold(vha, atio, ha_locked);
+ rc = qlt_chk_qfull_thresh_hold(vha, ha->base_qpair,
+ atio, ha_locked);
if (rc != 0) {
tgt->atio_irq_cmd_count--;
return;
@@ -5278,19 +5396,19 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
if (unlikely(rc != 0)) {
if (rc == -ESRCH) {
if (!ha_locked)
- spin_lock_irqsave
- (&ha->hardware_lock, flags);
+ spin_lock_irqsave(&ha->hardware_lock,
+ flags);
#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
- qlt_send_busy(vha, atio, SAM_STAT_BUSY);
+ qlt_send_busy(ha->base_qpair, atio,
+ SAM_STAT_BUSY);
#else
- qlt_send_term_exchange(vha, NULL, atio, 1, 0);
+ qlt_send_term_exchange(ha->base_qpair, NULL,
+ atio, 1, 0);
#endif
-
if (!ha_locked)
- spin_unlock_irqrestore
- (&ha->hardware_lock, flags);
-
+ spin_unlock_irqrestore(
+ &ha->hardware_lock, flags);
} else {
if (tgt->tgt_stop) {
ql_dbg(ql_dbg_tgt, vha, 0xe059,
@@ -5305,7 +5423,8 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
if (!ha_locked)
spin_lock_irqsave(
&ha->hardware_lock, flags);
- qlt_send_busy(vha, atio, SAM_STAT_BUSY);
+ qlt_send_busy(ha->base_qpair,
+ atio, SAM_STAT_BUSY);
if (!ha_locked)
spin_unlock_irqrestore(
&ha->hardware_lock, flags);
@@ -5346,15 +5465,15 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
/* ha->hardware_lock supposed to be held on entry */
/* called via callback from qla2xxx */
-static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
+static void qlt_response_pkt(struct scsi_qla_host *vha,
+ struct rsp_que *rsp, response_t *pkt)
{
- struct qla_hw_data *ha = vha->hw;
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
if (unlikely(tgt == NULL)) {
ql_dbg(ql_dbg_tgt, vha, 0xe05d,
- "qla_target(%d): Response pkt %x received, but no "
- "tgt (ha %p)\n", vha->vp_idx, pkt->entry_type, ha);
+ "qla_target(%d): Response pkt %x received, but no tgt (ha %p)\n",
+ vha->vp_idx, pkt->entry_type, vha->hw);
return;
}
@@ -5363,14 +5482,12 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
* Otherwise, some commands can stuck.
*/
- tgt->irq_cmd_count++;
-
switch (pkt->entry_type) {
case CTIO_CRC2:
case CTIO_TYPE7:
{
struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt;
- qlt_do_ctio_completion(vha, entry->handle,
+ qlt_do_ctio_completion(vha, rsp, entry->handle,
le16_to_cpu(entry->status)|(pkt->entry_status << 16),
entry);
break;
@@ -5389,19 +5506,17 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
break;
}
- rc = qlt_chk_qfull_thresh_hold(vha, atio, true);
- if (rc != 0) {
- tgt->irq_cmd_count--;
+ rc = qlt_chk_qfull_thresh_hold(vha, rsp->qpair, atio, 1);
+ if (rc != 0)
return;
- }
rc = qlt_handle_cmd_for_atio(vha, atio);
if (unlikely(rc != 0)) {
if (rc == -ESRCH) {
#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
- qlt_send_busy(vha, atio, 0);
+ qlt_send_busy(rsp->qpair, atio, 0);
#else
- qlt_send_term_exchange(vha, NULL, atio, 1, 0);
+ qlt_send_term_exchange(rsp->qpair, NULL, atio, 1, 0);
#endif
} else {
if (tgt->tgt_stop) {
@@ -5409,14 +5524,14 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
"qla_target: Unable to send "
"command to target, sending TERM "
"EXCHANGE for rsp\n");
- qlt_send_term_exchange(vha, NULL,
+ qlt_send_term_exchange(rsp->qpair, NULL,
atio, 1, 0);
} else {
ql_dbg(ql_dbg_tgt, vha, 0xe060,
"qla_target(%d): Unable to send "
"command to target, sending BUSY "
"status\n", vha->vp_idx);
- qlt_send_busy(vha, atio, 0);
+ qlt_send_busy(rsp->qpair, atio, 0);
}
}
}
@@ -5426,7 +5541,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
case CONTINUE_TGT_IO_TYPE:
{
struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt;
- qlt_do_ctio_completion(vha, entry->handle,
+ qlt_do_ctio_completion(vha, rsp, entry->handle,
le16_to_cpu(entry->status)|(pkt->entry_status << 16),
entry);
break;
@@ -5435,7 +5550,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
case CTIO_A64_TYPE:
{
struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt;
- qlt_do_ctio_completion(vha, entry->handle,
+ qlt_do_ctio_completion(vha, rsp, entry->handle,
le16_to_cpu(entry->status)|(pkt->entry_status << 16),
entry);
break;
@@ -5525,7 +5640,6 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
break;
}
- tgt->irq_cmd_count--;
}
/*
@@ -5538,15 +5652,9 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
int login_code;
- if (!ha->tgt.tgt_ops)
+ if (!tgt || tgt->tgt_stop || tgt->tgt_stopped)
return;
- if (unlikely(tgt == NULL)) {
- ql_dbg(ql_dbg_tgt, vha, 0xe03a,
- "ASYNC EVENT %#x, but no tgt (ha %p)\n", code, ha);
- return;
- }
-
if (((code == MBA_POINT_TO_POINT) || (code == MBA_CHG_IN_CONNECTION)) &&
IS_QLA2100(ha))
return;
@@ -5555,7 +5663,6 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
* Otherwise, some commands can stuck.
*/
- tgt->irq_cmd_count++;
switch (code) {
case MBA_RESET: /* Reset */
@@ -5578,7 +5685,8 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
if (tgt->link_reinit_iocb_pending) {
- qlt_send_notify_ack(vha, (void *)&tgt->link_reinit_iocb,
+ qlt_send_notify_ack(ha->base_qpair,
+ (void *)&tgt->link_reinit_iocb,
0, 0, 0, 0, 0, 0);
tgt->link_reinit_iocb_pending = 0;
}
@@ -5597,17 +5705,17 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
break;
case MBA_REJECTED_FCP_CMD:
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
- "qla_target(%d): Async event LS_REJECT occurred "
- "(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx,
- le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
- le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf017,
+ "qla_target(%d): Async event LS_REJECT occurred (m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)",
+ vha->vp_idx,
+ le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
+ le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
if (le16_to_cpu(mailbox[3]) == 1) {
/* exchange starvation. */
vha->hw->exch_starvation++;
if (vha->hw->exch_starvation > 5) {
- ql_log(ql_log_warn, vha, 0xffff,
+ ql_log(ql_log_warn, vha, 0xd03a,
"Exchange starvation-. Resetting RISC\n");
vha->hw->exch_starvation = 0;
@@ -5643,7 +5751,6 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
break;
}
- tgt->irq_cmd_count--;
}
static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
@@ -5707,12 +5814,12 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
case MODE_DUAL:
if (newfcport) {
if (!IS_IIDMA_CAPABLE(vha->hw) || !vha->hw->flags.gpsc_supported) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20fe,
"%s %d %8phC post upd_fcport fcp_cnt %d\n",
__func__, __LINE__, fcport->port_name, vha->fcport_count);
qla24xx_post_upd_fcport_work(vha, fcport);
} else {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc, vha, 0x20ff,
"%s %d %8phC post gpsc fcp_cnt %d\n",
__func__, __LINE__, fcport->port_name, vha->fcport_count);
qla24xx_post_gpsc_work(vha, fcport);
@@ -5838,7 +5945,7 @@ static void qlt_abort_work(struct qla_tgt *tgt,
}
if (!kref_get_unless_zero(&sess->sess_kref)) {
- ql_dbg(ql_dbg_tgt_tmr, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_tmr, vha, 0xf01c,
"%s: kref_get fail %8phC \n",
__func__, sess->port_name);
sess = NULL;
@@ -5861,7 +5968,8 @@ out_term2:
out_term:
spin_lock_irqsave(&ha->hardware_lock, flags);
- qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false);
+ qlt_24xx_send_abts_resp(ha->base_qpair, &prm->abts,
+ FCP_TMF_REJECTED, false);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -5875,7 +5983,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
unsigned long flags;
uint8_t *s_id = NULL; /* to hide compiler warnings */
int rc;
- uint32_t lun, unpacked_lun;
+ u64 unpacked_lun;
int fn;
void *iocb;
@@ -5902,7 +6010,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
}
if (!kref_get_unless_zero(&sess->sess_kref)) {
- ql_dbg(ql_dbg_tgt_tmr, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_tmr, vha, 0xf020,
"%s: kref_get fail %8phC\n",
__func__, sess->port_name);
sess = NULL;
@@ -5911,9 +6019,9 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
}
iocb = a;
- lun = a->u.isp24.fcp_cmnd.lun;
fn = a->u.isp24.fcp_cmnd.task_mgmt_flags;
- unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
+ unpacked_lun =
+ scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun);
rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
ha->tgt.tgt_ops->put_sess(sess);
@@ -5928,7 +6036,7 @@ out_term2:
ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
out_term:
- qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1, 0);
+ qlt_send_term_exchange(ha->base_qpair, NULL, &prm->tm_iocb2, 1, 0);
}
static void qlt_sess_work_fn(struct work_struct *work)
@@ -5976,6 +6084,8 @@ static void qlt_sess_work_fn(struct work_struct *work)
int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
{
struct qla_tgt *tgt;
+ int rc, i;
+ struct qla_qpair_hint *h;
if (!QLA_TGT_MODE_ENABLED())
return 0;
@@ -5998,9 +6108,47 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
return -ENOMEM;
}
+ tgt->qphints = kzalloc((ha->max_qpairs + 1) *
+ sizeof(struct qla_qpair_hint), GFP_KERNEL);
+ if (!tgt->qphints) {
+ kfree(tgt);
+ ql_log(ql_log_warn, base_vha, 0x0197,
+ "Unable to allocate qpair hints.\n");
+ return -ENOMEM;
+ }
+
if (!(base_vha->host->hostt->supported_mode & MODE_TARGET))
base_vha->host->hostt->supported_mode |= MODE_TARGET;
+ rc = btree_init64(&tgt->lun_qpair_map);
+ if (rc) {
+ kfree(tgt->qphints);
+ kfree(tgt);
+ ql_log(ql_log_info, base_vha, 0x0198,
+ "Unable to initialize lun_qpair_map btree\n");
+ return -EIO;
+ }
+ h = &tgt->qphints[0];
+ h->qpair = ha->base_qpair;
+ INIT_LIST_HEAD(&h->hint_elem);
+ h->cpuid = ha->base_qpair->cpuid;
+ list_add_tail(&h->hint_elem, &ha->base_qpair->hints_list);
+
+ for (i = 0; i < ha->max_qpairs; i++) {
+ unsigned long flags;
+
+ struct qla_qpair *qpair = ha->queue_pair_map[i];
+ h = &tgt->qphints[i + 1];
+ INIT_LIST_HEAD(&h->hint_elem);
+ if (qpair) {
+ h->qpair = qpair;
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ list_add_tail(&h->hint_elem, &qpair->hints_list);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+ h->cpuid = qpair->cpuid;
+ }
+ }
+
tgt->ha = ha;
tgt->vha = base_vha;
init_waitqueue_head(&tgt->waitQ);
@@ -6015,11 +6163,8 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
ql_dbg(ql_dbg_tgt, base_vha, 0xe067,
"qla_target(%d): using 64 Bit PCI addressing",
base_vha->vp_idx);
- tgt->tgt_enable_64bit_addr = 1;
/* 3 is reserved */
tgt->sg_tablesize = QLA_TGT_MAX_SG_24XX(base_vha->req->length - 3);
- tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX;
- tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX;
mutex_lock(&qla_tgt_mutex);
list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist);
@@ -6231,7 +6376,6 @@ qlt_enable_vha(struct scsi_qla_host *vha)
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
unsigned long flags;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
- int rspq_ent = QLA83XX_RSPQ_MSIX_ENTRY_NUMBER;
if (!tgt) {
ql_dbg(ql_dbg_tgt, vha, 0xe069,
@@ -6250,17 +6394,6 @@ qlt_enable_vha(struct scsi_qla_host *vha)
qla24xx_disable_vp(vha);
qla24xx_enable_vp(vha);
} else {
- if (ha->msix_entries) {
- ql_dbg(ql_dbg_tgt, vha, 0xffff,
- "%s: host%ld : vector %d cpu %d\n",
- __func__, vha->host_no,
- ha->msix_entries[rspq_ent].vector,
- ha->msix_entries[rspq_ent].cpuid);
-
- ha->tgt.rspq_vector_cpuid =
- ha->msix_entries[rspq_ent].cpuid;
- }
-
set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
qla2xxx_wake_dpc(base_vha);
qla2x00_wait_for_hba_online(base_vha);
@@ -6387,14 +6520,15 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked)
* can not be trusted. There is no point in passing
* it further up.
*/
- ql_log(ql_log_warn, vha, 0xffff,
+ ql_log(ql_log_warn, vha, 0xd03c,
"corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n",
pkt->u.isp24.fcp_hdr.s_id,
be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id),
le32_to_cpu(pkt->u.isp24.exchange_addr), pkt);
adjust_corrupted_atio(pkt);
- qlt_send_term_exchange(vha, NULL, pkt, ha_locked, 0);
+ qlt_send_term_exchange(ha->base_qpair, NULL, pkt,
+ ha_locked, 0);
} else {
qlt_24xx_atio_pkt_all_vps(vha,
(struct atio_from_isp *)pkt, ha_locked);
@@ -6445,8 +6579,9 @@ void
qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
{
struct qla_hw_data *ha = vha->hw;
- u32 tmp;
- u16 t;
+
+ if (!QLA_TGT_MODE_ENABLED())
+ return;
if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
if (!ha->tgt.saved_set) {
@@ -6461,24 +6596,10 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
ha->tgt.saved_set = 1;
}
- if (qla_tgt_mode_enabled(vha)) {
+ if (qla_tgt_mode_enabled(vha))
nv->exchange_count = cpu_to_le16(0xFFFF);
- } else { /* dual */
- if (ql_dm_tgt_ex_pct > 100) {
- ql_dm_tgt_ex_pct = 50;
- } else if (ql_dm_tgt_ex_pct == 100) {
- /* leave some for FW */
- ql_dm_tgt_ex_pct = 95;
- }
-
- tmp = ha->orig_fw_xcb_count * ql_dm_tgt_ex_pct;
- tmp = tmp/100;
- if (tmp > 0xffff)
- tmp = 0xffff;
-
- t = tmp & 0xffff;
- nv->exchange_count = cpu_to_le16(t);
- }
+ else /* dual */
+ nv->exchange_count = cpu_to_le16(ql2xexchoffld);
/* Enable target mode */
nv->firmware_options_1 |= cpu_to_le32(BIT_4);
@@ -6522,7 +6643,7 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
return;
}
- if (ha->tgt.enable_class_2) {
+ if (ha->base_qpair->enable_class_2) {
if (vha->flags.init_done)
fc_host_supported_classes(vha->host) =
FC_COS_CLASS2 | FC_COS_CLASS3;
@@ -6563,8 +6684,6 @@ void
qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
{
struct qla_hw_data *ha = vha->hw;
- u32 tmp;
- u16 t;
if (!QLA_TGT_MODE_ENABLED())
return;
@@ -6582,23 +6701,10 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
ha->tgt.saved_set = 1;
}
- if (qla_tgt_mode_enabled(vha)) {
+ if (qla_tgt_mode_enabled(vha))
nv->exchange_count = cpu_to_le16(0xFFFF);
- } else { /* dual */
- if (ql_dm_tgt_ex_pct > 100) {
- ql_dm_tgt_ex_pct = 50;
- } else if (ql_dm_tgt_ex_pct == 100) {
- /* leave some for FW */
- ql_dm_tgt_ex_pct = 95;
- }
-
- tmp = ha->orig_fw_xcb_count * ql_dm_tgt_ex_pct;
- tmp = tmp/100;
- if (tmp > 0xffff)
- tmp = 0xffff;
- t = tmp & 0xffff;
- nv->exchange_count = cpu_to_le16(t);
- }
+ else /* dual */
+ nv->exchange_count = cpu_to_le16(ql2xexchoffld);
/* Enable target mode */
nv->firmware_options_1 |= cpu_to_le32(BIT_4);
@@ -6641,7 +6747,7 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
return;
}
- if (ha->tgt.enable_class_2) {
+ if (ha->base_qpair->enable_class_2) {
if (vha->flags.init_done)
fc_host_supported_classes(vha->host) =
FC_COS_CLASS2 | FC_COS_CLASS3;
@@ -6688,21 +6794,6 @@ qlt_83xx_iospace_config(struct qla_hw_data *ha)
ha->msix_count += 1; /* For ATIO Q */
}
-int
-qlt_24xx_process_response_error(struct scsi_qla_host *vha,
- struct sts_entry_24xx *pkt)
-{
- switch (pkt->entry_type) {
- case ABTS_RECV_24XX:
- case ABTS_RESP_24XX:
- case CTIO_TYPE7:
- case NOTIFY_ACK_TYPE:
- case CTIO_CRC2:
- return 1;
- default:
- return 0;
- }
-}
void
qlt_modify_vp_config(struct scsi_qla_host *vha,
@@ -6744,7 +6835,7 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
rc = btree_init32(&ha->tgt.host_map);
if (rc)
- ql_log(ql_log_info, base_vha, 0xffff,
+ ql_log(ql_log_info, base_vha, 0xd03d,
"Unable to initialize ha->host_map btree\n");
qlt_update_vp_map(base_vha, SET_VP_IDX);
@@ -6780,7 +6871,8 @@ qlt_handle_abts_recv_work(struct work_struct *work)
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
- if (qla2x00_reset_active(vha) || (op->chip_reset != ha->chip_reset))
+ if (qla2x00_reset_active(vha) ||
+ (op->chip_reset != ha->base_qpair->chip_reset))
return;
spin_lock_irqsave(&ha->tgt.atio_lock, flags);
@@ -6788,14 +6880,15 @@ qlt_handle_abts_recv_work(struct work_struct *work)
spin_unlock_irqrestore(&ha->tgt.atio_lock, flags);
spin_lock_irqsave(&ha->hardware_lock, flags);
- qlt_response_pkt_all_vps(vha, (response_t *)&op->atio);
+ qlt_response_pkt_all_vps(vha, op->rsp, (response_t *)&op->atio);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
kfree(op);
}
void
-qlt_handle_abts_recv(struct scsi_qla_host *vha, response_t *pkt)
+qlt_handle_abts_recv(struct scsi_qla_host *vha, struct rsp_que *rsp,
+ response_t *pkt)
{
struct qla_tgt_sess_op *op;
@@ -6805,13 +6898,14 @@ qlt_handle_abts_recv(struct scsi_qla_host *vha, response_t *pkt)
/* do not reach for ATIO queue here. This is best effort err
* recovery at this point.
*/
- qlt_response_pkt_all_vps(vha, pkt);
+ qlt_response_pkt_all_vps(vha, rsp, pkt);
return;
}
memcpy(&op->atio, pkt, sizeof(*pkt));
op->vha = vha;
- op->chip_reset = vha->hw->chip_reset;
+ op->chip_reset = vha->hw->base_qpair->chip_reset;
+ op->rsp = rsp;
INIT_WORK(&op->work, qlt_handle_abts_recv_work);
queue_work(qla_tgt_wq, &op->work);
return;
@@ -6872,25 +6966,25 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd)
case SET_AL_PA:
slot = btree_lookup32(&vha->hw->tgt.host_map, key);
if (!slot) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf018,
"Save vha in host_map %p %06x\n", vha, key);
rc = btree_insert32(&vha->hw->tgt.host_map,
key, vha, GFP_ATOMIC);
if (rc)
- ql_log(ql_log_info, vha, 0xffff,
+ ql_log(ql_log_info, vha, 0xd03e,
"Unable to insert s_id into host_map: %06x\n",
key);
return;
}
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
- "replace existing vha in host_map %p %06x\n", vha, key);
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf019,
+ "replace existing vha in host_map %p %06x\n", vha, key);
btree_update32(&vha->hw->tgt.host_map, key, vha);
break;
case RESET_VP_IDX:
vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL;
break;
case RESET_AL_PA:
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01a,
"clear vha in host_map %p %06x\n", vha, key);
slot = btree_lookup32(&vha->hw->tgt.host_map, key);
if (slot)
@@ -6952,7 +7046,7 @@ int __init qlt_init(void)
sizeof(struct qla_tgt_mgmt_cmd), __alignof__(struct
qla_tgt_mgmt_cmd), 0, NULL);
if (!qla_tgt_mgmt_cmd_cachep) {
- ql_log(ql_log_fatal, NULL, 0xe06d,
+ ql_log(ql_log_fatal, NULL, 0xd04b,
"kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n");
return -ENOMEM;
}
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index d64420251194..7fe02d036bdf 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -70,6 +70,16 @@
/* Used to mark CTIO as intermediate */
#define CTIO_INTERMEDIATE_HANDLE_MARK BIT_30
+#define QLA_TGT_NULL_HANDLE 0
+
+#define QLA_TGT_HANDLE_MASK 0xF0000000
+#define QLA_QPID_HANDLE_MASK 0x00FF0000 /* qpair id mask */
+#define QLA_CMD_HANDLE_MASK 0x0000FFFF
+#define QLA_TGT_SKIP_HANDLE (0xFFFFFFFF & ~QLA_TGT_HANDLE_MASK)
+
+#define QLA_QPID_HANDLE_SHIFT 16
+#define GET_QID(_h) ((_h & QLA_QPID_HANDLE_MASK) >> QLA_QPID_HANDLE_SHIFT)
+
#ifndef OF_SS_MODE_0
/*
@@ -426,7 +436,7 @@ struct ctio7_to_24xx {
} status0;
struct {
uint16_t sense_length;
- uint16_t flags;
+ __le16 flags;
uint32_t residual;
__le16 ox_id;
uint16_t scsi_status;
@@ -664,6 +674,7 @@ struct abts_resp_from_24xx_fw {
struct qla_tgt_mgmt_cmd;
struct fc_port;
+struct qla_tgt_cmd;
/*
* This structure provides a template of function calls that the
@@ -675,7 +686,7 @@ struct qla_tgt_func_tmpl {
int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
unsigned char *, uint32_t, int, int, int);
void (*handle_data)(struct qla_tgt_cmd *);
- int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint16_t,
+ int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, u64, uint16_t,
uint32_t);
void (*free_cmd)(struct qla_tgt_cmd *);
void (*free_mcmd)(struct qla_tgt_mgmt_cmd *);
@@ -744,11 +755,6 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
#define QLA_TGT_STATE_DATA_IN 2 /* Data arrived + target processing */
#define QLA_TGT_STATE_PROCESSED 3 /* target done processing */
-
-/* Special handles */
-#define QLA_TGT_NULL_HANDLE 0
-#define QLA_TGT_SKIP_HANDLE (0xFFFFFFFF & ~CTIO_COMPLETION_HANDLE_MARK)
-
/* ATIO task_codes field */
#define ATIO_SIMPLE_QUEUE 0
#define ATIO_HEAD_OF_QUEUE 1
@@ -781,22 +787,28 @@ struct qla_port_24xx_data {
uint16_t reserved;
};
+struct qla_qpair_hint {
+ struct list_head hint_elem;
+ struct qla_qpair *qpair;
+ u16 cpuid;
+ uint8_t cmd_cnt;
+};
+
struct qla_tgt {
struct scsi_qla_host *vha;
struct qla_hw_data *ha;
-
+ struct btree_head64 lun_qpair_map;
+ struct qla_qpair_hint *qphints;
/*
* To sync between IRQ handlers and qlt_target_release(). Needed,
* because req_pkt() can drop/reaquire HW lock inside. Protected by
* HW lock.
*/
- int irq_cmd_count;
int atio_irq_cmd_count;
- int datasegs_per_cmd, datasegs_per_cont, sg_tablesize;
+ int sg_tablesize;
/* Target's flags, serialized by pha->hardware_lock */
- unsigned int tgt_enable_64bit_addr:1; /* 64-bits PCI addr enabled */
unsigned int link_reinit_iocb_pending:1;
/*
@@ -832,6 +844,7 @@ struct qla_tgt_sess_op {
struct work_struct work;
struct list_head cmd_list;
bool aborted;
+ struct rsp_que *rsp;
};
enum trace_flags {
@@ -859,10 +872,16 @@ enum trace_flags {
};
struct qla_tgt_cmd {
+ /*
+ * Do not move cmd_type field. it needs to line up with srb->cmd_type
+ */
+ uint8_t cmd_type;
+ uint8_t pad[7];
struct se_cmd se_cmd;
struct fc_port *sess;
+ struct qla_qpair *qpair;
+ uint32_t reset_count;
int state;
- 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];
@@ -885,10 +904,10 @@ struct qla_tgt_cmd {
int sg_cnt; /* SG segments count */
int bufflen; /* cmd buffer length */
int offset;
- uint32_t unpacked_lun;
+ u64 unpacked_lun;
enum dma_data_direction dma_data_direction;
- uint32_t reset_count;
+ uint16_t vp_idx;
uint16_t loop_id; /* to save extra sess dereferences */
struct qla_tgt *tgt; /* to save extra sess dereferences */
struct scsi_qla_host *vha;
@@ -939,6 +958,7 @@ struct qla_tgt_mgmt_cmd {
uint16_t tmr_func;
uint8_t fc_tm_rsp;
struct fc_port *sess;
+ struct qla_qpair *qpair;
struct se_cmd se_cmd;
struct work_struct free_work;
unsigned int flags;
@@ -960,7 +980,6 @@ struct qla_tgt_prm {
int seg_cnt;
int req_cnt;
uint16_t rq_result;
- uint16_t scsi_status;
int sense_buffer_len;
int residual;
int add_status_pkt;
@@ -1040,7 +1059,8 @@ static inline void sid_to_portid(const uint8_t *s_id, port_id_t *p)
/*
* Exported symbols from qla_target.c LLD logic used by qla2xxx code..
*/
-extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *);
+extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, struct rsp_que *,
+ response_t *);
extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
extern int qlt_abort_cmd(struct qla_tgt_cmd *);
@@ -1073,11 +1093,13 @@ extern int qlt_stop_phase1(struct qla_tgt *);
extern void qlt_stop_phase2(struct qla_tgt *);
extern irqreturn_t qla83xx_msix_atio_q(int, void *);
extern void qlt_83xx_iospace_config(struct qla_hw_data *);
-extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
+extern int qlt_free_qfull_cmds(struct qla_qpair *);
extern void qlt_logo_completion_handler(fc_port_t *, int);
extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
-void qlt_send_resp_ctio(scsi_qla_host_t *, struct qla_tgt_cmd *, uint8_t,
+void qlt_send_resp_ctio(struct qla_qpair *, struct qla_tgt_cmd *, uint8_t,
uint8_t, uint8_t, uint8_t);
+extern void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *,
+ struct qla_tgt_cmd *);
#endif /* __QLA_TARGET_H */
diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
index c197972a3e2d..33142610882f 100644
--- a/drivers/scsi/qla2xxx/qla_tmpl.c
+++ b/drivers/scsi/qla2xxx/qla_tmpl.c
@@ -219,8 +219,6 @@ qla27xx_skip_entry(struct qla27xx_fwdt_entry *ent, void *buf)
{
if (buf)
ent->hdr.driver_flags |= DRIVER_FLAG_SKIP_ENTRY;
- ql_dbg(ql_dbg_misc + ql_dbg_verbose, NULL, 0xd011,
- "Skipping entry %d\n", ent->hdr.entry_type);
}
static int
@@ -818,6 +816,8 @@ qla27xx_walk_template(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_misc, vha, 0xd01a,
"%s: entry count %lx\n", __func__, count);
while (count--) {
+ if (buf && *len >= vha->hw->fw_dump_len)
+ break;
if (qla27xx_find_entry(ent->hdr.entry_type)(vha, ent, buf, len))
break;
ent = qla27xx_next_entry(ent);
@@ -825,18 +825,20 @@ qla27xx_walk_template(struct scsi_qla_host *vha,
if (count)
ql_dbg(ql_dbg_misc, vha, 0xd018,
- "%s: residual count (%lx)\n", __func__, count);
+ "%s: entry residual count (%lx)\n", __func__, count);
if (ent->hdr.entry_type != ENTRY_TYPE_TMP_END)
ql_dbg(ql_dbg_misc, vha, 0xd019,
- "%s: missing end (%lx)\n", __func__, count);
+ "%s: missing end entry (%lx)\n", __func__, count);
- ql_dbg(ql_dbg_misc, vha, 0xd01b,
- "%s: len=%lx\n", __func__, *len);
+ if (buf && *len != vha->hw->fw_dump_len)
+ ql_dbg(ql_dbg_misc, vha, 0xd01b,
+ "%s: length=%#lx residual=%+ld\n",
+ __func__, *len, vha->hw->fw_dump_len - *len);
if (buf) {
ql_log(ql_log_warn, vha, 0xd015,
- "Firmware dump saved to temp buffer (%ld/%p)\n",
+ "Firmware dump saved to temp buffer (%lu/%p)\n",
vha->host_no, vha->hw->fw_dump);
qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
}
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 45bc84e8e3bf..005a378f7fab 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "9.00.00.00-k"
+#define QLA2XXX_VERSION "10.00.00.00-k"
-#define QLA_DRIVER_MAJOR_VER 9
+#define QLA_DRIVER_MAJOR_VER 10
#define QLA_DRIVER_MINOR_VER 0
#define QLA_DRIVER_PATCH_VER 0
#define QLA_DRIVER_BETA_VER 0
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 7443e4efa3ae..c4b414833b86 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <generated/utsrelease.h>
#include <linux/utsname.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
@@ -284,7 +283,7 @@ static void tcm_qla2xxx_complete_free(struct work_struct *work)
WARN_ON(cmd->trc_flags & TRC_CMD_FREE);
- cmd->vha->tgt_counters.qla_core_ret_sta_ctio++;
+ cmd->qpair->tgt_counters.qla_core_ret_sta_ctio++;
cmd->trc_flags |= TRC_CMD_FREE;
transport_generic_free_cmd(&cmd->se_cmd, 0);
}
@@ -296,7 +295,7 @@ static void tcm_qla2xxx_complete_free(struct work_struct *work)
*/
static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd)
{
- cmd->vha->tgt_counters.core_qla_free_cmd++;
+ cmd->qpair->tgt_counters.core_qla_free_cmd++;
cmd->cmd_in_wq = 1;
WARN_ON(cmd->trc_flags & TRC_CMD_DONE);
@@ -492,7 +491,7 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
}
#endif
- cmd->vha->tgt_counters.qla_core_sbt_cmd++;
+ cmd->qpair->tgt_counters.qla_core_sbt_cmd++;
return target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0],
cmd->unpacked_lun, data_length, fcp_task_attr,
data_dir, flags);
@@ -520,7 +519,7 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
}
spin_unlock_irqrestore(&cmd->cmd_lock, flags);
- cmd->vha->tgt_counters.qla_core_ret_ctio++;
+ cmd->qpair->tgt_counters.qla_core_ret_ctio++;
if (!cmd->write_data_transferred) {
/*
* Check if se_cmd has already been aborted via LUN_RESET, and
@@ -595,7 +594,7 @@ static int tcm_qla2xxx_dif_tags(struct qla_tgt_cmd *cmd,
/*
* Called from qla_target.c:qlt_issue_task_mgmt()
*/
-static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, uint32_t lun,
+static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun,
uint16_t tmr_func, uint32_t tag)
{
struct fc_port *sess = mcmd->sess;
@@ -686,6 +685,19 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
struct qla_tgt_cmd, se_cmd);
int xmit_type = QLA_TGT_XMIT_STATUS;
+ if (cmd->aborted) {
+ /*
+ * Cmd can loop during Q-full. tcm_qla2xxx_aborted_task
+ * can get ahead of this cmd. tcm_qla2xxx_aborted_task
+ * already kick start the free.
+ */
+ pr_debug(
+ "queue_data_in aborted cmd[%p] refcount %d transport_state %x, t_state %x, se_cmd_flags %x\n",
+ cmd, kref_read(&cmd->se_cmd.cmd_kref),
+ cmd->se_cmd.transport_state, cmd->se_cmd.t_state,
+ cmd->se_cmd.se_cmd_flags);
+ return 0;
+ }
cmd->bufflen = se_cmd->data_length;
cmd->sg = NULL;
cmd->sg_cnt = 0;
@@ -1870,9 +1882,9 @@ static ssize_t tcm_qla2xxx_wwn_version_show(struct config_item *item,
char *page)
{
return sprintf(page,
- "TCM QLOGIC QLA2XXX NPIV capable fabric module %s on %s/%s on "
- UTS_RELEASE"\n", QLA2XXX_VERSION, utsname()->sysname,
- utsname()->machine);
+ "TCM QLOGIC QLA2XXX NPIV capable fabric module %s on %s/%s on %s\n",
+ QLA2XXX_VERSION, utsname()->sysname,
+ utsname()->machine, utsname()->release);
}
CONFIGFS_ATTR_RO(tcm_qla2xxx_wwn_, version);
@@ -1976,9 +1988,9 @@ static int tcm_qla2xxx_register_configfs(void)
{
int ret;
- pr_debug("TCM QLOGIC QLA2XXX fabric module %s on %s/%s on "
- UTS_RELEASE"\n", QLA2XXX_VERSION, utsname()->sysname,
- utsname()->machine);
+ pr_debug("TCM QLOGIC QLA2XXX fabric module %s on %s/%s on %s\n",
+ QLA2XXX_VERSION, utsname()->sysname,
+ utsname()->machine, utsname()->release);
ret = target_register_template(&tcm_qla2xxx_ops);
if (ret)