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);
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 "
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;
}
/*
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"
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) {
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;
}