Michal Suchanek 6dd4a1
From d5b45dd5ba6c944b17118530843e67bf9c096e49 Mon Sep 17 00:00:00 2001
Michal Suchanek 6dd4a1
From: Brian King <brking@linux.vnet.ibm.com>
Michal Suchanek 6dd4a1
Date: Tue, 11 May 2021 13:12:18 -0500
Michal Suchanek 6dd4a1
Subject: [PATCH] scsi: ibmvfc: Handle move login failure
Michal Suchanek 6dd4a1
Michal Suchanek 6dd4a1
References: bsc#1185938 ltc#192043
Michal Suchanek 6dd4a1
Patch-mainline: queued
Michal Suchanek 6dd4a1
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
Michal Suchanek 6dd4a1
Git-commit: d5b45dd5ba6c944b17118530843e67bf9c096e49
Michal Suchanek 6dd4a1
Michal Suchanek 6dd4a1
When service is being performed on an SVC with NPIV enabled, the WWPN of
Michal Suchanek 6dd4a1
the canister / node being serviced fails over to the another canister /
Michal Suchanek 6dd4a1
node. This looks to the ibmvfc driver as a WWPN moving from one SCSI ID to
Michal Suchanek 6dd4a1
another. The driver will first attempt to do an implicit logout of the old
Michal Suchanek 6dd4a1
SCSI ID. If this works, we simply delete the rport at the old location and
Michal Suchanek 6dd4a1
add an rport at the new location and the FC transport class handles
Michal Suchanek 6dd4a1
everything. However, if there is I/O outstanding, this implicit logout will
Michal Suchanek 6dd4a1
fail, in which case we will send a "move login" request to the VIOS. This
Michal Suchanek 6dd4a1
will cancel any outstanding I/O to that port, logout the port, and PLOGI
Michal Suchanek 6dd4a1
the new port. Recently we've encountered a scenario where the move login
Michal Suchanek 6dd4a1
fails. This was resulting in an attempted plogi to the new scsi id, without
Michal Suchanek 6dd4a1
the old scsi id getting logged out, which is a VIOS protocol violation. To
Michal Suchanek 6dd4a1
solve this, we want to keep tracking the old scsi id as the current scsi
Michal Suchanek 6dd4a1
id. That way, once terminate_rport_io cancels the outstanding i/o, it will
Michal Suchanek 6dd4a1
send us back through to do an implicit logout of the old scsi id, rather
Michal Suchanek 6dd4a1
than the new scsi id, and then we can plogi the new scsi id.
Michal Suchanek 6dd4a1
Michal Suchanek 6dd4a1
Link: https://lore.kernel.org/r/1620756740-7045-2-git-send-email-brking@linux.vnet.ibm.com
Michal Suchanek 6dd4a1
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Michal Suchanek 6dd4a1
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Michal Suchanek 6dd4a1
Acked-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek 6dd4a1
---
Michal Suchanek 6dd4a1
 drivers/scsi/ibmvscsi/ibmvfc.c | 16 ++++++++--------
Michal Suchanek 6dd4a1
 drivers/scsi/ibmvscsi/ibmvfc.h |  2 +-
Michal Suchanek 6dd4a1
 2 files changed, 9 insertions(+), 9 deletions(-)
Michal Suchanek 6dd4a1
Michal Suchanek 6dd4a1
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
Michal Suchanek 6dd4a1
index 6540d48eb0e8..4ac5bff69305 100644
Michal Suchanek 6dd4a1
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
Michal Suchanek 6dd4a1
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
Michal Suchanek 6dd4a1
@@ -4299,9 +4299,10 @@ static void ibmvfc_tgt_move_login_done(struct ibmvfc_event *evt)
Michal Suchanek 6dd4a1
 	ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
Michal Suchanek 6dd4a1
 	switch (status) {
Michal Suchanek 6dd4a1
 	case IBMVFC_MAD_SUCCESS:
Michal Suchanek 6dd4a1
-		tgt_dbg(tgt, "Move Login succeeded for old scsi_id: %llX\n", tgt->old_scsi_id);
Michal Suchanek 6dd4a1
+		tgt_dbg(tgt, "Move Login succeeded for new scsi_id: %llX\n", tgt->new_scsi_id);
Michal Suchanek 6dd4a1
 		tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name);
Michal Suchanek 6dd4a1
 		tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name);
Michal Suchanek 6dd4a1
+		tgt->scsi_id = tgt->new_scsi_id;
Michal Suchanek 6dd4a1
 		tgt->ids.port_id = tgt->scsi_id;
Michal Suchanek 6dd4a1
 		memcpy(&tgt->service_parms, &rsp->service_parms,
Michal Suchanek 6dd4a1
 		       sizeof(tgt->service_parms));
Michal Suchanek 6dd4a1
@@ -4319,8 +4320,8 @@ static void ibmvfc_tgt_move_login_done(struct ibmvfc_event *evt)
Michal Suchanek 6dd4a1
 		level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_move_login);
Michal Suchanek 6dd4a1
 
Michal Suchanek 6dd4a1
 		tgt_log(tgt, level,
Michal Suchanek 6dd4a1
-			"Move Login failed: old scsi_id: %llX, flags:%x, vios_flags:%x, rc=0x%02X\n",
Michal Suchanek 6dd4a1
-			tgt->old_scsi_id, be32_to_cpu(rsp->flags), be16_to_cpu(rsp->vios_flags),
Michal Suchanek 6dd4a1
+			"Move Login failed: new scsi_id: %llX, flags:%x, vios_flags:%x, rc=0x%02X\n",
Michal Suchanek 6dd4a1
+			tgt->new_scsi_id, be32_to_cpu(rsp->flags), be16_to_cpu(rsp->vios_flags),
Michal Suchanek 6dd4a1
 			status);
Michal Suchanek 6dd4a1
 		break;
Michal Suchanek 6dd4a1
 	}
Michal Suchanek 6dd4a1
@@ -4357,8 +4358,8 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target *tgt)
Michal Suchanek 6dd4a1
 	move->common.opcode = cpu_to_be32(IBMVFC_MOVE_LOGIN);
Michal Suchanek 6dd4a1
 	move->common.length = cpu_to_be16(sizeof(*move));
Michal Suchanek 6dd4a1
 
Michal Suchanek 6dd4a1
-	move->old_scsi_id = cpu_to_be64(tgt->old_scsi_id);
Michal Suchanek 6dd4a1
-	move->new_scsi_id = cpu_to_be64(tgt->scsi_id);
Michal Suchanek 6dd4a1
+	move->old_scsi_id = cpu_to_be64(tgt->scsi_id);
Michal Suchanek 6dd4a1
+	move->new_scsi_id = cpu_to_be64(tgt->new_scsi_id);
Michal Suchanek 6dd4a1
 	move->wwpn = cpu_to_be64(tgt->wwpn);
Michal Suchanek 6dd4a1
 	move->node_name = cpu_to_be64(tgt->ids.node_name);
Michal Suchanek 6dd4a1
 
Michal Suchanek 6dd4a1
@@ -4367,7 +4368,7 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target *tgt)
Michal Suchanek 6dd4a1
 		ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
Michal Suchanek 6dd4a1
 		kref_put(&tgt->kref, ibmvfc_release_tgt);
Michal Suchanek 6dd4a1
 	} else
Michal Suchanek 6dd4a1
-		tgt_dbg(tgt, "Sent Move Login for old scsi_id: %llX\n", tgt->old_scsi_id);
Michal Suchanek 6dd4a1
+		tgt_dbg(tgt, "Sent Move Login for new scsi_id: %llX\n", tgt->new_scsi_id);
Michal Suchanek 6dd4a1
 }
Michal Suchanek 6dd4a1
 
Michal Suchanek 6dd4a1
 /**
Michal Suchanek 6dd4a1
@@ -4737,8 +4738,7 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost,
Michal Suchanek 6dd4a1
 			 * normal ibmvfc_set_tgt_action to set this, as we
Michal Suchanek 6dd4a1
 			 * don't normally want to allow this state change.
Michal Suchanek 6dd4a1
 			 */
Michal Suchanek 6dd4a1
-			wtgt->old_scsi_id = wtgt->scsi_id;
Michal Suchanek 6dd4a1
-			wtgt->scsi_id = scsi_id;
Michal Suchanek 6dd4a1
+			wtgt->new_scsi_id = scsi_id;
Michal Suchanek 6dd4a1
 			wtgt->action = IBMVFC_TGT_ACTION_INIT;
Michal Suchanek 6dd4a1
 			ibmvfc_init_tgt(wtgt, ibmvfc_tgt_move_login);
Michal Suchanek 6dd4a1
 			goto unlock_out;
Michal Suchanek 6dd4a1
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
Michal Suchanek 6dd4a1
index 19dcec3ae9ba..4601bd21372d 100644
Michal Suchanek 6dd4a1
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
Michal Suchanek 6dd4a1
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
Michal Suchanek 6dd4a1
@@ -718,7 +718,7 @@ struct ibmvfc_target {
Michal Suchanek 6dd4a1
 	struct ibmvfc_host *vhost;
Michal Suchanek 6dd4a1
 	u64 scsi_id;
Michal Suchanek 6dd4a1
 	u64 wwpn;
Michal Suchanek 6dd4a1
-	u64 old_scsi_id;
Michal Suchanek 6dd4a1
+	u64 new_scsi_id;
Michal Suchanek 6dd4a1
 	struct fc_rport *rport;
Michal Suchanek 6dd4a1
 	int target_id;
Michal Suchanek 6dd4a1
 	enum ibmvfc_target_action action;
Michal Suchanek 6dd4a1
-- 
Michal Suchanek 6dd4a1
2.26.2
Michal Suchanek 6dd4a1