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

📄 zfcp_aux.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
			    (ZFCP_STATUS_PORT_DID_DID, &port->status)) {				ZFCP_LOG_INFO("incoming RSCN, trying to open "					      "port 0x%016Lx\n", port->wwpn);				zfcp_erp_port_reopen(port,						     ZFCP_STATUS_COMMON_ERP_FAILED);				continue;			}			/*			 * FIXME: race: d_id might being invalidated			 * (...DID_DID reset)			 */			if ((port->d_id & range_mask)			    == (fcp_rscn_element->nport_did & range_mask)) {				ZFCP_LOG_TRACE("reopen did 0x%08x\n",					       fcp_rscn_element->nport_did);				/*				 * Unfortunately, an RSCN does not specify the				 * type of change a target underwent. We assume				 * that it makes sense to reopen the link.				 * FIXME: Shall we try to find out more about				 * the target and link state before closing it?				 * How to accomplish this? (nameserver?)				 * Where would such code be put in?				 * (inside or outside erp)				 */				ZFCP_LOG_INFO("incoming RSCN, trying to open "					      "port 0x%016Lx\n", port->wwpn);				zfcp_test_link(port);			}		}		read_unlock_irqrestore(&zfcp_data.config_lock, flags);	}}static voidzfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,			    struct fsf_status_read_buffer *status_buffer){	logi *els_logi = (logi *) status_buffer->payload;	struct zfcp_port *port;	unsigned long flags;	read_lock_irqsave(&zfcp_data.config_lock, flags);	list_for_each_entry(port, &adapter->port_list_head, list) {		if (port->wwpn == (*(wwn_t *) & els_logi->nport_wwn))			break;	}	read_unlock_irqrestore(&zfcp_data.config_lock, flags);	if (!port || (port->wwpn != (*(wwn_t *) & els_logi->nport_wwn))) {		ZFCP_LOG_DEBUG("ignored incoming PLOGI for nonexisting port "			       "with d_id 0x%08x on adapter %s\n",			       status_buffer->d_id,			       zfcp_get_busid_by_adapter(adapter));	} else {		zfcp_erp_port_forced_reopen(port, 0);	}}static voidzfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,			   struct fsf_status_read_buffer *status_buffer){	struct fcp_logo *els_logo = (struct fcp_logo *) status_buffer->payload;	struct zfcp_port *port;	unsigned long flags;	read_lock_irqsave(&zfcp_data.config_lock, flags);	list_for_each_entry(port, &adapter->port_list_head, list) {		if (port->wwpn == els_logo->nport_wwpn)			break;	}	read_unlock_irqrestore(&zfcp_data.config_lock, flags);	if (!port || (port->wwpn != els_logo->nport_wwpn)) {		ZFCP_LOG_DEBUG("ignored incoming LOGO for nonexisting port "			       "with d_id 0x%08x on adapter %s\n",			       status_buffer->d_id,			       zfcp_get_busid_by_adapter(adapter));	} else {		zfcp_erp_port_forced_reopen(port, 0);	}}static voidzfcp_fsf_incoming_els_unknown(struct zfcp_adapter *adapter,			      struct fsf_status_read_buffer *status_buffer){	ZFCP_LOG_NORMAL("warning: unknown incoming ELS 0x%08x "			"for adapter %s\n", *(u32 *) (status_buffer->payload),			zfcp_get_busid_by_adapter(adapter));}voidzfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req){	struct fsf_status_read_buffer *status_buffer;	u32 els_type;	struct zfcp_adapter *adapter;	status_buffer = (struct fsf_status_read_buffer *) fsf_req->data;	els_type = *(u32 *) (status_buffer->payload);	adapter = fsf_req->adapter;	zfcp_san_dbf_event_incoming_els(fsf_req);	if (els_type == LS_PLOGI)		zfcp_fsf_incoming_els_plogi(adapter, status_buffer);	else if (els_type == LS_LOGO)		zfcp_fsf_incoming_els_logo(adapter, status_buffer);	else if ((els_type & 0xffff0000) == LS_RSCN)		/* we are only concerned with the command, not the length */		zfcp_fsf_incoming_els_rscn(adapter, status_buffer);	else		zfcp_fsf_incoming_els_unknown(adapter, status_buffer);}/** * zfcp_gid_pn_buffers_alloc - allocate buffers for GID_PN nameserver request * @gid_pn: pointer to return pointer to struct zfcp_gid_pn_data * @pool: pointer to mempool_t if non-null memory pool is used for allocation */static intzfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool){	struct zfcp_gid_pn_data *data;	if (pool != NULL) {		data = mempool_alloc(pool, GFP_ATOMIC);		if (likely(data != NULL)) {			data->ct.pool = pool;		}	} else {		data = kmalloc(sizeof(struct zfcp_gid_pn_data), GFP_ATOMIC);	}        if (NULL == data)                return -ENOMEM;	memset(data, 0, sizeof(*data));        data->ct.req = &data->req;        data->ct.resp = &data->resp;	data->ct.req_count = data->ct.resp_count = 1;	zfcp_address_to_sg(&data->ct_iu_req, &data->req);        zfcp_address_to_sg(&data->ct_iu_resp, &data->resp);        data->req.length = sizeof(struct ct_iu_gid_pn_req);        data->resp.length = sizeof(struct ct_iu_gid_pn_resp);	*gid_pn = data;	return 0;}/** * zfcp_gid_pn_buffers_free - free buffers for GID_PN nameserver request * @gid_pn: pointer to struct zfcp_gid_pn_data which has to be freed */static voidzfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn){        if ((gid_pn->ct.pool != 0))		mempool_free(gid_pn, gid_pn->ct.pool);	else                kfree(gid_pn);	return;}/** * zfcp_ns_gid_pn_request - initiate GID_PN nameserver request * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed */intzfcp_ns_gid_pn_request(struct zfcp_erp_action *erp_action){	int ret;        struct ct_iu_gid_pn_req *ct_iu_req;        struct zfcp_gid_pn_data *gid_pn;        struct zfcp_adapter *adapter = erp_action->adapter;	ret = zfcp_gid_pn_buffers_alloc(&gid_pn, adapter->pool.data_gid_pn);	if (ret < 0) {		ZFCP_LOG_INFO("error: buffer allocation for gid_pn nameserver "			      "request failed for adapter %s\n",			      zfcp_get_busid_by_adapter(adapter));		goto out;	}	/* setup nameserver request */        ct_iu_req = zfcp_sg_to_address(gid_pn->ct.req);        ct_iu_req->header.revision = ZFCP_CT_REVISION;        ct_iu_req->header.gs_type = ZFCP_CT_DIRECTORY_SERVICE;        ct_iu_req->header.gs_subtype = ZFCP_CT_NAME_SERVER;        ct_iu_req->header.options = ZFCP_CT_SYNCHRONOUS;        ct_iu_req->header.cmd_rsp_code = ZFCP_CT_GID_PN;        ct_iu_req->header.max_res_size = ZFCP_CT_MAX_SIZE;	ct_iu_req->wwpn = erp_action->port->wwpn;        /* setup parameters for send generic command */        gid_pn->ct.port = adapter->nameserver_port;	gid_pn->ct.handler = zfcp_ns_gid_pn_handler;	gid_pn->ct.handler_data = (unsigned long) gid_pn;        gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;        gid_pn->ct.timer = &erp_action->timer;	gid_pn->port = erp_action->port;	ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp,			       erp_action);	if (ret) {		ZFCP_LOG_INFO("error: initiation of gid_pn nameserver request "                              "failed for adapter %s\n",			      zfcp_get_busid_by_adapter(adapter));                zfcp_gid_pn_buffers_free(gid_pn);	} out:	return ret;}/** * zfcp_ns_gid_pn_handler - handler for GID_PN nameserver request * @data: unsigned long, contains pointer to struct zfcp_gid_pn_data */static void zfcp_ns_gid_pn_handler(unsigned long data){	struct zfcp_port *port;        struct zfcp_send_ct *ct;	struct ct_iu_gid_pn_req *ct_iu_req;	struct ct_iu_gid_pn_resp *ct_iu_resp;        struct zfcp_gid_pn_data *gid_pn;	gid_pn = (struct zfcp_gid_pn_data *) data;	port = gid_pn->port;        ct = &gid_pn->ct;	ct_iu_req = zfcp_sg_to_address(ct->req);	ct_iu_resp = zfcp_sg_to_address(ct->resp);	if (ct->status != 0)		goto failed;	if (zfcp_check_ct_response(&ct_iu_resp->header)) {		/* FIXME: do we need some specific erp entry points */		atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);		goto failed;	}	/* paranoia */	if (ct_iu_req->wwpn != port->wwpn) {		ZFCP_LOG_NORMAL("bug: wwpn 0x%016Lx returned by nameserver "				"lookup does not match expected wwpn 0x%016Lx "				"for adapter %s\n", ct_iu_req->wwpn, port->wwpn,				zfcp_get_busid_by_port(port));		goto mismatch;	}	/* looks like a valid d_id */        port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;	atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);	ZFCP_LOG_DEBUG("adapter %s:  wwpn=0x%016Lx ---> d_id=0x%08x\n",		       zfcp_get_busid_by_port(port), port->wwpn, port->d_id);	goto out; mismatch:	ZFCP_LOG_DEBUG("CT IUs do not match:\n");	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_req,		      sizeof(struct ct_iu_gid_pn_req));	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_resp,		      sizeof(struct ct_iu_gid_pn_resp)); failed:	ZFCP_LOG_NORMAL("warning: failed gid_pn nameserver request for wwpn "			"0x%016Lx for adapter %s\n",			port->wwpn, zfcp_get_busid_by_port(port)); out:        zfcp_gid_pn_buffers_free(gid_pn);	return;}/* reject CT_IU reason codes acc. to FC-GS-4 */static const struct zfcp_rc_entry zfcp_ct_rc[] = {	{0x01, "invalid command code"},	{0x02, "invalid version level"},	{0x03, "logical error"},	{0x04, "invalid CT_IU size"},	{0x05, "logical busy"},	{0x07, "protocol error"},	{0x09, "unable to perform command request"},	{0x0b, "command not supported"},	{0x0d, "server not available"},	{0x0e, "session could not be established"},	{0xff, "vendor specific error"},	{0, NULL},};/* LS_RJT reason codes acc. to FC-FS */static const struct zfcp_rc_entry zfcp_ls_rjt_rc[] = {	{0x01, "invalid LS_Command code"},	{0x03, "logical error"},	{0x05, "logical busy"},	{0x07, "protocol error"},	{0x09, "unable to perform command request"},	{0x0b, "command not supported"},	{0x0e, "command already in progress"},	{0xff, "vendor specific error"},	{0, NULL},};/* reject reason codes according to FC-PH/FC-FS */static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = {	{0x01, "invalid D_ID"},	{0x02, "invalid S_ID"},	{0x03, "Nx_Port not available, temporary"},	{0x04, "Nx_Port not available, permament"},	{0x05, "class not supported"},	{0x06, "delimiter usage error"},	{0x07, "TYPE not supported"},	{0x08, "invalid Link_Control"},	{0x09, "invalid R_CTL field"},	{0x0a, "invalid F_CTL field"},	{0x0b, "invalid OX_ID"},	{0x0c, "invalid RX_ID"},	{0x0d, "invalid SEQ_ID"},	{0x0e, "invalid DF_CTL"},	{0x0f, "invalid SEQ_CNT"},	{0x10, "invalid parameter field"},	{0x11, "exchange error"},	{0x12, "protocol error"},	{0x13, "incorrect length"},	{0x14, "unsupported ACK"},	{0x15, "class of service not supported by entity at FFFFFE"},	{0x16, "login required"},	{0x17, "excessive sequences attempted"},	{0x18, "unable to establish exchange"},	{0x1a, "fabric path not available"},	{0x1b, "invalid VC_ID (class 4)"},	{0x1c, "invalid CS_CTL field"},	{0x1d, "insufficient resources for VC (class 4)"},	{0x1f, "invalid class of service"},	{0x20, "preemption request rejected"},	{0x21, "preemption not enabled"},	{0x22, "multicast error"},	{0x23, "multicast error terminate"},	{0x24, "process login required"},	{0xff, "vendor specific reject"},	{0, NULL},};/** * zfcp_rc_description - return description for given reaon code * @code: reason code * @rc_table: table of reason codes and descriptions */static inline const char *zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table){	const char *descr = "unknown reason code";	do {		if (code == rc_table->code) {			descr = rc_table->description;			break;		}		rc_table++;	} while (rc_table->code && rc_table->description);	return descr;}/** * zfcp_check_ct_response - evaluate reason code for CT_IU * @rjt: response payload to an CT_IU request * Return: 0 for accept CT_IU, 1 for reject CT_IU or invlid response code */intzfcp_check_ct_response(struct ct_hdr *rjt){	if (rjt->cmd_rsp_code == ZFCP_CT_ACCEPT)		return 0;	if (rjt->cmd_rsp_code != ZFCP_CT_REJECT) {		ZFCP_LOG_NORMAL("error: invalid Generic Service command/"				"response code (0x%04hx)\n",				rjt->cmd_rsp_code);		return 1;	}	ZFCP_LOG_INFO("Generic Service command rejected\n");	ZFCP_LOG_INFO("%s (0x%02x, 0x%02x, 0x%02x)\n",		      zfcp_rc_description(rjt->reason_code, zfcp_ct_rc),		      (u32) rjt->reason_code, (u32) rjt->reason_code_expl,		      (u32) rjt->vendor_unique);	return 1;}/** * zfcp_print_els_rjt - print reject parameter and description for ELS reject * @rjt_par: reject parameter acc. to FC-PH/FC-FS * @rc_table: table of reason codes and descriptions */static inline voidzfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par,		   const struct zfcp_rc_entry *rc_table){	ZFCP_LOG_INFO("%s (%02x %02x %02x %02x)\n",		      zfcp_rc_description(rjt_par->reason_code, rc_table),		      (u32) rjt_par->action, (u32) rjt_par->reason_code,		      (u32) rjt_par->reason_expl, (u32) rjt_par->vendor_unique);}/** * zfcp_fsf_handle_els_rjt - evaluate status qualifier/reason code on ELS reject * @sq: status qualifier word * @rjt_par: reject parameter as described in FC-PH and FC-FS * Return: -EROMTEIO for LS_RJT, -EREMCHG for invalid D_ID, -EIO else */intzfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par){	int ret = -EIO;	if (sq == FSF_IOSTAT_NPORT_RJT) {		ZFCP_LOG_INFO("ELS rejected (P_RJT)\n");		zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc);		/* invalid d_id */		if (rjt_par->reason_code == 0x01)			ret = -EREMCHG;	} else if (sq == FSF_IOSTAT_FABRIC_RJT) {		ZFCP_LOG_INFO("ELS rejected (F_RJT)\n");		zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc);		/* invalid d_id */		if (rjt_par->reason_code == 0x01)			ret = -EREMCHG;	} else if (sq == FSF_IOSTAT_LS_RJT) {		ZFCP_LOG_INFO("ELS rejected (LS_RJT)\n");		zfcp_print_els_rjt(rjt_par, zfcp_ls_rjt_rc);		ret = -EREMOTEIO;	} else		ZFCP_LOG_INFO("unexpected SQ: 0x%02x\n", sq);	return ret;}#undef ZFCP_LOG_AREA

⌨️ 快捷键说明

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