aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/scsi/zfcp_def.h1
-rw-r--r--drivers/s390/scsi/zfcp_fc.c9
2 files changed, 10 insertions, 0 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 601f5a575de..c1becfc1e7f 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -232,6 +232,7 @@ struct zfcp_ls_adisc {
/* remote port status */
#define ZFCP_STATUS_PORT_PHYS_OPEN 0x00000001
+#define ZFCP_STATUS_PORT_LINK_TEST 0x00000002
/* well known address (WKA) port status*/
enum zfcp_wka_status {
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 47daebfa7e5..94c13bd32b5 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -404,6 +404,7 @@ static void zfcp_fc_adisc_handler(unsigned long data)
/* port is good, unblock rport without going through erp */
zfcp_scsi_schedule_rport_register(port);
out:
+ atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
zfcp_port_put(port);
kfree(adisc);
}
@@ -450,13 +451,21 @@ void zfcp_fc_link_test_work(struct work_struct *work)
port->rport_task = RPORT_DEL;
zfcp_scsi_rport_work(&port->rport_work);
+ /* only issue one test command at one time per port */
+ if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST)
+ goto out;
+
+ atomic_set_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
+
retval = zfcp_fc_adisc(port);
if (retval == 0)
return;
/* send of ADISC was not possible */
+ atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL);
+out:
zfcp_port_put(port);
}