[SCSI] zfcp: fix adapter initialization
Andreas Herrmann [Thu, 1 Dec 2005 01:50:36 +0000 (02:50 +0100)]
Fixed various problems in opening sequence of adapters which was previously
changed with NPIV support:
o corrected handling when exchange port data function is not supported,
  otherwise adapters on z900 cannot be opened anymore
o corrected setup of timer for exchange port data if called from error
  recovery
o corrected check of return code of exchange config data

Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_fsf.c

index 8d503d9..ee7314d 100644 (file)
@@ -2243,29 +2243,26 @@ 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 xconfig, xport;
+       int retval;
 
-       if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
-                            &erp_action->adapter->status)) {
+       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;
        }
 
-       xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
-       xport   = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
-       if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED))
+       retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
+       if (retval == ZFCP_ERP_FAILED)
+               return ZFCP_ERP_FAILED;
+
+       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);
@@ -2354,41 +2351,29 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
 static int
 zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
 {
-       int retval = ZFCP_ERP_SUCCEEDED;
+       int ret;
        int retries;
        int sleep;
        struct zfcp_adapter *adapter = erp_action->adapter;
 
        atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
 
-       for (retries = 0; ; retries++) {
-               ZFCP_LOG_DEBUG("Doing exchange port data\n");
+       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);
-               if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) {
-                       retval = ZFCP_ERP_FAILED;
-                       debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
-                       ZFCP_LOG_INFO("error: initiation of exchange of "
-                                     "port data failed for adapter %s\n",
-                                     zfcp_get_busid_by_adapter(adapter));
-                       break;
+               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_fstx_xok");
-               ZFCP_LOG_DEBUG("Xchange underway\n");
+               debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
 
-               /*
-                * Why this works:
-                * Both the normal completion handler as well as the timeout
-                * handler will do an 'up' when the 'exchange port data'
-                * request completes or times out. Thus, the signal to go on
-                * won't be lost utilizing this semaphore.
-                * Furthermore, this 'adapter_reopen' action is
-                * guaranteed to be the only action being there (highest action
-                * which prevents other actions from being created).
-                * Resulting from that, the wake signal recognized here
-                * _must_ be the one belonging to the 'exchange port
-                * data' request.
-                */
                down(&adapter->erp_ready_sem);
                if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
                        ZFCP_LOG_INFO("error: exchange of port data "
@@ -2396,29 +2381,19 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
                                      zfcp_get_busid_by_adapter(adapter));
                        break;
                }
-
                if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
                                      &adapter->status))
                        break;
 
-               ZFCP_LOG_DEBUG("host connection still initialising... "
-                              "waiting and retrying...\n");
-               /* sleep a little bit before retry */
-               sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ?
-                               ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP :
-                               ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
-               msleep(jiffies_to_msecs(sleep));
-       }
-
-       if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
-                            &adapter->status)) {
-               ZFCP_LOG_INFO("error: exchange of port data for "
-                             "adapter %s failed\n",
-                             zfcp_get_busid_by_adapter(adapter));
-               retval = ZFCP_ERP_FAILED;
-       }
+               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 retval;
+       return ZFCP_ERP_SUCCEEDED;
 }
 
 /*
index 3b0fc11..fbc81b0 100644 (file)
@@ -2191,13 +2191,10 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
                 return -EOPNOTSUPP;
         }
 
-       timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
-       if (!timer)
-               return -ENOMEM;
-
        /* setup new FSF request */
        retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
-                                     0, 0, &lock_flags, &fsf_req);
+                                    erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0,
+                                    0, &lock_flags, &fsf_req);
        if (retval < 0) {
                ZFCP_LOG_INFO("error: Out of resources. Could not create an "
                               "exchange port data request for"
@@ -2205,25 +2202,33 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
                              zfcp_get_busid_by_adapter(adapter));
                write_unlock_irqrestore(&adapter->request_queue.queue_lock,
                                        lock_flags);
-               goto out;
-       }
-
-       if (erp_action) {
-               erp_action->fsf_req = fsf_req;
-               fsf_req->erp_action = erp_action;
+               return retval;
        }
 
        if (data)
-       fsf_req->data = (unsigned long) data;
+               fsf_req->data = (unsigned long) data;
 
        sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
         sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
         sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
-       init_timer(timer);
-       timer->function = zfcp_fsf_request_timeout_handler;
-       timer->data = (unsigned long) adapter;
-       timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
+       if (erp_action) {
+               erp_action->fsf_req = fsf_req;
+               fsf_req->erp_action = erp_action;
+               timer = &erp_action->timer;
+       } else {
+               timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC);
+               if (!timer) {
+                       write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+                                               lock_flags);
+                       zfcp_fsf_req_free(fsf_req);
+                       return -ENOMEM;
+               }
+               init_timer(timer);
+               timer->function = zfcp_fsf_request_timeout_handler;
+               timer->data = (unsigned long) adapter;
+               timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
+       }
 
        retval = zfcp_fsf_req_send(fsf_req, timer);
        if (retval) {
@@ -2233,23 +2238,22 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
                zfcp_fsf_req_free(fsf_req);
                if (erp_action)
                        erp_action->fsf_req = NULL;
+               else
+                       kfree(timer);
                write_unlock_irqrestore(&adapter->request_queue.queue_lock,
                                        lock_flags);
-               goto out;
+               return retval;
        }
 
-       ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n",
-                      zfcp_get_busid_by_adapter(adapter));
-
-       write_unlock_irqrestore(&adapter->request_queue.queue_lock,
-                               lock_flags);
+       write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
 
-       wait_event(fsf_req->completion_wq,
-                  fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
-       del_timer_sync(timer);
-       zfcp_fsf_req_free(fsf_req);
- out:
-       kfree(timer);
+       if (!erp_action) {
+               wait_event(fsf_req->completion_wq,
+                          fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+               del_timer_sync(timer);
+               zfcp_fsf_req_free(fsf_req);
+               kfree(timer);
+       }
        return retval;
 }