Merge branch 'net.b0' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/bird
[powerpc.git] / drivers / s390 / scsi / zfcp_erp.c
index 376cb0f..da947e6 100644 (file)
@@ -31,8 +31,6 @@
 
 #define ZFCP_LOG_AREA                  ZFCP_LOG_AREA_ERP
 
-#define ZFCP_ERP_REVISION "$Revision: 1.86 $"
-
 #include "zfcp_ext.h"
 
 static int zfcp_erp_adisc(struct zfcp_port *);
@@ -82,6 +80,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *);
+static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open_fsf_statusread(
        struct zfcp_erp_action *);
 
@@ -345,13 +344,13 @@ zfcp_erp_adisc(struct zfcp_port *port)
 
        /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports
           without FC-AL-2 capability, so we don't set it */
-       adisc->wwpn = adapter->wwpn;
-       adisc->wwnn = adapter->wwnn;
-       adisc->nport_id = adapter->s_id;
+       adisc->wwpn = fc_host_port_name(adapter->scsi_host);
+       adisc->wwnn = fc_host_node_name(adapter->scsi_host);
+       adisc->nport_id = fc_host_port_id(adapter->scsi_host);
        ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
                      "(wwpn=0x%016Lx, wwnn=0x%016Lx, "
                      "hard_nport_id=0x%08x, nport_id=0x%08x)\n",
-                     adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn,
+                     adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn,
                      (wwn_t) adisc->wwnn, adisc->hard_nport_id,
                      adisc->nport_id);
 
@@ -404,7 +403,7 @@ zfcp_erp_adisc_handler(unsigned long data)
        struct zfcp_send_els *send_els;
        struct zfcp_port *port;
        struct zfcp_adapter *adapter;
-       fc_id_t d_id;
+       u32 d_id;
        struct zfcp_ls_adisc_acc *adisc;
 
        send_els = (struct zfcp_send_els *) data;
@@ -435,9 +434,9 @@ zfcp_erp_adisc_handler(unsigned long data)
        ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "
                      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
                      "hard_nport_id=0x%08x, nport_id=0x%08x)\n",
-                     d_id, adapter->s_id, (wwn_t) adisc->wwpn,
-                     (wwn_t) adisc->wwnn, adisc->hard_nport_id,
-                     adisc->nport_id);
+                     d_id, fc_host_port_id(adapter->scsi_host),
+                     (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn,
+                     adisc->hard_nport_id, adisc->nport_id);
 
        /* set wwnn for port */
        if (port->wwnn == 0)
@@ -1070,11 +1069,6 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
 
        atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
 
-       rwlock_init(&adapter->erp_lock);
-       INIT_LIST_HEAD(&adapter->erp_ready_head);
-       INIT_LIST_HEAD(&adapter->erp_running_head);
-       sema_init(&adapter->erp_ready_sem, 0);
-
        retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);
        if (retval < 0) {
                ZFCP_LOG_NORMAL("error: creation of erp thread failed for "
@@ -2247,27 +2241,29 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
        return retval;
 }
 
-/*
- * function:    zfcp_fsf_init
- *
- * purpose:    initializes FSF operation for the specified adapter
- *
- * returns:    0 - succesful initialization of FSF operation
- *             !0 - failed to initialize FSF operation
- */
 static int
 zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
 {
        int retval;
 
-       /* do 'exchange configuration data' */
+       if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+                             &erp_action->adapter->status)) &&
+           (erp_action->adapter->adapter_features &
+            FSF_FEATURE_HBAAPI_MANAGEMENT)) {
+               zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
+               atomic_set(&erp_action->adapter->erp_counter, 0);
+               return ZFCP_ERP_FAILED;
+       }
+
        retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
        if (retval == ZFCP_ERP_FAILED)
-               return retval;
+               return ZFCP_ERP_FAILED;
 
-       /* start the desired number of Status Reads */
-       retval = zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
-       return retval;
+       retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
+       if (retval == ZFCP_ERP_FAILED)
+               return ZFCP_ERP_FAILED;
+
+       return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
 }
 
 /*
@@ -2350,6 +2346,54 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
        return retval;
 }
 
+static int
+zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
+{
+       int ret;
+       int retries;
+       int sleep;
+       struct zfcp_adapter *adapter = erp_action->adapter;
+
+       atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
+
+       retries = 0;
+       do {
+               write_lock(&adapter->erp_lock);
+               zfcp_erp_action_to_running(erp_action);
+               write_unlock(&adapter->erp_lock);
+               zfcp_erp_timeout_init(erp_action);
+               ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
+               if (ret == -EOPNOTSUPP) {
+                       debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
+                       return ZFCP_ERP_SUCCEEDED;
+               } else if (ret) {
+                       debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
+                       return ZFCP_ERP_FAILED;
+               }
+               debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
+
+               down(&adapter->erp_ready_sem);
+               if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+                       ZFCP_LOG_INFO("error: exchange of port data "
+                                     "for adapter %s timed out\n",
+                                     zfcp_get_busid_by_adapter(adapter));
+                       break;
+               }
+               if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+                                     &adapter->status))
+                       break;
+
+               if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) {
+                       sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP;
+                       retries++;
+               } else
+                       sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
+               schedule_timeout(sleep);
+       } while (1);
+
+       return ZFCP_ERP_SUCCEEDED;
+}
+
 /*
  * function:   
  *
@@ -2567,7 +2611,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
        case ZFCP_ERP_STEP_UNINITIALIZED:
        case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
        case ZFCP_ERP_STEP_PORT_CLOSING:
-               if (adapter->fc_topology == FSF_TOPO_P2P) {
+               if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) {
                        if (port->wwpn != adapter->peer_wwpn) {
                                ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx "
                                                "on adapter %s.\nPeer WWPN "
@@ -3357,7 +3401,7 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
 /**
  * zfcp_erp_action_cleanup
  *
- * Register unit with scsi stack if appropiate and fix reference counts.
+ * Register unit with scsi stack if appropriate and fix reference counts.
  * Note: Temporary units are not registered with scsi stack.
  */
 static void
@@ -3599,6 +3643,9 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
        struct zfcp_port *port;
        unsigned long flags;
 
+       if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+               return;
+
        debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
        debug_event(adapter->erp_dbf, 3, &adapter->name, 8);