zfcp_erp.c

来自「linux 内核源代码」· C语言 代码 · 共 2,247 行 · 第 1/5 页

C
2,247
字号
	if (set_or_clear == ZFCP_SET) {		atomic_set_mask(mask, &unit->status);		debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_s");	} else {		atomic_clear_mask(mask, &unit->status);		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {			atomic_set(&unit->erp_counter, 0);		}		debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_c");	}	debug_event(unit->port->adapter->erp_dbf, 3, &unit->fcp_lun,		    sizeof (fcp_lun_t));	debug_event(unit->port->adapter->erp_dbf, 3, &mask, sizeof (u32));}/* * function: * * purpose:	Wrappper for zfcp_erp_port_reopen_all_internal *              used to ensure the correct locking * * returns:	0	- initiated action successfully *		<0	- failed to initiate action */intzfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask){	int retval;	unsigned long flags;	read_lock_irqsave(&zfcp_data.config_lock, flags);	write_lock(&adapter->erp_lock);	retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask);	write_unlock(&adapter->erp_lock);	read_unlock_irqrestore(&zfcp_data.config_lock, flags);	return retval;}static intzfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask){	int retval = 0;	struct zfcp_port *port;	list_for_each_entry(port, &adapter->port_list_head, list)		if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))			zfcp_erp_port_reopen_internal(port, clear_mask);	return retval;}/* * function: * * purpose: * * returns:	FIXME */static intzfcp_erp_unit_reopen_all_internal(struct zfcp_port *port, int clear_mask){	int retval = 0;	struct zfcp_unit *unit;	list_for_each_entry(unit, &port->unit_list_head, list)	    zfcp_erp_unit_reopen_internal(unit, clear_mask);	return retval;}/* * function: * * purpose:	this routine executes the 'Reopen Adapter' action *		(the entire action is processed synchronously, since *		there are no actions which might be run concurrently *		per definition) * * returns:	ZFCP_ERP_SUCCEEDED	- action finished successfully *		ZFCP_ERP_FAILED		- action finished unsuccessfully */static intzfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action){	int retval;	struct zfcp_adapter *adapter = erp_action->adapter;	retval = zfcp_erp_adapter_strategy_close(erp_action);	if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)		retval = ZFCP_ERP_EXIT;	else		retval = zfcp_erp_adapter_strategy_open(erp_action);	debug_text_event(adapter->erp_dbf, 3, "a_ast/ret");	debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));	debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));	if (retval == ZFCP_ERP_FAILED) {		ZFCP_LOG_INFO("Waiting to allow the adapter %s "			      "to recover itself\n",			      zfcp_get_busid_by_adapter(adapter));		msleep(jiffies_to_msecs(ZFCP_TYPE2_RECOVERY_TIME));	}	return retval;}/* * function: * * purpose: * * returns:	ZFCP_ERP_SUCCEEDED      - action finished successfully *              ZFCP_ERP_FAILED         - action finished unsuccessfully */static intzfcp_erp_adapter_strategy_close(struct zfcp_erp_action *erp_action){	int retval;	atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING,			&erp_action->adapter->status);	retval = zfcp_erp_adapter_strategy_generic(erp_action, 1);	atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING,			  &erp_action->adapter->status);	return retval;}/* * function: * * purpose: * * returns:	ZFCP_ERP_SUCCEEDED      - action finished successfully *              ZFCP_ERP_FAILED         - action finished unsuccessfully */static intzfcp_erp_adapter_strategy_open(struct zfcp_erp_action *erp_action){	int retval;	atomic_set_mask(ZFCP_STATUS_COMMON_OPENING,			&erp_action->adapter->status);	retval = zfcp_erp_adapter_strategy_generic(erp_action, 0);	atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING,			  &erp_action->adapter->status);	return retval;}/* * function:    zfcp_register_adapter * * purpose:	allocate the irq associated with this devno and register *		the FSF adapter with the SCSI stack * * returns: */static intzfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close){	int retval = ZFCP_ERP_SUCCEEDED;	if (close)		goto close_only;	retval = zfcp_erp_adapter_strategy_open_qdio(erp_action);	if (retval != ZFCP_ERP_SUCCEEDED)		goto failed_qdio;	retval = zfcp_erp_adapter_strategy_open_fsf(erp_action);	if (retval != ZFCP_ERP_SUCCEEDED)		goto failed_openfcp;	atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &erp_action->adapter->status);	goto out; close_only:	atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,			  &erp_action->adapter->status); failed_openfcp:	zfcp_close_fsf(erp_action->adapter); failed_qdio:	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |			  ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |			  ZFCP_STATUS_ADAPTER_XPORT_OK,			  &erp_action->adapter->status); out:	return retval;}/* * function:    zfcp_qdio_init * * purpose:	setup QDIO operation for specified adapter * * returns:	0 - successful setup *		!0 - failed setup */static intzfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action){	int retval;	int i;	volatile struct qdio_buffer_element *sbale;	struct zfcp_adapter *adapter = erp_action->adapter;	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) {		ZFCP_LOG_NORMAL("bug: second attempt to set up QDIO on "				"adapter %s\n",				zfcp_get_busid_by_adapter(adapter));		goto failed_sanity;	}	if (qdio_establish(&adapter->qdio_init_data) != 0) {		ZFCP_LOG_INFO("error: establishment of QDIO queues failed "			      "on adapter %s\n",			      zfcp_get_busid_by_adapter(adapter));		goto failed_qdio_establish;	}	debug_text_event(adapter->erp_dbf, 3, "qdio_est");	if (qdio_activate(adapter->ccw_device, 0) != 0) {		ZFCP_LOG_INFO("error: activation of QDIO queues failed "			      "on adapter %s\n",			      zfcp_get_busid_by_adapter(adapter));		goto failed_qdio_activate;	}	debug_text_event(adapter->erp_dbf, 3, "qdio_act");	/*	 * put buffers into response queue,	 */	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {		sbale = &(adapter->response_queue.buffer[i]->element[0]);		sbale->length = 0;		sbale->flags = SBAL_FLAGS_LAST_ENTRY;		sbale->addr = NULL;	}	ZFCP_LOG_TRACE("calling do_QDIO on adapter %s (flags=0x%x, "		       "queue_no=%i, index_in_queue=%i, count=%i)\n",		       zfcp_get_busid_by_adapter(adapter),		       QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q);	retval = do_QDIO(adapter->ccw_device,			 QDIO_FLAG_SYNC_INPUT,			 0, 0, QDIO_MAX_BUFFERS_PER_Q, NULL);	if (retval) {		ZFCP_LOG_NORMAL("bug: setup of QDIO failed (retval=%d)\n",				retval);		goto failed_do_qdio;	} else {		adapter->response_queue.free_index = 0;		atomic_set(&adapter->response_queue.free_count, 0);		ZFCP_LOG_DEBUG("%i buffers successfully enqueued to "			       "response queue\n", QDIO_MAX_BUFFERS_PER_Q);	}	/* set index of first avalable SBALS / number of available SBALS */	adapter->request_queue.free_index = 0;	atomic_set(&adapter->request_queue.free_count, QDIO_MAX_BUFFERS_PER_Q);	adapter->request_queue.distance_from_int = 0;	/* initialize waitqueue used to wait for free SBALs in requests queue */	init_waitqueue_head(&adapter->request_wq);	/* ok, we did it - skip all cleanups for different failures */	atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);	retval = ZFCP_ERP_SUCCEEDED;	goto out; failed_do_qdio:	/* NOP */ failed_qdio_activate:	debug_text_event(adapter->erp_dbf, 3, "qdio_down1a");	while (qdio_shutdown(adapter->ccw_device,			     QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)		msleep(1000);	debug_text_event(adapter->erp_dbf, 3, "qdio_down1b"); failed_qdio_establish: failed_sanity:	retval = ZFCP_ERP_FAILED; out:	return retval;}static intzfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action){	int retval;	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);}static intzfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action){	int retval = ZFCP_ERP_SUCCEEDED;	int retries;	int sleep = ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP;	struct zfcp_adapter *adapter = erp_action->adapter;	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);	for (retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES; retries; retries--) {		atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,				  &adapter->status);		ZFCP_LOG_DEBUG("Doing exchange config data\n");		write_lock_irq(&adapter->erp_lock);		zfcp_erp_action_to_running(erp_action);		write_unlock_irq(&adapter->erp_lock);		if (zfcp_fsf_exchange_config_data(erp_action)) {			retval = ZFCP_ERP_FAILED;			debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");			ZFCP_LOG_INFO("error:  initiation of exchange of "				      "configuration data failed for "				      "adapter %s\n",				      zfcp_get_busid_by_adapter(adapter));			break;		}		debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok");		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 config 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 config		 * data' request.		 */		down(&adapter->erp_ready_sem);		if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {			ZFCP_LOG_INFO("error: exchange of configuration data "				      "for adapter %s timed out\n",				      zfcp_get_busid_by_adapter(adapter));			break;		}		if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,				     &adapter->status))			break;		ZFCP_LOG_DEBUG("host connection still initialising... "			       "waiting and retrying...\n");		/* sleep a little bit before retry */		msleep(jiffies_to_msecs(sleep));		sleep *= 2;	}	atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,			  &adapter->status);	if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,			      &adapter->status)) {		ZFCP_LOG_INFO("error: exchange of configuration data for "			      "adapter %s failed\n",			      zfcp_get_busid_by_adapter(adapter));		retval = ZFCP_ERP_FAILED;	}	return retval;}static intzfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action){	int ret;	struct zfcp_adapter *adapter;	adapter = erp_action->adapter;	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);	write_lock_irq(&adapter->erp_lock);	zfcp_erp_action_to_running(erp_action);	write_unlock_irq(&adapter->erp_lock);	ret = zfcp_fsf_exchange_port_data(erp_action);	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");	ret = ZFCP_ERP_SUCCEEDED;	down(&adapter->erp_ready_sem);	if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {		ZFCP_LOG_INFO("error: exchange port data timed out (adapter "			      "%s)\n", zfcp_get_busid_by_adapter(adapter));		ret = ZFCP_ERP_FAILED;	}	/* don't treat as error for the sake of compatibility */	if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status))		ZFCP_LOG_INFO("warning: exchange port data failed (adapter "			      "%s\n", zfcp_get_busid_by_adapter(adapter));	return ret;}static intzfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action					      *erp_action){	int retval = ZFCP_ERP_SUCCEEDED;	int temp_ret;	struct zfcp_adapter *adapter = erp_action->adapter;	int i;	adapter->status_read_failed = 0;	for (i = 0; i < ZFCP_STATUS_READS_RECOM; i++) {		temp_ret = zfcp_fsf_status_read(adapter, ZFCP_WAIT_FOR_SBAL);		if (temp_ret < 0) {			ZFCP_LOG_INFO("error: set-up of unsolicited status "				      "notification failed on adapter %s\n",				      zfcp_get_busid_by_adapter(adapter));			retval = ZFCP_ERP_FAILED;			i--;			break;		}	}	return retva

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?