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

📄 zfcp_fsf.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
                        "to be reopened\n",                        unit->fcp_lun, unit->port->wwpn,                        zfcp_get_busid_by_unit(unit));                debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");		zfcp_erp_unit_boxed(unit);                new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR                        | ZFCP_STATUS_FSFREQ_RETRY;                break;	case FSF_ADAPTER_STATUS_AVAILABLE:		switch (new_fsf_req->qtcb->header.fsf_status_qual.word[0]) {		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:			debug_text_event(new_fsf_req->adapter->erp_dbf, 1,					 "fsf_sq_ltest");			zfcp_test_link(unit->port);			new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;			break;		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:			/* SCSI stack will escalate */			debug_text_event(new_fsf_req->adapter->erp_dbf, 1,					 "fsf_sq_ulp");			new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;			break;		default:			ZFCP_LOG_NORMAL			    ("bug: Wrong status qualifier 0x%x arrived.\n",			     new_fsf_req->qtcb->header.fsf_status_qual.word[0]);			debug_text_event(new_fsf_req->adapter->erp_dbf, 0,					 "fsf_sq_inval:");			debug_exception(new_fsf_req->adapter->erp_dbf, 0,					&new_fsf_req->qtcb->header.					fsf_status_qual.word[0], sizeof (u32));			break;		}		break;	case FSF_GOOD:		retval = 0;		new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;		break;	default:		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "				"(debug info 0x%x)\n",				new_fsf_req->qtcb->header.fsf_status);		debug_text_event(new_fsf_req->adapter->erp_dbf, 0,				 "fsf_s_inval:");		debug_exception(new_fsf_req->adapter->erp_dbf, 0,				&new_fsf_req->qtcb->header.fsf_status,				sizeof (u32));		break;	} skip_fsfstatus:	return retval;}/** * zfcp_use_one_sbal - checks whether req buffer and resp bother each fit into *	one SBALE * Two scatter-gather lists are passed, one for the reqeust and one for the * response. */static inline intzfcp_use_one_sbal(struct scatterlist *req, int req_count,                  struct scatterlist *resp, int resp_count){        return ((req_count == 1) &&		(resp_count == 1) &&                (((unsigned long) zfcp_sg_to_address(&req[0]) &		  PAGE_MASK) ==		 ((unsigned long) (zfcp_sg_to_address(&req[0]) +				   req[0].length - 1) & PAGE_MASK)) &&                (((unsigned long) zfcp_sg_to_address(&resp[0]) &		  PAGE_MASK) ==                 ((unsigned long) (zfcp_sg_to_address(&resp[0]) +				   resp[0].length - 1) & PAGE_MASK)));}/** * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS) * @ct: pointer to struct zfcp_send_ct which conatins all needed data for *	the request * @pool: pointer to memory pool, if non-null this pool is used to allocate *	a struct zfcp_fsf_req * @erp_action: pointer to erp_action, if non-null the Generic Service request *	is sent within error recovery */intzfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,		 struct zfcp_erp_action *erp_action){	volatile struct qdio_buffer_element *sbale;	struct zfcp_port *port;	struct zfcp_adapter *adapter;        struct zfcp_fsf_req *fsf_req;        unsigned long lock_flags;        int bytes;	int ret = 0;	port = ct->port;	adapter = port->adapter;	ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC,				  ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,				  pool, &lock_flags, &fsf_req);	if (ret < 0) {                ZFCP_LOG_INFO("error: Could not create CT request (FC-GS) for "			      "adapter: %s\n",			      zfcp_get_busid_by_adapter(adapter));		goto failed_req;	}        if (erp_action != NULL) {                erp_action->fsf_req = fsf_req;                fsf_req->erp_action = erp_action;        }	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);        if (zfcp_use_one_sbal(ct->req, ct->req_count,                              ct->resp, ct->resp_count)){                /* both request buffer and response buffer                   fit into one sbale each */                sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;                sbale[2].addr = zfcp_sg_to_address(&ct->req[0]);                sbale[2].length = ct->req[0].length;                sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]);                sbale[3].length = ct->resp[0].length;                sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;	} else if (adapter->adapter_features &                   FSF_FEATURE_ELS_CT_CHAINED_SBALS) {                /* try to use chained SBALs */                bytes = zfcp_qdio_sbals_from_sg(fsf_req,                                                SBAL_FLAGS0_TYPE_WRITE_READ,                                                ct->req, ct->req_count,                                                ZFCP_MAX_SBALS_PER_CT_REQ);                if (bytes <= 0) {                        ZFCP_LOG_INFO("error: creation of CT request failed "				      "on adapter %s\n",				      zfcp_get_busid_by_adapter(adapter));                        if (bytes == 0)                                ret = -ENOMEM;                        else                                ret = bytes;                        goto failed_send;                }                fsf_req->qtcb->bottom.support.req_buf_length = bytes;                fsf_req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;                bytes = zfcp_qdio_sbals_from_sg(fsf_req,                                                SBAL_FLAGS0_TYPE_WRITE_READ,                                                ct->resp, ct->resp_count,                                                ZFCP_MAX_SBALS_PER_CT_REQ);                if (bytes <= 0) {                        ZFCP_LOG_INFO("error: creation of CT request failed "				      "on adapter %s\n",				      zfcp_get_busid_by_adapter(adapter));                        if (bytes == 0)                                ret = -ENOMEM;                        else                                ret = bytes;                        goto failed_send;                }                fsf_req->qtcb->bottom.support.resp_buf_length = bytes;        } else {                /* reject send generic request */		ZFCP_LOG_INFO(			"error: microcode does not support chained SBALs,"                        "CT request too big (adapter %s)\n",			zfcp_get_busid_by_adapter(adapter));                ret = -EOPNOTSUPP;                goto failed_send;        }	/* settings in QTCB */	fsf_req->qtcb->header.port_handle = port->handle;	fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;	fsf_req->qtcb->bottom.support.timeout = ct->timeout;        fsf_req->data = (unsigned long) ct;	zfcp_san_dbf_event_ct_request(fsf_req);	/* start QDIO request for this FSF request */	ret = zfcp_fsf_req_send(fsf_req, ct->timer);	if (ret) {		ZFCP_LOG_DEBUG("error: initiation of CT request failed "			       "(adapter %s, port 0x%016Lx)\n",			       zfcp_get_busid_by_adapter(adapter), port->wwpn);		goto failed_send;	}	ZFCP_LOG_DEBUG("CT request initiated (adapter %s, port 0x%016Lx)\n",		       zfcp_get_busid_by_adapter(adapter), port->wwpn);	goto out; failed_send:	zfcp_fsf_req_free(fsf_req);        if (erp_action != NULL) {                erp_action->fsf_req = NULL;        } failed_req: out:        write_unlock_irqrestore(&adapter->request_queue.queue_lock,				lock_flags);	return ret;}/** * zfcp_fsf_send_ct_handler - handler for Generic Service requests * @fsf_req: pointer to struct zfcp_fsf_req * * Data specific for the Generic Service request is passed using * fsf_req->data. There we find the pointer to struct zfcp_send_ct. * Usually a specific handler for the CT request is called which is * found in this structure. */static intzfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req){	struct zfcp_port *port;	struct zfcp_adapter *adapter;	struct zfcp_send_ct *send_ct;	struct fsf_qtcb_header *header;	struct fsf_qtcb_bottom_support *bottom;	int retval = -EINVAL;	u16 subtable, rule, counter;	adapter = fsf_req->adapter;	send_ct = (struct zfcp_send_ct *) fsf_req->data;	port = send_ct->port;	header = &fsf_req->qtcb->header;	bottom = &fsf_req->qtcb->bottom.support;	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)		goto skip_fsfstatus;	/* evaluate FSF status in QTCB */	switch (header->fsf_status) {        case FSF_GOOD:		zfcp_san_dbf_event_ct_response(fsf_req);                retval = 0;		break;        case FSF_SERVICE_CLASS_NOT_SUPPORTED:		if (adapter->fc_service_class <= 3) {			ZFCP_LOG_INFO("error: adapter %s does not support fc "				      "class %d.\n",				      zfcp_get_busid_by_port(port),				      adapter->fc_service_class);		} else {			ZFCP_LOG_INFO("bug: The fibre channel class at the "				      "adapter %s is invalid. "				      "(debug info %d)\n",				      zfcp_get_busid_by_port(port),				      adapter->fc_service_class);		}		/* stop operation for this adapter */		debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");		zfcp_erp_adapter_shutdown(adapter, 0);		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;		break;        case FSF_ADAPTER_STATUS_AVAILABLE:                switch (header->fsf_status_qual.word[0]){                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:			/* reopening link to port */			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");			zfcp_test_link(port);			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;			break;                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:			/* ERP strategy will escalate */			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;			break;                default:			ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x "				      "arrived.\n",				      header->fsf_status_qual.word[0]);			break;                }                break;	case FSF_ACCESS_DENIED:		ZFCP_LOG_NORMAL("access denied, cannot send generic service "				"command (adapter %s, port d_id=0x%08x)\n",				zfcp_get_busid_by_port(port), port->d_id);		for (counter = 0; counter < 2; counter++) {			subtable = header->fsf_status_qual.halfword[counter * 2];			rule = header->fsf_status_qual.halfword[counter * 2 + 1];			switch (subtable) {			case FSF_SQ_CFDC_SUBTABLE_OS:			case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN:			case FSF_SQ_CFDC_SUBTABLE_PORT_DID:			case FSF_SQ_CFDC_SUBTABLE_LUN:       				ZFCP_LOG_INFO("Access denied (%s rule %d)\n",					zfcp_act_subtable_type[subtable], rule);				break;			}		}		debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");		zfcp_erp_port_access_denied(port);		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;		break;        case FSF_GENERIC_COMMAND_REJECTED:		ZFCP_LOG_INFO("generic service command rejected "			      "(adapter %s, port d_id=0x%08x)\n",			      zfcp_get_busid_by_port(port), port->d_id);		ZFCP_LOG_INFO("status qualifier:\n");		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,			      (char *) &header->fsf_status_qual,			      sizeof (union fsf_status_qual));		debug_text_event(adapter->erp_dbf, 1, "fsf_s_gcom_rej");		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;		break;        case FSF_PORT_HANDLE_NOT_VALID:		ZFCP_LOG_DEBUG("Temporary port identifier 0x%x for port "			       "0x%016Lx on adapter %s invalid. This may "			       "happen occasionally.\n", port->handle,			       port->wwpn, zfcp_get_busid_by_port(port));		ZFCP_LOG_INFO("status qualifier:\n");		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,			      (char *) &header->fsf_status_qual,			      sizeof (union fsf_status_qual));		debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv");		zfcp_erp_adapter_reopen(adapter, 0);		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;		break;        case FSF_PORT_BOXED:		ZFCP_LOG_INFO("port needs to be reopened "			      "(adapter %s, port d_id=0x%08x)\n",			      zfcp_get_busid_by_port(port), port->d_id);		debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");		zfcp_erp_port_boxed(port);		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR		    | ZFCP_STATUS_FSFREQ_RETRY;		break;	/* following states should never occure, all cases avoided	   in zfcp_fsf_send_ct - but who knows ... */	case FSF_PAYLOAD_SIZE_MISMATCH:		ZFCP_LOG_INFO("payload size mismatch (adapter: %s, "			      "req_buf_length=%d, resp_buf_length=%d)\n",			      zfcp_get_busid_by_adapter(adapter),			      bottom->req_buf_length, bottom->resp_buf_length);		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;		break;	case FSF_REQUEST_SIZE_TOO_LARGE:		ZFCP_LOG_INFO("request size too large (adapter: %s, "			      "req_buf_length=%d)\n",			      zfcp_get_busid_by_adapter(adapter),			      bottom->req_buf_length);		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;		break;	case FSF_RESPONSE_SIZE_TOO_LARGE:		ZFCP_LOG_INFO("response size too large (adapter: %s, "			      "resp_buf_length=%d)\n",			      zfcp_get_busid_by_adapter(adapter),			      bottom->resp_buf_length);		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;		break;	case FSF_SBAL_MISMATCH:		ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, "			      "resp_buf_length=%d)\n",			      zfcp_get_busid_by_adapter(adapter),			      bottom->req_buf_length, bottom->resp_buf_length);		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;		break;       default:		ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "				"(debug info 0x%x)\n", header->fsf_status);		debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:");		debug_exception(adapter->erp_dbf, 0,				&header->fsf_status_qual.word[0], sizeof (u32));		break;	}skip_fsfstatus:	send_ct->status = retval;	if (send_ct->handler != NULL)		send_ct->handler(send_ct->handler_data);	return retval;}/** * zfcp_fsf_send_els - initiate an ELS command (FC-FS) * @els: pointer to struct zfcp_send_els which contains all needed data for *	the command. */intzfcp_fsf_send_els(struct zfcp_send_els *els){	volatile struct qdio_buffer_element *sbale;	struct zfcp_fsf_req *fsf_req;	u32 d_id;	struct zfcp_adapter *adapter;	unsigned long lock_flags;        int bytes;	int ret = 0;	d_id = els->d_id;	adapter = els->adapter;

⌨️ 快捷键说明

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