[SCSI] zfcp: Only issue one test link command per port
authorChristof Schmitt <christof.schmitt@de.ibm.com>
Tue, 18 Aug 2009 13:43:11 +0000 (15:43 +0200)
committerJames Bottomley <James.Bottomley@suse.de>
Sat, 5 Sep 2009 13:49:13 +0000 (08:49 -0500)
When the FCP channel returns a series of commands with the error
status "test link", zfcp will send a series of ELS ADISC commands.
This is technically no problem, but it is enough to only issue one
test command per remote port. So, track whether a ELS ADISC command is
already pending, and do not send a new one if there is already a
pending command.

Reviewed-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_fc.c

index 601f5a575defa37d3f467f60f2b6ee8b32e506cc..c1becfc1e7fe9bd4b3c057e5a3980c2c9df1d567 100644 (file)
@@ -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 {
index 47daebfa7e59af2f7b17e91184182199ed7bb26f..94c13bd32b5fbeb1db3c6bba835cbbfe8a6c5f4b 100644 (file)
@@ -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);
 }