* [PATCH 01/22] qla2xxx: Fix wrong IOCB type assumption.
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-14 21:09 ` Christoph Hellwig
2016-12-06 20:30 ` [PATCH 02/22] qla2xxx: Include ATIO queue in firmware dump when in target mode Himanshu Madhani
` (21 subsequent siblings)
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
qlt_reset is call with Immedidate Notification IOCB only.
Current code wrongly cast it as ATIO IOCB.
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_target.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index bff9689..8a762a6 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -668,11 +668,10 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
{
struct qla_hw_data *ha = vha->hw;
struct qla_tgt_sess *sess = NULL;
- uint32_t unpacked_lun, lun = 0;
+ uint32_t unpacked_lun = 0;
uint16_t loop_id;
int res = 0;
struct imm_ntfy_from_isp *n = (struct imm_ntfy_from_isp *)iocb;
- struct atio_from_isp *a = (struct atio_from_isp *)iocb;
unsigned long flags;
loop_id = le16_to_cpu(n->u.isp24.nport_handle);
@@ -725,9 +724,6 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
"loop_id %d)\n", vha->host_no, sess, sess->port_name,
mcmd, loop_id);
- lun = a->u.isp24.fcp_cmnd.lun;
- unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
-
return qlt_issue_task_mgmt(sess, unpacked_lun, mcmd,
iocb, QLA24XX_MGMT_SEND_NACK);
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 01/22] qla2xxx: Fix wrong IOCB type assumption.
2016-12-06 20:30 ` [PATCH 01/22] qla2xxx: Fix wrong IOCB type assumption Himanshu Madhani
@ 2016-12-14 21:09 ` Christoph Hellwig
2016-12-15 17:20 ` Madhani, Himanshu
0 siblings, 1 reply; 50+ messages in thread
From: Christoph Hellwig @ 2016-12-14 21:09 UTC (permalink / raw)
To: Himanshu Madhani; +Cc: target-devel, nab, giridhar.malavali, linux-scsi
On Tue, Dec 06, 2016 at 12:30:30PM -0800, Himanshu Madhani wrote:
> + uint32_t unpacked_lun = 0;
Please remove the unpacked_lun variable as well, and just directly
pass 0 to qlt_issue_task_mgmt.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 01/22] qla2xxx: Fix wrong IOCB type assumption.
2016-12-14 21:09 ` Christoph Hellwig
@ 2016-12-15 17:20 ` Madhani, Himanshu
0 siblings, 0 replies; 50+ messages in thread
From: Madhani, Himanshu @ 2016-12-15 17:20 UTC (permalink / raw)
To: Christoph Hellwig
Cc: target-devel@vger.kernel.org, nab@linux-iscsi.org,
Malavali, Giridhar, linux-scsi@vger.kernel.org
On 12/14/16, 1:09 PM, "Christoph Hellwig" <hch@infradead.org> wrote:
>On Tue, Dec 06, 2016 at 12:30:30PM -0800, Himanshu Madhani wrote:
>> + uint32_t unpacked_lun = 0;
>
>Please remove the unpacked_lun variable as well, and just directly
>pass 0 to qlt_issue_task_mgmt.
Ack, will update and resend this patch.
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 02/22] qla2xxx: Include ATIO queue in firmware dump when in target mode
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
2016-12-06 20:30 ` [PATCH 01/22] qla2xxx: Fix wrong IOCB type assumption Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-06 20:30 ` [PATCH 03/22] qla2xxx: Set tcm_qla2xxx version to automatically track qla2xxx version Himanshu Madhani
` (20 subsequent siblings)
22 siblings, 0 replies; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@cavium.com>
---
drivers/scsi/qla2xxx/qla_tmpl.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
index 36935c9..9ae89af 100644
--- a/drivers/scsi/qla2xxx/qla_tmpl.c
+++ b/drivers/scsi/qla2xxx/qla_tmpl.c
@@ -433,6 +433,18 @@ static inline void (*qla27xx_read_vector(uint width))(void __iomem*, void *, ulo
count++;
}
}
+ } else if (QLA_TGT_MODE_ENABLED() &&
+ (ent->t263.queue_type == T263_QUEUE_TYPE_ATIO)) {
+ struct qla_hw_data *ha = vha->hw;
+ struct atio *atr = ha->tgt.atio_ring;
+
+ if (atr || !buf) {
+ length = ha->tgt.atio_q_length;
+ qla27xx_insert16(0, buf, len);
+ qla27xx_insert16(length, buf, len);
+ qla27xx_insertbuf(atr, length * sizeof(*atr), buf, len);
+ count++;
+ }
} else {
ql_dbg(ql_dbg_misc, vha, 0xd026,
"%s: unknown queue %x\n", __func__, ent->t263.queue_type);
@@ -676,6 +688,18 @@ static inline void (*qla27xx_read_vector(uint width))(void __iomem*, void *, ulo
count++;
}
}
+ } else if (QLA_TGT_MODE_ENABLED() &&
+ (ent->t274.queue_type == T274_QUEUE_TYPE_ATIO_SHAD)) {
+ struct qla_hw_data *ha = vha->hw;
+ struct atio *atr = ha->tgt.atio_ring_ptr;
+
+ if (atr || !buf) {
+ qla27xx_insert16(0, buf, len);
+ qla27xx_insert16(1, buf, len);
+ qla27xx_insert32(ha->tgt.atio_q_in ? *ha->tgt.atio_q_in : 0,
+ buf, len);
+ count++;
+ }
} else {
ql_dbg(ql_dbg_misc, vha, 0xd02f,
"%s: unknown queue %x\n", __func__, ent->t274.queue_type);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 03/22] qla2xxx: Set tcm_qla2xxx version to automatically track qla2xxx version.
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
2016-12-06 20:30 ` [PATCH 01/22] qla2xxx: Fix wrong IOCB type assumption Himanshu Madhani
2016-12-06 20:30 ` [PATCH 02/22] qla2xxx: Include ATIO queue in firmware dump when in target mode Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-14 21:12 ` Christoph Hellwig
2016-12-06 20:30 ` [PATCH 04/22] qla2xxx: Clear BIT 15 in NVRAM during initialization Himanshu Madhani
` (19 subsequent siblings)
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@cavium.com>
---
drivers/scsi/qla2xxx/tcm_qla2xxx.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h
index 37e026a..37e9f57 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h
@@ -1,7 +1,7 @@
#include <target/target_core_base.h>
#include <linux/btree.h>
-#define TCM_QLA2XXX_VERSION "v0.1"
+#define TCM_QLA2XXX_VERSION QLA2XXX_VERSION
/* length of ASCII WWPNs including pad */
#define TCM_QLA2XXX_NAMELEN 32
/*
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 04/22] qla2xxx: Clear BIT 15 in NVRAM during initialization.
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (2 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 03/22] qla2xxx: Set tcm_qla2xxx version to automatically track qla2xxx version Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-06 20:30 ` [PATCH 05/22] qla2xxx: Add DebugFS node of irq vector cpuid Himanshu Madhani
` (18 subsequent siblings)
22 siblings, 0 replies; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
Some of the ports have BIT_15 of firmware_options1 set. This is a
reserved bit and should not be set for Target Mode. Clear BIT 15
during stage1 initialization.
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@cavium.com>
---
drivers/scsi/qla2xxx/qla_target.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 8a762a6..adb3b93 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -6527,7 +6527,6 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
/* Disable ini mode, if requested */
if (!qla_ini_mode_enabled(vha))
nv->firmware_options_1 |= cpu_to_le32(BIT_5);
-
/* Disable Full Login after LIP */
nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
/* Enable initial LIP */
@@ -6541,6 +6540,13 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
/* Disable Full Login after LIP */
nv->host_p &= cpu_to_le32(~BIT_10);
+
+ /*
+ * clear BIT 15 explicitly as we have seen at least
+ * a couple of instances where this was set and this
+ * was causing the firmware to not be initialized.
+ */
+ nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_15);
/* Enable target PRLI control */
nv->firmware_options_2 |= cpu_to_le32(BIT_14);
} else {
@@ -6630,6 +6636,13 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
/* Enable initial LIP */
nv->firmware_options_1 &= cpu_to_le32(~BIT_9);
+ /*
+ * clear BIT 15 explicitly as we have seen at
+ * least a couple of instances where this was set
+ * and this was causing the firmware to not be
+ * initialized.
+ */
+ nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_15);
if (ql2xtgt_tape_enable)
/* Enable FC tape support */
nv->firmware_options_2 |= cpu_to_le32(BIT_12);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 05/22] qla2xxx: Add DebugFS node of irq vector cpuid
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (3 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 04/22] qla2xxx: Clear BIT 15 in NVRAM during initialization Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-14 21:13 ` Christoph Hellwig
2016-12-06 20:30 ` [PATCH 06/22] qla2xxx: Collect addtional debug data for FW Himanshu Madhani
` (17 subsequent siblings)
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
> cat /sys/kernel/debug/qla2xxx/*/irq_cpuid
qla2xxx_81
IRQ Name Vector CPUID
qla2xxx (default) 150 9
qla2xxx (rsp_q) 151 9
qla2xxx (atio_q) 152 9
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_dbg.c | 2 +-
drivers/scsi/qla2xxx/qla_def.h | 1 +
drivers/scsi/qla2xxx/qla_dfs.c | 52 +++++++++++++++++++++++++++++++++++++++++-
drivers/scsi/qla2xxx/qla_isr.c | 14 ++++++++++++
4 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 21d9fb7..b2e3167 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -59,7 +59,7 @@
* | | | 0xb13c-0xb140 |
* | | | 0xb149 |
* | MultiQ | 0xc010 | |
- * | Misc | 0xd301 | 0xd031-0xd0ff |
+ * | Misc | 0xd303 | 0xd031-0xd0ff |
* | | | 0xd101-0xd1fe |
* | | | 0xd214-0xd2fe |
* | Target Mode | 0xe080 | |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 84f2cc3..1e3a3fa 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3448,6 +3448,7 @@ struct qla_hw_data {
struct dentry *dfs_fce;
struct dentry *dfs_tgt_counters;
struct dentry *dfs_fw_resource_cnt;
+ struct dentry *dfs_irq_cpuid;
dma_addr_t fce_dma;
void *fce;
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 34272fd..08d7a05 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -13,6 +13,42 @@
static atomic_t qla2x00_dfs_root_count;
static int
+qla2x00_dfs_irq_cpuid_show(struct seq_file *s, void *unused)
+{
+ int i;
+ scsi_qla_host_t *vha = s->private;
+ struct qla_hw_data *ha = vha->hw;
+ struct qla_msix_entry *qentry;
+
+ seq_printf(s, "%s\n", vha->host_str);
+ seq_printf(s, "%20s Vector CPUID\n", "IRQ Name");
+
+ for (i = 0; i < ha->msix_count; i++) {
+ qentry = &ha->msix_entries[i];
+ if (qentry->have_irq)
+ seq_printf(s, "%20s %3d %d\n",
+ qentry->name, qentry->vector,
+ qentry->cpuid);
+ }
+
+ return 0;
+}
+
+static int
+qla2x00_dfs_irq_cpuid_open(struct inode *inode, struct file *file)
+{
+ scsi_qla_host_t *vha = inode->i_private;
+ return single_open(file, qla2x00_dfs_irq_cpuid_show, vha);
+}
+
+static const struct file_operations dfs_irq_cpuid_ops = {
+ .open = qla2x00_dfs_irq_cpuid_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int
qla2x00_dfs_tgt_sess_show(struct seq_file *s, void *unused)
{
scsi_qla_host_t *vha = s->private;
@@ -293,11 +329,20 @@
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,
+ ql_log(ql_log_warn, vha, 0xd302,
"Unable to create debugFS tgt_sess node.\n");
goto out;
}
+ ha->dfs_irq_cpuid = debugfs_create_file("irq_cpuid",
+ S_IRUSR, ha->dfs_dir, vha, &dfs_irq_cpuid_ops);
+ if (!ha->dfs_irq_cpuid) {
+ ql_log(ql_log_warn, vha, 0xd303,
+ "Unable to create debugFS irq_cpuid node.\n");
+ goto out;
+ }
+
+
out:
return 0;
}
@@ -307,6 +352,11 @@
{
struct qla_hw_data *ha = vha->hw;
+ if (ha->dfs_irq_cpuid) {
+ debugfs_remove(ha->dfs_irq_cpuid);
+ ha->dfs_irq_cpuid = 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_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 98e4904..dec4b37 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -3121,6 +3121,20 @@ struct qla_init_msix_entry {
msix_entries[QLA_ATIO_VECTOR].handler,
0, msix_entries[QLA_ATIO_VECTOR].name, rsp);
qentry->have_irq = 1;
+ qentry->irq_notify.notify = qla_irq_affinity_notify;
+ qentry->irq_notify.release = qla_irq_affinity_release;
+
+ /* Register for CPU affinity notification. */
+ irq_set_affinity_notifier(qentry->vector, &qentry->irq_notify);
+
+ /* Schedule work (ie. trigger a notification) to read cpu
+ * mask for this specific irq.
+ * kref_get is required because
+ * irq_affinity_notify() will do
+ * kref_put().
+ */
+ kref_get(&qentry->irq_notify.kref);
+ schedule_work(&qentry->irq_notify.work);
}
msix_register_fail:
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 05/22] qla2xxx: Add DebugFS node of irq vector cpuid
2016-12-06 20:30 ` [PATCH 05/22] qla2xxx: Add DebugFS node of irq vector cpuid Himanshu Madhani
@ 2016-12-14 21:13 ` Christoph Hellwig
2016-12-15 19:32 ` Madhani, Himanshu
0 siblings, 1 reply; 50+ messages in thread
From: Christoph Hellwig @ 2016-12-14 21:13 UTC (permalink / raw)
To: Himanshu Madhani; +Cc: target-devel, nab, giridhar.malavali, linux-scsi
On Tue, Dec 06, 2016 at 12:30:34PM -0800, Himanshu Madhani wrote:
> From: Quinn Tran <quinn.tran@cavium.com>
>
> > cat /sys/kernel/debug/qla2xxx/*/irq_cpuid
> qla2xxx_81
> IRQ Name Vector CPUID
> qla2xxx (default) 150 9
> qla2xxx (rsp_q) 151 9
> qla2xxx (atio_q) 152 9
Doesn't make sense - an interrupt can be assigned to multiple
CPUIDs, and you can see the assignment based on the irq count
in /proc/interrupts
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 05/22] qla2xxx: Add DebugFS node of irq vector cpuid
2016-12-14 21:13 ` Christoph Hellwig
@ 2016-12-15 19:32 ` Madhani, Himanshu
0 siblings, 0 replies; 50+ messages in thread
From: Madhani, Himanshu @ 2016-12-15 19:32 UTC (permalink / raw)
To: Christoph Hellwig
Cc: target-devel@vger.kernel.org, nab@linux-iscsi.org,
Malavali, Giridhar, linux-scsi@vger.kernel.org
Hi Christoph,
On 12/14/16, 1:13 PM, "Christoph Hellwig" <hch@infradead.org> wrote:
>Doesn't make sense - an interrupt can be assigned to multiple
>CPUIDs, and you can see the assignment based on the irq count
>in /proc/interrupts
>
We Added this for our debug purpose. We’ll drop this patch in next series.
Thanks,
Himanshu
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 06/22] qla2xxx: Collect addtional debug data for FW
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (4 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 05/22] qla2xxx: Add DebugFS node of irq vector cpuid Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-06 20:30 ` [PATCH 07/22] qla2xxx: Fix crash due to null pointer access Himanshu Madhani
` (16 subsequent siblings)
22 siblings, 0 replies; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_mbx.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index a94a3ab..76184ee 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -318,20 +318,33 @@ static int is_rom_cmd(uint16_t cmd)
}
} else {
- uint16_t mb0;
- uint32_t ictrl;
+ uint16_t mb[8];
+ uint32_t ictrl, host_status, hccr;
uint16_t w;
if (IS_FWI2_CAPABLE(ha)) {
- mb0 = RD_REG_WORD(®->isp24.mailbox0);
+ mb[0] = RD_REG_WORD(®->isp24.mailbox0);
+ mb[1] = RD_REG_WORD(®->isp24.mailbox1);
+ mb[2] = RD_REG_WORD(®->isp24.mailbox2);
+ mb[3] = RD_REG_WORD(®->isp24.mailbox3);
+ mb[7] = RD_REG_WORD(®->isp24.mailbox7);
ictrl = RD_REG_DWORD(®->isp24.ictrl);
+ host_status = RD_REG_DWORD(®->isp24.host_status);
+ hccr = RD_REG_DWORD(®->isp24.hccr);
+
+ ql_log(ql_log_warn, vha, 0x1119,
+ "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],
+ mb[7], host_status, hccr);
+
} else {
- mb0 = RD_MAILBOX_REG(ha, ®->isp, 0);
+ mb[0] = RD_MAILBOX_REG(ha, ®->isp, 0);
ictrl = RD_REG_WORD(®->isp.ictrl);
+ ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119,
+ "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
+ "mb[0]=0x%x\n", command, ictrl, jiffies, mb[0]);
}
- ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119,
- "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
- "mb[0]=0x%x\n", command, ictrl, jiffies, mb0);
ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019);
/* Capture FW dump only, if PCI device active */
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 07/22] qla2xxx: Fix crash due to null pointer access.
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (5 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 06/22] qla2xxx: Collect addtional debug data for FW Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-06 20:30 ` [PATCH 08/22] qla2xxx: Refactore target code to remove symbol dependency Himanshu Madhani
` (15 subsequent siblings)
22 siblings, 0 replies; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
This patch fixes crash due to Null pointer access.
Following stack trace will be seen.
[1469877.797315] Call Trace:
[1469877.799940] [<ffffffffa03ab6e9>] qla2x00_mem_alloc+0xb09/0x10c0 [qla2xxx]
[1469877.806980] [<ffffffffa03ac50a>] qla2x00_probe_one+0x86a/0x1b50 [qla2xxx]
[1469877.814013] [<ffffffff813b6d01>] ? __pm_runtime_resume+0x51/0xa0
[1469877.820265] [<ffffffff8157c1f5>] ? _raw_spin_lock_irqsave+0x25/0x90
[1469877.826776] [<ffffffff8157cd2d>] ? _raw_spin_unlock_irqrestore+0x6d/0x80
[1469877.833720] [<ffffffff810741d1>] ? preempt_count_sub+0xb1/0x100
[1469877.839885] [<ffffffff8157cd0c>] ? _raw_spin_unlock_irqrestore+0x4c/0x80
[1469877.846830] [<ffffffff81319b9c>] local_pci_probe+0x4c/0xb0
[1469877.852562] [<ffffffff810741d1>] ? preempt_count_sub+0xb1/0x100
[1469877.858727] [<ffffffff81319c89>] pci_call_probe+0x89/0xb0
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_os.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 544f957..ce8c1dd 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3681,7 +3681,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
sizeof(struct ct6_dsd), 0,
SLAB_HWCACHE_ALIGN, NULL);
if (!ctx_cachep)
- goto fail_free_gid_list;
+ goto fail_free_srb_mempool;
}
ha->ctx_mempool = mempool_create_slab_pool(SRB_MIN_REQ,
ctx_cachep);
@@ -3834,7 +3834,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
ha->loop_id_map = kzalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE) * sizeof(long),
GFP_KERNEL);
if (!ha->loop_id_map)
- goto fail_async_pd;
+ goto fail_loop_id_map;
else {
qla2x00_set_reserved_loop_ids(ha);
ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0123,
@@ -3843,10 +3843,15 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
return 0;
+fail_loop_id_map:
+ dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);
+ ha->async_pd = NULL;
fail_async_pd:
dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
+ ha->ex_init_cb = NULL;
fail_ex_init_cb:
kfree(ha->npiv_info);
+ ha->npiv_info = NULL;
fail_npiv_info:
dma_free_coherent(&ha->pdev->dev, ((*rsp)->length + 1) *
sizeof(response_t), (*rsp)->ring, (*rsp)->dma);
@@ -3870,6 +3875,14 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
ha->ms_iocb = NULL;
ha->ms_iocb_dma = 0;
+
+ if (ha->sns_cmd) {
+ dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
+ ha->sns_cmd, ha->sns_cmd_dma);
+ ha->sns_cmd_dma = 0;
+ ha->sns_cmd = NULL;
+ }
+
fail_dma_pool:
if (IS_QLA82XX(ha) || ql2xenabledif) {
dma_pool_destroy(ha->fcp_cmnd_dma_pool);
@@ -3887,10 +3900,12 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
kfree(ha->nvram);
ha->nvram = NULL;
fail_free_ctx_mempool:
- mempool_destroy(ha->ctx_mempool);
+ if (ha->ctx_mempool)
+ mempool_destroy(ha->ctx_mempool);
ha->ctx_mempool = NULL;
fail_free_srb_mempool:
- mempool_destroy(ha->srb_mempool);
+ if (ha->srb_mempool)
+ mempool_destroy(ha->srb_mempool);
ha->srb_mempool = NULL;
fail_free_gid_list:
dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 08/22] qla2xxx: Refactore target code to remove symbol dependency
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (6 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 07/22] qla2xxx: Fix crash due to null pointer access Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-14 21:18 ` Christoph Hellwig
2016-12-06 20:30 ` [PATCH 09/22] qla2xxx: Refactor T10-DIF PI support Himanshu Madhani
` (14 subsequent siblings)
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
Following changes are done for target code
- Move cmd search out of qla to remove symbol dependency. The
command list is held in se_session struct. This knowledege
should be in tcm_qla2xxx.
- Move code that "convert Task Mgmt Command flags fr ATIO
to TCM #define" from qla2xx driver to tcm_qla2xxx driver.
- Move percpu_ida_alloc/free to tcm_qla2xxx
- Refactor sess_kref handling as driver does not access se_session
often. Remove se_session internal knowledge from qla2xxx as
tcm_qla2xxx is the only one that have this knowledge.
- Move Command residual check from qla2xxx to tcm_qla2xxx
- qla2xxx currently access t_task_cdb/t_task_lba field in
se_cmd struct. Remove access of TCM's private data struct.
- Remove direct access of scsi_status field in se_cmd
- Remove se_cmd from qlt_do_ctio_completion
- Remove se_cmd access in srr code section
- Move se_cmd struct outside of qla_tgt_cmd/qla_tgt_mgmt_cmd.
- To convert the pointer from one struct to another, new inline
functions was added to take care of the convertion.
- Allow target driver to handle MBA_REJECTED_FCP_CMD AEN 8049. This
will allow driver to gracefully handle reaching the exchange
limit if desired. Ideally, we could track each NPORT
that we are caching by LRU time and logout the oldest handle.
- Moves allocation/free mechanism for task management commands
to TCM shim driver layer.
- Merge qla_tgt_sess into struct fc_port structures
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_bsg.c | 8 +-
drivers/scsi/qla2xxx/qla_def.h | 34 ++
drivers/scsi/qla2xxx/qla_dfs.c | 10 +-
drivers/scsi/qla2xxx/qla_gbl.h | 1 +
drivers/scsi/qla2xxx/qla_init.c | 26 +-
drivers/scsi/qla2xxx/qla_iocb.c | 7 +-
drivers/scsi/qla2xxx/qla_isr.c | 8 +-
drivers/scsi/qla2xxx/qla_mid.c | 3 +
drivers/scsi/qla2xxx/qla_mr.c | 12 +-
drivers/scsi/qla2xxx/qla_os.c | 10 +-
drivers/scsi/qla2xxx/qla_target.c | 793 ++++++++++++-------------------------
drivers/scsi/qla2xxx/qla_target.h | 157 +++-----
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 588 ++++++++++++++++++++-------
drivers/scsi/qla2xxx/tcm_qla2xxx.h | 14 +-
14 files changed, 855 insertions(+), 816 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 1bf8061..cdf0dce 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -61,7 +61,7 @@
if (sp->type == SRB_CT_CMD ||
sp->type == SRB_FXIOCB_BCMD ||
sp->type == SRB_ELS_CMD_HST)
- kfree(sp->fcport);
+ qla2x00_free_fcport(sp->fcport);
qla2x00_rel_sp(vha, sp);
}
@@ -409,7 +409,7 @@
done_free_fcport:
if (bsg_request->msgcode == FC_BSG_RPT_ELS)
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
done:
return rval;
}
@@ -549,7 +549,7 @@
return rval;
done_free_fcport:
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
done_unmap_sg:
dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
@@ -2052,7 +2052,7 @@
return rval;
done_free_fcport:
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
done_unmap_rsp_sg:
if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 1e3a3fa..07cda5a 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1793,6 +1793,7 @@ struct crc_context {
#define SS_RESIDUAL_OVER BIT_10
#define SS_SENSE_LEN_VALID BIT_9
#define SS_RESPONSE_INFO_LEN_VALID BIT_8
+#define SS_SCSI_STATUS_BYTE 0xff
#define SS_RESERVE_CONFLICT (BIT_4 | BIT_3)
#define SS_BUSY_CONDITION BIT_3
@@ -2033,6 +2034,20 @@ struct mbx_entry {
FCT_TARGET
} fc_port_type_t;
+typedef enum {
+ QLT_PLOGI_LINK_SAME_WWN,
+ QLT_PLOGI_LINK_CONFLICT,
+ QLT_PLOGI_LINK_MAX
+} qlt_plogi_link_t;
+
+typedef struct {
+ struct list_head list;
+ u8 iocb[64]; /* imm_ntfy_from_isp */
+ port_id_t id;
+ int ref_count;
+} qlt_plogi_ack_t;
+
+
/*
* Fibre channel port structure.
*/
@@ -2046,6 +2061,25 @@ struct mbx_entry {
uint16_t loop_id;
uint16_t old_loop_id;
+ unsigned int conf_compl_supported:1;
+ unsigned int deleted:2;
+ unsigned int local:1;
+ unsigned int logout_on_delete:1;
+ unsigned int keep_nport_handle:1;
+ unsigned int send_els_logo:1;
+
+ unsigned char logout_completed;
+ int generation;
+
+ void *se_sess;
+ struct kref sess_kref;
+ struct qla_tgt *tgt;
+ unsigned long expires;
+ struct list_head del_list_entry;
+ struct work_struct free_work;
+
+ qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX];
+
uint16_t tgt_id;
uint16_t old_tgt_id;
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 08d7a05..6aa24ee 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -54,7 +54,7 @@
scsi_qla_host_t *vha = s->private;
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
- struct qla_tgt_sess *sess = NULL;
+ struct fc_port *sess = NULL;
struct qla_tgt *tgt= vha->vha_tgt.qla_tgt;
seq_printf(s, "%s\n",vha->host_str);
@@ -62,11 +62,11 @@
seq_printf(s, "Port ID Port Name Handle\n");
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
+ list_for_each_entry(sess, &vha->vp_fcports, list) {
seq_printf(s, "%02x:%02x:%02x %8phC %d\n",
- sess->s_id.b.domain,sess->s_id.b.area,
- sess->s_id.b.al_pa, sess->port_name,
- sess->loop_id);
+ sess->d_id.b.domain, sess->d_id.b.area,
+ sess->d_id.b.al_pa, sess->port_name,
+ sess->loop_id);
}
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index afa0116..13c4d51 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -158,6 +158,7 @@ extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
extern void qla2x00_relogin(struct scsi_qla_host *);
extern void qla2x00_do_work(struct scsi_qla_host *);
extern void qla2x00_free_fcports(struct scsi_qla_host *);
+extern void qla2x00_free_fcport(fc_port_t *);
extern void qla83xx_schedule_work(scsi_qla_host_t *, int);
extern void qla83xx_service_idc_aen(struct work_struct *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 632d5f3..f3ea6b6 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2998,6 +2998,12 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
return fcport;
}
+void
+qla2x00_free_fcport(fc_port_t *fcport)
+{
+ kfree(fcport);
+}
+
/*
* qla2x00_configure_loop
* Updates Fibre Channel Device Database with what is actually on loop.
@@ -3293,7 +3299,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
}
cleanup_allocation:
- kfree(new_fcport);
+ qla2x00_free_fcport(new_fcport);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_disc, vha, 0x201d,
@@ -3352,12 +3358,6 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
"Unable to allocate fc remote port.\n");
return;
}
- /*
- * Create target mode FC NEXUS in qla_target.c if target mode is
- * enabled..
- */
-
- qlt_fc_port_added(vha, fcport);
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
*((fc_port_t **)rport->dd_data) = fcport;
@@ -3407,12 +3407,6 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
reg_port:
if (qla_ini_mode_enabled(vha))
qla2x00_reg_remote_port(vha, fcport);
- else {
- /*
- * Create target mode FC NEXUS in qla_target.c
- */
- qlt_fc_port_added(vha, fcport);
- }
}
/*
@@ -3677,7 +3671,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
/* Free all new device structures not processed. */
list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
list_del(&fcport->list);
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
}
if (rval) {
@@ -3803,7 +3797,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
list_for_each_entry_safe(fcport, fcptemp,
new_fcports, list) {
list_del(&fcport->list);
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
}
rval = QLA_SUCCESS;
break;
@@ -3939,7 +3933,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
new_fcport->d_id.b24 = nxt_d_id.b24;
}
- kfree(new_fcport);
+ qla2x00_free_fcport(new_fcport);
return (rval);
}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 58e49a3..61f4d21 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2248,7 +2248,7 @@ struct fw_dif_context {
logio->control_flags =
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
if (!sp->fcport->tgt_session ||
- !sp->fcport->tgt_session->keep_nport_handle)
+ !sp->fcport->keep_nport_handle)
logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
logio->port_id[0] = sp->fcport->d_id.b.al_pa;
@@ -2345,7 +2345,8 @@ struct fw_dif_context {
srb_t *sp = (srb_t *)data;
struct srb_iocb *elsio = &sp->u.iocb_cmd;
- kfree(sp->fcport);
+ if (sp->fcport)
+ qla2x00_free_fcport(sp->fcport);
if (elsio->u.els_logo.els_logo_pyld)
dma_free_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
@@ -2421,7 +2422,7 @@ struct fw_dif_context {
/* Alloc SRB structure */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp) {
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
ql_log(ql_log_info, vha, 0x70e6,
"SRB allocation failed\n");
return -ENOMEM;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index dec4b37..5fd3b07 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1215,7 +1215,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
req->outstanding_cmds[index] = NULL;
/* Save ISP completion status */
- sp->done(ha, sp, DID_OK << 16);
+ sp->done(vha, sp, DID_OK << 16);
} else {
ql_log(ql_log_warn, vha, 0x3016, "Invalid SCSI SRB.\n");
@@ -2408,7 +2408,7 @@ struct scsi_dif_tuple {
resid_len, fw_resid_len, sp, cp);
if (rsp->status_srb == NULL)
- sp->done(ha, sp, res);
+ sp->done(vha, sp, res);
}
/**
@@ -2465,7 +2465,7 @@ struct scsi_dif_tuple {
/* Place command on done queue. */
if (sense_len == 0) {
rsp->status_srb = NULL;
- sp->done(ha, sp, cp->result);
+ sp->done(vha, sp, cp->result);
}
}
@@ -2497,7 +2497,7 @@ struct scsi_dif_tuple {
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (sp) {
- sp->done(ha, sp, res);
+ sp->done(vha, sp, res);
return;
}
fatal:
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index c6d6f0d..544aff1 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -599,6 +599,9 @@
struct qla_hw_data *ha = vha->hw;
struct qla_qpair *qpair, *tqpair;
+ if (!vha->hw)
+ return 0;
+
if (ql2xmqsupport) {
list_for_each_entry_safe(qpair, tqpair, &vha->qp_list,
qp_list_elem)
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index 02f1de1..4eac33e 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -1211,7 +1211,7 @@
fcport->old_tgt_id);
qla2x00_mark_device_lost(vha, fcport, 0, 0);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- kfree(new_fcport);
+ qla2x00_free_fcport(new_fcport);
return rval;
}
break;
@@ -1229,7 +1229,7 @@
return QLA_MEMORY_ALLOC_FAILED;
}
- kfree(new_fcport);
+ qla2x00_free_fcport(new_fcport);
return rval;
}
@@ -1297,7 +1297,7 @@
/* Free all new device structures not processed. */
list_for_each_entry_safe(fcport, rmptemp, &new_fcports, list) {
list_del(&fcport->list);
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
}
return rval;
@@ -2537,7 +2537,7 @@
par_sense_len, rsp_info_len);
if (rsp->status_srb == NULL)
- sp->done(ha, sp, res);
+ sp->done(vha, sp, res);
}
/**
@@ -2614,7 +2614,7 @@
/* Place command on done queue. */
if (sense_len == 0) {
rsp->status_srb = NULL;
- sp->done(ha, sp, cp->result);
+ sp->done(vha, sp, cp->result);
}
}
@@ -2695,7 +2695,7 @@
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (sp) {
- sp->done(ha, sp, res);
+ sp->done(vha, sp, res);
return;
}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index ce8c1dd..d6f4ce7 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1200,7 +1200,7 @@ uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
}
spin_lock_irqsave(&ha->hardware_lock, flags);
- sp->done(ha, sp, 0);
+ sp->done(vha, sp, 0);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Did the command return during mailbox execution? */
@@ -1598,7 +1598,8 @@ uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
struct qla_hw_data *ha = vha->hw;
struct req_que *req;
- qlt_host_reset_handler(ha);
+ if (ha->tgt.tgt_ops)
+ qlt_host_reset_handler(ha);
spin_lock_irqsave(&ha->hardware_lock, flags);
for (que = 0; que < ha->max_req_queues; que++) {
@@ -3476,6 +3477,9 @@ static void qla2x00_destroy_mbx_wq(struct qla_hw_data *ha)
{
struct qla_hw_data *ha = vha->hw;
+ if (!ha)
+ return;
+
qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
/* Disable timer */
@@ -3527,7 +3531,7 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha)
list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) {
list_del(&fcport->list);
qla2x00_clear_loop_id(fcport);
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
fcport = NULL;
}
}
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index adb3b93..cf4f86d 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -102,7 +102,7 @@ enum fcp_resp_rsp_codes {
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 int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
+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
*cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort);
@@ -123,12 +123,11 @@ static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
/*
* Global Variables
*/
-static struct kmem_cache *qla_tgt_mgmt_cmd_cachep;
static struct kmem_cache *qla_tgt_plogi_cachep;
-static mempool_t *qla_tgt_mgmt_cmd_mempool;
static struct workqueue_struct *qla_tgt_wq;
static DEFINE_MUTEX(qla_tgt_mutex);
-static LIST_HEAD(qla_tgt_glist);
+LIST_HEAD(qla_tgt_glist);
+EXPORT_SYMBOL(qla_tgt_glist);
/* This API intentionally takes dest as a parameter, rather than returning
* int value to avoid caller forgetting to issue wmb() after the store */
@@ -140,21 +139,6 @@ void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest)
wmb();
}
-/* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */
-static struct qla_tgt_sess *qlt_find_sess_by_port_name(
- struct qla_tgt *tgt,
- const uint8_t *port_name)
-{
- struct qla_tgt_sess *sess;
-
- list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) {
- if (!memcmp(sess->port_name, port_name, WWN_SIZE))
- return sess;
- }
-
- return NULL;
-}
-
/* Might release hw lock, then reaquire!! */
static inline int qlt_issue_marker(struct scsi_qla_host *vha, int vha_locked)
{
@@ -409,8 +393,9 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
list_for_each_entry(pla, &vha->plogi_ack_list, list) {
if (pla->id.b24 == id->b24) {
- qlt_send_term_imm_notif(vha, &pla->iocb, 1);
- pla->iocb = *iocb;
+ qlt_send_term_imm_notif(vha,
+ (struct imm_ntfy_from_isp *)&pla->iocb, 1);
+ memcpy(pla->iocb, iocb, sizeof(pla->iocb));
return pla;
}
}
@@ -423,7 +408,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
return NULL;
}
- pla->iocb = *iocb;
+ memcpy(pla->iocb, iocb, sizeof(pla->iocb));
pla->id = *id;
list_add_tail(&pla->list, &vha->plogi_ack_list);
@@ -432,6 +417,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
static void qlt_plogi_ack_unref(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla)
{
+ struct imm_ntfy_from_isp *iocb = (struct imm_ntfy_from_isp *)&pla->iocb;
BUG_ON(!pla->ref_count);
pla->ref_count--;
@@ -440,12 +426,12 @@ static void qlt_plogi_ack_unref(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla)
ql_dbg(ql_dbg_async, vha, 0x5089,
"Sending PLOGI ACK to wwn %8phC s_id %02x:%02x:%02x loop_id %#04x"
- " exch %#x ox_id %#x\n", pla->iocb.u.isp24.port_name,
- pla->iocb.u.isp24.port_id[2], pla->iocb.u.isp24.port_id[1],
- pla->iocb.u.isp24.port_id[0],
- le16_to_cpu(pla->iocb.u.isp24.nport_handle),
- pla->iocb.u.isp24.exchange_address, pla->iocb.ox_id);
- qlt_send_notify_ack(vha, &pla->iocb, 0, 0, 0, 0, 0, 0);
+ " exch %#x ox_id %#x\n", iocb->u.isp24.port_name,
+ iocb->u.isp24.port_id[2], iocb->u.isp24.port_id[1],
+ iocb->u.isp24.port_id[0],
+ le16_to_cpu(iocb->u.isp24.nport_handle),
+ iocb->u.isp24.exchange_address, iocb->ox_id);
+ qlt_send_notify_ack(vha, iocb, 0, 0, 0, 0, 0, 0);
list_del(&pla->list);
kmem_cache_free(qla_tgt_plogi_cachep, pla);
@@ -453,8 +439,9 @@ static void qlt_plogi_ack_unref(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla)
static void
qlt_plogi_ack_link(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla,
- struct qla_tgt_sess *sess, qlt_plogi_link_t link)
+ struct fc_port *sess, qlt_plogi_link_t link)
{
+ struct imm_ntfy_from_isp *iocb = (struct imm_ntfy_from_isp *)&pla->iocb;
/* Inc ref_count first because link might already be pointing at pla */
pla->ref_count++;
@@ -464,8 +451,8 @@ static void qlt_plogi_ack_unref(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla)
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf097,
"Linking sess %p [%d] wwn %8phC with PLOGI ACK to wwn %8phC"
" s_id %02x:%02x:%02x, ref=%d\n", sess, link, sess->port_name,
- pla->iocb.u.isp24.port_name, pla->iocb.u.isp24.port_id[2],
- pla->iocb.u.isp24.port_id[1], pla->iocb.u.isp24.port_id[0],
+ iocb->u.isp24.port_name, iocb->u.isp24.port_id[2],
+ iocb->u.isp24.port_id[1], iocb->u.isp24.port_id[0],
pla->ref_count);
sess->plogi_link[link] = pla;
@@ -519,7 +506,7 @@ static void qlt_plogi_ack_unref(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla)
static void qlt_free_session_done(struct work_struct *work)
{
- struct qla_tgt_sess *sess = container_of(work, struct qla_tgt_sess,
+ struct fc_port *sess = container_of(work, struct fc_port,
free_work);
struct qla_tgt *tgt = sess->tgt;
struct scsi_qla_host *vha = sess->vha;
@@ -532,7 +519,7 @@ static void qlt_free_session_done(struct work_struct *work)
"%s: se_sess %p / sess %p from port %8phC loop_id %#04x"
" s_id %02x:%02x:%02x logout %d keep %d els_logo %d\n",
__func__, sess->se_sess, sess, sess->port_name, sess->loop_id,
- sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+ sess->d_id.b.domain, sess->d_id.b.area, sess->d_id.b.al_pa,
sess->logout_on_delete, sess->keep_nport_handle,
sess->send_els_logo);
@@ -540,7 +527,7 @@ static void qlt_free_session_done(struct work_struct *work)
if (sess->send_els_logo) {
qlt_port_logo_t logo;
- logo.id = sess->s_id;
+ logo.id = sess->d_id;
logo.cmd_count = 0;
qlt_send_first_logo(vha, &logo);
}
@@ -550,10 +537,9 @@ static void qlt_free_session_done(struct work_struct *work)
memset(&fcport, 0, sizeof(fcport));
fcport.loop_id = sess->loop_id;
- fcport.d_id = sess->s_id;
+ fcport.d_id = sess->d_id;
memcpy(fcport.port_name, sess->port_name, WWN_SIZE);
fcport.vha = vha;
- fcport.tgt_session = sess;
rc = qla2x00_post_async_logout_work(vha, &fcport, NULL);
if (rc != QLA_SUCCESS)
@@ -591,20 +577,18 @@ static void qlt_free_session_done(struct work_struct *work)
spin_lock_irqsave(&ha->hardware_lock, flags);
{
- qlt_plogi_ack_t *own =
- sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
- qlt_plogi_ack_t *con =
- sess->plogi_link[QLT_PLOGI_LINK_CONFLICT];
-
+ qlt_plogi_ack_t *own = sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
+ qlt_plogi_ack_t *con = sess->plogi_link[QLT_PLOGI_LINK_CONFLICT];
+ struct imm_ntfy_from_isp *iocb;
if (con) {
+ iocb = (struct imm_ntfy_from_isp *)&con->iocb;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf099,
- "se_sess %p / sess %p port %8phC is gone,"
- " %s (ref=%d), releasing PLOGI for %8phC (ref=%d)\n",
- sess->se_sess, sess, sess->port_name,
- own ? "releasing own PLOGI" :
- "no own PLOGI pending",
- own ? own->ref_count : -1,
- con->iocb.u.isp24.port_name, con->ref_count);
+ "se_sess %p / sess %p port %8phC is gone,"
+ " %s (ref=%d), releasing PLOGI for %8phC (ref=%d)\n",
+ sess->se_sess, sess, sess->port_name,
+ own ? "releasing own PLOGI" : "no own PLOGI pending",
+ own ? own->ref_count : -1,
+ iocb->u.isp24.port_name, con->ref_count);
qlt_plogi_ack_unref(vha, con);
} else {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf09a,
@@ -619,14 +603,13 @@ static void qlt_free_session_done(struct work_struct *work)
qlt_plogi_ack_unref(vha, own);
}
- list_del(&sess->sess_list_entry);
-
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ sess->se_sess = NULL;
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001,
"Unregistration of sess %p finished\n", sess);
- kfree(sess);
/*
* We need to protect against race, when tgt is freed before or
* inside wake_up()
@@ -637,38 +620,31 @@ static void qlt_free_session_done(struct work_struct *work)
}
/* ha->tgt.sess_lock supposed to be held on entry */
-static void qlt_release_session(struct kref *kref)
+void qlt_unreg_sess(struct fc_port *sess)
{
- struct qla_tgt_sess *sess =
- container_of(kref, struct qla_tgt_sess, sess_kref);
struct scsi_qla_host *vha = sess->vha;
+ ql_dbg(ql_dbg_disc, sess->vha, 0xffff,
+ "%s sess %p for deletion %8phC\n",
+ __func__, sess, sess->port_name);
+
if (sess->se_sess)
vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess);
- if (!list_empty(&sess->del_list_entry))
- list_del_init(&sess->del_list_entry);
+ qla2x00_mark_device_lost(vha, sess, 1, 1);
+
sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
INIT_WORK(&sess->free_work, qlt_free_session_done);
schedule_work(&sess->free_work);
}
-
-void qlt_put_sess(struct qla_tgt_sess *sess)
-{
- if (!sess)
- return;
-
- assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
- kref_put(&sess->sess_kref, qlt_release_session);
-}
-EXPORT_SYMBOL(qlt_put_sess);
+EXPORT_SYMBOL(qlt_unreg_sess);
static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
{
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt_sess *sess = NULL;
- uint32_t unpacked_lun = 0;
+ struct fc_port *sess = NULL;
+ u64 unpacked_lun = 0;
uint16_t loop_id;
int res = 0;
struct imm_ntfy_from_isp *n = (struct imm_ntfy_from_isp *)iocb;
@@ -681,31 +657,6 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
qlt_clear_tgt_db(vha->vha_tgt.qla_tgt);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-#if 0 /* FIXME: do we need to choose a session here? */
- if (!list_empty(&ha->tgt.qla_tgt->sess_list)) {
- sess = list_entry(ha->tgt.qla_tgt->sess_list.next,
- typeof(*sess), sess_list_entry);
- switch (mcmd) {
- case QLA_TGT_NEXUS_LOSS_SESS:
- mcmd = QLA_TGT_NEXUS_LOSS;
- break;
- case QLA_TGT_ABORT_ALL_SESS:
- mcmd = QLA_TGT_ABORT_ALL;
- break;
- case QLA_TGT_NEXUS_LOSS:
- case QLA_TGT_ABORT_ALL:
- break;
- default:
- ql_dbg(ql_dbg_tgt, vha, 0xe046,
- "qla_target(%d): Not allowed "
- "command %x in %s", vha->vp_idx,
- mcmd, __func__);
- sess = NULL;
- break;
- }
- } else
- sess = NULL;
-#endif
} else {
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id);
@@ -729,7 +680,7 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
}
/* ha->tgt.sess_lock supposed to be held on entry */
-static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
+static void qlt_schedule_sess_for_deletion(struct fc_port *sess,
bool immediate)
{
struct qla_tgt *tgt = sess->tgt;
@@ -761,7 +712,7 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
"qla_target(%d): session for port %8phC (loop ID %d s_id %02x:%02x:%02x)"
" scheduled for deletion in %u secs (expires: %lu) immed: %d, logout: %d, gen: %#x\n",
sess->vha->vp_idx, sess->port_name, sess->loop_id,
- sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+ sess->d_id.b.domain, sess->d_id.b.area, sess->d_id.b.al_pa,
dev_loss_tmo, sess->expires, immediate, sess->logout_on_delete,
sess->generation);
@@ -775,10 +726,13 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
/* ha->tgt.sess_lock supposed to be held on entry */
static void qlt_clear_tgt_db(struct qla_tgt *tgt)
{
- struct qla_tgt_sess *sess;
+ struct fc_port *sess;
+ scsi_qla_host_t *vha = tgt->vha;
- list_for_each_entry(sess, &tgt->sess_list, sess_list_entry)
- qlt_schedule_sess_for_deletion(sess, true);
+ list_for_each_entry(sess, &vha->vp_fcports, list) {
+ if (sess->se_sess)
+ qlt_schedule_sess_for_deletion(sess, true);
+ }
/* At this point tgt could be already dead */
}
@@ -833,7 +787,7 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id,
}
/* ha->tgt.sess_lock supposed to be held on entry */
-static void qlt_undelete_sess(struct qla_tgt_sess *sess)
+static void qlt_undelete_sess(struct fc_port *sess)
{
BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING);
@@ -847,7 +801,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
sess_del_work);
struct scsi_qla_host *vha = tgt->vha;
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt_sess *sess;
+ struct fc_port *sess;
unsigned long flags, elapsed;
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
@@ -865,7 +819,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
sess);
if (sess->se_sess)
ha->tgt.tgt_ops->shutdown_sess(sess);
- qlt_put_sess(sess);
+ ha->tgt.tgt_ops->put_sess(sess);
} else {
schedule_delayed_work(&tgt->sess_del_work,
sess->expires - elapsed);
@@ -879,25 +833,24 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
* Adds an extra ref to allow to drop hw lock after adding sess to the list.
* Caller must put it.
*/
-static struct qla_tgt_sess *qlt_create_sess(
+static struct fc_port *qlt_create_sess(
struct scsi_qla_host *vha,
fc_port_t *fcport,
bool local)
{
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt_sess *sess;
+ struct fc_port *sess;
unsigned long flags;
/* Check to avoid double sessions */
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- list_for_each_entry(sess, &vha->vha_tgt.qla_tgt->sess_list,
- sess_list_entry) {
+ list_for_each_entry(sess, &vha->vp_fcports, list) {
if (!memcmp(sess->port_name, fcport->port_name, WWN_SIZE)) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005,
"Double sess %p found (s_id %x:%x:%x, "
"loop_id %d), updating to d_id %x:%x:%x, "
- "loop_id %d", sess, sess->s_id.b.domain,
- sess->s_id.b.al_pa, sess->s_id.b.area,
+ "loop_id %d", sess, sess->d_id.b.domain,
+ sess->d_id.b.al_pa, sess->d_id.b.area,
sess->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.al_pa, fcport->d_id.b.area,
fcport->loop_id);
@@ -920,7 +873,8 @@ static struct qla_tgt_sess *qlt_create_sess(
}
}
- kref_get(&sess->sess_kref);
+ ha->tgt.tgt_ops->get_sess(sess);
+
ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
(fcport->flags & FCF_CONF_COMP_SUPPORTED));
@@ -947,7 +901,7 @@ static struct qla_tgt_sess *qlt_create_sess(
}
sess->tgt = vha->vha_tgt.qla_tgt;
sess->vha = vha;
- sess->s_id = fcport->d_id;
+ sess->d_id = fcport->d_id;
sess->loop_id = fcport->loop_id;
sess->local = local;
kref_init(&sess->sess_kref);
@@ -959,6 +913,7 @@ static struct qla_tgt_sess *qlt_create_sess(
* code will adjust these flags as necessary. */
sess->logout_on_delete = 1;
sess->keep_nport_handle = 0;
+ memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006,
"Adding sess %p to tgt %p via ->check_initiator_node_acl()\n",
@@ -966,10 +921,10 @@ static struct qla_tgt_sess *qlt_create_sess(
sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);
BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
- memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list);
+ list_add_tail(&sess->list, &vha->vp_fcports);
+
vha->vha_tgt.qla_tgt->sess_count++;
qlt_do_generation_tick(vha, &sess->generation);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
@@ -978,8 +933,8 @@ static struct qla_tgt_sess *qlt_create_sess(
"qla_target(%d): %ssession for wwn %8phC (loop_id %d, "
"s_id %x:%x:%x, confirmed completion %ssupported) added\n",
vha->vp_idx, local ? "local " : "", fcport->port_name,
- fcport->loop_id, sess->s_id.b.domain, sess->s_id.b.area,
- sess->s_id.b.al_pa, sess->conf_compl_supported ? "" : "not ");
+ fcport->loop_id, sess->d_id.b.domain, sess->d_id.b.area,
+ sess->d_id.b.al_pa, sess->conf_compl_supported ? "" : "not ");
/*
* Determine if this fc_port->port_name is allowed to access
@@ -992,83 +947,16 @@ static struct qla_tgt_sess *qlt_create_sess(
return NULL;
} else {
/*
- * Take an extra reference to ->sess_kref here to handle qla_tgt_sess
+ * Take an extra reference to ->sess_kref here to handle fc_port
* access across ->tgt.sess_lock reaquire.
*/
- kref_get(&sess->sess_kref);
+ ha->tgt.tgt_ops->get_sess(sess);
}
return sess;
}
/*
- * Called from qla2x00_reg_remote_port()
- */
-void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
-{
- struct qla_hw_data *ha = vha->hw;
- struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
- struct qla_tgt_sess *sess;
- unsigned long flags;
-
- if (!vha->hw->tgt.tgt_ops)
- return;
-
- if (!tgt || (fcport->port_type != FCT_INITIATOR))
- return;
-
- if (qla_ini_mode_enabled(vha))
- return;
-
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- if (tgt->tgt_stop) {
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
- return;
- }
- sess = qlt_find_sess_by_port_name(tgt, fcport->port_name);
- if (!sess) {
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-
- mutex_lock(&vha->vha_tgt.tgt_mutex);
- sess = qlt_create_sess(vha, fcport, false);
- mutex_unlock(&vha->vha_tgt.tgt_mutex);
-
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- } else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
- /* Point of no return */
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
- return;
- } else {
- kref_get(&sess->sess_kref);
-
- if (sess->deleted) {
- qlt_undelete_sess(sess);
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04c,
- "qla_target(%u): %ssession for port %8phC "
- "(loop ID %d) reappeared\n", vha->vp_idx,
- sess->local ? "local " : "", sess->port_name,
- sess->loop_id);
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
- "Reappeared sess %p\n", sess);
- }
- ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
- (fcport->flags & FCF_CONF_COMP_SUPPORTED));
- }
-
- if (sess && sess->local) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04d,
- "qla_target(%u): local session for "
- "port %8phC (loop ID %d) became global\n", vha->vp_idx,
- fcport->port_name, sess->loop_id);
- sess->local = 0;
- }
- qlt_put_sess(sess);
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-}
-
-/*
* max_gen - specifies maximum session generation
* at which this deletion requestion is still valid
*/
@@ -1076,7 +964,7 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
{
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
- struct qla_tgt_sess *sess;
+ struct fc_port *sess = fcport;
unsigned long flags;
if (!vha->hw->tgt.tgt_ops)
@@ -1090,8 +978,7 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
return;
}
- sess = qlt_find_sess_by_port_name(tgt, fcport->port_name);
- if (!sess) {
+ if (!sess->se_sess) {
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
return;
}
@@ -1124,8 +1011,8 @@ static inline int test_tgt_sess_count(struct qla_tgt *tgt)
*/
spin_lock_irqsave(&ha->hardware_lock, flags);
ql_dbg(ql_dbg_tgt, tgt->vha, 0xe002,
- "tgt %p, empty(sess_list)=%d sess_count=%d\n",
- tgt, list_empty(&tgt->sess_list), tgt->sess_count);
+ "tgt %p, sess_count=%d\n",
+ tgt, tgt->sess_count);
res = (tgt->sess_count == 0);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -1188,8 +1075,8 @@ int qlt_stop_phase1(struct qla_tgt *tgt)
spin_unlock_irqrestore(&tgt->sess_work_lock, flags);
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00a,
- "Waiting for tgt %p: list_empty(sess_list)=%d "
- "sess_count=%d\n", tgt, list_empty(&tgt->sess_list),
+ "Waiting for tgt %p: "
+ "sess_count=%d\n", tgt,
tgt->sess_count);
wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
@@ -1299,6 +1186,9 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha,
request_t *pkt;
struct nack_to_isp *nack;
+ if (qla2x00_reset_active(vha))
+ return;
+
ql_dbg(ql_dbg_tgt, vha, 0xe004, "Sending NOTIFY_ACK (ha=%p)\n", ha);
/* Send marker if required */
@@ -1509,7 +1399,7 @@ 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;
@@ -1519,7 +1409,7 @@ static void abort_cmds_for_lun(struct scsi_qla_host *vha,
spin_lock(&vha->cmd_list_lock);
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(
@@ -1529,7 +1419,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(
@@ -1542,67 +1432,48 @@ static void abort_cmds_for_lun(struct scsi_qla_host *vha,
/* ha->hardware_lock supposed to be held on entry */
static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
- struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess)
+ struct abts_recv_from_24xx *abts, struct fc_port *sess)
{
struct qla_hw_data *ha = vha->hw;
- struct se_session *se_sess = sess->se_sess;
struct qla_tgt_mgmt_cmd *mcmd;
- struct se_cmd *se_cmd;
- u32 lun = 0;
int rc;
- bool found_lun = false;
-
- spin_lock(&se_sess->sess_cmd_lock);
- 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;
- }
- }
- spin_unlock(&se_sess->sess_cmd_lock);
-
- /* cmd not in LIO lists, look in qla list */
- 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);
- return 0;
- } else {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081,
- "unable to find cmd in driver or LIO for tag 0x%x\n",
- abts->exchange_addr_to_abort);
- return -ENOENT;
- }
- }
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f,
"qla_target(%d): task abort (tag=%d)\n",
vha->vp_idx, abts->exchange_addr_to_abort);
- mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC);
+ mcmd = ha->tgt.tgt_ops->alloc_mgmt_cmd();
if (mcmd == NULL) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf051,
"qla_target(%d): %s: Allocation of ABORT cmd failed",
vha->vp_idx, __func__);
return -ENOMEM;
}
- memset(mcmd, 0, sizeof(*mcmd));
mcmd->sess = sess;
memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts));
mcmd->reset_count = vha->hw->chip_reset;
+ mcmd->tmr_func = QLA_TGT_ABTS;
- rc = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, TMR_ABORT_TASK,
+ /* handle_tmr will search for LUN id based on exchange addr*/
+ rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, mcmd->tmr_func,
abts->exchange_addr_to_abort);
if (rc != 0) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052,
"qla_target(%d): tgt_ops->handle_tmr()"
" failed: %d", vha->vp_idx, rc);
- mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
- return -EFAULT;
+ ha->tgt.tgt_ops->free_mgmt_cmd(mcmd);
+
+ 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);
+ return 0;
+ } else {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081,
+ "unable to find cmd in driver or LIO for tag 0x%x\n",
+ abts->exchange_addr_to_abort);
+ return -ENOENT;
+ }
}
return 0;
@@ -1615,7 +1486,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
struct abts_recv_from_24xx *abts)
{
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt_sess *sess;
+ struct fc_port *sess;
uint32_t tag = abts->exchange_addr_to_abort;
uint8_t s_id[3];
int rc;
@@ -1732,12 +1603,6 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha,
qla2x00_start_iocbs(ha, ha->req);
}
-void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd)
-{
- mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
-}
-EXPORT_SYMBOL(qlt_free_mcmd);
-
/* callback from target fabric module code */
void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
{
@@ -2113,7 +1978,6 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
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;
prm->cmd = cmd;
prm->tgt = tgt;
@@ -2136,20 +2000,23 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
*full_req_cnt = prm->req_cnt;
- if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
- prm->residual = se_cmd->residual_count;
+ if (cmd->residual < 0) {
+ prm->residual = -(cmd->residual);
ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 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,
- cmd->bufflen, prm->rq_result);
+ "Residual underflow: %d (tag %d, "
+ "op %x, bufflen %d, rq_result %x)\n",
+ prm->residual, cmd->atio.u.isp24.exchange_addr,
+ cmd->cdb ? cmd->cdb[0] : 0,
+ cmd->bufflen, prm->rq_result);
prm->rq_result |= SS_RESIDUAL_UNDER;
- } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
- prm->residual = se_cmd->residual_count;
+ } else if (cmd->residual > 0) {
+ prm->residual = cmd->residual;
ql_dbg(ql_dbg_io, vha, 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);
+ "Residual overflow: %d (tag %d, "
+ "op %x, bufflen %d, rq_result %x)\n",
+ prm->residual, cmd->atio.u.isp24.exchange_addr,
+ cmd->cdb ? cmd->cdb[0] : 0,
+ cmd->bufflen, prm->rq_result);
prm->rq_result |= SS_RESIDUAL_OVER;
}
@@ -2222,7 +2089,8 @@ static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type)
== 50) {
*xmit_type &= ~QLA_TGT_XMIT_STATUS;
ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf015,
- "Dropping cmd %p (tag %d) status", cmd, se_cmd->tag);
+ "Dropping cmd %p (tag %d) status", cmd,
+ cmd->atio.u.isp24.exchange_addr);
}
#endif
/*
@@ -2246,8 +2114,8 @@ static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type)
ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf016,
"Cutting cmd %p (tag %d) buffer"
" tail to len %d, sg_cnt %d (cmd->bufflen %d,"
- " cmd->sg_cnt %d)", cmd, se_cmd->tag, tot_len, leave,
- cmd->bufflen, cmd->sg_cnt);
+ " cmd->sg_cnt %d)", cmd, cmd->atio.u.isp24.exchange_addr,
+ tot_len, leave, cmd->bufflen, cmd->sg_cnt);
cmd->bufflen = tot_len;
cmd->sg_cnt = leave;
@@ -2258,13 +2126,15 @@ static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type)
ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf017,
"Cutting cmd %p (tag %d) buffer head "
- "to offset %d (cmd->bufflen %d)", cmd, se_cmd->tag, offset,
+ "to offset %d (cmd->bufflen %d)", cmd,
+ cmd->atio.u.isp24.exchange_addr, offset,
cmd->bufflen);
if (offset == 0)
*xmit_type &= ~QLA_TGT_XMIT_DATA;
else if (qlt_set_data_offset(cmd, offset)) {
ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf018,
- "qlt_set_data_offset() failed (tag %d)", se_cmd->tag);
+ "qlt_set_data_offset() failed (tag %d)",
+ cmd->atio.u.isp24.exchange_addr);
}
}
}
@@ -2290,7 +2160,7 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
int i;
if (qlt_need_explicit_conf(prm->tgt->ha, prm->cmd, 1)) {
- if (prm->cmd->se_cmd.scsi_status != 0) {
+ if ((prm->rq_result & SS_SCSI_STATUS_BYTE) != 0) {
ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe017,
"Skipping EXPLICIT_CONFORM and "
"CTIO7_FLAGS_CONFORM_REQ for FCP READ w/ "
@@ -2474,9 +2344,9 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
memset(pkt, 0, sizeof(*pkt));
ql_dbg(ql_dbg_tgt, vha, 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,
- prm->prot_sg, prm->prot_seg_cnt, se_cmd->t_task_lba);
+ "qla_target(%d):%s: ulp_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,
+ prm->prot_sg, prm->prot_seg_cnt, cmd->lba);
if ((se_cmd->prot_op == TARGET_PROT_DIN_INSERT) ||
(se_cmd->prot_op == TARGET_PROT_DOUT_STRIP))
@@ -2690,10 +2560,10 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
qlt_check_srr_debug(cmd, &xmit_type);
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",
+ "is_send_status=%d, cmd->bufflen=%d, cmd->sg_cnt=%d, cmd->dma_data_direction=%d ulp_cmd[%p]\n",
(xmit_type & QLA_TGT_XMIT_STATUS) ?
1 : 0, cmd->bufflen, cmd->sg_cnt, cmd->dma_data_direction,
- &cmd->se_cmd);
+ cmd->ulp_cmd);
res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
&full_req_cnt);
@@ -2918,7 +2788,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
uint32_t e_ref_tag, a_ref_tag;
uint16_t e_app_tag, a_app_tag;
uint16_t e_guard, a_guard;
- uint64_t lba = cmd->se_cmd.t_task_lba;
+ uint64_t lba = cmd->lba;
a_guard = be16_to_cpu(*(uint16_t *)(ap + 0));
a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2));
@@ -3000,7 +2870,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
/* check guard */
if (e_guard != a_guard) {
cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
- cmd->se_cmd.bad_sector = cmd->se_cmd.t_task_lba;
+ cmd->se_cmd.bad_sector = cmd->lba;
ql_log(ql_log_warn, vha, 0xe076,
"Guard ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
@@ -3026,7 +2896,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
/* check appl tag */
if (e_app_tag != a_app_tag) {
cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED;
- cmd->se_cmd.bad_sector = cmd->se_cmd.t_task_lba;
+ cmd->se_cmd.bad_sector = cmd->lba;
ql_log(ql_log_warn, vha, 0xe078,
"App Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
@@ -3239,7 +3109,7 @@ static void qlt_init_term_exchange(struct scsi_qla_host *vha)
/* This cmd was never sent to TCM. There is no need
* to schedule free or call free_cmd
*/
- qlt_free_cmd(cmd);
+ vha->hw->tgt.tgt_ops->release_cmd(cmd);
vha->hw->tgt.num_qfull_cmds_alloc--;
}
}
@@ -3272,13 +3142,12 @@ int qlt_abort_cmd(struct qla_tgt_cmd *cmd)
{
struct qla_tgt *tgt = cmd->tgt;
struct scsi_qla_host *vha = tgt->vha;
- struct se_cmd *se_cmd = &cmd->se_cmd;
unsigned long flags;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
"qla_target(%d): terminating exchange for aborted cmd=%p "
- "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd,
- se_cmd->tag);
+ "(ulp_cmd=%p, tag=%d)", vha->vp_idx, cmd, cmd->ulp_cmd,
+ cmd->atio.u.isp24.exchange_addr);
spin_lock_irqsave(&cmd->cmd_lock, flags);
if (cmd->aborted) {
@@ -3288,14 +3157,9 @@ 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);
return EIO;
}
cmd->aborted = 1;
- cmd->cmd_flags |= BIT_6;
spin_unlock_irqrestore(&cmd->cmd_lock, flags);
qlt_send_term_exchange(vha, cmd, &cmd->atio, 0, 1);
@@ -3305,11 +3169,9 @@ int qlt_abort_cmd(struct qla_tgt_cmd *cmd)
void qlt_free_cmd(struct qla_tgt_cmd *cmd)
{
- struct qla_tgt_sess *sess = cmd->sess;
-
ql_dbg(ql_dbg_tgt, cmd->vha, 0xe074,
- "%s: se_cmd[%p] ox_id %04x\n",
- __func__, &cmd->se_cmd,
+ "%s: ulp_cmd[%p] ox_id %04x\n",
+ __func__, cmd->ulp_cmd,
be16_to_cpu(cmd->atio.u.isp24.fcp_hdr.ox_id));
BUG_ON(cmd->cmd_in_wq);
@@ -3324,13 +3186,6 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd)
cmd->jiffies_at_free = get_jiffies_64();
if (unlikely(cmd->free_sg))
kfree(cmd->sg);
-
- if (!sess || !sess->se_sess) {
- WARN_ON(1);
- return;
- }
- cmd->jiffies_at_free = get_jiffies_64();
- percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
}
EXPORT_SYMBOL(qlt_free_cmd);
@@ -3343,7 +3198,7 @@ static int qlt_prepare_srr_ctio(struct scsi_qla_host *vha,
struct qla_tgt_srr_imm *imm;
tgt->ctio_srr_id++;
- cmd->cmd_flags |= BIT_15;
+ cmd->trc_flags |= TRC_SRR_CTIO;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf019,
"qla_target(%d): CTIO with SRR status received\n", vha->vp_idx);
@@ -3526,7 +3381,7 @@ static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha,
dump_stack();
}
- cmd->cmd_flags |= BIT_17;
+ cmd->trc_flags |= TRC_FLUSH;
ha->tgt.tgt_ops->free_cmd(cmd);
}
@@ -3573,7 +3428,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
uint32_t status, void *ctio)
{
struct qla_hw_data *ha = vha->hw;
- struct se_cmd *se_cmd;
+ void *ulp_cmd;
struct qla_tgt_cmd *cmd;
if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) {
@@ -3590,7 +3445,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
if (cmd == NULL)
return;
- se_cmd = &cmd->se_cmd;
+ ulp_cmd = (void *)cmd->ulp_cmd;
cmd->cmd_sent_to_fw = 0;
qlt_unmap_sg(vha, cmd);
@@ -3606,10 +3461,10 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
/* They are OK */
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf058,
"qla_target(%d): CTIO with "
- "status %#x received, state %x, se_cmd %p, "
+ "status %#x received, state %x, ulp_cmd %p, "
"(LIP_RESET=e, ABORTED=2, TARGET_RESET=17, "
"TIMEOUT=b, INVALID_RX_ID=8)\n", vha->vp_idx,
- status, cmd->state, se_cmd);
+ status, cmd->state, ulp_cmd);
break;
case CTIO_PORT_LOGGED_OUT:
@@ -3619,10 +3474,11 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
(status & 0xFFFF) == CTIO_PORT_LOGGED_OUT;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf059,
- "qla_target(%d): CTIO with %s status %x "
- "received (state %x, se_cmd %p)\n", vha->vp_idx,
- logged_out ? "PORT LOGGED OUT" : "PORT UNAVAILABLE",
- status, cmd->state, se_cmd);
+ "qla_target(%d): CTIO with PORT LOGGED "
+ "OUT (29) or PORT UNAVAILABLE (28) status %x "
+ "received (state %x, ulp_cmd %p)\n", vha->vp_idx,
+ status, cmd->state, ulp_cmd);
+ break;
if (logged_out && cmd->sess) {
/*
@@ -3638,8 +3494,8 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
case CTIO_SRR_RECEIVED:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05a,
"qla_target(%d): CTIO with SRR_RECEIVED"
- " status %x received (state %x, se_cmd %p)\n",
- vha->vp_idx, status, cmd->state, se_cmd);
+ " status %x received (state %x, ulp_cmd %p)\n",
+ vha->vp_idx, status, cmd->state, ulp_cmd);
if (qlt_prepare_srr_ctio(vha, cmd, ctio) != 0)
break;
else
@@ -3649,8 +3505,8 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
struct ctio_crc_from_fw *crc =
(struct ctio_crc_from_fw *)ctio;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf073,
- "qla_target(%d): CTIO with DIF_ERROR status %x received (state %x, se_cmd %p) actual_dif[0x%llx] expect_dif[0x%llx]\n",
- vha->vp_idx, status, cmd->state, se_cmd,
+ "qla_target(%d): CTIO with DIF_ERROR status %x received (state %x, ulp_cmd %p) actual_dif[0x%llx] expect_dif[0x%llx]\n",
+ vha->vp_idx, status, cmd->state, ulp_cmd,
*((u64 *)&crc->actual_dif[0]),
*((u64 *)&crc->expected_dif[0]));
@@ -3678,8 +3534,9 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
}
default:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b,
- "qla_target(%d): CTIO with error status 0x%x received (state %x, se_cmd %p\n",
- vha->vp_idx, status, cmd->state, se_cmd);
+ "qla_target(%d): CTIO with error status 0x%x received "
+ "(state %x, ulp_cmd %p\n",
+ vha->vp_idx, status, cmd->state, ulp_cmd);
break;
}
@@ -3692,7 +3549,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->cmd_flags |= BIT_13;
+ cmd->trc_flags |= TRC_CTIO_ERR;
if (qlt_term_ctio_exchange(vha, ctio, cmd, status))
return;
}
@@ -3700,7 +3557,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
skip_term:
if (cmd->state == QLA_TGT_STATE_PROCESSED) {
- cmd->cmd_flags |= BIT_12;
+ cmd->trc_flags |= TRC_CTIO_DONE;
} else if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
cmd->state = QLA_TGT_STATE_DATA_IN;
@@ -3710,11 +3567,12 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
ha->tgt.tgt_ops->handle_data(cmd);
return;
} else if (cmd->aborted) {
- cmd->cmd_flags |= BIT_18;
+ cmd->trc_flags |= TRC_CTIO_ABORTED;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e,
- "Aborted command %p (tag %lld) finished\n", cmd, se_cmd->tag);
+ "Aborted command %p (tag %d) finished\n",
+ cmd, cmd->atio.u.isp24.exchange_addr);
} else {
- cmd->cmd_flags |= BIT_19;
+ cmd->trc_flags |= TRC_CTIO_STRANGE;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c,
"qla_target(%d): A command in state (%d) should "
"not return a CTIO complete\n", vha->vp_idx, cmd->state);
@@ -3729,39 +3587,8 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
ha->tgt.tgt_ops->free_cmd(cmd);
}
-static inline int qlt_get_fcp_task_attr(struct scsi_qla_host *vha,
- uint8_t task_codes)
-{
- int fcp_task_attr;
-
- switch (task_codes) {
- case ATIO_SIMPLE_QUEUE:
- fcp_task_attr = TCM_SIMPLE_TAG;
- break;
- case ATIO_HEAD_OF_QUEUE:
- fcp_task_attr = TCM_HEAD_TAG;
- break;
- case ATIO_ORDERED_QUEUE:
- fcp_task_attr = TCM_ORDERED_TAG;
- break;
- case ATIO_ACA_QUEUE:
- fcp_task_attr = TCM_ACA_TAG;
- break;
- case ATIO_UNTAGGED:
- fcp_task_attr = TCM_SIMPLE_TAG;
- break;
- default:
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05d,
- "qla_target: unknown task code %x, use ORDERED instead\n",
- task_codes);
- fcp_task_attr = TCM_ORDERED_TAG;
- break;
- }
- return fcp_task_attr;
-}
-
-static struct qla_tgt_sess *qlt_make_local_sess(struct scsi_qla_host *,
+static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *,
uint8_t *);
/*
* Process context for I/O path into tcm_qla2xxx code
@@ -3771,15 +3598,15 @@ 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 qla_tgt_sess *sess = cmd->sess;
+ 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;
+ int ret, data_dir, bidi = 0;
cmd->cmd_in_wq = 0;
- cmd->cmd_flags |= BIT_1;
+ cmd->trc_flags |= TRC_DO_WORK;
if (tgt->tgt_stop)
goto out_term;
@@ -3792,7 +3619,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);
@@ -3807,21 +3633,20 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
else
data_dir = DMA_NONE;
- fcp_task_attr = qlt_get_fcp_task_attr(vha,
- atio->u.isp24.fcp_cmnd.task_attr);
+
data_length = be32_to_cpu(get_unaligned((uint32_t *)
&atio->u.isp24.fcp_cmnd.add_cdb[
atio->u.isp24.fcp_cmnd.add_cdb_len]));
ret = ha->tgt.tgt_ops->handle_cmd(vha, cmd, cdb, data_length,
- fcp_task_attr, data_dir, bidi);
+ atio->u.isp24.fcp_cmnd.task_attr, data_dir, bidi);
if (ret != 0)
goto out_term;
/*
* Drop extra session reference from qla_tgt_handle_cmd_for_atio*(
*/
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- qlt_put_sess(sess);
+ ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return;
@@ -3831,16 +3656,16 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
* cmd has not sent to target yet, so pass NULL as the second
* argument to qlt_send_term_exchange() and free the memory here.
*/
- cmd->cmd_flags |= BIT_2;
+ cmd->trc_flags |= TRC_DO_WORK_ERR;
spin_lock_irqsave(&ha->hardware_lock, flags);
qlt_send_term_exchange(vha, 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);
+ ha->tgt.tgt_ops->release_cmd(cmd);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- qlt_put_sess(sess);
+ ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
@@ -3858,31 +3683,25 @@ static void qlt_do_work(struct work_struct *work)
}
static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
- struct qla_tgt_sess *sess,
+ struct fc_port *sess,
struct atio_from_isp *atio)
{
- struct se_session *se_sess = sess->se_sess;
struct qla_tgt_cmd *cmd;
- int tag;
- tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
- if (tag < 0)
+ cmd = vha->hw->tgt.tgt_ops->alloc_cmd(sess);
+ if (!cmd)
return NULL;
- cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
- memset(cmd, 0, sizeof(struct qla_tgt_cmd));
-
memcpy(&cmd->atio, atio, sizeof(*atio));
cmd->state = QLA_TGT_STATE_NEW;
cmd->tgt = vha->vha_tgt.qla_tgt;
qlt_incr_num_pend_cmds(vha);
cmd->vha = vha;
- cmd->se_cmd.map_tag = tag;
cmd->sess = sess;
cmd->loop_id = sess->loop_id;
cmd->conf_compl_supported = sess->conf_compl_supported;
- cmd->cmd_flags = 0;
+ cmd->trc_flags = 0;
cmd->jiffies_at_alloc = get_jiffies_64();
cmd->reset_count = vha->hw->chip_reset;
@@ -3899,7 +3718,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
struct qla_tgt_sess_op, work);
scsi_qla_host_t *vha = op->vha;
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt_sess *sess;
+ struct fc_port *sess;
struct qla_tgt_cmd *cmd;
unsigned long flags;
uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id;
@@ -3940,7 +3759,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
if (!cmd) {
spin_lock_irqsave(&ha->hardware_lock, flags);
qlt_send_busy(vha, &op->atio, SAM_STAT_BUSY);
- qlt_put_sess(sess);
+ ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
kfree(op);
return;
@@ -3967,7 +3786,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
{
struct qla_hw_data *ha = vha->hw;
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
- struct qla_tgt_sess *sess;
+ struct fc_port *sess;
struct qla_tgt_cmd *cmd;
if (unlikely(tgt->tgt_stop)) {
@@ -4007,20 +3826,18 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
/*
* Do kref_get() before returning + dropping qla_hw_data->hardware_lock.
*/
- kref_get(&sess->sess_kref);
+ ha->tgt.tgt_ops->get_sess(sess);
cmd = qlt_get_tag(vha, sess, atio);
if (!cmd) {
ql_dbg(ql_dbg_io, vha, 0x3062,
"qla_target(%d): Allocation of cmd failed\n", vha->vp_idx);
- qlt_put_sess(sess);
+ ha->tgt.tgt_ops->put_sess(sess);
return -ENOMEM;
}
cmd->cmd_in_wq = 1;
- cmd->cmd_flags |= BIT_0;
- cmd->se_cmd.cpuid = ha->msix_count ?
- ha->tgt.rspq_vector_cpuid : WORK_CPU_UNBOUND;
+ cmd->trc_flags |= TRC_NEW_CMD;
spin_lock(&vha->cmd_list_lock);
list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list);
@@ -4032,7 +3849,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
queue_work_on(smp_processor_id(), qla_tgt_wq,
&cmd->work);
else
- queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq,
+ queue_work_on(ha->tgt.rspq_vector_cpuid, qla_tgt_wq,
&cmd->work);
} else {
queue_work(qla_tgt_wq, &cmd->work);
@@ -4042,7 +3859,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
}
/* ha->hardware_lock supposed to be held on entry */
-static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
+static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun,
int fn, void *iocb, int flags)
{
struct scsi_qla_host *vha = sess->vha;
@@ -4050,9 +3867,8 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
struct qla_tgt_mgmt_cmd *mcmd;
struct atio_from_isp *a = (struct atio_from_isp *)iocb;
int res;
- uint8_t tmr_func;
- mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC);
+ mcmd = ha->tgt.tgt_ops->alloc_mgmt_cmd();
if (!mcmd) {
ql_dbg(ql_dbg_tgt_tmr, vha, 0x10009,
"qla_target(%d): Allocation of management "
@@ -4060,7 +3876,6 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
"leak\n", vha->vp_idx);
return -ENOMEM;
}
- memset(mcmd, 0, sizeof(*mcmd));
mcmd->sess = sess;
if (iocb) {
@@ -4072,79 +3887,17 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
mcmd->reset_count = vha->hw->chip_reset;
switch (fn) {
- case QLA_TGT_CLEAR_ACA:
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x10000,
- "qla_target(%d): CLEAR_ACA received\n", sess->vha->vp_idx);
- tmr_func = TMR_CLEAR_ACA;
- break;
-
- case QLA_TGT_TARGET_RESET:
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x10001,
- "qla_target(%d): TARGET_RESET received\n",
- sess->vha->vp_idx);
- tmr_func = TMR_TARGET_WARM_RESET;
- break;
-
case QLA_TGT_LUN_RESET:
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x10002,
- "qla_target(%d): LUN_RESET received\n", sess->vha->vp_idx);
- tmr_func = TMR_LUN_RESET;
abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id);
break;
-
- case QLA_TGT_CLEAR_TS:
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x10003,
- "qla_target(%d): CLEAR_TS received\n", sess->vha->vp_idx);
- tmr_func = TMR_CLEAR_TASK_SET;
- break;
-
- case QLA_TGT_ABORT_TS:
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x10004,
- "qla_target(%d): ABORT_TS received\n", sess->vha->vp_idx);
- tmr_func = TMR_ABORT_TASK_SET;
- break;
-#if 0
- case QLA_TGT_ABORT_ALL:
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x10005,
- "qla_target(%d): Doing ABORT_ALL_TASKS\n",
- sess->vha->vp_idx);
- tmr_func = 0;
- break;
-
- case QLA_TGT_ABORT_ALL_SESS:
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x10006,
- "qla_target(%d): Doing ABORT_ALL_TASKS_SESS\n",
- sess->vha->vp_idx);
- tmr_func = 0;
- break;
-
- case QLA_TGT_NEXUS_LOSS_SESS:
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x10007,
- "qla_target(%d): Doing NEXUS_LOSS_SESS\n",
- sess->vha->vp_idx);
- tmr_func = 0;
- break;
-
- case QLA_TGT_NEXUS_LOSS:
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x10008,
- "qla_target(%d): Doing NEXUS_LOSS\n", sess->vha->vp_idx);
- tmr_func = 0;
- break;
-#endif
- default:
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000a,
- "qla_target(%d): Unknown task mgmt fn 0x%x\n",
- sess->vha->vp_idx, fn);
- mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
- return -ENOSYS;
}
- res = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, tmr_func, 0);
+ res = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, mcmd->tmr_func, 0);
if (res != 0) {
ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000b,
"qla_target(%d): tgt.tgt_ops->handle_tmr() failed: %d\n",
sess->vha->vp_idx, res);
- mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
+ ha->tgt.tgt_ops->free_mgmt_cmd(mcmd);
return -EFAULT;
}
@@ -4157,14 +3910,13 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
struct atio_from_isp *a = (struct atio_from_isp *)iocb;
struct qla_hw_data *ha = vha->hw;
struct qla_tgt *tgt;
- struct qla_tgt_sess *sess;
- uint32_t lun, unpacked_lun;
+ struct fc_port *sess;
+ 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);
@@ -4172,7 +3924,7 @@ 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,
@@ -4190,38 +3942,37 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
/* ha->hardware_lock supposed to be held on entry */
static int __qlt_abort_task(struct scsi_qla_host *vha,
- struct imm_ntfy_from_isp *iocb, struct qla_tgt_sess *sess)
+ struct imm_ntfy_from_isp *iocb, struct fc_port *sess)
{
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);
+ mcmd = ha->tgt.tgt_ops->alloc_mgmt_cmd();
if (mcmd == NULL) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05f,
"qla_target(%d): %s: Allocation of ABORT cmd failed\n",
vha->vp_idx, __func__);
return -ENOMEM;
}
- memset(mcmd, 0, sizeof(*mcmd));
mcmd->sess = sess;
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);
+ unpacked_lun = scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun);
mcmd->reset_count = vha->hw->chip_reset;
+ mcmd->tmr_func = QLA_TGT_2G_ABORT_TASK;
- rc = ha->tgt.tgt_ops->handle_tmr(mcmd, unpacked_lun, TMR_ABORT_TASK,
+ rc = ha->tgt.tgt_ops->handle_tmr(mcmd, unpacked_lun, mcmd->tmr_func,
le16_to_cpu(iocb->u.isp2x.seq_id));
if (rc != 0) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf060,
"qla_target(%d): tgt_ops->handle_tmr() failed: %d\n",
vha->vp_idx, rc);
- mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
+ ha->tgt.tgt_ops->free_mgmt_cmd(mcmd);
return -EFAULT;
}
@@ -4233,7 +3984,7 @@ static int qlt_abort_task(struct scsi_qla_host *vha,
struct imm_ntfy_from_isp *iocb)
{
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt_sess *sess;
+ struct fc_port *sess;
int loop_id;
unsigned long flags;
@@ -4263,14 +4014,14 @@ void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
" port %8phC loop_id %#04x s_id %02x:%02x:%02x"
" LOGO failed: %#x\n",
__func__,
- fcport->tgt_session->se_sess,
+ fcport->se_sess,
fcport->tgt_session,
fcport->port_name, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa, rc);
}
- fcport->tgt_session->logout_completed = 1;
+ fcport->logout_completed = 1;
}
}
@@ -4281,16 +4032,17 @@ void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
* deletion. Returns existing session with matching wwn if present.
* Null otherwise.
*/
-static struct qla_tgt_sess *
+static struct fc_port *
qlt_find_sess_invalidate_other(struct qla_tgt *tgt, uint64_t wwn,
- port_id_t port_id, uint16_t loop_id, struct qla_tgt_sess **conflict_sess)
+ port_id_t port_id, uint16_t loop_id, struct fc_port **conflict_sess)
{
- struct qla_tgt_sess *sess = NULL, *other_sess;
+ struct fc_port *sess = NULL, *other_sess;
uint64_t other_wwn;
+ scsi_qla_host_t *vha = tgt->vha;
*conflict_sess = NULL;
- list_for_each_entry(other_sess, &tgt->sess_list, sess_list_entry) {
+ list_for_each_entry(other_sess, &vha->vp_fcports, list) {
other_wwn = wwn_to_u64(other_sess->port_name);
@@ -4301,7 +4053,7 @@ void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
}
/* find other sess with nport_id collision */
- if (port_id.b24 == other_sess->s_id.b24) {
+ if (port_id.b24 == other_sess->d_id.b24) {
if (loop_id != other_sess->loop_id) {
ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000c,
"Invalidating sess %p loop_id %d wwn %llx.\n",
@@ -4382,7 +4134,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
{
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt_sess *sess = NULL, *conflict_sess = NULL;
+ struct fc_port *sess = NULL, *conflict_sess = NULL;
uint64_t wwn;
port_id_t port_id;
uint16_t loop_id;
@@ -4462,7 +4214,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
* PLOGI and situation will correct itself.
*/
sess->keep_nport_handle = ((sess->loop_id == loop_id) &&
- (sess->s_id.b24 == port_id.b24));
+ (sess->d_id.b24 == port_id.b24));
qlt_schedule_sess_for_deletion(sess, true);
break;
@@ -4510,7 +4262,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
sess->local = 0;
sess->loop_id = loop_id;
- sess->s_id = port_id;
+ sess->d_id = port_id;
if (wd3_lo & BIT_7)
sess->conf_compl_supported = 1;
@@ -4695,7 +4447,6 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
(struct imm_ntfy_from_isp *)&imm->imm_ntfy;
struct qla_hw_data *ha = vha->hw;
struct qla_tgt_cmd *cmd = sctio->cmd;
- struct se_cmd *se_cmd = &cmd->se_cmd;
unsigned long flags;
int xmit_type = 0, resp = 0;
uint32_t offset;
@@ -4707,6 +4458,8 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf028, "SRR cmd %p, srr_ui %x\n",
cmd, srr_ui);
+ ha->tgt.tgt_ops->srr_get_cur_state(cmd, SRR_STATUS);
+
switch (srr_ui) {
case SRR_IU_STATUS:
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -4724,13 +4477,13 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
dump_stack();
goto out_reject;
}
- if (se_cmd->scsi_status != 0) {
+
+ if (cmd->scsi_status != 0) {
ql_dbg(ql_dbg_tgt, vha, 0xe02a,
"Rejecting SRR_IU_DATA_IN with non GOOD "
"scsi_status\n");
goto out_reject;
}
- cmd->bufflen = se_cmd->data_length;
if (qlt_has_data(cmd)) {
if (qlt_srr_adjust_data(cmd, offset, &xmit_type) != 0)
@@ -4742,9 +4495,10 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
resp = 1;
} else {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf064,
- "qla_target(%d): SRR for in data for cmd without them (tag %lld, SCSI status %d), reject",
- vha->vp_idx, se_cmd->tag,
- cmd->se_cmd.scsi_status);
+ "qla_target(%d): SRR for in data for cmd "
+ "without them (tag %d, SCSI status %d), "
+ "reject", vha->vp_idx, cmd->atio.u.isp24.exchange_addr,
+ cmd->scsi_status);
goto out_reject;
}
break;
@@ -4756,13 +4510,13 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
dump_stack();
goto out_reject;
}
- if (se_cmd->scsi_status != 0) {
+
+ if (cmd->scsi_status != 0) {
ql_dbg(ql_dbg_tgt, vha, 0xe02b,
"Rejecting SRR_IU_DATA_OUT"
" with non GOOD scsi_status\n");
goto out_reject;
}
- cmd->bufflen = se_cmd->data_length;
if (qlt_has_data(cmd)) {
if (qlt_srr_adjust_data(cmd, offset, &xmit_type) != 0)
@@ -4772,13 +4526,15 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
0, 0, 0, NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (xmit_type & QLA_TGT_XMIT_DATA) {
- cmd->cmd_flags |= BIT_8;
+ cmd->trc_flags |= TRC_SRR_XRDY;
qlt_rdy_to_xfer(cmd);
}
} else {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf066,
- "qla_target(%d): SRR for out data for cmd without them (tag %lld, SCSI status %d), reject",
- vha->vp_idx, se_cmd->tag, cmd->se_cmd.scsi_status);
+ "qla_target(%d): SRR for out data for cmd "
+ "without them (tag %d, SCSI status %d), "
+ "reject", vha->vp_idx, cmd->atio.u.isp24.exchange_addr,
+ cmd->scsi_status);
goto out_reject;
}
break;
@@ -4791,8 +4547,8 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
/* Transmit response in case of status and data-in cases */
if (resp) {
- cmd->cmd_flags |= BIT_7;
- qlt_xmit_response(cmd, xmit_type, se_cmd->scsi_status);
+ cmd->trc_flags |= TRC_SRR_RSP;
+ qlt_xmit_response(cmd, xmit_type, cmd->scsi_status);
}
return;
@@ -4807,7 +4563,7 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
cmd->state = QLA_TGT_STATE_DATA_IN;
dump_stack();
} else {
- cmd->cmd_flags |= BIT_9;
+ cmd->trc_flags |= TRC_SRR_TERM;
qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -4852,7 +4608,6 @@ static void qlt_handle_srr_work(struct work_struct *work)
list_for_each_entry(sctio, &tgt->srr_ctio_list, srr_list_entry) {
struct qla_tgt_srr_imm *imm, *i, *ti;
struct qla_tgt_cmd *cmd;
- struct se_cmd *se_cmd;
imm = NULL;
list_for_each_entry_safe(i, ti, &tgt->srr_imm_list,
@@ -4897,15 +4652,15 @@ static void qlt_handle_srr_work(struct work_struct *work)
cmd->sg = NULL;
cmd->free_sg = 0;
}
- se_cmd = &cmd->se_cmd;
- cmd->sg_cnt = se_cmd->t_data_nents;
- cmd->sg = se_cmd->t_data_sg;
+ tgt->ha->tgt.tgt_ops->srr_get_cur_state(cmd, SRR_SG);
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c,
- "SRR cmd %p (se_cmd %p, tag %lld, op %x), sg_cnt=%d, offset=%d",
- cmd, &cmd->se_cmd, se_cmd->tag, se_cmd->t_task_cdb ?
- se_cmd->t_task_cdb[0] : 0, cmd->sg_cnt, cmd->offset);
+ "SRR cmd %p (ulp_cmd %p, tag %d, op %x), "
+ "sg_cnt=%d, offset=%d",
+ cmd, cmd->ulp_cmd, cmd->atio.u.isp24.exchange_addr,
+ cmd->cdb ? cmd->cdb[0] : 0,
+ cmd->sg_cnt, cmd->offset);
qlt_handle_srr(vha, sctio, imm);
@@ -5152,7 +4907,7 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
struct ctio7_to_24xx *ctio24;
struct qla_hw_data *ha = vha->hw;
request_t *pkt;
- struct qla_tgt_sess *sess = NULL;
+ struct fc_port *sess = NULL;
unsigned long flags;
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
@@ -5213,10 +4968,8 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
{
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt_sess *sess;
- struct se_session *se_sess;
+ struct fc_port *sess;
struct qla_tgt_cmd *cmd;
- int tag;
if (unlikely(tgt->tgt_stop)) {
ql_dbg(ql_dbg_io, vha, 0x300a,
@@ -5245,13 +4998,7 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
if (!sess)
return;
- se_sess = sess->se_sess;
-
- tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
- if (tag < 0)
- return;
-
- cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
+ cmd = ha->tgt.tgt_ops->alloc_cmd(sess);
if (!cmd) {
ql_dbg(ql_dbg_io, vha, 0x3009,
"qla_target(%d): %s: Allocation of cmd failed\n",
@@ -5267,8 +5014,6 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
return;
}
- memset(cmd, 0, sizeof(struct qla_tgt_cmd));
-
qlt_incr_num_pend_cmds(vha);
INIT_LIST_HEAD(&cmd->cmd_list);
memcpy(&cmd->atio, atio, sizeof(*atio));
@@ -5353,7 +5098,7 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
/* This cmd was never sent to TCM. There is no need
* to schedule free or call free_cmd
*/
- qlt_free_cmd(cmd);
+ ha->tgt.tgt_ops->release_cmd(cmd);
}
return rc;
}
@@ -5748,6 +5493,7 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
case MBA_LOOP_DOWN:
case MBA_LIP_RESET:
case MBA_RSCN_UPDATE:
+ case MBA_REJECTED_FCP_CMD:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03c,
"qla_target(%d): Async event %#x occurred "
"(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx, code,
@@ -5785,7 +5531,7 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
fc_port_t *fcport;
int rc;
- fcport = kzalloc(sizeof(*fcport), GFP_KERNEL);
+ fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (!fcport) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06f,
"qla_target(%d): Allocation of tmp FC port failed",
@@ -5801,7 +5547,7 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
"qla_target(%d): Failed to retrieve fcport "
"information -- get_port_database() returned %x "
"(loop_id=0x%04x)", vha->vp_idx, rc, loop_id);
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
return NULL;
}
@@ -5809,10 +5555,10 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
}
/* Must be called under tgt_mutex */
-static struct qla_tgt_sess *qlt_make_local_sess(struct scsi_qla_host *vha,
+static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *vha,
uint8_t *s_id)
{
- struct qla_tgt_sess *sess = NULL;
+ struct fc_port *sess = NULL;
fc_port_t *fcport = NULL;
int rc, global_resets;
uint16_t loop_id = 0;
@@ -5874,7 +5620,7 @@ static struct qla_tgt_sess *qlt_make_local_sess(struct scsi_qla_host *vha,
mutex_unlock(&vha->vha_tgt.tgt_mutex);
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
return sess;
}
@@ -5883,7 +5629,7 @@ static void qlt_abort_work(struct qla_tgt *tgt,
{
struct scsi_qla_host *vha = tgt->vha;
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt_sess *sess = NULL;
+ struct fc_port *sess = NULL;
unsigned long flags = 0, flags2 = 0;
uint32_t be_s_id;
uint8_t s_id[3];
@@ -5915,7 +5661,7 @@ static void qlt_abort_work(struct qla_tgt *tgt,
goto out_term2;
}
- kref_get(&sess->sess_kref);
+ ha->tgt.tgt_ops->get_sess(sess);
}
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -5928,7 +5674,7 @@ static void qlt_abort_work(struct qla_tgt *tgt,
goto out_term;
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- qlt_put_sess(sess);
+ ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
return;
@@ -5939,7 +5685,7 @@ static void qlt_abort_work(struct qla_tgt *tgt,
qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- qlt_put_sess(sess);
+ ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
}
@@ -5949,11 +5695,11 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
struct atio_from_isp *a = &prm->tm_iocb2;
struct scsi_qla_host *vha = tgt->vha;
struct qla_hw_data *ha = vha->hw;
- struct qla_tgt_sess *sess = NULL;
+ struct fc_port *sess = NULL;
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;
@@ -5979,25 +5725,24 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
goto out_term;
}
- kref_get(&sess->sess_kref);
+ ha->tgt.tgt_ops->get_sess(sess);
}
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);
if (rc != 0)
goto out_term;
- qlt_put_sess(sess);
+ ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return;
out_term:
qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1, 0);
- qlt_put_sess(sess);
+ ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
@@ -6074,7 +5819,6 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
tgt->ha = ha;
tgt->vha = base_vha;
init_waitqueue_head(&tgt->waitQ);
- INIT_LIST_HEAD(&tgt->sess_list);
INIT_LIST_HEAD(&tgt->del_sess_list);
INIT_DELAYED_WORK(&tgt->sess_del_work,
(void (*)(struct work_struct *))qlt_del_sess_work_fn);
@@ -6234,16 +5978,11 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
void qlt_lport_deregister(struct scsi_qla_host *vha)
{
struct qla_hw_data *ha = vha->hw;
- struct Scsi_Host *sh = vha->host;
/*
* Clear the target_lport_ptr qla_target_template pointer in qla_hw_data
*/
vha->vha_tgt.target_lport_ptr = NULL;
ha->tgt.tgt_ops = NULL;
- /*
- * Release the Scsi_Host reference for the underlying qla2xxx host
- */
- scsi_host_put(sh);
}
EXPORT_SYMBOL(qlt_lport_deregister);
@@ -6913,15 +6652,6 @@ int __init qlt_init(void)
if (!QLA_TGT_MODE_ENABLED())
return 0;
- qla_tgt_mgmt_cmd_cachep = kmem_cache_create("qla_tgt_mgmt_cmd_cachep",
- 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,
- "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n");
- return -ENOMEM;
- }
-
qla_tgt_plogi_cachep = kmem_cache_create("qla_tgt_plogi_cachep",
sizeof(qlt_plogi_ack_t),
__alignof__(qlt_plogi_ack_t),
@@ -6931,16 +6661,7 @@ int __init qlt_init(void)
ql_log(ql_log_fatal, NULL, 0xe06d,
"kmem_cache_create for qla_tgt_plogi_cachep failed\n");
ret = -ENOMEM;
- goto out_mgmt_cmd_cachep;
- }
-
- qla_tgt_mgmt_cmd_mempool = mempool_create(25, mempool_alloc_slab,
- mempool_free_slab, qla_tgt_mgmt_cmd_cachep);
- if (!qla_tgt_mgmt_cmd_mempool) {
- ql_log(ql_log_fatal, NULL, 0xe06e,
- "mempool_create for qla_tgt_mgmt_cmd_mempool failed\n");
- ret = -ENOMEM;
- goto out_plogi_cachep;
+ return ret;
}
qla_tgt_wq = alloc_workqueue("qla_tgt_wq", 0, 0);
@@ -6948,19 +6669,15 @@ int __init qlt_init(void)
ql_log(ql_log_fatal, NULL, 0xe06f,
"alloc_workqueue for qla_tgt_wq failed\n");
ret = -ENOMEM;
- goto out_cmd_mempool;
+ goto out_plogi_cachep;
}
/*
* Return 1 to signal that initiator-mode is being disabled
*/
return (ql2x_ini_mode == QLA2XXX_INI_MODE_DISABLED) ? 1 : 0;
-out_cmd_mempool:
- mempool_destroy(qla_tgt_mgmt_cmd_mempool);
out_plogi_cachep:
kmem_cache_destroy(qla_tgt_plogi_cachep);
-out_mgmt_cmd_cachep:
- kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep);
return ret;
}
@@ -6970,7 +6687,5 @@ void qlt_exit(void)
return;
destroy_workqueue(qla_tgt_wq);
- mempool_destroy(qla_tgt_mgmt_cmd_mempool);
kmem_cache_destroy(qla_tgt_plogi_cachep);
- kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep);
}
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index f26c5f6..b09445d 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -709,36 +709,47 @@ struct abts_resp_from_24xx_fw {
/********************************************************************\
* Type Definitions used by initiator & target halves
\********************************************************************/
+typedef enum {
+ SRR_STATUS,
+ SRR_SG,
+} srr_state_op_t;
struct qla_tgt_mgmt_cmd;
-struct qla_tgt_sess;
-
+struct fc_port;
/*
* This structure provides a template of function calls that the
* target driver (from within qla_target.c) can issue to the
* target module (tcm_qla2xxx).
*/
struct qla_tgt_func_tmpl {
-
int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
- unsigned char *, uint32_t, int, int, int);
+ unsigned char *, uint32_t, uint8_t, int, int);
void (*handle_data)(struct qla_tgt_cmd *);
void (*handle_dif_err)(struct qla_tgt_cmd *);
- int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint8_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 *);
- void (*free_session)(struct qla_tgt_sess *);
+ void (*free_mgmt_cmd)(struct qla_tgt_mgmt_cmd *);
+ void (*free_session)(struct fc_port *);
int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,
- struct qla_tgt_sess *);
- void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);
- struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,
+ struct fc_port *);
+ void (*update_sess)(struct fc_port *, port_id_t, uint16_t, bool);
+ struct fc_port *(*find_sess_by_loop_id)(struct scsi_qla_host *,
const uint16_t);
- struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *,
+ struct fc_port *(*find_sess_by_s_id)(struct scsi_qla_host *,
const uint8_t *);
- void (*clear_nacl_from_fcport_map)(struct qla_tgt_sess *);
- void (*shutdown_sess)(struct qla_tgt_sess *);
+ void (*clear_nacl_from_fcport_map)(struct fc_port *);
+ void (*get_sess)(struct fc_port *);
+ void (*put_sess)(struct fc_port *);
+ void (*shutdown_sess)(struct fc_port *);
+ void (*release_cmd)(struct qla_tgt_cmd *);
+ struct qla_tgt_cmd * (*alloc_cmd)(struct fc_port *);
+ struct qla_tgt_mgmt_cmd * (*alloc_mgmt_cmd)(void);
+
+ /* support routine */
+ void (*srr_get_cur_state)(struct qla_tgt_cmd *, srr_state_op_t op);
};
int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
@@ -775,6 +786,8 @@ struct qla_tgt_func_tmpl {
#define QLA_TGT_ABORT_ALL 0xFFFE
#define QLA_TGT_NEXUS_LOSS_SESS 0xFFFD
#define QLA_TGT_NEXUS_LOSS 0xFFFC
+#define QLA_TGT_ABTS 0xFFFB
+#define QLA_TGT_2G_ABORT_TASK 0xFFFA
/* Notify Acknowledge flags */
#define NOTIFY_ACK_RES_COUNT BIT_8
@@ -852,9 +865,6 @@ struct qla_tgt {
/* Count of sessions refering qla_tgt. Protected by hardware_lock. */
int sess_count;
- /* Protected by hardware_lock. Addition also protected by tgt_mutex. */
- struct list_head sess_list;
-
/* Protected by hardware_lock */
struct list_head del_sess_list;
struct delayed_work sess_del_work;
@@ -897,85 +907,31 @@ enum qla_sess_deletion {
QLA_SESS_DELETION_IN_PROGRESS = 2,
};
-typedef enum {
- QLT_PLOGI_LINK_SAME_WWN,
- QLT_PLOGI_LINK_CONFLICT,
- QLT_PLOGI_LINK_MAX
-} qlt_plogi_link_t;
-
-typedef struct {
- struct list_head list;
- struct imm_ntfy_from_isp iocb;
- port_id_t id;
- int ref_count;
-} qlt_plogi_ack_t;
-
-/*
- * Equivilant to IT Nexus (Initiator-Target)
- */
-struct qla_tgt_sess {
- uint16_t loop_id;
- port_id_t s_id;
-
- unsigned int conf_compl_supported:1;
- unsigned int deleted:2;
- unsigned int local:1;
- unsigned int logout_on_delete:1;
- unsigned int keep_nport_handle:1;
- unsigned int send_els_logo:1;
-
- unsigned char logout_completed;
-
- int generation;
-
- struct se_session *se_sess;
- struct kref sess_kref;
- struct scsi_qla_host *vha;
- struct qla_tgt *tgt;
-
- struct list_head sess_list_entry;
- unsigned long expires;
- struct list_head del_list_entry;
-
- uint8_t port_name[WWN_SIZE];
- struct work_struct free_work;
-
- qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX];
+enum trace_flags {
+ TRC_NEW_CMD = BIT_0,
+ TRC_DO_WORK = BIT_1,
+ TRC_DO_WORK_ERR = BIT_2,
+ TRC_XFR_RDY = BIT_3,
+ TRC_XMIT_DATA = BIT_4,
+ TRC_XMIT_STATUS = BIT_5,
+ TRC_SRR_RSP = BIT_6,
+ TRC_SRR_XRDY = BIT_7,
+ TRC_SRR_TERM = BIT_8,
+ TRC_SRR_CTIO = BIT_9,
+ TRC_FLUSH = BIT_10,
+ TRC_CTIO_ERR = BIT_11,
+ TRC_CTIO_DONE = BIT_12,
+ TRC_CTIO_ABORTED = BIT_13,
+ TRC_CTIO_STRANGE = BIT_14,
+ TRC_CMD_DONE = BIT_15,
+ TRC_CMD_CHK_STOP = BIT_16,
+ TRC_CMD_FREE = BIT_17,
+ TRC_DATA_IN = BIT_18,
};
-typedef enum {
- /*
- * BIT_0 - Atio Arrival / schedule to work
- * BIT_1 - qlt_do_work
- * BIT_2 - qlt_do work failed
- * BIT_3 - xfer rdy/tcm_qla2xxx_write_pending
- * BIT_4 - read respond/tcm_qla2xx_queue_data_in
- * BIT_5 - status respond / tcm_qla2xx_queue_status
- * BIT_6 - tcm request to abort/Term exchange.
- * pre_xmit_response->qlt_send_term_exchange
- * BIT_7 - SRR received (qlt_handle_srr->qlt_xmit_response)
- * BIT_8 - SRR received (qlt_handle_srr->qlt_rdy_to_xfer)
- * BIT_9 - SRR received (qla_handle_srr->qlt_send_term_exchange)
- * BIT_10 - Data in - hanlde_data->tcm_qla2xxx_handle_data
-
- * BIT_12 - good completion - qlt_ctio_do_completion -->free_cmd
- * BIT_13 - Bad completion -
- * qlt_ctio_do_completion --> qlt_term_ctio_exchange
- * BIT_14 - Back end data received/sent.
- * BIT_15 - SRR prepare ctio
- * BIT_16 - complete free
- * BIT_17 - flush - qlt_abort_cmd_on_host_reset
- * BIT_18 - completion w/abort status
- * BIT_19 - completion w/unknown status
- * BIT_20 - tcm_qla2xxx_free_cmd
- */
- CMD_FLAG_DATA_WORK = BIT_11,
- CMD_FLAG_DATA_WORK_FREE = BIT_21,
-} cmd_flags_t;
-
struct qla_tgt_cmd {
- struct se_cmd se_cmd;
- struct qla_tgt_sess *sess;
+ void *ulp_cmd;
+ struct fc_port *sess;
int state;
struct work_struct free_work;
struct work_struct work;
@@ -994,14 +950,18 @@ struct qla_tgt_cmd {
unsigned int cmd_sent_to_fw:1;
unsigned int cmd_in_wq:1;
unsigned int aborted:1;
+ unsigned int data_work:1;
+ unsigned int data_work_free:1;
struct scatterlist *sg; /* cmd data buffer SG vector */
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;
+ int residual; /* + = over, - = under */
+ int8_t scsi_status;
uint16_t loop_id; /* to save extra sess dereferences */
struct qla_tgt *tgt; /* to save extra sess dereferences */
@@ -1014,11 +974,13 @@ struct qla_tgt_cmd {
uint32_t prot_sg_cnt;
uint32_t blk_sz;
struct crc_context *ctx;
+ uint8_t *cdb;
+ uint64_t lba;
uint64_t jiffies_at_alloc;
uint64_t jiffies_at_free;
- cmd_flags_t cmd_flags;
+ enum trace_flags trc_flags;
};
struct qla_tgt_sess_work_param {
@@ -1036,10 +998,10 @@ struct qla_tgt_sess_work_param {
};
struct qla_tgt_mgmt_cmd {
- uint8_t tmr_func;
+ uint16_t tmr_func;
uint8_t fc_tm_rsp;
- struct qla_tgt_sess *sess;
- struct se_cmd se_cmd;
+ struct fc_port *sess;
+ void *ulp_cmd;
struct work_struct free_work;
unsigned int flags;
uint32_t reset_count;
@@ -1101,7 +1063,7 @@ struct qla_tgt_srr_ctio {
extern int qlt_lport_register(void *, u64, u64, u64,
int (*callback)(struct scsi_qla_host *, void *, u64, u64));
extern void qlt_lport_deregister(struct scsi_qla_host *);
-void qlt_put_sess(struct qla_tgt_sess *sess);
+extern void qlt_unreg_sess(struct fc_port *);
extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *);
extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int);
extern int __init qlt_init(void);
@@ -1159,7 +1121,6 @@ static inline void sid_to_portid(const uint8_t *s_id, port_id_t *p)
extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
extern int qlt_abort_cmd(struct qla_tgt_cmd *);
extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
-extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *);
extern void qlt_enable_vha(struct scsi_qla_host *);
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 6643f6f..3fef40b 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -51,6 +51,50 @@
static struct workqueue_struct *tcm_qla2xxx_free_wq;
static struct workqueue_struct *tcm_qla2xxx_cmd_wq;
+static struct kmem_cache *tcm_qla_tgt_mgmt_cmd_cachep;
+static mempool_t *tcm_qla_tgt_mgmt_cmd_mempool;
+
+inline struct se_cmd *Q_TO_SE_CMD(struct qla_tgt_cmd *qcmd)
+{
+ struct tcm_qla_tgt_cmd *tc =
+ container_of(qcmd, struct tcm_qla_tgt_cmd, qcmd);
+
+ return &tc->se_cmd;
+}
+
+inline struct qla_tgt_cmd *SE_TO_Q_CMD(struct se_cmd *se_cmd)
+{
+ struct tcm_qla_tgt_cmd *tc =
+ container_of(se_cmd, struct tcm_qla_tgt_cmd, se_cmd);
+
+ return &tc->qcmd;
+}
+
+inline struct se_cmd *QMGT_TO_SE_CMD(struct qla_tgt_mgmt_cmd *qcmd)
+{
+ struct tcm_qla_tgt_mgmt_cmd *tc =
+ container_of(qcmd, struct tcm_qla_tgt_mgmt_cmd, mgt_cmd);
+
+ return &tc->se_cmd;
+}
+
+inline struct qla_tgt_mgmt_cmd *SE_TO_QMGT_CMD(struct se_cmd *se_cmd)
+{
+ struct tcm_qla_tgt_mgmt_cmd *tc =
+ container_of(se_cmd, struct tcm_qla_tgt_mgmt_cmd, se_cmd);
+
+ return &tc->mgt_cmd;
+}
+
+inline struct
+tcm_qla_tgt_mgmt_cmd *QMGT_TO_TMGT_CMD(struct qla_tgt_mgmt_cmd * qcmd)
+{
+ struct tcm_qla_tgt_mgmt_cmd *tc =
+ container_of(qcmd, struct tcm_qla_tgt_mgmt_cmd, mgt_cmd);
+
+ return tc;
+}
+
/*
* Parse WWN.
* If strict, we require lower-case hex and colon separators to be sure
@@ -262,7 +306,7 @@ static void tcm_qla2xxx_complete_mcmd(struct work_struct *work)
struct qla_tgt_mgmt_cmd *mcmd = container_of(work,
struct qla_tgt_mgmt_cmd, free_work);
- transport_generic_free_cmd(&mcmd->se_cmd, 0);
+ transport_generic_free_cmd(QMGT_TO_SE_CMD(mcmd), 0);
}
/*
@@ -276,17 +320,37 @@ static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd)
queue_work(tcm_qla2xxx_free_wq, &mcmd->free_work);
}
+static void tcm_qla2xxx_free_mgmt_cmd(struct qla_tgt_mgmt_cmd *qcmd)
+{
+ struct tcm_qla_tgt_mgmt_cmd *mcmd = QMGT_TO_TMGT_CMD(qcmd);
+ mempool_free(mcmd, tcm_qla_tgt_mgmt_cmd_mempool);
+}
+
+static struct qla_tgt_mgmt_cmd *tcm_qla2xxx_alloc_mgmt_cmd(void)
+{
+ struct tcm_qla_tgt_mgmt_cmd *tmcmd = NULL;
+ struct qla_tgt_mgmt_cmd *mcmd = NULL;
+
+ tmcmd = mempool_alloc(tcm_qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC);
+ if (tmcmd) {
+ memset(tmcmd, 0, sizeof(struct tcm_qla_tgt_mgmt_cmd));
+ mcmd = &tmcmd->mgt_cmd;
+ }
+
+ return mcmd;
+}
+
static void tcm_qla2xxx_complete_free(struct work_struct *work)
{
struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
cmd->cmd_in_wq = 0;
- WARN_ON(cmd->cmd_flags & BIT_16);
+ WARN_ON(cmd->trc_flags & TRC_CMD_FREE);
cmd->vha->tgt_counters.qla_core_ret_sta_ctio++;
- cmd->cmd_flags |= BIT_16;
- transport_generic_free_cmd(&cmd->se_cmd, 0);
+ cmd->trc_flags |= TRC_CMD_FREE;
+ transport_generic_free_cmd(Q_TO_SE_CMD(cmd), 0);
}
/*
@@ -299,8 +363,8 @@ static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd)
cmd->vha->tgt_counters.core_qla_free_cmd++;
cmd->cmd_in_wq = 1;
- BUG_ON(cmd->cmd_flags & BIT_20);
- cmd->cmd_flags |= BIT_20;
+ BUG_ON(cmd->trc_flags & TRC_CMD_DONE);
+ cmd->trc_flags |= TRC_CMD_DONE;
INIT_WORK(&cmd->work, tcm_qla2xxx_complete_free);
queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
@@ -314,34 +378,101 @@ static int tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd)
struct qla_tgt_cmd *cmd;
if ((se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) == 0) {
- cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
- cmd->cmd_flags |= BIT_14;
+ cmd = SE_TO_Q_CMD(se_cmd);
+ cmd->trc_flags |= TRC_CMD_CHK_STOP;
}
return target_put_sess_cmd(se_cmd);
}
+static void tcm_qla2xxx_release_session(struct kref *kref)
+{
+ struct fc_port *sess = container_of(kref,
+ struct fc_port, sess_kref);
+
+ qlt_unreg_sess(sess);
+}
+
+static void tcm_qla2xxx_put_sess(struct fc_port *sess)
+{
+ if (!sess)
+ return;
+
+ assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
+ kref_put(&sess->sess_kref, tcm_qla2xxx_release_session);
+}
+
+static void tcm_qla2xxx_get_sess(struct fc_port *sess)
+{
+ if (!sess)
+ return;
+
+ kref_get(&sess->sess_kref);
+}
+
/* tcm_qla2xxx_release_cmd - Callback from TCM Core to release underlying
* fabric descriptor @se_cmd command to release
*/
static void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd)
{
struct qla_tgt_cmd *cmd;
+ struct se_session *se_sess;
if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) {
- struct qla_tgt_mgmt_cmd *mcmd = container_of(se_cmd,
- struct qla_tgt_mgmt_cmd, se_cmd);
- qlt_free_mcmd(mcmd);
+ tcm_qla2xxx_free_mgmt_cmd(SE_TO_QMGT_CMD(se_cmd));
return;
}
- cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
+ cmd = SE_TO_Q_CMD(se_cmd);
qlt_free_cmd(cmd);
+
+ if (!cmd->sess || !cmd->sess->se_sess) {
+ WARN_ON(1);
+ return;
+ }
+
+ se_sess = (struct se_session *)cmd->sess->se_sess;
+
+ cmd->jiffies_at_free = get_jiffies_64();
+ percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
+}
+
+static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd)
+{
+ tcm_qla2xxx_release_cmd(Q_TO_SE_CMD(cmd));
+}
+
+static struct qla_tgt_cmd *tcm_qla2xxx_alloc_cmd(struct fc_port *sess)
+{
+ struct se_session *se_sess = (struct se_session *)sess->se_sess;
+ int tag;
+ struct qla_tgt_cmd *cmd = NULL;
+ struct tcm_qla_tgt_cmd *tc = NULL;
+ struct qla_hw_data *ha = sess->vha->hw;
+
+ tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
+ if (tag < 0)
+ return NULL;
+
+ tc = &((struct tcm_qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
+ if (tc) {
+ memset(tc, 0, sizeof(struct tcm_qla_tgt_cmd));
+ tc->se_cmd.map_tag = tag;
+ tc->se_cmd.cpuid = -1;
+
+ if (ha->msix_count)
+ tc->se_cmd.cpuid = ha->tgt.rspq_vector_cpuid;
+
+ tc->qcmd.ulp_cmd = (void *)&tc->se_cmd;
+ cmd = &tc->qcmd;
+ }
+
+ return cmd;
}
static void tcm_qla2xxx_close_session(struct se_session *se_sess)
{
- struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr;
+ struct fc_port *sess = se_sess->fabric_sess_ptr;
struct scsi_qla_host *vha;
unsigned long flags;
@@ -350,7 +481,7 @@ static void tcm_qla2xxx_close_session(struct se_session *se_sess)
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
target_sess_cmd_list_set_waiting(se_sess);
- qlt_put_sess(sess);
+ tcm_qla2xxx_put_sess(sess);
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
}
@@ -371,13 +502,13 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
*/
pr_debug("write_pending aborted cmd[%p] refcount %d "
"transport_state %x, t_state %x, se_cmd_flags %x\n",
- cmd,cmd->se_cmd.cmd_kref.refcount.counter,
- cmd->se_cmd.transport_state,
- cmd->se_cmd.t_state,
- cmd->se_cmd.se_cmd_flags);
+ cmd, se_cmd->cmd_kref.refcount.counter,
+ se_cmd->transport_state,
+ se_cmd->t_state,
+ se_cmd->se_cmd_flags);
return 0;
}
- cmd->cmd_flags |= BIT_3;
+ cmd->trc_flags |= TRC_XFR_RDY;
cmd->bufflen = se_cmd->data_length;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
@@ -388,6 +519,8 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
cmd->prot_sg = se_cmd->t_prot_sg;
cmd->blk_sz = se_cmd->se_dev->dev_attrib.block_size;
se_cmd->pi_err = 0;
+ cmd->cdb = se_cmd->t_task_cdb;
+ cmd->lba = se_cmd->t_task_lba;
/*
* qla_target.c:qlt_rdy_to_xfer() will call pci_map_sg() to setup
@@ -424,8 +557,7 @@ static void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *nacl)
static int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd)
{
if (!(se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) {
- struct qla_tgt_cmd *cmd = container_of(se_cmd,
- struct qla_tgt_cmd, se_cmd);
+ struct qla_tgt_cmd *cmd = SE_TO_Q_CMD(se_cmd);
return cmd->state;
}
@@ -436,18 +568,43 @@ static int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd)
* Called from process context in qla_target.c:qlt_do_work() code
*/
static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
- unsigned char *cdb, uint32_t data_length, int fcp_task_attr,
+ unsigned char *cdb, uint32_t data_length, uint8_t task_codes,
int data_dir, int bidi)
{
- struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct se_cmd *se_cmd = Q_TO_SE_CMD(cmd);
struct se_session *se_sess;
- struct qla_tgt_sess *sess;
+ struct fc_port *sess;
#ifdef CONFIG_TCM_QLA2XXX_DEBUG
struct se_portal_group *se_tpg;
struct tcm_qla2xxx_tpg *tpg;
#endif
+ int fcp_task_attr;
int flags = TARGET_SCF_ACK_KREF;
+
+ switch (task_codes) {
+ case ATIO_SIMPLE_QUEUE:
+ fcp_task_attr = TCM_SIMPLE_TAG;
+ break;
+ case ATIO_HEAD_OF_QUEUE:
+ fcp_task_attr = TCM_HEAD_TAG;
+ break;
+ case ATIO_ORDERED_QUEUE:
+ fcp_task_attr = TCM_ORDERED_TAG;
+ break;
+ case ATIO_ACA_QUEUE:
+ fcp_task_attr = TCM_ACA_TAG;
+ break;
+ case ATIO_UNTAGGED:
+ fcp_task_attr = TCM_SIMPLE_TAG;
+ break;
+ default:
+ pr_err("qla_target: unknown task code %x, use ORDERED instead\n",
+ task_codes);
+ fcp_task_attr = TCM_ORDERED_TAG;
+ break;
+ }
+
if (bidi)
flags |= TARGET_SCF_BIDI_OP;
@@ -456,10 +613,11 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
sess = cmd->sess;
if (!sess) {
- pr_err("Unable to locate struct qla_tgt_sess from qla_tgt_cmd\n");
+ pr_err("Unable to locate struct fc_port from qla_tgt_cmd\n");
return -EINVAL;
}
+ se_cmd->tag = cmd->atio.u.isp24.exchange_addr;
se_sess = sess->se_sess;
if (!se_sess) {
pr_err("Unable to locate active struct se_session\n");
@@ -485,6 +643,7 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
{
struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
unsigned long flags;
+ struct se_cmd *se_cmd = Q_TO_SE_CMD(cmd);
/*
* Ensure that the complete FCP WRITE payload has been received.
@@ -493,9 +652,9 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
cmd->cmd_in_wq = 0;
spin_lock_irqsave(&cmd->cmd_lock, flags);
- cmd->cmd_flags |= CMD_FLAG_DATA_WORK;
+ cmd->data_work = 1;
if (cmd->aborted) {
- cmd->cmd_flags |= CMD_FLAG_DATA_WORK_FREE;
+ cmd->data_work_free = 1;
spin_unlock_irqrestore(&cmd->cmd_lock, flags);
tcm_qla2xxx_free_cmd(cmd);
@@ -509,22 +668,22 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
* Check if se_cmd has already been aborted via LUN_RESET, and
* waiting upon completion in tcm_qla2xxx_write_pending_status()
*/
- if (cmd->se_cmd.transport_state & CMD_T_ABORTED) {
- complete(&cmd->se_cmd.t_transport_stop_comp);
+ if (se_cmd->transport_state & CMD_T_ABORTED) {
+ complete(&se_cmd->t_transport_stop_comp);
return;
}
- if (cmd->se_cmd.pi_err)
- transport_generic_request_failure(&cmd->se_cmd,
- cmd->se_cmd.pi_err);
+ if (se_cmd->pi_err)
+ transport_generic_request_failure(se_cmd,
+ se_cmd->pi_err);
else
- transport_generic_request_failure(&cmd->se_cmd,
+ transport_generic_request_failure(se_cmd,
TCM_CHECK_CONDITION_ABORT_CMD);
return;
}
- return target_execute_cmd(&cmd->se_cmd);
+ return target_execute_cmd(se_cmd);
}
/*
@@ -532,7 +691,7 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
*/
static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
{
- cmd->cmd_flags |= BIT_10;
+ cmd->trc_flags |= TRC_DATA_IN;
cmd->cmd_in_wq = 1;
INIT_WORK(&cmd->work, tcm_qla2xxx_handle_data_work);
queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
@@ -546,8 +705,8 @@ static void tcm_qla2xxx_handle_dif_work(struct work_struct *work)
* need to wait for SCSI status/check condition to
* finish responding generate by transport_generic_request_failure.
*/
- kref_get(&cmd->se_cmd.cmd_kref);
- transport_generic_request_failure(&cmd->se_cmd, cmd->se_cmd.pi_err);
+ kref_get(&se_cmd->cmd_kref);
+ transport_generic_request_failure(se_cmd, se_cmd->pi_err);
}
/*
@@ -562,20 +721,113 @@ static void tcm_qla2xxx_handle_dif_err(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,
- uint8_t tmr_func, uint32_t tag)
+static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun,
+ uint16_t tmr_func, uint32_t tag)
{
- struct qla_tgt_sess *sess = mcmd->sess;
- struct se_cmd *se_cmd = &mcmd->se_cmd;
+ struct fc_port *sess = mcmd->sess;
+ struct se_cmd *se_cmd = QMGT_TO_SE_CMD(mcmd);
+ struct se_session *se_sess = sess->se_sess;
+ bool found_lun = false;
+ unsigned long flags;
+ int transl_tmr_func;
+
+ switch (tmr_func) {
+ case QLA_TGT_ABTS:
+ 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 = SE_TO_Q_CMD(se_cmd);
+ struct abts_recv_from_24xx *abts = &mcmd->orig_iocb.abts;
+
+ if (se_cmd->tag == abts->exchange_addr_to_abort) {
+ lun = cmd->unpacked_lun;
+ found_lun = true;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+ if (!found_lun)
+ return -ENOBUFS;
+
+ pr_debug("%ld: ABTS received\n",
+ sess->vha->host_no);
+
+ transl_tmr_func = TMR_ABORT_TASK;
+ break;
+
+ case QLA_TGT_2G_ABORT_TASK:
+ pr_debug("%ld: 2G Abort Task received\n",
+ sess->vha->host_no);
+ transl_tmr_func = TMR_ABORT_TASK;
+ break;
+
+ case QLA_TGT_CLEAR_ACA:
+ pr_debug("%ld: CLEAR_ACA received\n",
+ sess->vha->host_no);
+ transl_tmr_func = TMR_CLEAR_ACA;
+ break;
+
+ case QLA_TGT_TARGET_RESET:
+ pr_debug("%ld: TARGET_RESET received\n",
+ sess->vha->host_no);
+ transl_tmr_func = TMR_TARGET_WARM_RESET;
+ break;
+
+ case QLA_TGT_LUN_RESET:
+ pr_debug("%ld: LUN_RESET received\n",
+ sess->vha->host_no);
+ transl_tmr_func = TMR_LUN_RESET;
+ break;
+
+ case QLA_TGT_CLEAR_TS:
+ pr_debug("%ld: CLEAR_TS received\n",
+ sess->vha->host_no);
+ transl_tmr_func = TMR_CLEAR_TASK_SET;
+ break;
+
+ case QLA_TGT_ABORT_TS:
+ pr_debug("%ld: ABORT_TS received\n",
+ sess->vha->host_no);
+ transl_tmr_func = TMR_ABORT_TASK_SET;
+ break;
+#if 0
+ case QLA_TGT_ABORT_ALL:
+ pr_debug("%d: Doing ABORT_ALL_TASKS\n",
+ sess->vha->vp_idx);
+ transl_tmr_func = 0;
+ break;
+
+ case QLA_TGT_ABORT_ALL_SESS:
+ pr_debug("%d: Doing ABORT_ALL_TASKS_SESS\n",
+ sess->vha->vp_idx);
+ transl_tmr_func = 0;
+ break;
+
+ case QLA_TGT_NEXUS_LOSS_SESS:
+ pr_debug("%d: Doing NEXUS_LOSS_SESS\n",
+ sess->vha->vp_idx);
+ transl_tmr_func = 0;
+ break;
+
+ case QLA_TGT_NEXUS_LOSS:
+ pr_debug("%d: Doing NEXUS_LOSS\n", sess->vha->vp_idx);
+ transl_tmr_func = 0;
+ break;
+#endif
+
+ default:
+ pr_debug("%ld: Unknown task mgmt fn 0x%x\n",
+ sess->vha->host_no, tmr_func);
+ return -ENOSYS;
+ break;
+ }
return target_submit_tmr(se_cmd, sess->se_sess, NULL, lun, mcmd,
- tmr_func, GFP_ATOMIC, tag, TARGET_SCF_ACK_KREF);
+ transl_tmr_func, GFP_ATOMIC, tag, TARGET_SCF_ACK_KREF);
}
static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
{
- struct qla_tgt_cmd *cmd = container_of(se_cmd,
- struct qla_tgt_cmd, se_cmd);
+ struct qla_tgt_cmd *cmd = SE_TO_Q_CMD(se_cmd);
if (cmd->aborted) {
/* Cmd can loop during Q-full. tcm_qla2xxx_aborted_task
@@ -584,14 +836,14 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
*/
pr_debug("queue_data_in aborted cmd[%p] refcount %d "
"transport_state %x, t_state %x, se_cmd_flags %x\n",
- cmd,cmd->se_cmd.cmd_kref.refcount.counter,
- cmd->se_cmd.transport_state,
- cmd->se_cmd.t_state,
- cmd->se_cmd.se_cmd_flags);
+ cmd, se_cmd->cmd_kref.refcount.counter,
+ se_cmd->transport_state,
+ se_cmd->t_state,
+ se_cmd->se_cmd_flags);
return 0;
}
- cmd->cmd_flags |= BIT_4;
+ cmd->trc_flags |= TRC_XMIT_DATA;
cmd->bufflen = se_cmd->data_length;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
@@ -603,6 +855,13 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
cmd->prot_sg = se_cmd->t_prot_sg;
cmd->blk_sz = se_cmd->se_dev->dev_attrib.block_size;
se_cmd->pi_err = 0;
+ cmd->cdb = se_cmd->t_task_cdb;
+ cmd->lba = se_cmd->t_task_lba;
+
+ if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT)
+ cmd->residual = -(se_cmd->residual_count);
+ else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT)
+ cmd->residual = se_cmd->residual_count;
/*
* Now queue completed DATA_IN the qla2xxx LLD and response ring
@@ -613,8 +872,8 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
{
- struct qla_tgt_cmd *cmd = container_of(se_cmd,
- struct qla_tgt_cmd, se_cmd);
+ struct qla_tgt_cmd *cmd = SE_TO_Q_CMD(se_cmd);
+
int xmit_type = QLA_TGT_XMIT_STATUS;
cmd->bufflen = se_cmd->data_length;
@@ -622,11 +881,11 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
cmd->sg_cnt = 0;
cmd->offset = 0;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
- if (cmd->cmd_flags & BIT_5) {
- pr_crit("Bit_5 already set for cmd = %p.\n", cmd);
+ if (cmd->trc_flags & TRC_XMIT_STATUS) {
+ pr_crit("Multiple calls for status = %p.\n", cmd);
dump_stack();
}
- cmd->cmd_flags |= BIT_5;
+ cmd->trc_flags |= TRC_XMIT_STATUS;
if (se_cmd->data_direction == DMA_FROM_DEVICE) {
/*
@@ -642,6 +901,12 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
cmd->bufflen = 0;
}
+
+ if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT)
+ cmd->residual = -(se_cmd->residual_count);
+ else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT)
+ cmd->residual = se_cmd->residual_count;
+
/*
* Now queue status response to qla2xxx LLD code and response ring
*/
@@ -651,8 +916,8 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd)
{
struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
- struct qla_tgt_mgmt_cmd *mcmd = container_of(se_cmd,
- struct qla_tgt_mgmt_cmd, se_cmd);
+ struct qla_tgt_mgmt_cmd *mcmd = SE_TO_QMGT_CMD(se_cmd);
+
pr_debug("queue_tm_rsp: mcmd: %p func: 0x%02x response: 0x%02x\n",
mcmd, se_tmr->function, se_tmr->response);
@@ -683,24 +948,22 @@ static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd)
}
-#define DATA_WORK_NOT_FREE(_flags) \
- (( _flags & (CMD_FLAG_DATA_WORK|CMD_FLAG_DATA_WORK_FREE)) == \
- CMD_FLAG_DATA_WORK)
+#define DATA_WORK_NOT_FREE(_cmd) (_cmd->data_work && !_cmd->data_work_free)
+
static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
{
- struct qla_tgt_cmd *cmd = container_of(se_cmd,
- struct qla_tgt_cmd, se_cmd);
+ struct qla_tgt_cmd *cmd = SE_TO_Q_CMD(se_cmd);
unsigned long flags;
if (qlt_abort_cmd(cmd))
return;
spin_lock_irqsave(&cmd->cmd_lock, flags);
- if ((cmd->state == QLA_TGT_STATE_NEW)||
+ if ((cmd->state == QLA_TGT_STATE_NEW) ||
((cmd->state == QLA_TGT_STATE_DATA_IN) &&
- DATA_WORK_NOT_FREE(cmd->cmd_flags)) ) {
+ DATA_WORK_NOT_FREE(cmd))) {
- cmd->cmd_flags |= CMD_FLAG_DATA_WORK_FREE;
+ cmd->data_work_free = 1;
spin_unlock_irqrestore(&cmd->cmd_lock, flags);
/* Cmd have not reached firmware.
* Use this trigger to free it. */
@@ -713,13 +976,14 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
}
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
- struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *);
+ struct tcm_qla2xxx_nacl *, struct fc_port *);
/*
* Expected to be called with struct qla_hw_data->tgt.sess_lock held
*/
-static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess)
+static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct fc_port *sess)
{
- struct se_node_acl *se_nacl = sess->se_sess->se_node_acl;
+ struct se_node_acl *se_nacl =
+ ((struct se_session *)sess->se_sess)->se_node_acl;
struct se_portal_group *se_tpg = se_nacl->se_tpg;
struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
@@ -756,7 +1020,7 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess)
tcm_qla2xxx_clear_sess_lookup(lport, nacl, sess);
}
-static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess)
+static void tcm_qla2xxx_shutdown_sess(struct fc_port *sess)
{
assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
target_sess_cmd_list_set_waiting(sess->se_sess);
@@ -1141,7 +1405,7 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(
/*
* Expected to be called with struct qla_hw_data->tgt.sess_lock held
*/
-static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
+static struct fc_port *tcm_qla2xxx_find_sess_by_s_id(
scsi_qla_host_t *vha,
const uint8_t *s_id)
{
@@ -1169,12 +1433,12 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
se_nacl, se_nacl->initiatorname);
nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl);
- if (!nacl->qla_tgt_sess) {
- pr_err("Unable to locate struct qla_tgt_sess\n");
+ if (!nacl->fc_port) {
+ pr_err("Unable to locate struct fc_port\n");
return NULL;
}
- return nacl->qla_tgt_sess;
+ return nacl->fc_port;
}
/*
@@ -1185,7 +1449,7 @@ static void tcm_qla2xxx_set_sess_by_s_id(
struct se_node_acl *new_se_nacl,
struct tcm_qla2xxx_nacl *nacl,
struct se_session *se_sess,
- struct qla_tgt_sess *qla_tgt_sess,
+ struct fc_port *fc_port,
uint8_t *s_id)
{
u32 key;
@@ -1209,22 +1473,22 @@ static void tcm_qla2xxx_set_sess_by_s_id(
pr_debug("Wiping nonexisting fc_port entry\n");
}
- qla_tgt_sess->se_sess = se_sess;
- nacl->qla_tgt_sess = qla_tgt_sess;
+ fc_port->se_sess = se_sess;
+ nacl->fc_port = fc_port;
return;
}
- if (nacl->qla_tgt_sess) {
+ if (nacl->fc_port) {
if (new_se_nacl == NULL) {
- pr_debug("Clearing existing nacl->qla_tgt_sess and fc_port entry\n");
+ pr_debug("Clearing existing nacl->fc_port and fc_port entry\n");
btree_remove32(&lport->lport_fcport_map, key);
- nacl->qla_tgt_sess = NULL;
+ nacl->fc_port = NULL;
return;
}
- pr_debug("Replacing existing nacl->qla_tgt_sess and fc_port entry\n");
+ pr_debug("Replacing existing nacl->fc_port and fc_port entry\n");
btree_update32(&lport->lport_fcport_map, key, new_se_nacl);
- qla_tgt_sess->se_sess = se_sess;
- nacl->qla_tgt_sess = qla_tgt_sess;
+ fc_port->se_sess = se_sess;
+ nacl->fc_port = fc_port;
return;
}
@@ -1234,19 +1498,19 @@ static void tcm_qla2xxx_set_sess_by_s_id(
return;
}
- pr_debug("Replacing existing fc_port entry w/o active nacl->qla_tgt_sess\n");
+ pr_debug("Replacing existing fc_port entry w/o active nacl->fc_port\n");
btree_update32(&lport->lport_fcport_map, key, new_se_nacl);
- qla_tgt_sess->se_sess = se_sess;
- nacl->qla_tgt_sess = qla_tgt_sess;
+ fc_port->se_sess = se_sess;
+ nacl->fc_port = fc_port;
- pr_debug("Setup nacl->qla_tgt_sess %p by s_id for se_nacl: %p, initiatorname: %s\n",
- nacl->qla_tgt_sess, new_se_nacl, new_se_nacl->initiatorname);
+ pr_debug("Setup nacl->fc_port %p by s_id for se_nacl: %p, initiatorname: %s\n",
+ nacl->fc_port, new_se_nacl, new_se_nacl->initiatorname);
}
/*
* Expected to be called with struct qla_hw_data->tgt.sess_lock held
*/
-static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id(
+static struct fc_port *tcm_qla2xxx_find_sess_by_loop_id(
scsi_qla_host_t *vha,
const uint16_t loop_id)
{
@@ -1274,12 +1538,12 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id(
nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl);
- if (!nacl->qla_tgt_sess) {
- pr_err("Unable to locate struct qla_tgt_sess\n");
+ if (!nacl->fc_port) {
+ pr_err("Unable to locate struct fc_port\n");
return NULL;
}
- return nacl->qla_tgt_sess;
+ return nacl->fc_port;
}
/*
@@ -1290,7 +1554,7 @@ static void tcm_qla2xxx_set_sess_by_loop_id(
struct se_node_acl *new_se_nacl,
struct tcm_qla2xxx_nacl *nacl,
struct se_session *se_sess,
- struct qla_tgt_sess *qla_tgt_sess,
+ struct fc_port *fc_port,
uint16_t loop_id)
{
struct se_node_acl *saved_nacl;
@@ -1305,27 +1569,27 @@ static void tcm_qla2xxx_set_sess_by_loop_id(
if (!saved_nacl) {
pr_debug("Setting up new fc_loopid->se_nacl to new_se_nacl\n");
fc_loopid->se_nacl = new_se_nacl;
- if (qla_tgt_sess->se_sess != se_sess)
- qla_tgt_sess->se_sess = se_sess;
- if (nacl->qla_tgt_sess != qla_tgt_sess)
- nacl->qla_tgt_sess = qla_tgt_sess;
+ if (fc_port->se_sess != se_sess)
+ fc_port->se_sess = se_sess;
+ if (nacl->fc_port != fc_port)
+ nacl->fc_port = fc_port;
return;
}
- if (nacl->qla_tgt_sess) {
+ if (nacl->fc_port) {
if (new_se_nacl == NULL) {
- pr_debug("Clearing nacl->qla_tgt_sess and fc_loopid->se_nacl\n");
+ pr_debug("Clearing nacl->fc_port and fc_loopid->se_nacl\n");
fc_loopid->se_nacl = NULL;
- nacl->qla_tgt_sess = NULL;
+ nacl->fc_port = NULL;
return;
}
- pr_debug("Replacing existing nacl->qla_tgt_sess and fc_loopid->se_nacl\n");
+ pr_debug("Replacing existing nacl->fc_port and fc_loopid->se_nacl\n");
fc_loopid->se_nacl = new_se_nacl;
- if (qla_tgt_sess->se_sess != se_sess)
- qla_tgt_sess->se_sess = se_sess;
- if (nacl->qla_tgt_sess != qla_tgt_sess)
- nacl->qla_tgt_sess = qla_tgt_sess;
+ if (fc_port->se_sess != se_sess)
+ fc_port->se_sess = se_sess;
+ if (nacl->fc_port != fc_port)
+ nacl->fc_port = fc_port;
return;
}
@@ -1335,29 +1599,29 @@ static void tcm_qla2xxx_set_sess_by_loop_id(
return;
}
- pr_debug("Replacing existing fc_loopid->se_nacl w/o active nacl->qla_tgt_sess\n");
+ pr_debug("Replacing existing fc_loopid->se_nacl w/o active nacl->fc_port\n");
fc_loopid->se_nacl = new_se_nacl;
- if (qla_tgt_sess->se_sess != se_sess)
- qla_tgt_sess->se_sess = se_sess;
- if (nacl->qla_tgt_sess != qla_tgt_sess)
- nacl->qla_tgt_sess = qla_tgt_sess;
+ if (fc_port->se_sess != se_sess)
+ fc_port->se_sess = se_sess;
+ if (nacl->fc_port != fc_port)
+ nacl->fc_port = fc_port;
- pr_debug("Setup nacl->qla_tgt_sess %p by loop_id for se_nacl: %p, initiatorname: %s\n",
- nacl->qla_tgt_sess, new_se_nacl, new_se_nacl->initiatorname);
+ pr_debug("Setup nacl->fc_port %p by loop_id for se_nacl: %p, initiatorname: %s\n",
+ nacl->fc_port, new_se_nacl, new_se_nacl->initiatorname);
}
/*
* Should always be called with qla_hw_data->tgt.sess_lock held.
*/
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport,
- struct tcm_qla2xxx_nacl *nacl, struct qla_tgt_sess *sess)
+ struct tcm_qla2xxx_nacl *nacl, struct fc_port *sess)
{
struct se_session *se_sess = sess->se_sess;
unsigned char be_sid[3];
- be_sid[0] = sess->s_id.b.domain;
- be_sid[1] = sess->s_id.b.area;
- be_sid[2] = sess->s_id.b.al_pa;
+ be_sid[0] = sess->d_id.b.domain;
+ be_sid[1] = sess->d_id.b.area;
+ be_sid[2] = sess->d_id.b.al_pa;
tcm_qla2xxx_set_sess_by_s_id(lport, NULL, nacl, se_sess,
sess, be_sid);
@@ -1365,7 +1629,7 @@ static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport,
sess, sess->loop_id);
}
-static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess)
+static void tcm_qla2xxx_free_session(struct fc_port *sess)
{
struct qla_tgt *tgt = sess->tgt;
struct qla_hw_data *ha = tgt->ha;
@@ -1377,7 +1641,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess)
se_sess = sess->se_sess;
if (!se_sess) {
- pr_err("struct qla_tgt_sess->se_sess is NULL\n");
+ pr_err("struct fc_port->se_sess is NULL\n");
dump_stack();
return;
}
@@ -1404,14 +1668,14 @@ static int tcm_qla2xxx_session_cb(struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl = se_sess->se_node_acl;
struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
struct tcm_qla2xxx_nacl, se_node_acl);
- struct qla_tgt_sess *qlat_sess = p;
+ struct fc_port *qlat_sess = p;
uint16_t loop_id = qlat_sess->loop_id;
unsigned long flags;
unsigned char be_sid[3];
- be_sid[0] = qlat_sess->s_id.b.domain;
- be_sid[1] = qlat_sess->s_id.b.area;
- be_sid[2] = qlat_sess->s_id.b.al_pa;
+ be_sid[0] = qlat_sess->d_id.b.domain;
+ be_sid[1] = qlat_sess->d_id.b.area;
+ be_sid[2] = qlat_sess->d_id.b.al_pa;
/*
* And now setup se_nacl and session pointers into HW lport internal
@@ -1434,7 +1698,7 @@ static int tcm_qla2xxx_session_cb(struct se_portal_group *se_tpg,
static int tcm_qla2xxx_check_initiator_node_acl(
scsi_qla_host_t *vha,
unsigned char *fc_wwpn,
- struct qla_tgt_sess *qlat_sess)
+ struct fc_port *qlat_sess)
{
struct qla_hw_data *ha = vha->hw;
struct tcm_qla2xxx_lport *lport;
@@ -1469,33 +1733,34 @@ static int tcm_qla2xxx_check_initiator_node_acl(
* via ConfigFS, or via running in TPG demo mode.
*/
se_sess = target_alloc_session(&tpg->se_tpg, num_tags,
- sizeof(struct qla_tgt_cmd),
- TARGET_PROT_ALL, port_name,
- qlat_sess, tcm_qla2xxx_session_cb);
+ sizeof(struct tcm_qla_tgt_cmd), TARGET_PROT_ALL, port_name,
+ qlat_sess, tcm_qla2xxx_session_cb);
+
if (IS_ERR(se_sess))
return PTR_ERR(se_sess);
return 0;
}
-static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
+static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id,
uint16_t loop_id, bool conf_compl_supported)
{
struct qla_tgt *tgt = sess->tgt;
struct qla_hw_data *ha = tgt->ha;
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
struct tcm_qla2xxx_lport *lport = vha->vha_tgt.target_lport_ptr;
- struct se_node_acl *se_nacl = sess->se_sess->se_node_acl;
+ struct se_node_acl *se_nacl =
+ ((struct se_session *)sess->se_sess)->se_node_acl;
struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
struct tcm_qla2xxx_nacl, se_node_acl);
u32 key;
- if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24)
+ if (sess->loop_id != loop_id || sess->d_id.b24 != s_id.b24)
pr_info("Updating session %p from port %8phC loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n",
sess, sess->port_name,
- sess->loop_id, loop_id, sess->s_id.b.domain,
- sess->s_id.b.area, sess->s_id.b.al_pa, s_id.b.domain,
+ sess->loop_id, loop_id, sess->d_id.b.domain,
+ sess->d_id.b.area, sess->d_id.b.al_pa, s_id.b.domain,
s_id.b.area, s_id.b.al_pa);
if (sess->loop_id != loop_id) {
@@ -1515,18 +1780,18 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
sess->loop_id = loop_id;
}
- if (sess->s_id.b24 != s_id.b24) {
- key = (((u32) sess->s_id.b.domain << 16) |
- ((u32) sess->s_id.b.area << 8) |
- ((u32) sess->s_id.b.al_pa));
+ if (sess->d_id.b24 != s_id.b24) {
+ key = (((u32) sess->d_id.b.domain << 16) |
+ ((u32) sess->d_id.b.area << 8) |
+ ((u32) sess->d_id.b.al_pa));
if (btree_lookup32(&lport->lport_fcport_map, key))
WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl,
"Found wrong se_nacl when updating s_id %x:%x:%x\n",
- sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+ sess->d_id.b.domain, sess->d_id.b.area, sess->d_id.b.al_pa);
else
WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n",
- sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+ sess->d_id.b.domain, sess->d_id.b.area, sess->d_id.b.al_pa);
key = (((u32) s_id.b.domain << 16) |
((u32) s_id.b.area << 8) |
@@ -1540,7 +1805,7 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC);
}
- sess->s_id = s_id;
+ sess->d_id = s_id;
nacl->nport_id = key;
}
@@ -1551,6 +1816,28 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
sess->keep_nport_handle = 0;
}
+static void tcm_qla2xxx_srr_get_cur_state(struct qla_tgt_cmd *cmd,
+ srr_state_op_t op)
+{
+ struct se_cmd *se_cmd = Q_TO_SE_CMD(cmd);
+
+ switch (op) {
+ case SRR_SG:
+ cmd->sg_cnt = se_cmd->t_data_nents;
+ cmd->sg = se_cmd->t_data_sg;
+ break;
+
+ case SRR_STATUS:
+ cmd->scsi_status = se_cmd->scsi_status;
+ cmd->bufflen = se_cmd->data_length;
+ break;
+
+ default:
+ BUG_ON(1);
+ break;
+ }
+}
+
/*
* Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
*/
@@ -1561,13 +1848,19 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
.handle_tmr = tcm_qla2xxx_handle_tmr,
.free_cmd = tcm_qla2xxx_free_cmd,
.free_mcmd = tcm_qla2xxx_free_mcmd,
+ .free_mgmt_cmd = tcm_qla2xxx_free_mgmt_cmd,
.free_session = tcm_qla2xxx_free_session,
.update_sess = tcm_qla2xxx_update_sess,
+ .get_sess = tcm_qla2xxx_get_sess,
.check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,
.find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id,
.find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id,
.clear_nacl_from_fcport_map = tcm_qla2xxx_clear_nacl_from_fcport_map,
.shutdown_sess = tcm_qla2xxx_shutdown_sess,
+ .release_cmd = tcm_qla2xxx_rel_cmd,
+ .alloc_cmd = tcm_qla2xxx_alloc_cmd,
+ .alloc_mgmt_cmd = tcm_qla2xxx_alloc_mgmt_cmd,
+ .srr_get_cur_state = tcm_qla2xxx_srr_get_cur_state,
};
static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport)
@@ -1930,8 +2223,29 @@ static int tcm_qla2xxx_register_configfs(void)
goto out_free_wq;
}
+ tcm_qla_tgt_mgmt_cmd_cachep = kmem_cache_create("tcm_qla_tgt_mgmt_cmd_cachep",
+ sizeof(struct tcm_qla_tgt_mgmt_cmd),
+ __alignof__(struct tcm_qla_tgt_mgmt_cmd), 0, NULL);
+ if (!tcm_qla_tgt_mgmt_cmd_cachep) {
+ pr_debug("kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n");
+ ret = -ENOMEM;
+ goto out_free_cmd_wq;
+ }
+
+ tcm_qla_tgt_mgmt_cmd_mempool = mempool_create(25, mempool_alloc_slab,
+ mempool_free_slab, tcm_qla_tgt_mgmt_cmd_cachep);
+ if (!tcm_qla_tgt_mgmt_cmd_mempool) {
+ pr_debug("mempool_create for tcm_qla_tgt_mgmt_cmd_mempool failed\n");
+ ret = -ENOMEM;
+ goto out_free_cmd_cachep;
+ }
+
return 0;
+out_free_cmd_cachep:
+ kmem_cache_destroy(tcm_qla_tgt_mgmt_cmd_cachep);
+out_free_cmd_wq:
+ destroy_workqueue(tcm_qla2xxx_cmd_wq);
out_free_wq:
destroy_workqueue(tcm_qla2xxx_free_wq);
out_fabric_npiv:
@@ -1943,6 +2257,8 @@ static int tcm_qla2xxx_register_configfs(void)
static void tcm_qla2xxx_deregister_configfs(void)
{
+ mempool_destroy(tcm_qla_tgt_mgmt_cmd_mempool);
+ kmem_cache_destroy(tcm_qla_tgt_mgmt_cmd_cachep);
destroy_workqueue(tcm_qla2xxx_cmd_wq);
destroy_workqueue(tcm_qla2xxx_free_wq);
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h
index 37e9f57..911c3d9 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h
@@ -21,8 +21,8 @@ struct tcm_qla2xxx_nacl {
u64 nport_wwnn;
/* ASCII formatted WWPN for FC Initiator Nport */
char nport_name[TCM_QLA2XXX_NAMELEN];
- /* Pointer to qla_tgt_sess */
- struct qla_tgt_sess *qla_tgt_sess;
+ /* Pointer to fc_port */
+ struct fc_port *fc_port;
/* Pointer to TCM FC nexus */
struct se_session *nport_nexus;
};
@@ -81,3 +81,13 @@ struct tcm_qla2xxx_lport {
/* Returned by tcm_qla2xxx_make_lport() */
struct se_wwn lport_wwn;
};
+
+struct tcm_qla_tgt_cmd {
+ struct se_cmd se_cmd;
+ struct qla_tgt_cmd qcmd;
+};
+
+struct tcm_qla_tgt_mgmt_cmd {
+ struct se_cmd se_cmd;
+ struct qla_tgt_mgmt_cmd mgt_cmd;
+};
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 08/22] qla2xxx: Refactore target code to remove symbol dependency
2016-12-06 20:30 ` [PATCH 08/22] qla2xxx: Refactore target code to remove symbol dependency Himanshu Madhani
@ 2016-12-14 21:18 ` Christoph Hellwig
2016-12-15 19:29 ` Madhani, Himanshu
0 siblings, 1 reply; 50+ messages in thread
From: Christoph Hellwig @ 2016-12-14 21:18 UTC (permalink / raw)
To: Himanshu Madhani; +Cc: target-devel, nab, giridhar.malavali, linux-scsi
- the new qla2x00_free_fcport is entirely pointless, please drop
that part of the patch (and even if it wasn't pointless it should
have been a patch on it's own)
- please use struct names and not typedefs for your new structures
- pretty much avery single items in your list should be a separate
patch. And some of them are actively counterproductive and should
be dropped:
- Remove direct access of scsi_status field in se_cmd
- Remove se_cmd from qlt_do_ctio_completion
- Remove se_cmd access in srr code section
- Move se_cmd struct outside of qla_tgt_cmd/qla_tgt_mgmt_cmd.
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 08/22] qla2xxx: Refactore target code to remove symbol dependency
2016-12-14 21:18 ` Christoph Hellwig
@ 2016-12-15 19:29 ` Madhani, Himanshu
2016-12-15 20:50 ` Tran, Quinn
0 siblings, 1 reply; 50+ messages in thread
From: Madhani, Himanshu @ 2016-12-15 19:29 UTC (permalink / raw)
To: Christoph Hellwig
Cc: target-devel@vger.kernel.org, nab@linux-iscsi.org,
Malavali, Giridhar, linux-scsi@vger.kernel.org
Hi Christoph,
On 12/14/16, 1:18 PM, "Christoph Hellwig" <hch@infradead.org> wrote:
> - the new qla2x00_free_fcport is entirely pointless, please drop
> that part of the patch (and even if it wasn't pointless it should
> have been a patch on it's own)
> - please use struct names and not typedefs for your new structures
> - pretty much avery single items in your list should be a separate
> patch. And some of them are actively counterproductive and should
> be dropped:
>
> - Remove direct access of scsi_status field in se_cmd
> - Remove se_cmd from qlt_do_ctio_completion
> - Remove se_cmd access in srr code section
> - Move se_cmd struct outside of qla_tgt_cmd/qla_tgt_mgmt_cmd.
We combined the patches which includes fixes, enhancements and cleanups to
Support multiple target stacks, reviews from customer, and to improve code
maintainability. This patch tries to organize code logically which is spread
across qla_target and tcm_qla2xxx. We will split this patch into multiple
subset and resubmit the series.
Thanks,
- Himanshu
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 08/22] qla2xxx: Refactore target code to remove symbol dependency
2016-12-15 19:29 ` Madhani, Himanshu
@ 2016-12-15 20:50 ` Tran, Quinn
2016-12-16 8:17 ` Christoph Hellwig
2016-12-16 8:49 ` Bart Van Assche
0 siblings, 2 replies; 50+ messages in thread
From: Tran, Quinn @ 2016-12-15 20:50 UTC (permalink / raw)
To: Madhani, Himanshu, Christoph Hellwig
Cc: target-devel@vger.kernel.org, nab@linux-iscsi.org,
Malavali, Giridhar, linux-scsi@vger.kernel.org
Christoph,
Qlogic was asked to support other Target Stack (SC ST) using the same qla2xxx.ko upstream driver. I had mentioned this during the last 2015 LSF get together. Hopefully, that gives a better context. The understanding that came away was “Qlogic do what is needed to provide this support without creating any dead code”.
As for the cleanup patch(es), we fail to mention that conversation. The patch attempts to remove any knowledge of TCM’s specific symbol and try to formalize the interface. Qla2xxx driver will behave in a more generic manner when it comes to Target Mode. All TCM knowledge will be confined to the tcm_qla2xxx driver before communicating with QLA driver. The same goes for other target stack.
The patches look like its copying a lot of fields without doing a whole lot, instead the patches are translating the request from tcm_qla2xxx to qla2xxx.
As for T10-PI change in this series, the goal were the same : 1) remove TCM knowledge/cleanup, 2) additional bug fixes were needed while testing with other stacks.
Regards,
Quinn Tran
-----Original Message-----
From: <linux-scsi-owner@vger.kernel.org> on behalf of "Madhani, Himanshu" <Himanshu.Madhani@cavium.com>
Date: Thursday, December 15, 2016 at 11:29 AM
To: Christoph Hellwig <hch@infradead.org>
Cc: target-devel <target-devel@vger.kernel.org>, Nicholas Bellinger <nab@linux-iscsi.org>, "Malavali, Giridhar" <Giridhar.Malavali@cavium.com>, "linux-scsi@vger.kernel.org" <linux-scsi@vger.kernel.org>
Subject: Re: [PATCH 08/22] qla2xxx: Refactore target code to remove symbol dependency
Resent-From: <quinn.tran@qlogic.com>
Hi Christoph,
On 12/14/16, 1:18 PM, "Christoph Hellwig" <hch@infradead.org> wrote:
> - the new qla2x00_free_fcport is entirely pointless, please drop
> that part of the patch (and even if it wasn't pointless it should
> have been a patch on it's own)
> - please use struct names and not typedefs for your new structures
> - pretty much avery single items in your list should be a separate
> patch. And some of them are actively counterproductive and should
> be dropped:
>
> - Remove direct access of scsi_status field in se_cmd
> - Remove se_cmd from qlt_do_ctio_completion
> - Remove se_cmd access in srr code section
> - Move se_cmd struct outside of qla_tgt_cmd/qla_tgt_mgmt_cmd.
We combined the patches which includes fixes, enhancements and cleanups to
Support multiple target stacks, reviews from customer, and to improve code
maintainability. This patch tries to organize code logically which is spread
across qla_target and tcm_qla2xxx. We will split this patch into multiple
subset and resubmit the series.
Thanks,
- Himanshu
>
?�{.n�+�������+%��lzwm��b�맲��r��zX��??�(��?��ܨ}���Ơz�&j:+v���?����zZ+��+zf���h���~����i���z�?�w���?����&�)ߢ?f
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 08/22] qla2xxx: Refactore target code to remove symbol dependency
2016-12-15 20:50 ` Tran, Quinn
@ 2016-12-16 8:17 ` Christoph Hellwig
2016-12-16 8:49 ` Bart Van Assche
1 sibling, 0 replies; 50+ messages in thread
From: Christoph Hellwig @ 2016-12-16 8:17 UTC (permalink / raw)
To: Tran, Quinn
Cc: Madhani, Himanshu, Christoph Hellwig,
target-devel@vger.kernel.org, nab@linux-iscsi.org,
Malavali, Giridhar, linux-scsi@vger.kernel.org
On Thu, Dec 15, 2016 at 08:50:39PM +0000, Tran, Quinn wrote:
> Christoph,
>
> Qlogic was asked to support other Target Stack (SC ST) using the same qla2xxx.ko upstream driver. I had mentioned this during the last 2015 LSF get together. Hopefully, that gives a better context. The understanding that came away was “Qlogic do what is needed to provide this support without creating any dead code”.
Right. And what you're doing here is to create tons of pointless and
dead code. If you can support something else without clearly making the
in-kernel version worse it's all fine. This patch on the other hand is
complete crap and totally unacceptable in this form.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 08/22] qla2xxx: Refactore target code to remove symbol dependency
2016-12-15 20:50 ` Tran, Quinn
2016-12-16 8:17 ` Christoph Hellwig
@ 2016-12-16 8:49 ` Bart Van Assche
1 sibling, 0 replies; 50+ messages in thread
From: Bart Van Assche @ 2016-12-16 8:49 UTC (permalink / raw)
To: Tran, Quinn, Madhani, Himanshu, Christoph Hellwig
Cc: target-devel@vger.kernel.org, nab@linux-iscsi.org,
Malavali, Giridhar, linux-scsi@vger.kernel.org
On 12/15/2016 09:50 PM, Tran, Quinn wrote:
> Qlogic was asked to support other Target Stack (SCST) using the same
> qla2xxx.ko upstream driver. I had mentioned this during the last 2015
> LSF get together. Hopefully, that gives a better context. The
> understanding that came away was “Qlogic do what is needed to provide
> this support without creating any dead code”.
>
> [ ... ]
>
> The patches look like its copying a lot of fields without doing a whole
> lot, instead the patches are translating the request from tcm_qla2xxx to
> qla2xxx.
Hello Quinn,
Are you perhaps referring to the 2015 LSF/MM session I had proposed
([LSF/MM TOPIC] Unifying the LIO and SCST target drivers -
https://marc.info/?l=linux-scsi&m=142122995413575)? The approach taken
in patch 08/22 of this series is not what I had in mind. More in
general, as you maybe know shim (translation) layers are not welcome in
the Linux kernel.
Simplifying the LIO core is still on my to do list. A possible starting
point is the patch series I posted one year ago ([PATCH 00/20] SCSI
target patches for kernel v4.4 -
https://www.spinics.net/lists/target-devel/msg10788.html). That kind of
simplification helps with reducing the maintenance burden for target
drivers that support the two in-kernel SCSI target stacks without
violating any of the established rules for kernel driver development.
Bart.
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 09/22] qla2xxx: Refactor T10-DIF PI support
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (7 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 08/22] qla2xxx: Refactore target code to remove symbol dependency Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-14 21:03 ` Christoph Hellwig
2016-12-06 20:30 ` [PATCH 10/22] qla2xxx: Add framework for Async fabric discovery Himanshu Madhani
` (13 subsequent siblings)
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
qla2xxx currently access T10-DIF protection opcode and type
field in se_cmd struct. Add translation code so qla2xxx driver
would not acces private TCM data structure.
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Anil Gurumurthy <anil.gurumurthy@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_dbg.h | 1 +
drivers/scsi/qla2xxx/qla_def.h | 23 ++
drivers/scsi/qla2xxx/qla_dfs.c | 15 +
drivers/scsi/qla2xxx/qla_gbl.h | 6 +-
drivers/scsi/qla2xxx/qla_init.c | 3 +
drivers/scsi/qla2xxx/qla_inline.h | 17 +
drivers/scsi/qla2xxx/qla_iocb.c | 17 +-
drivers/scsi/qla2xxx/qla_isr.c | 3 +
drivers/scsi/qla2xxx/qla_target.c | 613 ++++++++++++++++++++++++-------------
drivers/scsi/qla2xxx/qla_target.h | 47 ++-
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 158 ++++++++--
11 files changed, 661 insertions(+), 242 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index e1fc4e6..c6bffe9 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -348,6 +348,7 @@ void __attribute__((format (printf, 4, 5)))
#define ql_dbg_tgt 0x00004000 /* Target mode */
#define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */
#define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */
+#define ql_dbg_tgt_dif 0x00000800 /* Target mode dif */
extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *,
uint32_t, void **);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 07cda5a..8cee332 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2859,6 +2859,16 @@ struct qla_chip_state_84xx {
uint32_t gold_fw_version;
};
+struct qla_dif_statistics {
+ uint64_t dif_input_bytes;
+ uint64_t dif_output_bytes;
+ uint64_t dif_input_requests;
+ uint64_t dif_output_requests;
+ uint32_t dif_guard_err;
+ uint32_t dif_ref_tag_err;
+ uint32_t dif_app_tag_err;
+};
+
struct qla_statistics {
uint32_t total_isp_aborts;
uint64_t input_bytes;
@@ -2871,6 +2881,7 @@ struct qla_statistics {
uint32_t stat_max_pend_cmds;
uint32_t stat_max_qfull_cmds_alloc;
uint32_t stat_max_qfull_cmds_dropped;
+ struct qla_dif_statistics qla_dif_stats;
};
struct bidi_statistics {
@@ -2878,6 +2889,17 @@ struct bidi_statistics {
unsigned long long transfer_bytes;
};
+/* DIF */
+struct qla_tc_param {
+ struct scsi_qla_host *vha;
+ uint32_t blk_sz;
+ uint32_t bufflen;
+ struct scatterlist *sg;
+ struct scatterlist *prot_sg;
+ struct crc_context *ctx;
+ uint8_t *ctx_dsd_alloced;
+};
+
/* Multi queue support */
#define MBC_INITIALIZE_MULTIQ 0x1f
#define QLA_QUE_PAGE 0X1000
@@ -3007,6 +3029,7 @@ struct qlt_hw_data {
uint16_t atio_q_length;
uint32_t __iomem *atio_q_in;
uint32_t __iomem *atio_q_out;
+ uint64_t atio_ring_end_addr;
struct qla_tgt_func_tmpl *tgt_ops;
struct qla_tgt_cmd *cmds[DEFAULT_OUTSTANDING_COMMANDS];
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 6aa24ee..f69ff52 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -151,6 +151,21 @@
seq_printf(s, "num Q full sent = %lld\n",
vha->tgt_counters.num_q_full_sent);
+/* DIF stats */
+ seq_printf(s, "DIF Inp Bytes = %lld\n",
+ vha->qla_stats.qla_dif_stats.dif_input_bytes);
+ seq_printf(s, "DIF Outp Bytes = %lld\n",
+ vha->qla_stats.qla_dif_stats.dif_output_bytes);
+ seq_printf(s, "DIF Inp Req = %lld\n",
+ vha->qla_stats.qla_dif_stats.dif_input_requests);
+ seq_printf(s, "DIF Outp Req = %lld\n",
+ vha->qla_stats.qla_dif_stats.dif_output_requests);
+ seq_printf(s, "DIF Guard err = %d\n",
+ vha->qla_stats.qla_dif_stats.dif_guard_err);
+ seq_printf(s, "DIF Ref tag err = %d\n",
+ vha->qla_stats.qla_dif_stats.dif_ref_tag_err);
+ seq_printf(s, "DIF App tag err = %d\n",
+ vha->qla_stats.qla_dif_stats.dif_app_tag_err);
return 0;
}
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 13c4d51..9303dbe 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -243,11 +243,11 @@ int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *,
extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, 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_tgt_cmd *);
+ uint32_t *, uint16_t, struct qla_tc_param *);
extern int qla24xx_walk_and_build_sglist(struct qla_hw_data *, srb_t *,
- uint32_t *, uint16_t, struct qla_tgt_cmd *);
+ uint32_t *, uint16_t, struct qla_tc_param *);
extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *,
- uint32_t *, uint16_t, struct qla_tgt_cmd *);
+ uint32_t *, uint16_t, struct qla_tc_param *);
extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index f3ea6b6..30c840d 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2260,6 +2260,9 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
ha->tgt.atio_ring_ptr = ha->tgt.atio_ring;
ha->tgt.atio_ring_index = 0;
+ ha->tgt.atio_ring_end_addr = (uint64_t)(ha->tgt.atio_ring +
+ (ha->tgt.atio_q_length - 1));
+
/* Initialize ATIO queue entries */
qlt_init_atio_q_entries(vha);
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 44e4045..5382b03 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -319,3 +319,20 @@
fcport->retry_delay_timestamp = jiffies +
(retry_delay * HZ / 10);
}
+
+static inline uint8_t *qla_atio_look_ahead(struct qlt_hw_data *ha_tgt,
+ struct atio *cur_atio, int index)
+{
+ struct atio *npkt = NULL;
+ int i;
+
+ /* index=1 : get the next IOCB. index=2: get 2nd iocb from cur_atio */
+ npkt = cur_atio;
+ for (i = 1; i <= index; i++) {
+ npkt++;
+ if ((uint64_t)npkt > ha_tgt->atio_ring_end_addr)
+ npkt = ha_tgt->atio_ring;
+ }
+
+ return (uint8_t *)npkt;
+}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 61f4d21..2bb65c6 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -889,7 +889,7 @@ struct fw_dif_context {
int
qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
- uint32_t *dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc)
+ uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
{
void *next_dsd;
uint8_t avail_dsds = 0;
@@ -966,7 +966,7 @@ struct fw_dif_context {
} else {
list_add_tail(&dsd_ptr->list,
&(tc->ctx->dsd_list));
- tc->ctx_dsd_alloced = 1;
+ *tc->ctx_dsd_alloced = 1;
}
@@ -1005,7 +1005,7 @@ struct fw_dif_context {
int
qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
- uint16_t tot_dsds, struct qla_tgt_cmd *tc)
+ uint16_t tot_dsds, struct qla_tc_param *tc)
{
void *next_dsd;
uint8_t avail_dsds = 0;
@@ -1066,7 +1066,7 @@ struct fw_dif_context {
} else {
list_add_tail(&dsd_ptr->list,
&(tc->ctx->dsd_list));
- tc->ctx_dsd_alloced = 1;
+ *tc->ctx_dsd_alloced = 1;
}
/* add new list to cmd iocb or last list */
@@ -1092,7 +1092,7 @@ struct fw_dif_context {
int
qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
- uint32_t *dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc)
+ uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
{
void *next_dsd;
uint8_t avail_dsds = 0;
@@ -1158,7 +1158,7 @@ struct fw_dif_context {
} else {
list_add_tail(&dsd_ptr->list,
&(tc->ctx->dsd_list));
- tc->ctx_dsd_alloced = 1;
+ *tc->ctx_dsd_alloced = 1;
}
/* add new list to cmd iocb or last list */
@@ -1231,9 +1231,14 @@ struct fw_dif_context {
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
cmd_pkt->control_flags =
cpu_to_le16(CF_WRITE_DATA);
+ vha->qla_stats.qla_dif_stats.dif_output_bytes += scsi_bufflen(cmd);
+ vha->qla_stats.qla_dif_stats.dif_output_requests++;
+
} else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
cmd_pkt->control_flags =
cpu_to_le16(CF_READ_DATA);
+ vha->qla_stats.qla_dif_stats.dif_input_bytes += scsi_bufflen(cmd);
+ vha->qla_stats.qla_dif_stats.dif_input_requests++;
}
if ((scsi_get_prot_op(cmd) == SCSI_PROT_READ_INSERT) ||
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 5fd3b07..ccdb890 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1872,6 +1872,7 @@ struct scsi_dif_tuple {
set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
+ vha->qla_stats.qla_dif_stats.dif_guard_err++;
return 1;
}
@@ -1882,6 +1883,7 @@ struct scsi_dif_tuple {
set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
+ vha->qla_stats.qla_dif_stats.dif_ref_tag_err++;
return 1;
}
@@ -1892,6 +1894,7 @@ struct scsi_dif_tuple {
set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
+ vha->qla_stats.qla_dif_stats.dif_app_tag_err++;
return 1;
}
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index cf4f86d..8c42ff4 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -36,8 +36,6 @@
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
-#include <target/target_core_base.h>
-#include <target/target_core_fabric.h>
#include "qla_def.h"
#include "qla_target.h"
@@ -129,6 +127,28 @@ static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
LIST_HEAD(qla_tgt_glist);
EXPORT_SYMBOL(qla_tgt_glist);
+static const char *prot_op_str(u32 prot_op)
+{
+ switch (prot_op) {
+ case QLA_PROT_NORMAL:
+ return "NORMAL";
+ case QLA_PROT_DIN_INSERT:
+ return "DIN_INSERT";
+ case QLA_PROT_DOUT_INSERT:
+ return "DOUT_INSERT";
+ case QLA_PROT_DIN_STRIP:
+ return "DIN_STRIP";
+ case QLA_PROT_DOUT_STRIP:
+ return "DOUT_STRIP";
+ case QLA_PROT_DIN_PASS:
+ return "DIN_PASS";
+ case QLA_PROT_DOUT_PASS:
+ return "DOUT_PASS";
+ default:
+ return "UNKNOWN";
+ }
+}
+
/* This API intentionally takes dest as a parameter, rather than returning
* int value to avoid caller forgetting to issue wmb() after the store */
void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest)
@@ -1603,6 +1623,99 @@ static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha,
qla2x00_start_iocbs(ha, ha->req);
}
+/* ha->hardware_lock supposed to be held on entry */
+static inline uint32_t qlt_make_handle(struct scsi_qla_host *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t h;
+
+ 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;
+ 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;
+
+ return h;
+}
+/* Code added for T10 DIF support */
+/*
+ * 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,
+ 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;
+
+
+ ql_dbg(ql_dbg_tgt_dif, vha, 0x3066,
+ "Sending response CTIO7 (vha=%p, atio=%p, scsi_status=%02x, "
+ "sense_key=%02x, asc=%02x, ascq=%02x",
+ vha, atio, scsi_status, sense_key, asc, ascq);
+
+ ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(vha, NULL);
+ if (ctio == NULL) {
+ ql_dbg(ql_dbg_async, vha, 0x3067,
+ "qla2x00t(%ld): %s failed: unable to allocate "
+ "request packet", vha->host_no, __func__);
+ goto out;
+ }
+
+ ctio->entry_type = CTIO_TYPE7;
+ ctio->entry_count = 1;
+ ctio->handle = QLA_TGT_SKIP_HANDLE;
+ ctio->nport_handle = cmd->sess->loop_id;
+ ctio->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT);
+ ctio->vp_index = vha->vp_idx;
+ ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
+ 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 = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
+ ctio->u.status1.ox_id = cpu_to_le16(temp);
+ ctio->u.status1.scsi_status =
+ cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID | scsi_status);
+ ctio->u.status1.response_len = __constant_cpu_to_le16(18);
+
+ ctio->u.status1.residual = get_unaligned((uint32_t *)
+ &atio->u.isp24.fcp_cmnd.add_cdb[0]);
+ if (ctio->u.status1.residual != 0)
+ ctio->u.status1.scsi_status |= __constant_cpu_to_le16(SS_RESIDUAL_UNDER);
+
+ /* Response code and sense key */
+ ((uint32_t *)ctio->u.status1.sense_data)[0] =
+ cpu_to_le32((0x70 << 24) | (sense_key << 8));
+ /* Additional sense length */
+ ((uint32_t *)ctio->u.status1.sense_data)[1] = __constant_cpu_to_le32(0x0a);
+ /* ASC and ASCQ */
+ ((uint32_t *)ctio->u.status1.sense_data)[3] = cpu_to_le32((asc << 24) |
+ (ascq << 16));
+
+ /* Memory Barrier */
+ wmb();
+ qla2x00_start_iocbs(vha, vha->req);
+
+out:
+ return;
+}
+
/* callback from target fabric module code */
void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
{
@@ -1669,7 +1782,7 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm)
prm->cmd->sg_mapped = 1;
- if (cmd->se_cmd.prot_op == TARGET_PROT_NORMAL) {
+ if (cmd->prot_op == QLA_PROT_NORMAL) {
/*
* If greater than four sg entries then we need to allocate
* the continuation entries
@@ -1680,8 +1793,8 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm)
prm->tgt->datasegs_per_cont);
} else {
/* DIF */
- if ((cmd->se_cmd.prot_op == TARGET_PROT_DIN_INSERT) ||
- (cmd->se_cmd.prot_op == TARGET_PROT_DOUT_STRIP)) {
+ if ((cmd->prot_op == QLA_PROT_DIN_INSERT) ||
+ (cmd->prot_op == QLA_PROT_DOUT_STRIP)) {
prm->seg_cnt = DIV_ROUND_UP(cmd->bufflen, cmd->blk_sz);
prm->tot_dsds = prm->seg_cnt;
} else
@@ -1695,8 +1808,8 @@ static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm)
if (unlikely(prm->prot_seg_cnt == 0))
goto out_err;
- if ((cmd->se_cmd.prot_op == TARGET_PROT_DIN_INSERT) ||
- (cmd->se_cmd.prot_op == TARGET_PROT_DOUT_STRIP)) {
+ if ((cmd->prot_op == QLA_PROT_DIN_INSERT) ||
+ (cmd->prot_op == QLA_PROT_DOUT_STRIP)) {
/* Dif Bundling not support here */
prm->prot_seg_cnt = DIV_ROUND_UP(cmd->bufflen,
cmd->blk_sz);
@@ -1782,34 +1895,6 @@ static inline void *qlt_get_req_pkt(struct scsi_qla_host *vha)
return (cont_entry_t *)vha->req->ring_ptr;
}
-/* ha->hardware_lock supposed to be held on entry */
-static inline uint32_t qlt_make_handle(struct scsi_qla_host *vha)
-{
- struct qla_hw_data *ha = vha->hw;
- uint32_t h;
-
- 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;
- 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;
-
- return h;
-}
/* ha->hardware_lock supposed to be held on entry */
static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm,
@@ -2143,6 +2228,60 @@ static inline void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type)
{}
#endif
+
+static void qlt_print_dif_err(struct qla_tgt_prm *prm)
+{
+ struct qla_tgt_cmd *cmd;
+ struct scsi_qla_host *vha;
+
+
+ /* asc 0x10=dif error */
+ if (prm->sense_buffer && (prm->sense_buffer[12] == 0x10)) {
+
+ cmd = prm->cmd;
+ vha = cmd->vha;
+ /* ASCQ */
+ switch (prm->sense_buffer[13]) {
+ case 1:
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+ "BE detected Guard TAG ERR: lba[0x%llx|%lld] len[0x%x] "
+ "ulp_cmd=%p tag[%x]",
+ cmd->lba, cmd->lba,
+ cmd->num_blks, cmd->ulp_cmd,
+ cmd->atio.u.isp24.exchange_addr);
+ break;
+ case 2:
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+ "BE detected APP TAG ERR: lba[0x%llx|%lld] len[0x%x] "
+ "ulp_cmd=%p tag[%x]",
+ cmd->lba, cmd->lba,
+ cmd->num_blks, cmd->ulp_cmd,
+ cmd->atio.u.isp24.exchange_addr);
+ break;
+ case 3:
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+ "BE detected REF TAG ERR: lba[0x%llx|%lld] len[0x%x] "
+ "ulp_cmd=%p tag[%x]",
+ cmd->lba, cmd->lba,
+ cmd->num_blks, cmd->ulp_cmd,
+ cmd->atio.u.isp24.exchange_addr);
+ break;
+ default:
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+ "BE detected Dif ERR: lba[%llx|%lld] len[%x] "
+ "ulp_cmd=%p tag[%x]",
+ cmd->lba, cmd->lba,
+ cmd->num_blks, cmd->ulp_cmd,
+ cmd->atio.u.isp24.exchange_addr);
+ break;
+ }
+
+ ql_dump_buffer(ql_dbg_tgt_dif, vha, 0xffff,
+ cmd->cdb, 16);
+ }
+}
+
+
static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
struct qla_tgt_prm *prm)
{
@@ -2183,18 +2322,9 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
for (i = 0; i < prm->sense_buffer_len/4; i++)
((uint32_t *)ctio->u.status1.sense_data)[i] =
cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]);
-#if 0
- if (unlikely((prm->sense_buffer_len % 4) != 0)) {
- static int q;
- if (q < 10) {
- ql_dbg(ql_dbg_tgt, vha, 0xe04f,
- "qla_target(%d): %d bytes of sense "
- "lost", prm->tgt->ha->vp_idx,
- prm->sense_buffer_len % 4);
- q++;
- }
- }
-#endif
+
+ qlt_print_dif_err(prm);
+
} else {
ctio->u.status1.flags &=
~cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0);
@@ -2212,7 +2342,7 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
/* diff */
static inline int
-qlt_hba_err_chk_enabled(struct se_cmd *se_cmd)
+qlt_hba_err_chk_enabled(struct qla_tgt_cmd *cmd)
{
/*
* Uncomment when corresponding SCSI changes are done.
@@ -2221,19 +2351,19 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
return 0;
*
*/
- switch (se_cmd->prot_op) {
- case TARGET_PROT_DOUT_INSERT:
- case TARGET_PROT_DIN_STRIP:
+ switch (cmd->prot_op) {
+ case QLA_PROT_DOUT_INSERT:
+ case QLA_PROT_DIN_STRIP:
if (ql2xenablehba_err_chk >= 1)
return 1;
break;
- case TARGET_PROT_DOUT_PASS:
- case TARGET_PROT_DIN_PASS:
+ case QLA_PROT_DOUT_PASS:
+ case QLA_PROT_DIN_PASS:
if (ql2xenablehba_err_chk >= 2)
return 1;
break;
- case TARGET_PROT_DIN_INSERT:
- case TARGET_PROT_DOUT_STRIP:
+ case QLA_PROT_DIN_INSERT:
+ case QLA_PROT_DOUT_STRIP:
return 1;
default:
break;
@@ -2241,14 +2371,32 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
return 0;
}
-/*
- * qla24xx_set_t10dif_tags_from_cmd - Extract Ref and App tags from SCSI command
- *
- */
-static inline void
-qlt_set_t10dif_tags(struct se_cmd *se_cmd, struct crc_context *ctx)
+static inline int
+qla_tgt_ref_mask_check(struct qla_tgt_cmd *cmd)
+{
+ switch (cmd->prot_op) {
+ case QLA_PROT_DIN_INSERT:
+ case QLA_PROT_DOUT_INSERT:
+ case QLA_PROT_DIN_STRIP:
+ case QLA_PROT_DOUT_STRIP:
+ case QLA_PROT_DIN_PASS:
+ case QLA_PROT_DOUT_PASS:
+ return 1;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static void
+qla_tgt_set_dif_tags(struct qla_tgt_cmd *cmd, struct crc_context *ctx,
+ uint16_t *pfw_prot_opts)
{
- uint32_t lba = 0xffffffff & se_cmd->t_task_lba;
+ uint32_t lba = 0xffffffff & cmd->lba;
+ uint32_t t32 = 0;
+ scsi_qla_host_t *vha = cmd->tgt->vha;
+ struct qla_hw_data *ha = vha->hw;
/* wait til Mode Sense/Select cmd, modepage Ah, subpage 2
* have been immplemented by TCM, before AppTag is avail.
@@ -2258,17 +2406,32 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
ctx->app_tag_mask[0] = 0x0;
ctx->app_tag_mask[1] = 0x0;
- switch (se_cmd->prot_type) {
- case TARGET_DIF_TYPE0_PROT:
+ if (IS_PI_UNINIT_CAPABLE(ha)) {
+ if ((cmd->prot_type == QLA_TGT_PROT_TYPE1) ||
+ (cmd->prot_type == QLA_TGT_PROT_TYPE2))
+ *pfw_prot_opts |= PO_DIS_VALD_APP_ESC;
+ else if (cmd->prot_type == QLA_TGT_PROT_TYPE3)
+ *pfw_prot_opts |= PO_DIS_VALD_APP_REF_ESC;
+ }
+
+ t32 = ha->tgt.tgt_ops->get_dif_tags(cmd, pfw_prot_opts);
+
+#if 0
+ if (cmd->prot_op == TARGET_PROT_PASS_NOCHECK) {
+ *pfw_prot_opts |= PO_DISABLE_GUARD_CHECK|
+ PO_DIS_APP_TAG_VALD|PO_DIS_REF_TAG_VALD;
+ return;
+ }
+#endif
+
+ switch (cmd->prot_type) {
+ case QLA_TGT_PROT_TYPE0:
/*
* No check for ql2xenablehba_err_chk, as it would be an
* I/O error if hba tag generation is not done.
*/
ctx->ref_tag = cpu_to_le32(lba);
- if (!qlt_hba_err_chk_enabled(se_cmd))
- break;
-
/* enable ALL bytes of the ref tag */
ctx->ref_tag_mask[0] = 0xff;
ctx->ref_tag_mask[1] = 0xff;
@@ -2279,11 +2442,14 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
* For TYpe 1 protection: 16 bit GUARD tag, 32 bit REF tag, and
* 16 bit app tag.
*/
- case TARGET_DIF_TYPE1_PROT:
+ case QLA_TGT_PROT_TYPE1:
ctx->ref_tag = cpu_to_le32(lba);
- if (!qlt_hba_err_chk_enabled(se_cmd))
+ if (!qla_tgt_ref_mask_check(cmd) ||
+ !(ha->tgt.tgt_ops->chk_dif_tags(t32))) {
+ *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
break;
+ }
/* enable ALL bytes of the ref tag */
ctx->ref_tag_mask[0] = 0xff;
@@ -2295,11 +2461,14 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
* For TYPE 2 protection: 16 bit GUARD + 32 bit REF tag has to
* match LBA in CDB + N
*/
- case TARGET_DIF_TYPE2_PROT:
+ case QLA_TGT_PROT_TYPE2:
ctx->ref_tag = cpu_to_le32(lba);
- if (!qlt_hba_err_chk_enabled(se_cmd))
+ if (!qla_tgt_ref_mask_check(cmd) ||
+ !(ha->tgt.tgt_ops->chk_dif_tags(t32))) {
+ *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
break;
+ }
/* enable ALL bytes of the ref tag */
ctx->ref_tag_mask[0] = 0xff;
@@ -2309,14 +2478,13 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
break;
/* For Type 3 protection: 16 bit GUARD only */
- case TARGET_DIF_TYPE3_PROT:
+ case QLA_TGT_PROT_TYPE3:
+ *pfw_prot_opts |= PO_DIS_REF_TAG_VALD;
ctx->ref_tag_mask[0] = ctx->ref_tag_mask[1] =
ctx->ref_tag_mask[2] = ctx->ref_tag_mask[3] = 0x00;
break;
}
}
-
-
static inline int
qlt_build_ctio_crc2_pkt(struct qla_tgt_prm *prm, scsi_qla_host_t *vha)
{
@@ -2332,10 +2500,10 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
dma_addr_t crc_ctx_dma;
uint16_t fw_prot_opts = 0;
struct qla_tgt_cmd *cmd = prm->cmd;
- struct se_cmd *se_cmd = &cmd->se_cmd;
uint32_t h;
struct atio_from_isp *atio = &prm->cmd->atio;
uint16_t t16;
+ struct qla_tc_param tc;
ha = vha->hw;
@@ -2345,28 +2513,29 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
ql_dbg(ql_dbg_tgt, vha, 0xe071,
"qla_target(%d):%s: ulp_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,
+ vha->vp_idx, __func__, cmd->ulp_cmd, cmd->prot_op,
prm->prot_sg, prm->prot_seg_cnt, cmd->lba);
- if ((se_cmd->prot_op == TARGET_PROT_DIN_INSERT) ||
- (se_cmd->prot_op == TARGET_PROT_DOUT_STRIP))
+ if ((cmd->prot_op == QLA_PROT_DIN_INSERT) ||
+ (cmd->prot_op == QLA_PROT_DOUT_STRIP))
bundling = 0;
/* Compute dif len and adjust data len to incude protection */
data_bytes = cmd->bufflen;
dif_bytes = (data_bytes / cmd->blk_sz) * 8;
- switch (se_cmd->prot_op) {
- case TARGET_PROT_DIN_INSERT:
- case TARGET_PROT_DOUT_STRIP:
+ switch (cmd->prot_op) {
+ case QLA_PROT_DIN_INSERT:
+ case QLA_PROT_DOUT_STRIP:
transfer_length = data_bytes;
- data_bytes += dif_bytes;
+ if (cmd->prot_sg_cnt)
+ data_bytes += dif_bytes;
break;
- case TARGET_PROT_DIN_STRIP:
- case TARGET_PROT_DOUT_INSERT:
- case TARGET_PROT_DIN_PASS:
- case TARGET_PROT_DOUT_PASS:
+ case QLA_PROT_DIN_STRIP:
+ case QLA_PROT_DOUT_INSERT:
+ case QLA_PROT_DIN_PASS:
+ case QLA_PROT_DOUT_PASS:
transfer_length = data_bytes + dif_bytes;
break;
@@ -2374,29 +2543,30 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
BUG();
break;
}
-
- if (!qlt_hba_err_chk_enabled(se_cmd))
+ if (!qlt_hba_err_chk_enabled(cmd))
fw_prot_opts |= 0x10; /* Disable Guard tag checking */
/* HBA error checking enabled */
else if (IS_PI_UNINIT_CAPABLE(ha)) {
- if ((se_cmd->prot_type == TARGET_DIF_TYPE1_PROT) ||
- (se_cmd->prot_type == TARGET_DIF_TYPE2_PROT))
+ if ((cmd->prot_type == QLA_TGT_PROT_TYPE1) ||
+ (cmd->prot_type == QLA_TGT_PROT_TYPE2))
fw_prot_opts |= PO_DIS_VALD_APP_ESC;
- else if (se_cmd->prot_type == TARGET_DIF_TYPE3_PROT)
+ else if (cmd->prot_type == QLA_TGT_PROT_TYPE3)
fw_prot_opts |= PO_DIS_VALD_APP_REF_ESC;
}
- switch (se_cmd->prot_op) {
- case TARGET_PROT_DIN_INSERT:
- case TARGET_PROT_DOUT_INSERT:
+ switch (cmd->prot_op) {
+ case QLA_PROT_DIN_INSERT:
+ case QLA_PROT_DOUT_INSERT:
fw_prot_opts |= PO_MODE_DIF_INSERT;
+ bundling = 0;
break;
- case TARGET_PROT_DIN_STRIP:
- case TARGET_PROT_DOUT_STRIP:
+ case QLA_PROT_DIN_STRIP:
+ case QLA_PROT_DOUT_STRIP:
fw_prot_opts |= PO_MODE_DIF_REMOVE;
+ bundling = 0;
break;
- case TARGET_PROT_DIN_PASS:
- case TARGET_PROT_DOUT_PASS:
+ case QLA_PROT_DIN_PASS:
+ case QLA_PROT_DOUT_PASS:
fw_prot_opts |= PO_MODE_DIF_PASS;
/* FUTURE: does tcm require T10CRC<->IPCKSUM conversion? */
break;
@@ -2425,7 +2595,7 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK;
- pkt->nport_handle = prm->cmd->loop_id;
+ 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];
@@ -2471,7 +2641,7 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
/* Set handle */
crc_ctx_pkt->handle = pkt->handle;
- qlt_set_t10dif_tags(se_cmd, crc_ctx_pkt);
+ qla_tgt_set_dif_tags(cmd, crc_ctx_pkt, &fw_prot_opts);
pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma));
pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma));
@@ -2498,16 +2668,24 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes);
crc_ctx_pkt->guard_seed = cpu_to_le16(0);
+ memset((uint8_t *)&tc, 0 , sizeof(tc));
+ tc.vha = vha;
+ tc.blk_sz = cmd->blk_sz;
+ tc.bufflen = cmd->bufflen;
+ tc.sg = cmd->sg;
+ tc.prot_sg = cmd->prot_sg;
+ tc.ctx = crc_ctx_pkt;
+ tc.ctx_dsd_alloced = &cmd->ctx_dsd_alloced;
/* Walks data segments */
pkt->flags |= cpu_to_le16(CTIO7_FLAGS_DSD_PTR);
if (!bundling && prm->prot_seg_cnt) {
if (qla24xx_walk_and_build_sglist_no_difb(ha, NULL, cur_dsd,
- prm->tot_dsds, cmd))
+ prm->tot_dsds, &tc))
goto crc_queuing_error;
} else if (qla24xx_walk_and_build_sglist(ha, NULL, cur_dsd,
- (prm->tot_dsds - prm->prot_seg_cnt), cmd))
+ (prm->tot_dsds - prm->prot_seg_cnt), &tc))
goto crc_queuing_error;
if (bundling && prm->prot_seg_cnt) {
@@ -2516,13 +2694,14 @@ static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio,
cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
if (qla24xx_walk_and_build_prot_sglist(ha, NULL, cur_dsd,
- prm->prot_seg_cnt, cmd))
+ prm->prot_seg_cnt, &tc))
goto crc_queuing_error;
}
return QLA_SUCCESS;
crc_queuing_error:
/* Cleanup will be performed by the caller */
+ vha->hw->tgt.cmds[h-1] = NULL;
return QLA_FUNCTION_FAILED;
}
@@ -2598,10 +2777,14 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
if (unlikely(res))
goto out_unmap_unlock;
- if (cmd->se_cmd.prot_op && (xmit_type & QLA_TGT_XMIT_DATA))
+ if (cmd->prot_op &&
+ (xmit_type & QLA_TGT_XMIT_DATA) &&
+ qlt_has_data(cmd)) {
res = qlt_build_ctio_crc2_pkt(&prm, vha);
+ }
else
res = qlt_24xx_build_ctio_pkt(&prm, vha);
+
if (unlikely(res != 0)) {
vha->req->cnt += full_req_cnt;
goto out_unmap_unlock;
@@ -2614,7 +2797,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
cpu_to_le16(CTIO7_FLAGS_DATA_IN |
CTIO7_FLAGS_STATUS_MODE_0);
- if (cmd->se_cmd.prot_op == TARGET_PROT_NORMAL)
+ if (cmd->prot_op == QLA_PROT_NORMAL)
qlt_load_data_segments(&prm, vha);
if (prm.add_status_pkt == 0) {
@@ -2739,7 +2922,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
res = qlt_check_reserve_free_req(vha, prm.req_cnt);
if (res != 0)
goto out_unlock_free_unmap;
- if (cmd->se_cmd.prot_op)
+ if (cmd->prot_op != QLA_PROT_NORMAL)
res = qlt_build_ctio_crc2_pkt(&prm, vha);
else
res = qlt_24xx_build_ctio_pkt(&prm, vha);
@@ -2753,7 +2936,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
pkt->u.status0.flags |= cpu_to_le16(CTIO7_FLAGS_DATA_OUT |
CTIO7_FLAGS_STATUS_MODE_0);
- if (cmd->se_cmd.prot_op == TARGET_PROT_NORMAL)
+ if (cmd->prot_op == QLA_PROT_NORMAL)
qlt_load_data_segments(&prm, vha);
cmd->state = QLA_TGT_STATE_NEED_DATA;
@@ -2776,50 +2959,47 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
/*
- * Checks the guard or meta-data for the type of error
- * detected by the HBA.
+ * it is assumed either hardware_lock or qpair lock is held.
*/
-static inline int
+static void
qlt_handle_dif_error(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd,
- struct ctio_crc_from_fw *sts)
+ struct ctio_crc_from_fw *sts)
{
uint8_t *ap = &sts->actual_dif[0];
uint8_t *ep = &sts->expected_dif[0];
- uint32_t e_ref_tag, a_ref_tag;
- uint16_t e_app_tag, a_app_tag;
- uint16_t e_guard, a_guard;
uint64_t lba = cmd->lba;
+ uint8_t scsi_status, sense_key, asc, ascq;
+ unsigned long flags;
- a_guard = be16_to_cpu(*(uint16_t *)(ap + 0));
- a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2));
- a_ref_tag = be32_to_cpu(*(uint32_t *)(ap + 4));
+ cmd->trc_flags |= TRC_DIF_ERR;
- e_guard = be16_to_cpu(*(uint16_t *)(ep + 0));
- e_app_tag = be16_to_cpu(*(uint16_t *)(ep + 2));
- e_ref_tag = be32_to_cpu(*(uint32_t *)(ep + 4));
+ cmd->a_guard = be16_to_cpu(*(uint16_t *)(ap + 0));
+ cmd->a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2));
+ cmd->a_ref_tag = be32_to_cpu(*(uint32_t *)(ap + 4));
- ql_dbg(ql_dbg_tgt, vha, 0xe075,
- "iocb(s) %p Returned STATUS.\n", sts);
+ cmd->e_guard = be16_to_cpu(*(uint16_t *)(ep + 0));
+ cmd->e_app_tag = be16_to_cpu(*(uint16_t *)(ep + 2));
+ cmd->e_ref_tag = be32_to_cpu(*(uint32_t *)(ep + 4));
- ql_dbg(ql_dbg_tgt, vha, 0xf075,
- "dif check TGT cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x]\n",
- cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba,
- a_ref_tag, e_ref_tag, a_app_tag, e_app_tag, a_guard, e_guard);
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xf075,
+ "%s: aborted %d state %d\n",
+ __func__, cmd->aborted, cmd->state);
+ scsi_status = sense_key = asc = ascq = 0;
+
+#if 0
/*
* Ignore sector if:
* For type 3: ref & app tag is all 'f's
* For type 0,1,2: app tag is all 'f's
*/
- if ((a_app_tag == 0xffff) &&
- ((cmd->se_cmd.prot_type != TARGET_DIF_TYPE3_PROT) ||
- (a_ref_tag == 0xffffffff))) {
+ if ((cmd->a_app_tag == 0xffff) &&
+ ((cmd->prot_type != QLA_TGT_PROT_TYPE3) ||
+ (cmd->a_ref_tag == 0xffffffff))) {
uint32_t blocks_done;
/* 2TB boundary case covered automatically with this */
- blocks_done = e_ref_tag - (uint32_t)lba + 1;
- cmd->se_cmd.bad_sector = e_ref_tag;
- cmd->se_cmd.pi_err = 0;
+ blocks_done = cmd->e_ref_tag - (uint32_t)lba + 1;
ql_dbg(ql_dbg_tgt, vha, 0xf074,
"need to return scsi good\n");
@@ -2828,7 +3008,6 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
uint32_t i, k = 0, num_ent;
struct scatterlist *sg, *sgl;
-
sgl = cmd->prot_sg;
/* Patch the corresponding protection tags */
@@ -2845,68 +3024,97 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
if (k != blocks_done) {
ql_log(ql_log_warn, vha, 0xf076,
"unexpected tag values tag:lba=%u:%llu)\n",
- e_ref_tag, (unsigned long long)lba);
+ cmd->e_ref_tag, (unsigned long long)lba);
goto out;
}
-
-#if 0
- struct sd_dif_tuple *spt;
- /* TODO:
- * This section came from initiator. Is it valid here?
- * should ulp be override with actual val???
- */
- spt = page_address(sg_page(sg)) + sg->offset;
- spt += j;
-
- spt->app_tag = 0xffff;
- if (cmd->se_cmd.prot_type == SCSI_PROT_DIF_TYPE3)
- spt->ref_tag = 0xffffffff;
-#endif
}
-
- return 0;
}
+#endif
- /* check guard */
- if (e_guard != a_guard) {
- cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
- cmd->se_cmd.bad_sector = cmd->lba;
-
- ql_log(ql_log_warn, vha, 0xe076,
- "Guard ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
- cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba,
- a_ref_tag, e_ref_tag, a_app_tag, e_app_tag,
- a_guard, e_guard, cmd);
- goto out;
+ /* 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);
+
+ cmd->dif_err_code = DIF_ERR_APP;
+ scsi_status = SAM_STAT_CHECK_CONDITION;
+ sense_key = ABORTED_COMMAND;
+ asc = 0x10;
+ ascq = 0x2;
}
/* check ref tag */
- if (e_ref_tag != a_ref_tag) {
- cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
- cmd->se_cmd.bad_sector = e_ref_tag;
-
- ql_log(ql_log_warn, vha, 0xe077,
- "Ref Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
- cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba,
- a_ref_tag, e_ref_tag, a_app_tag, e_app_tag,
- a_guard, e_guard, cmd);
+ 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);
+
+ cmd->dif_err_code = DIF_ERR_REF;
+ scsi_status = SAM_STAT_CHECK_CONDITION;
+ sense_key = ABORTED_COMMAND;
+ asc = 0x10;
+ ascq = 0x3;
goto out;
}
- /* check appl tag */
- if (e_app_tag != a_app_tag) {
- cmd->se_cmd.pi_err = TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED;
- cmd->se_cmd.bad_sector = cmd->lba;
-
- ql_log(ql_log_warn, vha, 0xe078,
- "App Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
- cmd->atio.u.isp24.fcp_cmnd.cdb[0], lba,
- a_ref_tag, e_ref_tag, a_app_tag, e_app_tag,
- a_guard, e_guard, 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);
+
+ cmd->dif_err_code = DIF_ERR_GRD;
+ scsi_status = SAM_STAT_CHECK_CONDITION;
+ sense_key = ABORTED_COMMAND;
+ asc = 0x10;
+ ascq = 0x1;
goto out;
}
+
out:
- return 1;
+ switch (cmd->state) {
+ case QLA_TGT_STATE_NEED_DATA:
+ /* handle_data will load DIF error code */
+ cmd->state = QLA_TGT_STATE_DATA_IN;
+ vha->hw->tgt.tgt_ops->handle_data(cmd);
+ break;
+
+ default:
+ spin_lock_irqsave(&cmd->cmd_lock, flags);
+ if (cmd->aborted) {
+ spin_unlock_irqrestore(&cmd->cmd_lock, flags);
+ vha->hw->tgt.tgt_ops->free_cmd(cmd);
+ break;
+ }
+ spin_unlock_irqrestore(&cmd->cmd_lock, flags);
+
+ qlt_send_resp_ctio(vha, cmd, scsi_status, sense_key, asc, ascq);
+ /* assume scsi status gets out on the wire.
+ * Will not wait for completion.
+ */
+ vha->hw->tgt.tgt_ops->free_cmd(cmd);
+
+ break;
+ }
}
@@ -3046,8 +3254,7 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
/* Most likely, it isn't needed */
ctio24->u.status1.residual = get_unaligned((uint32_t *)
- &atio->u.isp24.fcp_cmnd.add_cdb[
- atio->u.isp24.fcp_cmnd.add_cdb_len]);
+ &atio->u.isp24.fcp_cmnd.add_cdb[0]);
if (ctio24->u.status1.residual != 0)
ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER;
@@ -3281,6 +3488,17 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio,
{
int term = 0;
+ if (cmd->prot_op) {
+ ql_dbg(ql_dbg_tgt_dif, vha, 0xffff,
+ "Term DIF cmd: lba[0x%llx|%lld] len[0x%x] "
+ "ulp_cmd=%p tag[%x] op %#x/%s",
+ cmd->lba, cmd->lba,
+ cmd->num_blks, cmd->ulp_cmd,
+ cmd->atio.u.isp24.exchange_addr,
+ cmd->prot_op,
+ prot_op_str(cmd->prot_op));
+ }
+
if (ctio != NULL) {
struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio;
term = !(c->flags &
@@ -3505,32 +3723,15 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
struct ctio_crc_from_fw *crc =
(struct ctio_crc_from_fw *)ctio;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf073,
- "qla_target(%d): CTIO with DIF_ERROR status %x received (state %x, ulp_cmd %p) actual_dif[0x%llx] expect_dif[0x%llx]\n",
+ "qla_target(%d): CTIO with DIF_ERROR status %x "
+ "received (state %x, ulp_cmd %p) actual_dif[0x%llx] "
+ "expect_dif[0x%llx]\n",
vha->vp_idx, status, cmd->state, ulp_cmd,
*((u64 *)&crc->actual_dif[0]),
*((u64 *)&crc->expected_dif[0]));
- if (qlt_handle_dif_error(vha, cmd, ctio)) {
- if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
- /* scsi Write/xfer rdy complete */
- goto skip_term;
- } else {
- /* scsi read/xmit respond complete
- * call handle dif to send scsi status
- * rather than terminate exchange.
- */
- cmd->state = QLA_TGT_STATE_PROCESSED;
- ha->tgt.tgt_ops->handle_dif_err(cmd);
- return;
- }
- } else {
- /* Need to generate a SCSI good completion.
- * because FW did not send scsi status.
- */
- status = 0;
- goto skip_term;
- }
- break;
+ qlt_handle_dif_error(vha, cmd, ctio);
+ return;
}
default:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b,
@@ -3554,7 +3755,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
return;
}
}
-skip_term:
+
if (cmd->state == QLA_TGT_STATE_PROCESSED) {
cmd->trc_flags |= TRC_CTIO_DONE;
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index b09445d..c43910b 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -725,7 +725,6 @@ struct qla_tgt_func_tmpl {
int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
unsigned char *, uint32_t, uint8_t, int, int);
void (*handle_data)(struct qla_tgt_cmd *);
- void (*handle_dif_err)(struct qla_tgt_cmd *);
int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, u64, uint16_t,
uint32_t);
void (*free_cmd)(struct qla_tgt_cmd *);
@@ -750,6 +749,8 @@ struct qla_tgt_func_tmpl {
/* support routine */
void (*srr_get_cur_state)(struct qla_tgt_cmd *, srr_state_op_t op);
+ int (*get_dif_tags)(struct qla_tgt_cmd *cmd, uint16_t *pfw_prot_opts);
+ int (*chk_dif_tags)(uint32_t tag);
};
int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
@@ -907,6 +908,23 @@ enum qla_sess_deletion {
QLA_SESS_DELETION_IN_PROGRESS = 2,
};
+enum qla_tgt_prot_op {
+ QLA_PROT_NORMAL = 0,
+ QLA_PROT_DIN_INSERT,
+ QLA_PROT_DOUT_INSERT,
+ QLA_PROT_DIN_STRIP,
+ QLA_PROT_DOUT_STRIP,
+ QLA_PROT_DIN_PASS,
+ QLA_PROT_DOUT_PASS,
+};
+
+enum qla_tgt_prot_type {
+ QLA_TGT_PROT_TYPE0,
+ QLA_TGT_PROT_TYPE1,
+ QLA_TGT_PROT_TYPE2,
+ QLA_TGT_PROT_TYPE3,
+};
+
enum trace_flags {
TRC_NEW_CMD = BIT_0,
TRC_DO_WORK = BIT_1,
@@ -927,6 +945,7 @@ enum trace_flags {
TRC_CMD_CHK_STOP = BIT_16,
TRC_CMD_FREE = BIT_17,
TRC_DATA_IN = BIT_18,
+ TRC_DIF_ERR = BIT_19,
};
struct qla_tgt_cmd {
@@ -944,7 +963,6 @@ struct qla_tgt_cmd {
unsigned int sg_mapped:1;
unsigned int free_sg:1;
unsigned int write_data_transferred:1;
- unsigned int ctx_dsd_alloced:1;
unsigned int q_full:1;
unsigned int term_exchg:1;
unsigned int cmd_sent_to_fw:1;
@@ -961,7 +979,6 @@ struct qla_tgt_cmd {
enum dma_data_direction dma_data_direction;
uint32_t reset_count;
int residual; /* + = over, - = under */
- int8_t scsi_status;
uint16_t loop_id; /* to save extra sess dereferences */
struct qla_tgt *tgt; /* to save extra sess dereferences */
@@ -973,9 +990,28 @@ struct qla_tgt_cmd {
struct scatterlist *prot_sg;
uint32_t prot_sg_cnt;
uint32_t blk_sz;
+ uint32_t num_blks;
+
+ uint8_t ctx_dsd_alloced; /* do not covert this field to bit field */
+
+ /* override scsi status in case of ULP does not T10-dif */
+ uint8_t dif_err_code;
+#define DIF_ERR_NONE 0
+#define DIF_ERR_GRD 1
+#define DIF_ERR_REF 2
+#define DIF_ERR_APP 3
+ uint8_t scsi_status;
+ uint8_t sense_key;
+ uint8_t asc;
+ uint8_t ascq;
+
struct crc_context *ctx;
+ uint32_t prot_op; /* qla_tgt_prot_op */
+ uint32_t prot_type;
uint8_t *cdb;
uint64_t lba;
+ uint32_t a_ref_tag, e_ref_tag;
+ uint16_t a_guard, e_guard, a_app_tag, e_app_tag;
uint64_t jiffies_at_alloc;
uint64_t jiffies_at_free;
@@ -1152,4 +1188,9 @@ extern void qlt_modify_vp_config(struct scsi_qla_host *,
extern void qlt_logo_completion_handler(fc_port_t *, int);
extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
+void qlt_set_t10dif_tags(struct qla_tgt_cmd *cmd, struct crc_context *ctx,
+ uint16_t *pfw_prot_opts);
+void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
+ uint8_t scsi_status, uint8_t sense_key, uint8_t asc, uint8_t ascq);
+
#endif /* __QLA_TARGET_H */
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 3fef40b..8facd3d 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -490,10 +490,43 @@ static u32 tcm_qla2xxx_sess_get_index(struct se_session *se_sess)
return 0;
}
+static void tcm_qla2xxx_prot_op(struct qla_tgt_cmd *cmd)
+{
+ struct se_cmd *se_cmd = Q_TO_SE_CMD(cmd);
+
+ switch (se_cmd->prot_op) {
+ case TARGET_PROT_NORMAL:
+ cmd->prot_op = QLA_PROT_NORMAL;
+ break;
+ case TARGET_PROT_DIN_INSERT:
+ cmd->prot_op = QLA_PROT_DIN_INSERT;
+ break;
+ case TARGET_PROT_DOUT_INSERT:
+ cmd->prot_op = QLA_PROT_DOUT_INSERT;
+ break;
+ case TARGET_PROT_DIN_STRIP:
+ cmd->prot_op = QLA_PROT_DIN_STRIP;
+ break;
+ case TARGET_PROT_DOUT_STRIP:
+ cmd->prot_op = QLA_PROT_DOUT_STRIP;
+ break;
+ case TARGET_PROT_DIN_PASS:
+ cmd->prot_op = QLA_PROT_DIN_PASS;
+ break;
+ case TARGET_PROT_DOUT_PASS:
+ cmd->prot_op = QLA_PROT_DOUT_PASS;
+ break;
+ }
+}
+
+static void tcm_qla2xxx_prot_type(struct qla_tgt_cmd *cmd)
+{
+ cmd->prot_type = (Q_TO_SE_CMD(cmd))->prot_type;
+}
+
static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
{
- struct qla_tgt_cmd *cmd = container_of(se_cmd,
- struct qla_tgt_cmd, se_cmd);
+ struct qla_tgt_cmd *cmd = SE_TO_Q_CMD(se_cmd);
if (cmd->aborted) {
/* Cmd can loop during Q-full. tcm_qla2xxx_aborted_task
@@ -519,6 +552,8 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
cmd->prot_sg = se_cmd->t_prot_sg;
cmd->blk_sz = se_cmd->se_dev->dev_attrib.block_size;
se_cmd->pi_err = 0;
+ tcm_qla2xxx_prot_op(cmd);
+ tcm_qla2xxx_prot_type(cmd);
cmd->cdb = se_cmd->t_task_cdb;
cmd->lba = se_cmd->t_task_lba;
@@ -639,6 +674,80 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
data_dir, flags);
}
+static int
+tcm_qla2xxx_chk_dif_tags(uint32_t tag)
+{
+ return 0;
+}
+
+/* TODO: Return the type of check needed, similar to SCST */
+
+static int
+tcm_qla2xxx_dif_tags(struct qla_tgt_cmd *cmd, uint16_t *pfw_prot_opts)
+{
+ struct se_cmd *se_cmd = Q_TO_SE_CMD(cmd);
+ uint32_t t32=0;
+
+ if (!(se_cmd->prot_checks & TARGET_DIF_CHECK_GUARD))
+ *pfw_prot_opts |= PO_DISABLE_GUARD_CHECK;
+
+ if (!(se_cmd->prot_checks & TARGET_DIF_CHECK_APPTAG))
+ *pfw_prot_opts |= PO_DIS_APP_TAG_VALD;
+
+ return t32;
+}
+
+static void tcm_qla2xxx_check_dif_err(struct qla_tgt_cmd *cmd)
+{
+ struct se_cmd *se_cmd = Q_TO_SE_CMD(cmd);
+
+ if ((cmd->a_app_tag == 0xffff) &&
+ ((cmd->prot_type != QLA_TGT_PROT_TYPE3) ||
+ (cmd->a_ref_tag == 0xffffffff))) {
+ se_cmd->bad_sector = cmd->e_ref_tag;
+ se_cmd->pi_err = 0;
+ return;
+ }
+
+ /* check guard */
+ if (cmd->e_guard != cmd->a_guard) {
+ se_cmd->pi_err = TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
+ se_cmd->bad_sector = cmd->lba;
+
+ pr_err("Guard ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
+ cmd->atio.u.isp24.fcp_cmnd.cdb[0], cmd->lba,
+ cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag, cmd->e_app_tag,
+ cmd->a_guard, cmd->e_guard, cmd);
+ goto out;
+ }
+
+ /* check ref tag */
+ if (cmd->e_ref_tag != cmd->a_ref_tag) {
+ se_cmd->pi_err = TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
+ se_cmd->bad_sector = cmd->e_ref_tag;
+
+ pr_err("Ref Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
+ cmd->atio.u.isp24.fcp_cmnd.cdb[0], cmd->lba,
+ cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag, cmd->e_app_tag,
+ cmd->a_guard, cmd->e_guard, cmd);
+ goto out;
+ }
+
+ /* check appl tag */
+ if (cmd->e_app_tag != cmd->a_app_tag) {
+ se_cmd->pi_err = TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED;
+ se_cmd->bad_sector = cmd->lba;
+
+ pr_err("App Tag ERR: cdb 0x%x lba 0x%llx: [Actual|Expected] Ref Tag[0x%x|0x%x], App Tag [0x%x|0x%x], Guard [0x%x|0x%x] cmd=%p\n",
+ cmd->atio.u.isp24.fcp_cmnd.cdb[0], cmd->lba,
+ cmd->a_ref_tag, cmd->e_ref_tag, cmd->a_app_tag, cmd->e_app_tag,
+ cmd->a_guard, cmd->e_guard, cmd);
+ goto out;
+ }
+out:
+ return;
+}
+
static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
{
struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
@@ -663,6 +772,10 @@ 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++;
+
+ if (cmd->prot_op)
+ tcm_qla2xxx_check_dif_err(cmd);
+
if (!cmd->write_data_transferred) {
/*
* Check if se_cmd has already been aborted via LUN_RESET, and
@@ -673,6 +786,21 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
return;
}
+ switch (cmd->dif_err_code) {
+ case DIF_ERR_GRD:
+ se_cmd->pi_err = TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
+ break;
+ case DIF_ERR_REF:
+ se_cmd->pi_err = TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
+ break;
+ case DIF_ERR_APP:
+ se_cmd->pi_err = TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED;
+ break;
+ case DIF_ERR_NONE:
+ default:
+ break;
+ }
+
if (se_cmd->pi_err)
transport_generic_request_failure(se_cmd,
se_cmd->pi_err);
@@ -697,27 +825,6 @@ static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
}
-static void tcm_qla2xxx_handle_dif_work(struct work_struct *work)
-{
- struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
-
- /* take an extra kref to prevent cmd free too early.
- * need to wait for SCSI status/check condition to
- * finish responding generate by transport_generic_request_failure.
- */
- kref_get(&se_cmd->cmd_kref);
- transport_generic_request_failure(se_cmd, se_cmd->pi_err);
-}
-
-/*
- * Called from qla_target.c:qlt_do_ctio_completion()
- */
-static void tcm_qla2xxx_handle_dif_err(struct qla_tgt_cmd *cmd)
-{
- INIT_WORK(&cmd->work, tcm_qla2xxx_handle_dif_work);
- queue_work(tcm_qla2xxx_free_wq, &cmd->work);
-}
-
/*
* Called from qla_target.c:qlt_issue_task_mgmt()
*/
@@ -855,6 +962,8 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
cmd->prot_sg = se_cmd->t_prot_sg;
cmd->blk_sz = se_cmd->se_dev->dev_attrib.block_size;
se_cmd->pi_err = 0;
+ tcm_qla2xxx_prot_op(cmd);
+ tcm_qla2xxx_prot_type(cmd);
cmd->cdb = se_cmd->t_task_cdb;
cmd->lba = se_cmd->t_task_lba;
@@ -1844,7 +1953,6 @@ static void tcm_qla2xxx_srr_get_cur_state(struct qla_tgt_cmd *cmd,
static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
.handle_cmd = tcm_qla2xxx_handle_cmd,
.handle_data = tcm_qla2xxx_handle_data,
- .handle_dif_err = tcm_qla2xxx_handle_dif_err,
.handle_tmr = tcm_qla2xxx_handle_tmr,
.free_cmd = tcm_qla2xxx_free_cmd,
.free_mcmd = tcm_qla2xxx_free_mcmd,
@@ -1861,6 +1969,8 @@ static void tcm_qla2xxx_srr_get_cur_state(struct qla_tgt_cmd *cmd,
.alloc_cmd = tcm_qla2xxx_alloc_cmd,
.alloc_mgmt_cmd = tcm_qla2xxx_alloc_mgmt_cmd,
.srr_get_cur_state = tcm_qla2xxx_srr_get_cur_state,
+ .get_dif_tags = tcm_qla2xxx_dif_tags,
+ .chk_dif_tags = tcm_qla2xxx_chk_dif_tags,
};
static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 09/22] qla2xxx: Refactor T10-DIF PI support
2016-12-06 20:30 ` [PATCH 09/22] qla2xxx: Refactor T10-DIF PI support Himanshu Madhani
@ 2016-12-14 21:03 ` Christoph Hellwig
0 siblings, 0 replies; 50+ messages in thread
From: Christoph Hellwig @ 2016-12-14 21:03 UTC (permalink / raw)
To: Himanshu Madhani; +Cc: target-devel, nab, giridhar.malavali, linux-scsi
On Tue, Dec 06, 2016 at 12:30:38PM -0800, Himanshu Madhani wrote:
> From: Quinn Tran <quinn.tran@cavium.com>
>
> qla2xxx currently access T10-DIF protection opcode and type
> field in se_cmd struct. Add translation code so qla2xxx driver
> would not acces private TCM data structure.
And what's the point of doing that?
> 11 files changed, 661 insertions(+), 242 deletions(-)
And independent of the above a "cleanup" that adds over 400 lines of
code is simply not acceptable.
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 10/22] qla2xxx: Add framework for Async fabric discovery.
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (8 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 09/22] qla2xxx: Refactor T10-DIF PI support Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-06 20:30 ` [PATCH 11/22] qla2xxx: Refactor session management code Himanshu Madhani
` (12 subsequent siblings)
22 siblings, 0 replies; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
Currently code makes login/logout decision after a full scan of
the fabric. It's an expensive process in a large SAN. Eliminate
duplication of command by moving the login/logout decision from
a full fabric scan to an individual scan of the affected port.
Also, current code ignore the completion of the NACK.
This patch also attempts to optimize exepsive fabric discovery
process by optimizing the process of scanning switch for affected
port when RSCN is received.
This patch adds following capabilities in the driver
- Send Notification Acknowledgement asynchronously.
- Update session/fcport state asynchronously.
- Create a session or fcport struct asynchronously.
- Send GNL asynchronously. The command will ask FW to
provide a list of FC Port entries FW knows about.
- Send GPDB asynchronously. The command will ask FW to
provide detail data of an FC Port FW knows about or
perform ADISC to verify the state of the session.
- Send GPNID asynchronously. The command will ask switch
to provide WWPN for provided NPort ID.
- Send GPSC asynchronously. The command will ask switch
to provide registered port speed for provided WWPN.
- Send GIDPN asynchronously. The command will ask the
switch to provide Nport ID for provided WWPN.
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_attr.c | 3 +
drivers/scsi/qla2xxx/qla_def.h | 169 ++++-
drivers/scsi/qla2xxx/qla_fw.h | 30 +
drivers/scsi/qla2xxx/qla_gbl.h | 58 +-
drivers/scsi/qla2xxx/qla_gs.c | 687 +++++++++++++++++--
drivers/scsi/qla2xxx/qla_init.c | 1346 ++++++++++++++++++++++++++++---------
drivers/scsi/qla2xxx/qla_inline.h | 7 +-
drivers/scsi/qla2xxx/qla_iocb.c | 74 +-
drivers/scsi/qla2xxx/qla_isr.c | 221 ++++--
drivers/scsi/qla2xxx/qla_mbx.c | 88 ---
drivers/scsi/qla2xxx/qla_os.c | 184 +++--
drivers/scsi/qla2xxx/qla_target.c | 226 ++++++-
drivers/scsi/qla2xxx/qla_target.h | 17 +-
13 files changed, 2493 insertions(+), 617 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 47eb4d5..f48b76c 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2156,6 +2156,9 @@ struct device_attribute *qla2x00_host_attrs[] = {
clear_bit(vha->vp_idx, ha->vp_idx_map);
mutex_unlock(&ha->vport_lock);
+ dma_free_coherent(&ha->pdev->dev,
+ vha->gnl.size, vha->gnl.l, vha->gnl.ldma);
+
if (vha->qpair->vp_idx == vha->vp_idx) {
if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
ql_log(ql_log_warn, vha, 0x7087,
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 8cee332..f281f3d 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -55,6 +55,8 @@
#include "qla_settings.h"
+#define MODE_DUAL (MODE_TARGET|MODE_INITIATOR)
+
/*
* Data bit definitions
*/
@@ -251,6 +253,14 @@
#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */
#include "qla_fw.h"
+
+struct name_list_extended {
+ struct get_name_list_extended *l;
+ dma_addr_t ldma;
+ struct list_head fcports; /* protect by sess_list */
+ u32 size;
+ u8 sent;
+};
/*
* Timeout timer counts in seconds
*/
@@ -309,6 +319,17 @@ struct els_logo_payload {
uint8_t wwpn[WWN_SIZE];
};
+struct ct_arg {
+ void *iocb;
+ u16 nport_handle;
+ dma_addr_t req_dma;
+ dma_addr_t rsp_dma;
+ u32 req_size;
+ u32 rsp_size;
+ void *req;
+ void *rsp;
+};
+
/*
* SRB extensions.
*/
@@ -320,6 +341,7 @@ struct srb_iocb {
#define SRB_LOGIN_COND_PLOGI BIT_1
#define SRB_LOGIN_SKIP_PRLI BIT_2
uint16_t data[2];
+ u32 iop[2];
} logio;
struct {
#define ELS_DCMD_TIMEOUT 20
@@ -372,6 +394,16 @@ struct srb_iocb {
__le16 comp_status;
struct completion comp;
} abt;
+ struct ct_arg ctarg;
+ struct {
+ __le16 in_mb[28]; /* fr fw */
+ __le16 out_mb[28]; /* to fw */
+ void *out, *in;
+ dma_addr_t out_dma, in_dma;
+ } mbx;
+ struct {
+ struct imm_ntfy_from_isp *ntfy;
+ } nack;
} u;
struct timer_list timer;
@@ -392,16 +424,24 @@ struct srb_iocb {
#define SRB_FXIOCB_BCMD 11
#define SRB_ABT_CMD 12
#define SRB_ELS_DCMD 13
+#define SRB_MB_IOCB 14
+#define SRB_CT_PTHRU_CMD 15
+#define SRB_NACK_PLOGI 16
+#define SRB_NACK_PRLI 17
+#define SRB_NACK_LOGO 18
typedef struct srb {
atomic_t ref_count;
struct fc_port *fcport;
+ void *vha;
uint32_t handle;
uint16_t flags;
uint16_t type;
char *name;
int iocbs;
struct qla_qpair *qpair;
+ u32 gen1; /* scratch */
+ u32 gen2; /* scratch */
union {
struct srb_iocb iocb_cmd;
struct bsg_job *bsg_job;
@@ -1975,6 +2015,16 @@ struct mbx_entry {
uint8_t port_name[WWN_SIZE];
};
+/* mailbox command 4G & above */
+struct mbx_24xx_entry {
+ uint8_t entry_type;
+ uint8_t entry_count;
+ uint8_t sys_define1;
+ uint8_t entry_status;
+ uint32_t handle;
+ uint16_t mb[28];
+};
+
/*
* ISP request and response queue entry sizes
*/
@@ -2040,13 +2090,56 @@ struct mbx_entry {
QLT_PLOGI_LINK_MAX
} qlt_plogi_link_t;
+#define IOCB_SIZE 64
+
typedef struct {
struct list_head list;
- u8 iocb[64]; /* imm_ntfy_from_isp */
+ u8 iocb[IOCB_SIZE]; /* imm_ntfy_from_isp */
port_id_t id;
int ref_count;
+ void *fcport;
} qlt_plogi_ack_t;
+struct ct_sns_desc {
+ struct ct_sns_pkt *ct_sns;
+ dma_addr_t ct_sns_dma;
+};
+
+enum discovery_state {
+ DSC_DELETED,
+ DSC_GID_PN,
+ DSC_GNL,
+ DSC_LOGIN_PEND,
+ DSC_LOGIN_FAILED,
+ DSC_GPDB,
+ DSC_GPSC,
+ DSC_UPD_FCPORT,
+ DSC_LOGIN_COMPLETE,
+ DSC_DELETE_PEND,
+};
+
+enum login_state { /* FW control Target side */
+ DSC_LS_LLIOCB_SENT = 2,
+ DSC_LS_PLOGI_PEND,
+ DSC_LS_PLOGI_COMP,
+ DSC_LS_PRLI_PEND,
+ DSC_LS_PRLI_COMP,
+ DSC_LS_PORT_UNAVAIL,
+ DSC_LS_PRLO_PEND = 9,
+ DSC_LS_LOGO_PEND,
+};
+
+enum fcport_mgt_event {
+ FCME_RELOGIN=1,
+ FCME_RSCN,
+ FCME_GIDPN_DONE,
+ FCME_PLOGI_DONE, /* Initiator side sent LLIOCB */
+ FCME_GNL_DONE,
+ FCME_GPSC_DONE,
+ FCME_GPDB_DONE,
+ FCME_GPNID_DONE,
+ FCME_DELETE_DONE,
+};
/*
* Fibre channel port structure.
@@ -2065,9 +2158,12 @@ struct mbx_entry {
unsigned int deleted:2;
unsigned int local:1;
unsigned int logout_on_delete:1;
+ unsigned int logo_ack_needed:1;
unsigned int keep_nport_handle:1;
unsigned int send_els_logo:1;
+ unsigned int login_pause:1;
+ struct fc_port *conflict;
unsigned char logout_completed;
int generation;
@@ -2108,8 +2204,30 @@ struct mbx_entry {
unsigned long retry_delay_timestamp;
struct qla_tgt_sess *tgt_session;
+ struct ct_sns_desc ct_desc;
+ enum discovery_state disc_state;
+ enum login_state fw_login_state;
+ u32 login_gen, last_login_gen;
+ u32 rscn_gen, last_rscn_gen;
+ u32 chip_reset;
+ struct list_head gnl_entry;
+ struct work_struct del_work;
+ u8 iocb[IOCB_SIZE]; /* */
} fc_port_t;
+#define QLA_FCPORT_SCAN 1
+#define QLA_FCPORT_FOUND 2
+
+struct event_arg {
+ enum fcport_mgt_event event;
+ fc_port_t *fcport;
+ srb_t *sp;
+ port_id_t id;
+ u16 data[2], rc;
+ u8 port_name[WWN_SIZE];
+ u32 iop[2];
+};
+
#include "qla_mr.h"
/*
@@ -2136,6 +2254,7 @@ struct mbx_entry {
#define FCF_FCP2_DEVICE BIT_2
#define FCF_ASYNC_SENT BIT_3
#define FCF_CONF_COMP_SUPPORTED BIT_4
+#define FCF_DELETE_DEV BIT_5
/* No loop ID flag. */
#define FC_NO_LOOP_ID 0x1000
@@ -2187,6 +2306,10 @@ struct mbx_entry {
#define GFT_ID_REQ_SIZE (16 + 4)
#define GFT_ID_RSP_SIZE (16 + 32)
+#define GID_PN_CMD 0x121
+#define GID_PN_REQ_SIZE (16 + 8)
+#define GID_PN_RSP_SIZE (16 + 4)
+
#define RFT_ID_CMD 0x217
#define RFT_ID_REQ_SIZE (16 + 4 + 32)
#define RFT_ID_RSP_SIZE 16
@@ -2512,6 +2635,10 @@ struct ct_sns_req {
uint8_t reserved;
uint8_t port_name[3];
} gff_id;
+
+ struct {
+ uint8_t port_name[8];
+ } gid_pn;
} req;
};
@@ -2591,6 +2718,10 @@ struct ct_sns_rsp {
struct {
uint8_t fc4_features[128];
} gff_id;
+ struct {
+ uint8_t reserved;
+ uint8_t port_id[3];
+ } gid_pn;
} rsp;
};
@@ -2732,11 +2863,11 @@ struct isp_operations {
uint16_t (*calc_req_entries) (uint16_t);
void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
- void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t);
- void * (*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
+ void *(*prep_ms_iocb) (struct scsi_qla_host *, struct ct_arg *);
+ void *(*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
uint32_t);
- uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *,
+ uint8_t *(*read_nvram) (struct scsi_qla_host *, uint8_t *,
uint32_t, uint32_t);
int (*write_nvram) (struct scsi_qla_host *, uint8_t *, uint32_t,
uint32_t);
@@ -2799,13 +2930,21 @@ enum qla_work_type {
QLA_EVT_AEN,
QLA_EVT_IDC_ACK,
QLA_EVT_ASYNC_LOGIN,
- QLA_EVT_ASYNC_LOGIN_DONE,
QLA_EVT_ASYNC_LOGOUT,
QLA_EVT_ASYNC_LOGOUT_DONE,
QLA_EVT_ASYNC_ADISC,
QLA_EVT_ASYNC_ADISC_DONE,
QLA_EVT_UEVENT,
QLA_EVT_AENFX,
+ QLA_EVT_GIDPN,
+ QLA_EVT_GPNID,
+ QLA_EVT_GPNID_DONE,
+ QLA_EVT_NEW_SESS,
+ QLA_EVT_GPDB,
+ QLA_EVT_GPSC,
+ QLA_EVT_UPD_FCPORT,
+ QLA_EVT_GNL,
+ QLA_EVT_NACK,
};
@@ -2841,6 +2980,23 @@ struct qla_work_evt {
struct {
srb_t *sp;
} iosb;
+ struct {
+ port_id_t id;
+ } gpnid;
+ struct {
+ port_id_t id;
+ u8 port_name[8];
+ void *pla;
+ } new_sess;
+ struct { /*Get PDB, Get Speed, update fcport, gnl, gidpn */
+ fc_port_t *fcport;
+ u8 opt;
+ } fcport;
+ struct {
+ fc_port_t *fcport;
+ u8 iocb[IOCB_SIZE];
+ int type;
+ } nack;
} u;
};
@@ -3849,6 +4005,9 @@ struct qla_tgt_counters {
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 */
+ int fcport_count;
} scsi_qla_host_t;
struct qla27xx_image_status {
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 8a2368b..00938f1 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -72,6 +72,36 @@ struct port_database_24xx {
uint8_t reserved_3[24];
};
+/* MB 75h returns a list of DB entries similar to port_database_24xx(64B).
+ However, in this case it returns 1st 40 bytes.
+*/
+struct get_name_list_extended {
+ __le16 flags;
+ u8 current_login_state;
+ u8 last_login_state;
+ u8 hard_address[3];
+ u8 reserved_1;
+ u8 port_id[3];
+ u8 sequence_id;
+ __le16 port_timer;
+ __le16 nport_handle; /* N_PORT handle. */
+ __le16 receive_data_size;
+ __le16 reserved_2;
+
+ /* PRLI SVC Param are Big endian */
+ u8 prli_svc_param_word_0[2]; /* Bits 15-0 of word 0 */
+ u8 prli_svc_param_word_3[2]; /* Bits 15-0 of word 3 */
+ u8 port_name[WWN_SIZE];
+ u8 node_name[WWN_SIZE];
+};
+
+/* MB 75h: This is the short version of the database */
+struct get_name_list {
+ u8 port_node_name[WWN_SIZE]; /* B7 most sig, B0 least sig */
+ __le16 nport_handle;
+ u8 reserved;
+};
+
struct vp_database_24xx {
uint16_t vp_status;
uint8_t options;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 9303dbe..94fc7b4 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -73,6 +73,12 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
+
+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 int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
@@ -94,6 +100,13 @@ extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
int, int);
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_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 *, void *);
+int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
/*
* Global Data in qla_os.c source file.
@@ -135,8 +148,6 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
extern int qla2x00_post_async_login_work(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
-extern int qla2x00_post_async_login_done_work(struct scsi_qla_host *,
- fc_port_t *, uint16_t *);
extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *,
@@ -180,6 +191,10 @@ extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
extern void qla2x00_sp_compl(void *, void *, int);
extern void qla2xxx_qpair_sp_free_dma(void *, void *);
extern void qla2xxx_qpair_sp_compl(void *, void *, int);
+extern int qla24xx_post_upd_fcport_work(struct scsi_qla_host *, fc_port_t *);
+void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
+ uint16_t *);
+int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
/*
* Global Functions in qla_mid.c source file.
@@ -303,9 +318,6 @@ extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *,
qla2x00_init_firmware(scsi_qla_host_t *, uint16_t);
extern int
-qla2x00_get_node_name_list(scsi_qla_host_t *, void **, int *);
-
-extern int
qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t);
extern int
@@ -484,6 +496,9 @@ extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
uint32_t);
extern irqreturn_t
qla2xxx_msix_rsp_q(int irq, void *dev_id);
+fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t);
+fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8);
+fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);
/*
* Global Function Prototypes in qla_sup.c source file.
@@ -575,8 +590,8 @@ extern void ql_dump_buffer(uint32_t, scsi_qla_host_t *, int32_t,
/*
* Global Function Prototypes in qla_gs.c source file.
*/
-extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
-extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
+extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
+extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
extern int qla2x00_ga_nxt(scsi_qla_host_t *, fc_port_t *);
extern int qla2x00_gid_pt(scsi_qla_host_t *, sw_info_t *);
extern int qla2x00_gpn_id(scsi_qla_host_t *, sw_info_t *);
@@ -592,6 +607,24 @@ extern void ql_dump_buffer(uint32_t, scsi_qla_host_t *, int32_t,
extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *);
extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *);
extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t);
+extern int qla2x00_chk_ms_status(scsi_qla_host_t *, ms_iocb_entry_t *,
+ struct ct_sns_rsp *, const char *);
+extern void qla2x00_async_iocb_timeout(void *data);
+extern int qla24xx_async_gidpn(scsi_qla_host_t *, fc_port_t *);
+int qla24xx_post_gidpn_work(struct scsi_qla_host *, fc_port_t *);
+void qla24xx_handle_gidpn_event(scsi_qla_host_t *, struct event_arg *);
+
+extern void qla2x00_free_fcport(fc_port_t *);
+
+extern int qla24xx_post_gpnid_work(struct scsi_qla_host *, port_id_t *);
+extern int qla24xx_async_gpnid(scsi_qla_host_t *, port_id_t *);
+void qla24xx_async_gpnid_done(scsi_qla_host_t *, srb_t*);
+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 *);
+
/*
* Global Function Prototypes in qla_attr.c source file.
@@ -804,4 +837,15 @@ extern int qla_get_exlogin_status(scsi_qla_host_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 *);
+int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
+ struct imm_ntfy_from_isp *, int);
+void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *);
+void qlt_plogi_ack_link(struct scsi_qla_host *, qlt_plogi_ack_t *,
+ struct fc_port *, qlt_plogi_link_t);
+void qlt_plogi_ack_unref(struct scsi_qla_host *, qlt_plogi_ack_t *);
+extern void qlt_schedule_sess_for_deletion(struct fc_port *, bool);
+extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
+ uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
+void qla24xx_delete_sess_fn(struct work_struct *);
+
#endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 94e8a85..d7164da 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -24,12 +24,12 @@
* Returns a pointer to the @ha's ms_iocb.
*/
void *
-qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
+qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
{
struct qla_hw_data *ha = vha->hw;
ms_iocb_entry_t *ms_pkt;
- ms_pkt = ha->ms_iocb;
+ ms_pkt = (ms_iocb_entry_t *)arg->iocb;
memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
ms_pkt->entry_type = MS_IOCB_TYPE;
@@ -39,15 +39,15 @@
ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
ms_pkt->cmd_dsd_count = cpu_to_le16(1);
ms_pkt->total_dsd_count = cpu_to_le16(2);
- ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
- ms_pkt->req_bytecount = cpu_to_le32(req_size);
+ ms_pkt->rsp_bytecount = cpu_to_le32(arg->rsp_size);
+ ms_pkt->req_bytecount = cpu_to_le32(arg->req_size);
- ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
- ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(arg->req_dma));
+ ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(arg->req_dma));
ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
- ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
- ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
+ ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
vha->qla_stats.control_requests++;
@@ -64,29 +64,29 @@
* Returns a pointer to the @ha's ms_iocb.
*/
void *
-qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
+qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
{
struct qla_hw_data *ha = vha->hw;
struct ct_entry_24xx *ct_pkt;
- ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
+ ct_pkt = (struct ct_entry_24xx *)arg->iocb;
memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
ct_pkt->entry_type = CT_IOCB_TYPE;
ct_pkt->entry_count = 1;
- ct_pkt->nport_handle = cpu_to_le16(NPH_SNS);
+ ct_pkt->nport_handle = cpu_to_le16(arg->nport_handle);
ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
ct_pkt->cmd_dsd_count = cpu_to_le16(1);
ct_pkt->rsp_dsd_count = cpu_to_le16(1);
- ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
- ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
+ ct_pkt->rsp_byte_count = cpu_to_le32(arg->rsp_size);
+ ct_pkt->cmd_byte_count = cpu_to_le32(arg->req_size);
- ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
- ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(arg->req_dma));
+ ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(arg->req_dma));
ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
- ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
- ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
+ ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
+ ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
ct_pkt->vp_index = vha->vp_idx;
@@ -117,7 +117,7 @@
return &p->p.req;
}
-static int
+int
qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
struct ct_sns_rsp *ct_rsp, const char *routine)
{
@@ -183,14 +183,21 @@
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct qla_hw_data *ha = vha->hw;
+ struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_ga_nxt(vha, fcport);
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = GA_NXT_REQ_SIZE;
+ arg.rsp_size = GA_NXT_RSP_SIZE;
+ arg.nport_handle = NPH_SNS;
+
/* Issue GA_NXT */
/* Prepare common MS IOCB */
- ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GA_NXT_REQ_SIZE,
- GA_NXT_RSP_SIZE);
+ ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
@@ -269,16 +276,24 @@
struct ct_sns_gid_pt_data *gid_data;
struct qla_hw_data *ha = vha->hw;
uint16_t gid_pt_rsp_size;
+ struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_gid_pt(vha, list);
gid_data = NULL;
gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
+
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = GID_PT_REQ_SIZE;
+ arg.rsp_size = gid_pt_rsp_size;
+ arg.nport_handle = NPH_SNS;
+
/* Issue GID_PT */
/* Prepare common MS IOCB */
- ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GID_PT_REQ_SIZE,
- gid_pt_rsp_size);
+ ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
@@ -344,15 +359,22 @@
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct qla_hw_data *ha = vha->hw;
+ struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_gpn_id(vha, list);
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = GPN_ID_REQ_SIZE;
+ arg.rsp_size = GPN_ID_RSP_SIZE;
+ arg.nport_handle = NPH_SNS;
+
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Issue GPN_ID */
/* Prepare common MS IOCB */
- ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GPN_ID_REQ_SIZE,
- GPN_ID_RSP_SIZE);
+ ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
@@ -406,15 +428,22 @@
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
+ struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_gnn_id(vha, list);
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = GNN_ID_REQ_SIZE;
+ arg.rsp_size = GNN_ID_RSP_SIZE;
+ arg.nport_handle = NPH_SNS;
+
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Issue GNN_ID */
/* Prepare common MS IOCB */
- ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GNN_ID_REQ_SIZE,
- GNN_ID_RSP_SIZE);
+ ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
@@ -473,14 +502,21 @@
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
+ struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_rft_id(vha);
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = RFT_ID_REQ_SIZE;
+ arg.rsp_size = RFT_ID_RSP_SIZE;
+ arg.nport_handle = NPH_SNS;
+
/* Issue RFT_ID */
/* Prepare common MS IOCB */
- ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFT_ID_REQ_SIZE,
- RFT_ID_RSP_SIZE);
+ ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
@@ -526,6 +562,7 @@
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
+ struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
ql_dbg(ql_dbg_disc, vha, 0x2046,
@@ -533,10 +570,16 @@
return (QLA_SUCCESS);
}
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = RFF_ID_REQ_SIZE;
+ arg.rsp_size = RFF_ID_RSP_SIZE;
+ arg.nport_handle = NPH_SNS;
+
/* Issue RFF_ID */
/* Prepare common MS IOCB */
- ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFF_ID_REQ_SIZE,
- RFF_ID_RSP_SIZE);
+ ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
@@ -584,14 +627,21 @@
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
+ struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_rnn_id(vha);
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = RNN_ID_REQ_SIZE;
+ arg.rsp_size = RNN_ID_RSP_SIZE;
+ arg.nport_handle = NPH_SNS;
+
/* Issue RNN_ID */
/* Prepare common MS IOCB */
- ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RNN_ID_REQ_SIZE,
- RNN_ID_RSP_SIZE);
+ ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
@@ -651,6 +701,7 @@
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
+ struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
ql_dbg(ql_dbg_disc, vha, 0x2050,
@@ -658,10 +709,17 @@
return (QLA_SUCCESS);
}
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = 0;
+ arg.rsp_size = RSNN_NN_RSP_SIZE;
+ arg.nport_handle = NPH_SNS;
+
/* Issue RSNN_NN */
/* Prepare common MS IOCB */
/* Request size adjusted after CT preparation */
- ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
+ ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
@@ -1103,7 +1161,7 @@
*
* Returns 0 on success.
*/
-static int
+int
qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
{
int ret, rval;
@@ -2425,15 +2483,22 @@
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
+ struct ct_arg arg;
if (!IS_IIDMA_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = GFPN_ID_REQ_SIZE;
+ arg.rsp_size = GFPN_ID_RSP_SIZE;
+ arg.nport_handle = NPH_SNS;
+
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Issue GFPN_ID */
/* Prepare common MS IOCB */
- ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFPN_ID_REQ_SIZE,
- GFPN_ID_RSP_SIZE);
+ ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
@@ -2471,36 +2536,6 @@
return (rval);
}
-static inline void *
-qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size,
- uint32_t rsp_size)
-{
- struct ct_entry_24xx *ct_pkt;
- struct qla_hw_data *ha = vha->hw;
- ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
- memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
-
- ct_pkt->entry_type = CT_IOCB_TYPE;
- ct_pkt->entry_count = 1;
- ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
- ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
- ct_pkt->cmd_dsd_count = cpu_to_le16(1);
- ct_pkt->rsp_dsd_count = cpu_to_le16(1);
- ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
- ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
-
- ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
- ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
- ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
-
- ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
- ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
- ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
- ct_pkt->vp_index = vha->vp_idx;
-
- return ct_pkt;
-}
-
static inline struct ct_sns_req *
qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
@@ -2530,9 +2565,10 @@
int rval;
uint16_t i;
struct qla_hw_data *ha = vha->hw;
- ms_iocb_entry_t *ms_pkt;
+ ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
+ struct ct_arg arg;
if (!IS_IIDMA_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
@@ -2543,11 +2579,17 @@
if (rval)
return rval;
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = GPSC_REQ_SIZE;
+ arg.rsp_size = GPSC_RSP_SIZE;
+ arg.nport_handle = vha->mgmt_svr_loop_id;
+
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Issue GFPN_ID */
/* Prepare common MS IOCB */
- ms_pkt = qla24xx_prep_ms_fm_iocb(vha, GPSC_REQ_SIZE,
- GPSC_RSP_SIZE);
+ ms_pkt = qla24xx_prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
@@ -2641,6 +2683,7 @@
struct ct_sns_rsp *ct_rsp;
struct qla_hw_data *ha = vha->hw;
uint8_t fcp_scsi_features = 0;
+ struct ct_arg arg;
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Set default FC4 Type as UNKNOWN so the default is to
@@ -2651,9 +2694,15 @@
if (!IS_FWI2_CAPABLE(ha))
continue;
+ arg.iocb = ha->ms_iocb;
+ arg.req_dma = ha->ct_sns_dma;
+ arg.rsp_dma = ha->ct_sns_dma;
+ arg.req_size = GFF_ID_REQ_SIZE;
+ arg.rsp_size = GFF_ID_RSP_SIZE;
+ arg.nport_handle = NPH_SNS;
+
/* Prepare common MS IOCB */
- ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE,
- GFF_ID_RSP_SIZE);
+ ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
@@ -2692,3 +2741,499 @@
break;
}
}
+
+/* GID_PN completion processing. */
+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);
+
+ if (ea->sp->gen2 != fcport->login_gen) {
+ /* PLOGI/PRLI/LOGO came in while cmd was out.*/
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%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;
+ }
+
+ if (!ea->rc) {
+ if (ea->sp->gen1 == fcport->rscn_gen) {
+ fcport->scan_state = QLA_FCPORT_FOUND;
+ fcport->flags |= FCF_FABRIC_DEVICE;
+
+ if (fcport->d_id.b24 == ea->id.b24) {
+ /* cable plugged into the same place */
+ switch (vha->host->active_mode) {
+ case MODE_TARGET:
+ /* no-op. let the other guy login to us.*/
+ break;
+ case MODE_INITIATOR:
+ case MODE_DUAL:
+ default:
+ if (atomic_read(&fcport->state) == FCS_ONLINE)
+ break;
+ qla24xx_post_gnl_work(vha, fcport);
+ break;
+ }
+ } else { /* fcport->d_id.b24 != ea->id.b24 */
+ fcport->d_id.b24 = ea->id.b24;
+
+ if (fcport->deleted == QLA_SESS_DELETED)
+ qlt_schedule_sess_for_deletion(fcport, true);
+ }
+ } else { /* ea->sp->gen1 != fcport->rscn_gen */
+ /* rscn came in while cmd was out */
+ qla24xx_post_gidpn_work(vha, fcport);
+ }
+ } else { /* ea->rc */
+ /* cable pulled */
+ if (ea->sp->gen1 == fcport->rscn_gen) {
+ if (ea->sp->gen2 == fcport->login_gen)
+ qlt_schedule_sess_for_deletion(fcport, true);
+ else
+ qla24xx_fcport_handle_login(vha, fcport);
+ } else
+ qla24xx_post_gidpn_work(vha, fcport);
+ }
+} /* gidpn_event */
+
+void qla2x00_async_gidpn_sp_done(void *v, void *s, int res)
+{
+ struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
+ struct srb *sp = (struct srb *)s;
+ fc_port_t *fcport = sp->fcport;
+ u8 *id = fcport->ct_desc.ct_sns->p.rsp.rsp.gid_pn.port_id;
+ struct event_arg ea;
+
+ fcport->flags &= ~FCF_ASYNC_SENT;
+
+ memset(&ea, 0, sizeof(ea));
+ ea.fcport = fcport;
+ ea.id.b.domain = id[0];
+ ea.id.b.area = id[1];
+ ea.id.b.al_pa = id[2];
+ ea.sp = sp;
+ ea.rc = res;
+ ea.event = FCME_GIDPN_DONE;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async done-%s res %x, WWPN %8phC ID %3phC \n",
+ sp->name, res, fcport->port_name, id);
+
+ qla2x00_fcport_event_handler(vha, &ea);
+
+ sp->free(vha, sp);
+}
+
+int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
+{
+ int rval = QLA_FUNCTION_FAILED;
+ struct ct_sns_req *ct_req;
+ srb_t *sp;
+
+ fcport->flags |= FCF_ASYNC_SENT;
+ fcport->disc_state = DSC_GID_PN;
+ fcport->scan_state = QLA_FCPORT_SCAN;
+ sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_CT_PTHRU_CMD;
+ sp->name = "gidpn";
+ 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, GID_PN_CMD,
+ GID_PN_RSP_SIZE);
+
+ /* GIDPN req */
+ memcpy(ct_req->req.gid_pn.port_name, fcport->port_name,
+ WWN_SIZE);
+
+ /* req & rsp use the same buffer */
+ 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 = GID_PN_REQ_SIZE;
+ sp->u.iocb_cmd.u.ctarg.rsp_size = GID_PN_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+ sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+ sp->done = qla2x00_async_gidpn_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+ 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);
+ return rval;
+
+done_free_sp:
+ sp->free(vha, sp);
+done:
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ return rval;
+}
+
+
+int qla24xx_post_gidpn_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+ struct qla_work_evt *e;
+
+ if ((atomic_read(&vha->loop_state) != LOOP_READY) ||
+ test_bit(UNLOADING, &vha->dpc_flags))
+ return 0;
+
+ e = qla2x00_alloc_work(vha, QLA_EVT_GIDPN);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.fcport.fcport = fcport;
+ return qla2x00_post_work(vha, e);
+}
+
+int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+ struct qla_work_evt *e;
+ e = qla2x00_alloc_work(vha, QLA_EVT_GPSC);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.fcport.fcport = fcport;
+ return qla2x00_post_work(vha, e);
+}
+
+void qla24xx_async_gpsc_sp_done(void *v, void *s, int res)
+{
+ struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
+ struct qla_hw_data *ha = vha->hw;
+ struct srb *sp = (struct srb *)s;
+ fc_port_t *fcport = sp->fcport;
+ struct ct_sns_rsp *ct_rsp;
+ struct event_arg ea;
+
+ ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async done-%s res %x, WWPN %8phC \n",
+ sp->name, res, fcport->port_name);
+
+ fcport->flags &= ~FCF_ASYNC_SENT;
+
+ if (res == (DID_ERROR << 16)) {
+ /* entry status error */
+ goto done;
+ } else if (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");
+ ha->flags.gpsc_supported = 0;
+ res = QLA_SUCCESS;
+ }
+ } else {
+ switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
+ case BIT_15:
+ fcport->fp_speed = PORT_SPEED_1GB;
+ break;
+ case BIT_14:
+ fcport->fp_speed = PORT_SPEED_2GB;
+ break;
+ case BIT_13:
+ fcport->fp_speed = PORT_SPEED_4GB;
+ break;
+ case BIT_12:
+ fcport->fp_speed = PORT_SPEED_10GB;
+ break;
+ case BIT_11:
+ fcport->fp_speed = PORT_SPEED_8GB;
+ break;
+ case BIT_10:
+ fcport->fp_speed = PORT_SPEED_16GB;
+ break;
+ case BIT_8:
+ fcport->fp_speed = PORT_SPEED_32GB;
+ 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));
+ }
+done:
+ memset(&ea, 0, sizeof(ea));
+ ea.event = FCME_GPSC_DONE;
+ ea.rc = res;
+ ea.fcport = fcport;
+ qla2x00_fcport_event_handler(vha, &ea);
+
+ sp->free(vha, sp);
+}
+
+int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
+{
+ int rval = QLA_FUNCTION_FAILED;
+ struct ct_sns_req *ct_req;
+ srb_t *sp;
+
+ fcport->flags |= FCF_ASYNC_SENT;
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_CT_PTHRU_CMD;
+ sp->name = "gpsc";
+ 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 = qla24xx_prep_ct_fm_req(fcport->ct_desc.ct_sns, GPSC_CMD,
+ GPSC_RSP_SIZE);
+
+ /* GPSC req */
+ memcpy(ct_req->req.gpsc.port_name, fcport->port_name,
+ WWN_SIZE);
+
+ 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 = GPSC_REQ_SIZE;
+ sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id;
+
+ sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+ sp->done = qla24xx_async_gpsc_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+ 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);
+ return rval;
+
+done_free_sp:
+ sp->free(vha, sp);
+done:
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ return rval;
+}
+
+int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
+{
+ struct qla_work_evt *e;
+
+ if (test_bit(UNLOADING, &vha->dpc_flags))
+ return 0;
+
+ e = qla2x00_alloc_work(vha, QLA_EVT_GPNID);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.gpnid.id = *id;
+ return qla2x00_post_work(vha, e);
+}
+
+void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t *sp)
+{
+ if (sp->u.iocb_cmd.u.ctarg.req) {
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt),
+ sp->u.iocb_cmd.u.ctarg.req,
+ sp->u.iocb_cmd.u.ctarg.req_dma);
+ sp->u.iocb_cmd.u.ctarg.req = NULL;
+ }
+ if (sp->u.iocb_cmd.u.ctarg.rsp) {
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt),
+ sp->u.iocb_cmd.u.ctarg.rsp,
+ sp->u.iocb_cmd.u.ctarg.rsp_dma);
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+ }
+
+ sp->free(vha, sp);
+}
+
+void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+ fc_port_t *fcport;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1);
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+ if (fcport) {
+ /* cable moved. just plugged in */
+ fcport->rscn_gen++;
+ fcport->d_id = ea->id;
+ fcport->scan_state = QLA_FCPORT_FOUND;
+ fcport->flags |= FCF_FABRIC_DEVICE;
+
+ qlt_schedule_sess_for_deletion(fcport, true);
+ } else {
+ /* create new fcport */
+ qla24xx_post_newsess_work(vha, &ea->id, ea->port_name, NULL);
+ }
+}
+
+void qla2x00_async_gpnid_sp_done(void *v, void *s, int res)
+{
+ struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
+ struct srb *sp = (struct srb *)s;
+ struct ct_sns_req *ct_req =
+ (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
+ struct ct_sns_rsp *ct_rsp =
+ (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
+ 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);
+
+ memset(&ea, 0, sizeof(ea));
+ memcpy(ea.port_name, ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
+ ea.sp = sp;
+ ea.id.b.domain = ct_req->req.port_id.port_id[0];
+ ea.id.b.area = ct_req->req.port_id.port_id[1];
+ ea.id.b.al_pa = ct_req->req.port_id.port_id[2];
+ ea.rc = res;
+ ea.event = FCME_GPNID_DONE;
+
+ qla2x00_fcport_event_handler(vha, &ea);
+
+ e = qla2x00_alloc_work(vha, QLA_EVT_GPNID_DONE);
+ if (!e) {
+ /* please ignore kernel warning. otherwise, we have mem leak. */
+ if (sp->u.iocb_cmd.u.ctarg.req) {
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt),
+ sp->u.iocb_cmd.u.ctarg.req,
+ sp->u.iocb_cmd.u.ctarg.req_dma);
+ sp->u.iocb_cmd.u.ctarg.req = NULL;
+ }
+ if (sp->u.iocb_cmd.u.ctarg.rsp) {
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt),
+ sp->u.iocb_cmd.u.ctarg.rsp,
+ sp->u.iocb_cmd.u.ctarg.rsp_dma);
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+ }
+
+ sp->free(vha, sp);
+ return;
+ }
+
+ e->u.iosb.sp = sp;
+ qla2x00_post_work(vha, e);
+}
+
+/* Get WWPN with Nport ID. */
+int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
+{
+ int rval = QLA_FUNCTION_FAILED;
+ struct ct_sns_req *ct_req;
+ srb_t *sp;
+ struct ct_sns_pkt *ct_sns;
+
+ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ sp->type = SRB_CT_PTHRU_CMD;
+ sp->name = "gpnid";
+ qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+ sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+ 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");
+ goto done_free_sp;
+ }
+
+ sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
+ 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");
+ goto done_free_sp;
+ }
+
+ ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
+ memset(ct_sns, 0, sizeof(*ct_sns));
+
+ ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
+ /* CT_IU preamble */
+ ct_req = qla2x00_prep_ct_req(ct_sns, GPN_ID_CMD, GPN_ID_RSP_SIZE);
+
+ /* GPN_ID req */
+ ct_req->req.port_id.port_id[0] = id->b.domain;
+ ct_req->req.port_id.port_id[1] = id->b.area;
+ ct_req->req.port_id.port_id[2] = id->b.al_pa;
+
+ sp->u.iocb_cmd.u.ctarg.req_size = GPN_ID_REQ_SIZE;
+ sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_ID_RSP_SIZE;
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+ sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
+ sp->done = qla2x00_async_gpnid_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+ 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);
+ return rval;
+
+done_free_sp:
+ if (sp->u.iocb_cmd.u.ctarg.req) {
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt),
+ sp->u.iocb_cmd.u.ctarg.req,
+ sp->u.iocb_cmd.u.ctarg.req_dma);
+ sp->u.iocb_cmd.u.ctarg.req = NULL;
+ }
+ if (sp->u.iocb_cmd.u.ctarg.rsp) {
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt),
+ sp->u.iocb_cmd.u.ctarg.rsp,
+ sp->u.iocb_cmd.u.ctarg.rsp_dma);
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+ }
+
+ sp->free(vha, sp);
+done:
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 30c840d..857fa09 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -30,15 +30,15 @@
static int qla2x00_configure_loop(scsi_qla_host_t *);
static int qla2x00_configure_local_loop(scsi_qla_host_t *);
static int qla2x00_configure_fabric(scsi_qla_host_t *);
-static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *, struct list_head *);
-static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
- uint16_t *);
-
+static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *);
static int qla2x00_restart_isp(scsi_qla_host_t *);
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 void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
+ struct event_arg *);
/* SRB Extensions ---------------------------------------------------------- */
@@ -47,8 +47,8 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
{
srb_t *sp = (srb_t *)__data;
struct srb_iocb *iocb;
- fc_port_t *fcport = sp->fcport;
- struct qla_hw_data *ha = fcport->vha->hw;
+ scsi_qla_host_t *vha = (scsi_qla_host_t *)sp->vha;
+ struct qla_hw_data *ha = vha->hw;
struct req_que *req;
unsigned long flags;
@@ -57,7 +57,7 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
req->outstanding_cmds[sp->handle] = NULL;
iocb = &sp->u.iocb_cmd;
iocb->timeout(sp);
- sp->free(fcport->vha, sp);
+ sp->free(vha, sp);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -94,29 +94,47 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
return tmo;
}
-static void
+void
qla2x00_async_iocb_timeout(void *data)
{
srb_t *sp = (srb_t *)data;
fc_port_t *fcport = sp->fcport;
+ struct srb_iocb *lio = &sp->u.iocb_cmd;
+ struct event_arg ea;
ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
- "Async-%s timeout - hdl=%x portid=%02x%02x%02x.\n",
+ "Async-%s timeout - hdl=%x portid=%02x%02x%02x %8phC.\n",
sp->name, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa);
+ fcport->d_id.b.al_pa, fcport->port_name);
- fcport->flags &= ~FCF_ASYNC_SENT;
- if (sp->type == SRB_LOGIN_CMD) {
- struct srb_iocb *lio = &sp->u.iocb_cmd;
- qla2x00_post_async_logout_work(fcport->vha, fcport, NULL);
+ if (fcport)
+ fcport->flags &= ~FCF_ASYNC_SENT;
+
+ switch (sp->type) {
+ case SRB_LOGIN_CMD:
/* Retry as needed. */
lio->u.logio.data[0] = MBS_COMMAND_ERROR;
lio->u.logio.data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
QLA_LOGIO_LOGIN_RETRIED : 0;
- qla2x00_post_async_login_done_work(fcport->vha, fcport,
- lio->u.logio.data);
- } else if (sp->type == SRB_LOGOUT_CMD) {
+ memset(&ea, 0, sizeof(ea));
+ ea.event = FCME_PLOGI_DONE;
+ ea.fcport = sp->fcport;
+ ea.data[0] = lio->u.logio.data[0];
+ ea.data[1] = lio->u.logio.data[1];
+ ea.sp = sp;
+
+ qla24xx_handle_plogi_done_event(fcport->vha, &ea);
+ break;
+ case SRB_LOGOUT_CMD:
qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
+ break;
+ case SRB_CT_PTHRU_CMD:
+ case SRB_MB_IOCB:
+ case SRB_NACK_PLOGI:
+ case SRB_NACK_PRLI:
+ case SRB_NACK_LOGO:
+ sp->done(sp->vha, sp, QLA_FUNCTION_TIMEOUT);
+ break;
}
}
@@ -126,10 +144,25 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
srb_t *sp = (srb_t *)ptr;
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
+ struct event_arg ea;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%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_PLOGI_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);
+ }
- if (!test_bit(UNLOADING, &vha->dpc_flags))
- qla2x00_post_async_login_done_work(sp->fcport->vha, sp->fcport,
- lio->u.logio.data);
sp->free(sp->fcport->vha, sp);
}
@@ -139,13 +172,21 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
{
srb_t *sp;
struct srb_iocb *lio;
- int rval;
+ int rval = QLA_FUNCTION_FAILED;
+
+ if (!vha->flags.online)
+ goto done;
+
+ 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))
+ goto done;
- rval = QLA_FUNCTION_FAILED;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
+ fcport->flags |= FCF_ASYNC_SENT;
sp->type = SRB_LOGIN_CMD;
sp->name = "login";
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
@@ -165,8 +206,8 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
}
ql_dbg(ql_dbg_disc, vha, 0x2072,
- "Async-login - hdl=%x, loopid=%x portid=%02x%02x%02x "
- "retries=%d.\n", sp->handle, fcport->loop_id,
+ "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x "
+ "retries=%d.\n", fcport->port_name, sp->handle, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
fcport->login_retry);
return rval;
@@ -174,6 +215,7 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
done_free_sp:
sp->free(fcport->vha, sp);
done:
+ fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
}
@@ -184,6 +226,7 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
+ sp->fcport->flags &= ~FCF_ASYNC_SENT;
if (!test_bit(UNLOADING, &vha->dpc_flags))
qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport,
lio->u.logio.data);
@@ -198,6 +241,7 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
int rval;
rval = QLA_FUNCTION_FAILED;
+ fcport->flags |= FCF_ASYNC_SENT;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
@@ -214,14 +258,16 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
goto done_free_sp;
ql_dbg(ql_dbg_disc, vha, 0x2070,
- "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
+ "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x %8phC.\n",
sp->handle, fcport->loop_id, fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa);
+ fcport->d_id.b.area, fcport->d_id.b.al_pa,
+ fcport->port_name);
return rval;
done_free_sp:
sp->free(fcport->vha, sp);
done:
+ sp->fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
}
@@ -276,6 +322,792 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
return rval;
}
+void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
+ struct event_arg *ea)
+{
+ fc_port_t *fcport, *conflict_fcport;
+ struct get_name_list_extended *e;
+ u16 i, n, found = 0, loop_id;
+ port_id_t id;
+ u64 wwn;
+ u8 opt = 0;
+
+ 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);
+ }
+ return;
+ }
+
+ if (fcport->last_rscn_gen != fcport->rscn_gen) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%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);
+ return;
+ }
+
+
+ n = ea->data[0]/sizeof(struct get_name_list_extended);
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%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,
+ fcport->d_id.b.al_pa, fcport->loop_id);
+
+ for (i = 0; i < n; i++) {
+ e = &vha->gnl.l[i];
+ wwn = wwn_to_u64(e->port_name);
+
+ if (memcmp((u8 *)&wwn, fcport->port_name, WWN_SIZE))
+ continue;
+
+ found = 1;
+ id.b.domain = e->port_id[2];
+ id.b.area = e->port_id[1];
+ id.b.al_pa = e->port_id[0];
+ id.b.rsvd_1 = 0;
+
+ 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);
+
+ if ((id.b24 != fcport->d_id.b24) ||
+ ((fcport->loop_id != FC_NO_LOOP_ID) &&
+ (fcport->loop_id != loop_id))) {
+ qlt_schedule_sess_for_deletion(fcport, true);
+ return;
+ }
+
+ fcport->loop_id = loop_id;
+
+ wwn = wwn_to_u64(fcport->port_name);
+ qlt_find_sess_invalidate_other(vha, wwn,
+ id, loop_id, &conflict_fcport);
+
+ if (conflict_fcport) {
+ /* Another share fcport share the same loop_id & nport id.
+ Conflict fcport needs to finish cleanup before this
+ fcport can proceed to login.
+ */
+ conflict_fcport->conflict = fcport;
+ fcport->login_pause = 1;
+ }
+
+ switch (e->current_login_state) {
+ case DSC_LS_PORT_UNAVAIL:
+ 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);
+ qla24xx_fcport_handle_login(vha, fcport);
+ break;
+
+ case DSC_LS_PRLI_COMP:
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post gpdb\n",
+ __func__, __LINE__, fcport->port_name);
+ opt = PDO_FORCE_ADISC;
+ qla24xx_post_gpdb_work(vha, fcport, opt);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!found) {
+ /* fw has no record of this port */
+ if (fcport->loop_id == FC_NO_LOOP_ID) {
+ qla2x00_find_new_loop_id(vha, fcport);
+ fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
+ } else {
+ for (i = 0; i < n; i++) {
+ e = &vha->gnl.l[i];
+ id.b.domain = e->port_id[0];
+ id.b.area = e->port_id[1];
+ id.b.al_pa = e->port_id[2];
+ id.b.rsvd_1 = 0;
+ loop_id = le16_to_cpu(e->nport_handle);
+
+ if (fcport->d_id.b24 == id.b24) {
+ conflict_fcport =
+ qla2x00_find_fcport_by_wwpn(vha,
+ e->port_name, 0);
+ qlt_schedule_sess_for_deletion
+ (conflict_fcport, true);
+ }
+
+ if (fcport->loop_id == loop_id) {
+ /* FW already picked this loop id for another fcport */
+ qla2x00_find_new_loop_id(vha, fcport);
+ }
+ }
+ }
+ qla24xx_fcport_handle_login(vha, fcport);
+ }
+} /* gnl_event */
+
+
+static void
+qla24xx_async_gnl_sp_done(void *v, void *s, int res)
+{
+ struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
+ struct srb *sp = (struct srb *)s;
+ unsigned long flags;
+ struct fc_port *fcport = NULL, *tf;
+ u16 i, n = 0, loop_id;
+ struct event_arg ea;
+ struct get_name_list_extended *e;
+ u64 wwn;
+ struct list_head h;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "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]);
+
+ memset(&ea, 0, sizeof(ea));
+ ea.sp = sp;
+ ea.rc = res;
+ ea.event = FCME_GNL_DONE;
+
+ if (sp->u.iocb_cmd.u.mbx.in_mb[1] >=
+ sizeof(struct get_name_list_extended)) {
+ n = sp->u.iocb_cmd.u.mbx.in_mb[1] /
+ sizeof(struct get_name_list_extended);
+ ea.data[0] = sp->u.iocb_cmd.u.mbx.in_mb[1]; /* amnt xfered */
+ }
+
+ for (i = 0; i < n; i++) {
+ e = &vha->gnl.l[i];
+ loop_id = le16_to_cpu(e->nport_handle);
+ /* mask out reserve bit */
+ loop_id = (loop_id & 0x7fff);
+ 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,
+ "%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,
+ (loop_id & 0x7fff));
+ }
+
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ vha->gnl.sent = 0;
+
+ INIT_LIST_HEAD(&h);
+ fcport = tf = NULL;
+ if (!list_empty(&vha->gnl.fcports))
+ list_splice_init(&vha->gnl.fcports, &h);
+
+ list_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
+ list_del_init(&fcport->gnl_entry);
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ ea.fcport = fcport;
+
+ qla2x00_fcport_event_handler(vha, &ea);
+ }
+
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+ sp->free(vha, sp);
+}
+
+int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+ srb_t *sp;
+ struct srb_iocb *mbx;
+ int rval = QLA_FUNCTION_FAILED;
+ unsigned long flags;
+ u16 *mb;
+
+ if (!vha->flags.online)
+ goto done;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-gnlist WWPN %8phC \n",
+ fcport->port_name);
+
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ fcport->flags |= FCF_ASYNC_SENT;
+ fcport->disc_state = DSC_GNL;
+ fcport->last_rscn_gen = fcport->rscn_gen;
+ fcport->last_login_gen = fcport->login_gen;
+
+ list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports);
+ if (vha->gnl.sent) {
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+ rval = QLA_SUCCESS;
+ goto done;
+ }
+ vha->gnl.sent = 1;
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+ sp->type = SRB_MB_IOCB;
+ sp->name = "gnlist";
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
+
+ qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
+
+ mb = sp->u.iocb_cmd.u.mbx.out_mb;
+ mb[0] = MBC_PORT_NODE_NAME_LIST;
+ mb[1] = BIT_2 | BIT_3;
+ mb[2] = MSW(vha->gnl.ldma);
+ mb[3] = LSW(vha->gnl.ldma);
+ mb[6] = MSW(MSD(vha->gnl.ldma));
+ mb[7] = LSW(MSD(vha->gnl.ldma));
+ mb[8] = vha->gnl.size;
+ mb[9] = vha->vp_idx;
+
+ mbx = &sp->u.iocb_cmd;
+ mbx->timeout = qla2x00_async_iocb_timeout;
+
+ sp->done = qla24xx_async_gnl_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+ 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);
+
+ return rval;
+
+done_free_sp:
+ sp->free(fcport->vha, sp);
+done:
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ return rval;
+}
+
+int qla24xx_post_gnl_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+ struct qla_work_evt *e;
+ e = qla2x00_alloc_work(vha, QLA_EVT_GNL);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.fcport.fcport = fcport;
+ return qla2x00_post_work(vha, e);
+}
+
+
+void qla24xx_async_gpdb_sp_done(void *v, void *s, int res)
+{
+ struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
+ struct srb *sp = (struct srb *)s;
+ struct qla_hw_data *ha = vha->hw;
+ uint64_t zero = 0;
+ struct port_database_24xx *pd;
+ fc_port_t *fcport = sp->fcport;
+ u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
+ int rval = QLA_SUCCESS;
+ struct event_arg ea;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async done-%s res %x, WWPN %8phC mb[1]=%x mb[2]=%x \n",
+ sp->name, res, fcport->port_name, mb[1], mb[2]);
+
+ fcport->flags &= ~FCF_ASYNC_SENT;
+
+ if (res) {
+ rval = res;
+ goto gpd_error_out;
+ }
+
+ pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
+
+ /* 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);
+ rval = QLA_FUNCTION_FAILED;
+ goto gpd_error_out;
+ }
+
+ if (fcport->loop_id == FC_NO_LOOP_ID ||
+ (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
+ memcmp(fcport->port_name, pd->port_name, 8))) {
+
+ /* We lost the device mid way. */
+ rval = QLA_NOT_LOGGED_IN;
+ goto gpd_error_out;
+ }
+
+ /* Names are little-endian. */
+ memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
+
+ /* Get port_id of device. */
+ fcport->d_id.b.domain = pd->port_id[0];
+ fcport->d_id.b.area = pd->port_id[1];
+ 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;
+
+ /* Passback COS information. */
+ fcport->supported_classes = (pd->flags & PDF_CLASS_2) ?
+ FC_COS_CLASS2 : FC_COS_CLASS3;
+
+ if (pd->prli_svc_param_word_3[0] & BIT_7) {
+ fcport->flags |= FCF_CONF_COMP_SUPPORTED;
+ fcport->conf_compl_supported = 1;
+ }
+
+gpd_error_out:
+ memset(&ea, 0, sizeof(ea));
+ ea.event = FCME_GPDB_DONE;
+ ea.rc = rval;
+ ea.fcport = fcport;
+ ea.sp = sp;
+
+ qla2x00_fcport_event_handler(vha, &ea);
+
+ dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
+ sp->u.iocb_cmd.u.mbx.in_dma);
+
+ sp->free(vha, sp);
+}
+
+static int qla24xx_post_gpdb_work(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
+{
+ struct qla_work_evt *e;
+ e = qla2x00_alloc_work(vha, QLA_EVT_GPDB);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.fcport.fcport = fcport;
+ e->u.fcport.opt = opt;
+ return qla2x00_post_work(vha, e);
+}
+
+int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
+{
+ srb_t *sp;
+ struct srb_iocb *mbx;
+ int rval = QLA_FUNCTION_FAILED;
+ u16 *mb;
+ dma_addr_t pd_dma;
+ struct port_database_24xx *pd;
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!vha->flags.online)
+ goto done;
+
+ fcport->flags |= FCF_ASYNC_SENT;
+ fcport->disc_state = DSC_GPDB;
+
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+ 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");
+ goto done_free_sp;
+ }
+ memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
+
+ sp->type = SRB_MB_IOCB;
+ sp->name = "gpdb";
+ sp->gen1 = fcport->rscn_gen;
+ sp->gen2 = fcport->login_gen;
+ qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
+
+ mb = sp->u.iocb_cmd.u.mbx.out_mb;
+ mb[0] = MBC_GET_PORT_DATABASE;
+ mb[1] = fcport->loop_id;
+ mb[2] = MSW(pd_dma);
+ mb[3] = LSW(pd_dma);
+ mb[6] = MSW(MSD(pd_dma));
+ mb[7] = LSW(MSD(pd_dma));
+ mb[9] = vha->vp_idx;
+ mb[10] = opt;
+
+ mbx = &sp->u.iocb_cmd;
+ mbx->timeout = qla2x00_async_iocb_timeout;
+ mbx->u.mbx.in = (void *)pd;
+ mbx->u.mbx.in_dma = pd_dma;
+
+ sp->done = qla24xx_async_gpdb_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+ 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);
+
+ return rval;
+
+done_free_sp:
+ if (pd)
+ dma_pool_free(ha->s_dma_pool, pd, pd_dma);
+
+ sp->free(vha, sp);
+done:
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ qla24xx_post_gpdb_work(vha, fcport, opt);
+ return rval;
+}
+
+
+void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+ int rval = ea->rc;
+ fc_port_t *fcport = ea->fcport;
+ unsigned long flags;
+
+ fcport->flags &= ~FCF_ASYNC_SENT;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %8phC DS %d LS %d \n",
+ __func__, fcport->port_name, fcport->disc_state,
+ fcport->fw_login_state);
+
+ if (ea->sp->gen2 != fcport->login_gen) {
+ /* target side must have changed it. */
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%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) {
+ qla24xx_post_gidpn_work(vha, fcport);
+ return;
+ }
+
+ if (rval != QLA_SUCCESS) {
+ qlt_schedule_sess_for_deletion(fcport, true);
+ return;
+ }
+
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ ea->fcport->login_gen++;
+ ea->fcport->deleted = 0;
+ vha->fcport_count++;
+ ea->fcport->logout_on_delete = 1;
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+ 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__, fcport->port_name,
+ vha->fcport_count);
+
+ qla24xx_post_upd_fcport_work(vha, fcport);
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post gpsc fcp_cnt %d\n",
+ __func__, __LINE__, fcport->port_name, vha->fcport_count);
+
+ qla24xx_post_gpsc_work(vha, fcport);
+ }
+} /* gpdb event */
+
+
+int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+
+ if (fcport->login_retry == 0)
+ return 0;
+
+ if (fcport->scan_state != QLA_FCPORT_FOUND)
+ return 0;
+
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%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, fcport->conflict,
+ fcport->last_rscn_gen, fcport->rscn_gen,
+ fcport->last_login_gen, fcport->login_gen,
+ fcport->login_retry, fcport->loop_id);
+
+
+ fcport->login_retry--;
+
+ 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 0;
+
+ if (vha->host->active_mode == MODE_TARGET)
+ /* for pure Target Mode. Login will not be initiated */
+ return 0;
+
+ if (fcport->flags & FCF_ASYNC_SENT) {
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+ return 0;
+ }
+
+ 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);
+ qla24xx_async_gnl(vha, fcport);
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%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);
+ }
+ break;
+
+ case DSC_GNL:
+ if (fcport->login_pause) {
+ fcport->last_rscn_gen = fcport->rscn_gen;
+ fcport->last_login_gen = fcport->login_gen;
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+ break;
+ }
+
+ 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);
+
+ 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);
+ fcport->disc_state = DSC_LOGIN_PEND;
+ qla2x00_post_async_login_work(vha, fcport, NULL);
+ }
+
+ break;
+ case DSC_LOGIN_PEND:
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+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);
+
+ if (fcport->flags & FCF_ASYNC_SENT)
+ return;
+
+ switch (fcport->disc_state) {
+ case DSC_DELETED:
+ case DSC_LOGIN_COMPLETE:
+ qla24xx_post_gidpn_work(fcport->vha, fcport);
+ break;
+
+ default:
+ break;
+ }
+}
+
+int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
+ u8 *port_name, void *pla)
+{
+ struct qla_work_evt *e;
+ e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.new_sess.id = *id;
+ e->u.new_sess.pla = pla;
+ memcpy(e->u.new_sess.port_name, port_name, WWN_SIZE);
+
+ return qla2x00_post_work(vha, e);
+}
+
+int qla24xx_handle_delete_done_event(scsi_qla_host_t *vha,
+ struct event_arg *ea)
+{
+ fc_port_t *fcport = ea->fcport;
+
+ if (test_bit(UNLOADING, &vha->dpc_flags))
+ return 0;
+
+ switch (vha->host->active_mode) {
+ case MODE_INITIATOR:
+ case MODE_DUAL:
+ if (fcport->scan_state == QLA_FCPORT_FOUND)
+ qla24xx_fcport_handle_login(vha, fcport);
+ break;
+
+ case MODE_TARGET:
+ default:
+ /* no-op */
+ break;
+ }
+
+ return 0;
+}
+
+
+void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
+ struct event_arg *ea)
+{
+ fc_port_t *fcport = ea->fcport;
+
+ if (fcport->scan_state != QLA_FCPORT_FOUND) {
+ fcport->login_retry++;
+ 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);
+
+ 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;
+
+ if (fcport->flags & FCF_ASYNC_SENT) {
+ fcport->login_retry++;
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+ return;
+ }
+
+ if (fcport->disc_state == DSC_DELETE_PEND) {
+ fcport->login_retry++;
+ return;
+ }
+
+ if (fcport->last_rscn_gen != fcport->rscn_gen) {
+ qla24xx_async_gidpn(vha, fcport);
+ } else {
+ if (fcport->deleted)
+ qla24xx_fcport_handle_login(vha, fcport);
+ else
+ qlt_schedule_sess_for_deletion(fcport, true);
+ }
+}
+
+void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
+ struct event_arg *ea)
+{
+ fc_port_t *fcport;
+ int rc;
+
+ if (ea->fcport && (ea->fcport->chip_reset != vha->hw->chip_reset))
+ qlt_schedule_sess_for_deletion(ea->fcport, true);
+
+
+ switch (ea->event) {
+ case FCME_RELOGIN:
+ if (test_bit(UNLOADING, &vha->dpc_flags))
+ return;
+
+ qla24xx_handle_relogin_event(vha, ea);
+ break;
+
+ case FCME_RSCN:
+ if (test_bit(UNLOADING, &vha->dpc_flags))
+ return;
+
+ fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
+ if (!fcport) {
+ /* 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);
+ }
+ } else {
+ ea->fcport = fcport;
+ qla24xx_handle_rscn_event(fcport, ea);
+ }
+ break;
+ case FCME_GIDPN_DONE:
+ qla24xx_handle_gidpn_event(vha, ea);
+ break;
+ case FCME_GNL_DONE:
+ qla24xx_handle_gnl_done_event(vha, ea);
+ break;
+ case FCME_GPSC_DONE:
+ qla24xx_post_upd_fcport_work(vha, ea->fcport);
+ break;
+ case FCME_PLOGI_DONE: /* Initiator side sent LLIOCB */
+ qla24xx_handle_plogi_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_DELETE_DONE:
+ qla24xx_handle_delete_done_event(vha, ea);
+ break;
+ default:
+ BUG_ON(1);
+ break;
+ }
+}
+
static void
qla2x00_tmf_iocb_timeout(void *data)
{
@@ -441,59 +1273,69 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
return qla24xx_async_abort_cmd(sp);
}
-void
-qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
- uint16_t *data)
+static void
+qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
{
- int rval;
+ port_id_t cid; /* conflict Nport id */
- switch (data[0]) {
+
+ switch (ea->data[0]) {
case MBS_COMMAND_COMPLETE:
/*
* Driver must validate login state - If PRLI not complete,
* force a relogin attempt via implicit LOGO, PLOGI, and PRLI
* requests.
*/
- rval = qla2x00_get_port_database(vha, fcport, 0);
- if (rval == QLA_NOT_LOGGED_IN) {
- fcport->flags &= ~FCF_ASYNC_SENT;
- fcport->flags |= FCF_LOGIN_NEEDED;
- set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
- break;
- }
-
- if (rval != QLA_SUCCESS) {
- qla2x00_post_async_logout_work(vha, fcport, NULL);
- qla2x00_post_async_login_work(vha, fcport, NULL);
- break;
- }
- if (fcport->flags & FCF_FCP2_DEVICE) {
- qla2x00_post_async_adisc_work(vha, fcport, data);
- break;
- }
- qla2x00_update_fcport(vha, fcport);
+ 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);
break;
case MBS_COMMAND_ERROR:
- fcport->flags &= ~FCF_ASYNC_SENT;
- if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
+ ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d %8phC cmd error %x\n",
+ __func__, __LINE__, ea->fcport->port_name, ea->data[1]);
+
+ ea->fcport->flags &= ~FCF_ASYNC_SENT;
+ ea->fcport->disc_state = DSC_LOGIN_FAILED;
+ if (ea->data[1] & QLA_LOGIO_LOGIN_RETRIED)
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
else
- qla2x00_mark_device_lost(vha, fcport, 1, 0);
- break;
- case MBS_PORT_ID_USED:
- fcport->loop_id = data[1];
- qla2x00_post_async_logout_work(vha, fcport, NULL);
- qla2x00_post_async_login_work(vha, fcport, NULL);
+ qla2x00_mark_device_lost(vha, ea->fcport, 1, 0);
break;
+
+
case MBS_LOOP_ID_USED:
- fcport->loop_id++;
- rval = qla2x00_find_new_loop_id(vha, fcport);
- if (rval != QLA_SUCCESS) {
- fcport->flags &= ~FCF_ASYNC_SENT;
- qla2x00_mark_device_lost(vha, fcport, 1, 0);
- break;
+ /* data[1] = IO PARAM 1 = nport ID */
+ cid.b.domain = (ea->iop[1] >> 16) & 0xff;
+ cid.b.area = (ea->iop[1] >> 8) & 0xff;
+ 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);
+
+ if (IS_SW_RESV_ADDR(cid)) {
+ set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
+ ea->fcport->loop_id = FC_NO_LOOP_ID;
+ } else {
+ qla2x00_clear_loop_id(ea->fcport);
}
- qla2x00_post_async_login_work(vha, fcport, NULL);
+ 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);
+
+ qla2x00_clear_loop_id(ea->fcport);
+ qla24xx_post_gidpn_work(vha, ea->fcport);
break;
}
return;
@@ -503,10 +1345,9 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
uint16_t *data)
{
- /* Don't re-login in target mode */
- if (!fcport->tgt_session)
- qla2x00_mark_device_lost(vha, fcport, 1, 0);
+ qla2x00_mark_device_lost(vha, fcport, 1, 0);
qlt_logo_completion_handler(fcport, data[0]);
+ fcport->login_gen++;
return;
}
@@ -709,7 +1550,8 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
}
}
- if (qla_ini_mode_enabled(vha))
+ if (qla_ini_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha))
rval = qla2x00_init_rings(vha);
ha->flags.chip_reset_done = 1;
@@ -2998,12 +3840,39 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
fcport->supported_classes = FC_COS_UNSPECIFIED;
+ fcport->ct_desc.ct_sns = dma_alloc_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt), &fcport->ct_desc.ct_sns_dma,
+ GFP_ATOMIC);
+ fcport->disc_state = DSC_DELETED;
+ fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
+ fcport->deleted = QLA_SESS_DELETED;
+ fcport->login_retry = vha->hw->login_retry_count;
+ fcport->login_retry = 5;
+ fcport->logout_on_delete = 1;
+
+ if (!fcport->ct_desc.ct_sns) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Failed to allocate ct_sns request.\n");
+ kfree(fcport);
+ fcport = NULL;
+ }
+ INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn);
+ INIT_LIST_HEAD(&fcport->gnl_entry);
+ INIT_LIST_HEAD(&fcport->list);
+
return fcport;
}
void
qla2x00_free_fcport(fc_port_t *fcport)
{
+ if (fcport->ct_desc.ct_sns) {
+ dma_free_coherent(&fcport->vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt), fcport->ct_desc.ct_sns,
+ fcport->ct_desc.ct_sns_dma);
+
+ fcport->ct_desc.ct_sns = NULL;
+ }
kfree(fcport);
}
@@ -3343,6 +4212,8 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
}
}
+
+/* qla2x00_reg_remote_port is reserved for Initiator Mode only.*/
static void
qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
{
@@ -3396,20 +4267,46 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
{
fcport->vha = vha;
+ if (IS_SW_RESV_ADDR(fcport->d_id))
+ return;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %8phC \n",
+ __func__, fcport->port_name);
+
if (IS_QLAFX00(vha->hw)) {
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
goto reg_port;
}
fcport->login_retry = 0;
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+ fcport->disc_state = DSC_LOGIN_COMPLETE;
+ fcport->deleted = 0;
+ fcport->logout_on_delete = 1;
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
qla2x00_iidma_fcport(vha, fcport);
qla24xx_update_fcport_fcp_prio(vha, fcport);
reg_port:
- if (qla_ini_mode_enabled(vha))
+ switch (vha->host->active_mode) {
+ case MODE_INITIATOR:
+ qla2x00_reg_remote_port(vha, fcport);
+ break;
+ case MODE_TARGET:
+ if (!vha->vha_tgt.qla_tgt->tgt_stop &&
+ !vha->vha_tgt.qla_tgt->tgt_stopped)
+ qlt_fc_port_added(vha, fcport);
+ break;
+ case MODE_DUAL:
qla2x00_reg_remote_port(vha, fcport);
+ if (!vha->vha_tgt.qla_tgt->tgt_stop &&
+ !vha->vha_tgt.qla_tgt->tgt_stopped)
+ qlt_fc_port_added(vha, fcport);
+ break;
+ default:
+ break;
+ }
}
/*
@@ -3427,13 +4324,11 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
qla2x00_configure_fabric(scsi_qla_host_t *vha)
{
int rval;
- fc_port_t *fcport, *fcptemp;
- uint16_t next_loopid;
+ fc_port_t *fcport;
uint16_t mb[MAILBOX_REGISTER_COUNT];
uint16_t loop_id;
LIST_HEAD(new_fcports);
struct qla_hw_data *ha = vha->hw;
- struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
int discovery_gen;
/* If FL port exists, then SNS is present */
@@ -3452,6 +4347,8 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
vha->device_flags |= SWITCH_FOUND;
do {
+ qla2x00_mgmt_svr_login(vha);
+
/* FDMI support. */
if (ql2xfdmienable &&
test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags))
@@ -3498,9 +4395,6 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
}
}
-#define QLA_FCPORT_SCAN 1
-#define QLA_FCPORT_FOUND 2
-
list_for_each_entry(fcport, &vha->vp_fcports, list) {
fcport->scan_state = QLA_FCPORT_SCAN;
}
@@ -3513,169 +4407,18 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
* will be newer than discovery_gen. */
qlt_do_generation_tick(vha, &discovery_gen);
- rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
+ rval = qla2x00_find_all_fabric_devs(vha);
if (rval != QLA_SUCCESS)
break;
- /*
- * Logout all previous fabric devices marked lost, except
- * FCP2 devices.
- */
- list_for_each_entry(fcport, &vha->vp_fcports, list) {
- if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
- break;
-
- if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
- continue;
-
- if (fcport->scan_state == QLA_FCPORT_SCAN) {
- if (qla_ini_mode_enabled(base_vha) &&
- atomic_read(&fcport->state) == FCS_ONLINE) {
- qla2x00_mark_device_lost(vha, fcport,
- ql2xplogiabsentdevice, 0);
- if (fcport->loop_id != FC_NO_LOOP_ID &&
- (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
- fcport->port_type != FCT_INITIATOR &&
- fcport->port_type != FCT_BROADCAST) {
- ha->isp_ops->fabric_logout(vha,
- fcport->loop_id,
- fcport->d_id.b.domain,
- fcport->d_id.b.area,
- fcport->d_id.b.al_pa);
- qla2x00_clear_loop_id(fcport);
- }
- } else if (!qla_ini_mode_enabled(base_vha)) {
- /*
- * In target mode, explicitly kill
- * sessions and log out of devices
- * that are gone, so that we don't
- * end up with an initiator using the
- * wrong ACL (if the fabric recycles
- * an FC address and we have a stale
- * session around) and so that we don't
- * report initiators that are no longer
- * on the fabric.
- */
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077,
- "port gone, logging out/killing session: "
- "%8phC state 0x%x flags 0x%x fc4_type 0x%x "
- "scan_state %d\n",
- fcport->port_name,
- atomic_read(&fcport->state),
- fcport->flags, fcport->fc4_type,
- fcport->scan_state);
- qlt_fc_port_deleted(vha, fcport,
- discovery_gen);
- }
- }
- }
-
- /* Starting free loop ID. */
- next_loopid = ha->min_external_loopid;
-
- /*
- * Scan through our port list and login entries that need to be
- * logged in.
- */
- list_for_each_entry(fcport, &vha->vp_fcports, list) {
- if (atomic_read(&vha->loop_down_timer) ||
- test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
- break;
-
- if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
- (fcport->flags & FCF_LOGIN_NEEDED) == 0)
- continue;
-
- /*
- * If we're not an initiator, skip looking for devices
- * and logging in. There's no reason for us to do it,
- * and it seems to actively cause problems in target
- * mode if we race with the initiator logging into us
- * (we might get the "port ID used" status back from
- * our login command and log out the initiator, which
- * seems to cause havoc).
- */
- if (!qla_ini_mode_enabled(base_vha)) {
- if (fcport->scan_state == QLA_FCPORT_FOUND) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078,
- "port %8phC state 0x%x flags 0x%x fc4_type 0x%x "
- "scan_state %d (initiator mode disabled; skipping "
- "login)\n", fcport->port_name,
- atomic_read(&fcport->state),
- fcport->flags, fcport->fc4_type,
- fcport->scan_state);
- }
- continue;
- }
-
- if (fcport->loop_id == FC_NO_LOOP_ID) {
- fcport->loop_id = next_loopid;
- rval = qla2x00_find_new_loop_id(
- base_vha, fcport);
- if (rval != QLA_SUCCESS) {
- /* Ran out of IDs to use */
- break;
- }
- }
- /* Login and update database */
- qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
- }
/* Exit if out of loop IDs. */
if (rval != QLA_SUCCESS) {
break;
}
- /*
- * Login and add the new devices to our port list.
- */
- list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
- if (atomic_read(&vha->loop_down_timer) ||
- test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
- break;
-
- /*
- * If we're not an initiator, skip looking for devices
- * and logging in. There's no reason for us to do it,
- * and it seems to actively cause problems in target
- * mode if we race with the initiator logging into us
- * (we might get the "port ID used" status back from
- * our login command and log out the initiator, which
- * seems to cause havoc).
- */
- if (qla_ini_mode_enabled(base_vha)) {
- /* Find a new loop ID to use. */
- fcport->loop_id = next_loopid;
- rval = qla2x00_find_new_loop_id(base_vha,
- fcport);
- if (rval != QLA_SUCCESS) {
- /* Ran out of IDs to use */
- break;
- }
-
- /* Login and update database */
- qla2x00_fabric_dev_login(vha, fcport,
- &next_loopid);
- } else {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079,
- "new port %8phC state 0x%x flags 0x%x fc4_type "
- "0x%x scan_state %d (initiator mode disabled; "
- "skipping login)\n",
- fcport->port_name,
- atomic_read(&fcport->state),
- fcport->flags, fcport->fc4_type,
- fcport->scan_state);
- }
-
- list_move_tail(&fcport->list, &vha->vp_fcports);
- }
} while (0);
- /* Free all new device structures not processed. */
- list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
- list_del(&fcport->list);
- qla2x00_free_fcport(fcport);
- }
if (rval) {
ql_dbg(ql_dbg_disc, vha, 0x2068,
@@ -3699,12 +4442,11 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
* Kernel context.
*/
static int
-qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
- struct list_head *new_fcports)
+qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
{
int rval;
uint16_t loop_id;
- fc_port_t *fcport, *new_fcport, *fcptemp;
+ fc_port_t *fcport, *new_fcport;
int found;
sw_info_t *swl;
@@ -3713,6 +4455,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
port_id_t wrap = {}, nxt_d_id;
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+ unsigned long flags;
rval = QLA_SUCCESS;
@@ -3733,9 +4476,8 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
swl = NULL;
} else if (qla2x00_gnn_id(vha, swl) != QLA_SUCCESS) {
swl = NULL;
- } else if (ql2xiidmaenable &&
- qla2x00_gfpn_id(vha, swl) == QLA_SUCCESS) {
- qla2x00_gpsc(vha, swl);
+ } else if (qla2x00_gfpn_id(vha, swl) != QLA_SUCCESS) {
+ swl = NULL;
}
/* If other queries succeeded probe for FC-4 type */
@@ -3797,11 +4539,6 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
ql_log(ql_log_warn, vha, 0x2064,
"SNS scan failed -- assuming "
"zero-entry result.\n");
- list_for_each_entry_safe(fcport, fcptemp,
- new_fcports, list) {
- list_del(&fcport->list);
- qla2x00_free_fcport(fcport);
- }
rval = QLA_SUCCESS;
break;
}
@@ -3844,6 +4581,8 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
new_fcport->fc4_type != FC4_TYPE_UNKNOWN))
continue;
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+
/* Locate matching device in database. */
found = 0;
list_for_each_entry(fcport, &vha->vp_fcports, list) {
@@ -3866,7 +4605,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
*/
if (fcport->d_id.b24 == new_fcport->d_id.b24 &&
(atomic_read(&fcport->state) == FCS_ONLINE ||
- !qla_ini_mode_enabled(base_vha))) {
+ (vha->host->active_mode == MODE_TARGET))) {
break;
}
@@ -3886,7 +4625,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
* Log it out if still logged in and mark it for
* relogin later.
*/
- if (!qla_ini_mode_enabled(base_vha)) {
+ if (qla_tgt_mode_enabled(base_vha)) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080,
"port changed FC ID, %8phC"
" old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n",
@@ -3909,20 +4648,23 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
(fcport->flags & FCF_ASYNC_SENT) == 0 &&
fcport->port_type != FCT_INITIATOR &&
fcport->port_type != FCT_BROADCAST) {
- ha->isp_ops->fabric_logout(vha, fcport->loop_id,
- fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa);
- qla2x00_clear_loop_id(fcport);
+ /* cable moved */
+ fcport->flags |= FCF_DELETE_DEV;
}
break;
}
- if (found)
+ if (found) {
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
continue;
+ }
/* If device was not in our fcports list, then add it. */
new_fcport->scan_state = QLA_FCPORT_FOUND;
- list_add_tail(&new_fcport->list, new_fcports);
+ list_add_tail(&new_fcport->list, &vha->vp_fcports);
+
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
/* Allocate a new replacement fcport. */
nxt_d_id.b24 = new_fcport->d_id.b24;
@@ -3938,6 +4680,47 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
qla2x00_free_fcport(new_fcport);
+ /*
+ * Logout all previous fabric devices marked lost, except
+ * FCP2 devices.
+ */
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
+ break;
+
+ if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
+ (fcport->flags & FCF_LOGIN_NEEDED) == 0)
+ continue;
+
+ if (fcport->scan_state == QLA_FCPORT_SCAN) {
+ if ((qla_dual_mode_enabled(vha) ||
+ qla_ini_mode_enabled(vha)) &&
+ atomic_read(&fcport->state) == FCS_ONLINE) {
+ qla2x00_mark_device_lost(vha, fcport,
+ ql2xplogiabsentdevice, 0);
+ if (fcport->loop_id != FC_NO_LOOP_ID &&
+ (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
+ fcport->port_type != FCT_INITIATOR &&
+ fcport->port_type != FCT_BROADCAST) {
+ /* cable disconnected */
+ qlt_schedule_sess_for_deletion(fcport,
+ true);
+ continue;
+ }
+ }
+ }
+
+ if (fcport->flags & FCF_DELETE_DEV) {
+ /* cable move detected */
+ fcport->flags &= ~FCF_DELETE_DEV;
+ qlt_schedule_sess_for_deletion(fcport, true);
+ continue;
+ }
+
+ if (fcport->scan_state == QLA_FCPORT_FOUND)
+ qla24xx_fcport_handle_login(vha, fcport);
+ }
+
return (rval);
}
@@ -3989,64 +4772,6 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
return (rval);
}
-/*
- * qla2x00_fabric_dev_login
- * Login fabric target device and update FC port database.
- *
- * Input:
- * ha: adapter state pointer.
- * fcport: port structure list pointer.
- * next_loopid: contains value of a new loop ID that can be used
- * by the next login attempt.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
-static int
-qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport,
- uint16_t *next_loopid)
-{
- int rval;
- uint8_t opts;
- struct qla_hw_data *ha = vha->hw;
-
- rval = QLA_SUCCESS;
-
- if (IS_ALOGIO_CAPABLE(ha)) {
- if (fcport->flags & FCF_ASYNC_SENT)
- return rval;
- fcport->flags |= FCF_ASYNC_SENT;
- rval = qla2x00_post_async_login_work(vha, fcport, NULL);
- if (!rval)
- return rval;
- }
-
- fcport->flags &= ~FCF_ASYNC_SENT;
- rval = qla2x00_fabric_login(vha, fcport, next_loopid);
- if (rval == QLA_SUCCESS) {
- /* Send an ADISC to FCP2 devices.*/
- opts = 0;
- if (fcport->flags & FCF_FCP2_DEVICE)
- opts |= BIT_1;
- rval = qla2x00_get_port_database(vha, fcport, opts);
- if (rval != QLA_SUCCESS) {
- ha->isp_ops->fabric_logout(vha, fcport->loop_id,
- fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa);
- qla2x00_mark_device_lost(vha, fcport, 1, 0);
- } else {
- qla2x00_update_fcport(vha, fcport);
- }
- } else {
- /* Retry Login. */
- qla2x00_mark_device_lost(vha, fcport, 1, 0);
- }
-
- return (rval);
-}
/*
* qla2x00_fabric_login
@@ -4338,13 +5063,6 @@ int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
spin_unlock_irqrestore(&ha->vport_slock, flags);
qla2x00_rport_del(fcport);
- /*
- * Release the target mode FC NEXUS in
- * qla_target.c, if target mod is enabled.
- */
- qlt_fc_port_deleted(vha, fcport,
- base_vha->total_fcport_update_gen);
-
spin_lock_irqsave(&ha->vport_slock, flags);
}
}
@@ -4727,6 +5445,8 @@ int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
if (!(IS_P3P_TYPE(ha)))
ha->isp_ops->reset_chip(vha);
+ ha->chip_reset++;
+
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -4782,7 +5502,7 @@ int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
qla2x00_abort_all_cmds(vha, DID_RESET << 16);
}
- ha->chip_reset++;
+
/* memory barrier */
wmb();
}
@@ -5206,7 +5926,7 @@ static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *vha,
rval = 1;
}
- if (!qla_ini_mode_enabled(vha)) {
+ if (qla_tgt_mode_enabled(vha)) {
/* Don't enable full login after initial LIP */
nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
/* Don't enable LIP full login for initiator */
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 5382b03..d6dd976 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -166,8 +166,8 @@
/* Don't print state transitions during initial allocation of fcport */
if (old_state && old_state != state) {
ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
- "FCPort state transitioned from %s to %s - "
- "portid=%02x%02x%02x.\n",
+ "FCPort %8phC state transitioned from %s to %s - "
+ "portid=%02x%02x%02x.\n", fcport->port_name,
port_state_str[old_state], port_state_str[state],
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa);
@@ -263,6 +263,7 @@
memset(sp, 0, sizeof(*sp));
sp->fcport = fcport;
sp->iocbs = 1;
+ sp->vha = vha;
done:
if (!sp)
QLA_VHA_MARK_NOT_BUSY(vha);
@@ -285,7 +286,7 @@
sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout;
add_timer(&sp->u.iocb_cmd.timer);
sp->free = qla2x00_sp_free;
- if ((IS_QLAFX00(sp->fcport->vha->hw)) &&
+ if ((IS_QLAFX00(((scsi_qla_host_t *)sp->vha)->hw)) &&
(sp->type == SRB_FXIOCB_DCMD))
init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
if (sp->type == SRB_ELS_DCMD)
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 2bb65c6..b7d3739 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2252,7 +2252,7 @@ struct fw_dif_context {
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags =
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
- if (!sp->fcport->tgt_session ||
+ if (!sp->fcport->se_sess ||
!sp->fcport->keep_nport_handle)
logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
@@ -3085,19 +3085,72 @@ struct fw_dif_context {
wmb();
}
+
+static void
+qla2x00_mb_iocb(srb_t *sp, struct mbx_24xx_entry *mbx)
+{
+ int i, sz;
+
+ mbx->entry_type = MBX_IOCB_TYPE;
+ mbx->handle = sp->handle;
+ sz = min(ARRAY_SIZE(mbx->mb),
+ ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.out_mb));
+
+ for (i = 0; i < sz; i++)
+ mbx->mb[i] = cpu_to_le16(sp->u.iocb_cmd.u.mbx.out_mb[i]);
+
+}
+
+static void
+qla2x00_ctpthru_cmd_iocb(srb_t *sp, struct ct_entry_24xx *ct_pkt)
+{
+ sp->u.iocb_cmd.u.ctarg.iocb = ct_pkt;
+ qla24xx_prep_ms_iocb(sp->vha, &sp->u.iocb_cmd.u.ctarg);
+ ct_pkt->handle = sp->handle;
+}
+
+static void qla2x00_send_notify_ack_iocb(srb_t *sp,
+ struct nack_to_isp *nack)
+{
+ struct imm_ntfy_from_isp *ntfy = sp->u.iocb_cmd.u.nack.ntfy;
+
+ nack->entry_type = NOTIFY_ACK_TYPE;
+ nack->entry_count = 1;
+ nack->ox_id = ntfy->ox_id;
+
+ nack->u.isp24.handle = sp->handle;
+ nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
+ if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
+ nack->u.isp24.flags = ntfy->u.isp24.flags &
+ cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
+ }
+ nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
+ nack->u.isp24.status = ntfy->u.isp24.status;
+ nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
+ nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
+ nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
+ nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
+ nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
+ nack->u.isp24.srr_flags = 0;
+ nack->u.isp24.srr_reject_code = 0;
+ nack->u.isp24.srr_reject_code_expl = 0;
+ nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
+}
+
int
qla2x00_start_sp(srb_t *sp)
{
int rval;
- struct qla_hw_data *ha = sp->fcport->vha->hw;
+ scsi_qla_host_t *vha = (scsi_qla_host_t *)sp->vha;
+ struct qla_hw_data *ha = vha->hw;
void *pkt;
unsigned long flags;
rval = QLA_FUNCTION_FAILED;
spin_lock_irqsave(&ha->hardware_lock, flags);
- pkt = qla2x00_alloc_iocbs(sp->fcport->vha, sp);
+ pkt = qla2x00_alloc_iocbs(vha, sp);
if (!pkt) {
- ql_log(ql_log_warn, sp->fcport->vha, 0x700c,
+ ql_log(ql_log_warn, vha, 0x700c,
"qla2x00_alloc_iocbs failed.\n");
goto done;
}
@@ -3145,12 +3198,23 @@ struct fw_dif_context {
case SRB_ELS_DCMD:
qla24xx_els_logo_iocb(sp, pkt);
break;
+ case SRB_CT_PTHRU_CMD:
+ qla2x00_ctpthru_cmd_iocb(sp, pkt);
+ break;
+ case SRB_MB_IOCB:
+ qla2x00_mb_iocb(sp, pkt);
+ break;
+ case SRB_NACK_PLOGI:
+ case SRB_NACK_PRLI:
+ case SRB_NACK_LOGO:
+ qla2x00_send_notify_ack_iocb(sp, pkt);
+ break;
default:
break;
}
wmb();
- qla2x00_start_iocbs(sp->fcport->vha, ha->req_q_map[0]);
+ qla2x00_start_iocbs(vha, ha->req_q_map[0]);
done:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return rval;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index ccdb890..c5a1ce4 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -564,14 +564,51 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
return ret;
}
-static inline fc_port_t *
+
+fc_port_t *
qla2x00_find_fcport_by_loopid(scsi_qla_host_t *vha, uint16_t loop_id)
{
- fc_port_t *fcport;
+ fc_port_t *f, *tf;
+ f = tf = NULL;
- list_for_each_entry(fcport, &vha->vp_fcports, list)
- if (fcport->loop_id == loop_id)
- return fcport;
+ list_for_each_entry_safe(f, tf, &vha->vp_fcports, list)
+ if (f->loop_id == loop_id)
+ return f;
+ return NULL;
+}
+
+fc_port_t *
+qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *vha, u8 *wwpn, u8 incl_deleted)
+{
+ fc_port_t *f, *tf;
+ f = tf = NULL;
+
+ list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
+ if (memcmp(f->port_name, wwpn, WWN_SIZE) == 0) {
+ if (incl_deleted)
+ return f;
+ else if (f->deleted == 0)
+ return f;
+ }
+ }
+ return NULL;
+}
+
+fc_port_t *
+qla2x00_find_fcport_by_nportid(scsi_qla_host_t *vha, port_id_t *id,
+ u8 incl_deleted)
+{
+ fc_port_t *f, *tf;
+ f = tf = NULL;
+
+ list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
+ if (f->d_id.b24 == id->b24) {
+ if (incl_deleted)
+ return f;
+ else if (f->deleted == 0)
+ return f;
+ }
+ }
return NULL;
}
@@ -1042,10 +1079,14 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
atomic_set(&vha->loop_down_timer, 0);
vha->flags.management_server_logged_in = 0;
+ {
+ struct event_arg ea;
+ memset(&ea, 0, sizeof(ea));
+ ea.event = FCME_RSCN;
+ ea.id.b24 = rscn_entry;
+ qla2x00_fcport_event_handler(vha, &ea);
+ }
- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- set_bit(RSCN_UPDATE, &vha->dpc_flags);
- qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
break;
/* case MBA_RIO_RESPONSE: */
@@ -1350,59 +1391,121 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
}
static void
-qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
- sts_entry_t *pkt, int iocb_type)
+qla24xx_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+ struct mbx_24xx_entry *pkt)
{
- const char func[] = "CT_IOCB";
+ const char func[] = "MBX-IOCB2";
const char *type;
srb_t *sp;
- struct bsg_job *bsg_job;
- struct fc_bsg_reply *bsg_reply;
- uint16_t comp_status;
+ struct srb_iocb *si;
+ u16 sz, i;
int res;
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (!sp)
return;
- bsg_job = sp->u.bsg_job;
- bsg_reply = bsg_job->reply;
+ type = sp->name;
- type = "ct pass-through";
+ si = &sp->u.iocb_cmd;
+ sz = min(ARRAY_SIZE(pkt->mb),
+ ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.in_mb));
- comp_status = le16_to_cpu(pkt->comp_status);
+ for (i = 0; i < sz; i++)
+ si->u.mbx.in_mb[i] = le16_to_cpu(pkt->mb[i]);
- /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
- * fc payload to the caller
- */
- bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
- bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ res = (si->u.mbx.in_mb[0] & MBS_MASK);
- if (comp_status != CS_COMPLETE) {
- if (comp_status == CS_DATA_UNDERRUN) {
- res = DID_OK << 16;
- bsg_reply->reply_payload_rcv_len =
- le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
+ sp->done(vha, sp, res);
+}
- ql_log(ql_log_warn, vha, 0x5048,
- "CT pass-through-%s error "
- "comp_status-status=0x%x total_byte = 0x%x.\n",
- type, comp_status,
- bsg_reply->reply_payload_rcv_len);
- } else {
- ql_log(ql_log_warn, vha, 0x5049,
- "CT pass-through-%s error "
- "comp_status-status=0x%x.\n", type, comp_status);
- res = DID_ERROR << 16;
- bsg_reply->reply_payload_rcv_len = 0;
- }
- ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
- (uint8_t *)pkt, sizeof(*pkt));
- } else {
- res = DID_OK << 16;
- bsg_reply->reply_payload_rcv_len =
- bsg_job->reply_payload.payload_len;
- bsg_job->reply_len = 0;
+static void
+qla24xxx_nack_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+ struct nack_to_isp *pkt)
+{
+ const char func[] = "nack";
+ srb_t *sp;
+ int res = 0;
+
+ sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+ if (!sp)
+ return;
+
+ if (pkt->u.isp2x.status != cpu_to_le16(NOTIFY_ACK_SUCCESS))
+ res = QLA_FUNCTION_FAILED;
+
+ sp->done(vha, sp, res);
+}
+
+static void
+qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
+ sts_entry_t *pkt, int iocb_type)
+{
+ const char func[] = "CT_IOCB";
+ const char *type;
+ srb_t *sp;
+ struct bsg_job *bsg_job;
+ struct fc_bsg_reply *bsg_reply;
+ uint16_t comp_status;
+ int res = 0;
+
+ sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+ if (!sp)
+ return;
+
+ switch (sp->type) {
+ case SRB_CT_CMD:
+ bsg_job = sp->u.bsg_job;
+ bsg_reply = bsg_job->reply;
+
+ type = "ct pass-through";
+
+ comp_status = le16_to_cpu(pkt->comp_status);
+
+ /*
+ * return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
+ * fc payload to the caller
+ */
+
+ bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+
+ if (comp_status != CS_COMPLETE) {
+ if (comp_status == CS_DATA_UNDERRUN) {
+ res = DID_OK << 16;
+ bsg_reply->reply_payload_rcv_len =
+ le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
+
+ ql_log(ql_log_warn, vha, 0x5048,
+ "CT pass-through-%s error "
+ "comp_status-status=0x%x total_byte = 0x%x.\n",
+ type, comp_status,
+ bsg_reply->reply_payload_rcv_len);
+ } else {
+ ql_log(ql_log_warn, vha, 0x5049,
+ "CT pass-through-%s error "
+ "comp_status-status=0x%x.\n", type, comp_status);
+ res = DID_ERROR << 16;
+ bsg_reply->reply_payload_rcv_len = 0;
+ }
+ ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
+ (uint8_t *)pkt, sizeof(*pkt));
+ } else {
+ res = DID_OK << 16;
+ bsg_reply->reply_payload_rcv_len =
+ bsg_job->reply_payload.payload_len;
+ bsg_job->reply_len = 0;
+ }
+ break;
+ case SRB_CT_PTHRU_CMD:
+ /*
+ * borrowing sts_entry_24xx.comp_status.
+ * same location as ct_entry_24xx.comp_status
+ */
+ res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
+ (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
+ sp->name);
+ break;
}
sp->done(vha, sp, res);
@@ -1443,6 +1546,15 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
"Completing %s: (%p) type=%d.\n", type, sp, sp->type);
sp->done(vha, sp, 0);
return;
+ case SRB_CT_PTHRU_CMD:
+ /* borrowing sts_entry_24xx.comp_status.
+ same location as ct_entry_24xx.comp_status
+ */
+ res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
+ (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
+ sp->name);
+ sp->done(vha, sp, res);
+ return;
default:
ql_dbg(ql_dbg_user, vha, 0x503e,
"Unrecognized SRB: (%p) type=%d.\n", sp, sp->type);
@@ -1569,6 +1681,8 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
iop[0] = le32_to_cpu(logio->io_parameter[0]);
iop[1] = le32_to_cpu(logio->io_parameter[1]);
+ lio->u.logio.iop[0] = iop[0];
+ lio->u.logio.iop[1] = iop[1];
switch (iop[0]) {
case LSC_SCODE_PORTID_USED:
data[0] = MBS_PORT_ID_USED;
@@ -2637,10 +2751,16 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
}
case ABTS_RESP_24XX:
case CTIO_TYPE7:
- case NOTIFY_ACK_TYPE:
case CTIO_CRC2:
qlt_response_pkt_all_vps(vha, (response_t *)pkt);
break;
+ case NOTIFY_ACK_TYPE:
+ if (pkt->handle == QLA_TGT_SKIP_HANDLE)
+ qlt_response_pkt_all_vps(vha, (response_t *)pkt);
+ else
+ qla24xxx_nack_iocb_entry(vha, rsp->req,
+ (struct nack_to_isp *) pkt);
+ break;
case MARKER_TYPE:
/* Do nothing in this case, this check is to prevent it
* from falling into default case
@@ -2650,6 +2770,11 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
qla24xx_abort_iocb_entry(vha, rsp->req,
(struct abort_entry_24xx *)pkt);
break;
+ case MBX_IOCB_TYPE:
+ qla24xx_mbx_iocb_entry(vha, rsp->req,
+ (struct mbx_24xx_entry *)pkt);
+ break;
+
default:
/* Type Not Supported. */
ql_dbg(ql_dbg_async, vha, 0x5042,
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 76184ee..44be150 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1679,94 +1679,6 @@ static int is_rom_cmd(uint16_t cmd)
return rval;
}
-/*
- * qla2x00_get_node_name_list
- * Issue get node name list mailbox command, kmalloc()
- * and return the resulting list. Caller must kfree() it!
- *
- * Input:
- * ha = adapter state pointer.
- * out_data = resulting list
- * out_len = length of the resulting list
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
-int
-qla2x00_get_node_name_list(scsi_qla_host_t *vha, void **out_data, int *out_len)
-{
- struct qla_hw_data *ha = vha->hw;
- struct qla_port_24xx_data *list = NULL;
- void *pmap;
- mbx_cmd_t mc;
- dma_addr_t pmap_dma;
- ulong dma_size;
- int rval, left;
-
- left = 1;
- while (left > 0) {
- dma_size = left * sizeof(*list);
- pmap = dma_alloc_coherent(&ha->pdev->dev, dma_size,
- &pmap_dma, GFP_KERNEL);
- if (!pmap) {
- ql_log(ql_log_warn, vha, 0x113f,
- "%s(%ld): DMA Alloc failed of %ld\n",
- __func__, vha->host_no, dma_size);
- rval = QLA_MEMORY_ALLOC_FAILED;
- goto out;
- }
-
- mc.mb[0] = MBC_PORT_NODE_NAME_LIST;
- mc.mb[1] = BIT_1 | BIT_3;
- mc.mb[2] = MSW(pmap_dma);
- mc.mb[3] = LSW(pmap_dma);
- mc.mb[6] = MSW(MSD(pmap_dma));
- mc.mb[7] = LSW(MSD(pmap_dma));
- mc.mb[8] = dma_size;
- mc.out_mb = MBX_0|MBX_1|MBX_2|MBX_3|MBX_6|MBX_7|MBX_8;
- mc.in_mb = MBX_0|MBX_1;
- mc.tov = 30;
- mc.flags = MBX_DMA_IN;
-
- rval = qla2x00_mailbox_command(vha, &mc);
- if (rval != QLA_SUCCESS) {
- if ((mc.mb[0] == MBS_COMMAND_ERROR) &&
- (mc.mb[1] == 0xA)) {
- left += le16_to_cpu(mc.mb[2]) /
- sizeof(struct qla_port_24xx_data);
- goto restart;
- }
- goto out_free;
- }
-
- left = 0;
-
- list = kmemdup(pmap, dma_size, GFP_KERNEL);
- if (!list) {
- ql_log(ql_log_warn, vha, 0x1140,
- "%s(%ld): failed to allocate node names list "
- "structure.\n", __func__, vha->host_no);
- rval = QLA_MEMORY_ALLOC_FAILED;
- goto out_free;
- }
-
-restart:
- dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma);
- }
-
- *out_data = list;
- *out_len = dma_size;
-
-out:
- return rval;
-
-out_free:
- dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma);
- return rval;
-}
/*
* qla2x00_get_port_database
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index d6f4ce7..133d92a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2913,6 +2913,18 @@ static void qla2x00_destroy_mbx_wq(struct qla_hw_data *ha)
if (ret)
goto probe_init_failed;
+ base_vha->gnl.size = (ha->max_loop_id + 1) *
+ sizeof(struct get_name_list_extended);
+ base_vha->gnl.l = dma_alloc_coherent(&ha->pdev->dev,
+ base_vha->gnl.size, &base_vha->gnl.ldma, GFP_KERNEL);
+ INIT_LIST_HEAD(&base_vha->gnl.fcports);
+
+ if (base_vha->gnl.l == NULL) {
+ ql_log(ql_log_fatal, base_vha, 0xffff,
+ "Alloc failed for name list.\n");
+ goto probe_init_failed;
+ }
+
/* Alloc arrays of request and response ring ptrs */
if (!qla2x00_alloc_queues(ha, req, rsp)) {
ql_log(ql_log_fatal, base_vha, 0x003d,
@@ -3141,7 +3153,8 @@ static void qla2x00_destroy_mbx_wq(struct qla_hw_data *ha)
ql_dbg(ql_dbg_init, base_vha, 0x00f2,
"Init done and hba is online.\n");
- if (qla_ini_mode_enabled(base_vha))
+ if (qla_ini_mode_enabled(base_vha) ||
+ qla_dual_mode_enabled(base_vha))
scsi_scan_host(host);
else
ql_dbg(ql_dbg_init, base_vha, 0x0122,
@@ -3390,6 +3403,9 @@ static void qla2x00_destroy_mbx_wq(struct qla_hw_data *ha)
* resources.
*/
if (!atomic_read(&pdev->enable_cnt)) {
+ dma_free_coherent(&ha->pdev->dev,
+ base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
+
scsi_host_put(base_vha->host);
kfree(ha);
pci_set_drvdata(pdev, NULL);
@@ -3406,6 +3422,10 @@ static void qla2x00_destroy_mbx_wq(struct qla_hw_data *ha)
set_bit(UNLOADING, &base_vha->dpc_flags);
+
+ dma_free_coherent(&ha->pdev->dev,
+ base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
+
if (IS_QLAFX00(ha))
qlafx00_driver_shutdown(base_vha, 20);
@@ -3561,7 +3581,6 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha)
if (rport)
fc_remote_port_delete(rport);
qlt_do_generation_tick(vha, &now);
- qlt_fc_port_deleted(vha, fcport, now);
}
}
@@ -3604,7 +3623,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
fcport->login_retry = vha->hw->login_retry_count;
ql_dbg(ql_dbg_disc, vha, 0x2067,
- "Port login retry %8phN, id = 0x%04x retry cnt=%d.\n",
+ "Port login retry %8phN, lid 0x%04x retry cnt=%d.\n",
fcport->port_name, fcport->loop_id, fcport->login_retry);
}
}
@@ -3628,6 +3647,9 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
fc_port_t *fcport;
list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ fcport->scan_state = 0;
+ qlt_schedule_sess_for_deletion(fcport, 1);
+
if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx)
continue;
@@ -4262,7 +4284,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
return vha;
}
-static struct qla_work_evt *
+struct qla_work_evt *
qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
{
struct qla_work_evt *e;
@@ -4284,7 +4306,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
return e;
}
-static int
+int
qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
{
unsigned long flags;
@@ -4345,7 +4367,6 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
}
qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN);
-qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE);
qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
@@ -4398,6 +4419,65 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
return qla2x00_post_work(vha, e);
}
+
+int qla24xx_post_upd_fcport_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+ struct qla_work_evt *e;
+ e = qla2x00_alloc_work(vha, QLA_EVT_UPD_FCPORT);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.fcport.fcport = fcport;
+ return qla2x00_post_work(vha, e);
+}
+
+static
+void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
+{
+ unsigned long flags;
+ fc_port_t *fcport = NULL;
+ qlt_plogi_ack_t *pla = (qlt_plogi_ack_t *)e->u.new_sess.pla;
+
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1);
+ if (fcport) {
+ fcport->d_id = e->u.new_sess.id;
+ if (pla) {
+ fcport->fw_login_state = DSC_LS_PLOGI_PEND;
+ qlt_plogi_ack_link(vha, pla, fcport, QLT_PLOGI_LINK_SAME_WWN);
+ /* we took an extra ref_count to prevent PLOGI ACK when
+ * fcport/sess has not been created.
+ */
+ pla->ref_count--;
+ }
+ } else {
+ fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
+ if (fcport) {
+ fcport->d_id = e->u.new_sess.id;
+ fcport->scan_state = QLA_FCPORT_FOUND;
+ fcport->flags |= FCF_FABRIC_DEVICE;
+ fcport->fw_login_state = DSC_LS_PLOGI_PEND;
+
+ memcpy(&fcport->port_name, e->u.new_sess.port_name,
+ WWN_SIZE);
+ list_add_tail(&fcport->list, &vha->vp_fcports);
+
+ if (pla) {
+ qlt_plogi_ack_link(vha, pla, fcport, QLT_PLOGI_LINK_SAME_WWN);
+ pla->ref_count--;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+ if (fcport) {
+ if (pla)
+ qlt_plogi_ack_unref(vha, pla);
+ else
+ qla24xx_async_gnl(vha, fcport);
+ }
+}
+
void
qla2x00_do_work(struct scsi_qla_host *vha)
{
@@ -4424,10 +4504,6 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
qla2x00_async_login(vha, e->u.logio.fcport,
e->u.logio.data);
break;
- case QLA_EVT_ASYNC_LOGIN_DONE:
- qla2x00_async_login_done(vha, e->u.logio.fcport,
- e->u.logio.data);
- break;
case QLA_EVT_ASYNC_LOGOUT:
qla2x00_async_logout(vha, e->u.logio.fcport);
break;
@@ -4449,6 +4525,33 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
case QLA_EVT_AENFX:
qlafx00_process_aen(vha, e);
break;
+ case QLA_EVT_GIDPN:
+ qla24xx_async_gidpn(vha, e->u.fcport.fcport);
+ break;
+ case QLA_EVT_GPNID:
+ qla24xx_async_gpnid(vha, &e->u.gpnid.id);
+ break;
+ case QLA_EVT_GPNID_DONE:
+ qla24xx_async_gpnid_done(vha, e->u.iosb.sp);
+ break;
+ case QLA_EVT_NEW_SESS:
+ qla24xx_create_new_sess(vha, e);
+ break;
+ case QLA_EVT_GPDB:
+ qla24xx_async_gpdb(vha, e->u.fcport.fcport, e->u.fcport.opt);
+ break;
+ case QLA_EVT_GPSC:
+ qla24xx_async_gpsc(vha, e->u.fcport.fcport);
+ break;
+ case QLA_EVT_UPD_FCPORT:
+ qla2x00_update_fcport(vha, e->u.fcport.fcport);
+ break;
+ case QLA_EVT_GNL:
+ qla24xx_async_gnl(vha, e->u.fcport.fcport);
+ break;
+ case QLA_EVT_NACK:
+ qla24xx_do_nack_work(vha, e);
+ break;
}
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
@@ -4465,9 +4568,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
{
fc_port_t *fcport;
int status;
- uint16_t next_loopid = 0;
- struct qla_hw_data *ha = vha->hw;
- uint16_t data[2];
+ struct event_arg ea;
list_for_each_entry(fcport, &vha->vp_fcports, list) {
/*
@@ -4478,53 +4579,16 @@ 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) {
- if (fcport->flags & FCF_FCP2_DEVICE)
- ha->isp_ops->fabric_logout(vha,
- fcport->loop_id,
- fcport->d_id.b.domain,
- fcport->d_id.b.area,
- fcport->d_id.b.al_pa);
-
- if (fcport->loop_id == FC_NO_LOOP_ID) {
- fcport->loop_id = next_loopid =
- ha->min_external_loopid;
- status = qla2x00_find_new_loop_id(
- vha, fcport);
- if (status != QLA_SUCCESS) {
- /* Ran out of IDs to use */
- break;
- }
- }
+ 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);
+ memset(&ea, 0, sizeof(ea));
+ ea.event = FCME_RELOGIN;
+ ea.fcport = fcport;
+ qla2x00_fcport_event_handler(vha, &ea);
- if (IS_ALOGIO_CAPABLE(ha)) {
- fcport->flags |= FCF_ASYNC_SENT;
- data[0] = 0;
- data[1] = QLA_LOGIO_LOGIN_RETRIED;
- status = qla2x00_post_async_login_work(
- vha, fcport, data);
- if (status == QLA_SUCCESS)
- continue;
- /* Attempt a retry. */
- status = 1;
- } else {
- status = qla2x00_fabric_login(vha,
- fcport, &next_loopid);
- if (status == QLA_SUCCESS) {
- int status2;
- uint8_t opts;
-
- opts = 0;
- if (fcport->flags &
- FCF_FCP2_DEVICE)
- opts |= BIT_1;
- status2 =
- qla2x00_get_port_database(
- vha, fcport, opts);
- if (status2 != QLA_SUCCESS)
- status = 1;
- }
- }
- } else
+ } else {
status = qla2x00_local_device_login(vha,
fcport);
@@ -4549,6 +4613,8 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
if (fcport->login_retry == 0 && status != QLA_SUCCESS)
qla2x00_clear_loop_id(fcport);
+
+ }
}
if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
break;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 8c42ff4..b5c20362 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -118,6 +118,9 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha,
uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan);
static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
struct imm_ntfy_from_isp *imm, int ha_locked);
+static struct fc_port *qlt_create_sess(struct scsi_qla_host *vha,
+ fc_port_t *fcport, bool local);
+void qlt_unreg_sess(struct fc_port *sess);
/*
* Global Variables
*/
@@ -396,9 +399,203 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
}
+static
+void qla2x00_async_nack_sp_done(void *v, void *s, int res)
+{
+ struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
+ struct srb *sp = (struct srb *)s;
+ 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);
+
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ sp->fcport->flags &= ~FCF_ASYNC_SENT;
+
+ switch (sp->type) {
+ case SRB_NACK_PLOGI:
+ sp->fcport->login_gen++;
+ sp->fcport->fw_login_state = DSC_LS_PLOGI_COMP;
+ break;
+
+ case SRB_NACK_PRLI:
+ sp->fcport->fw_login_state = DSC_LS_PRLI_COMP;
+ sp->fcport->deleted = 0;
+ vha->fcport_count++;
+ break;
+
+ case SRB_NACK_LOGO:
+ sp->fcport->login_gen++;
+ sp->fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
+ qlt_logo_completion_handler(sp->fcport, MBS_COMMAND_COMPLETE);
+ break;
+ }
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+ sp->free(vha, sp);
+}
+
+int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
+ struct imm_ntfy_from_isp *ntfy, int type)
+{
+ int rval = QLA_FUNCTION_FAILED;
+ srb_t *sp;
+ char *c = NULL;
+
+ fcport->flags |= FCF_ASYNC_SENT;
+ switch (type) {
+ case SRB_NACK_PLOGI:
+ fcport->fw_login_state = DSC_LS_PLOGI_PEND;
+ c = "PLOGI";
+ break;
+ case SRB_NACK_PRLI:
+ fcport->fw_login_state = DSC_LS_PRLI_PEND;
+ c = "PRLI";
+ break;
+ case SRB_NACK_LOGO:
+ fcport->fw_login_state = DSC_LS_LOGO_PEND;
+ c = "LOGO";
+ break;
+ }
+
+ sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
+ if (!sp)
+ goto done;
+
+ sp->type = type;
+ sp->name = "nack";
+
+ qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
+
+ sp->u.iocb_cmd.u.nack.ntfy = ntfy;
+
+ sp->done = qla2x00_async_nack_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+ 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);
+
+ return rval;
+
+done_free_sp:
+ sp->free(vha, sp);
+done:
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ return rval;
+}
+
+void qla24xx_do_nack_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
+{
+ fc_port_t *t;
+ unsigned long flags;
+
+ switch (e->u.nack.type) {
+ case SRB_NACK_PRLI:
+ mutex_lock(&vha->vha_tgt.tgt_mutex);
+ t = qlt_create_sess(vha, e->u.nack.fcport, 0);
+ mutex_unlock(&vha->vha_tgt.tgt_mutex);
+ if (t) {
+ printk(KERN_INFO "%s create sess success %p",
+ __func__, t);
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ /* create sess has an extra kref */
+ vha->hw->tgt.tgt_ops->put_sess(e->u.nack.fcport);
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+ }
+ break;
+ }
+
+ qla24xx_async_notify_ack(vha, e->u.nack.fcport,
+ (struct imm_ntfy_from_isp *)e->u.nack.iocb, e->u.nack.type);
+}
+
+void qla24xx_delete_sess_fn(struct work_struct *work)
+{
+ fc_port_t *fcport = container_of(work, struct fc_port, del_work);
+ struct qla_hw_data *ha = fcport->vha->hw;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+
+ if (fcport->se_sess) {
+ ha->tgt.tgt_ops->shutdown_sess(fcport);
+ ha->tgt.tgt_ops->put_sess(fcport);
+ } else
+ qlt_unreg_sess(fcport);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+}
+
+
/*
- * All qlt_plogi_ack_t operations are protected by hardware_lock
+ * Called from qla2x00_reg_remote_port()
*/
+void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ struct fc_port *sess = fcport;
+ unsigned long flags;
+
+ if (!vha->hw->tgt.tgt_ops)
+ return;
+
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ if (tgt->tgt_stop) {
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+ return;
+ }
+
+ if (fcport->disc_state == DSC_DELETE_PEND) {
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+ return;
+ }
+
+ if (!sess->se_sess) {
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
+ mutex_lock(&vha->vha_tgt.tgt_mutex);
+ sess = qlt_create_sess(vha, fcport, false);
+ mutex_unlock(&vha->vha_tgt.tgt_mutex);
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ } else {
+ if (fcport->fw_login_state == DSC_LS_PRLI_COMP) {
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+ return;
+ }
+
+ ha->tgt.tgt_ops->get_sess(sess);
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04c,
+ "qla_target(%u): %ssession for port %8phC "
+ "(loop ID %d) reappeared\n", vha->vp_idx,
+ sess->local ? "local " : "", sess->port_name,
+ sess->loop_id);
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
+ "Reappeared sess %p\n", sess);
+
+ ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+ (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+ }
+
+ if (sess && sess->local) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04d,
+ "qla_target(%u): local session for "
+ "port %8phC (loop ID %d) became global\n", vha->vp_idx,
+ fcport->port_name, sess->loop_id);
+ sess->local = 0;
+ }
+ ha->tgt.tgt_ops->put_sess(sess);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+}
+
/*
* This is a zero-base ref-counting solution, since hardware_lock
@@ -435,7 +632,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
return pla;
}
-static void qlt_plogi_ack_unref(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla)
+void qlt_plogi_ack_unref(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla)
{
struct imm_ntfy_from_isp *iocb = (struct imm_ntfy_from_isp *)&pla->iocb;
BUG_ON(!pla->ref_count);
@@ -457,7 +654,7 @@ static void qlt_plogi_ack_unref(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla)
kmem_cache_free(qla_tgt_plogi_cachep, pla);
}
-static void
+void
qlt_plogi_ack_link(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla,
struct fc_port *sess, qlt_plogi_link_t link)
{
@@ -654,6 +851,9 @@ void qlt_unreg_sess(struct fc_port *sess)
qla2x00_mark_device_lost(vha, sess, 1, 1);
sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
+ sess->disc_state = DSC_DELETE_PEND;
+ sess->last_rscn_gen = sess->rscn_gen;
+ sess->last_login_gen = sess->login_gen;
INIT_WORK(&sess->free_work, qlt_free_session_done);
schedule_work(&sess->free_work);
@@ -700,7 +900,7 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
}
/* ha->tgt.sess_lock supposed to be held on entry */
-static void qlt_schedule_sess_for_deletion(struct fc_port *sess,
+void qlt_schedule_sess_for_deletion(struct fc_port *sess,
bool immediate)
{
struct qla_tgt *tgt = sess->tgt;
@@ -1232,6 +1432,7 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha,
nack = (struct nack_to_isp *)pkt;
nack->ox_id = ntfy->ox_id;
+ nack->u.isp24.handle = QLA_TGT_SKIP_HANDLE;
nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
nack->u.isp24.flags = ntfy->u.isp24.flags &
@@ -4233,13 +4434,12 @@ void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
* deletion. Returns existing session with matching wwn if present.
* Null otherwise.
*/
-static struct fc_port *
-qlt_find_sess_invalidate_other(struct qla_tgt *tgt, uint64_t wwn,
+struct fc_port *
+qlt_find_sess_invalidate_other(scsi_qla_host_t *vha, uint64_t wwn,
port_id_t port_id, uint16_t loop_id, struct fc_port **conflict_sess)
{
struct fc_port *sess = NULL, *other_sess;
uint64_t other_wwn;
- scsi_qla_host_t *vha = tgt->vha;
*conflict_sess = NULL;
@@ -4256,7 +4456,7 @@ void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
/* find other sess with nport_id collision */
if (port_id.b24 == other_sess->d_id.b24) {
if (loop_id != other_sess->loop_id) {
- ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000c,
+ ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000c,
"Invalidating sess %p loop_id %d wwn %llx.\n",
other_sess, other_sess->loop_id, other_wwn);
@@ -4282,7 +4482,7 @@ void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
/* find other sess with nport handle collision */
if (loop_id == other_sess->loop_id) {
- ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000d,
+ ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000d,
"Invalidating sess %p loop_id %d wwn %llx.\n",
other_sess, other_sess->loop_id, other_wwn);
@@ -4368,8 +4568,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
if (wwn) {
spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
- sess = qlt_find_sess_invalidate_other(tgt, wwn,
- port_id, loop_id, &conflict_sess);
+ sess = qlt_find_sess_invalidate_other(vha, wwn,
+ port_id, loop_id, &conflict_sess);
spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
}
@@ -4424,8 +4624,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
if (wwn) {
spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
- sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id,
- loop_id, &conflict_sess);
+ sess = qlt_find_sess_invalidate_other(vha, wwn, port_id,
+ loop_id, &conflict_sess);
spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
}
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index c43910b..6db17ab 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -903,9 +903,9 @@ struct qla_tgt_sess_op {
enum qla_sess_deletion {
QLA_SESS_DELETION_NONE = 0,
- QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of
- * this one */
- QLA_SESS_DELETION_IN_PROGRESS = 2,
+ QLA_SESS_DELETION_IN_PROGRESS,
+ QLA_SESS_DELETION_PENDING,
+ QLA_SESS_DELETED,
};
enum qla_tgt_prot_op {
@@ -1115,14 +1115,21 @@ extern int qlt_lport_register(void *, u64, u64, u64,
static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha)
{
- return ha->host->active_mode & MODE_TARGET;
+ return ha->host->active_mode == MODE_TARGET;
}
static inline bool qla_ini_mode_enabled(struct scsi_qla_host *ha)
{
- return ha->host->active_mode & MODE_INITIATOR;
+ return ha->host->active_mode == MODE_INITIATOR;
}
+static inline bool qla_dual_mode_enabled(struct scsi_qla_host *ha)
+{
+ return (ha->host->active_mode == MODE_DUAL);
+}
+
+
+
static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)
{
if (ha->host->active_mode & MODE_INITIATOR)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 11/22] qla2xxx: Refactor session management code.
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (9 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 10/22] qla2xxx: Add framework for Async fabric discovery Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-14 21:04 ` Christoph Hellwig
2016-12-06 20:30 ` [PATCH 12/22] qla2xxx: Add Dual mode support in the driver Himanshu Madhani
` (11 subsequent siblings)
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
Current code has 2 structures/codes tracking the same
remote port (fc_port & qla_tgt_sess). Merge these structures
and code under same fc_port.
In target mode, current code does not communicate session
state change to initiator side, Merget target and initiator
mode sessions into same session.
In driver unload path, schedule all session for deletion
and wait for deletion complete before allowing driver unload
to advance.
This patch also refactors unused session deletion in target mode
and does cleanup of dead code.
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_def.h | 3 +-
drivers/scsi/qla2xxx/qla_gbl.h | 1 +
drivers/scsi/qla2xxx/qla_gs.c | 58 ++-
drivers/scsi/qla2xxx/qla_init.c | 159 ++++---
drivers/scsi/qla2xxx/qla_isr.c | 43 +-
drivers/scsi/qla2xxx/qla_os.c | 46 +-
drivers/scsi/qla2xxx/qla_target.c | 905 ++++++++++++++++++++++---------------
drivers/scsi/qla2xxx/qla_target.h | 4 +-
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 17 +-
9 files changed, 762 insertions(+), 474 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index f281f3d..6370aca 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2162,6 +2162,7 @@ enum fcport_mgt_event {
unsigned int keep_nport_handle:1;
unsigned int send_els_logo:1;
unsigned int login_pause:1;
+ unsigned int login_succ:1;
struct fc_port *conflict;
unsigned char logout_completed;
@@ -2254,7 +2255,6 @@ struct event_arg {
#define FCF_FCP2_DEVICE BIT_2
#define FCF_ASYNC_SENT BIT_3
#define FCF_CONF_COMP_SUPPORTED BIT_4
-#define FCF_DELETE_DEV BIT_5
/* No loop ID flag. */
#define FC_NO_LOOP_ID 0x1000
@@ -4008,6 +4008,7 @@ struct qla_tgt_counters {
struct name_list_extended gnl;
/* Count of active session/fcport */
int fcport_count;
+ wait_queue_head_t fcport_waitQ;
} scsi_qla_host_t;
struct qla27xx_image_status {
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 94fc7b4..3593a39 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -844,6 +844,7 @@ void qlt_plogi_ack_link(struct scsi_qla_host *, qlt_plogi_ack_t *,
struct fc_port *, qlt_plogi_link_t);
void qlt_plogi_ack_unref(struct scsi_qla_host *, qlt_plogi_ack_t *);
extern void qlt_schedule_sess_for_deletion(struct fc_port *, bool);
+extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *);
extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
void qla24xx_delete_sess_fn(struct work_struct *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index d7164da..fa49470 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -2777,28 +2777,55 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
default:
if (atomic_read(&fcport->state) == FCS_ONLINE)
break;
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post gnl\n",
+ __func__, __LINE__, fcport->port_name);
+
qla24xx_post_gnl_work(vha, fcport);
break;
}
} else { /* fcport->d_id.b24 != ea->id.b24 */
fcport->d_id.b24 = ea->id.b24;
- if (fcport->deleted == QLA_SESS_DELETED)
- qlt_schedule_sess_for_deletion(fcport, true);
+ if (fcport->deleted == QLA_SESS_DELETED) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%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 */
/* rscn came in while cmd was out */
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post gidpn\n",
+ __func__, __LINE__, fcport->port_name);
+
qla24xx_post_gidpn_work(vha, fcport);
}
} else { /* ea->rc */
/* cable pulled */
if (ea->sp->gen1 == fcport->rscn_gen) {
- if (ea->sp->gen2 == fcport->login_gen)
- qlt_schedule_sess_for_deletion(fcport, true);
- else
+ if (ea->sp->gen2 == fcport->login_gen) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%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,
+ "%s %d %8phC login\n",
+ __func__, __LINE__, fcport->port_name);
+
qla24xx_fcport_handle_login(vha, fcport);
- } else
+ }
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post gidpn\n",
+ __func__, __LINE__, fcport->port_name);
+
qla24xx_post_gidpn_work(vha, fcport);
+ }
}
} /* gidpn_event */
@@ -2836,6 +2863,9 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
struct ct_sns_req *ct_req;
srb_t *sp;
+ if (!vha->flags.online)
+ goto done;
+
fcport->flags |= FCF_ASYNC_SENT;
fcport->disc_state = DSC_GID_PN;
fcport->scan_state = QLA_FCPORT_SCAN;
@@ -2995,6 +3025,9 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
struct ct_sns_req *ct_req;
srb_t *sp;
+ if (!vha->flags.online)
+ goto done;
+
fcport->flags |= FCF_ASYNC_SENT;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
@@ -3090,14 +3123,22 @@ 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(fcport, true);
+ qlt_schedule_sess_for_deletion_lock(fcport);
} else {
/* create new fcport */
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post new sess\n",
+ __func__, __LINE__, ea->port_name);
+
qla24xx_post_newsess_work(vha, &ea->id, ea->port_name, NULL);
}
}
@@ -3163,6 +3204,9 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
srb_t *sp;
struct ct_sns_pkt *ct_sns;
+ if (!vha->flags.online)
+ goto done;
+
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
if (!sp)
goto done;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 857fa09..cfdfb02 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -187,6 +187,8 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
goto done;
fcport->flags |= FCF_ASYNC_SENT;
+ fcport->logout_completed = 0;
+
sp->type = SRB_LOGIN_CMD;
sp->name = "login";
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
@@ -293,6 +295,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
int rval;
rval = QLA_FUNCTION_FAILED;
+ fcport->flags |= FCF_ASYNC_SENT;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
@@ -319,6 +322,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
done_free_sp:
sp->free(fcport->vha, sp);
done:
+ fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
}
@@ -395,7 +399,10 @@ void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
if ((id.b24 != fcport->d_id.b24) ||
((fcport->loop_id != FC_NO_LOOP_ID) &&
(fcport->loop_id != loop_id))) {
- qlt_schedule_sess_for_deletion(fcport, true);
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post del sess\n",
+ __func__, __LINE__, fcport->port_name);
+ qlt_schedule_sess_for_deletion(fcport, 1);
return;
}
@@ -415,7 +422,16 @@ void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
}
switch (e->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);
+ 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;
@@ -425,16 +441,6 @@ void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
__func__, __LINE__, fcport->port_name);
qla24xx_fcport_handle_login(vha, fcport);
break;
-
- case DSC_LS_PRLI_COMP:
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post gpdb\n",
- __func__, __LINE__, fcport->port_name);
- opt = PDO_FORCE_ADISC;
- qla24xx_post_gpdb_work(vha, fcport, opt);
- break;
- default:
- break;
}
}
@@ -456,8 +462,13 @@ void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
conflict_fcport =
qla2x00_find_fcport_by_wwpn(vha,
e->port_name, 0);
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post del sess\n",
+ __func__, __LINE__,
+ conflict_fcport->port_name);
qlt_schedule_sess_for_deletion
- (conflict_fcport, true);
+ (conflict_fcport, 1);
}
if (fcport->loop_id == loop_id) {
@@ -623,7 +634,7 @@ int qla24xx_post_gnl_work(struct scsi_qla_host *vha, fc_port_t *fcport)
return qla2x00_post_work(vha, e);
}
-
+static
void qla24xx_async_gpdb_sp_done(void *v, void *s, int res)
{
struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
@@ -792,7 +803,7 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
return rval;
}
-
+static
void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
{
int rval = ea->rc;
@@ -815,36 +826,50 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
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",
+ __func__, __LINE__, fcport->port_name);
+
qla24xx_post_gidpn_work(vha, fcport);
return;
}
if (rval != QLA_SUCCESS) {
- qlt_schedule_sess_for_deletion(fcport, true);
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post del sess\n",
+ __func__, __LINE__, fcport->port_name);
+
+ qlt_schedule_sess_for_deletion_lock(fcport);
return;
}
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
ea->fcport->login_gen++;
ea->fcport->deleted = 0;
- vha->fcport_count++;
ea->fcport->logout_on_delete = 1;
- spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
- 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__, fcport->port_name,
- vha->fcport_count);
+ if (!ea->fcport->login_succ && !IS_SW_RESV_ADDR(ea->fcport->d_id)) {
+ vha->fcport_count++;
+ ea->fcport->login_succ = 1;
- qla24xx_post_upd_fcport_work(vha, fcport);
- } else {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s %d %8phC post gpsc fcp_cnt %d\n",
- __func__, __LINE__, fcport->port_name, vha->fcport_count);
+ 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__, fcport->port_name,
+ vha->fcport_count);
- qla24xx_post_gpsc_work(vha, fcport);
+ qla24xx_post_upd_fcport_work(vha, fcport);
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post gpsc fcp_cnt %d\n",
+ __func__, __LINE__, fcport->port_name,
+ vha->fcport_count);
+
+ qla24xx_post_gpsc_work(vha, fcport);
+ }
}
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
} /* gpdb event */
@@ -927,7 +952,24 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
}
break;
- case DSC_LOGIN_PEND:
+
+ case DSC_LOGIN_FAILED:
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%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);
+
+ qla24xx_post_gpdb_work(vha, fcport, PDO_FORCE_ADISC);
+ break;
+
default:
break;
}
@@ -935,7 +977,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
return 0;
}
-
+static
void qla24xx_handle_rscn_event(fc_port_t *fcport, struct event_arg *ea)
{
fcport->rscn_gen++;
@@ -974,6 +1016,7 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
return qla2x00_post_work(vha, e);
}
+static
int qla24xx_handle_delete_done_event(scsi_qla_host_t *vha,
struct event_arg *ea)
{
@@ -998,7 +1041,7 @@ int qla24xx_handle_delete_done_event(scsi_qla_host_t *vha,
return 0;
}
-
+static
void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
struct event_arg *ea)
{
@@ -1035,13 +1078,14 @@ 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",
+ __func__, __LINE__, fcport->port_name);
qla24xx_async_gidpn(vha, fcport);
- } else {
- if (fcport->deleted)
- qla24xx_fcport_handle_login(vha, fcport);
- else
- qlt_schedule_sess_for_deletion(fcport, true);
+ return;
}
+
+ qla24xx_fcport_handle_login(vha, fcport);
}
void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
@@ -1050,9 +1094,6 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
fc_port_t *fcport;
int rc;
- if (ea->fcport && (ea->fcport->chip_reset != vha->hw->chip_reset))
- qlt_schedule_sess_for_deletion(ea->fcport, true);
-
switch (ea->event) {
case FCME_RELOGIN:
@@ -3813,8 +3854,14 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
rport = fcport->drport ? fcport->drport: fcport->rport;
fcport->drport = NULL;
spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
- if (rport)
+ if (rport) {
+ ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
+ "%s %8phN. rport %p roles %x \n",
+ __func__, fcport->port_name, rport,
+ rport->roles);
+
fc_remote_port_delete(rport);
+ }
}
/**
@@ -4244,6 +4291,12 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
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");
+
fc_remote_port_rolechg(rport, rport_ids.roles);
}
@@ -4643,15 +4696,6 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
fcport->d_id.b24 = new_fcport->d_id.b24;
fcport->flags |= FCF_LOGIN_NEEDED;
- if (fcport->loop_id != FC_NO_LOOP_ID &&
- (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
- (fcport->flags & FCF_ASYNC_SENT) == 0 &&
- fcport->port_type != FCT_INITIATOR &&
- fcport->port_type != FCT_BROADCAST) {
- /* cable moved */
- fcport->flags |= FCF_DELETE_DEV;
- }
-
break;
}
@@ -4702,21 +4746,18 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
(fcport->flags & FCF_FCP2_DEVICE) == 0 &&
fcport->port_type != FCT_INITIATOR &&
fcport->port_type != FCT_BROADCAST) {
- /* cable disconnected */
- qlt_schedule_sess_for_deletion(fcport,
- true);
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post del sess\n",
+ __func__, __LINE__,
+ fcport->port_name);
+
+ qlt_schedule_sess_for_deletion_lock
+ (fcport);
continue;
}
}
}
- if (fcport->flags & FCF_DELETE_DEV) {
- /* cable move detected */
- fcport->flags &= ~FCF_DELETE_DEV;
- qlt_schedule_sess_for_deletion(fcport, true);
- continue;
- }
-
if (fcport->scan_state == QLA_FCPORT_FOUND)
qla24xx_fcport_handle_login(vha, fcport);
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index c5a1ce4..7a7a8c6 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -974,7 +974,11 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
ql_dbg(ql_dbg_async, vha, 0x508a,
"Marking port lost loopid=%04x portid=%06x.\n",
fcport->loop_id, fcport->d_id.b24);
- qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
+ if (qla_ini_mode_enabled(vha)) {
+ qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
+ fcport->logout_on_delete = 0;
+ qlt_schedule_sess_for_deletion_lock(fcport);
+ }
break;
global_port_update:
@@ -1064,19 +1068,6 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
if (qla2x00_is_a_vp_did(vha, rscn_entry))
break;
- /*
- * Search for the rport related to this RSCN entry and mark it
- * as lost.
- */
- list_for_each_entry(fcport, &vha->vp_fcports, list) {
- if (atomic_read(&fcport->state) != FCS_ONLINE)
- continue;
- if (fcport->d_id.b24 == rscn_entry) {
- qla2x00_mark_device_lost(vha, fcport, 0, 0);
- break;
- }
- }
-
atomic_set(&vha->loop_down_timer, 0);
vha->flags.management_server_logged_in = 0;
{
@@ -1279,7 +1270,8 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
index = LSW(pkt->handle);
if (index >= req->num_outstanding_cmds) {
ql_log(ql_log_warn, vha, 0x5031,
- "Invalid command index (%x).\n", index);
+ "Invalid command index (%x) type %8ph.\n",
+ index, iocb);
if (IS_P3P_TYPE(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
else
@@ -2194,6 +2186,7 @@ struct scsi_dif_tuple {
int res = 0;
uint16_t state_flags = 0;
uint16_t retry_delay = 0;
+ uint8_t no_logout = 0;
sts = (sts_entry_t *) pkt;
sts24 = (struct sts_entry_24xx *) pkt;
@@ -2454,6 +2447,7 @@ struct scsi_dif_tuple {
break;
case CS_PORT_LOGGED_OUT:
+ no_logout = 1;
case CS_PORT_CONFIG_CHG:
case CS_PORT_BUSY:
case CS_INCOMPLETE:
@@ -2476,14 +2470,21 @@ struct scsi_dif_tuple {
break;
}
- ql_dbg(ql_dbg_io, fcport->vha, 0x3021,
- "Port to be marked lost on fcport=%02x%02x%02x, current "
- "port state= %s.\n", fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa,
- port_state_str[atomic_read(&fcport->state)]);
+ if (atomic_read(&fcport->state) == FCS_ONLINE) {
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x3021,
+ "Port to be marked lost on fcport=%02x%02x%02x, current "
+ "port state= %s comp_status %x.\n", fcport->d_id.b.domain,
+ fcport->d_id.b.area, fcport->d_id.b.al_pa,
+ port_state_str[atomic_read(&fcport->state)],
+ comp_status);
+
+ if (no_logout)
+ fcport->logout_on_delete = 0;
- if (atomic_read(&fcport->state) == FCS_ONLINE)
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
+ qlt_schedule_sess_for_deletion_lock(fcport);
+ }
+
break;
case CS_ABORTED:
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 133d92a..4be58b0 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1040,6 +1040,34 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
return (return_status);
}
+
+static inline int test_fcport_count(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
+ 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);
+ res = (vha->fcport_count == 0);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
+ return res;
+}
+
+/* qla2x00_wait_for_sess_deletion can only be called from remove_one.
+ * it has dependency on UNLOADING flag to stop device discovery
+ */
+static void
+qla2x00_wait_for_sess_deletion(scsi_qla_host_t *vha)
+{
+ qla2x00_mark_all_devices_lost(vha, 0);
+
+ wait_event(vha->fcport_waitQ, test_fcport_count(vha));
+}
+
/*
* qla2x00_wait_for_hba_ready
* Wait till the HBA is ready before doing driver unload
@@ -3414,12 +3442,15 @@ static void qla2x00_destroy_mbx_wq(struct qla_hw_data *ha)
qla2x00_wait_for_hba_ready(base_vha);
- /* if UNLOAD flag is already set, then continue unload,
+ /*
+ * if UNLOAD flag is already set, then continue unload,
* where it was set first.
*/
if (test_bit(UNLOADING, &base_vha->dpc_flags))
return;
+ qla2x00_wait_for_sess_deletion(base_vha);
+
set_bit(UNLOADING, &base_vha->dpc_flags);
@@ -3578,8 +3609,13 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha)
qla2xxx_wake_dpc(base_vha);
} else {
int now;
- if (rport)
+ if (rport) {
+ ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
+ "%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);
}
}
@@ -3646,9 +3682,12 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
{
fc_port_t *fcport;
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Mark all dev lost\n");
+
list_for_each_entry(fcport, &vha->vp_fcports, list) {
fcport->scan_state = 0;
- qlt_schedule_sess_for_deletion(fcport, 1);
+ qlt_schedule_sess_for_deletion_lock(fcport);
if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx)
continue;
@@ -4271,6 +4310,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
spin_lock_init(&vha->work_lock);
spin_lock_init(&vha->cmd_list_lock);
+ init_waitqueue_head(&vha->fcport_waitQ);
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
ql_dbg(ql_dbg_init, vha, 0x0041,
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index b5c20362..cd7494f 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -399,6 +399,23 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt)
}
+/*
+ * All qlt_plogi_ack_t operations are protected by hardware_lock
+ */
+static int qla24xx_post_nack_work(struct scsi_qla_host *vha, fc_port_t *fcport,
+ struct imm_ntfy_from_isp *ntfy, int type)
+{
+ struct qla_work_evt *e;
+ e = qla2x00_alloc_work(vha, QLA_EVT_NACK);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.nack.fcport = fcport;
+ e->u.nack.type = type;
+ memcpy(e->u.nack.iocb, ntfy, IOCB_SIZE);
+ return qla2x00_post_work(vha, e);
+}
+
static
void qla2x00_async_nack_sp_done(void *v, void *s, int res)
{
@@ -412,17 +429,44 @@ void qla2x00_async_nack_sp_done(void *v, void *s, int res)
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
sp->fcport->flags &= ~FCF_ASYNC_SENT;
+ sp->fcport->chip_reset = vha->hw->chip_reset;
switch (sp->type) {
case SRB_NACK_PLOGI:
sp->fcport->login_gen++;
sp->fcport->fw_login_state = DSC_LS_PLOGI_COMP;
+ sp->fcport->logout_on_delete = 1;
break;
case SRB_NACK_PRLI:
sp->fcport->fw_login_state = DSC_LS_PRLI_COMP;
sp->fcport->deleted = 0;
- vha->fcport_count++;
+
+ if (!sp->fcport->login_succ &&
+ !IS_SW_RESV_ADDR(sp->fcport->d_id)) {
+ sp->fcport->login_succ = 1;
+
+ vha->fcport_count++;
+
+ 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);
+
+ 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);
+
+ qla24xx_post_gpsc_work(vha, sp->fcport);
+ }
+ }
break;
case SRB_NACK_LOGO:
@@ -530,73 +574,76 @@ void qla24xx_delete_sess_fn(struct work_struct *work)
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
-
/*
* Called from qla2x00_reg_remote_port()
*/
void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
{
- struct qla_hw_data *ha = vha->hw;
- struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
- struct fc_port *sess = fcport;
- unsigned long flags;
-
- if (!vha->hw->tgt.tgt_ops)
- return;
-
-
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- if (tgt->tgt_stop) {
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
- return;
- }
-
- if (fcport->disc_state == DSC_DELETE_PEND) {
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
- return;
- }
-
- if (!sess->se_sess) {
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-
- mutex_lock(&vha->vha_tgt.tgt_mutex);
- sess = qlt_create_sess(vha, fcport, false);
- mutex_unlock(&vha->vha_tgt.tgt_mutex);
-
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- } else {
- if (fcport->fw_login_state == DSC_LS_PRLI_COMP) {
+ struct qla_hw_data *ha = vha->hw;
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ struct fc_port *sess = fcport;
+ unsigned long flags;
+
+ if (!vha->hw->tgt.tgt_ops)
+ return;
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ if (tgt->tgt_stop) {
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+ return;
+ }
+
+ if (fcport->disc_state == DSC_DELETE_PEND) {
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+ return;
+ }
+
+ if (!sess->se_sess) {
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
+ mutex_lock(&vha->vha_tgt.tgt_mutex);
+ sess = qlt_create_sess(vha, fcport, false);
+ mutex_unlock(&vha->vha_tgt.tgt_mutex);
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ } else {
+ if (fcport->fw_login_state == DSC_LS_PRLI_COMP) {
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+ return;
+ }
+
+ if (!ha->tgt.tgt_ops->get_sess(sess)) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s: kref_get fail sess %8phC \n",
+ __func__, sess->port_name);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return;
}
- ha->tgt.tgt_ops->get_sess(sess);
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04c,
- "qla_target(%u): %ssession for port %8phC "
- "(loop ID %d) reappeared\n", vha->vp_idx,
- sess->local ? "local " : "", sess->port_name,
- sess->loop_id);
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04c,
+ "qla_target(%u): %ssession for port %8phC "
+ "(loop ID %d) reappeared\n", vha->vp_idx,
+ sess->local ? "local " : "", sess->port_name,
+ sess->loop_id);
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
- "Reappeared sess %p\n", sess);
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
+ "Reappeared sess %p\n", sess);
- ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
- (fcport->flags & FCF_CONF_COMP_SUPPORTED));
- }
+ ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+ (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+ }
- if (sess && sess->local) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04d,
- "qla_target(%u): local session for "
- "port %8phC (loop ID %d) became global\n", vha->vp_idx,
- fcport->port_name, sess->loop_id);
- sess->local = 0;
- }
- ha->tgt.tgt_ops->put_sess(sess);
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+ if (sess && sess->local) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04d,
+ "qla_target(%u): local session for "
+ "port %8phC (loop ID %d) became global\n", vha->vp_idx,
+ fcport->port_name, sess->loop_id);
+ sess->local = 0;
+ }
+ ha->tgt.tgt_ops->put_sess(sess);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
-
/*
* This is a zero-base ref-counting solution, since hardware_lock
* guarantees that ref_count is not modified concurrently.
@@ -635,20 +682,41 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
void qlt_plogi_ack_unref(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla)
{
struct imm_ntfy_from_isp *iocb = (struct imm_ntfy_from_isp *)&pla->iocb;
+ port_id_t port_id;
+ uint16_t loop_id;
+ fc_port_t *fcport = pla->fcport;
+
BUG_ON(!pla->ref_count);
pla->ref_count--;
if (pla->ref_count)
return;
- ql_dbg(ql_dbg_async, vha, 0x5089,
+ ql_dbg(ql_dbg_disc, vha, 0x5089,
"Sending PLOGI ACK to wwn %8phC s_id %02x:%02x:%02x loop_id %#04x"
" exch %#x ox_id %#x\n", iocb->u.isp24.port_name,
iocb->u.isp24.port_id[2], iocb->u.isp24.port_id[1],
iocb->u.isp24.port_id[0],
le16_to_cpu(iocb->u.isp24.nport_handle),
iocb->u.isp24.exchange_address, iocb->ox_id);
- qlt_send_notify_ack(vha, iocb, 0, 0, 0, 0, 0, 0);
+
+ port_id.b.domain = iocb->u.isp24.port_id[2];
+ port_id.b.area = iocb->u.isp24.port_id[1];
+ port_id.b.al_pa = iocb->u.isp24.port_id[0];
+ port_id.b.rsvd_1 = 0;
+
+ loop_id = le16_to_cpu(iocb->u.isp24.nport_handle);
+
+ fcport->loop_id = loop_id;
+ fcport->d_id = port_id;
+ qla24xx_post_nack_work(vha, fcport, iocb, SRB_NACK_PLOGI);
+
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (fcport->plogi_link[QLT_PLOGI_LINK_SAME_WWN] == pla)
+ fcport->plogi_link[QLT_PLOGI_LINK_SAME_WWN] = NULL;
+ if (fcport->plogi_link[QLT_PLOGI_LINK_CONFLICT] == pla)
+ fcport->plogi_link[QLT_PLOGI_LINK_CONFLICT] = NULL;
+ }
list_del(&pla->list);
kmem_cache_free(qla_tgt_plogi_cachep, pla);
@@ -662,15 +730,19 @@ void qlt_plogi_ack_unref(struct scsi_qla_host *vha, qlt_plogi_ack_t *pla)
/* Inc ref_count first because link might already be pointing at pla */
pla->ref_count++;
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf097,
+ "Linking sess %p [%d] wwn %8phC with PLOGI ACK to wwn %8phC"
+ " s_id %02x:%02x:%02x, ref=%d pla %p link %d\n",
+ sess, link, sess->port_name,
+ iocb->u.isp24.port_name, iocb->u.isp24.port_id[2],
+ iocb->u.isp24.port_id[1], iocb->u.isp24.port_id[0],
+ pla->ref_count, pla, link);
+
if (sess->plogi_link[link])
qlt_plogi_ack_unref(vha, sess->plogi_link[link]);
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf097,
- "Linking sess %p [%d] wwn %8phC with PLOGI ACK to wwn %8phC"
- " s_id %02x:%02x:%02x, ref=%d\n", sess, link, sess->port_name,
- iocb->u.isp24.port_name, iocb->u.isp24.port_id[2],
- iocb->u.isp24.port_id[1], iocb->u.isp24.port_id[0],
- pla->ref_count);
+ if (link == QLT_PLOGI_LINK_SAME_WWN)
+ pla->fcport = sess;
sess->plogi_link[link] = pla;
}
@@ -730,7 +802,7 @@ static void qlt_free_session_done(struct work_struct *work)
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
bool logout_started = false;
- fc_port_t fcport;
+ struct event_arg ea;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf084,
"%s: se_sess %p / sess %p from port %8phC loop_id %#04x"
@@ -740,8 +812,8 @@ static void qlt_free_session_done(struct work_struct *work)
sess->logout_on_delete, sess->keep_nport_handle,
sess->send_els_logo);
- BUG_ON(!tgt);
+ if (!IS_SW_RESV_ADDR(sess->d_id)) {
if (sess->send_els_logo) {
qlt_port_logo_t logo;
logo.id = sess->d_id;
@@ -751,20 +823,19 @@ static void qlt_free_session_done(struct work_struct *work)
if (sess->logout_on_delete) {
int rc;
-
- memset(&fcport, 0, sizeof(fcport));
- fcport.loop_id = sess->loop_id;
- fcport.d_id = sess->d_id;
- memcpy(fcport.port_name, sess->port_name, WWN_SIZE);
- fcport.vha = vha;
-
- rc = qla2x00_post_async_logout_work(vha, &fcport, NULL);
+ rc = qla2x00_post_async_logout_work(vha, sess, NULL);
if (rc != QLA_SUCCESS)
ql_log(ql_log_warn, vha, 0xf085,
"Schedule logo failed sess %p rc %d\n",
sess, rc);
else
logout_started = true;
+ } else if (sess->logo_ack_needed) {
+ sess->logo_ack_needed = 0;
+ qla24xx_async_notify_ack(vha, sess,
+ (struct imm_ntfy_from_isp *)sess->iocb, SRB_NACK_LOGO);
+ logout_started = true;
+ }
}
/*
@@ -786,12 +857,36 @@ static void qlt_free_session_done(struct work_struct *work)
msleep(100);
}
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf087,
+ ql_dbg(ql_dbg_disc, vha, 0xf087,
"%s: sess %p logout completed\n",
__func__, sess);
}
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ if (sess->se_sess) {
+ sess->se_sess = NULL;
+ if (tgt && !IS_SW_RESV_ADDR(sess->d_id))
+ tgt->sess_count--;
+ }
+ sess->disc_state = DSC_DELETED;
+ sess->fw_login_state = DSC_LS_PORT_UNAVAIL;
+ sess->deleted = QLA_SESS_DELETED;
+ sess->login_retry = vha->hw->login_retry_count;
+ if (sess->login_succ && !IS_SW_RESV_ADDR(sess->d_id)) {
+ vha->fcport_count--;
+ sess->login_succ = 0;
+ }
+
+ if (sess->chip_reset != sess->vha->hw->chip_reset)
+ qla2x00_clear_loop_id(sess);
+
+
+ if (sess->conflict) {
+ sess->conflict->login_pause = 0;
+ sess->conflict = NULL;
+ if (!test_bit(UNLOADING, &vha->dpc_flags))
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+ }
{
qlt_plogi_ack_t *own = sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
@@ -807,33 +902,46 @@ static void qlt_free_session_done(struct work_struct *work)
own ? own->ref_count : -1,
iocb->u.isp24.port_name, con->ref_count);
qlt_plogi_ack_unref(vha, con);
+ sess->plogi_link[QLT_PLOGI_LINK_CONFLICT] = NULL;
} else {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf09a,
- "se_sess %p / sess %p port %8phC is gone, %s (ref=%d)\n",
- sess->se_sess, sess, sess->port_name,
- own ? "releasing own PLOGI" :
- "no own PLOGI pending",
- own ? own->ref_count : -1);
+ "se_sess %p / sess %p port %8phC is gone, %s (ref=%d)\n",
+ sess->se_sess, sess, sess->port_name,
+ own ? "releasing own PLOGI" : "no own PLOGI pending",
+ own ? own->ref_count : -1);
}
- if (own)
+ if (own) {
+ sess->fw_login_state = DSC_LS_PLOGI_PEND;
qlt_plogi_ack_unref(vha, own);
+ sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] = NULL;
+ }
}
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- sess->se_sess = NULL;
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001,
- "Unregistration of sess %p finished\n", sess);
+ "Unregistration of sess %p %8phC finished fcp_cnt %d\n",
+ sess, sess->port_name, vha->fcport_count);
/*
* We need to protect against race, when tgt is freed before or
* inside wake_up()
*/
- tgt->sess_count--;
- if (tgt->sess_count == 0)
+
+ if (tgt && (tgt->sess_count == 0))
wake_up_all(&tgt->waitQ);
+
+ if (vha->fcport_count == 0)
+ wake_up_all(&vha->fcport_waitQ);
+
+ if (!tgt || !tgt->tgt_stop) {
+ memset(&ea, 0, sizeof(ea));
+ ea.event = FCME_DELETE_DONE;
+ ea.fcport = sess;
+ qla2x00_fcport_event_handler(vha, &ea);
+ }
}
/* ha->tgt.sess_lock supposed to be held on entry */
@@ -899,48 +1007,59 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
iocb, QLA24XX_MGMT_SEND_NACK);
}
+static void qla24xx_chk_fcp_state(struct fc_port *sess)
+{
+ if (sess->chip_reset != sess->vha->hw->chip_reset) {
+ sess->logout_on_delete = 0;
+ sess->logo_ack_needed = 0;
+ sess->fw_login_state = DSC_LS_PORT_UNAVAIL;
+ sess->scan_state = 0;
+ }
+}
+
+
/* ha->tgt.sess_lock supposed to be held on entry */
void qlt_schedule_sess_for_deletion(struct fc_port *sess,
bool immediate)
{
struct qla_tgt *tgt = sess->tgt;
- uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5;
- if (sess->deleted) {
- /* Upgrade to unconditional deletion in case it was temporary */
- if (immediate && sess->deleted == QLA_SESS_DELETION_PENDING)
- list_del(&sess->del_list_entry);
- else
+ if (sess->disc_state == DSC_DELETE_PEND)
+ return;
+
+ if (sess->disc_state == DSC_DELETED) {
+ if (tgt && tgt->tgt_stop && (tgt->sess_count == 0))
+ wake_up_all(&tgt->waitQ);
+ if (sess->vha->fcport_count == 0)
+ wake_up_all(&sess->vha->fcport_waitQ);
+
+ if (!sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] &&
+ !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT])
return;
}
- ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
- "Scheduling sess %p for deletion\n", sess);
+ sess->disc_state = DSC_DELETE_PEND;
- if (immediate) {
- dev_loss_tmo = 0;
- sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
- list_add(&sess->del_list_entry, &tgt->del_sess_list);
- } else {
- sess->deleted = QLA_SESS_DELETION_PENDING;
- list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
- }
+ if (sess->deleted == QLA_SESS_DELETED)
+ sess->logout_on_delete = 0;
- sess->expires = jiffies + dev_loss_tmo * HZ;
+ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
+ qla24xx_chk_fcp_state(sess);
- ql_dbg(ql_dbg_tgt, sess->vha, 0xe048,
- "qla_target(%d): session for port %8phC (loop ID %d s_id %02x:%02x:%02x)"
- " scheduled for deletion in %u secs (expires: %lu) immed: %d, logout: %d, gen: %#x\n",
- sess->vha->vp_idx, sess->port_name, sess->loop_id,
- sess->d_id.b.domain, sess->d_id.b.area, sess->d_id.b.al_pa,
- dev_loss_tmo, sess->expires, immediate, sess->logout_on_delete,
- sess->generation);
+ ql_dbg(ql_dbg_disc, sess->vha, 0xe001,
+ "Scheduling sess %p for deletion %8phC\n",
+ sess, sess->port_name);
- if (immediate)
- mod_delayed_work(system_wq, &tgt->sess_del_work, 0);
- else
- schedule_delayed_work(&tgt->sess_del_work,
- sess->expires - jiffies);
+ schedule_work(&sess->del_work);
+}
+
+void qlt_schedule_sess_for_deletion_lock(struct fc_port *sess)
+{
+ unsigned long flags;
+ struct qla_hw_data *ha = sess->vha->hw;
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ qlt_schedule_sess_for_deletion(sess, 1);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
/* ha->tgt.sess_lock supposed to be held on entry */
@@ -951,7 +1070,7 @@ static void qlt_clear_tgt_db(struct qla_tgt *tgt)
list_for_each_entry(sess, &vha->vp_fcports, list) {
if (sess->se_sess)
- qlt_schedule_sess_for_deletion(sess, true);
+ qlt_schedule_sess_for_deletion(sess, 1);
}
/* At this point tgt could be already dead */
@@ -1006,49 +1125,6 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id,
return res;
}
-/* ha->tgt.sess_lock supposed to be held on entry */
-static void qlt_undelete_sess(struct fc_port *sess)
-{
- BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING);
-
- list_del_init(&sess->del_list_entry);
- sess->deleted = 0;
-}
-
-static void qlt_del_sess_work_fn(struct delayed_work *work)
-{
- struct qla_tgt *tgt = container_of(work, struct qla_tgt,
- sess_del_work);
- struct scsi_qla_host *vha = tgt->vha;
- struct qla_hw_data *ha = vha->hw;
- struct fc_port *sess;
- unsigned long flags, elapsed;
-
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- while (!list_empty(&tgt->del_sess_list)) {
- sess = list_entry(tgt->del_sess_list.next, typeof(*sess),
- del_list_entry);
- elapsed = jiffies;
- if (time_after_eq(elapsed, sess->expires)) {
- /* No turning back */
- list_del_init(&sess->del_list_entry);
- sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
- "Timeout: sess %p about to be deleted\n",
- sess);
- if (sess->se_sess)
- ha->tgt.tgt_ops->shutdown_sess(sess);
- ha->tgt.tgt_ops->put_sess(sess);
- } else {
- schedule_delayed_work(&tgt->sess_del_work,
- sess->expires - elapsed);
- break;
- }
- }
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-}
-
/*
* Adds an extra ref to allow to drop hw lock after adding sess to the list.
* Caller must put it.
@@ -1059,73 +1135,23 @@ static struct fc_port *qlt_create_sess(
bool local)
{
struct qla_hw_data *ha = vha->hw;
- struct fc_port *sess;
+ struct fc_port *sess = fcport;
unsigned long flags;
+ unsigned char be_sid[3];
- /* Check to avoid double sessions */
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- list_for_each_entry(sess, &vha->vp_fcports, list) {
- if (!memcmp(sess->port_name, fcport->port_name, WWN_SIZE)) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005,
- "Double sess %p found (s_id %x:%x:%x, "
- "loop_id %d), updating to d_id %x:%x:%x, "
- "loop_id %d", sess, sess->d_id.b.domain,
- sess->d_id.b.al_pa, sess->d_id.b.area,
- sess->loop_id, fcport->d_id.b.domain,
- fcport->d_id.b.al_pa, fcport->d_id.b.area,
- fcport->loop_id);
-
- /* Cannot undelete at this point */
- if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
- spin_unlock_irqrestore(&ha->tgt.sess_lock,
- flags);
- return NULL;
- }
-
- if (sess->deleted)
- qlt_undelete_sess(sess);
-
- if (!sess->se_sess) {
- if (ha->tgt.tgt_ops->check_initiator_node_acl(vha,
- &sess->port_name[0], sess) < 0) {
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
- return NULL;
- }
- }
-
- ha->tgt.tgt_ops->get_sess(sess);
-
- ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
- (fcport->flags & FCF_CONF_COMP_SUPPORTED));
-
- if (sess->local && !local)
- sess->local = 0;
-
- qlt_do_generation_tick(vha, &sess->generation);
-
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-
- return sess;
+ if (fcport->se_sess) {
+ if (!ha->tgt.tgt_ops->get_sess(sess)) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s: kref_get fail sess %8phC \n",
+ __func__, sess->port_name);
+ return NULL;
}
+ return fcport;
}
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-
- sess = kzalloc(sizeof(*sess), GFP_KERNEL);
- if (!sess) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04a,
- "qla_target(%u): session allocation failed, all commands "
- "from port %8phC will be refused", vha->vp_idx,
- fcport->port_name);
- return NULL;
- }
sess->tgt = vha->vha_tgt.qla_tgt;
- sess->vha = vha;
- sess->d_id = fcport->d_id;
- sess->loop_id = fcport->loop_id;
sess->local = local;
kref_init(&sess->sess_kref);
- INIT_LIST_HEAD(&sess->del_list_entry);
/* Under normal circumstances we want to logout from firmware when
* session eventually ends and release corresponding nport handle.
@@ -1133,28 +1159,10 @@ static struct fc_port *qlt_create_sess(
* code will adjust these flags as necessary. */
sess->logout_on_delete = 1;
sess->keep_nport_handle = 0;
- memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006,
- "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n",
- sess, vha->vha_tgt.qla_tgt);
-
- sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);
- BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
-
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- list_add_tail(&sess->list, &vha->vp_fcports);
-
- vha->vha_tgt.qla_tgt->sess_count++;
- qlt_do_generation_tick(vha, &sess->generation);
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b,
- "qla_target(%d): %ssession for wwn %8phC (loop_id %d, "
- "s_id %x:%x:%x, confirmed completion %ssupported) added\n",
- vha->vp_idx, local ? "local " : "", fcport->port_name,
- fcport->loop_id, sess->d_id.b.domain, sess->d_id.b.area,
- sess->d_id.b.al_pa, sess->conf_compl_supported ? "" : "not ");
+ sess->logout_completed = 0;
+ be_sid[0] = sess->d_id.b.domain;
+ be_sid[1] = sess->d_id.b.area;
+ be_sid[2] = sess->d_id.b.al_pa;
/*
* Determine if this fc_port->port_name is allowed to access
@@ -1164,6 +1172,9 @@ 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,
+ "(%d) %8phC check_initiator_node_acl failed\n",
+ vha->vp_idx, fcport->port_name);
return NULL;
} else {
/*
@@ -1173,51 +1184,25 @@ static struct fc_port *qlt_create_sess(
ha->tgt.tgt_ops->get_sess(sess);
}
- return sess;
-}
-
-/*
- * max_gen - specifies maximum session generation
- * at which this deletion requestion is still valid
- */
-void
-qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
-{
- struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
- struct fc_port *sess = fcport;
- unsigned long flags;
-
- if (!vha->hw->tgt.tgt_ops)
- return;
-
- if (!tgt)
- return;
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ if (!IS_SW_RESV_ADDR(sess->d_id))
+ vha->vha_tgt.qla_tgt->sess_count++;
- spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
- if (tgt->tgt_stop) {
- spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
- return;
- }
- if (!sess->se_sess) {
- spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
- return;
- }
+ qlt_do_generation_tick(vha, &sess->generation);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
- if (max_gen - sess->generation < 0) {
- spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092,
- "Ignoring stale deletion request for se_sess %p / sess %p"
- " for port %8phC, req_gen %d, sess_gen %d\n",
- sess->se_sess, sess, sess->port_name, max_gen,
- sess->generation);
- return;
- }
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006,
+ "Adding sess %p se_sess %p to tgt %p via ->check_initiator_node_acl()\n",
+ sess, sess->se_sess, vha->vha_tgt.qla_tgt);
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf008, "qla_tgt_fc_port_deleted %p", sess);
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b,
+ "qla_target(%d): %ssession for wwn %8phC (loop_id %d, "
+ "s_id %x:%x:%x, confirmed completion %ssupported) added\n",
+ vha->vp_idx, local ? "local " : "", fcport->port_name,
+ fcport->loop_id, sess->d_id.b.domain, sess->d_id.b.area,
+ sess->d_id.b.al_pa, sess->conf_compl_supported ? "" : "not ");
- sess->local = 1;
- qlt_schedule_sess_for_deletion(sess, false);
- spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+ return sess;
}
static inline int test_tgt_sess_count(struct qla_tgt *tgt)
@@ -1229,12 +1214,12 @@ static inline int test_tgt_sess_count(struct qla_tgt *tgt)
* We need to protect against race, when tgt is freed before or
* inside wake_up()
*/
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ql_dbg(ql_dbg_tgt, tgt->vha, 0xe002,
"tgt %p, sess_count=%d\n",
tgt, tgt->sess_count);
res = (tgt->sess_count == 0);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return res;
}
@@ -1282,8 +1267,6 @@ int qlt_stop_phase1(struct qla_tgt *tgt)
mutex_unlock(&vha->vha_tgt.tgt_mutex);
mutex_unlock(&qla_tgt_mutex);
- flush_delayed_work(&tgt->sess_del_work);
-
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf009,
"Waiting for sess works (tgt %p)", tgt);
spin_lock_irqsave(&tgt->sess_work_lock, flags);
@@ -1759,7 +1742,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
- if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ if (sess->deleted) {
qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false);
return;
}
@@ -1944,10 +1927,19 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
return;
}
- if (mcmd->flags == QLA24XX_MGMT_SEND_NACK)
- qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy,
- 0, 0, 0, 0, 0, 0);
- else {
+ if (mcmd->flags == QLA24XX_MGMT_SEND_NACK) {
+ if (mcmd->orig_iocb.imm_ntfy.u.isp24.status_subcode ==
+ ELS_LOGO) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "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);
+ }
+ } else {
if (mcmd->orig_iocb.atio.u.raw.entry_type == ABTS_RECV_24XX)
qlt_24xx_send_abts_resp(vha, &mcmd->orig_iocb.abts,
mcmd->fc_tm_rsp, false);
@@ -2924,7 +2916,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
int res;
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ 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. */
@@ -3104,7 +3096,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!vha->flags.online || (cmd->reset_count != ha->chip_reset) ||
- (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)) {
+ (cmd->sess && cmd->sess->deleted)) {
/*
* Either the port is not online or this request was from
* previous life, just abort the processing.
@@ -3906,7 +3898,11 @@ 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;
- qlt_schedule_sess_for_deletion(cmd->sess, true);
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post del sess\n",
+ __func__, __LINE__, cmd->sess->port_name);
+
+ qlt_schedule_sess_for_deletion_lock(cmd->sess);
}
break;
}
@@ -4190,6 +4186,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
struct fc_port *sess;
struct qla_tgt_cmd *cmd;
+ unsigned long flags;
if (unlikely(tgt->tgt_stop)) {
ql_dbg(ql_dbg_io, vha, 0x3061,
@@ -4218,7 +4215,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 == QLA_SESS_DELETION_IN_PROGRESS) {
+ if (sess->deleted) {
ql_dbg(ql_dbg_io, vha, 0x3061,
"New command while old session %p is being deleted\n",
sess);
@@ -4228,13 +4225,22 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
/*
* Do kref_get() before returning + dropping qla_hw_data->hardware_lock.
*/
- ha->tgt.tgt_ops->get_sess(sess);
+ if (!ha->tgt.tgt_ops->get_sess(sess)) {
+ ql_dbg(ql_dbg_tgt, vha, 0xffff,
+ "%s: kref_get fail, %8phC oxid %x \n",
+ __func__, sess->port_name,
+ be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id));
+ return -EFAULT;
+ }
cmd = qlt_get_tag(vha, sess, atio);
if (!cmd) {
ql_dbg(ql_dbg_io, vha, 0x3062,
"qla_target(%d): Allocation of cmd failed\n", vha->vp_idx);
+
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return -ENOMEM;
}
@@ -4336,7 +4342,7 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
sizeof(struct atio_from_isp));
}
- if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)
+ if (sess->deleted)
return -EFAULT;
return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
@@ -4409,22 +4415,20 @@ static int qlt_abort_task(struct scsi_qla_host *vha,
void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
{
- if (fcport->tgt_session) {
- if (rc != MBS_COMMAND_COMPLETE) {
- ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf093,
- "%s: se_sess %p / sess %p from"
- " port %8phC loop_id %#04x s_id %02x:%02x:%02x"
- " LOGO failed: %#x\n",
- __func__,
- fcport->se_sess,
- fcport->tgt_session,
- fcport->port_name, fcport->loop_id,
- fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa, rc);
- }
-
- fcport->logout_completed = 1;
+ if (rc != MBS_COMMAND_COMPLETE) {
+ ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf093,
+ "%s: se_sess %p / sess %p from"
+ " port %8phC loop_id %#04x s_id %02x:%02x:%02x"
+ " LOGO failed: %#x\n",
+ __func__,
+ fcport->se_sess,
+ fcport,
+ fcport->port_name, fcport->loop_id,
+ fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa, rc);
}
+
+ fcport->logout_completed = 1;
}
/*
@@ -4472,6 +4476,11 @@ struct fc_port *
* 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,
+ "Invalidating sess %p loop_id %d wwn %llx.\n",
+ other_sess, other_sess->loop_id, other_wwn);
+
+
other_sess->keep_nport_handle = 1;
*conflict_sess = other_sess;
qlt_schedule_sess_for_deletion(other_sess,
@@ -4481,7 +4490,8 @@ struct fc_port *
}
/* find other sess with nport handle collision */
- if (loop_id == other_sess->loop_id) {
+ if ((loop_id == other_sess->loop_id) &&
+ (loop_id != FC_NO_LOOP_ID)) {
ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000d,
"Invalidating sess %p loop_id %d wwn %llx.\n",
other_sess, other_sess->loop_id, other_wwn);
@@ -4553,9 +4563,12 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
loop_id = le16_to_cpu(iocb->u.isp24.nport_handle);
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026,
- "qla_target(%d): Port ID: 0x%3phC ELS opcode: 0x%02x\n",
- vha->vp_idx, iocb->u.isp24.port_id, iocb->u.isp24.status_subcode);
+ ql_dbg(ql_dbg_disc, vha, 0xf026,
+ "qla_target(%d): Port ID: %02x:%02x:%02x ELS opcode: 0x%02x lid %d %8phC\n",
+ vha->vp_idx, iocb->u.isp24.port_id[2],
+ iocb->u.isp24.port_id[1], iocb->u.isp24.port_id[0],
+ iocb->u.isp24.status_subcode, loop_id,
+ iocb->u.isp24.port_name);
/* res = 1 means ack at the end of thread
* res = 0 means ack async/later.
@@ -4573,7 +4586,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
}
- if (IS_SW_RESV_ADDR(port_id) || (!sess && !conflict_sess)) {
+ if (IS_SW_RESV_ADDR(port_id)) {
res = 1;
break;
}
@@ -4581,42 +4594,66 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
pla = qlt_plogi_ack_find_add(vha, &port_id, iocb);
if (!pla) {
qlt_send_term_imm_notif(vha, iocb, 1);
-
- res = 0;
break;
}
res = 0;
- if (conflict_sess)
+ if (conflict_sess) {
+ conflict_sess->login_gen++;
qlt_plogi_ack_link(vha, pla, conflict_sess,
- QLT_PLOGI_LINK_CONFLICT);
+ QLT_PLOGI_LINK_CONFLICT);
+ }
- if (!sess)
+ if (!sess) {
+ pla->ref_count++;
+ qla24xx_post_newsess_work(vha, &port_id,
+ iocb->u.isp24.port_name, pla);
+ res = 0;
break;
+ }
qlt_plogi_ack_link(vha, pla, sess, QLT_PLOGI_LINK_SAME_WWN);
- /*
- * Under normal circumstances we want to release nport handle
- * during LOGO process to avoid nport handle leaks inside FW.
- * The exception is when LOGO is done while another PLOGI with
- * the same nport handle is waiting as might be the case here.
- * Note: there is always a possibily of a race where session
- * deletion has already started for other reasons (e.g. ACL
- * removal) and now PLOGI arrives:
- * 1. if PLOGI arrived in FW after nport handle has been freed,
- * FW must have assigned this PLOGI a new/same handle and we
- * can proceed ACK'ing it as usual when session deletion
- * completes.
- * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT
- * bit reached it, the handle has now been released. We'll
- * get an error when we ACK this PLOGI. Nothing will be sent
- * back to initiator. Initiator should eventually retry
- * PLOGI and situation will correct itself.
- */
- sess->keep_nport_handle = ((sess->loop_id == loop_id) &&
- (sess->d_id.b24 == port_id.b24));
- qlt_schedule_sess_for_deletion(sess, true);
+ sess->fw_login_state = DSC_LS_PLOGI_PEND;
+ sess->d_id = port_id;
+ sess->login_gen++;
+
+ switch (sess->disc_state) {
+ case DSC_DELETED:
+ qlt_plogi_ack_unref(vha, pla);
+ break;
+
+ default:
+ /*
+ * Under normal circumstances we want to release nport handle
+ * during LOGO process to avoid nport handle leaks inside FW.
+ * The exception is when LOGO is done while another PLOGI with
+ * the same nport handle is waiting as might be the case here.
+ * Note: there is always a possibily of a race where session
+ * deletion has already started for other reasons (e.g. ACL
+ * removal) and now PLOGI arrives:
+ * 1. if PLOGI arrived in FW after nport handle has been freed,
+ * FW must have assigned this PLOGI a new/same handle and we
+ * can proceed ACK'ing it as usual when session deletion
+ * completes.
+ * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT
+ * bit reached it, the handle has now been released. We'll
+ * get an error when we ACK this PLOGI. Nothing will be sent
+ * back to initiator. Initiator should eventually retry
+ * PLOGI and situation will correct itself.
+ */
+ 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);
+
+
+ qlt_schedule_sess_for_deletion_lock(sess);
+ break;
+ }
+
break;
case ELS_PRLI:
@@ -4639,7 +4676,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
}
if (sess != NULL) {
- if (sess->deleted) {
+ if (sess->fw_login_state == DSC_LS_PLOGI_PEND) {
/*
* Impatient initiator sent PRLI before last
* PLOGI could finish. Will force him to re-try,
@@ -4664,10 +4701,15 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
sess->local = 0;
sess->loop_id = loop_id;
sess->d_id = port_id;
+ sess->fw_login_state = DSC_LS_PRLI_PEND;
if (wd3_lo & BIT_7)
sess->conf_compl_supported = 1;
+ if ((wd3_lo & BIT_4) == 0)
+ sess->port_type = FCT_INITIATOR;
+ else
+ sess->port_type = FCT_TARGET;
}
res = 1; /* send notify ack */
@@ -4677,15 +4719,50 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
} else {
- /* todo: else - create sess here. */
- res = 1; /* send notify ack */
- }
+ if (sess) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post nack\n",
+ __func__, __LINE__, sess->port_name);
+ qla24xx_post_nack_work(vha, sess, iocb,
+ SRB_NACK_PRLI);
+ res = 0;
+ }
+ }
break;
case ELS_LOGO:
case ELS_PRLO:
+ spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+ sess = qla2x00_find_fcport_by_loopid(vha, loop_id);
+ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
+ if (sess) {
+ sess->login_gen++;
+ sess->fw_login_state = DSC_LS_LOGO_PEND;
+ sess->logout_on_delete = 0;
+ sess->logo_ack_needed = 1;
+ memcpy(sess->iocb, iocb, IOCB_SIZE);
+ }
+
res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS);
+
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s: logo %llx res %d sess %p ",
+ __func__, wwn, res, sess);
+ if (res == 0) {
+ /* cmd went up to ULP. look for qlt_xmit_tm_rsp()
+ for LOGO_ACK */
+ BUG_ON(!sess);
+ res = 0;
+ } else {
+ /* cmd did not go upstair. */
+ if (sess) {
+ qlt_schedule_sess_for_deletion_lock(sess);
+ res = 0;
+ }
+ /* else logo will be ack */
+ }
break;
case ELS_PDISC:
case ELS_ADISC:
@@ -4696,6 +4773,16 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
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,
+ "sess %p lid %d|%d DS %d LS %d\n",
+ sess, sess->loop_id, loop_id,
+ sess->disc_state, sess->fw_login_state);
+ }
+
res = 1; /* send notify ack */
break;
}
@@ -5929,8 +6016,10 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
uint16_t loop_id)
{
- fc_port_t *fcport;
+ fc_port_t *fcport, *tfcp, *del;
int rc;
+ unsigned long flags;
+ u8 newfcport = 0;
fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (!fcport) {
@@ -5952,6 +6041,59 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
return NULL;
}
+ del = NULL;
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ tfcp = qla2x00_find_fcport_by_wwpn(vha, fcport->port_name, 1);
+
+ if (tfcp) {
+ tfcp->d_id = fcport->d_id;
+ tfcp->port_type = fcport->port_type;
+ tfcp->supported_classes = fcport->supported_classes;
+ tfcp->flags |= fcport->flags;
+
+ del = fcport;
+ fcport = tfcp;
+ } else {
+ if (vha->hw->current_topology == ISP_CFG_F)
+ fcport->flags |= FCF_FABRIC_DEVICE;
+
+ list_add_tail(&fcport->list, &vha->vp_fcports);
+ if (!IS_SW_RESV_ADDR(fcport->d_id))
+ vha->fcport_count++;
+ fcport->login_gen++;
+ fcport->disc_state = DSC_LOGIN_COMPLETE;
+ fcport->login_succ = 1;
+ newfcport = 1;
+ }
+
+ fcport->deleted = 0;
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+ switch (vha->host->active_mode) {
+ case MODE_INITIATOR:
+ case MODE_DUAL:
+ if (newfcport) {
+ 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__, fcport->port_name, vha->fcport_count);
+ qla24xx_post_upd_fcport_work(vha, fcport);
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post gpsc fcp_cnt %d\n",
+ __func__, __LINE__, fcport->port_name, vha->fcport_count);
+ qla24xx_post_gpsc_work(vha, fcport);
+ }
+ }
+ break;
+
+ case MODE_TARGET:
+ default:
+ break;
+ }
+ if (del)
+ qla2x00_free_fcport(del);
+
return fcport;
}
@@ -5964,6 +6106,17 @@ static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *vha,
int rc, global_resets;
uint16_t loop_id = 0;
+ if ((s_id[0] == 0xFF) && (s_id[1] == 0xFC)) {
+ /*
+ * This is Domain Controller, so it should be
+ * OK to drop SCSI commands from it.
+ */
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf042,
+ "Unable to find initiator with S_ID %x:%x:%x",
+ s_id[0], s_id[1], s_id[2]);
+ return NULL;
+ }
+
mutex_lock(&vha->vha_tgt.tgt_mutex);
retry:
@@ -5974,21 +6127,11 @@ static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *vha,
if (rc != 0) {
mutex_unlock(&vha->vha_tgt.tgt_mutex);
- if ((s_id[0] == 0xFF) &&
- (s_id[1] == 0xFC)) {
- /*
- * This is Domain Controller, so it should be
- * OK to drop SCSI commands from it.
- */
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf042,
- "Unable to find initiator with S_ID %x:%x:%x",
- s_id[0], s_id[1], s_id[2]);
- } else
- ql_log(ql_log_info, vha, 0xf071,
- "qla_target(%d): Unable to find "
- "initiator with S_ID %x:%x:%x",
- vha->vp_idx, s_id[0], s_id[1],
- s_id[2]);
+ ql_log(ql_log_info, vha, 0xf071,
+ "qla_target(%d): Unable to find "
+ "initiator with S_ID %x:%x:%x",
+ vha->vp_idx, s_id[0], s_id[1],
+ s_id[2]);
if (rc == -ENOENT) {
qlt_port_logo_t logo;
@@ -6021,7 +6164,6 @@ static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *vha,
mutex_unlock(&vha->vha_tgt.tgt_mutex);
- qla2x00_free_fcport(fcport);
return sess;
}
@@ -6057,12 +6199,18 @@ static void qlt_abort_work(struct qla_tgt *tgt,
if (!sess)
goto out_term2;
} else {
- if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ if (sess->deleted) {
sess = NULL;
goto out_term2;
}
- ha->tgt.tgt_ops->get_sess(sess);
+ if (!ha->tgt.tgt_ops->get_sess(sess)) {
+ ql_dbg(ql_dbg_tgt_tmr, vha, 0xffff,
+ "%s: kref_get fail %8pHC \n",
+ __func__, sess->port_name);
+ sess = NULL;
+ goto out_term2;
+ }
}
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -6121,12 +6269,18 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
if (!sess)
goto out_term;
} else {
- if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ if (sess->deleted) {
sess = NULL;
goto out_term;
}
- ha->tgt.tgt_ops->get_sess(sess);
+ if (!ha->tgt.tgt_ops->get_sess(sess)) {
+ ql_dbg(ql_dbg_tgt_tmr, vha, 0xffff,
+ "%s: kref_get fail %8pHC \n",
+ __func__, sess->port_name);
+ sess = NULL;
+ goto out_term;
+ }
}
iocb = a;
@@ -6221,8 +6375,6 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
tgt->vha = base_vha;
init_waitqueue_head(&tgt->waitQ);
INIT_LIST_HEAD(&tgt->del_sess_list);
- INIT_DELAYED_WORK(&tgt->sess_del_work,
- (void (*)(struct work_struct *))qlt_del_sess_work_fn);
spin_lock_init(&tgt->sess_work_lock);
INIT_WORK(&tgt->sess_work, qlt_sess_work_fn);
INIT_LIST_HEAD(&tgt->sess_works_list);
@@ -6400,6 +6552,7 @@ static void qlt_set_mode(struct scsi_qla_host *vha)
case QLA2XXX_INI_MODE_ENABLED:
vha->host->active_mode |= MODE_TARGET;
break;
+
default:
break;
}
@@ -6422,6 +6575,7 @@ static void qlt_clear_mode(struct scsi_qla_host *vha)
break;
case QLA2XXX_INI_MODE_ENABLED:
vha->host->active_mode &= ~MODE_TARGET;
+ vha->host->active_mode |= MODE_INITIATOR;
break;
default:
break;
@@ -6544,13 +6698,12 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
* FC-4 Feature bit 0 indicates target functionality to the name server.
*/
if (qla_tgt_mode_enabled(vha)) {
- if (qla_ini_mode_enabled(vha))
- ct_req->req.rff_id.fc4_feature = BIT_0 | BIT_1;
- else
- ct_req->req.rff_id.fc4_feature = BIT_0;
+ ct_req->req.rff_id.fc4_feature = BIT_0;
} else if (qla_ini_mode_enabled(vha)) {
ct_req->req.rff_id.fc4_feature = BIT_1;
- }
+ } else if (qla_dual_mode_enabled(vha))
+ ct_req->req.rff_id.fc4_feature = BIT_0 | BIT_1;
+
}
/*
@@ -6665,7 +6818,7 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
nv->firmware_options_1 |= cpu_to_le32(BIT_4);
/* Disable ini mode, if requested */
- if (!qla_ini_mode_enabled(vha))
+ if (qla_tgt_mode_enabled(vha))
nv->firmware_options_1 |= cpu_to_le32(BIT_5);
/* Disable Full Login after LIP */
nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
@@ -6769,7 +6922,7 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
nv->firmware_options_1 |= cpu_to_le32(BIT_4);
/* Disable ini mode, if requested */
- if (!qla_ini_mode_enabled(vha))
+ if (qla_tgt_mode_enabled(vha))
nv->firmware_options_1 |= cpu_to_le32(BIT_5);
/* Disable Full Login after LIP */
@@ -6880,7 +7033,7 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
if (qla_tgt_mode_enabled(vha))
vpmod->options_idx1 &= ~BIT_5;
/* Disable ini mode, if requested */
- if (!qla_ini_mode_enabled(vha))
+ if (qla_tgt_mode_enabled(vha))
vpmod->options_idx1 &= ~BIT_4;
}
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 6db17ab..6d0d738 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -740,7 +740,7 @@ struct qla_tgt_func_tmpl {
struct fc_port *(*find_sess_by_s_id)(struct scsi_qla_host *,
const uint8_t *);
void (*clear_nacl_from_fcport_map)(struct fc_port *);
- void (*get_sess)(struct fc_port *);
+ int (*get_sess)(struct fc_port *);
void (*put_sess)(struct fc_port *);
void (*shutdown_sess)(struct fc_port *);
void (*release_cmd)(struct qla_tgt_cmd *);
@@ -868,7 +868,6 @@ struct qla_tgt {
/* Protected by hardware_lock */
struct list_head del_sess_list;
- struct delayed_work sess_del_work;
spinlock_t sess_work_lock;
struct list_head sess_works_list;
@@ -904,7 +903,6 @@ struct qla_tgt_sess_op {
enum qla_sess_deletion {
QLA_SESS_DELETION_NONE = 0,
QLA_SESS_DELETION_IN_PROGRESS,
- QLA_SESS_DELETION_PENDING,
QLA_SESS_DELETED,
};
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 8facd3d..c13314a 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -402,12 +402,21 @@ static void tcm_qla2xxx_put_sess(struct fc_port *sess)
kref_put(&sess->sess_kref, tcm_qla2xxx_release_session);
}
-static void tcm_qla2xxx_get_sess(struct fc_port *sess)
+/*
+ * return
+ * 1: kref_get success.
+ * 0: kref_get fail
+ */
+static int tcm_qla2xxx_get_sess(struct fc_port *sess)
{
- if (!sess)
- return;
+ struct se_session *se_sess;
+
+ se_sess = (struct se_session *)sess->se_sess;
+
+ if (!se_sess)
+ return 0;
- kref_get(&sess->sess_kref);
+ return kref_get_unless_zero(&sess->sess_kref);
}
/* tcm_qla2xxx_release_cmd - Callback from TCM Core to release underlying
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 11/22] qla2xxx: Refactor session management code.
2016-12-06 20:30 ` [PATCH 11/22] qla2xxx: Refactor session management code Himanshu Madhani
@ 2016-12-14 21:04 ` Christoph Hellwig
0 siblings, 0 replies; 50+ messages in thread
From: Christoph Hellwig @ 2016-12-14 21:04 UTC (permalink / raw)
To: Himanshu Madhani; +Cc: target-devel, nab, giridhar.malavali, linux-scsi
On Tue, Dec 06, 2016 at 12:30:40PM -0800, Himanshu Madhani wrote:
> 9 files changed, 762 insertions(+), 474 deletions(-)
Again, a refactor that almost doubles the amount of code is a bad
one, please go back to the drawing board.
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 12/22] qla2xxx: Add Dual mode support in the driver
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (10 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 11/22] qla2xxx: Refactor session management code Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-06 20:30 ` [PATCH 13/22] qla2xxx: Fix invalid handle erroneous message Himanshu Madhani
` (10 subsequent siblings)
22 siblings, 0 replies; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
Add switch to allow both Initiator Mode & Target
mode to operate at the same time.
Also remove unwanted/unused ini_mode_force option
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_def.h | 2 +-
drivers/scsi/qla2xxx/qla_init.c | 8 +--
drivers/scsi/qla2xxx/qla_isr.c | 19 +++++-
drivers/scsi/qla2xxx/qla_target.c | 129 +++++++++++++++++++++++++++++--------
drivers/scsi/qla2xxx/qla_target.h | 15 ++---
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 2 +-
6 files changed, 131 insertions(+), 44 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 6370aca..6bf7ff9 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3175,7 +3175,6 @@ struct qlt_hw_data {
/* Protected by hw lock */
uint32_t enable_class_2:1;
uint32_t enable_explicit_conf:1;
- uint32_t ini_mode_force_reverse:1;
uint32_t node_name_set:1;
dma_addr_t atio_dma; /* Physical address. */
@@ -3328,6 +3327,7 @@ struct qla_hw_data {
#define FLOGI_SP_SUPPORT BIT_13
uint8_t port_no; /* Physical port of adapter */
+ uint8_t exch_starvation;
/* Timeout timers. */
uint8_t loop_down_abort_time; /* port down timer */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index cfdfb02..df6a51f 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -813,9 +813,9 @@ 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,
- "%s %8phC DS %d LS %d \n",
+ "%s %8phC DS %d LS %d rval %d \n",
__func__, fcport->port_name, fcport->disc_state,
- fcport->fw_login_state);
+ fcport->fw_login_state, rval);
if (ea->sp->gen2 != fcport->login_gen) {
/* target side must have changed it. */
@@ -4020,7 +4020,8 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
* Process any ATIO queue entries that came in
* while we weren't online.
*/
- if (qla_tgt_mode_enabled(vha)) {
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha)) {
if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) {
spin_lock_irqsave(&ha->tgt.atio_lock,
flags);
@@ -5739,7 +5740,6 @@ int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
if (!status) {
/* Issue a marker after FW becomes ready. */
qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
-
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 7a7a8c6..04899f4 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1029,7 +1029,8 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
qla2x00_mark_all_devices_lost(vha, 1);
- if (vha->vp_idx == 0 && !qla_ini_mode_enabled(vha))
+ if (vha->vp_idx == 0 &&
+ (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)))
set_bit(SCR_PENDING, &vha->dpc_flags);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
@@ -1648,6 +1649,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
fcport->d_id.b.area, fcport->d_id.b.al_pa,
le32_to_cpu(logio->io_parameter[0]));
+ vha->hw->exch_starvation = 0;
data[0] = MBS_COMMAND_COMPLETE;
if (sp->type != SRB_LOGIN_CMD)
goto logio_done;
@@ -1683,6 +1685,21 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
case LSC_SCODE_NPORT_USED:
data[0] = MBS_LOOP_ID_USED;
break;
+ case LSC_SCODE_NOXCB:
+ vha->hw->exch_starvation++;
+ if (vha->hw->exch_starvation > 5) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Exchange starvation. Reseting RISC\n");
+
+ vha->hw->exch_starvation = 0;
+
+ if (IS_P3P_TYPE(vha->hw))
+ set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
+ else
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ }
+ /* drop through */
default:
data[0] = MBS_COMMAND_ERROR;
break;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index cd7494f..8ccbd74 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -53,8 +53,17 @@
"disabled on enabling target mode and then on disabling target mode "
"enabled back; "
"\"disabled\" - initiator mode will never be enabled; "
+ "\"dual\" - Initiator Modes will be enabled. Target Mode can be activated "
+ "when ready "
"\"enabled\" (default) - initiator mode will always stay enabled.");
+static int ql_dm_tgt_ex_pct = 50;
+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 ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
static int temp_sam_status = SAM_STAT_BUSY;
@@ -1285,7 +1294,8 @@ int qlt_stop_phase1(struct qla_tgt *tgt)
wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
/* Big hammer */
- if (!ha->flags.host_shutting_down && qla_tgt_mode_enabled(vha))
+ if (!ha->flags.host_shutting_down &&
+ (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)))
qlt_disable_vha(vha);
/* Wait for sessions to clear out (just in case) */
@@ -5981,7 +5991,6 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
case MBA_LOOP_DOWN:
case MBA_LIP_RESET:
case MBA_RSCN_UPDATE:
- case MBA_REJECTED_FCP_CMD:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03c,
"qla_target(%d): Async event %#x occurred "
"(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx, code,
@@ -5989,6 +5998,35 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
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]));
+
+ 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,
+ "Exchange starvation-. Reseting RISC\n");
+
+ vha->hw->exch_starvation = 0;
+
+ if (IS_P3P_TYPE(vha->hw))
+ set_bit(FCOE_CTX_RESET_NEEDED,
+ &vha->dpc_flags);
+ else
+ set_bit(ISP_ABORT_NEEDED,
+ &vha->dpc_flags);
+
+ qla2xxx_wake_dpc(vha);
+ }
+ }
+
+ break;
+
case MBA_PORT_UPDATE:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03d,
"qla_target(%d): Port update async event %#x "
@@ -5998,10 +6036,11 @@ void qlt_async_event(uint16_t code, struct scsi_qla_host *vha,
le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
login_code = le16_to_cpu(mailbox[2]);
- if (login_code == 0x4)
+ if (login_code == 0x4) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03e,
"Async MB 2: Got PLOGI Complete\n");
- else if (login_code == 0x7)
+ vha->hw->exch_starvation = 0;
+ } else if (login_code == 0x7)
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03f,
"Async MB 2: Port Logged Out\n");
break;
@@ -6542,30 +6581,26 @@ void qlt_lport_deregister(struct scsi_qla_host *vha)
/* Must be called under HW lock */
static void qlt_set_mode(struct scsi_qla_host *vha)
{
- struct qla_hw_data *ha = vha->hw;
-
switch (ql2x_ini_mode) {
case QLA2XXX_INI_MODE_DISABLED:
case QLA2XXX_INI_MODE_EXCLUSIVE:
vha->host->active_mode = MODE_TARGET;
break;
case QLA2XXX_INI_MODE_ENABLED:
- vha->host->active_mode |= MODE_TARGET;
+ vha->host->active_mode = MODE_UNKNOWN;
+ break;
+ case QLA2XXX_INI_MODE_DUAL:
+ vha->host->active_mode = MODE_DUAL;
break;
default:
break;
}
-
- if (ha->tgt.ini_mode_force_reverse)
- qla_reverse_ini_mode(vha);
}
/* Must be called under HW lock */
static void qlt_clear_mode(struct scsi_qla_host *vha)
{
- struct qla_hw_data *ha = vha->hw;
-
switch (ql2x_ini_mode) {
case QLA2XXX_INI_MODE_DISABLED:
vha->host->active_mode = MODE_UNKNOWN;
@@ -6574,15 +6609,12 @@ static void qlt_clear_mode(struct scsi_qla_host *vha)
vha->host->active_mode = MODE_INITIATOR;
break;
case QLA2XXX_INI_MODE_ENABLED:
- vha->host->active_mode &= ~MODE_TARGET;
- vha->host->active_mode |= MODE_INITIATOR;
+ case QLA2XXX_INI_MODE_DUAL:
+ vha->host->active_mode = MODE_INITIATOR;
break;
default:
break;
}
-
- if (ha->tgt.ini_mode_force_reverse)
- qla_reverse_ini_mode(vha);
}
/*
@@ -6670,9 +6702,6 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
void
qlt_vport_create(struct scsi_qla_host *vha, struct qla_hw_data *ha)
{
- if (!qla_tgt_mode_enabled(vha))
- return;
-
vha->vha_tgt.qla_tgt = NULL;
mutex_init(&vha->vha_tgt.tgt_mutex);
@@ -6722,7 +6751,7 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
uint16_t cnt;
struct atio_from_isp *pkt = (struct atio_from_isp *)ha->tgt.atio_ring;
- if (!qla_tgt_mode_enabled(vha))
+ if (qla_ini_mode_enabled(vha))
return;
for (cnt = 0; cnt < ha->tgt.atio_q_length; cnt++) {
@@ -6798,8 +6827,11 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
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(vha)) {
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha)) {
if (!ha->tgt.saved_set) {
/* We save only once */
ha->tgt.saved_exchange_count = nv->exchange_count;
@@ -6812,7 +6844,23 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
ha->tgt.saved_set = 1;
}
- nv->exchange_count = cpu_to_le16(0xFFFF);
+ 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);
+ }
/* Enable target mode */
nv->firmware_options_1 |= cpu_to_le32(BIT_4);
@@ -6899,11 +6947,13 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
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;
- if (qla_tgt_mode_enabled(vha)) {
+ if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
if (!ha->tgt.saved_set) {
/* We save only once */
ha->tgt.saved_exchange_count = nv->exchange_count;
@@ -6916,7 +6966,24 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
ha->tgt.saved_set = 1;
}
- nv->exchange_count = cpu_to_le16(0xFFFF);
+ 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);
+ }
/* Enable target mode */
nv->firmware_options_1 |= cpu_to_le32(BIT_4);
@@ -7030,9 +7097,15 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
qlt_modify_vp_config(struct scsi_qla_host *vha,
struct vp_config_entry_24xx *vpmod)
{
- if (qla_tgt_mode_enabled(vha))
+
+ /* enable target mode.
+ Bit5=1 => disable */
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha))
vpmod->options_idx1 &= ~BIT_5;
- /* Disable ini mode, if requested */
+
+ /* Disable ini mode, if requested.
+ bit4=1 => disable */
if (qla_tgt_mode_enabled(vha))
vpmod->options_idx1 &= ~BIT_4;
}
@@ -7187,6 +7260,8 @@ static int __init qlt_parse_ini_mode(void)
ql2x_ini_mode = QLA2XXX_INI_MODE_DISABLED;
else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_ENABLED) == 0)
ql2x_ini_mode = QLA2XXX_INI_MODE_ENABLED;
+ else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_DUAL) == 0)
+ ql2x_ini_mode = QLA2XXX_INI_MODE_DUAL;
else
return false;
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 6d0d738..90b056e 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -45,10 +45,12 @@
#define QLA2XXX_INI_MODE_STR_EXCLUSIVE "exclusive"
#define QLA2XXX_INI_MODE_STR_DISABLED "disabled"
#define QLA2XXX_INI_MODE_STR_ENABLED "enabled"
+#define QLA2XXX_INI_MODE_STR_DUAL "dual"
#define QLA2XXX_INI_MODE_EXCLUSIVE 0
#define QLA2XXX_INI_MODE_DISABLED 1
#define QLA2XXX_INI_MODE_ENABLED 2
+#define QLA2XXX_INI_MODE_DUAL 3
#define QLA2XXX_COMMAND_COUNT_INIT 250
#define QLA2XXX_IMMED_NOTIFY_COUNT_INIT 250
@@ -1108,7 +1110,9 @@ extern int qlt_lport_register(void *, u64, u64, u64,
* This macro is used during early initializations when host->active_mode
* is not set. Right now, ha value is ignored.
*/
-#define QLA_TGT_MODE_ENABLED() (ql2x_ini_mode != QLA2XXX_INI_MODE_ENABLED)
+#define QLA_TGT_MODE_ENABLED() \
+ ((ql2x_ini_mode != QLA2XXX_INI_MODE_ENABLED) || \
+ (ql2x_ini_mode == QLA2XXX_INI_MODE_DUAL))
extern int ql2x_ini_mode;
static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha)
@@ -1127,15 +1131,6 @@ static inline bool qla_dual_mode_enabled(struct scsi_qla_host *ha)
}
-
-static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)
-{
- if (ha->host->active_mode & MODE_INITIATOR)
- ha->host->active_mode &= ~MODE_INITIATOR;
- else
- ha->host->active_mode |= MODE_INITIATOR;
-}
-
static inline uint32_t sid_to_key(const uint8_t *s_id)
{
uint32_t key;
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index c13314a..08033d8 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -2102,7 +2102,7 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
(struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr;
struct fc_vport_identifiers vport_id;
- if (!qla_tgt_mode_enabled(base_vha)) {
+ if (qla_ini_mode_enabled(base_vha)) {
pr_err("qla2xxx base_vha not enabled for target mode\n");
return -EPERM;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 13/22] qla2xxx: Fix invalid handle erroneous message.
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (11 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 12/22] qla2xxx: Add Dual mode support in the driver Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-06 20:30 ` [PATCH 14/22] qla2xxx: Add interrupt polling mechanism Himanshu Madhani
` (9 subsequent siblings)
22 siblings, 0 replies; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
Termination of Immediate Notification IOCB was using
wrong IOCB handle. IOCB completion code was unable to
find appropriate code path due to wrong handle.
Following message is seen in the logs.
"Error entry - invalid handle/queue (ffff)."
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_isr.c | 9 +++++++++
drivers/scsi/qla2xxx/qla_target.c | 2 +-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 04899f4..c7f73b1 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -2630,6 +2630,15 @@ struct scsi_dif_tuple {
if (pkt->entry_status & RF_BUSY)
res = DID_BUS_BUSY << 16;
+ if ((pkt->entry_type == NOTIFY_ACK_TYPE) &&
+ (pkt->handle == QLA_TGT_SKIP_HANDLE)) {
+ /* There are some NACK that uses the SP method and
+ * some are not using the SP method of sending. filter
+ * NACK here to prevent erroneous err.
+ */
+ return;
+ }
+
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (sp) {
sp->done(vha, sp, res);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 8ccbd74..e6b2a45 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -3344,7 +3344,7 @@ static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha,
pkt->entry_type = NOTIFY_ACK_TYPE;
pkt->entry_count = 1;
- pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
+ pkt->handle = QLA_TGT_SKIP_HANDLE;
nack = (struct nack_to_isp *)pkt;
nack->ox_id = ntfy->ox_id;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 14/22] qla2xxx: Add interrupt polling mechanism
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (12 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 13/22] qla2xxx: Fix invalid handle erroneous message Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-14 21:06 ` Christoph Hellwig
2016-12-06 20:30 ` [PATCH 15/22] qla2xxx: Rename qlini_mode parameter Himanshu Madhani
` (8 subsequent siblings)
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
This patch adds capability to poll for an interrupt, If hardware
does not generate any interrupt for 2 seconds.
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_def.h | 8 +++++
drivers/scsi/qla2xxx/qla_dfs.c | 75 +++++++++++++++++++++++++++++++++++++++
drivers/scsi/qla2xxx/qla_gbl.h | 1 +
drivers/scsi/qla2xxx/qla_isr.c | 22 ++++++++++--
drivers/scsi/qla2xxx/qla_os.c | 31 ++++++++++++++++
drivers/scsi/qla2xxx/qla_target.c | 6 ++++
6 files changed, 141 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 6bf7ff9..09da61f 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2921,6 +2921,10 @@ struct qla_msix_entry {
void *handle;
struct irq_affinity_notify irq_notify;
int cpuid;
+ irqreturn_t (*irq_handler)(int, void *);
+ u32 intr_cnt;
+ u32 last_intr_cnt;
+ struct work_struct intr_work;
};
#define WATCH_INTERVAL 1 /* number of seconds */
@@ -3826,6 +3830,10 @@ struct qla_hw_data {
struct qlt_hw_data tgt;
int allow_cna_fw_dump;
+
+ int irqpoll_interval, irqpoll_cnt;
+ struct dentry *dfs_irqpoll;
+#define MAX_IRQPOLL_INTV 30
};
struct qla_tgt_counters {
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index f69ff52..18cedf7 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -12,6 +12,68 @@
static struct dentry *qla2x00_dfs_root;
static atomic_t qla2x00_dfs_root_count;
+
+static int
+qla_dfs_irqpoll_show(struct seq_file *s, void *unused)
+{
+ struct scsi_qla_host *vha = s->private;
+ struct qla_hw_data *ha = vha->hw;
+
+ seq_printf(s, "IRQ poll interval: %d Seconds (max=%d, def=0/off)\n",
+ ha->irqpoll_interval, MAX_IRQPOLL_INTV);
+
+ return 0;
+}
+
+static ssize_t qla_dfs_irqpoll_write(struct file *file, const char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ struct seq_file *s = file->private_data;
+ char *buf;
+ int ret = 0;
+ int interval = 0;
+ struct scsi_qla_host *vha = s->private;
+ struct qla_hw_data *ha = vha->hw;
+
+ buf = memdup_user(ubuf, len);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ if (sscanf(buf, "%d", &interval) != 1)
+ return -EINVAL;
+
+ if (interval > MAX_IRQPOLL_INTV || interval < 0)
+ return -ERANGE;
+
+ ha->irqpoll_interval = interval;
+
+ if (ha->irqpoll_interval == 0)
+ ql_log(ql_log_info, vha, 0xffff,
+ "IRQ Poll turned off.\n");
+ else
+ ql_log(ql_log_info, vha, 0xffff,
+ "IRQ Poll turned on(%d).\n", ha->irqpoll_interval);
+
+
+ kfree(buf);
+ return (ret) ? ret : len;
+}
+
+static int
+qla_dfs_irqpoll_open(struct inode *inode, struct file *file)
+{
+ struct scsi_qla_host *vha = inode->i_private;
+ return single_open(file, qla_dfs_irqpoll_show, vha);
+}
+
+static const struct file_operations dfs_irqpoll = {
+ .open = qla_dfs_irqpoll_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = qla_dfs_irqpoll_write,
+};
+
static int
qla2x00_dfs_irq_cpuid_show(struct seq_file *s, void *unused)
{
@@ -357,6 +419,14 @@
goto out;
}
+ ha->dfs_irqpoll = debugfs_create_file("irq_poll_interval",
+ S_IRUSR, ha->dfs_dir, vha, &dfs_irqpoll);
+ if (!ha->dfs_irqpoll) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Unable to create debugFS irq_poll_interval node.\n");
+ goto out;
+ }
+
out:
return 0;
@@ -367,6 +437,11 @@
{
struct qla_hw_data *ha = vha->hw;
+ if (ha->dfs_irqpoll) {
+ debugfs_remove(ha->dfs_irqpoll);
+ ha->dfs_irqpoll = NULL;
+ }
+
if (ha->dfs_irq_cpuid) {
debugfs_remove(ha->dfs_irq_cpuid);
ha->dfs_irq_cpuid = NULL;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 3593a39..944f37a 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -140,6 +140,7 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *,
extern int ql2xexlogins;
extern int ql2xexchoffld;
extern int ql2xfwholdabts;
+extern struct workqueue_struct *qla_wq;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index c7f73b1..eee98c9 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -3003,6 +3003,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
}
ha = rsp->hw;
reg = &ha->iobase->isp24;
+ ha->msix_entries[1].intr_cnt++;
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -3047,6 +3048,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
ha = rsp->hw;
reg = &ha->iobase->isp24;
status = 0;
+ ha->msix_entries[0].intr_cnt++;
spin_lock_irqsave(&ha->hardware_lock, flags);
vha = pci_get_drvdata(ha->pdev);
@@ -3150,6 +3152,16 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
return IRQ_HANDLED;
}
+static
+void qla_irq_poll(struct work_struct *work)
+{
+ struct qla_msix_entry *qentry =
+ container_of(work, struct qla_msix_entry, intr_work);
+
+ if (qentry)
+ qentry->irq_handler(qentry->vector, qentry->handle);
+}
+
/* Interrupt handling helpers. */
struct qla_init_msix_entry {
@@ -3235,18 +3247,23 @@ struct qla_init_msix_entry {
rsp->msix = qentry;
scnprintf(qentry->name, sizeof(qentry->name),
msix_entries[i].name);
- if (IS_P3P_TYPE(ha))
+ if (IS_P3P_TYPE(ha)) {
ret = request_irq(qentry->vector,
qla82xx_msix_entries[i].handler,
0, qla82xx_msix_entries[i].name, rsp);
- else
+
+ qentry->irq_handler = qla82xx_msix_entries[i].handler;
+ } else {
ret = request_irq(qentry->vector,
msix_entries[i].handler,
0, msix_entries[i].name, rsp);
+ qentry->irq_handler = msix_entries[i].handler;
+ }
if (ret)
goto msix_register_fail;
qentry->have_irq = 1;
qentry->in_use = 1;
+ INIT_WORK(&qentry->intr_work, qla_irq_poll);
/* Register for CPU affinity notification. */
irq_set_affinity_notifier(qentry->vector, &qentry->irq_notify);
@@ -3278,6 +3295,7 @@ struct qla_init_msix_entry {
qentry->have_irq = 1;
qentry->irq_notify.notify = qla_irq_affinity_notify;
qentry->irq_notify.release = qla_irq_affinity_release;
+ qentry->irq_handler = msix_entries[QLA_ATIO_VECTOR].handler;
/* Register for CPU affinity notification. */
irq_set_affinity_notifier(qentry->vector, &qentry->irq_notify);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 4be58b0..18795c3 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -36,6 +36,9 @@
* CT6 CTX allocation cache
*/
static struct kmem_cache *ctx_cachep;
+
+struct workqueue_struct *qla_wq;
+
/*
* error level for logging
*/
@@ -5895,6 +5898,26 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
qla2xxx_wake_dpc(vha);
}
+ if (ha->irqpoll_interval && ha->msix_count &&
+ (atomic_read(&vha->loop_state) == LOOP_READY) &&
+ (IS_QLA83XX(ha) || IS_QLA27XX(ha))) {
+
+ struct qla_msix_entry *qentry;
+
+ ha->irqpoll_cnt++;
+ if (ha->irqpoll_cnt >= ha->irqpoll_interval) {
+ ha->irqpoll_cnt = 0;
+ /* scan default & rspq 1 */
+ for (index = 0; index < 2; index++) {
+ qentry = &ha->msix_entries[index];
+ if (qentry->last_intr_cnt == qentry->intr_cnt) {
+ queue_work_on(qentry->cpuid, qla_wq, &qentry->intr_work);
+ }
+ qentry->last_intr_cnt = qentry->intr_cnt+1;
+ }
+ }
+ }
+
qla2x00_restart_timer(vha, WATCH_INTERVAL);
}
@@ -6369,6 +6392,13 @@ struct fw_blob *
{
int ret = 0;
+ qla_wq = alloc_workqueue("qla_wq", WQ_MEM_RECLAIM, 0);
+ if (!qla_wq) {
+ ql_log(ql_log_fatal, NULL, 0xffff,
+ "Unable to allocate qla_wq...Failing load!.\n");
+ return -ENOMEM;
+ }
+
/* Allocate cache for SRBs. */
srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
SLAB_HWCACHE_ALIGN, NULL);
@@ -6455,6 +6485,7 @@ struct fw_blob *
kmem_cache_destroy(ctx_cachep);
fc_release_transport(qla2xxx_transport_template);
fc_release_transport(qla2xxx_transport_vport_template);
+ destroy_workqueue(qla_wq);
}
module_init(qla2x00_module_init);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index e6b2a45..cc24d1a 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -7138,8 +7138,14 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
unsigned long flags;
rsp = (struct rsp_que *) dev_id;
+ if (!rsp) {
+ ql_log(ql_log_info, NULL, 0xffff,
+ "%s: NULL atio queue pointer.\n", __func__);
+ return IRQ_NONE;
+ }
ha = rsp->hw;
vha = pci_get_drvdata(ha->pdev);
+ ha->msix_entries[2].intr_cnt++;
spin_lock_irqsave(&ha->tgt.atio_lock, flags);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 14/22] qla2xxx: Add interrupt polling mechanism
2016-12-06 20:30 ` [PATCH 14/22] qla2xxx: Add interrupt polling mechanism Himanshu Madhani
@ 2016-12-14 21:06 ` Christoph Hellwig
2016-12-15 9:27 ` Bart Van Assche
0 siblings, 1 reply; 50+ messages in thread
From: Christoph Hellwig @ 2016-12-14 21:06 UTC (permalink / raw)
To: Himanshu Madhani; +Cc: target-devel, nab, giridhar.malavali, linux-scsi
On Tue, Dec 06, 2016 at 12:30:43PM -0800, Himanshu Madhani wrote:
> From: Quinn Tran <quinn.tran@cavium.com>
>
> This patch adds capability to poll for an interrupt, If hardware
> does not generate any interrupt for 2 seconds.
This description sounds like the hardware might be buggy and not
generate interrupts, in which case 2 seconds is a very long time.
Can you explain the intention a bit better?
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 14/22] qla2xxx: Add interrupt polling mechanism
2016-12-14 21:06 ` Christoph Hellwig
@ 2016-12-15 9:27 ` Bart Van Assche
2016-12-15 17:12 ` Madhani, Himanshu
0 siblings, 1 reply; 50+ messages in thread
From: Bart Van Assche @ 2016-12-15 9:27 UTC (permalink / raw)
To: Christoph Hellwig, Himanshu Madhani
Cc: target-devel, nab, giridhar.malavali, linux-scsi
On 12/14/2016 10:06 PM, Christoph Hellwig wrote:
> On Tue, Dec 06, 2016 at 12:30:43PM -0800, Himanshu Madhani wrote:
>> From: Quinn Tran <quinn.tran@cavium.com>
>>
>> This patch adds capability to poll for an interrupt, If hardware
>> does not generate any interrupt for 2 seconds.
>
> This description sounds like the hardware might be buggy and not
> generate interrupts, in which case 2 seconds is a very long time.
>
> Can you explain the intention a bit better?
In addition to Christoph's question: is this a workaround for a hardware
bug or for a firmware bug? If it is a workaround for a firmware bug,
since the qla2xxx firmware can be upgraded, why is an interrupt polling
mechanism added to the kernel driver instead of fixing the firmware?
Bart.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 14/22] qla2xxx: Add interrupt polling mechanism
2016-12-15 9:27 ` Bart Van Assche
@ 2016-12-15 17:12 ` Madhani, Himanshu
0 siblings, 0 replies; 50+ messages in thread
From: Madhani, Himanshu @ 2016-12-15 17:12 UTC (permalink / raw)
To: Bart Van Assche, Christoph Hellwig
Cc: target-devel@vger.kernel.org, nab@linux-iscsi.org,
Malavali, Giridhar, linux-scsi@vger.kernel.org
Hi Bart, Christoph,
On 12/15/16, 1:27 AM, "Bart Van Assche" <bart.vanassche@gmail.com> wrote:
>On 12/14/2016 10:06 PM, Christoph Hellwig wrote:
>> On Tue, Dec 06, 2016 at 12:30:43PM -0800, Himanshu Madhani wrote:
>>> From: Quinn Tran <quinn.tran@cavium.com>
>>>
>>> This patch adds capability to poll for an interrupt, If hardware
>>> does not generate any interrupt for 2 seconds.
>>
>> This description sounds like the hardware might be buggy and not
>> generate interrupts, in which case 2 seconds is a very long time.
>>
>> Can you explain the intention a bit better?
>
>In addition to Christoph's question: is this a workaround for a hardware
>bug or for a firmware bug? If it is a workaround for a firmware bug,
>since the qla2xxx firmware can be upgraded, why is an interrupt polling
>mechanism added to the kernel driver instead of fixing the firmware?
>
>Bart.
This issue was seen where we were debugging intermittent slow switch response
related to cable pull in a small set of test environment. We thought it was
a HW issue but turns out to be the switch. We left the patch in the test
cycle to see if the problem re-occur and missed taking it out before
submission. Since then we have not seen the problem re-occur. We’ll drop
this patch from the series.
Thanks,
- Himanshu
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 15/22] qla2xxx: Rename qlini_mode parameter
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (13 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 14/22] qla2xxx: Add interrupt polling mechanism Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-14 21:07 ` Christoph Hellwig
2016-12-06 20:30 ` [PATCH 16/22] qla2xxx: Improve RSCN handling in driver Himanshu Madhani
` (7 subsequent siblings)
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
Qlogic's adapter is able to behave in multiple modes:
initiator, target, exclusive/either, and dual/both.
This patch renames the qlini_mode -> qlop_mode and allow
different setting for each port and exchange resource control.
Usage:
modprobe qla2xxx qlop_mode=dual_mode
echo 95 > /sys/class/scsi_host/<host X>/ql_dm_tgt_ex_pct
echo dual_mode > /sys/class/scsi_host/<host X>/f_qlop_mode
echo ini_mode > /sys/class/scsi_host/<host Y>/f_qlop_mode
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_attr.c | 351 ++++++++++++++++++++++++++++++++++++++
drivers/scsi/qla2xxx/qla_def.h | 4 +
drivers/scsi/qla2xxx/qla_gbl.h | 4 +
drivers/scsi/qla2xxx/qla_os.c | 4 +
drivers/scsi/qla2xxx/qla_target.c | 117 ++++++-------
drivers/scsi/qla2xxx/qla_target.h | 22 +--
6 files changed, 425 insertions(+), 77 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index f48b76c..d8b77aa 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1504,6 +1504,351 @@
ha->pep_version[0], ha->pep_version[1], ha->pep_version[2]);
}
+
+static ssize_t
+qla2x00_tgt_ex_pct_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ int len = 0;
+
+ if (ql2x_op_mode == QLA2XXX_OP_MODE_INITIATOR) {
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ "This option is not supported. Driver need to be loaded with "
+ "non-initiator mode (qlop_mode)");
+ return len;
+ }
+
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ "target exchange percentage: new %d : current: %d\n\n",
+ vha->u_tgt_ex_pct, vha->tgt_ex_pct);
+
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ "Please (re)set operating mode via \"f_qlop_mode\" to load new setting\n");
+ return len;
+}
+
+static ssize_t
+qla2x00_tgt_ex_pct_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ int val = 0;
+
+ if (ql2x_op_mode == QLA2XXX_OP_MODE_INITIATOR)
+ goto out;
+
+ if (sscanf(buf, "%d", &val) != 1)
+ return -EINVAL;
+
+ if (val > 100)
+ val = 100;
+ else if (val < 0)
+ val = 0;
+
+ vha->u_tgt_ex_pct = val;
+out:
+ return strlen(buf);
+}
+
+static ssize_t
+qla2x00_opmode_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ int len = 0;
+
+ if (ql2x_op_mode == QLA2XXX_OP_MODE_INITIATOR) {
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ "This option is not supported. Driver need to be loaded with "
+ "non-initiator mode (qlop_mode)");
+ return len;
+ }
+
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ "Supported options: exclusive | tgt_mode | ini_mode | dual_mode\n");
+
+ /* --- */
+ len += scnprintf(buf + len, PAGE_SIZE-len, "Current selection: ");
+
+ switch (vha->qlop_mode) {
+ case QLA2XXX_OP_MODE_EXCLUSIVE:
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ QLA2XXX_OP_MODE_STR_EXCLUSIVE);
+ break;
+ case QLA2XXX_OP_MODE_TARGET:
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ QLA2XXX_OP_MODE_STR_TARGET);
+ break;
+ case QLA2XXX_OP_MODE_INITIATOR:
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ QLA2XXX_OP_MODE_STR_INITIATOR);
+ break;
+ case QLA2XXX_OP_MODE_DUAL:
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ QLA2XXX_OP_MODE_STR_DUAL);
+ break;
+ }
+ len += scnprintf(buf + len, PAGE_SIZE-len, "\n");
+
+ return len;
+}
+
+
+void qla_adj_tgt_exch_pct(scsi_qla_host_t *vha, int op)
+{
+ /* reserve a few exchange for FW for mgt. */
+ switch (op) {
+ case QLA2XXX_OP_MODE_TARGET:
+ vha->u_tgt_ex_pct = MAX_TGT_EXCH_PCT;
+ break;
+
+ case QLA2XXX_OP_MODE_EXCLUSIVE:
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha)) {
+ vha->u_tgt_ex_pct = MAX_TGT_EXCH_PCT;
+ } else
+ vha->u_tgt_ex_pct = 0;
+ break;
+
+ case QLA2XXX_OP_MODE_INITIATOR:
+ /* target mode does not need any exchange reserve. */
+ vha->u_tgt_ex_pct = 0;
+ break;
+
+ case QLA2XXX_OP_MODE_DUAL:
+ if (vha->u_tgt_ex_pct >= 100)
+ vha->u_tgt_ex_pct = MAX_TGT_EXCH_PCT;
+
+ if (vha->u_tgt_ex_pct <= 0)
+ vha->u_tgt_ex_pct = MIN_TGT_EXCH_PCT;
+ break;
+ }
+}
+
+static
+int qla_set_opmode(scsi_qla_host_t *vha, int op)
+{
+ int rc = 0;
+ enum {
+ NO_ACTION,
+ MODE_CHANGE_ACCEPT,
+ MODE_CHANGE_NO_ACTION,
+ TARGET_STILL_ACTIVE,
+ };
+ int action = NO_ACTION;
+ int set_mode = 0;
+
+ qla_adj_tgt_exch_pct(vha, op);
+
+ switch (vha->qlop_mode) {
+ case QLA2XXX_OP_MODE_TARGET:
+ switch (op) {
+ case QLA2XXX_OP_MODE_TARGET:
+ if (qla_tgt_mode_enabled(vha)) {
+ if (vha->tgt_ex_pct != vha->u_tgt_ex_pct)
+ action = MODE_CHANGE_ACCEPT;
+ } else {
+ action = MODE_CHANGE_NO_ACTION;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_EXCLUSIVE:
+ if (qla_tgt_mode_enabled(vha)) {
+ if (vha->tgt_ex_pct != vha->u_tgt_ex_pct)
+ action = MODE_CHANGE_ACCEPT;
+ else
+ action = MODE_CHANGE_NO_ACTION;
+ } else {
+ action = MODE_CHANGE_ACCEPT;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_DUAL:
+ action = MODE_CHANGE_ACCEPT;
+ /* active_mode is target only, reset it to dual */
+ if (qla_tgt_mode_enabled(vha))
+ set_mode = 1;
+ break;
+
+ case QLA2XXX_OP_MODE_INITIATOR:
+ if (qla_tgt_mode_enabled(vha))
+ action = TARGET_STILL_ACTIVE;
+ else
+ action = MODE_CHANGE_ACCEPT;
+ break;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_EXCLUSIVE:
+ switch (op) {
+ case QLA2XXX_OP_MODE_EXCLUSIVE:
+ if (qla_tgt_mode_enabled(vha)) {
+ if (vha->tgt_ex_pct != vha->u_tgt_ex_pct)
+ action = MODE_CHANGE_ACCEPT;
+ else
+ action = NO_ACTION;
+ } else {
+ action = NO_ACTION;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_TARGET:
+ if (qla_tgt_mode_enabled(vha)) {
+ if (vha->tgt_ex_pct != vha->u_tgt_ex_pct)
+ action = MODE_CHANGE_ACCEPT;
+ else
+ action = MODE_CHANGE_NO_ACTION;
+ } else {
+ action = MODE_CHANGE_NO_ACTION;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_DUAL: /* exclusive -> dual */
+ if (qla_tgt_mode_enabled(vha)) {
+ action = MODE_CHANGE_ACCEPT;
+ set_mode = 1;
+ } else {
+ action = MODE_CHANGE_NO_ACTION;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_INITIATOR:
+ if (qla_tgt_mode_enabled(vha))
+ action = TARGET_STILL_ACTIVE;
+ else
+ action = MODE_CHANGE_NO_ACTION;
+ break;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_INITIATOR:
+ switch (op) {
+ case QLA2XXX_OP_MODE_INITIATOR:
+ action = NO_ACTION;
+ break;
+ default:
+ action = MODE_CHANGE_NO_ACTION;
+ break;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_DUAL:
+ switch (op) {
+ case QLA2XXX_OP_MODE_DUAL:
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha)) {
+ if (vha->tgt_ex_pct != vha->u_tgt_ex_pct)
+ action = MODE_CHANGE_ACCEPT;
+ else
+ action = NO_ACTION;
+ } else {
+ action = MODE_CHANGE_NO_ACTION;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_TARGET:
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha)) {
+ /* turning off initiator mode */
+ set_mode = 1;
+ action = MODE_CHANGE_ACCEPT;
+ } else {
+ action = MODE_CHANGE_NO_ACTION;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_EXCLUSIVE:
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha)) {
+ set_mode = 1;
+ action = MODE_CHANGE_ACCEPT;
+ } else {
+ action = MODE_CHANGE_NO_ACTION;
+ }
+ break;
+
+ case QLA2XXX_OP_MODE_INITIATOR:
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha))
+ action = TARGET_STILL_ACTIVE;
+ else
+ action = MODE_CHANGE_NO_ACTION;
+ }
+ break;
+ }
+
+ switch (action) {
+ case MODE_CHANGE_ACCEPT:
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Mode change accepted %d|%d exch pct %d|%d.\n",
+ vha->qlop_mode, op,
+ vha->tgt_ex_pct, vha->u_tgt_ex_pct);
+ vha->qlop_mode = op;
+ vha->tgt_ex_pct = vha->u_tgt_ex_pct;
+ if (set_mode)
+ qlt_set_mode(vha);
+
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ break;
+
+ case MODE_CHANGE_NO_ACTION:
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Mode is set. No action taken. %d|%d pct %d|%d.\n",
+ vha->qlop_mode, op,
+ vha->tgt_ex_pct, vha->u_tgt_ex_pct);
+ vha->tgt_ex_pct = vha->u_tgt_ex_pct;
+ vha->qlop_mode = op;
+ break;
+
+ case TARGET_STILL_ACTIVE:
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Target Mode is active. Unable to change Mode.\n");
+ break;
+
+ case NO_ACTION:
+ default:
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Mode unchange. No action taken. %d|%d pct %d|%d.\n",
+ vha->qlop_mode, op,
+ vha->tgt_ex_pct, vha->u_tgt_ex_pct);
+ break;
+ }
+
+ return rc;
+}
+
+static ssize_t
+qla2x00_opmode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ char op_mode[16];
+ int op;
+
+
+ if (ql2x_op_mode == QLA2XXX_OP_MODE_INITIATOR)
+ return -EINVAL;
+
+ memset(op_mode,0,16);
+ if (sscanf(buf, "%15s", op_mode) != 1)
+ return -EINVAL;
+
+ if (strcasecmp(op_mode, QLA2XXX_OP_MODE_STR_EXCLUSIVE) == 0)
+ op = QLA2XXX_OP_MODE_EXCLUSIVE;
+ else if (strcasecmp(op_mode, QLA2XXX_OP_MODE_STR_TARGET) == 0)
+ op = QLA2XXX_OP_MODE_TARGET;
+ else if (strcasecmp(op_mode, QLA2XXX_OP_MODE_STR_INITIATOR) == 0)
+ op = QLA2XXX_OP_MODE_INITIATOR;
+ else if (strcasecmp(op_mode, QLA2XXX_OP_MODE_STR_DUAL) == 0)
+ op = QLA2XXX_OP_MODE_DUAL;
+ else
+ return -EINVAL;
+
+ qla_set_opmode(vha, op);
+ return strlen(buf);
+}
+
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
@@ -1549,6 +1894,10 @@ static DEVICE_ATTR(allow_cna_fw_dump, S_IRUGO | S_IWUSR,
qla2x00_allow_cna_fw_dump_show,
qla2x00_allow_cna_fw_dump_store);
static DEVICE_ATTR(pep_version, S_IRUGO, qla2x00_pep_version_show, NULL);
+static DEVICE_ATTR(f_qlop_mode, S_IRUGO | S_IWUSR,
+ qla2x00_opmode_show, qla2x00_opmode_store);
+static DEVICE_ATTR(ql_dm_tgt_ex_pct, S_IRUGO | S_IWUSR,
+ qla2x00_tgt_ex_pct_show, qla2x00_tgt_ex_pct_store);
struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_driver_version,
@@ -1583,6 +1932,8 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_fw_dump_size,
&dev_attr_allow_cna_fw_dump,
&dev_attr_pep_version,
+ &dev_attr_f_qlop_mode,
+ &dev_attr_ql_dm_tgt_ex_pct,
NULL,
};
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 09da61f..85beab6 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -4017,6 +4017,10 @@ struct qla_tgt_counters {
/* Count of active session/fcport */
int fcport_count;
wait_queue_head_t fcport_waitQ;
+ int qlop_mode;
+ int tgt_ex_pct, u_tgt_ex_pct;
+#define MAX_TGT_EXCH_PCT 99
+#define MIN_TGT_EXCH_PCT 1
} scsi_qla_host_t;
struct qla27xx_image_status {
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 944f37a..bc2bf57 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -140,8 +140,10 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *,
extern int ql2xexlogins;
extern int ql2xexchoffld;
extern int ql2xfwholdabts;
+extern int ql_dm_tgt_ex_pct;
extern struct workqueue_struct *qla_wq;
+
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
@@ -645,6 +647,7 @@ extern int qla2x00_echo_test(scsi_qla_host_t *,
extern int qla24xx_update_all_fcp_prio(scsi_qla_host_t *);
extern int qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *,
struct qla_fcp_prio_cfg *, uint8_t);
+extern void qla_adj_tgt_exch_pct(scsi_qla_host_t *vha, int op);
/*
* Global Function Prototypes in qla_dfs.c source file.
@@ -849,5 +852,6 @@ void qlt_plogi_ack_link(struct scsi_qla_host *, qlt_plogi_ack_t *,
extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
void qla24xx_delete_sess_fn(struct work_struct *);
+void qlt_set_mode(struct scsi_qla_host *);
#endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 18795c3..845527d 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4301,6 +4301,10 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
vha->host = host;
vha->host_no = host->host_no;
vha->hw = ha;
+ vha->qlop_mode = ql2x_op_mode;
+ vha->u_tgt_ex_pct = ql_dm_tgt_ex_pct;
+ qla_adj_tgt_exch_pct(vha, ql2x_op_mode);
+ vha->tgt_ex_pct = vha->u_tgt_ex_pct;
INIT_LIST_HEAD(&vha->vp_fcports);
INIT_LIST_HEAD(&vha->work_list);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index cc24d1a..089f4ce 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -45,26 +45,26 @@
MODULE_PARM_DESC(ql2xtgt_tape_enable,
"Enables Sequence level error recovery (aka FC Tape). Default is 0 - no SLER. 1 - Enable SLER.");
-static char *qlini_mode = QLA2XXX_INI_MODE_STR_ENABLED;
-module_param(qlini_mode, charp, S_IRUGO);
-MODULE_PARM_DESC(qlini_mode,
- "Determines when initiator mode will be enabled. Possible values: "
+static char *qlop_mode = QLA2XXX_OP_MODE_STR_INITIATOR;
+module_param(qlop_mode, charp, S_IRUGO);
+MODULE_PARM_DESC(qlop_mode,
+ "Determines operating mode. Possible values: "
"\"exclusive\" - initiator mode will be enabled on load, "
"disabled on enabling target mode and then on disabling target mode "
"enabled back; "
- "\"disabled\" - initiator mode will never be enabled; "
- "\"dual\" - Initiator Modes will be enabled. Target Mode can be activated "
- "when ready "
- "\"enabled\" (default) - initiator mode will always stay enabled.");
+ "\"tgt_mode\" - Target mode only. Initiator mode will never be enabled; "
+ "\"dual_mode\" - Initiator Modes will be enabled. Target Mode can be "
+ "activated when ready; "
+ "\"ini_mode\" (default) - initiator mode will always stay enabled.");
-static int ql_dm_tgt_ex_pct = 50;
+int ql_dm_tgt_ex_pct = 50;
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 "
+ "For Dual Mode (qlop_mode=dual_mode), this parameter determines "
"the percentage of exchanges/cmds FW will allocate resources "
"for Target mode.");
-int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
+int ql2x_op_mode = QLA2XXX_OP_MODE_EXCLUSIVE;
static int temp_sam_status = SAM_STAT_BUSY;
@@ -6579,17 +6579,17 @@ void qlt_lport_deregister(struct scsi_qla_host *vha)
EXPORT_SYMBOL(qlt_lport_deregister);
/* Must be called under HW lock */
-static void qlt_set_mode(struct scsi_qla_host *vha)
+void qlt_set_mode(struct scsi_qla_host *vha)
{
- switch (ql2x_ini_mode) {
- case QLA2XXX_INI_MODE_DISABLED:
- case QLA2XXX_INI_MODE_EXCLUSIVE:
+ switch (vha->qlop_mode) {
+ case QLA2XXX_OP_MODE_TARGET:
+ case QLA2XXX_OP_MODE_EXCLUSIVE:
vha->host->active_mode = MODE_TARGET;
break;
- case QLA2XXX_INI_MODE_ENABLED:
+ case QLA2XXX_OP_MODE_INITIATOR:
vha->host->active_mode = MODE_UNKNOWN;
break;
- case QLA2XXX_INI_MODE_DUAL:
+ case QLA2XXX_OP_MODE_DUAL:
vha->host->active_mode = MODE_DUAL;
break;
@@ -6601,15 +6601,15 @@ static void qlt_set_mode(struct scsi_qla_host *vha)
/* Must be called under HW lock */
static void qlt_clear_mode(struct scsi_qla_host *vha)
{
- switch (ql2x_ini_mode) {
- case QLA2XXX_INI_MODE_DISABLED:
+ switch (vha->qlop_mode) {
+ case QLA2XXX_OP_MODE_TARGET:
vha->host->active_mode = MODE_UNKNOWN;
break;
- case QLA2XXX_INI_MODE_EXCLUSIVE:
+ case QLA2XXX_OP_MODE_EXCLUSIVE:
vha->host->active_mode = MODE_INITIATOR;
break;
- case QLA2XXX_INI_MODE_ENABLED:
- case QLA2XXX_INI_MODE_DUAL:
+ case QLA2XXX_OP_MODE_INITIATOR:
+ case QLA2XXX_OP_MODE_DUAL:
vha->host->active_mode = MODE_INITIATOR;
break;
default:
@@ -6844,23 +6844,16 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
ha->tgt.saved_set = 1;
}
- 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;
- }
+ if (vha->tgt_ex_pct <= 0)
+ vha->tgt_ex_pct = MIN_TGT_EXCH_PCT;
- 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);
- }
+ tmp = ha->orig_fw_xcb_count * vha->tgt_ex_pct;
+ tmp = tmp/100;
+ if (tmp > 0xffff)
+ tmp = 0xffff;
+ t = tmp & 0xffff;
+
+ nv->exchange_count = cpu_to_le16(t);
/* Enable target mode */
nv->firmware_options_1 |= cpu_to_le32(BIT_4);
@@ -6966,24 +6959,16 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
ha->tgt.saved_set = 1;
}
- 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;
- }
+ if (vha->tgt_ex_pct <= 0)
+ vha->tgt_ex_pct = MIN_TGT_EXCH_PCT;
- tmp = ha->orig_fw_xcb_count * ql_dm_tgt_ex_pct;
- tmp = tmp/100;
- if (tmp > 0xffff)
- tmp = 0xffff;
+ tmp = ha->orig_fw_xcb_count * vha->tgt_ex_pct;
+ tmp = tmp/100;
+ if (tmp > 0xffff)
+ tmp = 0xffff;
+ t = tmp & 0xffff;
- t = tmp & 0xffff;
- nv->exchange_count = cpu_to_le16(t);
- }
+ nv->exchange_count = cpu_to_le16(t);
/* Enable target mode */
nv->firmware_options_1 |= cpu_to_le32(BIT_4);
@@ -7258,16 +7243,16 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
}
}
-static int __init qlt_parse_ini_mode(void)
+static int __init qlt_parse_operating_mode(void)
{
- if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_EXCLUSIVE) == 0)
- ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE;
- else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_DISABLED) == 0)
- ql2x_ini_mode = QLA2XXX_INI_MODE_DISABLED;
- else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_ENABLED) == 0)
- ql2x_ini_mode = QLA2XXX_INI_MODE_ENABLED;
- else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_DUAL) == 0)
- ql2x_ini_mode = QLA2XXX_INI_MODE_DUAL;
+ if (strcasecmp(qlop_mode, QLA2XXX_OP_MODE_STR_EXCLUSIVE) == 0)
+ ql2x_op_mode = QLA2XXX_OP_MODE_EXCLUSIVE;
+ else if (strcasecmp(qlop_mode, QLA2XXX_OP_MODE_STR_TARGET) == 0)
+ ql2x_op_mode = QLA2XXX_OP_MODE_TARGET;
+ else if (strcasecmp(qlop_mode, QLA2XXX_OP_MODE_STR_INITIATOR) == 0)
+ ql2x_op_mode = QLA2XXX_OP_MODE_INITIATOR;
+ else if (strcasecmp(qlop_mode, QLA2XXX_OP_MODE_STR_DUAL) == 0)
+ ql2x_op_mode = QLA2XXX_OP_MODE_DUAL;
else
return false;
@@ -7278,9 +7263,9 @@ int __init qlt_init(void)
{
int ret;
- if (!qlt_parse_ini_mode()) {
+ if (!qlt_parse_operating_mode()) {
ql_log(ql_log_fatal, NULL, 0xe06b,
- "qlt_parse_ini_mode() failed\n");
+ "qlt_parse_operating_mode() failed\n");
return -EINVAL;
}
@@ -7309,7 +7294,7 @@ int __init qlt_init(void)
/*
* Return 1 to signal that initiator-mode is being disabled
*/
- return (ql2x_ini_mode == QLA2XXX_INI_MODE_DISABLED) ? 1 : 0;
+ return (ql2x_op_mode == QLA2XXX_OP_MODE_TARGET) ? 1 : 0;
out_plogi_cachep:
kmem_cache_destroy(qla_tgt_plogi_cachep);
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 90b056e..507b8d9 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -42,15 +42,15 @@
*/
#define QLA2XXX_INITIATOR_MAGIC 57222
-#define QLA2XXX_INI_MODE_STR_EXCLUSIVE "exclusive"
-#define QLA2XXX_INI_MODE_STR_DISABLED "disabled"
-#define QLA2XXX_INI_MODE_STR_ENABLED "enabled"
-#define QLA2XXX_INI_MODE_STR_DUAL "dual"
+#define QLA2XXX_OP_MODE_STR_EXCLUSIVE "exclusive"
+#define QLA2XXX_OP_MODE_STR_TARGET "tgt_mode"
+#define QLA2XXX_OP_MODE_STR_INITIATOR "ini_mode"
+#define QLA2XXX_OP_MODE_STR_DUAL "dual_mode"
-#define QLA2XXX_INI_MODE_EXCLUSIVE 0
-#define QLA2XXX_INI_MODE_DISABLED 1
-#define QLA2XXX_INI_MODE_ENABLED 2
-#define QLA2XXX_INI_MODE_DUAL 3
+#define QLA2XXX_OP_MODE_EXCLUSIVE 0
+#define QLA2XXX_OP_MODE_TARGET 1
+#define QLA2XXX_OP_MODE_INITIATOR 2
+#define QLA2XXX_OP_MODE_DUAL 3
#define QLA2XXX_COMMAND_COUNT_INIT 250
#define QLA2XXX_IMMED_NOTIFY_COUNT_INIT 250
@@ -1111,9 +1111,9 @@ extern int qlt_lport_register(void *, u64, u64, u64,
* is not set. Right now, ha value is ignored.
*/
#define QLA_TGT_MODE_ENABLED() \
- ((ql2x_ini_mode != QLA2XXX_INI_MODE_ENABLED) || \
- (ql2x_ini_mode == QLA2XXX_INI_MODE_DUAL))
-extern int ql2x_ini_mode;
+ (ql2x_op_mode != QLA2XXX_OP_MODE_INITIATOR)
+
+extern int ql2x_op_mode;
static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha)
{
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 15/22] qla2xxx: Rename qlini_mode parameter
2016-12-06 20:30 ` [PATCH 15/22] qla2xxx: Rename qlini_mode parameter Himanshu Madhani
@ 2016-12-14 21:07 ` Christoph Hellwig
2016-12-15 17:21 ` Madhani, Himanshu
0 siblings, 1 reply; 50+ messages in thread
From: Christoph Hellwig @ 2016-12-14 21:07 UTC (permalink / raw)
To: Himanshu Madhani; +Cc: target-devel, nab, giridhar.malavali, linux-scsi
On Tue, Dec 06, 2016 at 12:30:44PM -0800, Himanshu Madhani wrote:
> From: Quinn Tran <quinn.tran@cavium.com>
>
> Qlogic's adapter is able to behave in multiple modes:
> initiator, target, exclusive/either, and dual/both.
>
> This patch renames the qlini_mode -> qlop_mode and allow
> different setting for each port and exchange resource control.
Removing an old module parameter will break existing setups. Please
add the new one overriding the old parameter, but don't remove the old
one.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 15/22] qla2xxx: Rename qlini_mode parameter
2016-12-14 21:07 ` Christoph Hellwig
@ 2016-12-15 17:21 ` Madhani, Himanshu
0 siblings, 0 replies; 50+ messages in thread
From: Madhani, Himanshu @ 2016-12-15 17:21 UTC (permalink / raw)
To: Christoph Hellwig
Cc: target-devel@vger.kernel.org, nab@linux-iscsi.org,
Malavali, Giridhar, linux-scsi@vger.kernel.org
On 12/14/16, 1:07 PM, "Christoph Hellwig" <hch@infradead.org> wrote:
>On Tue, Dec 06, 2016 at 12:30:44PM -0800, Himanshu Madhani wrote:
>> From: Quinn Tran <quinn.tran@cavium.com>
>>
>> Qlogic's adapter is able to behave in multiple modes:
>> initiator, target, exclusive/either, and dual/both.
>>
>> This patch renames the qlini_mode -> qlop_mode and allow
>> different setting for each port and exchange resource control.
>
>Removing an old module parameter will break existing setups. Please
>add the new one overriding the old parameter, but don't remove the old
>one.
Ack. Will revise patch to preserve old parameter.
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 16/22] qla2xxx: Improve RSCN handling in driver
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (14 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 15/22] qla2xxx: Rename qlini_mode parameter Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-07 11:32 ` Hannes Reinecke
2016-12-06 20:30 ` [PATCH 17/22] qla2xxx: Rerfactor use of sp context Himanshu Madhani
` (6 subsequent siblings)
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
- Save NPort ID early in link init.
- Add session deletion for TPRLO and send acknowledgement for TPRLO.
- Enable FW option to move ABTS, RIDA & PUREX from RSPQ
to ATIOQ.
- Move ABTS & RIDA to ATIOQ helps in keeping command ordering and
link up sequence ordering.
- Save Nport ID and update VP map so that SCSI CMD/ATIO
won't be dropped.
- fcport alloc does the initializes memory to zero. Remove
memset to zero since It migth corrupt link list.
- Turn off Registration for State Change MB in loop mode.
Current code blindly do State Change Registration when
the link is up. Move SCR behind fabric scan, so AL case
would not get erroneous error message.
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_def.h | 12 +-
drivers/scsi/qla2xxx/qla_fw.h | 59 +++++++---
drivers/scsi/qla2xxx/qla_gbl.h | 2 +
drivers/scsi/qla2xxx/qla_gs.c | 4 +-
drivers/scsi/qla2xxx/qla_init.c | 150 ++++++++++++++++++++----
drivers/scsi/qla2xxx/qla_isr.c | 6 +-
drivers/scsi/qla2xxx/qla_mbx.c | 123 ++++++++++++--------
drivers/scsi/qla2xxx/qla_os.c | 48 ++++----
drivers/scsi/qla2xxx/qla_target.c | 237 ++++++++++++++++++++++++++++++++++----
9 files changed, 501 insertions(+), 140 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 85beab6..f9a4528 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2141,6 +2141,14 @@ enum fcport_mgt_event {
FCME_DELETE_DONE,
};
+enum rscn_addr_format {
+ RSCN_PORT_ADDR,
+ RSCN_AREA_ADDR,
+ RSCN_DOM_ADDR,
+ RSCN_FAB_ADDR,
+};
+
+
/*
* Fibre channel port structure.
*/
@@ -3907,7 +3915,7 @@ struct qla_tgt_counters {
#define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */
#define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */
#define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */
-#define SCR_PENDING 21 /* SCR in target mode */
+#define FREE_BIT 21
#define PORT_UPDATE_NEEDED 22
#define FX00_RESET_RECOVERY 23
#define FX00_TARGET_SCAN 24
@@ -3961,7 +3969,9 @@ struct qla_tgt_counters {
/* list of commands waiting on workqueue */
struct list_head qla_cmd_list;
struct list_head qla_sess_op_cmd_list;
+ struct list_head unknown_atio_list;
spinlock_t cmd_list_lock;
+ struct delayed_work unknown_atio_work;
/* Counter to detect races between ELS and RSCN events */
atomic_t generation_tick;
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 00938f1..6f3439c 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1300,27 +1300,60 @@ struct vp_config_entry_24xx {
};
#define VP_RPT_ID_IOCB_TYPE 0x32 /* Report ID Acquisition entry. */
+enum VP_STATUS {
+ VP_STAT_COMPL,
+ VP_STAT_FAIL,
+ VP_STAT_ID_CHG,
+ VP_STAT_SNS_TO, /* timeout */
+ VP_STAT_SNS_RJT,
+ VP_STAT_SCR_TO, /* timeout */
+ VP_STAT_SCR_RJT,
+};
+
+enum VP_FLAGS {
+ VP_FLAGS_CON_FLOOP = 1,
+ VP_FLAGS_CON_P2P = 2,
+ VP_FLAGS_CON_FABRIC = 3,
+ VP_FLAGS_NAME_VALID = BIT_5,
+};
+
struct vp_rpt_id_entry_24xx {
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 vp_count; /* Format 0 -- | VP setup | VP acq |. */
- /* Format 1 -- | VP count |. */
- uint16_t vp_idx; /* Format 0 -- Reserved. */
- /* Format 1 -- VP status and index. */
+ uint32_t resv1;
+ uint8_t vp_acquired;
+ uint8_t vp_setup;
+ uint8_t vp_idx; /* Format 0=reserved */
+ uint8_t vp_status; /* Format 0=reserved */
uint8_t port_id[3];
uint8_t format;
-
- uint8_t vp_idx_map[16];
-
- uint8_t reserved_4[24];
- uint16_t bbcr;
- uint8_t reserved_5[6];
+ union {
+ struct {
+ /* format 0 loop */
+ uint8_t vp_idx_map[16];
+ uint8_t reserved_4[32];
+ } f0;
+ struct {
+ /* format 1 fabric */
+ uint8_t vpstat1_subcode; /* vp_status=1 subcode */
+ uint8_t flags;
+ uint16_t fip_flags;
+ uint8_t rsv2[12];
+
+ uint8_t ls_rjt_vendor;
+ uint8_t ls_rjt_explanation;
+ uint8_t ls_rjt_reason;
+ uint8_t rsv3[5];
+
+ uint8_t port_name[8];
+ uint8_t node_name[8];
+ uint16_t bbcr;
+ uint8_t reserved_5[6];
+ } f1;
+ } u;
};
#define VF_EVFP_IOCB_TYPE 0x26 /* Exchange Virtual Fabric Parameters entry. */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index bc2bf57..2e28b3f 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -142,6 +142,7 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *,
extern int ql2xfwholdabts;
extern int ql_dm_tgt_ex_pct;
extern struct workqueue_struct *qla_wq;
+extern int ql2xmvasynctoatio;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
@@ -853,5 +854,6 @@ extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
void qla24xx_delete_sess_fn(struct work_struct *);
void qlt_set_mode(struct scsi_qla_host *);
+void qlt_unknown_atio_work_fn(struct delayed_work *);
#endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index fa49470..1e70a58 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -2922,8 +2922,10 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
int qla24xx_post_gidpn_work(struct scsi_qla_host *vha, fc_port_t *fcport)
{
struct qla_work_evt *e;
+ int ls;
- if ((atomic_read(&vha->loop_state) != LOOP_READY) ||
+ ls = atomic_read(&vha->loop_state);
+ if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
test_bit(UNLOADING, &vha->dpc_flags))
return 0;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index df6a51f..1899333 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1091,9 +1091,9 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
struct event_arg *ea)
{
- fc_port_t *fcport;
+ fc_port_t *fcport, *f, *tf;
int rc;
-
+ uint32_t id=0, mask, rid;
switch (ea->event) {
case FCME_RELOGIN:
@@ -1107,19 +1107,59 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
if (test_bit(UNLOADING, &vha->dpc_flags))
return;
- fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
- if (!fcport) {
- /* 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);
+ switch (ea->id.b.rsvd_1) {
+ case RSCN_PORT_ADDR:
+ fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
+ if (!fcport) {
+ /* 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);
+ }
+ } else {
+ ea->fcport = fcport;
+ qla24xx_handle_rscn_event(fcport, ea);
}
- } else {
- ea->fcport = fcport;
- qla24xx_handle_rscn_event(fcport, ea);
+ break;
+
+ case RSCN_AREA_ADDR:
+ 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);
+ } else {
+ mask = 0xff0000;
+ ql_log(ql_dbg_async, vha, 0xffff,
+ "RSCN: Domain 0x%06x was affected\n",
+ ea->id.b24);
+ }
+
+ rid = ea->id.b24 & mask;
+
+ list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
+ id = f->d_id.b24 & mask;
+
+ if (rid == id) {
+ ea->fcport = f;
+ qla24xx_handle_rscn_event(f, 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);
+ qla2x00_mark_all_devices_lost(vha, 1);
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ break;
}
break;
case FCME_GIDPN_DONE:
@@ -2971,6 +3011,21 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
__func__, ha->fw_options[2]);
}
+ /* Move PUREX, ABTS RX & RIDA to ATIOQ */
+ if (ql2xmvasynctoatio) {
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha))
+ ha->fw_options[2] |= BIT_11;
+ else
+ 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);
+
/* Update Serial Link options. */
if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
return;
@@ -3980,10 +4035,11 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
} else if (ha->current_topology == ISP_CFG_N) {
clear_bit(RSCN_UPDATE, &flags);
-
+ } else if (ha->current_topology == ISP_CFG_NL) {
+ clear_bit(RSCN_UPDATE, &flags);
+ set_bit(LOCAL_LOOP_UPDATE, &flags);
} else if (!vha->flags.online ||
(test_bit(ABORT_ISP_ACTIVE, &flags))) {
-
set_bit(RSCN_UPDATE, &flags);
set_bit(LOCAL_LOOP_UPDATE, &flags);
}
@@ -4085,6 +4141,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
uint16_t loop_id;
uint8_t domain, area, al_pa;
struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
found_devs = 0;
new_fcport = NULL;
@@ -4125,7 +4182,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
"Marking port lost loop_id=0x%04x.\n",
fcport->loop_id);
- qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
+ qla2x00_mark_device_lost(vha, fcport, 0,0);
}
}
@@ -4156,13 +4213,14 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
if (loop_id > LAST_LOCAL_LOOP_ID)
continue;
- memset(new_fcport, 0, sizeof(fc_port_t));
+ memset(new_fcport->port_name, 0, WWN_SIZE);
/* Fill in member data. */
new_fcport->d_id.b.domain = domain;
new_fcport->d_id.b.area = area;
new_fcport->d_id.b.al_pa = al_pa;
new_fcport->loop_id = loop_id;
+
rval2 = qla2x00_get_port_database(vha, new_fcport, 0);
if (rval2 != QLA_SUCCESS) {
ql_dbg(ql_dbg_disc, vha, 0x201a,
@@ -4175,6 +4233,8 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
continue;
}
+
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
/* Check for matching device in port list. */
found = 0;
fcport = NULL;
@@ -4190,6 +4250,12 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
memcpy(fcport->node_name, new_fcport->node_name,
WWN_SIZE);
+ if (!fcport->login_succ) {
+ vha->fcport_count++;
+ fcport->login_succ = 1;
+ fcport->disc_state = DSC_LOGIN_COMPLETE;
+ }
+
found++;
break;
}
@@ -4200,16 +4266,28 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
/* Allocate a new replacement fcport. */
fcport = new_fcport;
+ if (!fcport->login_succ) {
+ vha->fcport_count++;
+ fcport->login_succ = 1;
+ fcport->disc_state = DSC_LOGIN_COMPLETE;
+ }
+
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
+
if (new_fcport == NULL) {
ql_log(ql_log_warn, vha, 0x201c,
"Failed to allocate memory for fcport.\n");
rval = QLA_MEMORY_ALLOC_FAILED;
goto cleanup_allocation;
}
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
new_fcport->flags &= ~FCF_FABRIC_DEVICE;
}
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
/* Base iIDMA settings on HBA port speed. */
fcport->fp_speed = ha->link_data_rate;
@@ -4400,6 +4478,16 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
}
vha->device_flags |= SWITCH_FOUND;
+
+ if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
+ rval = qla2x00_send_change_request(vha, 0x3, 0);
+ if (rval != QLA_SUCCESS)
+ ql_log(ql_log_warn, vha, 0x121,
+ "Failed to enable receiving of RSCN requests: 0x%x.\n",
+ rval);
+ }
+
+
do {
qla2x00_mgmt_svr_login(vha);
@@ -7174,6 +7262,7 @@ uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
ql_log(ql_log_warn, vha, 0x0076,
"NVRAM configuration failed.\n");
}
+
return (rval);
}
@@ -7294,13 +7383,26 @@ uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
__func__, ha->fw_options[2]);
}
- if (!ql2xetsenable)
- goto out;
+ /* Move PUREX, ABTS RX & RIDA to ATIOQ */
+ if (ql2xmvasynctoatio) {
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha))
+ ha->fw_options[2] |= BIT_11;
+ else
+ ha->fw_options[2] &= ~BIT_11;
+ }
+
+ 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);
- /* Enable ETS Burst. */
- memset(ha->fw_options, 0, sizeof(ha->fw_options));
- ha->fw_options[2] |= BIT_9;
-out:
qla2x00_set_fw_options(vha, ha->fw_options);
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index eee98c9..dac59b3 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1029,10 +1029,6 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
qla2x00_mark_all_devices_lost(vha, 1);
- if (vha->vp_idx == 0 &&
- (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)))
- set_bit(SCR_PENDING, &vha->dpc_flags);
-
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
set_bit(VP_CONFIG_OK, &vha->vp_flags);
@@ -1076,7 +1072,9 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
memset(&ea, 0, sizeof(ea));
ea.event = FCME_RSCN;
ea.id.b24 = rscn_entry;
+ ea.id.b.rsvd_1 = rscn_entry >> 24;
qla2x00_fcport_event_handler(vha, &ea);
+ qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
}
break;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 44be150..3caaf06 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -454,6 +454,9 @@ static int is_rom_cmd(uint16_t cmd)
mbx_done:
if (rval) {
+ if (command == MBC_MID_INITIALIZE_FIRMWARE)
+ ha->isp_ops->fw_dump(vha, 0);
+
ql_dbg(ql_dbg_disc, base_vha, 0x1020,
"**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n",
mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], command);
@@ -3641,10 +3644,8 @@ struct tsk_mgmt_cmd {
qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
struct vp_rpt_id_entry_24xx *rptid_entry)
{
- uint8_t vp_idx;
- uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
struct qla_hw_data *ha = vha->hw;
- scsi_qla_host_t *vp;
+ scsi_qla_host_t *vp = NULL;
unsigned long flags;
int found;
@@ -3655,78 +3656,106 @@ struct tsk_mgmt_cmd {
return;
if (rptid_entry->format == 0) {
+ /* loop */
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b7,
"Format 0 : Number of VPs setup %d, number of "
"VPs acquired %d.\n",
- MSB(le16_to_cpu(rptid_entry->vp_count)),
- LSB(le16_to_cpu(rptid_entry->vp_count)));
+ rptid_entry->vp_setup,rptid_entry->vp_acquired);
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b8,
"Primary port id %02x%02x%02x.\n",
rptid_entry->port_id[2], rptid_entry->port_id[1],
rptid_entry->port_id[0]);
+
+ vha->d_id.b.domain = rptid_entry->port_id[2];
+ vha->d_id.b.area = rptid_entry->port_id[1];
+ vha->d_id.b.al_pa = rptid_entry->port_id[0];
+
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ qlt_update_vp_map(vha, SET_AL_PA);
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
+
} else if (rptid_entry->format == 1) {
- vp_idx = LSB(stat);
+ /* fabric */
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b9,
"Format 1: VP[%d] enabled - status %d - with "
- "port id %02x%02x%02x.\n", vp_idx, MSB(stat),
+ "port id %02x%02x%02x.\n", rptid_entry->vp_idx,
+ rptid_entry->vp_status,
rptid_entry->port_id[2], rptid_entry->port_id[1],
rptid_entry->port_id[0]);
/* buffer to buffer credit flag */
- vha->flags.bbcr_enable = (rptid_entry->bbcr & 0xf) != 0;
+ vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0;
+
- /* FA-WWN is only for physical port */
- if (!vp_idx) {
- void *wwpn = ha->init_cb->port_name;
+ if (rptid_entry->vp_idx == 0) {
+ if (rptid_entry->vp_status == VP_STAT_COMPL) {
- if (!MSB(stat)) {
- if (rptid_entry->vp_idx_map[1] & BIT_6)
- wwpn = rptid_entry->reserved_4 + 8;
+#if 0
+ /* FA-WWN is only for physical port */
+
+ /* To Do: For Target Mode, changing WWPN during
+ * runtime cause Target un-config problem. The FA-WWN
+ * should be saved in separate field.
+ */
+ if (rptid_entry->u.f1.flags & VP_FLAGS_NAME_VALID) {
+ memcpy(vha->port_name, rptid_entry->u.f1.port_name,
+ WWN_SIZE);
+ }
+#endif
+
+ vha->d_id.b.domain = rptid_entry->port_id[2];
+ vha->d_id.b.area = rptid_entry->port_id[1];
+ vha->d_id.b.al_pa = rptid_entry->port_id[0];
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ qlt_update_vp_map(vha, SET_AL_PA);
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
}
- memcpy(vha->port_name, wwpn, WWN_SIZE);
+
fc_host_port_name(vha->host) =
wwn_to_u64(vha->port_name);
ql_dbg(ql_dbg_mbx, vha, 0x1018,
"FA-WWN portname %016llx (%x)\n",
- fc_host_port_name(vha->host), MSB(stat));
- }
-
- vp = vha;
- if (vp_idx == 0)
- goto reg_needed;
+ fc_host_port_name(vha->host), rptid_entry->vp_status);
+ set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
+ set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
- if (MSB(stat) != 0 && MSB(stat) != 2) {
- ql_dbg(ql_dbg_mbx, vha, 0x10ba,
- "Could not acquire ID for VP[%d].\n", vp_idx);
- return;
- }
+ } else {
+ if (rptid_entry->vp_status != VP_STAT_COMPL &&
+ rptid_entry->vp_status != VP_STAT_ID_CHG) {
+ ql_dbg(ql_dbg_mbx, vha, 0x10ba,
+ "Could not acquire ID for VP[%d].\n", rptid_entry->vp_idx);
+ return;
+ }
- found = 0;
- spin_lock_irqsave(&ha->vport_slock, flags);
- list_for_each_entry(vp, &ha->vp_list, list) {
- if (vp_idx == vp->vp_idx) {
- found = 1;
- break;
+ found = 0;
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ list_for_each_entry(vp, &ha->vp_list, list) {
+ if (rptid_entry->vp_idx == vp->vp_idx) {
+ found = 1;
+ break;
+ }
}
- }
- spin_unlock_irqrestore(&ha->vport_slock, flags);
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
- if (!found)
- return;
+ if (!found)
+ return;
- vp->d_id.b.domain = rptid_entry->port_id[2];
- vp->d_id.b.area = rptid_entry->port_id[1];
- vp->d_id.b.al_pa = rptid_entry->port_id[0];
+ vp->d_id.b.domain = rptid_entry->port_id[2];
+ vp->d_id.b.area = rptid_entry->port_id[1];
+ vp->d_id.b.al_pa = rptid_entry->port_id[0];
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ qlt_update_vp_map(vp, SET_AL_PA);
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
- /*
- * Cannot configure here as we are still sitting on the
- * response queue. Handle it in dpc context.
- */
- set_bit(VP_IDX_ACQUIRED, &vp->vp_flags);
+ /*
+ * Cannot configure here as we are still sitting on the
+ * response queue. Handle it in dpc context.
+ */
+ set_bit(VP_IDX_ACQUIRED, &vp->vp_flags);
+ set_bit(REGISTER_FC4_NEEDED, &vp->dpc_flags);
+ set_bit(REGISTER_FDMI_NEEDED, &vp->dpc_flags);
+ }
-reg_needed:
- set_bit(REGISTER_FC4_NEEDED, &vp->dpc_flags);
- set_bit(REGISTER_FDMI_NEEDED, &vp->dpc_flags);
set_bit(VP_DPC_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 845527d..b4f4ce0 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -239,6 +239,13 @@
"0 (Default) Do not set fw option. "
"1 - Set fw option to hold ABTS.");
+int ql2xmvasynctoatio = 1;
+module_param(ql2xmvasynctoatio, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ql2xmvasynctoatio ,
+ "Move PUREX, ABTS RX and RIDA IOCBs to ATIOQ"
+ "0 (Default). Do not move IOCBs"
+ "1 - Move IOCBs.");
+
/*
* SCSI host template entry points
*/
@@ -2944,18 +2951,6 @@ static void qla2x00_destroy_mbx_wq(struct qla_hw_data *ha)
if (ret)
goto probe_init_failed;
- base_vha->gnl.size = (ha->max_loop_id + 1) *
- sizeof(struct get_name_list_extended);
- base_vha->gnl.l = dma_alloc_coherent(&ha->pdev->dev,
- base_vha->gnl.size, &base_vha->gnl.ldma, GFP_KERNEL);
- INIT_LIST_HEAD(&base_vha->gnl.fcports);
-
- if (base_vha->gnl.l == NULL) {
- ql_log(ql_log_fatal, base_vha, 0xffff,
- "Alloc failed for name list.\n");
- goto probe_init_failed;
- }
-
/* Alloc arrays of request and response ring ptrs */
if (!qla2x00_alloc_queues(ha, req, rsp)) {
ql_log(ql_log_fatal, base_vha, 0x003d,
@@ -4288,10 +4283,10 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
struct scsi_qla_host *vha = NULL;
host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
- if (host == NULL) {
+ if (!host) {
ql_log_pci(ql_log_fatal, ha->pdev, 0x0107,
"Failed to allocate host from the scsi layer, aborting.\n");
- goto fail;
+ return NULL;
}
/* Clear our data area */
@@ -4314,11 +4309,23 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
INIT_LIST_HEAD(&vha->logo_list);
INIT_LIST_HEAD(&vha->plogi_ack_list);
INIT_LIST_HEAD(&vha->qp_list);
+ INIT_LIST_HEAD(&vha->gnl.fcports);
spin_lock_init(&vha->work_lock);
spin_lock_init(&vha->cmd_list_lock);
init_waitqueue_head(&vha->fcport_waitQ);
+ vha->gnl.size =
+ sizeof(struct get_name_list_extended[ha->max_loop_id+1]);
+ 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,
+ "Alloc failed for name list.\n");
+ scsi_remove_host(vha->host);
+ return NULL;
+ }
+
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
ql_dbg(ql_dbg_init, vha, 0x0041,
"Allocated the host=%p hw=%p vha=%p dev_name=%s",
@@ -4326,9 +4333,6 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
dev_name(&(ha->pdev->dev)));
return vha;
-
-fail:
- return vha;
}
struct qla_work_evt *
@@ -5554,16 +5558,6 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
qla2x00_update_fcports(base_vha);
}
- if (test_bit(SCR_PENDING, &base_vha->dpc_flags)) {
- int ret;
- ret = qla2x00_send_change_request(base_vha, 0x3, 0);
- if (ret != QLA_SUCCESS)
- ql_log(ql_log_warn, base_vha, 0x121,
- "Failed to enable receiving of RSCN "
- "requests: 0x%x.\n", ret);
- clear_bit(SCR_PENDING, &base_vha->dpc_flags);
- }
-
if (IS_QLAFX00(ha))
goto loop_resync_check;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 089f4ce..a696bbb 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -245,6 +245,107 @@ static inline void qlt_decr_num_pend_cmds(struct scsi_qla_host *vha)
spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
}
+
+static void qlt_queue_unknown_atio(scsi_qla_host_t *vha,
+ 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);
+ 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 */
+ goto out_term;
+ }
+
+ u->vha = vha;
+ memcpy(&u->atio, atio, sizeof(*atio));
+ INIT_LIST_HEAD(&u->cmd_list);
+
+ spin_lock_irqsave(&vha->cmd_list_lock, flags);
+ list_add_tail(&u->cmd_list, &vha->unknown_atio_list);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
+
+ schedule_delayed_work(&vha->unknown_atio_work, 1);
+
+out:
+ return;
+
+out_term:
+ qlt_send_term_exchange(vha, NULL, atio, ha_locked, 0);
+ goto out;
+}
+
+
+static void qlt_try_to_dequeue_unknown_atios(struct scsi_qla_host *vha,
+ uint8_t ha_locked)
+{
+ struct qla_tgt_sess_op *u, *t;
+ scsi_qla_host_t *host;
+ struct qla_tgt *tgt= vha->vha_tgt.qla_tgt;
+ unsigned long flags;
+ uint8_t queued=0;
+
+ 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 ATIO_TYPE7 %p, because of Abort",
+ u);
+ qlt_send_term_exchange(vha, 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);
+ qlt_24xx_atio_pkt(host, &u->atio, ha_locked);
+ } else if (tgt->tgt_stop) {
+ ql_dbg(ql_dbg_async, vha, 0xffff,
+ "Freeing unknown ATIO_TYPE7 %p, because tgt is being stopped",
+ u);
+ qlt_send_term_exchange(vha, 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);
+ if (!queued) {
+ queued = 1;
+ schedule_delayed_work(&vha->unknown_atio_work, 1);
+ }
+ continue;
+ }
+
+ abort:
+ spin_lock_irqsave(&vha->cmd_list_lock, flags);
+ list_del(&u->cmd_list);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
+
+ kfree(u);
+ }
+
+ return;
+}
+
+
+void qlt_unknown_atio_work_fn(struct delayed_work *work)
+{
+ struct scsi_qla_host *vha = container_of(work, struct scsi_qla_host,
+ unknown_atio_work);
+ qlt_try_to_dequeue_unknown_atios(vha, 0);
+ return;
+}
+
static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
struct atio_from_isp *atio, uint8_t ha_locked)
{
@@ -265,8 +366,14 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
atio->u.isp24.fcp_hdr.d_id[0],
atio->u.isp24.fcp_hdr.d_id[1],
atio->u.isp24.fcp_hdr.d_id[2]);
+
+
+ qlt_queue_unknown_atio(vha, atio, ha_locked);
break;
}
+ if (unlikely(!list_empty(&vha->unknown_atio_list)))
+ qlt_try_to_dequeue_unknown_atios(vha, ha_locked);
+
qlt_24xx_atio_pkt(host, atio, ha_locked);
break;
}
@@ -294,6 +401,31 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
break;
}
+ case VP_RPT_ID_IOCB_TYPE:
+ qla24xx_report_id_acquisition(vha,
+ (struct vp_rpt_id_entry_24xx *)atio);
+ break;
+
+ case ABTS_RECV_24XX:
+ {
+ struct abts_recv_from_24xx *entry =
+ (struct abts_recv_from_24xx *)atio;
+ struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha,
+ entry->vp_index);
+ if (unlikely(!host)) {
+ ql_dbg(ql_dbg_tgt, vha, 0xffff,
+ "qla_target(%d): Response pkt "
+ "(ABTS_RECV_24XX) received, with unknown "
+ "vp_index %d\n", vha->vp_idx, entry->vp_index);
+ break;
+ }
+ qlt_response_pkt(host, (response_t *)atio);
+ break;
+
+ }
+
+ /* case PUREX_IOCB_TYPE: ql2xmvasynctoatio */
+
default:
ql_dbg(ql_dbg_tgt, vha, 0xe040,
"qla_target(%d): Received unknown ATIO atio "
@@ -812,6 +944,7 @@ static void qlt_free_session_done(struct work_struct *work)
unsigned long flags;
bool logout_started = false;
struct event_arg ea;
+ scsi_qla_host_t *base_vha;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf084,
"%s: se_sess %p / sess %p from port %8phC loop_id %#04x"
@@ -823,28 +956,29 @@ static void qlt_free_session_done(struct work_struct *work)
if (!IS_SW_RESV_ADDR(sess->d_id)) {
- if (sess->send_els_logo) {
- qlt_port_logo_t logo;
- logo.id = sess->d_id;
- logo.cmd_count = 0;
- qlt_send_first_logo(vha, &logo);
- }
+ if (sess->send_els_logo) {
+ qlt_port_logo_t logo;
+ logo.id = sess->d_id;
+ logo.cmd_count = 0;
+ qlt_send_first_logo(vha, &logo);
+ }
- if (sess->logout_on_delete) {
- int rc;
- rc = qla2x00_post_async_logout_work(vha, sess, NULL);
- if (rc != QLA_SUCCESS)
- ql_log(ql_log_warn, vha, 0xf085,
- "Schedule logo failed sess %p rc %d\n",
- sess, rc);
- else
+ if (sess->logout_on_delete) {
+ int rc;
+ rc = qla2x00_post_async_logout_work(vha, sess, NULL);
+ if (rc != QLA_SUCCESS)
+ ql_log(ql_log_warn, vha, 0xf085,
+ "Schedule logo failed sess %p rc %d\n",
+ sess, rc);
+ else
+ logout_started = true;
+ } else if (sess->logo_ack_needed) {
+ sess->logo_ack_needed = 0;
+ qla24xx_async_notify_ack(vha, sess,
+ (struct imm_ntfy_from_isp *)sess->iocb,
+ SRB_NACK_LOGO);
logout_started = true;
- } else if (sess->logo_ack_needed) {
- sess->logo_ack_needed = 0;
- qla24xx_async_notify_ack(vha, sess,
- (struct imm_ntfy_from_isp *)sess->iocb, SRB_NACK_LOGO);
- logout_started = true;
- }
+ }
}
/*
@@ -871,6 +1005,12 @@ static void qlt_free_session_done(struct work_struct *work)
__func__, sess);
}
+ if (sess->logo_ack_needed) {
+ sess->logo_ack_needed = 0;
+ qla24xx_async_notify_ack(vha, sess,
+ (struct imm_ntfy_from_isp*)sess->iocb, SRB_NACK_LOGO);
+ }
+
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
if (sess->se_sess) {
sess->se_sess = NULL;
@@ -945,6 +1085,10 @@ static void qlt_free_session_done(struct work_struct *work)
if (vha->fcport_count == 0)
wake_up_all(&vha->fcport_waitQ);
+ base_vha = pci_get_drvdata(ha->pdev);
+ if (test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags))
+ return;
+
if (!tgt || !tgt->tgt_stop) {
memset(&ea, 0, sizeof(ea));
ea.event = FCME_DELETE_DONE;
@@ -1595,6 +1739,14 @@ 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);
+ return 1;
+ }
+ }
+
list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
if (tag == cmd->atio.u.isp24.exchange_addr) {
cmd->aborted = 1;
@@ -1631,6 +1783,18 @@ static void abort_cmds_for_lun(struct scsi_qla_host *vha,
if (op_key == key && op_lun == lun)
op->aborted = true;
}
+
+ list_for_each_entry(op, &vha->unknown_atio_list, cmd_list) {
+ uint32_t op_key;
+ u64 op_lun;
+
+ op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
+ op_lun = scsilun_to_int(
+ (struct scsi_lun *)&op->atio.u.isp24.fcp_cmnd.lun);
+ if (op_key == key && op_lun == lun)
+ op->aborted = true;
+ }
+
list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
uint32_t cmd_key;
u64 cmd_lun;
@@ -1939,7 +2103,11 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
if (mcmd->flags == QLA24XX_MGMT_SEND_NACK) {
if (mcmd->orig_iocb.imm_ntfy.u.isp24.status_subcode ==
- ELS_LOGO) {
+ ELS_LOGO ||
+ mcmd->orig_iocb.imm_ntfy.u.isp24.status_subcode ==
+ ELS_PRLO ||
+ mcmd->orig_iocb.imm_ntfy.u.isp24.status_subcode ==
+ ELS_TPRLO) {
ql_dbg(ql_dbg_disc, vha, 0xffff,
"TM response logo %phC status %#x state %#x",
mcmd->sess->port_name, mcmd->fc_tm_rsp,
@@ -4535,6 +4703,15 @@ static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id)
count++;
}
}
+
+ list_for_each_entry(op, &vha->unknown_atio_list, cmd_list) {
+ uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
+ if (op_key == key) {
+ op->aborted = true;
+ count++;
+ }
+ }
+
list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
uint32_t cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
if (cmd_key == key) {
@@ -4741,6 +4918,16 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
}
break;
+
+ case ELS_TPRLO:
+ if (le16_to_cpu(iocb->u.isp24.flags) &
+ NOTIFY24XX_FLAGS_GLOBAL_TPRLO) {
+ loop_id = 0xFFFF;
+ qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS);
+ res = 1;
+ break;
+ }
+ /* drop through */
case ELS_LOGO:
case ELS_PRLO:
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
@@ -4750,7 +4937,6 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
if (sess) {
sess->login_gen++;
sess->fw_login_state = DSC_LS_LOGO_PEND;
- sess->logout_on_delete = 0;
sess->logo_ack_needed = 1;
memcpy(sess->iocb, iocb, IOCB_SIZE);
}
@@ -4762,7 +4948,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
__func__, wwn, res, sess);
if (res == 0) {
/* cmd went up to ULP. look for qlt_xmit_tm_rsp()
- for LOGO_ACK */
+ for LOGO_ACK & sess delete */
BUG_ON(!sess);
res = 0;
} else {
@@ -7111,6 +7297,11 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
mutex_init(&base_vha->vha_tgt.tgt_mutex);
mutex_init(&base_vha->vha_tgt.tgt_host_action_mutex);
+
+ INIT_LIST_HEAD(&base_vha->unknown_atio_list);
+ INIT_DELAYED_WORK(&base_vha->unknown_atio_work,
+ (void (*)(struct work_struct *))qlt_unknown_atio_work_fn);
+
qlt_clear_mode(base_vha);
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 16/22] qla2xxx: Improve RSCN handling in driver
2016-12-06 20:30 ` [PATCH 16/22] qla2xxx: Improve RSCN handling in driver Himanshu Madhani
@ 2016-12-07 11:32 ` Hannes Reinecke
2016-12-09 19:38 ` Madhani, Himanshu
0 siblings, 1 reply; 50+ messages in thread
From: Hannes Reinecke @ 2016-12-07 11:32 UTC (permalink / raw)
To: Himanshu Madhani, target-devel, nab; +Cc: giridhar.malavali, linux-scsi
On 12/06/2016 09:30 PM, Himanshu Madhani wrote:
> From: Quinn Tran <quinn.tran@cavium.com>
>
> - Save NPort ID early in link init.
> - Add session deletion for TPRLO and send acknowledgement for TPRLO.
> - Enable FW option to move ABTS, RIDA & PUREX from RSPQ
> to ATIOQ.
> - Move ABTS & RIDA to ATIOQ helps in keeping command ordering and
> link up sequence ordering.
> - Save Nport ID and update VP map so that SCSI CMD/ATIO
> won't be dropped.
> - fcport alloc does the initializes memory to zero. Remove
> memset to zero since It migth corrupt link list.
> - Turn off Registration for State Change MB in loop mode.
>
> Current code blindly do State Change Registration when
> the link is up. Move SCR behind fabric scan, so AL case
> would not get erroneous error message.
>
> Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
> ---
> drivers/scsi/qla2xxx/qla_def.h | 12 +-
> drivers/scsi/qla2xxx/qla_fw.h | 59 +++++++---
> drivers/scsi/qla2xxx/qla_gbl.h | 2 +
> drivers/scsi/qla2xxx/qla_gs.c | 4 +-
> drivers/scsi/qla2xxx/qla_init.c | 150 ++++++++++++++++++++----
> drivers/scsi/qla2xxx/qla_isr.c | 6 +-
> drivers/scsi/qla2xxx/qla_mbx.c | 123 ++++++++++++--------
> drivers/scsi/qla2xxx/qla_os.c | 48 ++++----
> drivers/scsi/qla2xxx/qla_target.c | 237 ++++++++++++++++++++++++++++++++++----
> 9 files changed, 501 insertions(+), 140 deletions(-)
>
[ .. ]
> diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> index 44be150..3caaf06 100644
> --- a/drivers/scsi/qla2xxx/qla_mbx.c
> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> @@ -3655,78 +3656,106 @@ struct tsk_mgmt_cmd {
[ .. ]
> - /* FA-WWN is only for physical port */
> - if (!vp_idx) {
> - void *wwpn = ha->init_cb->port_name;
> + if (rptid_entry->vp_idx == 0) {
> + if (rptid_entry->vp_status == VP_STAT_COMPL) {
>
> - if (!MSB(stat)) {
> - if (rptid_entry->vp_idx_map[1] & BIT_6)
> - wwpn = rptid_entry->reserved_4 + 8;
> +#if 0
> + /* FA-WWN is only for physical port */
> +
> + /* To Do: For Target Mode, changing WWPN during
> + * runtime cause Target un-config problem. The FA-WWN
> + * should be saved in separate field.
> + */
> + if (rptid_entry->u.f1.flags & VP_FLAGS_NAME_VALID) {
> + memcpy(vha->port_name, rptid_entry->u.f1.port_name,
> + WWN_SIZE);
> + }
> +#endif
> +
> + vha->d_id.b.domain = rptid_entry->port_id[2];
> + vha->d_id.b.area = rptid_entry->port_id[1];
> + vha->d_id.b.al_pa = rptid_entry->port_id[0];
> + spin_lock_irqsave(&ha->vport_slock, flags);
> + qlt_update_vp_map(vha, SET_AL_PA);
> + spin_unlock_irqrestore(&ha->vport_slock, flags);
> }
> - memcpy(vha->port_name, wwpn, WWN_SIZE);
> +
This is a bit odd.
If you already have code for fixing the to-do, why is the to-do there?
And if the code doesn't work, what's the point of including it here?
I would suggest removing the code; the comment should be giving enough
of a hint of what needs to be implemented.
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.com +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 16/22] qla2xxx: Improve RSCN handling in driver
2016-12-07 11:32 ` Hannes Reinecke
@ 2016-12-09 19:38 ` Madhani, Himanshu
0 siblings, 0 replies; 50+ messages in thread
From: Madhani, Himanshu @ 2016-12-09 19:38 UTC (permalink / raw)
To: Hannes Reinecke, target-devel@vger.kernel.org,
nab@linux-iscsi.org
Cc: Malavali, Giridhar, linux-scsi@vger.kernel.org
Hi Hannes,
On 12/7/16, 3:32 AM, "Hannes Reinecke" <hare@suse.com> wrote:
>This is a bit odd.
>If you already have code for fixing the to-do, why is the to-do there?
>And if the code doesn't work, what's the point of including it here?
>
>I would suggest removing the code; the comment should be giving enough
>of a hint of what needs to be implemented.
Thanks for the review comments. This is one looks like got left off.
We’ll fix this code and resubmit this series.
Thanks,
- Himanshu
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 17/22] qla2xxx: Rerfactor use of sp context
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (15 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 16/22] qla2xxx: Improve RSCN handling in driver Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-06 20:30 ` [PATCH 18/22] qla2xxx: Fix slow mem alloc behind lock Himanshu Madhani
` (5 subsequent siblings)
22 siblings, 0 replies; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_attr.c | 12 +++----
drivers/scsi/qla2xxx/qla_bsg.c | 13 ++++---
drivers/scsi/qla2xxx/qla_def.h | 2 +-
drivers/scsi/qla2xxx/qla_gs.c | 14 ++++----
drivers/scsi/qla2xxx/qla_init.c | 42 +++++++++++-----------
drivers/scsi/qla2xxx/qla_inline.h | 10 +++---
drivers/scsi/qla2xxx/qla_iocb.c | 76 +++++++++++++++++++--------------------
drivers/scsi/qla2xxx/qla_isr.c | 44 +++++++++++------------
drivers/scsi/qla2xxx/qla_mid.c | 12 ++++---
drivers/scsi/qla2xxx/qla_mr.c | 46 +++++++++++-------------
drivers/scsi/qla2xxx/qla_os.c | 10 +++---
drivers/scsi/qla2xxx/qla_target.c | 4 +--
12 files changed, 138 insertions(+), 147 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index d8b77aa..5b53fdd 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2498,8 +2498,6 @@ struct device_attribute *qla2x00_host_attrs[] = {
"Timer for the VP[%d] has stopped\n", vha->vp_idx);
}
- BUG_ON(atomic_read(&vha->vref_count));
-
qla2x00_free_fcports(vha);
mutex_lock(&ha->vport_lock);
@@ -2510,10 +2508,12 @@ struct device_attribute *qla2x00_host_attrs[] = {
dma_free_coherent(&ha->pdev->dev,
vha->gnl.size, vha->gnl.l, vha->gnl.ldma);
- if (vha->qpair->vp_idx == vha->vp_idx) {
- if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
- ql_log(ql_log_warn, vha, 0x7087,
- "Queue Pair delete failed.\n");
+ if (vha->qpair) {
+ if (vha->qpair->vp_idx == vha->vp_idx) {
+ if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
+ ql_log(ql_log_warn, vha, 0x7087,
+ "Queue Pair delete failed.\n");
+ }
}
ql_log(ql_log_info, vha, 0x7088, "VP[%d] deleted.\n", id);
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index cdf0dce..5db25a7 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -16,21 +16,20 @@
qla2x00_bsg_job_done(void *data, void *ptr, int res)
{
srb_t *sp = (srb_t *)ptr;
- struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
struct bsg_job *bsg_job = sp->u.bsg_job;
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
bsg_reply->result = res;
bsg_job_done(bsg_job, bsg_reply->result,
bsg_reply->reply_payload_rcv_len);
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
}
void
qla2x00_bsg_sp_free(void *data, void *ptr)
{
srb_t *sp = (srb_t *)ptr;
- struct scsi_qla_host *vha = sp->fcport->vha;
+ struct scsi_qla_host *vha = sp->vha;
struct bsg_job *bsg_job = sp->u.bsg_job;
struct fc_bsg_request *bsg_request = bsg_job->request;
@@ -62,7 +61,7 @@
sp->type == SRB_FXIOCB_BCMD ||
sp->type == SRB_ELS_CMD_HST)
qla2x00_free_fcport(sp->fcport);
- qla2x00_rel_sp(vha, sp);
+ qla2x00_rel_sp(sp);
}
int
@@ -394,7 +393,7 @@
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x700e,
"qla2x00_start_sp failed = %d\n", rval);
- qla2x00_rel_sp(vha, sp);
+ qla2x00_rel_sp(sp);
rval = -EIO;
goto done_unmap_sg;
}
@@ -542,7 +541,7 @@
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x7017,
"qla2x00_start_sp failed=%d.\n", rval);
- qla2x00_rel_sp(vha, sp);
+ qla2x00_rel_sp(sp);
rval = -EIO;
goto done_free_fcport;
}
@@ -2578,6 +2577,6 @@
done:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
return 0;
}
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index f9a4528..3464d65 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -433,7 +433,7 @@ struct srb_iocb {
typedef struct srb {
atomic_t ref_count;
struct fc_port *fcport;
- void *vha;
+ struct scsi_qla_host *vha;
uint32_t handle;
uint16_t flags;
uint16_t type;
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 1e70a58..e36068c 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -2854,7 +2854,7 @@ void qla2x00_async_gidpn_sp_done(void *v, void *s, int res)
qla2x00_fcport_event_handler(vha, &ea);
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
}
int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
@@ -2912,7 +2912,7 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
return rval;
done_free_sp:
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
done:
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
@@ -3018,7 +3018,7 @@ void qla24xx_async_gpsc_sp_done(void *v, void *s, int res)
ea.fcport = fcport;
qla2x00_fcport_event_handler(vha, &ea);
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
}
int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
@@ -3073,7 +3073,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
return rval;
done_free_sp:
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
done:
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
@@ -3111,7 +3111,7 @@ void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t *sp)
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
}
void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
@@ -3190,7 +3190,7 @@ void qla2x00_async_gpnid_sp_done(void *v, void *s, int res)
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
return;
}
@@ -3279,7 +3279,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
done:
return rval;
}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 1899333..dcb8c49 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -47,18 +47,17 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
{
srb_t *sp = (srb_t *)__data;
struct srb_iocb *iocb;
- scsi_qla_host_t *vha = (scsi_qla_host_t *)sp->vha;
- struct qla_hw_data *ha = vha->hw;
+ scsi_qla_host_t *vha = sp->vha;
struct req_que *req;
unsigned long flags;
- spin_lock_irqsave(&ha->hardware_lock, flags);
- req = ha->req_q_map[0];
+ spin_lock_irqsave(&vha->hw->hardware_lock, flags);
+ req = vha->hw->req_q_map[0];
req->outstanding_cmds[sp->handle] = NULL;
iocb = &sp->u.iocb_cmd;
iocb->timeout(sp);
- sp->free(vha, sp);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ sp->free(sp->vha, sp);
+ spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
}
void
@@ -66,10 +65,9 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
{
srb_t *sp = (srb_t *)ptr;
struct srb_iocb *iocb = &sp->u.iocb_cmd;
- struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
del_timer(&iocb->timer);
- qla2x00_rel_sp(vha, sp);
+ qla2x00_rel_sp(sp);
}
/* Asynchronous Login/Logout Routines -------------------------------------- */
@@ -163,7 +161,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
qla2x00_fcport_event_handler(vha, &ea);
}
- sp->free(sp->fcport->vha, sp);
+ sp->free(sp->vha, sp);
}
int
@@ -215,7 +213,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
return rval;
done_free_sp:
- sp->free(fcport->vha, sp);
+ sp->free(sp->vha, sp);
done:
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
@@ -230,9 +228,9 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
sp->fcport->flags &= ~FCF_ASYNC_SENT;
if (!test_bit(UNLOADING, &vha->dpc_flags))
- qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport,
+ qla2x00_post_async_logout_done_work(sp->vha, sp->fcport,
lio->u.logio.data);
- sp->free(sp->fcport->vha, sp);
+ sp->free(sp->vha, sp);
}
int
@@ -267,7 +265,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
return rval;
done_free_sp:
- sp->free(fcport->vha, sp);
+ sp->free(sp->vha, sp);
done:
sp->fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
@@ -281,9 +279,9 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
if (!test_bit(UNLOADING, &vha->dpc_flags))
- qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport,
+ qla2x00_post_async_adisc_done_work(sp->vha, sp->fcport,
lio->u.logio.data);
- sp->free(sp->fcport->vha, sp);
+ sp->free(sp->vha, sp);
}
int
@@ -548,7 +546,7 @@ void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
}
int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
@@ -617,7 +615,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
return rval;
done_free_sp:
- sp->free(fcport->vha, sp);
+ sp->free(sp->vha, sp);
done:
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
@@ -716,7 +714,7 @@ void qla24xx_async_gpdb_sp_done(void *v, void *s, int res)
dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
sp->u.iocb_cmd.u.mbx.in_dma);
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
}
static int qla24xx_post_gpdb_work(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
@@ -796,7 +794,7 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
if (pd)
dma_pool_free(ha->s_dma_pool, pd, pd_dma);
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
done:
fcport->flags &= ~FCF_ASYNC_SENT;
qla24xx_post_gpdb_work(vha, fcport, opt);
@@ -1261,7 +1259,7 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
}
done_free_sp:
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
done:
return rval;
}
@@ -1288,7 +1286,7 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
static int
qla24xx_async_abort_cmd(srb_t *cmd_sp)
{
- scsi_qla_host_t *vha = cmd_sp->fcport->vha;
+ scsi_qla_host_t *vha = cmd_sp->vha;
fc_port_t *fcport = cmd_sp->fcport;
struct srb_iocb *abt_iocb;
srb_t *sp;
@@ -1321,7 +1319,7 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
QLA_SUCCESS : QLA_FUNCTION_FAILED;
done_free_sp:
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
done:
return rval;
}
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index d6dd976..d4966e3 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -249,14 +249,13 @@
qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
{
srb_t *sp = NULL;
- struct qla_hw_data *ha = vha->hw;
uint8_t bail;
QLA_VHA_MARK_BUSY(vha, bail);
if (unlikely(bail))
return NULL;
- sp = mempool_alloc(ha->srb_mempool, flag);
+ sp = mempool_alloc(vha->hw->srb_mempool, flag);
if (!sp)
goto done;
@@ -267,14 +266,15 @@
done:
if (!sp)
QLA_VHA_MARK_NOT_BUSY(vha);
+
return sp;
}
static inline void
-qla2x00_rel_sp(scsi_qla_host_t *vha, srb_t *sp)
+qla2x00_rel_sp(srb_t *sp)
{
- mempool_free(sp, vha->hw->srb_mempool);
- QLA_VHA_MARK_NOT_BUSY(vha);
+ mempool_free(sp, sp->vha->hw->srb_mempool);
+ QLA_VHA_MARK_NOT_BUSY(sp->vha);
}
static inline void
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index b7d3739..f892fca 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -23,7 +23,7 @@
{
uint16_t cflags;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
- struct scsi_qla_host *vha = sp->fcport->vha;
+ struct scsi_qla_host *vha = sp->vha;
cflags = 0;
@@ -210,7 +210,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
return;
}
- vha = sp->fcport->vha;
+ vha = sp->vha;
cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
/* Three DSDs are available in the Command Type 2 IOCB */
@@ -267,7 +267,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
return;
}
- vha = sp->fcport->vha;
+ vha = sp->vha;
cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
/* Two DSDs are available in the Command Type 3 IOCB */
@@ -324,7 +324,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
struct rsp_que *rsp;
/* Setup device pointers. */
- vha = sp->fcport->vha;
+ vha = sp->vha;
ha = vha->hw;
reg = &ha->iobase->isp;
cmd = GET_CMD_SP(sp);
@@ -601,7 +601,7 @@ int qla2x00_issue_marker(scsi_qla_host_t *vha, int ha_locked)
return 0;
}
- vha = sp->fcport->vha;
+ vha = sp->vha;
ha = vha->hw;
/* Set transfer direction */
@@ -716,7 +716,7 @@ int qla2x00_issue_marker(scsi_qla_host_t *vha, int ha_locked)
return;
}
- vha = sp->fcport->vha;
+ vha = sp->vha;
/* Set transfer direction */
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
@@ -1108,7 +1108,7 @@ struct fw_dif_context {
if (sp) {
cmd = GET_CMD_SP(sp);
sgl = scsi_prot_sglist(cmd);
- vha = sp->fcport->vha;
+ vha = sp->vha;
} else if (tc) {
vha = tc->vha;
sgl = tc->prot_sg;
@@ -1215,7 +1215,7 @@ struct fw_dif_context {
/* Update entry type to indicate Command Type CRC_2 IOCB */
*((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_CRC_2);
- vha = sp->fcport->vha;
+ vha = sp->vha;
ha = vha->hw;
/* No data transfer */
@@ -1225,7 +1225,7 @@ struct fw_dif_context {
return QLA_SUCCESS;
}
- cmd_pkt->vp_index = sp->fcport->vha->vp_idx;
+ cmd_pkt->vp_index = sp->vha->vp_idx;
/* Set transfer direction */
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
@@ -1420,7 +1420,7 @@ struct fw_dif_context {
struct req_que *req = NULL;
struct rsp_que *rsp = NULL;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
- struct scsi_qla_host *vha = sp->fcport->vha;
+ struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
/* Setup device pointers. */
@@ -1497,7 +1497,7 @@ struct fw_dif_context {
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;
+ cmd_pkt->vp_index = sp->vha->vp_idx;
int_to_scsilun(cmd->device->lun, &cmd_pkt->lun);
host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
@@ -1569,7 +1569,7 @@ struct fw_dif_context {
struct req_que *req = NULL;
struct rsp_que *rsp = NULL;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
- struct scsi_qla_host *vha = sp->fcport->vha;
+ struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
struct cmd_type_crc_2 *cmd_pkt;
uint32_t status = 0;
@@ -2219,13 +2219,13 @@ struct fw_dif_context {
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->fcport->vha->vp_idx;
+ logio->vp_index = sp->vha->vp_idx;
}
static void
qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx)
{
- struct qla_hw_data *ha = sp->fcport->vha->hw;
+ struct qla_hw_data *ha = sp->vha->hw;
struct srb_iocb *lio = &sp->u.iocb_cmd;
uint16_t opts;
@@ -2243,7 +2243,7 @@ struct fw_dif_context {
mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain);
mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 |
sp->fcport->d_id.b.al_pa);
- mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx);
+ mbx->mb9 = cpu_to_le16(sp->vha->vp_idx);
}
static void
@@ -2259,13 +2259,13 @@ struct fw_dif_context {
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->fcport->vha->vp_idx;
+ logio->vp_index = sp->vha->vp_idx;
}
static void
qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx)
{
- struct qla_hw_data *ha = sp->fcport->vha->hw;
+ struct qla_hw_data *ha = sp->vha->hw;
mbx->entry_type = MBX_IOCB_TYPE;
SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id);
@@ -2276,7 +2276,7 @@ struct fw_dif_context {
mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain);
mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 |
sp->fcport->d_id.b.al_pa);
- mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx);
+ mbx->mb9 = cpu_to_le16(sp->vha->vp_idx);
/* Implicit: mbx->mbx10 = 0. */
}
@@ -2286,13 +2286,13 @@ struct fw_dif_context {
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags = cpu_to_le16(LCF_COMMAND_ADISC);
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
- logio->vp_index = sp->fcport->vha->vp_idx;
+ logio->vp_index = sp->vha->vp_idx;
}
static void
qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx)
{
- struct qla_hw_data *ha = sp->fcport->vha->hw;
+ struct qla_hw_data *ha = sp->vha->hw;
mbx->entry_type = MBX_IOCB_TYPE;
SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id);
@@ -2307,7 +2307,7 @@ struct fw_dif_context {
mbx->mb3 = cpu_to_le16(LSW(ha->async_pd_dma));
mbx->mb6 = cpu_to_le16(MSW(MSD(ha->async_pd_dma)));
mbx->mb7 = cpu_to_le16(LSW(MSD(ha->async_pd_dma)));
- mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx);
+ mbx->mb9 = cpu_to_le16(sp->vha->vp_idx);
}
static void
@@ -2359,7 +2359,7 @@ struct fw_dif_context {
elsio->u.els_logo.els_logo_pyld_dma);
del_timer(&elsio->timer);
- qla2x00_rel_sp(vha, sp);
+ qla2x00_rel_sp(sp);
}
static void
@@ -2455,7 +2455,7 @@ struct fw_dif_context {
GFP_KERNEL);
if (!elsio->u.els_logo.els_logo_pyld) {
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
return QLA_FUNCTION_FAILED;
}
@@ -2474,7 +2474,7 @@ struct fw_dif_context {
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
return QLA_FUNCTION_FAILED;
}
@@ -2485,14 +2485,14 @@ struct fw_dif_context {
wait_for_completion(&elsio->u.els_logo.comp);
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
return rval;
}
static void
qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
{
- scsi_qla_host_t *vha = sp->fcport->vha;
+ scsi_qla_host_t *vha = sp->vha;
struct srb_iocb *elsio = &sp->u.iocb_cmd;
els_iocb->entry_type = ELS_IOCB_TYPE;
@@ -2524,7 +2524,7 @@ struct fw_dif_context {
els_iocb->rx_address[1] = 0;
els_iocb->rx_len = 0;
- sp->fcport->vha->qla_stats.control_requests++;
+ sp->vha->qla_stats.control_requests++;
}
static void
@@ -2540,7 +2540,7 @@ struct fw_dif_context {
els_iocb->handle = sp->handle;
els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id);
els_iocb->tx_dsd_count = cpu_to_le16(bsg_job->request_payload.sg_cnt);
- els_iocb->vp_index = sp->fcport->vha->vp_idx;
+ els_iocb->vp_index = sp->vha->vp_idx;
els_iocb->sof_type = EST_SOFI3;
els_iocb->rx_dsd_count = cpu_to_le16(bsg_job->reply_payload.sg_cnt);
@@ -2571,7 +2571,7 @@ struct fw_dif_context {
els_iocb->rx_len = cpu_to_le32(sg_dma_len
(bsg_job->reply_payload.sg_list));
- sp->fcport->vha->qla_stats.control_requests++;
+ sp->vha->qla_stats.control_requests++;
}
static void
@@ -2582,7 +2582,7 @@ struct fw_dif_context {
struct scatterlist *sg;
int index;
uint16_t tot_dsds;
- scsi_qla_host_t *vha = sp->fcport->vha;
+ scsi_qla_host_t *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
struct bsg_job *bsg_job = sp->u.bsg_job;
int loop_iterartion = 0;
@@ -2648,7 +2648,7 @@ struct fw_dif_context {
}
ct_iocb->entry_count = entry_count;
- sp->fcport->vha->qla_stats.control_requests++;
+ sp->vha->qla_stats.control_requests++;
}
static void
@@ -2659,7 +2659,7 @@ struct fw_dif_context {
struct scatterlist *sg;
int index;
uint16_t tot_dsds;
- scsi_qla_host_t *vha = sp->fcport->vha;
+ scsi_qla_host_t *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
struct bsg_job *bsg_job = sp->u.bsg_job;
int loop_iterartion = 0;
@@ -2671,7 +2671,7 @@ struct fw_dif_context {
ct_iocb->handle = sp->handle;
ct_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id);
- ct_iocb->vp_index = sp->fcport->vha->vp_idx;
+ ct_iocb->vp_index = sp->vha->vp_idx;
ct_iocb->comp_status = cpu_to_le16(0);
ct_iocb->cmd_dsd_count =
@@ -2745,7 +2745,7 @@ struct fw_dif_context {
uint32_t *fcp_dl;
uint8_t additional_cdb_len;
struct ct6_dsd *ctx;
- struct scsi_qla_host *vha = sp->fcport->vha;
+ struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = NULL;
struct rsp_que *rsp = NULL;
@@ -2907,7 +2907,7 @@ struct fw_dif_context {
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;
+ cmd_pkt->vp_index = sp->vha->vp_idx;
/* Build IOCB segments */
if (qla24xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds))
@@ -2980,7 +2980,7 @@ struct fw_dif_context {
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;
+ cmd_pkt->vp_index = sp->vha->vp_idx;
int_to_scsilun(cmd->device->lun, &cmd_pkt->lun);
host_to_fcp_swap((uint8_t *)&cmd_pkt->lun,
@@ -3066,7 +3066,7 @@ struct fw_dif_context {
qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb)
{
struct srb_iocb *aio = &sp->u.iocb_cmd;
- scsi_qla_host_t *vha = sp->fcport->vha;
+ scsi_qla_host_t *vha = sp->vha;
struct req_que *req = vha->req;
memset(abt_iocb, 0, sizeof(struct abort_entry_24xx));
@@ -3141,7 +3141,7 @@ static void qla2x00_send_notify_ack_iocb(srb_t *sp,
qla2x00_start_sp(srb_t *sp)
{
int rval;
- scsi_qla_host_t *vha = (scsi_qla_host_t *)sp->vha;
+ scsi_qla_host_t *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
void *pkt;
unsigned long flags;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index dac59b3..c81ada0 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1246,7 +1246,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
req->outstanding_cmds[index] = NULL;
/* Save ISP completion status */
- sp->done(vha, sp, DID_OK << 16);
+ sp->done(sp->vha, sp, DID_OK << 16);
} else {
ql_log(ql_log_warn, vha, 0x3016, "Invalid SCSI SRB.\n");
@@ -1264,18 +1264,16 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
struct qla_hw_data *ha = vha->hw;
sts_entry_t *pkt = iocb;
srb_t *sp = NULL;
- uint16_t index;
+ uint16_t index = LSW(pkt->handle);
- index = LSW(pkt->handle);
if (index >= req->num_outstanding_cmds) {
ql_log(ql_log_warn, vha, 0x5031,
- "Invalid command index (%x) type %8ph.\n",
- index, iocb);
+ "Invalid command index (%x) type %8ph.\n", index, iocb);
if (IS_P3P_TYPE(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
else
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
- goto done;
+ return sp;
}
sp = req->outstanding_cmds[index];
if (!sp) {
@@ -1288,10 +1286,8 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
"SRB handle (%x) mismatch %x.\n", sp->handle, index);
return NULL;
}
-
req->outstanding_cmds[index] = NULL;
-done:
return sp;
}
@@ -1378,7 +1374,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
le16_to_cpu(mbx->mb7));
logio_done:
- sp->done(vha, sp, 0);
+ sp->done(sp->vha, sp, 0);
}
static void
@@ -1407,7 +1403,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
res = (si->u.mbx.in_mb[0] & MBS_MASK);
- sp->done(vha, sp, res);
+ sp->done(sp->vha, sp, res);
}
static void
@@ -1425,7 +1421,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
if (pkt->u.isp2x.status != cpu_to_le16(NOTIFY_ACK_SUCCESS))
res = QLA_FUNCTION_FAILED;
- sp->done(vha, sp, res);
+ sp->done(sp->vha, sp, res);
}
static void
@@ -1535,7 +1531,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
type = "Driver ELS logo";
ql_dbg(ql_dbg_user, vha, 0x5047,
"Completing %s: (%p) type=%d.\n", type, sp, sp->type);
- sp->done(vha, sp, 0);
+ sp->done(sp->vha, sp, 0);
return;
case SRB_CT_PTHRU_CMD:
/* borrowing sts_entry_24xx.comp_status.
@@ -1544,7 +1540,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
(struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
sp->name);
- sp->done(vha, sp, res);
+ sp->done(sp->vha, sp, res);
return;
default:
ql_dbg(ql_dbg_user, vha, 0x503e,
@@ -1600,7 +1596,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
bsg_job->reply_len = 0;
}
- sp->done(vha, sp, res);
+ sp->done(sp->vha, sp, res);
}
static void
@@ -1712,7 +1708,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
le32_to_cpu(logio->io_parameter[1]));
logio_done:
- sp->done(vha, sp, 0);
+ sp->done(sp->vha, sp, 0);
}
static void
@@ -1762,7 +1758,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055,
(uint8_t *)sts, sizeof(*sts));
- sp->done(vha, sp, 0);
+ sp->done(sp->vha, sp, 0);
}
/**
@@ -1850,7 +1846,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
uint32_t sense_len, struct rsp_que *rsp, int res)
{
- struct scsi_qla_host *vha = sp->fcport->vha;
+ struct scsi_qla_host *vha = sp->vha;
struct scsi_cmnd *cp = GET_CMD_SP(sp);
uint32_t track_sense_len;
@@ -1878,7 +1874,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
if (sense_len) {
ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x301c,
"Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n",
- sp->fcport->vha->host_no, cp->device->id, cp->device->lun,
+ sp->vha->host_no, cp->device->id, cp->device->lun,
cp);
ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302b,
cp->sense_buffer, sense_len);
@@ -1900,7 +1896,7 @@ struct scsi_dif_tuple {
static inline int
qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
{
- struct scsi_qla_host *vha = sp->fcport->vha;
+ struct scsi_qla_host *vha = sp->vha;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
uint8_t *ap = &sts24->data[12];
uint8_t *ep = &sts24->data[20];
@@ -2168,7 +2164,7 @@ struct scsi_dif_tuple {
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
/* Always return DID_OK, bsg will send the vendor specific response
* in this case only */
- sp->done(vha, sp, (DID_OK << 6));
+ sp->done(sp->vha, sp, DID_OK << 6);
}
@@ -2541,7 +2537,7 @@ struct scsi_dif_tuple {
resid_len, fw_resid_len, sp, cp);
if (rsp->status_srb == NULL)
- sp->done(vha, sp, res);
+ sp->done(sp->vha, sp, res);
}
/**
@@ -2598,7 +2594,7 @@ struct scsi_dif_tuple {
/* Place command on done queue. */
if (sense_len == 0) {
rsp->status_srb = NULL;
- sp->done(vha, sp, cp->result);
+ sp->done(sp->vha, sp, cp->result);
}
}
@@ -2639,7 +2635,7 @@ struct scsi_dif_tuple {
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (sp) {
- sp->done(vha, sp, res);
+ sp->done(sp->vha, sp, res);
return;
}
fatal:
@@ -2697,7 +2693,7 @@ struct scsi_dif_tuple {
abt = &sp->u.iocb_cmd;
abt->u.abt.comp_status = le32_to_cpu(pkt->nport_handle);
- sp->done(vha, sp, 0);
+ sp->done(sp->vha, sp, 0);
}
/**
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 544aff1..01a2243 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -65,6 +65,7 @@
uint16_t vp_id;
struct qla_hw_data *ha = vha->hw;
unsigned long flags = 0;
+ uint count = 10;
mutex_lock(&ha->vport_lock);
/*
@@ -74,13 +75,14 @@
* ensures no active vp_list traversal while the vport is removed
* from the queue)
*/
- spin_lock_irqsave(&ha->vport_slock, flags);
- while (atomic_read(&vha->vref_count)) {
- spin_unlock_irqrestore(&ha->vport_slock, flags);
-
+ while (count-- && atomic_read(&vha->vref_count))
msleep(500);
- spin_lock_irqsave(&ha->vport_slock, flags);
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ if (atomic_read(&vha->vref_count)) {
+ ql_dbg(ql_dbg_vport, vha, 0xfffa,
+ "vha->vref_count=%u timeout\n", vha->vref_count.counter);
+ vha->vref_count = (atomic_t)ATOMIC_INIT(0);
}
list_del(&vha->list);
qlt_update_vp_map(vha, RESET_VP_IDX);
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index 4eac33e..599b3e8 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -1999,7 +1999,7 @@
dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
done_free_sp:
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
done:
return rval;
}
@@ -2127,7 +2127,7 @@
qlafx00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len,
uint32_t sense_len, struct rsp_que *rsp, int res)
{
- struct scsi_qla_host *vha = sp->fcport->vha;
+ struct scsi_qla_host *vha = sp->vha;
struct scsi_cmnd *cp = GET_CMD_SP(sp);
uint32_t track_sense_len;
@@ -2162,7 +2162,7 @@
if (sense_len) {
ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3039,
"Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n",
- sp->fcport->vha->host_no, cp->device->id, cp->device->lun,
+ sp->vha->host_no, cp->device->id, cp->device->lun,
cp);
ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3049,
cp->sense_buffer, sense_len);
@@ -2181,7 +2181,7 @@
(sstatus & cpu_to_le16((uint16_t)SS_RESPONSE_INFO_LEN_VALID)))
cpstatus = cpu_to_le16((uint16_t)CS_INCOMPLETE);
tmf->u.tmf.comp_status = cpstatus;
- sp->done(vha, sp, 0);
+ sp->done(sp->vha, sp, 0);
}
static void
@@ -2198,7 +2198,7 @@
abt = &sp->u.iocb_cmd;
abt->u.abt.comp_status = pkt->tgt_id_sts;
- sp->done(vha, sp, 0);
+ sp->done(sp->vha, sp, 0);
}
static void
@@ -2252,12 +2252,10 @@
bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
sizeof(struct qla_mt_iocb_rsp_fx00) + sizeof(uint8_t);
- ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
- sp->fcport->vha, 0x5080,
+ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, sp->vha, 0x5080,
(uint8_t *)pkt, sizeof(struct ioctl_iocb_entry_fx00));
- ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
- sp->fcport->vha, 0x5074,
+ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, sp->vha, 0x5074,
(uint8_t *)fw_sts_ptr, sizeof(struct qla_mt_iocb_rsp_fx00));
res = bsg_reply->result = DID_OK << 16;
@@ -2537,7 +2535,7 @@
par_sense_len, rsp_info_len);
if (rsp->status_srb == NULL)
- sp->done(vha, sp, res);
+ sp->done(sp->vha, sp, res);
}
/**
@@ -2614,7 +2612,7 @@
/* Place command on done queue. */
if (sense_len == 0) {
rsp->status_srb = NULL;
- sp->done(vha, sp, cp->result);
+ sp->done(sp->vha, sp, cp->result);
}
}
@@ -2695,7 +2693,7 @@
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (sp) {
- sp->done(vha, sp, res);
+ sp->done(sp->vha, sp, res);
return;
}
@@ -2997,7 +2995,7 @@
cont_a64_entry_t lcont_pkt;
cont_a64_entry_t *cont_pkt;
- vha = sp->fcport->vha;
+ vha = sp->vha;
req = vha->req;
cmd = GET_CMD_SP(sp);
@@ -3081,7 +3079,7 @@
struct req_que *req = NULL;
struct rsp_que *rsp = NULL;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
- struct scsi_qla_host *vha = sp->fcport->vha;
+ struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
struct cmd_type_7_fx00 *cmd_pkt;
struct cmd_type_7_fx00 lcmd_pkt;
@@ -3205,7 +3203,7 @@
qlafx00_tm_iocb(srb_t *sp, struct tsk_mgmt_entry_fx00 *ptm_iocb)
{
struct srb_iocb *fxio = &sp->u.iocb_cmd;
- scsi_qla_host_t *vha = sp->fcport->vha;
+ scsi_qla_host_t *vha = sp->vha;
struct req_que *req = vha->req;
struct tsk_mgmt_entry_fx00 tm_iocb;
struct scsi_lun llun;
@@ -3232,7 +3230,7 @@
qlafx00_abort_iocb(srb_t *sp, struct abort_iocb_entry_fx00 *pabt_iocb)
{
struct srb_iocb *fxio = &sp->u.iocb_cmd;
- scsi_qla_host_t *vha = sp->fcport->vha;
+ scsi_qla_host_t *vha = sp->vha;
struct req_que *req = vha->req;
struct abort_iocb_entry_fx00 abt_iocb;
@@ -3346,8 +3344,7 @@
REQUEST_ENTRY_SIZE);
cont_pkt =
qlafx00_prep_cont_type1_iocb(
- sp->fcport->vha->req,
- &lcont_pkt);
+ sp->vha->req, &lcont_pkt);
cur_dsd = (__le32 *)
lcont_pkt.dseg_0_address;
avail_dsds = 5;
@@ -3368,7 +3365,7 @@
&lcont_pkt, REQUEST_ENTRY_SIZE);
ql_dump_buffer(
ql_dbg_user + ql_dbg_verbose,
- sp->fcport->vha, 0x3042,
+ sp->vha, 0x3042,
(uint8_t *)&lcont_pkt,
REQUEST_ENTRY_SIZE);
}
@@ -3377,7 +3374,7 @@
memcpy_toio((void __iomem *)cont_pkt,
&lcont_pkt, REQUEST_ENTRY_SIZE);
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
- sp->fcport->vha, 0x3043,
+ sp->vha, 0x3043,
(uint8_t *)&lcont_pkt, REQUEST_ENTRY_SIZE);
}
}
@@ -3409,8 +3406,7 @@
REQUEST_ENTRY_SIZE);
cont_pkt =
qlafx00_prep_cont_type1_iocb(
- sp->fcport->vha->req,
- &lcont_pkt);
+ sp->vha->req, &lcont_pkt);
cur_dsd = (__le32 *)
lcont_pkt.dseg_0_address;
avail_dsds = 5;
@@ -3431,7 +3427,7 @@
REQUEST_ENTRY_SIZE);
ql_dump_buffer(
ql_dbg_user + ql_dbg_verbose,
- sp->fcport->vha, 0x3045,
+ sp->vha, 0x3045,
(uint8_t *)&lcont_pkt,
REQUEST_ENTRY_SIZE);
}
@@ -3440,7 +3436,7 @@
memcpy_toio((void __iomem *)cont_pkt,
&lcont_pkt, REQUEST_ENTRY_SIZE);
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
- sp->fcport->vha, 0x3046,
+ sp->vha, 0x3046,
(uint8_t *)&lcont_pkt, REQUEST_ENTRY_SIZE);
}
}
@@ -3452,7 +3448,7 @@
}
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
- sp->fcport->vha, 0x3047,
+ sp->vha, 0x3047,
(uint8_t *)&fx_iocb, sizeof(struct fxdisc_entry_fx00));
memcpy_toio((void __iomem *)pfxiocb, &fx_iocb,
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index b4f4ce0..87dc64a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -617,7 +617,7 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
{
srb_t *sp = (srb_t *)ptr;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
- struct qla_hw_data *ha = sp->fcport->vha->hw;
+ struct qla_hw_data *ha = sp->vha->hw;
void *ctx = GET_CMD_CTX_SP(sp);
if (sp->flags & SRB_DMA_VALID) {
@@ -656,7 +656,7 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
}
CMD_SP(cmd) = NULL;
- qla2x00_rel_sp(sp->fcport->vha, sp);
+ qla2x00_rel_sp(sp);
}
void
@@ -669,7 +669,7 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
cmd->result = res;
if (atomic_read(&sp->ref_count) == 0) {
- ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3015,
+ ql_dbg(ql_dbg_io, sp->vha, 0x3015,
"SP reference-count to ZERO -- sp=%p cmd=%p.\n",
sp, GET_CMD_SP(sp));
if (ql2xextended_error_logging & ql_dbg_io)
@@ -1238,7 +1238,7 @@ uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
}
spin_lock_irqsave(&ha->hardware_lock, flags);
- sp->done(vha, sp, 0);
+ sp->done(sp->vha, sp, 0);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Did the command return during mailbox execution? */
@@ -1283,7 +1283,7 @@ uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
continue;
if (sp->type != SRB_SCSI_CMD)
continue;
- if (vha->vp_idx != sp->fcport->vha->vp_idx)
+ if (vha->vp_idx != sp->vha->vp_idx)
continue;
match = 0;
cmd = GET_CMD_SP(sp);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index a696bbb..54a5337 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -618,7 +618,7 @@ void qla2x00_async_nack_sp_done(void *v, void *s, int res)
}
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
}
int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
@@ -668,7 +668,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
return rval;
done_free_sp:
- sp->free(vha, sp);
+ sp->free(sp->vha, sp);
done:
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 18/22] qla2xxx: Fix slow mem alloc behind lock
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (16 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 17/22] qla2xxx: Rerfactor use of sp context Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-06 20:30 ` [PATCH 19/22] qla2xxx: Reduce exess wait during chip reset Himanshu Madhani
` (4 subsequent siblings)
22 siblings, 0 replies; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
In Some instance following stack trace is seen for slow
memory allocation with lock held
Call Trace:
[<ffffffff81341687>] dump_stack+0x6b/0xa4
[<ffffffff810c3e30>] ? print_irqtrace_events+0xd0/0xe0
[<ffffffff8109e3c3>] ___might_sleep+0x183/0x240
[<ffffffff8109e4d2>] __might_sleep+0x52/0x90
[<ffffffff811fe17b>] kmem_cache_alloc_trace+0x5b/0x300
[<ffffffff810c666b>] ? __lock_acquired+0x30b/0x420
[<ffffffffa0733c28>] qla2x00_alloc_fcport+0x38/0x2a0 [qla2xxx]
[<ffffffffa07217f4>] ? qla2x00_do_work+0x34/0x2b0 [qla2xxx]
[<ffffffff816cc82b>] ? _raw_spin_lock_irqsave+0x7b/0x90
[<ffffffffa072169a>] ? qla24xx_create_new_sess+0x3a/0x160 [qla2xxx]
[<ffffffffa0721723>] qla24xx_create_new_sess+0xc3/0x160 [qla2xxx]
[<ffffffff810c91ed>] ? trace_hardirqs_on+0xd/0x10
[<ffffffffa07218f8>] qla2x00_do_work+0x138/0x2b0 [qla2xxx]
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_gbl.h | 1 +
drivers/scsi/qla2xxx/qla_os.c | 35 ++++++++++++++++++++++++++++++++++-
drivers/scsi/qla2xxx/qla_target.c | 11 +++++------
3 files changed, 40 insertions(+), 7 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 2e28b3f..9489a1c 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -143,6 +143,7 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *,
extern int ql_dm_tgt_ex_pct;
extern struct workqueue_struct *qla_wq;
extern int ql2xmvasynctoatio;
+extern struct kmem_cache *qla_tgt_plogi_cachep;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 87dc64a..8137238 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4486,8 +4486,9 @@ int qla24xx_post_upd_fcport_work(struct scsi_qla_host *vha, fc_port_t *fcport)
void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
{
unsigned long flags;
- fc_port_t *fcport = NULL;
+ fc_port_t *fcport = NULL, *tfcp;
qlt_plogi_ack_t *pla = (qlt_plogi_ack_t *)e->u.new_sess.pla;
+ uint8_t free_fcport = 0;
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1);
@@ -4502,6 +4503,8 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
pla->ref_count--;
}
} else {
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (fcport) {
fcport->d_id = e->u.new_sess.id;
@@ -4511,6 +4514,30 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
memcpy(&fcport->port_name, e->u.new_sess.port_name,
WWN_SIZE);
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %8phC mem alloc fail.\n",
+ __func__, e->u.new_sess.port_name);
+
+ if (pla)
+ kmem_cache_free(qla_tgt_plogi_cachep, pla);
+ return;
+ }
+
+ spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ /* search again to make sure one else got ahead */
+ tfcp = qla2x00_find_fcport_by_wwpn(vha,
+ e->u.new_sess.port_name, 1);
+ if (tfcp) {
+ /* should rarily happen */
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %8phC found existing fcport b4 add. DS %d LS %d\n",
+ __func__, tfcp->port_name, tfcp->disc_state,
+ tfcp->fw_login_state);
+
+ free_fcport = 1;
+ } else {
+
list_add_tail(&fcport->list, &vha->vp_fcports);
if (pla) {
@@ -4527,6 +4554,12 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
else
qla24xx_async_gnl(vha, fcport);
}
+
+ if (free_fcport) {
+ qla2x00_free_fcport(fcport);
+ if (pla)
+ kmem_cache_free(qla_tgt_plogi_cachep, pla);
+ }
}
void
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 54a5337..8a4b506 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -49,13 +49,12 @@
module_param(qlop_mode, charp, S_IRUGO);
MODULE_PARM_DESC(qlop_mode,
"Determines operating mode. Possible values: "
- "\"exclusive\" - initiator mode will be enabled on load, "
- "disabled on enabling target mode and then on disabling target mode "
- "enabled back; "
+ "\"exclusive\" - Initiator Mode will be enabled on load. "
+ " Target Mode can be activated when ready. Only one mode can be active at a time; "
"\"tgt_mode\" - Target mode only. Initiator mode will never be enabled; "
- "\"dual_mode\" - Initiator Modes will be enabled. Target Mode can be "
+ "\"dual_mode\" - Initiator Modes will be enabled on load. Target Mode can be "
"activated when ready; "
- "\"ini_mode\" (default) - initiator mode will always stay enabled.");
+ "\"ini_mode\" (default) - Initiator mode will always stay enabled.");
int ql_dm_tgt_ex_pct = 50;
module_param(ql_dm_tgt_ex_pct, int, S_IRUGO|S_IWUSR);
@@ -133,7 +132,7 @@ static struct fc_port *qlt_create_sess(struct scsi_qla_host *vha,
/*
* Global Variables
*/
-static struct kmem_cache *qla_tgt_plogi_cachep;
+struct kmem_cache *qla_tgt_plogi_cachep;
static struct workqueue_struct *qla_tgt_wq;
static DEFINE_MUTEX(qla_tgt_mutex);
LIST_HEAD(qla_tgt_glist);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 19/22] qla2xxx: Reduce exess wait during chip reset
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (17 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 18/22] qla2xxx: Fix slow mem alloc behind lock Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-06 20:30 ` [PATCH 20/22] qla2xxx: Allow relogin to go through if remote login did not finish Himanshu Madhani
` (3 subsequent siblings)
22 siblings, 0 replies; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
Per HW recommendation, Soft reset and Risc reset should
take 100uS to complete. This change pad the timeout up to
400uS, which should be plenty.
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_init.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index dcb8c49..d8b18a9 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2112,7 +2112,7 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
/* Wait for soft-reset to complete. */
RD_REG_DWORD(®->ctrl_status);
- for (cnt = 0; cnt < 6000000; cnt++) {
+ for (cnt = 0; cnt < 60; cnt++) {
barrier();
if ((RD_REG_DWORD(®->ctrl_status) &
CSRX_ISP_SOFT_RESET) == 0)
@@ -2155,7 +2155,7 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
RD_REG_DWORD(®->hccr);
RD_REG_WORD(®->mailbox0);
- for (cnt = 6000000; RD_REG_WORD(®->mailbox0) != 0 &&
+ for (cnt = 60; RD_REG_WORD(®->mailbox0) != 0 &&
rval == QLA_SUCCESS; cnt--) {
barrier();
if (cnt)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 20/22] qla2xxx: Allow relogin to go through if remote login did not finish
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (18 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 19/22] qla2xxx: Reduce exess wait during chip reset Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-07 12:05 ` Hannes Reinecke
2016-12-06 20:30 ` [PATCH 21/22] qla2xxx: Improve submission of non critical MB interface Himanshu Madhani
` (2 subsequent siblings)
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_def.h | 2 ++
drivers/scsi/qla2xxx/qla_init.c | 14 ++++++++++++--
drivers/scsi/qla2xxx/qla_isr.c | 25 +++++++++++++++++++------
drivers/scsi/qla2xxx/qla_os.c | 2 +-
drivers/scsi/qla2xxx/qla_target.c | 2 ++
5 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 3464d65..404acee 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2216,6 +2216,8 @@ enum rscn_addr_format {
struct ct_sns_desc ct_desc;
enum discovery_state disc_state;
enum login_state fw_login_state;
+ unsigned long plogi_nack_done_jiff;
+
u32 login_gen, last_login_gen;
u32 rscn_gen, last_rscn_gen;
u32 chip_reset;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index d8b18a9..549a7c6 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -895,10 +895,15 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
fcport->login_retry--;
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 0;
+ if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
+ unsigned long t = fcport->plogi_nack_done_jiff + HZ;
+ if (time_before_eq(jiffies, t))
+ return 0;
+ }
+
if (vha->host->active_mode == MODE_TARGET)
/* for pure Target Mode. Login will not be initiated */
return 0;
@@ -1060,10 +1065,15 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
fcport->flags);
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;
+ if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
+ unsigned long t = fcport->plogi_nack_done_jiff + HZ;
+ if (time_before_eq(jiffies, t))
+ return;
+ }
+
if (fcport->flags & FCF_ASYNC_SENT) {
fcport->login_retry++;
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index c81ada0..c02033b 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1625,9 +1625,9 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
QLA_LOGIO_LOGIN_RETRIED : 0;
if (logio->entry_status) {
ql_log(ql_log_warn, fcport->vha, 0x5034,
- "Async-%s error entry - hdl=%x"
+ "Async-%s error entry - %8phC hdl=%x"
"portid=%02x%02x%02x entry-status=%x.\n",
- type, sp->handle, fcport->d_id.b.domain,
+ type, fcport->port_name, sp->handle, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa,
logio->entry_status);
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x504d,
@@ -1638,8 +1638,9 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) {
ql_dbg(ql_dbg_async, fcport->vha, 0x5036,
- "Async-%s complete - hdl=%x portid=%02x%02x%02x "
- "iop0=%x.\n", type, sp->handle, fcport->d_id.b.domain,
+ "Async-%s complete - %8phC hdl=%x portid=%02x%02x%02x "
+ "iop0=%x.\n", type, fcport->port_name, sp->handle,
+ fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa,
le32_to_cpu(logio->io_parameter[0]));
@@ -1679,6 +1680,17 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
case LSC_SCODE_NPORT_USED:
data[0] = MBS_LOOP_ID_USED;
break;
+ case LSC_SCODE_CMD_FAILED:
+ if (iop[1] == 0x0606) {
+ /* PLOGI/PRLI Completed. We must have Recv PLOGI/PRLI,
+ * Target side acked.
+ */
+ data[0] = MBS_COMMAND_COMPLETE;
+ goto logio_done;
+ break;
+ }
+ data[0] = MBS_COMMAND_ERROR;
+ break;
case LSC_SCODE_NOXCB:
vha->hw->exch_starvation++;
if (vha->hw->exch_starvation > 5) {
@@ -1700,8 +1712,9 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
}
ql_dbg(ql_dbg_async, fcport->vha, 0x5037,
- "Async-%s failed - hdl=%x portid=%02x%02x%02x comp=%x "
- "iop0=%x iop1=%x.\n", type, sp->handle, fcport->d_id.b.domain,
+ "Async-%s failed - %8phC hdl=%x portid=%02x%02x%02x comp=%x "
+ "iop0=%x iop1=%x.\n", type, fcport->port_name,
+ sp->handle, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa,
le16_to_cpu(logio->comp_status),
le32_to_cpu(logio->io_parameter[0]),
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 8137238..3e089c3 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4512,7 +4512,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
fcport->flags |= FCF_FABRIC_DEVICE;
fcport->fw_login_state = DSC_LS_PLOGI_PEND;
- memcpy(&fcport->port_name, e->u.new_sess.port_name,
+ memcpy(fcport->port_name, e->u.new_sess.port_name,
WWN_SIZE);
} else {
ql_dbg(ql_dbg_disc, vha, 0xffff,
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 8a4b506..521b114 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -576,6 +576,7 @@ void qla2x00_async_nack_sp_done(void *v, void *s, int res)
sp->fcport->login_gen++;
sp->fcport->fw_login_state = DSC_LS_PLOGI_COMP;
sp->fcport->logout_on_delete = 1;
+ sp->fcport->plogi_nack_done_jiff = jiffies;
break;
case SRB_NACK_PRLI:
@@ -3509,6 +3510,7 @@ static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha,
return -ENOMEM;
}
+ vha->vha_tgt.qla_tgt->notify_ack_expected++;
pkt->entry_type = NOTIFY_ACK_TYPE;
pkt->entry_count = 1;
pkt->handle = QLA_TGT_SKIP_HANDLE;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 20/22] qla2xxx: Allow relogin to go through if remote login did not finish
2016-12-06 20:30 ` [PATCH 20/22] qla2xxx: Allow relogin to go through if remote login did not finish Himanshu Madhani
@ 2016-12-07 12:05 ` Hannes Reinecke
0 siblings, 0 replies; 50+ messages in thread
From: Hannes Reinecke @ 2016-12-07 12:05 UTC (permalink / raw)
To: Himanshu Madhani, target-devel, nab; +Cc: giridhar.malavali, linux-scsi
On 12/06/2016 09:30 PM, Himanshu Madhani wrote:
> From: Quinn Tran <quinn.tran@cavium.com>
>
> Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
> ---
> drivers/scsi/qla2xxx/qla_def.h | 2 ++
> drivers/scsi/qla2xxx/qla_init.c | 14 ++++++++++++--
> drivers/scsi/qla2xxx/qla_isr.c | 25 +++++++++++++++++++------
> drivers/scsi/qla2xxx/qla_os.c | 2 +-
> drivers/scsi/qla2xxx/qla_target.c | 2 ++
> 5 files changed, 36 insertions(+), 9 deletions(-)
>
[ .. ]
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index 8137238..3e089c3 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -4512,7 +4512,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
> fcport->flags |= FCF_FABRIC_DEVICE;
> fcport->fw_login_state = DSC_LS_PLOGI_PEND;
>
> - memcpy(&fcport->port_name, e->u.new_sess.port_name,
> + memcpy(fcport->port_name, e->u.new_sess.port_name,
> WWN_SIZE);
> } else {
> ql_dbg(ql_dbg_disc, vha, 0xffff,
Misplaced hunk, maybe?
Seems like a genuine fix, and unrelated to the rest of the path.
Please move to a separate patch (or merge with the original introducing
this issue, if possible).
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.com +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 21/22] qla2xxx: Improve submission of non critical MB interface.
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (19 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 20/22] qla2xxx: Allow relogin to go through if remote login did not finish Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-07 12:16 ` Hannes Reinecke
2016-12-06 20:30 ` [PATCH 22/22] qla2xxx: Add check for corrupt ATIO Himanshu Madhani
2016-12-12 23:10 ` [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Madhani, Himanshu
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
Move Get ID list, stats and Get Port Databasae mailbox commands
out of MB interface which is serialized to IOCB interface
to reduce contention.
Current driver wait for FW to be in the ready state
before processing in coming commands. For loop mode,
certain initiator takes longer for login to complete.
While other initiators already sends commands.
Add processing of Report ID Acquision F2. For Direct
connect and target mode, Rida F2 provides the ALPA/Nport ID
of the local adapter.
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_def.h | 34 +++-
drivers/scsi/qla2xxx/qla_dfs.c | 85 +++++++++-
drivers/scsi/qla2xxx/qla_fw.h | 18 +++
drivers/scsi/qla2xxx/qla_gbl.h | 12 +-
drivers/scsi/qla2xxx/qla_init.c | 112 ++++++--------
drivers/scsi/qla2xxx/qla_isr.c | 22 ++-
drivers/scsi/qla2xxx/qla_mbx.c | 315 +++++++++++++++++++++++++++++++++++---
drivers/scsi/qla2xxx/qla_os.c | 95 +++++++++---
drivers/scsi/qla2xxx/qla_target.c | 53 ++++---
drivers/scsi/qla2xxx/qla_target.h | 5 +
10 files changed, 607 insertions(+), 144 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 404acee..de058a1 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -395,11 +395,15 @@ struct srb_iocb {
struct completion comp;
} abt;
struct ct_arg ctarg;
+#define MAX_IOCB_MB_REG 28
+#define SIZEOF_IOCB_MB_REG (MAX_IOCB_MB_REG * sizeof(uint16_t))
struct {
- __le16 in_mb[28]; /* fr fw */
- __le16 out_mb[28]; /* to fw */
+ __le16 in_mb[MAX_IOCB_MB_REG]; /* fr fw */
+ __le16 out_mb[MAX_IOCB_MB_REG]; /* to fw */
void *out, *in;
dma_addr_t out_dma, in_dma;
+ struct completion comp;
+ int rc;
} mbx;
struct {
struct imm_ntfy_from_isp *ntfy;
@@ -2075,7 +2079,7 @@ struct mbx_24xx_entry {
/*
* Fibre channel port type.
*/
- typedef enum {
+typedef enum {
FCT_UNKNOWN,
FCT_RSCN,
FCT_SWITCH,
@@ -3217,6 +3221,8 @@ struct qlt_hw_data {
uint8_t tgt_node_name[WWN_SIZE];
struct dentry *dfs_tgt_sess;
+ struct dentry *dfs_tgt_port_database;
+
struct list_head q_full_list;
uint32_t num_pend_cmds;
uint32_t num_qfull_cmds_alloc;
@@ -3235,6 +3241,18 @@ struct qlt_hw_data {
#define LEAK_EXCHG_THRESH_HOLD_PERCENT 75 /* 75 percent */
+/* */
+enum chip_state {
+ QLA_CS_ROM = 0,
+ QLA_FW_OPTIONS,
+ QLA_INIT_FW,
+ QLA_CS_FW_RDY,
+};
+
+#define QLA_EARLY_LINKUP(_ha) \
+ ((_ha->flags.n2n_ae || _ha->flags.lip_ae) && \
+ _ha->flags.fw_started && !_ha->flags.fw_init_done)
+
/*
* Qlogic host adapter specific data structure.
*/
@@ -3284,7 +3302,12 @@ struct qla_hw_data {
uint32_t fawwpn_enabled:1;
uint32_t exlogins_enabled:1;
uint32_t exchoffld_enabled:1;
- /* 35 bits */
+
+ uint32_t lip_ae:1;
+ uint32_t n2n_ae:1;
+ uint32_t fw_started:1;
+ uint32_t fw_init_done:1;
+
} flags;
/* This spinlock is used to protect "io transactions", you must
@@ -3866,6 +3889,7 @@ struct qla_tgt_counters {
struct list_head vp_fcports; /* list of fcports */
struct list_head work_list;
spinlock_t work_lock;
+ struct work_struct iocb_work;
/* Commonly used flags and state information. */
struct Scsi_Host *host;
@@ -3885,6 +3909,8 @@ struct qla_tgt_counters {
uint32_t fw_tgt_reported:1;
uint32_t bbcr_enable:1;
uint32_t qpairs_available:1;
+
+ uint32_t iocb_work_sheduled:1;
} flags;
atomic_t loop_state;
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 18cedf7..9fad3a8 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -143,7 +143,6 @@ static ssize_t qla_dfs_irqpoll_write(struct file *file, const char __user *ubuf,
return single_open(file, qla2x00_dfs_tgt_sess_show, vha);
}
-
static const struct file_operations dfs_tgt_sess_ops = {
.open = qla2x00_dfs_tgt_sess_open,
.read = seq_read,
@@ -152,6 +151,77 @@ static ssize_t qla_dfs_irqpoll_write(struct file *file, const char __user *ubuf,
};
static int
+qla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused)
+{
+ scsi_qla_host_t *vha = s->private;
+ struct qla_hw_data *ha = vha->hw;
+ struct gid_list_info *gid_list;
+ dma_addr_t gid_list_dma;
+ fc_port_t fc_port;
+ char *id_iter;
+ int rc, i;
+ uint16_t entries, loop_id;
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+
+ seq_printf(s, "%s\n", vha->host_str);
+ if (tgt) {
+ gid_list = dma_alloc_coherent(&ha->pdev->dev,
+ qla2x00_gid_list_size(ha),
+ &gid_list_dma, GFP_KERNEL);
+ if (!gid_list) {
+ ql_dbg(ql_dbg_user, vha, 0x705c,
+ "DMA allocation failed for %u\n",
+ qla2x00_gid_list_size(ha));
+ return 0;
+ }
+
+ rc = qla24xx_gidlist_wait(vha, gid_list, gid_list_dma,
+ &entries);
+ if (rc != QLA_SUCCESS)
+ goto out_free_id_list;
+
+ id_iter = (char *)gid_list;
+
+ seq_printf(s, "Port Name Port ID Loop ID\n");
+
+ for (i = 0; i < entries; i++) {
+ struct gid_list_info *gid =
+ (struct gid_list_info *)id_iter;
+ loop_id = le16_to_cpu(gid->loop_id);
+ memset(&fc_port, 0, sizeof(fc_port_t));
+
+ fc_port.loop_id = loop_id;
+
+ rc = qla24xx_gpdb_wait(vha, &fc_port, 0);
+ seq_printf(s, "%8phC %02x%02x%02x %d\n",
+ fc_port.port_name, fc_port.d_id.b.domain,
+ fc_port.d_id.b.area, fc_port.d_id.b.al_pa,
+ fc_port.loop_id);
+ id_iter += ha->gid_list_info_size;
+ }
+out_free_id_list:
+ dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
+ gid_list, gid_list_dma);
+ }
+
+ return 0;
+}
+
+static int
+qla2x00_dfs_tgt_port_database_open(struct inode *inode, struct file *file)
+{
+ scsi_qla_host_t *vha = inode->i_private;
+ return single_open(file, qla2x00_dfs_tgt_port_database_show, vha);
+}
+
+static const struct file_operations dfs_tgt_port_database_ops = {
+ .open = qla2x00_dfs_tgt_port_database_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int
qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
{
struct scsi_qla_host *vha = s->private;
@@ -395,6 +465,14 @@ static ssize_t qla_dfs_irqpoll_write(struct file *file, const char __user *ubuf,
goto out;
}
+ 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,
+ "Unable to create debugFS tgt_port_database node.\n");
+ goto out;
+ }
+
ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, vha,
&dfs_fce_ops);
if (!ha->dfs_fce) {
@@ -452,6 +530,11 @@ static ssize_t qla_dfs_irqpoll_write(struct file *file, const char __user *ubuf,
ha->tgt.dfs_tgt_sess = NULL;
}
+ if (ha->tgt.dfs_tgt_port_database) {
+ debugfs_remove(ha->tgt.dfs_tgt_port_database);
+ ha->tgt.dfs_tgt_port_database = NULL;
+ }
+
if (ha->dfs_fw_resource_cnt) {
debugfs_remove(ha->dfs_fw_resource_cnt);
ha->dfs_fw_resource_cnt = NULL;
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 6f3439c..77a4d45 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1353,6 +1353,24 @@ struct vp_rpt_id_entry_24xx {
uint16_t bbcr;
uint8_t reserved_5[6];
} f1;
+ struct {
+ /* format 2: N2N direct connect */
+ uint8_t vpstat1_subcode;
+ uint8_t flags;
+ uint16_t rsv6;
+ uint8_t rsv2[12];
+
+ uint8_t ls_rjt_vendor;
+ uint8_t ls_rjt_explanation;
+ uint8_t ls_rjt_reason;
+ uint8_t rsv3[5];
+
+ uint8_t port_name[8];
+ uint8_t node_name[8];
+ uint32_t remote_nport_id;
+ uint32_t reserved_5;
+ } f2;
+
} u;
};
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 9489a1c..c713afb 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -107,6 +107,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *,
u8 *, void *);
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
+int qla24xx_async_abort_cmd(srb_t *);
/*
* Global Data in qla_os.c source file.
@@ -200,6 +201,8 @@ extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
+void qla2x00_schedule_work(struct scsi_qla_host *);
+
/*
* Global Functions in qla_mid.c source file.
@@ -375,7 +378,7 @@ extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *,
extern int
qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *,
- dma_addr_t, uint);
+ dma_addr_t, uint16_t);
extern int qla24xx_abort_command(srb_t *);
extern int qla24xx_async_abort_command(srb_t *);
@@ -479,6 +482,13 @@ extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
extern int
qla26xx_dport_diagnostics(scsi_qla_host_t *, void *, uint, uint);
+int qla24xx_send_mb_cmd(struct scsi_qla_host *, mbx_cmd_t *);
+int qla24xx_gpdb_wait(struct scsi_qla_host *, fc_port_t *, u8);
+int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t,
+ uint16_t *);
+int _qla24xx_parse_gpdb(struct scsi_qla_host *, fc_port_t *,
+ struct port_database_24xx *);
+
/*
* Global Function Prototypes in qla_isr.c source file.
*/
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 549a7c6..4934ee0 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -100,13 +100,18 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct event_arg ea;
- ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
- "Async-%s timeout - hdl=%x portid=%02x%02x%02x %8phC.\n",
- sp->name, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa, fcport->port_name);
- if (fcport)
+ if (fcport) {
fcport->flags &= ~FCF_ASYNC_SENT;
+ ql_dbg(ql_dbg_disc, sp->vha, 0x2071,
+ "Async-%s timeout - hdl=%x portid=%02x%02x%02x %8phC.\n",
+ sp->name, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa, fcport->port_name);
+ } else {
+ ql_dbg(ql_dbg_disc, sp->vha, 0x2071,
+ "Async-%s timeout - hdl=%x .\n",
+ sp->name, sp->handle);
+ }
switch (sp->type) {
case SRB_LOGIN_CMD:
@@ -638,7 +643,6 @@ void qla24xx_async_gpdb_sp_done(void *v, void *s, int res)
struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
struct srb *sp = (struct srb *)s;
struct qla_hw_data *ha = vha->hw;
- uint64_t zero = 0;
struct port_database_24xx *pd;
fc_port_t *fcport = sp->fcport;
u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
@@ -658,49 +662,7 @@ void qla24xx_async_gpdb_sp_done(void *v, void *s, int res)
pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
- /* 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);
- rval = QLA_FUNCTION_FAILED;
- goto gpd_error_out;
- }
-
- if (fcport->loop_id == FC_NO_LOOP_ID ||
- (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
- memcmp(fcport->port_name, pd->port_name, 8))) {
-
- /* We lost the device mid way. */
- rval = QLA_NOT_LOGGED_IN;
- goto gpd_error_out;
- }
-
- /* Names are little-endian. */
- memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
-
- /* Get port_id of device. */
- fcport->d_id.b.domain = pd->port_id[0];
- fcport->d_id.b.area = pd->port_id[1];
- 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;
-
- /* Passback COS information. */
- fcport->supported_classes = (pd->flags & PDF_CLASS_2) ?
- FC_COS_CLASS2 : FC_COS_CLASS3;
-
- if (pd->prli_svc_param_word_3[0] & BIT_7) {
- fcport->flags |= FCF_CONF_COMP_SUPPORTED;
- fcport->conf_compl_supported = 1;
- }
+ rval = _qla24xx_parse_gpdb(vha, fcport, pd);
gpd_error_out:
memset(&ea, 0, sizeof(ea));
@@ -880,7 +842,6 @@ 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,
"%s %8phC DS %d LS %d P %d fl %x confl %p "
"rscn %d|%d login %d|%d retry %d lid %d\n",
@@ -973,6 +934,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
qla24xx_post_gpdb_work(vha, fcport, PDO_FORCE_ADISC);
break;
+ case DSC_LOGIN_PEND:
default:
break;
}
@@ -1093,7 +1055,10 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
return;
}
- qla24xx_fcport_handle_login(vha, fcport);
+ if (fcport->deleted)
+ qla24xx_fcport_handle_login(vha, fcport);
+ else
+ qlt_schedule_sess_for_deletion(fcport, 1);
}
void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
@@ -1123,9 +1088,8 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
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);
+ "RSCN GPNID work failed %#06x\n",
+ ea->id.b24);
}
} else {
ea->fcport = fcport;
@@ -1138,13 +1102,13 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
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);
+ "RSCN: Area %#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);
+ "RSCN: Domain %#06x was affected\n",
+ ea->id.b24);
}
rid = ea->id.b24 & mask;
@@ -1293,7 +1257,7 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
complete(&abt->u.abt.comp);
}
-static int
+int
qla24xx_async_abort_cmd(srb_t *cmd_sp)
{
scsi_qla_host_t *vha = cmd_sp->vha;
@@ -1446,7 +1410,6 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
{
if (data[0] == MBS_COMMAND_COMPLETE) {
qla2x00_update_fcport(vha, fcport);
-
return;
}
@@ -3255,6 +3218,7 @@ void qla2x00_fcport_event_handler (scsi_qla_host_t *vha,
} else {
ql_dbg(ql_dbg_init, vha, 0x00d3,
"Init Firmware -- success.\n");
+ ha->flags.fw_started = 1;
}
return (rval);
@@ -4079,6 +4043,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
atomic_set(&vha->loop_state, LOOP_READY);
ql_dbg(ql_dbg_disc, vha, 0x2069,
"LOOP READY.\n");
+ ha->flags.fw_init_done = 1;
/*
* Process any ATIO queue entries that came in
@@ -4881,12 +4846,9 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
{
int rval;
struct qla_hw_data *ha = vha->hw;
- unsigned long flags = 0;
rval = QLA_SUCCESS;
- spin_lock_irqsave(&ha->vport_slock, flags);
-
dev->loop_id = find_first_zero_bit(ha->loop_id_map,
LOOPID_MAP_SIZE);
if (dev->loop_id >= LOOPID_MAP_SIZE ||
@@ -4896,8 +4858,6 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
} else
set_bit(dev->loop_id, ha->loop_id_map);
- spin_unlock_irqrestore(&ha->vport_slock, flags);
-
if (rval == QLA_SUCCESS)
ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
"Assigning new loopid=%x, portid=%x.\n",
@@ -4934,6 +4894,7 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
uint16_t tmp_loopid;
uint16_t mb[MAILBOX_REGISTER_COUNT];
struct qla_hw_data *ha = vha->hw;
+ unsigned long flags = 0;
retry = 0;
tmp_loopid = 0;
@@ -5012,7 +4973,9 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *vha, nvram_t *nv)
* Loop ID already used, try next loop ID.
*/
fcport->loop_id++;
+ spin_lock_irqsave(&ha->vport_slock, flags);
rval = qla2x00_find_new_loop_id(vha, fcport);
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
if (rval != QLA_SUCCESS) {
/* Ran out of loop IDs to use */
break;
@@ -5583,6 +5546,12 @@ int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
if (!(IS_P3P_TYPE(ha)))
ha->isp_ops->reset_chip(vha);
+ ha->flags.n2n_ae = 0;
+ ha->flags.lip_ae = 0;
+ ha->current_topology = 0;
+ ha->flags.fw_started = 0;
+ ha->flags.fw_init_done = 0;
+
ha->chip_reset++;
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
@@ -6214,6 +6183,10 @@ static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *vha,
vha->flags.process_response_queue = 1;
}
+ /* enable RIDA Format2 */
+ if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha))
+ icb->firmware_options_3 |= BIT_0;
+
if (rval) {
ql_log(ql_log_warn, vha, 0x0070,
"NVRAM configuration failed.\n");
@@ -6860,6 +6833,8 @@ uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
return;
if (!ha->fw_major_version)
return;
+ if (!ha->flags.fw_started)
+ return;
ret = qla2x00_stop_firmware(vha);
for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
@@ -6873,6 +6848,9 @@ uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
"Attempting retry of stop-firmware command.\n");
ret = qla2x00_stop_firmware(vha);
}
+
+ ha->flags.fw_started = 0;
+ ha->flags.fw_init_done = 0;
}
int
@@ -7266,6 +7244,10 @@ uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
vha->flags.process_response_queue = 1;
}
+ /* enable RIDA Format2 */
+ if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha))
+ icb->firmware_options_3 |= BIT_0;
+
if (rval) {
ql_log(ql_log_warn, vha, 0x0076,
"NVRAM configuration failed.\n");
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index c02033b..d854173 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -132,8 +132,9 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
schedule_work(&vha->hw->board_disable);
}
return true;
- } else
- return false;
+ }
+
+ return false;
}
bool
@@ -712,6 +713,8 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
"mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx);
ha->isp_ops->fw_dump(vha, 1);
+ ha->flags.fw_init_done = 0;
+ ha->flags.fw_started = 0;
if (IS_FWI2_CAPABLE(ha)) {
if (mb[1] == 0 && mb[2] == 0) {
@@ -765,6 +768,9 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
break;
case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */
+ ha->flags.lip_ae = 1;
+ ha->flags.n2n_ae = 0;
+
ql_dbg(ql_dbg_async, vha, 0x5009,
"LIP occurred (%x).\n", mb[1]);
@@ -796,11 +802,16 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
"LOOP UP detected (%s Gbps).\n",
qla2x00_get_link_speed_str(ha, ha->link_data_rate));
+
vha->flags.management_server_logged_in = 0;
qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
break;
case MBA_LOOP_DOWN: /* Loop Down Event */
+ ha->flags.n2n_ae=0;
+ ha->flags.lip_ae=0;
+ ha->current_topology = 0;
+
mbx = (IS_QLA81XX(ha) || IS_QLA8031(ha))
? RD_REG_WORD(®24->mailbox4) : 0;
mbx = (IS_P3P_TYPE(ha)) ? RD_REG_WORD(®82->mailbox_out[4])
@@ -870,6 +881,9 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
/* case MBA_DCBX_COMPLETE: */
case MBA_POINT_TO_POINT: /* Point-to-Point */
+ ha->flags.lip_ae = 0;
+ ha->flags.n2n_ae = 1;
+
if (IS_QLA2100(ha))
break;
@@ -1790,7 +1804,7 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
vha = pci_get_drvdata(ha->pdev);
- if (!vha->flags.online)
+ if (!ha->flags.fw_started)
return;
while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
@@ -2705,7 +2719,7 @@ struct scsi_dif_tuple {
return;
abt = &sp->u.iocb_cmd;
- abt->u.abt.comp_status = le32_to_cpu(pkt->nport_handle);
+ abt->u.abt.comp_status = le16_to_cpu(pkt->nport_handle);
sp->done(sp->vha, sp, 0);
}
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 3caaf06..b78bc95 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -18,6 +18,30 @@ struct mbx_cmd_info_t {
int status;
};
+struct mb_cmd_name {
+ uint16_t cmd;
+ char *str;
+} mb_str[] = {
+ {0xffff, "unknown"},
+ {MBC_GET_PORT_DATABASE, "GPDB"},
+ {MBC_GET_ID_LIST, "GIDList"},
+ {MBC_GET_LINK_PRIV_STATS, "Stats"},
+};
+
+static
+char *mb_to_str(uint16_t cmd)
+{
+ int i;
+ struct mb_cmd_name *e;
+
+ for (i = 0; i < ARRAY_SIZE(mb_str); i++) {
+ e = mb_str + i;
+ if (cmd == e->cmd)
+ return e->str;
+ }
+ return mb_str[0].str; /* unknown */
+}
+
struct rom_cmd {
uint16_t cmd;
} rom_cmds[] = {
@@ -2863,7 +2887,7 @@ static int is_rom_cmd(uint16_t cmd)
int
qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
- dma_addr_t stats_dma, uint options)
+ dma_addr_t stats_dma, uint16_t options)
{
int rval;
mbx_cmd_t mc;
@@ -2873,19 +2897,17 @@ static int is_rom_cmd(uint16_t cmd)
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088,
"Entered %s.\n", __func__);
- mcp->mb[0] = MBC_GET_LINK_PRIV_STATS;
- mcp->mb[2] = MSW(stats_dma);
- mcp->mb[3] = LSW(stats_dma);
- mcp->mb[6] = MSW(MSD(stats_dma));
- mcp->mb[7] = LSW(MSD(stats_dma));
- mcp->mb[8] = sizeof(struct link_statistics) / 4;
- mcp->mb[9] = vha->vp_idx;
- mcp->mb[10] = options;
- mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
- mcp->in_mb = MBX_2|MBX_1|MBX_0;
- mcp->tov = MBX_TOV_SECONDS;
- mcp->flags = IOCTL_CMD;
- rval = qla2x00_mailbox_command(vha, mcp);
+ memset(&mc, 0, sizeof(mc));
+ mc.mb[0] = MBC_GET_LINK_PRIV_STATS;
+ mc.mb[2] = MSW(stats_dma);
+ mc.mb[3] = LSW(stats_dma);
+ mc.mb[6] = MSW(MSD(stats_dma));
+ mc.mb[7] = LSW(MSD(stats_dma));
+ mc.mb[8] = sizeof(struct link_statistics) / 4;
+ mc.mb[9] = cpu_to_le16(vha->vp_idx);
+ mc.mb[10] = cpu_to_le16(options);
+
+ rval = qla24xx_send_mb_cmd(vha, &mc);
if (rval == QLA_SUCCESS) {
if (mcp->mb[0] != MBS_COMMAND_COMPLETE) {
@@ -3657,11 +3679,11 @@ struct tsk_mgmt_cmd {
if (rptid_entry->format == 0) {
/* loop */
- ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b7,
- "Format 0 : Number of VPs setup %d, number of "
+ ql_dbg(ql_dbg_async, vha, 0x10b7,
+ "RIDA Format 0 : Number of VPs setup %d, number of "
"VPs acquired %d.\n",
rptid_entry->vp_setup,rptid_entry->vp_acquired);
- ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b8,
+ ql_dbg(ql_dbg_async, vha, 0x10b8,
"Primary port id %02x%02x%02x.\n",
rptid_entry->port_id[2], rptid_entry->port_id[1],
rptid_entry->port_id[0]);
@@ -3676,8 +3698,8 @@ struct tsk_mgmt_cmd {
} else if (rptid_entry->format == 1) {
/* fabric */
- ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b9,
- "Format 1: VP[%d] enabled - status %d - with "
+ ql_dbg(ql_dbg_async, vha, 0x10b9,
+ "RIDA Format 1: VP[%d] enabled - status %d - with "
"port id %02x%02x%02x.\n", rptid_entry->vp_idx,
rptid_entry->vp_status,
rptid_entry->port_id[2], rptid_entry->port_id[1],
@@ -3713,7 +3735,7 @@ struct tsk_mgmt_cmd {
fc_host_port_name(vha->host) =
wwn_to_u64(vha->port_name);
- ql_dbg(ql_dbg_mbx, vha, 0x1018,
+ ql_dbg(ql_dbg_async, vha, 0x1018,
"FA-WWN portname %016llx (%x)\n",
fc_host_port_name(vha->host), rptid_entry->vp_status);
set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
@@ -3758,6 +3780,24 @@ struct tsk_mgmt_cmd {
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,
+ "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,
+ "N2N: Remote WWPN %8phC.\n",
+ rptid_entry->u.f2.port_name);
+
+ /* N2N. direct connect */
+ vha->d_id.b.domain = rptid_entry->port_id[2];
+ vha->d_id.b.area = rptid_entry->port_id[1];
+ vha->d_id.b.al_pa = rptid_entry->port_id[0];
+
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ qlt_update_vp_map(vha, SET_AL_PA);
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
}
}
@@ -5856,3 +5896,238 @@ struct cs84xx_mgmt_cmd {
return rval;
}
+
+void qla2x00_async_mb_sp_done(void *v, void *s, int res)
+{
+ struct srb *sp = s;
+ sp->u.iocb_cmd.u.mbx.rc = res;
+ complete(&sp->u.iocb_cmd.u.mbx.comp);
+ /* don't free sp here. Let the caller do the free */
+}
+
+/* This mailbox uses the iocb interface to send MB command.
+ * This allows non-critial (non chip setup) command to go out in parrallel.
+ */
+int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
+{
+ int rval = QLA_FUNCTION_FAILED;
+ srb_t *sp;
+ struct srb_iocb *c;
+ char *name;
+
+ if (!vha->hw->flags.fw_started)
+ goto done;
+
+ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
+
+ sp->type = SRB_MB_IOCB;
+ sp->name = mb_to_str(mcp->mb[0]);
+ name = sp->name;
+
+ qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha)+2);
+
+ memcpy(sp->u.iocb_cmd.u.mbx.out_mb,
+ mcp->mb, SIZEOF_IOCB_MB_REG);
+
+ c = &sp->u.iocb_cmd;
+ c->timeout = qla2x00_async_iocb_timeout;
+ init_completion(&c->u.mbx.comp);
+
+ sp->done = qla2x00_async_mb_sp_done;
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0xffff,
+ "%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",
+ sp->name, sp->handle);
+
+ wait_for_completion(&c->u.mbx.comp);
+
+ memcpy(mcp->mb, sp->u.iocb_cmd.u.mbx.in_mb,
+ SIZEOF_IOCB_MB_REG);
+ rval = c->u.mbx.rc;
+ switch (rval) {
+ case QLA_FUNCTION_TIMEOUT:
+ ql_dbg(ql_dbg_mbx, vha, 0xffff,
+ "%s: %s Timeout. %x.\n",
+ __func__, name, rval);
+ break;
+ case QLA_SUCCESS:
+ ql_dbg(ql_dbg_mbx, vha, 0xffff,
+ "%s: %s done.\n",
+ __func__, sp->name);
+ sp->free(sp->vha, sp);
+ break;
+
+ default:
+ ql_dbg(ql_dbg_mbx, vha, 0xffff,
+ "%s: %s Failed. %x.\n",
+ __func__,sp->name, rval);
+ sp->free(sp->vha, sp);
+ break;
+ }
+
+ return rval;
+
+done_free_sp:
+ sp->free(sp->vha, sp);
+done:
+ return rval;
+
+}
+
+
+/* qla24xx_gpdb_wait
+ * NOTE:don't call this routine from DPC thread
+ */
+int qla24xx_gpdb_wait(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
+{
+ int rval = QLA_FUNCTION_FAILED;
+ dma_addr_t pd_dma;
+ struct port_database_24xx *pd;
+ struct qla_hw_data *ha = vha->hw;
+ mbx_cmd_t mc;
+
+ if (!vha->hw->flags.fw_started)
+ goto done;
+
+ 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");
+ goto done_free_sp;
+ }
+ memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE));
+
+ memset(&mc, 0, sizeof(mc));
+ mc.mb[0] = MBC_GET_PORT_DATABASE;
+ mc.mb[1] = cpu_to_le16(fcport->loop_id);
+ mc.mb[2] = MSW(pd_dma);
+ mc.mb[3] = LSW(pd_dma);
+ mc.mb[6] = MSW(MSD(pd_dma));
+ mc.mb[7] = LSW(MSD(pd_dma));
+ mc.mb[9] = cpu_to_le16(vha->vp_idx);
+ mc.mb[10] = cpu_to_le16((uint16_t)opt);
+
+
+ rval = qla24xx_send_mb_cmd(vha, &mc);
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0xffff,
+ "%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",
+ __func__, fcport->port_name);
+
+done_free_sp:
+ if (pd)
+ dma_pool_free(ha->s_dma_pool, pd, pd_dma);
+
+done:
+ return rval;
+}
+
+
+int
+_qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
+ struct port_database_24xx *pd)
+{
+ int rval = QLA_SUCCESS;
+ uint64_t zero = 0;
+
+ /* 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);
+ rval = QLA_FUNCTION_FAILED;
+ goto gpd_error_out;
+ }
+
+ if (fcport->loop_id == FC_NO_LOOP_ID ||
+ (memcmp(fcport->port_name, (uint8_t *)&zero, 8) &&
+ memcmp(fcport->port_name, pd->port_name, 8))) {
+
+ /* We lost the device mid way. */
+ rval = QLA_NOT_LOGGED_IN;
+ goto gpd_error_out;
+ }
+
+ /* Names are little-endian. */
+ memcpy(fcport->node_name, pd->node_name, WWN_SIZE);
+ memcpy(fcport->port_name, pd->port_name, WWN_SIZE);
+
+ /* Get port_id of device. */
+ fcport->d_id.b.domain = pd->port_id[0];
+ fcport->d_id.b.area = pd->port_id[1];
+ 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;
+
+ /* Passback COS information. */
+ fcport->supported_classes = (pd->flags & PDF_CLASS_2) ?
+ FC_COS_CLASS2 : FC_COS_CLASS3;
+
+ if (pd->prli_svc_param_word_3[0] & BIT_7) {
+ fcport->flags |= FCF_CONF_COMP_SUPPORTED;
+ fcport->conf_compl_supported = 1;
+ }
+
+gpd_error_out:
+ return rval;
+}
+
+/* qla24xx_gidlist__wait
+ * NOTE: don't call this routine from DPC thread.
+ */
+int qla24xx_gidlist_wait(struct scsi_qla_host *vha,
+ void *id_list, dma_addr_t id_list_dma, uint16_t *entries)
+{
+ int rval = QLA_FUNCTION_FAILED;
+ mbx_cmd_t mc;
+
+ if (!vha->hw->flags.fw_started)
+ goto done;
+
+ memset(&mc, 0, sizeof(mc));
+ mc.mb[0] = MBC_GET_ID_LIST;
+ mc.mb[2] = MSW(id_list_dma);
+ mc.mb[3] = LSW(id_list_dma);
+ mc.mb[6] = MSW(MSD(id_list_dma));
+ mc.mb[7] = LSW(MSD(id_list_dma));
+ mc.mb[8] = 0;
+ mc.mb[9] = cpu_to_le16(vha->vp_idx);
+
+ rval = qla24xx_send_mb_cmd(vha, &mc);
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0xffff,
+ "%s: fail\n", __func__);
+ } else {
+ *entries = mc.mb[1];
+ ql_dbg(ql_dbg_mbx, vha, 0xffff,
+ "%s: done\n", __func__);
+ }
+done:
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 3e089c3..06a3b86 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4365,7 +4365,11 @@ struct qla_work_evt *
spin_lock_irqsave(&vha->work_lock, flags);
list_add_tail(&e->list, &vha->work_list);
spin_unlock_irqrestore(&vha->work_lock, flags);
- qla2xxx_wake_dpc(vha);
+
+ if (QLA_EARLY_LINKUP(vha->hw))
+ qla2x00_schedule_work(vha);
+ else
+ qla2xxx_wake_dpc(vha);
return QLA_SUCCESS;
}
@@ -4645,6 +4649,49 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
}
}
+
+static void qla2x00_iocb_work_fn(struct work_struct *work)
+{
+ struct scsi_qla_host *vha = container_of(work,
+ struct scsi_qla_host, iocb_work);
+ unsigned long flags;
+ int cnt = 0;
+
+ while (!list_empty(&vha->work_list)) {
+ qla2x00_do_work(vha);
+ cnt++;
+ if (cnt > 10)
+ break;
+ }
+
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->flags.iocb_work_sheduled = 0;
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+}
+
+void qla2x00_schedule_work(struct scsi_qla_host *vha)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&vha->work_lock, flags);
+ if (vha->flags.iocb_work_sheduled) {
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+ return;
+ } else {
+ vha->flags.iocb_work_sheduled = 1;
+ }
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+
+
+ /* we're in the middle of bringing up the adapter.
+ * the scheduled work need to go out now.
+ */
+ INIT_WORK(&vha->iocb_work,
+ (void (*)(struct work_struct *))qla2x00_iocb_work_fn);
+
+ schedule_work(&vha->iocb_work);
+}
+
/* Relogins all the fcports of a vport
* Context: dpc thread
*/
@@ -4655,10 +4702,10 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
struct event_arg ea;
list_for_each_entry(fcport, &vha->vp_fcports, list) {
- /*
- * If the port is not ONLINE then try to login
- * to it if we haven't run out of retries.
- */
+ /*
+ * If the port is not ONLINE then try to login
+ * to it if we haven't run out of retries.
+ */
if (atomic_read(&fcport->state) != FCS_ONLINE &&
fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
fcport->login_retry--;
@@ -4673,31 +4720,29 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
qla2x00_fcport_event_handler(vha, &ea);
} else {
- status = qla2x00_local_device_login(vha,
- fcport);
+ status = qla2x00_local_device_login(vha, fcport);
- if (status == QLA_SUCCESS) {
- fcport->old_loop_id = fcport->loop_id;
+ if (status == QLA_SUCCESS) {
+ fcport->old_loop_id = fcport->loop_id;
- ql_dbg(ql_dbg_disc, vha, 0x2003,
- "Port login OK: logged in ID 0x%x.\n",
- fcport->loop_id);
+ ql_dbg(ql_dbg_disc, vha, 0x2003,
+ "Port login OK: logged in ID 0x%x.\n",
+ fcport->loop_id);
- qla2x00_update_fcport(vha, fcport);
+ qla2x00_update_fcport(vha, fcport);
- } else if (status == 1) {
- set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
- /* retry the login again */
- ql_dbg(ql_dbg_disc, vha, 0x2007,
- "Retrying %d login again loop_id 0x%x.\n",
- fcport->login_retry, fcport->loop_id);
- } else {
- fcport->login_retry = 0;
- }
-
- if (fcport->login_retry == 0 && status != QLA_SUCCESS)
- qla2x00_clear_loop_id(fcport);
+ } else if (status == 1) {
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+ /* retry the login again */
+ ql_dbg(ql_dbg_disc, vha, 0x2007,
+ "Retrying %d login again loop_id 0x%x.\n",
+ fcport->login_retry, fcport->loop_id);
+ } else {
+ fcport->login_retry = 0;
+ }
+ if (fcport->login_retry == 0 && status != QLA_SUCCESS)
+ qla2x00_clear_loop_id(fcport);
}
}
if (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 521b114..6f01c66 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -637,6 +637,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
case SRB_NACK_PRLI:
fcport->fw_login_state = DSC_LS_PRLI_PEND;
c = "PRLI";
+ fcport->deleted = 0;
break;
case SRB_NACK_LOGO:
fcport->fw_login_state = DSC_LS_LOGO_PEND;
@@ -1249,7 +1250,7 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id,
}
/* Get list of logged in devices */
- rc = qla2x00_get_id_list(vha, gid_list, gid_list_dma, &entries);
+ rc = qla24xx_gidlist_wait(vha, gid_list, gid_list_dma, &entries);
if (rc != QLA_SUCCESS) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf045,
"qla_target(%d): get_id_list() failed: %x\n",
@@ -1543,7 +1544,7 @@ static void qlt_send_notify_ack(struct scsi_qla_host *vha,
request_t *pkt;
struct nack_to_isp *nack;
- if (qla2x00_reset_active(vha))
+ if (!ha->flags.fw_started)
return;
ql_dbg(ql_dbg_tgt, vha, 0xe004, "Sending NOTIFY_ACK (ha=%p)\n", ha);
@@ -2052,8 +2053,8 @@ void qlt_send_resp_ctio(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID | scsi_status);
ctio->u.status1.response_len = __constant_cpu_to_le16(18);
- ctio->u.status1.residual = get_unaligned((uint32_t *)
- &atio->u.isp24.fcp_cmnd.add_cdb[0]);
+ ctio->u.status1.residual = cpu_to_le32(GET_DL_FR_ATIO(atio));
+
if (ctio->u.status1.residual != 0)
ctio->u.status1.scsi_status |= __constant_cpu_to_le16(SS_RESIDUAL_UNDER);
@@ -3128,7 +3129,8 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
else
vha->tgt_counters.core_qla_que_buf++;
- if (!vha->flags.online || cmd->reset_count != ha->chip_reset) {
+ if (!ha->flags.fw_started ||
+ cmd->reset_count != ha->chip_reset) {
/*
* Either the port is not online or this request was from
* previous life, just abort the processing.
@@ -3273,7 +3275,8 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (!vha->flags.online || (cmd->reset_count != ha->chip_reset) ||
+ if (!ha->flags.fw_started ||
+ (cmd->reset_count != ha->chip_reset) ||
(cmd->sess && cmd->sess->deleted)) {
/*
* Either the port is not online or this request was from
@@ -3502,7 +3505,7 @@ static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt_tmr, vha, 0xe01c,
"Sending TERM ELS CTIO (ha=%p)\n", ha);
- pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL);
+ pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL);
if (pkt == NULL) {
ql_dbg(ql_dbg_tgt, vha, 0xe080,
"qla_target(%d): %s failed: unable to allocate "
@@ -3624,12 +3627,6 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
ctio24->u.status1.ox_id = cpu_to_le16(temp);
- /* Most likely, it isn't needed */
- ctio24->u.status1.residual = get_unaligned((uint32_t *)
- &atio->u.isp24.fcp_cmnd.add_cdb[0]);
- if (ctio24->u.status1.residual != 0)
- ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER;
-
/* Memory Barrier */
wmb();
qla2x00_start_iocbs(vha, vha->req);
@@ -4210,10 +4207,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
else
data_dir = DMA_NONE;
-
- data_length = be32_to_cpu(get_unaligned((uint32_t *)
- &atio->u.isp24.fcp_cmnd.add_cdb[
- atio->u.isp24.fcp_cmnd.add_cdb_len]));
+ data_length = GET_DL_FR_ATIO(atio);
ret = ha->tgt.tgt_ops->handle_cmd(vha, cmd, cdb, data_length,
atio->u.isp24.fcp_cmnd.task_attr, data_dir, bidi);
@@ -4864,7 +4858,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
}
if (sess != NULL) {
- if (sess->fw_login_state == DSC_LS_PLOGI_PEND) {
+ if ((sess->fw_login_state != DSC_LS_PLOGI_PEND) &&
+ (sess->fw_login_state != DSC_LS_PLOGI_COMP)) {
/*
* Impatient initiator sent PRLI before last
* PLOGI could finish. Will force him to re-try,
@@ -4903,9 +4898,19 @@ 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) {
- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
- qla2xxx_wake_dpc(vha);
+ if (sess) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s %d %8phC post nack\n",
+ __func__, __LINE__, sess->port_name);
+
+ qla24xx_post_nack_work(vha, sess, iocb,
+ SRB_NACK_PRLI);
+ res = 0;
+ } else {
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ }
} else {
if (sess) {
ql_dbg(ql_dbg_disc, vha, 0xffff,
@@ -5825,7 +5830,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
unsigned long flags;
if (unlikely(tgt == NULL)) {
- ql_dbg(ql_dbg_io, vha, 0x3064,
+ ql_dbg(ql_dbg_tgt, vha, 0x3064,
"ATIO pkt, but no tgt (ha %p)", ha);
return;
}
@@ -6257,7 +6262,7 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
fcport->loop_id = loop_id;
- rc = qla2x00_get_port_database(vha, fcport, 0);
+ rc = qla24xx_gpdb_wait(vha, fcport, 0);
if (rc != QLA_SUCCESS) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf070,
"qla_target(%d): Failed to retrieve fcport "
@@ -6959,7 +6964,7 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
struct atio_from_isp *pkt;
int cnt, i;
- if (!vha->flags.online)
+ if (!ha->flags.fw_started)
return;
while (ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) {
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 507b8d9..b57067d 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -436,6 +436,11 @@ struct atio_from_isp {
} u;
} __packed;
+
+#define GET_DL_FR_ATIO(_atio) \
+ (be32_to_cpu(get_unaligned((uint32_t *) \
+&_atio->u.isp24.fcp_cmnd.add_cdb[_atio->u.isp24.fcp_cmnd.add_cdb_len*4])))
+
#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
/*
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 21/22] qla2xxx: Improve submission of non critical MB interface.
2016-12-06 20:30 ` [PATCH 21/22] qla2xxx: Improve submission of non critical MB interface Himanshu Madhani
@ 2016-12-07 12:16 ` Hannes Reinecke
0 siblings, 0 replies; 50+ messages in thread
From: Hannes Reinecke @ 2016-12-07 12:16 UTC (permalink / raw)
To: Himanshu Madhani, target-devel, nab; +Cc: giridhar.malavali, linux-scsi
On 12/06/2016 09:30 PM, Himanshu Madhani wrote:
> From: Quinn Tran <quinn.tran@cavium.com>
>
> Move Get ID list, stats and Get Port Databasae mailbox commands
> out of MB interface which is serialized to IOCB interface
> to reduce contention.
>
> Current driver wait for FW to be in the ready state
> before processing in coming commands. For loop mode,
> certain initiator takes longer for login to complete.
> While other initiators already sends commands.
>
> Add processing of Report ID Acquision F2. For Direct
> connect and target mode, Rida F2 provides the ALPA/Nport ID
> of the local adapter.
>
> Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
> ---
> drivers/scsi/qla2xxx/qla_def.h | 34 +++-
> drivers/scsi/qla2xxx/qla_dfs.c | 85 +++++++++-
> drivers/scsi/qla2xxx/qla_fw.h | 18 +++
> drivers/scsi/qla2xxx/qla_gbl.h | 12 +-
> drivers/scsi/qla2xxx/qla_init.c | 112 ++++++--------
> drivers/scsi/qla2xxx/qla_isr.c | 22 ++-
> drivers/scsi/qla2xxx/qla_mbx.c | 315 +++++++++++++++++++++++++++++++++++---
> drivers/scsi/qla2xxx/qla_os.c | 95 +++++++++---
> drivers/scsi/qla2xxx/qla_target.c | 53 ++++---
> drivers/scsi/qla2xxx/qla_target.h | 5 +
> 10 files changed, 607 insertions(+), 144 deletions(-)
>
[ .. ]
> @@ -200,6 +201,8 @@ extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
> void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
> uint16_t *);
> int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
> +void qla2x00_schedule_work(struct scsi_qla_host *);
> +
>
> /*
> * Global Functions in qla_mid.c source file.
Pointless newline.
[ .. ]
> @@ -796,11 +802,16 @@ static void qla_irq_affinity_notify(struct irq_affinity_notify *,
> "LOOP UP detected (%s Gbps).\n",
> qla2x00_get_link_speed_str(ha, ha->link_data_rate));
>
> +
> vha->flags.management_server_logged_in = 0;
> qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
> break;
>
Same here.
> @@ -5856,3 +5896,238 @@ struct cs84xx_mgmt_cmd {
>
> return rval;
> }
> +
> +void qla2x00_async_mb_sp_done(void *v, void *s, int res)
> +{
> + struct srb *sp = s;
> + sp->u.iocb_cmd.u.mbx.rc = res;
> + complete(&sp->u.iocb_cmd.u.mbx.comp);
> + /* don't free sp here. Let the caller do the free */
> +}
> +
> +/* This mailbox uses the iocb interface to send MB command.
> + * This allows non-critial (non chip setup) command to go out in parrallel.
> + */
> +int qla24xx_send_mb_cmd(struct scsi_qla_host *vha, mbx_cmd_t *mcp)
> +{
> + int rval = QLA_FUNCTION_FAILED;
> + srb_t *sp;
> + struct srb_iocb *c;
> + char *name;
> +
> + if (!vha->hw->flags.fw_started)
> + goto done;
> +
> + sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
> + if (!sp)
> + goto done;
> +
> +
And here.
[ .. ]
> + case QLA_FUNCTION_TIMEOUT:
> + ql_dbg(ql_dbg_mbx, vha, 0xffff,
> + "%s: %s Timeout. %x.\n",
> + __func__, name, rval);
> + break;
> + case QLA_SUCCESS:
> + ql_dbg(ql_dbg_mbx, vha, 0xffff,
> + "%s: %s done.\n",
> + __func__, sp->name);
> + sp->free(sp->vha, sp);
> + break;
> +
> + default:
> + ql_dbg(ql_dbg_mbx, vha, 0xffff,
> + "%s: %s Failed. %x.\n",
> + __func__,sp->name, rval);
> + sp->free(sp->vha, sp);
> + break;
> + }
> +
> + return rval;
> +
> +done_free_sp:
> + sp->free(sp->vha, sp);
> +done:
> + return rval;
> +
> +}
> +
> +
And here.
[ .. ]
> + memset(&mc, 0, sizeof(mc));
> + mc.mb[0] = MBC_GET_PORT_DATABASE;
> + mc.mb[1] = cpu_to_le16(fcport->loop_id);
> + mc.mb[2] = MSW(pd_dma);
> + mc.mb[3] = LSW(pd_dma);
> + mc.mb[6] = MSW(MSD(pd_dma));
> + mc.mb[7] = LSW(MSD(pd_dma));
> + mc.mb[9] = cpu_to_le16(vha->vp_idx);
> + mc.mb[10] = cpu_to_le16((uint16_t)opt);
> +
> +
And here.
> + rval = qla24xx_send_mb_cmd(vha, &mc);
> + if (rval != QLA_SUCCESS) {
> + ql_dbg(ql_dbg_mbx, vha, 0xffff,
> + "%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",
> + __func__, fcport->port_name);
> +
> +done_free_sp:
> + if (pd)
> + dma_pool_free(ha->s_dma_pool, pd, pd_dma);
> +
> +done:
> + return rval;
> +}
> +
> +
And here.
[ .. ]
> +void qla2x00_schedule_work(struct scsi_qla_host *vha)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&vha->work_lock, flags);
> + if (vha->flags.iocb_work_sheduled) {
> + spin_unlock_irqrestore(&vha->work_lock, flags);
> + return;
> + } else {
> + vha->flags.iocb_work_sheduled = 1;
> + }
> + spin_unlock_irqrestore(&vha->work_lock, flags);
> +
> +
And here.
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.com +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 22/22] qla2xxx: Add check for corrupt ATIO.
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (20 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 21/22] qla2xxx: Improve submission of non critical MB interface Himanshu Madhani
@ 2016-12-06 20:30 ` Himanshu Madhani
2016-12-07 12:25 ` Hannes Reinecke
2016-12-12 23:10 ` [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Madhani, Himanshu
22 siblings, 1 reply; 50+ messages in thread
From: Himanshu Madhani @ 2016-12-06 20:30 UTC (permalink / raw)
To: target-devel, nab; +Cc: giridhar.malavali, linux-scsi, himanshu.madhani
From: Quinn Tran <quinn.tran@cavium.com>
corrupt ATIO is defined as length of fcp_header & fcp_cmd
payload is less than 0x38. It's the minimum size for a frame to
carry 8..16 bytes SCSI CDB. The exchange will be drop or
terminated if corrupted
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
---
drivers/scsi/qla2xxx/qla_def.h | 3 ++-
drivers/scsi/qla2xxx/qla_target.c | 23 ++++++++++++++++++++---
drivers/scsi/qla2xxx/qla_target.h | 16 +++++++++++++++-
3 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index de058a1..e1e686f 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1600,7 +1600,8 @@ struct link_statistics {
struct atio {
uint8_t entry_type; /* Entry type. */
uint8_t entry_count; /* Entry count. */
- uint8_t data[58];
+ uint16_t attr_n_length;
+ uint8_t data[56];
uint32_t signature;
#define ATIO_PROCESSED 0xDEADDEAD /* Signature */
};
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 6f01c66..c7093c79 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -6967,12 +6967,29 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
if (!ha->flags.fw_started)
return;
- while (ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) {
+ while ((ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) ||
+ FCPCMD_IS_CORRUPTED(ha->tgt.atio_ring_ptr)) {
pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr;
cnt = pkt->u.raw.entry_count;
- qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt,
- ha_locked);
+ if (unlikely(FCPCMD_IS_CORRUPTED(ha->tgt.atio_ring_ptr))) {
+ /* This packet is corrupted. The header + payload
+ * can not be trusted. There is no point in passing
+ * it further up.
+ */
+ ql_log(ql_log_warn, vha, 0xffff,
+ "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);
+
+ ADJ_CORRUPTED_ATIO(pkt);
+ qlt_send_term_exchange(vha, NULL, pkt, ha_locked, 0);
+ } else
+ qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt,
+ ha_locked);
for (i = 0; i < cnt; i++) {
ha->tgt.atio_ring_index++;
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index b57067d..3aff551 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -429,7 +429,10 @@ struct atio_from_isp {
struct {
uint8_t entry_type; /* Entry type. */
uint8_t entry_count; /* Entry count. */
- uint8_t data[58];
+ uint16_t attr_n_length;
+#define FCP_CMD_LENTH_MASK 0x0fff
+#define FCP_CMD_LENTH_MIN 0x38
+ uint8_t data[56];
uint32_t signature;
#define ATIO_PROCESSED 0xDEADDEAD /* Signature */
} raw;
@@ -437,6 +440,17 @@ struct atio_from_isp {
} __packed;
+#define FCPCMD_IS_CORRUPTED(_a) \
+((_a->entry_type == ATIO_TYPE7) && \
+((le16_to_cpu(_a->attr_n_length) & FCP_CMD_LENTH_MASK) < FCP_CMD_LENTH_MIN))
+
+/* adjust corrupted atio so we won't trip over the same entry again. */
+#define ADJ_CORRUPTED_ATIO(_a) \
+{ \
+ _a->u.raw.attr_n_length = cpu_to_le16(FCP_CMD_LENTH_MIN); \
+ ((struct atio_from_isp *)_a)->u.isp24.fcp_cmnd.add_cdb_len = 0; \
+}
+
#define GET_DL_FR_ATIO(_atio) \
(be32_to_cpu(get_unaligned((uint32_t *) \
&_atio->u.isp24.fcp_cmnd.add_cdb[_atio->u.isp24.fcp_cmnd.add_cdb_len*4])))
--
1.8.3.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 22/22] qla2xxx: Add check for corrupt ATIO.
2016-12-06 20:30 ` [PATCH 22/22] qla2xxx: Add check for corrupt ATIO Himanshu Madhani
@ 2016-12-07 12:25 ` Hannes Reinecke
0 siblings, 0 replies; 50+ messages in thread
From: Hannes Reinecke @ 2016-12-07 12:25 UTC (permalink / raw)
To: Himanshu Madhani, target-devel, nab; +Cc: giridhar.malavali, linux-scsi
On 12/06/2016 09:30 PM, Himanshu Madhani wrote:
> From: Quinn Tran <quinn.tran@cavium.com>
>
> corrupt ATIO is defined as length of fcp_header & fcp_cmd
> payload is less than 0x38. It's the minimum size for a frame to
> carry 8..16 bytes SCSI CDB. The exchange will be drop or
> terminated if corrupted
>
> Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
> ---
> drivers/scsi/qla2xxx/qla_def.h | 3 ++-
> drivers/scsi/qla2xxx/qla_target.c | 23 ++++++++++++++++++++---
> drivers/scsi/qla2xxx/qla_target.h | 16 +++++++++++++++-
> 3 files changed, 37 insertions(+), 5 deletions(-)
>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.com +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 00/22] qla2xxx: Target code enhancemets and feature update
2016-12-06 20:30 [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Himanshu Madhani
` (21 preceding siblings ...)
2016-12-06 20:30 ` [PATCH 22/22] qla2xxx: Add check for corrupt ATIO Himanshu Madhani
@ 2016-12-12 23:10 ` Madhani, Himanshu
2016-12-14 20:24 ` Madhani, Himanshu
22 siblings, 1 reply; 50+ messages in thread
From: Madhani, Himanshu @ 2016-12-12 23:10 UTC (permalink / raw)
To: target-devel@vger.kernel.org, nab@linux-iscsi.org
Cc: Malavali, Giridhar, linux-scsi@vger.kernel.org
Hi Nic,
On 12/6/16, 12:30 PM, "Himanshu Madhani" <himanshu.madhani@cavium.com> wrote:
>Hi Nic,
>
>Please consider this series for target-pending. This series is based on
>scsi-misc series that was submitted earlier today.
>
>Here's link for that series
> http://marc.info/?l=linux-scsi&m=148105128210090&w=2
>
>This series contains following changes
>
>o Clean up Target code and tcm_qla2xxx for cleaner interaction.
>o Enhanced and strengthen support for T10-DIF/PI.
>o Renamed qlini_mode to qlop_mode for better readbility.
>o Improve driver capability to manage dual personality
> (i.e. Initiator and Target) simultaneously.
>o Added capability to send non-critical MBX via IOCB path.
>o Some of the pending bug-fixes for target code.
>
>Thanks,
>Himanshu
>
>Himanshu Madhani (3):
> qla2xxx: Include ATIO queue in firmware dump when in target mode
> qla2xxx: Set tcm_qla2xxx version to automatically track qla2xxx
> version.
> qla2xxx: Clear BIT 15 in NVRAM during initialization.
>
>Joe Carnuccio (1):
> qla2xxx: Rerfactor use of sp context
>
>Quinn Tran (18):
> qla2xxx: Fix wrong IOCB type assumption.
> qla2xxx: Add DebugFS node of irq vector cpuid
> qla2xxx: Collect addtional debug data for FW
> qla2xxx: Fix crash due to null pointer access.
> qla2xxx: Refactore target code to remove symbol dependency
> qla2xxx: Refactor T10-DIF PI support
> qla2xxx: Add framework for Async fabric discovery.
> qla2xxx: Refactor session management code.
> qla2xxx: Add Dual mode support in the driver
> qla2xxx: Fix invalid handle erroneous message.
> qla2xxx: Add interrupt polling mechanism
> qla2xxx: Rename qlini_mode parameter
> qla2xxx: Improve RSCN handling in driver
> qla2xxx: Fix slow mem alloc behind lock
> qla2xxx: Reduce exess wait during chip reset
> qla2xxx: Allow relogin to go through if remote login did not finish
> qla2xxx: Improve submission of non critical MB interface.
> qla2xxx: Add check for corrupt ATIO.
>
> drivers/scsi/qla2xxx/qla_attr.c | 366 ++++-
> drivers/scsi/qla2xxx/qla_bsg.c | 21 +-
> drivers/scsi/qla2xxx/qla_dbg.c | 2 +-
> drivers/scsi/qla2xxx/qla_dbg.h | 1 +
> drivers/scsi/qla2xxx/qla_def.h | 287 +++-
> drivers/scsi/qla2xxx/qla_dfs.c | 237 ++-
> drivers/scsi/qla2xxx/qla_fw.h | 107 +-
> drivers/scsi/qla2xxx/qla_gbl.h | 86 +-
> drivers/scsi/qla2xxx/qla_gs.c | 733 ++++++++-
> drivers/scsi/qla2xxx/qla_init.c | 1604 +++++++++++++++-----
> drivers/scsi/qla2xxx/qla_inline.h | 34 +-
> drivers/scsi/qla2xxx/qla_iocb.c | 172 ++-
> drivers/scsi/qla2xxx/qla_isr.c | 414 ++++--
> drivers/scsi/qla2xxx/qla_mbx.c | 553 +++++--
> drivers/scsi/qla2xxx/qla_mid.c | 15 +-
> drivers/scsi/qla2xxx/qla_mr.c | 52 +-
> drivers/scsi/qla2xxx/qla_os.c | 454 ++++--
> drivers/scsi/qla2xxx/qla_target.c | 2890 +++++++++++++++++++++---------------
> drivers/scsi/qla2xxx/qla_target.h | 257 ++--
> drivers/scsi/qla2xxx/qla_tmpl.c | 24 +
> drivers/scsi/qla2xxx/tcm_qla2xxx.c | 753 ++++++++--
> drivers/scsi/qla2xxx/tcm_qla2xxx.h | 16 +-
> 22 files changed, 6658 insertions(+), 2420 deletions(-)
>
>--
>1.8.3.1
>
Would you please review/comment on these patches.
Thanks,
Himanshu
>
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 00/22] qla2xxx: Target code enhancemets and feature update
2016-12-12 23:10 ` [PATCH 00/22] qla2xxx: Target code enhancemets and feature update Madhani, Himanshu
@ 2016-12-14 20:24 ` Madhani, Himanshu
2016-12-14 21:19 ` Christoph Hellwig
0 siblings, 1 reply; 50+ messages in thread
From: Madhani, Himanshu @ 2016-12-14 20:24 UTC (permalink / raw)
To: target-devel@vger.kernel.org, nab@linux-iscsi.org,
Bart Van Assche
Cc: Malavali, Giridhar, linux-scsi@vger.kernel.org
Hi Bart,
On 12/12/16, 3:10 PM, "Madhani, Himanshu" <Himanshu.Madhani@cavium.com> wrote:
>Hi Nic,
>
>
>
>On 12/6/16, 12:30 PM, "Himanshu Madhani" <himanshu.madhani@cavium.com> wrote:
>
>>Hi Nic,
>>
>>Please consider this series for target-pending. This series is based on
>>scsi-misc series that was submitted earlier today.
>>
>>Here's link for that series
>> http://marc.info/?l=linux-scsi&m=148105128210090&w=2
>>
>>This series contains following changes
>>
>>o Clean up Target code and tcm_qla2xxx for cleaner interaction.
>>o Enhanced and strengthen support for T10-DIF/PI.
>>o Renamed qlini_mode to qlop_mode for better readbility.
>>o Improve driver capability to manage dual personality
>> (i.e. Initiator and Target) simultaneously.
>>o Added capability to send non-critical MBX via IOCB path.
>>o Some of the pending bug-fixes for target code.
>>
>>Thanks,
>>Himanshu
>>
>>Himanshu Madhani (3):
>> qla2xxx: Include ATIO queue in firmware dump when in target mode
>> qla2xxx: Set tcm_qla2xxx version to automatically track qla2xxx
>> version.
>> qla2xxx: Clear BIT 15 in NVRAM during initialization.
>>
>>Joe Carnuccio (1):
>> qla2xxx: Rerfactor use of sp context
>>
>>Quinn Tran (18):
>> qla2xxx: Fix wrong IOCB type assumption.
>> qla2xxx: Add DebugFS node of irq vector cpuid
>> qla2xxx: Collect addtional debug data for FW
>> qla2xxx: Fix crash due to null pointer access.
>> qla2xxx: Refactore target code to remove symbol dependency
>> qla2xxx: Refactor T10-DIF PI support
>> qla2xxx: Add framework for Async fabric discovery.
>> qla2xxx: Refactor session management code.
>> qla2xxx: Add Dual mode support in the driver
>> qla2xxx: Fix invalid handle erroneous message.
>> qla2xxx: Add interrupt polling mechanism
>> qla2xxx: Rename qlini_mode parameter
>> qla2xxx: Improve RSCN handling in driver
>> qla2xxx: Fix slow mem alloc behind lock
>> qla2xxx: Reduce exess wait during chip reset
>> qla2xxx: Allow relogin to go through if remote login did not finish
>> qla2xxx: Improve submission of non critical MB interface.
>> qla2xxx: Add check for corrupt ATIO.
>>
>> drivers/scsi/qla2xxx/qla_attr.c | 366 ++++-
>> drivers/scsi/qla2xxx/qla_bsg.c | 21 +-
>> drivers/scsi/qla2xxx/qla_dbg.c | 2 +-
>> drivers/scsi/qla2xxx/qla_dbg.h | 1 +
>> drivers/scsi/qla2xxx/qla_def.h | 287 +++-
>> drivers/scsi/qla2xxx/qla_dfs.c | 237 ++-
>> drivers/scsi/qla2xxx/qla_fw.h | 107 +-
>> drivers/scsi/qla2xxx/qla_gbl.h | 86 +-
>> drivers/scsi/qla2xxx/qla_gs.c | 733 ++++++++-
>> drivers/scsi/qla2xxx/qla_init.c | 1604 +++++++++++++++-----
>> drivers/scsi/qla2xxx/qla_inline.h | 34 +-
>> drivers/scsi/qla2xxx/qla_iocb.c | 172 ++-
>> drivers/scsi/qla2xxx/qla_isr.c | 414 ++++--
>> drivers/scsi/qla2xxx/qla_mbx.c | 553 +++++--
>> drivers/scsi/qla2xxx/qla_mid.c | 15 +-
>> drivers/scsi/qla2xxx/qla_mr.c | 52 +-
>> drivers/scsi/qla2xxx/qla_os.c | 454 ++++--
>> drivers/scsi/qla2xxx/qla_target.c | 2890 +++++++++++++++++++++---------------
>> drivers/scsi/qla2xxx/qla_target.h | 257 ++--
>> drivers/scsi/qla2xxx/qla_tmpl.c | 24 +
>> drivers/scsi/qla2xxx/tcm_qla2xxx.c | 753 ++++++++--
>> drivers/scsi/qla2xxx/tcm_qla2xxx.h | 16 +-
>> 22 files changed, 6658 insertions(+), 2420 deletions(-)
>>
>>--
>>1.8.3.1
>>
>
>Would you please review/comment on these patches.
>
>Thanks,
>Himanshu
>>
Can we get some review comments so that I can address them before sending updated series.
Thanks,
- Himanshu
>
^ permalink raw reply [flat|nested] 50+ messages in thread