You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
[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: Andreas Herrmann <aherrman@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
committed by
James Bottomley
parent
c48a29d065
commit
2448c45965
@@ -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)
|
|||||||
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)
|
|||||||
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,
|
return ZFCP_ERP_SUCCEEDED;
|
||||||
&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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -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,
|
|||||||
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,
|
|||||||
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,
|
if (!erp_action) {
|
||||||
lock_flags);
|
wait_event(fsf_req->completion_wq,
|
||||||
|
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);
|
kfree(timer);
|
||||||
zfcp_fsf_req_free(fsf_req);
|
}
|
||||||
out:
|
|
||||||
kfree(timer);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user