⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zfcp_erp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  *  * linux/drivers/s390/scsi/zfcp_erp.c  *  * FCP adapter driver for IBM eServer zSeries  *  * (C) Copyright IBM Corp. 2002, 2004 * * Author(s): Martin Peschke <mpeschke@de.ibm.com>  *            Raimund Schroeder <raimund.schroeder@de.ibm.com>  *            Aron Zeh *            Wolfgang Taphorn *            Stefan Bader <stefan.bader@de.ibm.com>  *            Heiko Carstens <heiko.carstens@de.ibm.com>  *            Andreas Herrmann <aherrman@de.ibm.com> *  * This program is free software; you can redistribute it and/or modify  * it under the terms of the GNU General Public License as published by  * the Free Software Foundation; either version 2, or (at your option)  * any later version.  *  * This program is distributed in the hope that it will be useful,  * but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  * GNU General Public License for more details.  *  * You should have received a copy of the GNU General Public License  * along with this program; if not, write to the Free Software  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */#define ZFCP_LOG_AREA			ZFCP_LOG_AREA_ERP#define ZFCP_ERP_REVISION "$Revision: 1.86 $"#include "zfcp_ext.h"static int zfcp_erp_adisc(struct zfcp_port *);static void zfcp_erp_adisc_handler(unsigned long);static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int);static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int);static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int);static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int);static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int);static void zfcp_erp_adapter_block(struct zfcp_adapter *, int);static void zfcp_erp_adapter_unblock(struct zfcp_adapter *);static void zfcp_erp_port_block(struct zfcp_port *, int);static void zfcp_erp_port_unblock(struct zfcp_port *);static void zfcp_erp_unit_block(struct zfcp_unit *, int);static void zfcp_erp_unit_unblock(struct zfcp_unit *);static int zfcp_erp_thread(void *);static int zfcp_erp_strategy(struct zfcp_erp_action *);static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *);static int zfcp_erp_strategy_memwait(struct zfcp_erp_action *);static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *, int);static int zfcp_erp_strategy_check_unit(struct zfcp_unit *, int);static int zfcp_erp_strategy_check_port(struct zfcp_port *, int);static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *, int);static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *,					 struct zfcp_port *,					 struct zfcp_unit *, int);static inline int zfcp_erp_strategy_statechange_detected(atomic_t *, u32);static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *,					      struct zfcp_port *,					      struct zfcp_unit *, int);static int zfcp_erp_strategy_check_queues(struct zfcp_adapter *);static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int);static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *);static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int);static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *);static int zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *);static int zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *);static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *);static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *);static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *);static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *);static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *);static int zfcp_erp_adapter_strategy_open_fsf_statusread(	struct zfcp_erp_action *);static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *);static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *);static int zfcp_erp_port_strategy(struct zfcp_erp_action *);static int zfcp_erp_port_strategy_clearstati(struct zfcp_port *);static int zfcp_erp_port_strategy_close(struct zfcp_erp_action *);static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *);static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *);static int zfcp_erp_port_strategy_open_nameserver_wakeup(	struct zfcp_erp_action *);static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *);static int zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *);static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *);static int zfcp_erp_unit_strategy(struct zfcp_erp_action *);static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *);static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *);static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *);static int zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *);static int zfcp_erp_action_dismiss_port(struct zfcp_port *);static int zfcp_erp_action_dismiss_unit(struct zfcp_unit *);static int zfcp_erp_action_dismiss(struct zfcp_erp_action *);static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *,				   struct zfcp_port *, struct zfcp_unit *);static int zfcp_erp_action_dequeue(struct zfcp_erp_action *);static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *,				    struct zfcp_port *, struct zfcp_unit *,				    int);static void zfcp_erp_action_ready(struct zfcp_erp_action *);static int  zfcp_erp_action_exists(struct zfcp_erp_action *);static inline void zfcp_erp_action_to_ready(struct zfcp_erp_action *);static inline void zfcp_erp_action_to_running(struct zfcp_erp_action *);static void zfcp_erp_memwait_handler(unsigned long);static void zfcp_erp_timeout_handler(unsigned long);static inline void zfcp_erp_timeout_init(struct zfcp_erp_action *);/** * zfcp_fsf_request_timeout_handler - called if a request timed out * @data: pointer to adapter for handler function * * This function needs to be called if requests (ELS, Generic Service, * or SCSI commands) exceed a certain time limit. The assumption is * that after the time limit the adapter get stuck. So we trigger a reopen of * the adapter. This should not be used for error recovery, SCSI abort * commands and SCSI requests from SCSI mid-layer. */voidzfcp_fsf_request_timeout_handler(unsigned long data){	struct zfcp_adapter *adapter;	adapter = (struct zfcp_adapter *) data;	zfcp_erp_adapter_reopen(adapter, 0);}/* * function:	zfcp_fsf_scsi_er_timeout_handler * * purpose:     This function needs to be called whenever a SCSI error recovery *              action (abort/reset) does not return. *              Re-opening the adapter means that the command can be returned *              by zfcp (it is guarranteed that it does not return via the *              adapter anymore). The buffer can then be used again. *     * returns:     sod all */voidzfcp_fsf_scsi_er_timeout_handler(unsigned long data){	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;	ZFCP_LOG_NORMAL("warning: SCSI error recovery timed out. "			"Restarting all operations on the adapter %s\n",			zfcp_get_busid_by_adapter(adapter));	debug_text_event(adapter->erp_dbf, 1, "eh_lmem_tout");	zfcp_erp_adapter_reopen(adapter, 0);	return;}/* * function:	 * * purpose:	called if an adapter failed, *		initiates adapter recovery which is done *		asynchronously * * returns:	0	- initiated action succesfully *		<0	- failed to initiate action */intzfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask){	int retval;	debug_text_event(adapter->erp_dbf, 5, "a_ro");	ZFCP_LOG_DEBUG("reopen adapter %s\n",		       zfcp_get_busid_by_adapter(adapter));	zfcp_erp_adapter_block(adapter, clear_mask);	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) {		ZFCP_LOG_DEBUG("skipped reopen of failed adapter %s\n",			       zfcp_get_busid_by_adapter(adapter));		debug_text_event(adapter->erp_dbf, 5, "a_ro_f");		/* ensure propagation of failed status to new devices */		zfcp_erp_adapter_failed(adapter);		retval = -EIO;		goto out;	}	retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,					 adapter, NULL, NULL); out:	return retval;}/* * function:	 * * purpose:	Wrappper for zfcp_erp_adapter_reopen_internal *              used to ensure the correct locking * * returns:	0	- initiated action succesfully *		<0	- failed to initiate action */intzfcp_erp_adapter_reopen(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_adapter_reopen_internal(adapter, clear_mask);	write_unlock(&adapter->erp_lock);	read_unlock_irqrestore(&zfcp_data.config_lock, flags);	return retval;}/* * function:	 * * purpose:	 * * returns: */intzfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask){	int retval;	retval = zfcp_erp_adapter_reopen(adapter,					 ZFCP_STATUS_COMMON_RUNNING |					 ZFCP_STATUS_COMMON_ERP_FAILED |					 clear_mask);	return retval;}/* * function:	 * * purpose:	 * * returns: */intzfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask){	int retval;	retval = zfcp_erp_port_reopen(port,				      ZFCP_STATUS_COMMON_RUNNING |				      ZFCP_STATUS_COMMON_ERP_FAILED |				      clear_mask);	return retval;}/* * function:	 * * purpose:	 * * returns: */intzfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask){	int retval;	retval = zfcp_erp_unit_reopen(unit,				      ZFCP_STATUS_COMMON_RUNNING |				      ZFCP_STATUS_COMMON_ERP_FAILED |				      clear_mask);	return retval;}/** * zfcp_erp_adisc - send ADISC ELS command * @port: port structure */intzfcp_erp_adisc(struct zfcp_port *port){	struct zfcp_adapter *adapter = port->adapter;	struct zfcp_send_els *send_els;	struct zfcp_ls_adisc *adisc;	void *address = NULL;	int retval = 0;	struct timer_list *timer;	send_els = kmalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC);	if (send_els == NULL)		goto nomem;	memset(send_els, 0, sizeof(*send_els));	send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);	if (send_els->req == NULL)		goto nomem;	memset(send_els->req, 0, sizeof(*send_els->req));	send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);	if (send_els->resp == NULL)		goto nomem;	memset(send_els->resp, 0, sizeof(*send_els->resp));	address = (void *) get_zeroed_page(GFP_ATOMIC);	if (address == NULL)		goto nomem;	zfcp_address_to_sg(address, send_els->req);	address += PAGE_SIZE >> 1;	zfcp_address_to_sg(address, send_els->resp);	send_els->req_count = send_els->resp_count = 1;	send_els->adapter = adapter;	send_els->port = port;	send_els->d_id = port->d_id;	send_els->handler = zfcp_erp_adisc_handler;	send_els->handler_data = (unsigned long) send_els;	adisc = zfcp_sg_to_address(send_els->req);	send_els->ls_code = adisc->code = ZFCP_LS_ADISC;	send_els->req->length = sizeof(struct zfcp_ls_adisc);	send_els->resp->length = sizeof(struct zfcp_ls_adisc_acc);	/* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports	   without FC-AL-2 capability, so we don't set it */	adisc->wwpn = fc_host_port_name(adapter->scsi_host);	adisc->wwnn = fc_host_node_name(adapter->scsi_host);	adisc->nport_id = fc_host_port_id(adapter->scsi_host);	ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "		      "(wwpn=0x%016Lx, wwnn=0x%016Lx, "		      "hard_nport_id=0x%08x, nport_id=0x%08x)\n",		      adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn,		      (wwn_t) adisc->wwnn, adisc->hard_nport_id,		      adisc->nport_id);	timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC);	if (!timer)		goto nomem;	init_timer(timer);	timer->function = zfcp_fsf_request_timeout_handler;	timer->data = (unsigned long) adapter;	timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;	send_els->timer = timer;	retval = zfcp_fsf_send_els(send_els);	if (retval != 0) {		ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "				"0x%08x on adapter %s\n", send_els->d_id,				zfcp_get_busid_by_adapter(adapter));		del_timer(send_els->timer);		goto freemem;	}	goto out; nomem:	retval = -ENOMEM; freemem:	if (address != NULL)		__free_pages(send_els->req->page, 0);	if (send_els != NULL) {		kfree(send_els->timer);		kfree(send_els->req);		kfree(send_els->resp);		kfree(send_els);	} out:	return retval;}/** * zfcp_erp_adisc_handler - handler for ADISC ELS command * @data: pointer to struct zfcp_send_els * * If ADISC failed (LS_RJT or timed out) forced reopen of the port is triggered. */voidzfcp_erp_adisc_handler(unsigned long data){	struct zfcp_send_els *send_els;	struct zfcp_port *port;	struct zfcp_adapter *adapter;	u32 d_id;	struct zfcp_ls_adisc_acc *adisc;	send_els = (struct zfcp_send_els *) data;	del_timer(send_els->timer);	adapter = send_els->adapter;	port = send_els->port;	d_id = send_els->d_id;	/* request rejected or timed out */	if (send_els->status != 0) {		ZFCP_LOG_NORMAL("ELS request rejected/timed out, "				"force physical port reopen "				"(adapter %s, port d_id=0x%08x)\n",				zfcp_get_busid_by_adapter(adapter), d_id);		debug_text_event(adapter->erp_dbf, 3, "forcreop");		if (zfcp_erp_port_forced_reopen(port, 0))			ZFCP_LOG_NORMAL("failed reopen of port "					"(adapter %s, wwpn=0x%016Lx)\n",					zfcp_get_busid_by_port(port),					port->wwpn);		goto out;	}	adisc = zfcp_sg_to_address(send_els->resp);	ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "		      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "		      "hard_nport_id=0x%08x, nport_id=0x%08x)\n",		      d_id, fc_host_port_id(adapter->scsi_host),		      (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn,		      adisc->hard_nport_id, adisc->nport_id);	/* set wwnn for port */	if (port->wwnn == 0)		port->wwnn = adisc->wwnn;	if (port->wwpn != adisc->wwpn) {		ZFCP_LOG_NORMAL("d_id assignment changed, reopening "				"port (adapter %s, wwpn=0x%016Lx, "				"adisc_resp_wwpn=0x%016Lx)\n",				zfcp_get_busid_by_port(port),				port->wwpn, (wwn_t) adisc->wwpn);		if (zfcp_erp_port_reopen(port, 0))			ZFCP_LOG_NORMAL("failed reopen of port "					"(adapter %s, wwpn=0x%016Lx)\n",					zfcp_get_busid_by_port(port),					port->wwpn);	} out:	zfcp_port_put(port);	__free_pages(send_els->req->page, 0);	kfree(send_els->timer);	kfree(send_els->req);

⌨️ 快捷键说明

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