]> err.no Git - linux-2.6/blobdiff - drivers/s390/scsi/zfcp_erp.c
[SCSI] zfcp: avoid if (whatever) ; constructs.
[linux-2.6] / drivers / s390 / scsi / zfcp_erp.c
index 7f60b6fdf7248676990d07ea3cc6df3f8a095e35..40fa056e2575abcaae08cc25bbc343437d150360 100644 (file)
@@ -64,8 +64,6 @@ static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int);
 static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int);
 static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *);
-static void zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *);
-static void zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *);
 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 *);
@@ -93,6 +91,7 @@ static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *);
 static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *);
 static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *);
 
+static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *);
 static void zfcp_erp_action_dismiss_port(struct zfcp_port *);
 static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *);
 static void zfcp_erp_action_dismiss(struct zfcp_erp_action *);
@@ -111,62 +110,84 @@ static inline void zfcp_erp_action_to_ready(struct zfcp_erp_action *);
 static inline void zfcp_erp_action_to_running(struct zfcp_erp_action *);
 
 static void zfcp_erp_memwait_handler(unsigned long);
-static void zfcp_erp_timeout_handler(unsigned long);
-static inline void zfcp_erp_timeout_init(struct zfcp_erp_action *);
 
 /**
- * zfcp_fsf_request_timeout_handler - called if a request timed out
- * @data: pointer to adapter for handler function
- *
- * This function needs to be called if requests (ELS, Generic Service,
- * or SCSI commands) exceed a certain time limit. The assumption is
- * that after the time limit the adapter get stuck. So we trigger a reopen of
- * the adapter. This should not be used for error recovery, SCSI abort
- * commands and SCSI requests from SCSI mid-layer.
+ * zfcp_close_qdio - close qdio queues for an adapter
  */
-void
-zfcp_fsf_request_timeout_handler(unsigned long data)
+static void zfcp_close_qdio(struct zfcp_adapter *adapter)
 {
-       struct zfcp_adapter *adapter;
+       struct zfcp_qdio_queue *req_queue;
+       int first, count;
 
-       adapter = (struct zfcp_adapter *) data;
+       if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+               return;
+
+       /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
+       req_queue = &adapter->request_queue;
+       write_lock_irq(&req_queue->queue_lock);
+       atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
+       write_unlock_irq(&req_queue->queue_lock);
+
+       debug_text_event(adapter->erp_dbf, 3, "qdio_down2a");
+       while (qdio_shutdown(adapter->ccw_device,
+                            QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
+               msleep(1000);
+       debug_text_event(adapter->erp_dbf, 3, "qdio_down2b");
 
-       zfcp_erp_adapter_reopen(adapter, 0);
+       /* cleanup used outbound sbals */
+       count = atomic_read(&req_queue->free_count);
+       if (count < QDIO_MAX_BUFFERS_PER_Q) {
+               first = (req_queue->free_index+count) % QDIO_MAX_BUFFERS_PER_Q;
+               count = QDIO_MAX_BUFFERS_PER_Q - count;
+               zfcp_qdio_zero_sbals(req_queue->buffer, first, count);
+       }
+       req_queue->free_index = 0;
+       atomic_set(&req_queue->free_count, 0);
+       req_queue->distance_from_int = 0;
+       adapter->response_queue.free_index = 0;
+       atomic_set(&adapter->response_queue.free_count, 0);
 }
 
 /**
- * zfcp_fsf_scsi_er_timeout_handler - timeout handler for scsi eh tasks
+ * zfcp_close_fsf - stop FSF operations for an adapter
  *
- * This function needs to be called whenever a SCSI error recovery
- * action (abort/reset) does not return.  Re-opening the adapter means
- * that the abort/reset command can be returned by zfcp. It won't complete
- * via the adapter anymore (because qdio queues are closed). If ERP is
- * already running on this adapter it will be stopped.
+ * Dismiss and cleanup all pending fsf_reqs (this wakes up all initiators of
+ * requests waiting for completion; especially this returns SCSI commands
+ * with error state).
  */
-void zfcp_fsf_scsi_er_timeout_handler(unsigned long data)
+static void zfcp_close_fsf(struct zfcp_adapter *adapter)
 {
-       struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
-       unsigned long flags;
+       /* close queues to ensure that buffers are not accessed by adapter */
+       zfcp_close_qdio(adapter);
+       zfcp_fsf_req_dismiss_all(adapter);
+       /* reset FSF request sequence number */
+       adapter->fsf_req_seq_no = 0;
+       /* all ports and units are closed */
+       zfcp_erp_modify_adapter_status(adapter,
+                                      ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
+}
 
-       ZFCP_LOG_NORMAL("warning: SCSI error recovery timed out. "
-                       "Restarting all operations on the adapter %s\n",
-                       zfcp_get_busid_by_adapter(adapter));
-       debug_text_event(adapter->erp_dbf, 1, "eh_lmem_tout");
+/**
+ * zfcp_fsf_request_timeout_handler - called if a request timed out
+ * @data: pointer to adapter for handler function
+ *
+ * This function needs to be called if requests (ELS, Generic Service,
+ * or SCSI commands) exceed a certain time limit. The assumption is
+ * that after the time limit the adapter get stuck. So we trigger a reopen of
+ * the adapter.
+ */
+static void zfcp_fsf_request_timeout_handler(unsigned long data)
+{
+       struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
+       zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
+}
 
-       write_lock_irqsave(&adapter->erp_lock, flags);
-       if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
-                            &adapter->status)) {
-               zfcp_erp_modify_adapter_status(adapter,
-                      ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN,
-                      ZFCP_CLEAR);
-               zfcp_erp_action_dismiss_adapter(adapter);
-               write_unlock_irqrestore(&adapter->erp_lock, flags);
-               /* dismiss all pending requests including requests for ERP */
-               zfcp_fsf_req_dismiss_all(adapter);
-               adapter->fsf_req_seq_no = 0;
-       } else
-               write_unlock_irqrestore(&adapter->erp_lock, flags);
-       zfcp_erp_adapter_reopen(adapter, 0);
+void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
+{
+       fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
+       fsf_req->timer.data = (unsigned long) fsf_req->adapter;
+       fsf_req->timer.expires = jiffies + timeout;
+       add_timer(&fsf_req->timer);
 }
 
 /*
@@ -179,7 +200,7 @@ void zfcp_fsf_scsi_er_timeout_handler(unsigned long data)
  * returns:    0       - initiated action successfully
  *             <0      - failed to initiate action
  */
-int
+static int
 zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
 {
        int retval;
@@ -274,7 +295,7 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
  * zfcp_erp_adisc - send ADISC ELS command
  * @port: port structure
  */
-int
+static int
 zfcp_erp_adisc(struct zfcp_port *port)
 {
        struct zfcp_adapter *adapter = port->adapter;
@@ -282,7 +303,6 @@ zfcp_erp_adisc(struct zfcp_port *port)
        struct zfcp_ls_adisc *adisc;
        void *address = NULL;
        int retval = 0;
-       struct timer_list *timer;
 
        send_els = kzalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC);
        if (send_els == NULL)
@@ -322,29 +342,18 @@ zfcp_erp_adisc(struct zfcp_port *port)
        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 "
+       ZFCP_LOG_INFO("ADISC request from s_id 0x%06x to d_id 0x%06x "
                      "(wwpn=0x%016Lx, wwnn=0x%016Lx, "
-                     "hard_nport_id=0x%08x, nport_id=0x%08x)\n",
+                     "hard_nport_id=0x%06x, nport_id=0x%06x)\n",
                      adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn,
                      (wwn_t) adisc->wwnn, adisc->hard_nport_id,
                      adisc->nport_id);
 
-       timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC);
-       if (!timer)
-               goto nomem;
-
-       init_timer(timer);
-       timer->function = zfcp_fsf_request_timeout_handler;
-       timer->data = (unsigned long) adapter;
-       timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
-       send_els->timer = timer;
-
        retval = zfcp_fsf_send_els(send_els);
        if (retval != 0) {
                ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
-                               "0x%08x on adapter %s\n", send_els->d_id,
+                               "0x%06x on adapter %s\n", send_els->d_id,
                                zfcp_get_busid_by_adapter(adapter));
-               del_timer(send_els->timer);
                goto freemem;
        }
 
@@ -356,7 +365,6 @@ zfcp_erp_adisc(struct zfcp_port *port)
        if (address != NULL)
                __free_pages(send_els->req->page, 0);
        if (send_els != NULL) {
-               kfree(send_els->timer);
                kfree(send_els->req);
                kfree(send_els->resp);
                kfree(send_els);
@@ -372,7 +380,7 @@ zfcp_erp_adisc(struct zfcp_port *port)
  *
  * If ADISC failed (LS_RJT or timed out) forced reopen of the port is triggered.
  */
-void
+static void
 zfcp_erp_adisc_handler(unsigned long data)
 {
        struct zfcp_send_els *send_els;
@@ -382,9 +390,6 @@ zfcp_erp_adisc_handler(unsigned long data)
        struct zfcp_ls_adisc_acc *adisc;
 
        send_els = (struct zfcp_send_els *) data;
-
-       del_timer(send_els->timer);
-
        adapter = send_els->adapter;
        port = send_els->port;
        d_id = send_els->d_id;
@@ -393,7 +398,7 @@ zfcp_erp_adisc_handler(unsigned long data)
        if (send_els->status != 0) {
                ZFCP_LOG_NORMAL("ELS request rejected/timed out, "
                                "force physical port reopen "
-                               "(adapter %s, port d_id=0x%08x)\n",
+                               "(adapter %s, port d_id=0x%06x)\n",
                                zfcp_get_busid_by_adapter(adapter), d_id);
                debug_text_event(adapter->erp_dbf, 3, "forcreop");
                if (zfcp_erp_port_forced_reopen(port, 0))
@@ -406,9 +411,9 @@ zfcp_erp_adisc_handler(unsigned long data)
 
        adisc = zfcp_sg_to_address(send_els->resp);
 
-       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",
+       ZFCP_LOG_INFO("ADISC response from d_id 0x%06x to s_id "
+                     "0x%06x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
+                     "hard_nport_id=0x%06x, nport_id=0x%06x)\n",
                      d_id, fc_host_port_id(adapter->scsi_host),
                      (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn,
                      adisc->hard_nport_id, adisc->nport_id);
@@ -433,7 +438,6 @@ zfcp_erp_adisc_handler(unsigned long data)
  out:
        zfcp_port_put(port);
        __free_pages(send_els->req->page, 0);
-       kfree(send_els->timer);
        kfree(send_els->req);
        kfree(send_els->resp);
        kfree(send_els);
@@ -834,32 +838,27 @@ zfcp_erp_action_exists(struct zfcp_erp_action *erp_action)
  *             and does appropriate preparations (dismiss fsf request, ...)
  *
  * locks:      called under erp_lock (disabled interrupts)
- *
- * returns:    0
  */
-static int
+static void
 zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
 {
-       int retval = 0;
-       struct zfcp_fsf_req *fsf_req = NULL;
        struct zfcp_adapter *adapter = erp_action->adapter;
 
        if (erp_action->fsf_req) {
                /* take lock to ensure that request is not deleted meanwhile */
                spin_lock(&adapter->req_list_lock);
-               if ((!zfcp_reqlist_ismember(adapter,
-                                           erp_action->fsf_req->req_id)) &&
-                   (fsf_req->erp_action == erp_action)) {
+               if (zfcp_reqlist_find(adapter, erp_action->fsf_req->req_id)) {
                        /* fsf_req still exists */
                        debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
-                       debug_event(adapter->erp_dbf, 3, &fsf_req,
+                       debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req,
                                    sizeof (unsigned long));
                        /* dismiss fsf_req of timed out/dismissed erp_action */
                        if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED |
                                                  ZFCP_STATUS_ERP_TIMEDOUT)) {
                                debug_text_event(adapter->erp_dbf, 3,
                                                 "a_ca_disreq");
-                               fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
+                               erp_action->fsf_req->status |=
+                                       ZFCP_STATUS_FSFREQ_DISMISSED;
                        }
                        if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
                                ZFCP_LOG_NORMAL("error: erp step timed out "
@@ -872,11 +871,11 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
                         * then keep it running asynchronously and don't mess
                         * with the association of erp_action and fsf_req.
                         */
-                       if (fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED |
+                       if (erp_action->fsf_req->status &
+                                       (ZFCP_STATUS_FSFREQ_COMPLETED |
                                               ZFCP_STATUS_FSFREQ_DISMISSED)) {
                                /* forget about association between fsf_req
                                   and erp_action */
-                               fsf_req->erp_action = NULL;
                                erp_action->fsf_req = NULL;
                        }
                } else {
@@ -890,8 +889,6 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
                spin_unlock(&adapter->req_list_lock);
        } else
                debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
-
-       return retval;
 }
 
 /**
@@ -909,8 +906,6 @@ static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,
                debug_text_event(adapter->erp_dbf, 2, "a_asyh_ex");
                debug_event(adapter->erp_dbf, 2, &erp_action->action,
                            sizeof (int));
-               if (!(set_mask & ZFCP_STATUS_ERP_TIMEDOUT))
-                       del_timer(&erp_action->timer);
                erp_action->status |= set_mask;
                zfcp_erp_action_ready(erp_action);
        } else {
@@ -957,8 +952,7 @@ zfcp_erp_memwait_handler(unsigned long data)
  *             action gets an appropriate flag and will be processed
  *             accordingly
  */
-static void
-zfcp_erp_timeout_handler(unsigned long data)
+void zfcp_erp_timeout_handler(unsigned long data)
 {
        struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
        struct zfcp_adapter *adapter = erp_action->adapter;
@@ -1382,7 +1376,7 @@ zfcp_erp_port_failed(struct zfcp_port *port)
 
        if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
                ZFCP_LOG_NORMAL("port erp failed (adapter %s, "
-                               "port d_id=0x%08x)\n",
+                               "port d_id=0x%06x)\n",
                                zfcp_get_busid_by_port(port), port->d_id);
        else
                ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n",
@@ -1596,6 +1590,61 @@ zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
        return result;
 }
 
+struct zfcp_erp_add_work {
+       struct zfcp_unit  *unit;
+       struct work_struct work;
+};
+
+/**
+ * zfcp_erp_scsi_scan
+ * @data: pointer to a struct zfcp_erp_add_work
+ *
+ * Registers a logical unit with the SCSI stack.
+ */
+static void zfcp_erp_scsi_scan(struct work_struct *work)
+{
+       struct zfcp_erp_add_work *p =
+               container_of(work, struct zfcp_erp_add_work, work);
+       struct zfcp_unit *unit = p->unit;
+       struct fc_rport *rport = unit->port->rport;
+       scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
+                        unit->scsi_lun, 0);
+       atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
+       wake_up(&unit->scsi_scan_wq);
+       zfcp_unit_put(unit);
+       kfree(p);
+}
+
+/**
+ * zfcp_erp_schedule_work
+ * @unit: pointer to unit which should be registered with SCSI stack
+ *
+ * Schedules work which registers a unit with the SCSI stack
+ */
+static void
+zfcp_erp_schedule_work(struct zfcp_unit *unit)
+{
+       struct zfcp_erp_add_work *p;
+
+       p = kzalloc(sizeof(*p), GFP_KERNEL);
+       if (!p) {
+               ZFCP_LOG_NORMAL("error: Out of resources. Could not register "
+                               "the FCP-LUN 0x%Lx connected to "
+                               "the port with WWPN 0x%Lx connected to "
+                               "the adapter %s with the SCSI stack.\n",
+                               unit->fcp_lun,
+                               unit->port->wwpn,
+                               zfcp_get_busid_by_unit(unit));
+               return;
+       }
+
+       zfcp_unit_get(unit);
+       atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
+       INIT_WORK(&p->work, zfcp_erp_scsi_scan);
+       p->unit = unit;
+       schedule_work(&p->work);
+}
+
 /*
  * function:   
  *
@@ -1638,8 +1687,8 @@ zfcp_erp_strategy_followup_actions(int action,
                break;
 
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
-               if (status == ZFCP_ERP_SUCCEEDED) ;     /* no further action */
-               else
+               /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */
+               if (status != ZFCP_ERP_SUCCEEDED)
                        zfcp_erp_port_reopen_internal(unit->port, 0);
                break;
        }
@@ -1934,9 +1983,12 @@ zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close)
                          &erp_action->adapter->status);
 
  failed_openfcp:
-       zfcp_erp_adapter_strategy_close_qdio(erp_action);
-       zfcp_erp_adapter_strategy_close_fsf(erp_action);
+       zfcp_close_fsf(erp_action->adapter);
  failed_qdio:
+       atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
+                         ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
+                         ZFCP_STATUS_ADAPTER_XPORT_OK,
+                         &erp_action->adapter->status);
  out:
        return retval;
 }
@@ -1987,7 +2039,7 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
                sbale = &(adapter->response_queue.buffer[i]->element[0]);
                sbale->length = 0;
                sbale->flags = SBAL_FLAGS_LAST_ENTRY;
-               sbale->addr = 0;
+               sbale->addr = NULL;
        }
 
        ZFCP_LOG_TRACE("calling do_QDIO on adapter %s (flags=0x%x, "
@@ -2040,59 +2092,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
        return retval;
 }
 
-/**
- * zfcp_erp_adapter_strategy_close_qdio - close qdio queues for an adapter
- */
-static void
-zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
-{
-       int first_used;
-       int used_count;
-       struct zfcp_adapter *adapter = erp_action->adapter;
-
-       if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) {
-               ZFCP_LOG_DEBUG("error: attempt to shut down inactive QDIO "
-                              "queues on adapter %s\n",
-                              zfcp_get_busid_by_adapter(adapter));
-               return;
-       }
-
-       /*
-        * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that
-        * do_QDIO won't be called while qdio_shutdown is in progress.
-        */
-       write_lock_irq(&adapter->request_queue.queue_lock);
-       atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
-       write_unlock_irq(&adapter->request_queue.queue_lock);
-
-       debug_text_event(adapter->erp_dbf, 3, "qdio_down2a");
-       while (qdio_shutdown(adapter->ccw_device,
-                            QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
-               msleep(1000);
-       debug_text_event(adapter->erp_dbf, 3, "qdio_down2b");
-
-       /*
-        * First we had to stop QDIO operation.
-        * Now it is safe to take the following actions.
-        */
-
-       /* Cleanup only necessary when there are unacknowledged buffers */
-       if (atomic_read(&adapter->request_queue.free_count)
-           < QDIO_MAX_BUFFERS_PER_Q) {
-               first_used = (adapter->request_queue.free_index +
-                             atomic_read(&adapter->request_queue.free_count))
-                       % QDIO_MAX_BUFFERS_PER_Q;
-               used_count = QDIO_MAX_BUFFERS_PER_Q -
-                       atomic_read(&adapter->request_queue.free_count);
-               zfcp_qdio_zero_sbals(adapter->request_queue.buffer,
-                                    first_used, used_count);
-       }
-       adapter->response_queue.free_index = 0;
-       atomic_set(&adapter->response_queue.free_count, 0);
-       adapter->request_queue.free_index = 0;
-       atomic_set(&adapter->request_queue.free_count, 0);
-       adapter->request_queue.distance_from_int = 0;
-}
 
 static int
 zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
@@ -2127,7 +2126,6 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
                write_lock_irq(&adapter->erp_lock);
                zfcp_erp_action_to_running(erp_action);
                write_unlock_irq(&adapter->erp_lock);
-               zfcp_erp_timeout_init(erp_action);
                if (zfcp_fsf_exchange_config_data(erp_action)) {
                        retval = ZFCP_ERP_FAILED;
                        debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
@@ -2172,6 +2170,9 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
                sleep *= 2;
        }
 
+       atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
+                         &adapter->status);
+
        if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
                              &adapter->status)) {
                ZFCP_LOG_INFO("error: exchange of configuration data for "
@@ -2196,7 +2197,6 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
        zfcp_erp_action_to_running(erp_action);
        write_unlock_irq(&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");
@@ -2248,27 +2248,6 @@ zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action
        return retval;
 }
 
-/**
- * zfcp_erp_adapter_strategy_close_fsf - stop FSF operations for an adapter
- */
-static void
-zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action)
-{
-       struct zfcp_adapter *adapter = erp_action->adapter;
-
-       /*
-        * wake waiting initiators of requests,
-        * return SCSI commands (with error status),
-        * clean up all requests (synchronously)
-        */
-       zfcp_fsf_req_dismiss_all(adapter);
-       /* reset FSF request sequence number */
-       adapter->fsf_req_seq_no = 0;
-       /* all ports and units are closed */
-       zfcp_erp_modify_adapter_status(adapter,
-                                      ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
-}
-
 /*
  * function:   
  *
@@ -2483,7 +2462,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
                                retval = ZFCP_ERP_FAILED;
                        }
                } else {
-                       ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%08x -> "
+                       ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> "
                                       "trying open\n", port->wwpn, port->d_id);
                        retval = zfcp_erp_port_strategy_open_port(erp_action);
                }
@@ -2523,7 +2502,7 @@ zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action)
        case ZFCP_ERP_STEP_UNINITIALIZED:
        case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
        case ZFCP_ERP_STEP_PORT_CLOSING:
-               ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%08x -> trying open\n",
+               ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> trying open\n",
                               port->wwpn, port->d_id);
                retval = zfcp_erp_port_strategy_open_port(erp_action);
                break;
@@ -2605,7 +2584,6 @@ zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action)
        struct zfcp_adapter *adapter = erp_action->adapter;
        struct zfcp_port *port = erp_action->port;
 
-       zfcp_erp_timeout_init(erp_action);
        retval = zfcp_fsf_close_physical_port(erp_action);
        if (retval == -ENOMEM) {
                debug_text_event(adapter->erp_dbf, 5, "o_pfstc_nomem");
@@ -2662,7 +2640,6 @@ zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
        struct zfcp_adapter *adapter = erp_action->adapter;
        struct zfcp_port *port = erp_action->port;
 
-       zfcp_erp_timeout_init(erp_action);
        retval = zfcp_fsf_close_port(erp_action);
        if (retval == -ENOMEM) {
                debug_text_event(adapter->erp_dbf, 5, "p_pstc_nomem");
@@ -2700,7 +2677,6 @@ zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
        struct zfcp_adapter *adapter = erp_action->adapter;
        struct zfcp_port *port = erp_action->port;
 
-       zfcp_erp_timeout_init(erp_action);
        retval = zfcp_fsf_open_port(erp_action);
        if (retval == -ENOMEM) {
                debug_text_event(adapter->erp_dbf, 5, "p_psto_nomem");
@@ -2738,7 +2714,6 @@ zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action)
        struct zfcp_adapter *adapter = erp_action->adapter;
        struct zfcp_port *port = erp_action->port;
 
-       zfcp_erp_timeout_init(erp_action);
        retval = zfcp_ns_gid_pn_request(erp_action);
        if (retval == -ENOMEM) {
                debug_text_event(adapter->erp_dbf, 5, "p_pstn_nomem");
@@ -2864,7 +2839,6 @@ zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
        struct zfcp_adapter *adapter = erp_action->adapter;
        struct zfcp_unit *unit = erp_action->unit;
 
-       zfcp_erp_timeout_init(erp_action);
        retval = zfcp_fsf_close_unit(erp_action);
        if (retval == -ENOMEM) {
                debug_text_event(adapter->erp_dbf, 5, "u_ustc_nomem");
@@ -2905,7 +2879,6 @@ zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
        struct zfcp_adapter *adapter = erp_action->adapter;
        struct zfcp_unit *unit = erp_action->unit;
 
-       zfcp_erp_timeout_init(erp_action);
        retval = zfcp_fsf_open_unit(erp_action);
        if (retval == -ENOMEM) {
                debug_text_event(adapter->erp_dbf, 5, "u_usto_nomem");
@@ -2930,14 +2903,13 @@ zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
        return retval;
 }
 
-static inline void
-zfcp_erp_timeout_init(struct zfcp_erp_action *erp_action)
+void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req)
 {
-       init_timer(&erp_action->timer);
-       erp_action->timer.function = zfcp_erp_timeout_handler;
-       erp_action->timer.data = (unsigned long) erp_action;
-       /* jiffies will be added in zfcp_fsf_req_send */
-       erp_action->timer.expires = ZFCP_ERP_FSFREQ_TIMEOUT;
+       BUG_ON(!fsf_req->erp_action);
+       fsf_req->timer.function = zfcp_erp_timeout_handler;
+       fsf_req->timer.data = (unsigned long) fsf_req->erp_action;
+       fsf_req->timer.expires = jiffies + ZFCP_ERP_FSFREQ_TIMEOUT;
+       add_timer(&fsf_req->timer);
 }
 
 /*
@@ -3181,9 +3153,9 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
                    && port->rport) {
                        atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
                                        &unit->status);
-                       scsi_scan_target(&port->rport->dev, 0,
-                                        port->rport->scsi_target_id,
-                                        unit->scsi_lun, 0);
+                       if (atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
+                                            &unit->status) == 0)
+                               zfcp_erp_schedule_work(unit);
                }
                zfcp_unit_put(unit);
                break;
@@ -3210,7 +3182,7 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
                                                zfcp_get_busid_by_port(port),
                                                port->wwpn);
                        else {
-                               scsi_flush_work(adapter->scsi_host);
+                               scsi_target_unblock(&port->rport->dev);
                                port->rport->maxframe_size = port->maxframe_size;
                                port->rport->supported_classes =
                                        port->supported_classes;
@@ -3224,7 +3196,6 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
                break;
        case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
                if (result != ZFCP_ERP_SUCCEEDED) {
-                       struct zfcp_port *port;
                        list_for_each_entry(port, &adapter->port_list_head, list)
                                if (port->rport &&
                                    !atomic_test_mask(ZFCP_STATUS_PORT_WKA,
@@ -3241,7 +3212,7 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
 }
 
 
-void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
+static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
 {
        struct zfcp_port *port;