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

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

[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
Loading
Loading
Loading
Loading
+32 −57
Original line number Diff line number Diff line
@@ -2243,29 +2243,26 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
	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);
@@ -2354,41 +2351,29 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *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 "
@@ -2396,29 +2381,19 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
				      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;
}

/*
+32 −28
Original line number Diff line number Diff line
@@ -2191,13 +2191,10 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
                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"
@@ -2205,12 +2202,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
			      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)
@@ -2220,10 +2212,23 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

	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) {
@@ -2233,23 +2238,22 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
		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);

	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);
 out:
		kfree(timer);
	}
	return retval;
}