Commit 2448c459 authored by Andreas Herrmann's avatar Andreas Herrmann Committed by James Bottomley

[SCSI] zfcp: fix adapter initialization

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: default avatarAndreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent c48a29d0
...@@ -2243,29 +2243,26 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) ...@@ -2243,29 +2243,26 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
return retval; 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 static int
zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) 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, if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
&erp_action->adapter->status)) { &erp_action->adapter->status)) &&
(erp_action->adapter->adapter_features &
FSF_FEATURE_HBAAPI_MANAGEMENT)) {
zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
atomic_set(&erp_action->adapter->erp_counter, 0); atomic_set(&erp_action->adapter->erp_counter, 0);
return ZFCP_ERP_FAILED; return ZFCP_ERP_FAILED;
} }
xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
xport = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); if (retval == ZFCP_ERP_FAILED)
if ((xconfig == ZFCP_ERP_FAILED) || (xport == 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_FAILED;
return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); 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) ...@@ -2354,41 +2351,29 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
static int static int
zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
{ {
int retval = ZFCP_ERP_SUCCEEDED; int ret;
int retries; int retries;
int sleep; int sleep;
struct zfcp_adapter *adapter = erp_action->adapter; struct zfcp_adapter *adapter = erp_action->adapter;
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
for (retries = 0; ; retries++) { retries = 0;
ZFCP_LOG_DEBUG("Doing exchange port data\n"); do {
write_lock(&adapter->erp_lock);
zfcp_erp_action_to_running(erp_action); zfcp_erp_action_to_running(erp_action);
write_unlock(&adapter->erp_lock);
zfcp_erp_timeout_init(erp_action); zfcp_erp_timeout_init(erp_action);
if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) { ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
retval = ZFCP_ERP_FAILED; if (ret == -EOPNOTSUPP) {
debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf"); debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
ZFCP_LOG_INFO("error: initiation of exchange of " return ZFCP_ERP_SUCCEEDED;
"port data failed for adapter %s\n", } else if (ret) {
zfcp_get_busid_by_adapter(adapter)); debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
break; return ZFCP_ERP_FAILED;
} }
debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok"); debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
ZFCP_LOG_DEBUG("Xchange underway\n");
/*
* 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); down(&adapter->erp_ready_sem);
if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
ZFCP_LOG_INFO("error: exchange of port data " 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) ...@@ -2396,29 +2381,19 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
zfcp_get_busid_by_adapter(adapter)); zfcp_get_busid_by_adapter(adapter));
break; break;
} }
if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
&adapter->status)) &adapter->status))
break; break;
ZFCP_LOG_DEBUG("host connection still initialising... " if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) {
"waiting and retrying...\n"); sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP;
/* sleep a little bit before retry */ retries++;
sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ? } else
ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP : sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; schedule_timeout(sleep);
msleep(jiffies_to_msecs(sleep)); } while (1);
}
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;
}
return retval; return ZFCP_ERP_SUCCEEDED;
} }
/* /*
......
...@@ -2191,13 +2191,10 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, ...@@ -2191,13 +2191,10 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
if (!timer)
return -ENOMEM;
/* setup new FSF request */ /* setup new FSF request */
retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 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) { if (retval < 0) {
ZFCP_LOG_INFO("error: Out of resources. Could not create an " ZFCP_LOG_INFO("error: Out of resources. Could not create an "
"exchange port data request for" "exchange port data request for"
...@@ -2205,25 +2202,33 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, ...@@ -2205,25 +2202,33 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
zfcp_get_busid_by_adapter(adapter)); zfcp_get_busid_by_adapter(adapter));
write_unlock_irqrestore(&adapter->request_queue.queue_lock, write_unlock_irqrestore(&adapter->request_queue.queue_lock,
lock_flags); lock_flags);
goto out; return retval;
}
if (erp_action) {
erp_action->fsf_req = fsf_req;
fsf_req->erp_action = erp_action;
} }
if (data) 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 = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
init_timer(timer); if (erp_action) {
timer->function = zfcp_fsf_request_timeout_handler; erp_action->fsf_req = fsf_req;
timer->data = (unsigned long) adapter; fsf_req->erp_action = erp_action;
timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; 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); retval = zfcp_fsf_req_send(fsf_req, timer);
if (retval) { if (retval) {
...@@ -2233,23 +2238,22 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, ...@@ -2233,23 +2238,22 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
zfcp_fsf_req_free(fsf_req); zfcp_fsf_req_free(fsf_req);
if (erp_action) if (erp_action)
erp_action->fsf_req = NULL; erp_action->fsf_req = NULL;
else
kfree(timer);
write_unlock_irqrestore(&adapter->request_queue.queue_lock, write_unlock_irqrestore(&adapter->request_queue.queue_lock,
lock_flags); lock_flags);
goto out; return retval;
} }
ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n", write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
zfcp_get_busid_by_adapter(adapter));
write_unlock_irqrestore(&adapter->request_queue.queue_lock,
lock_flags);
wait_event(fsf_req->completion_wq, if (!erp_action) {
fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); wait_event(fsf_req->completion_wq,
del_timer_sync(timer); fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
zfcp_fsf_req_free(fsf_req); del_timer_sync(timer);
out: zfcp_fsf_req_free(fsf_req);
kfree(timer); kfree(timer);
}
return retval; return retval;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment