[SCSI] zfcp: fix adapter erp when link is unplugged
Remove endless polling for replug of the local link. Just wait for link up notification. Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
@@ -152,11 +152,6 @@ typedef u32 scsi_lun_t;
|
|||||||
#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100
|
#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100
|
||||||
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
|
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
|
||||||
|
|
||||||
/* Retry 5 times every 2 second, then every minute */
|
|
||||||
#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5
|
|
||||||
#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200
|
|
||||||
#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000
|
|
||||||
|
|
||||||
/* timeout value for "default timer" for fsf requests */
|
/* timeout value for "default timer" for fsf requests */
|
||||||
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
|
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
|
||||||
|
|
||||||
|
@@ -2246,15 +2246,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
|
|||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
|
retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
|
||||||
if (retval == ZFCP_ERP_FAILED)
|
if (retval == ZFCP_ERP_FAILED)
|
||||||
return ZFCP_ERP_FAILED;
|
return ZFCP_ERP_FAILED;
|
||||||
@@ -2266,13 +2257,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
|
|||||||
return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
|
return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* function:
|
|
||||||
*
|
|
||||||
* purpose:
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
|
zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
|
||||||
{
|
{
|
||||||
@@ -2350,48 +2334,40 @@ 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 ret;
|
int ret;
|
||||||
int retries;
|
struct zfcp_adapter *adapter;
|
||||||
int sleep;
|
|
||||||
struct zfcp_adapter *adapter = erp_action->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);
|
||||||
|
|
||||||
retries = 0;
|
write_lock(&adapter->erp_lock);
|
||||||
do {
|
zfcp_erp_action_to_running(erp_action);
|
||||||
write_lock(&adapter->erp_lock);
|
write_unlock(&adapter->erp_lock);
|
||||||
zfcp_erp_action_to_running(erp_action);
|
|
||||||
write_unlock(&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");
|
|
||||||
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_xport_ok");
|
|
||||||
|
|
||||||
down(&adapter->erp_ready_sem);
|
zfcp_erp_timeout_init(erp_action);
|
||||||
if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
|
ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
|
||||||
ZFCP_LOG_INFO("error: exchange of port data "
|
if (ret == -EOPNOTSUPP) {
|
||||||
"for adapter %s timed out\n",
|
debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
|
||||||
zfcp_get_busid_by_adapter(adapter));
|
return ZFCP_ERP_SUCCEEDED;
|
||||||
break;
|
} else if (ret) {
|
||||||
}
|
debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
|
||||||
if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
|
return ZFCP_ERP_FAILED;
|
||||||
&adapter->status))
|
}
|
||||||
break;
|
debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
|
||||||
|
|
||||||
if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) {
|
ret = ZFCP_ERP_SUCCEEDED;
|
||||||
sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP;
|
down(&adapter->erp_ready_sem);
|
||||||
retries++;
|
if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
|
||||||
} else
|
ZFCP_LOG_INFO("error: exchange port data timed out (adapter "
|
||||||
sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
|
"%s)\n", zfcp_get_busid_by_adapter(adapter));
|
||||||
schedule_timeout(sleep);
|
ret = ZFCP_ERP_FAILED;
|
||||||
} while (1);
|
}
|
||||||
|
if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) {
|
||||||
|
ZFCP_LOG_INFO("error: exchange port data failed (adapter "
|
||||||
|
"%s\n", zfcp_get_busid_by_adapter(adapter));
|
||||||
|
ret = ZFCP_ERP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
return ZFCP_ERP_SUCCEEDED;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -388,6 +388,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
|
|||||||
case FSF_PROT_LINK_DOWN:
|
case FSF_PROT_LINK_DOWN:
|
||||||
zfcp_fsf_link_down_info_eval(adapter,
|
zfcp_fsf_link_down_info_eval(adapter,
|
||||||
&prot_status_qual->link_down_info);
|
&prot_status_qual->link_down_info);
|
||||||
|
zfcp_erp_adapter_reopen(adapter, 0);
|
||||||
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
|
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -558,10 +559,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
|
|||||||
|
|
||||||
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
|
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
|
||||||
|
|
||||||
if (link_down == NULL) {
|
if (link_down == NULL)
|
||||||
zfcp_erp_adapter_reopen(adapter, 0);
|
goto out;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (link_down->error_code) {
|
switch (link_down->error_code) {
|
||||||
case FSF_PSQ_LINK_NO_LIGHT:
|
case FSF_PSQ_LINK_NO_LIGHT:
|
||||||
@@ -643,16 +642,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
|
|||||||
link_down->explanation_code,
|
link_down->explanation_code,
|
||||||
link_down->vendor_specific_code);
|
link_down->vendor_specific_code);
|
||||||
|
|
||||||
switch (link_down->error_code) {
|
out:
|
||||||
case FSF_PSQ_LINK_NO_LIGHT:
|
zfcp_erp_adapter_failed(adapter);
|
||||||
case FSF_PSQ_LINK_WRAP_PLUG:
|
|
||||||
case FSF_PSQ_LINK_NO_FCP:
|
|
||||||
case FSF_PSQ_LINK_FIRMWARE_UPDATE:
|
|
||||||
zfcp_erp_adapter_reopen(adapter, 0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
zfcp_erp_adapter_failed(adapter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2304,6 +2295,35 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zfcp_fsf_exchange_port_evaluate
|
||||||
|
* @fsf_req: fsf_req which belongs to xchg port data request
|
||||||
|
* @xchg_ok: specifies if xchg port data was incomplete or complete (0/1)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
|
||||||
|
{
|
||||||
|
struct zfcp_adapter *adapter;
|
||||||
|
struct fsf_qtcb *qtcb;
|
||||||
|
struct fsf_qtcb_bottom_port *bottom, *data;
|
||||||
|
struct Scsi_Host *shost;
|
||||||
|
|
||||||
|
adapter = fsf_req->adapter;
|
||||||
|
qtcb = fsf_req->qtcb;
|
||||||
|
bottom = &qtcb->bottom.port;
|
||||||
|
shost = adapter->scsi_host;
|
||||||
|
|
||||||
|
data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
|
||||||
|
if (data)
|
||||||
|
memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
|
||||||
|
|
||||||
|
if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
|
||||||
|
fc_host_permanent_port_name(shost) = bottom->wwpn;
|
||||||
|
else
|
||||||
|
fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
|
||||||
|
fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
|
||||||
|
fc_host_supported_speeds(shost) = bottom->supported_speed;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request
|
* zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request
|
||||||
@@ -2312,38 +2332,26 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
|
|||||||
static void
|
static void
|
||||||
zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
|
zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter = fsf_req->adapter;
|
struct zfcp_adapter *adapter;
|
||||||
struct Scsi_Host *shost = adapter->scsi_host;
|
struct fsf_qtcb *qtcb;
|
||||||
struct fsf_qtcb *qtcb = fsf_req->qtcb;
|
|
||||||
struct fsf_qtcb_bottom_port *bottom, *data;
|
adapter = fsf_req->adapter;
|
||||||
|
qtcb = fsf_req->qtcb;
|
||||||
|
|
||||||
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
|
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (qtcb->header.fsf_status) {
|
switch (qtcb->header.fsf_status) {
|
||||||
case FSF_GOOD:
|
case FSF_GOOD:
|
||||||
|
zfcp_fsf_exchange_port_evaluate(fsf_req, 1);
|
||||||
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
|
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
|
||||||
|
|
||||||
bottom = &qtcb->bottom.port;
|
|
||||||
data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
|
|
||||||
if (data)
|
|
||||||
memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
|
|
||||||
if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
|
|
||||||
fc_host_permanent_port_name(shost) = bottom->wwpn;
|
|
||||||
else
|
|
||||||
fc_host_permanent_port_name(shost) =
|
|
||||||
fc_host_port_name(shost);
|
|
||||||
fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
|
|
||||||
fc_host_supported_speeds(shost) = bottom->supported_speed;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
|
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
|
||||||
|
zfcp_fsf_exchange_port_evaluate(fsf_req, 0);
|
||||||
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
|
atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
|
||||||
|
|
||||||
zfcp_fsf_link_down_info_eval(adapter,
|
zfcp_fsf_link_down_info_eval(adapter,
|
||||||
&qtcb->header.fsf_status_qual.link_down_info);
|
&qtcb->header.fsf_status_qual.link_down_info);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
|
debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
|
||||||
debug_event(adapter->erp_dbf, 0,
|
debug_event(adapter->erp_dbf, 0,
|
||||||
|
Reference in New Issue
Block a user