Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f8f3ed5 authored by Andreas Herrmann's avatar Andreas Herrmann Committed by
Browse files

[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: default avatarAndreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent c8024eb5
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -152,11 +152,6 @@ typedef u32 scsi_lun_t;
#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP	100
#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 */
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);

+28 −52
Original line number Diff line number Diff line
@@ -2246,15 +2246,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
{
	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);
	if (retval == 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);
}

/*
 * function:	
 *
 * purpose:	
 *
 * returns:
 */
static int
zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
{
@@ -2350,17 +2334,15 @@ static int
zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
{
	int ret;
	int retries;
	int sleep;
	struct zfcp_adapter *adapter = erp_action->adapter;
	struct zfcp_adapter *adapter;

	adapter = erp_action->adapter;
	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);

	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);
	ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
	if (ret == -EOPNOTSUPP) {
@@ -2372,26 +2354,20 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
	}
	debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");

	ret = ZFCP_ERP_SUCCEEDED;
	down(&adapter->erp_ready_sem);
	if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
			ZFCP_LOG_INFO("error: exchange of port data "
				      "for adapter %s timed out\n",
				      zfcp_get_busid_by_adapter(adapter));
			break;
		ZFCP_LOG_INFO("error: exchange port data timed out (adapter "
			      "%s)\n", zfcp_get_busid_by_adapter(adapter));
		ret = ZFCP_ERP_FAILED;
	}
	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;
	}
		if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
				      &adapter->status))
			break;

		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 ZFCP_ERP_SUCCEEDED;
	return ret;
}

/*
+41 −33
Original line number Diff line number Diff line
@@ -388,6 +388,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
	case FSF_PROT_LINK_DOWN:
		zfcp_fsf_link_down_info_eval(adapter,
					     &prot_status_qual->link_down_info);
		zfcp_erp_adapter_reopen(adapter, 0);
		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		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);

	if (link_down == NULL) {
		zfcp_erp_adapter_reopen(adapter, 0);
		return;
	}
	if (link_down == NULL)
		goto out;

	switch (link_down->error_code) {
	case FSF_PSQ_LINK_NO_LIGHT:
@@ -643,17 +642,9 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
				link_down->explanation_code,
				link_down->vendor_specific_code);

	switch (link_down->error_code) {
	case FSF_PSQ_LINK_NO_LIGHT:
	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:
 out:
	zfcp_erp_adapter_failed(adapter);
}
}

/*
 * function:	zfcp_fsf_req_dispatch
@@ -2304,46 +2295,63 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
	return retval;
}


/**
 * zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request
 * @fsf_req: pointer to struct zfcp_fsf_req
 * 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_data_handler(struct zfcp_fsf_req *fsf_req)
zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
{
	struct zfcp_adapter *adapter = fsf_req->adapter;
	struct Scsi_Host *shost = adapter->scsi_host;
	struct fsf_qtcb *qtcb = fsf_req->qtcb;
	struct zfcp_adapter *adapter;
	struct fsf_qtcb *qtcb;
	struct fsf_qtcb_bottom_port *bottom, *data;
	struct Scsi_Host *shost;

	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;

	switch (qtcb->header.fsf_status) {
        case FSF_GOOD:
		atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);

	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_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;
}

/**
 * zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request
 * @fsf_req: pointer to struct zfcp_fsf_req
 */
static void
zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
{
	struct zfcp_adapter *adapter;
	struct fsf_qtcb *qtcb;

	adapter = fsf_req->adapter;
	qtcb = fsf_req->qtcb;

	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;

	switch (qtcb->header.fsf_status) {
        case FSF_GOOD:
		zfcp_fsf_exchange_port_evaluate(fsf_req, 1);
		atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
		break;
	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
		zfcp_fsf_exchange_port_evaluate(fsf_req, 0);
		atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);

		zfcp_fsf_link_down_info_eval(adapter,
			&qtcb->header.fsf_status_qual.link_down_info);
                break;

        default:
		debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
		debug_event(adapter->erp_dbf, 0,