zfcp_fsf.c
来自「linux 内核源代码」· C语言 代码 · 共 2,033 行 · 第 1/5 页
C
2,033 行
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; ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, ZFCP_REQ_AUTO_CLEANUP, NULL, &lock_flags, &fsf_req); if (ret < 0) { ZFCP_LOG_INFO("error: creation of ELS request failed " "(adapter %s, port d_id: 0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id); goto failed_req; } sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); if (zfcp_use_one_sbal(els->req, els->req_count, els->resp, els->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(&els->req[0]); sbale[2].length = els->req[0].length; sbale[3].addr = zfcp_sg_to_address(&els->resp[0]); sbale[3].length = els->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, els->req, els->req_count, ZFCP_MAX_SBALS_PER_ELS_REQ); if (bytes <= 0) { ZFCP_LOG_INFO("error: creation of ELS request failed " "(adapter %s, port d_id: 0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id); 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, els->resp, els->resp_count, ZFCP_MAX_SBALS_PER_ELS_REQ); if (bytes <= 0) { ZFCP_LOG_INFO("error: creation of ELS request failed " "(adapter %s, port d_id: 0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id); if (bytes == 0) { ret = -ENOMEM; } else { ret = bytes; } goto failed_send; } fsf_req->qtcb->bottom.support.resp_buf_length = bytes; } else { /* reject request */ ZFCP_LOG_INFO("error: microcode does not support chained SBALs" ", ELS request too big (adapter %s, " "port d_id: 0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id); ret = -EOPNOTSUPP; goto failed_send; } /* settings in QTCB */ fsf_req->qtcb->bottom.support.d_id = d_id; fsf_req->qtcb->bottom.support.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; fsf_req->data = (unsigned long) els; sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); zfcp_san_dbf_event_els_request(fsf_req); zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); ret = zfcp_fsf_req_send(fsf_req); if (ret) { ZFCP_LOG_DEBUG("error: initiation of ELS request failed " "(adapter %s, port d_id: 0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id); goto failed_send; } ZFCP_LOG_DEBUG("ELS request initiated (adapter %s, port d_id: " "0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id); goto out; failed_send: zfcp_fsf_req_free(fsf_req); failed_req: out: write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); return ret;}/** * zfcp_fsf_send_els_handler - handler for ELS commands * @fsf_req: pointer to struct zfcp_fsf_req * * Data specific for the ELS command is passed using * fsf_req->data. There we find the pointer to struct zfcp_send_els. * Usually a specific handler for the ELS command is called which is * found in this structure. */static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req){ struct zfcp_adapter *adapter; struct zfcp_port *port; u32 d_id; struct fsf_qtcb_header *header; struct fsf_qtcb_bottom_support *bottom; struct zfcp_send_els *send_els; int retval = -EINVAL; u16 subtable, rule, counter; send_els = (struct zfcp_send_els *) fsf_req->data; adapter = send_els->adapter; port = send_els->port; d_id = send_els->d_id; header = &fsf_req->qtcb->header; bottom = &fsf_req->qtcb->bottom.support; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) goto skip_fsfstatus; switch (header->fsf_status) { case FSF_GOOD: zfcp_san_dbf_event_els_response(fsf_req); retval = 0; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: ZFCP_LOG_INFO("error: adapter %s does not support fc " "class %d.\n", zfcp_get_busid_by_adapter(adapter), ZFCP_FC_SERVICE_CLASS_DEFAULT); /* 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: debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); if (port && (send_els->ls_code != ZFCP_LS_ADISC)) zfcp_test_link(port); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; retval = zfcp_handle_els_rjt(header->fsf_status_qual.word[1], (struct zfcp_ls_rjt_par *) &header->fsf_status_qual.word[2]); break; case FSF_SQ_RETRY_IF_POSSIBLE: debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; default: ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x\n", header->fsf_status_qual.word[0]); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, (char*)header->fsf_status_qual.word, 16); } break; case FSF_ELS_COMMAND_REJECTED: ZFCP_LOG_INFO("ELS has been rejected because command filter " "prohibited sending " "(adapter: %s, port d_id: 0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id); break; case FSF_PAYLOAD_SIZE_MISMATCH: ZFCP_LOG_INFO( "ELS request size and ELS response size must be either " "both 0, or both greater than 0 " "(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); break; case FSF_REQUEST_SIZE_TOO_LARGE: ZFCP_LOG_INFO( "Length of the ELS request buffer, " "specified in QTCB bottom, " "exceeds the size of the buffers " "that have been allocated for ELS request data " "(adapter: %s, req_buf_length=%d)\n", zfcp_get_busid_by_adapter(adapter), bottom->req_buf_length); break; case FSF_RESPONSE_SIZE_TOO_LARGE: ZFCP_LOG_INFO( "Length of the ELS response buffer, " "specified in QTCB bottom, " "exceeds the size of the buffers " "that have been allocated for ELS response data " "(adapter: %s, resp_buf_length=%d)\n", zfcp_get_busid_by_adapter(adapter), bottom->resp_buf_length); break; case FSF_SBAL_MISMATCH: /* should never occure, avoided in zfcp_fsf_send_els */ 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; case FSF_ACCESS_DENIED: ZFCP_LOG_NORMAL("access denied, cannot send ELS command " "(adapter %s, port d_id=0x%06x)\n", zfcp_get_busid_by_adapter(adapter), 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"); if (port != NULL) zfcp_erp_port_access_denied(port); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; default: ZFCP_LOG_NORMAL( "bug: An unknown FSF Status was presented " "(adapter: %s, fsf_status=0x%08x)\n", zfcp_get_busid_by_adapter(adapter), 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)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; }skip_fsfstatus: send_els->status = retval; if (send_els->handler) send_els->handler(send_els->handler_data); return retval;}intzfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action){ volatile struct qdio_buffer_element *sbale; struct zfcp_fsf_req *fsf_req; struct zfcp_adapter *adapter = erp_action->adapter; unsigned long lock_flags; int retval; /* setup new FSF request */ retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, ZFCP_REQ_AUTO_CLEANUP, adapter->pool.fsf_req_erp, &lock_flags, &fsf_req); if (retval) { ZFCP_LOG_INFO("error: Could not create exchange configuration " "data request for adapter %s.\n", zfcp_get_busid_by_adapter(adapter)); write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); return retval; } sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; fsf_req->qtcb->bottom.config.feature_selection = FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING | FSF_FEATURE_NOTIFICATION_LOST | FSF_FEATURE_UPDATE_ALERT; fsf_req->erp_action = erp_action; erp_action->fsf_req = fsf_req; zfcp_erp_start_timer(fsf_req); retval = zfcp_fsf_req_send(fsf_req); write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); if (retval) { ZFCP_LOG_INFO("error: Could not send exchange configuration " "data command on the adapter %s\n", zfcp_get_busid_by_adapter(adapter)); zfcp_fsf_req_free(fsf_req); erp_action->fsf_req = NULL; } else ZFCP_LOG_DEBUG("exchange configuration data request initiated " "(adapter %s)\n", zfcp_get_busid_by_adapter(adapter)); return retval;}intzfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, struct fsf_qtcb_bottom_config *data){ volatile struct qdio_buffer_element *sbale; struct zfcp_fsf_req *fsf_req; unsigned long lock_flags; int retval; /* setup new FSF request */ retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, 0, NULL, &lock_flags, &fsf_req); if (retval) { ZFCP_LOG_INFO("error: Could not create exchange configuration " "data request for adapter %s.\n", zfcp_get_busid_by_adapter(adapter)); write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); return retval; } sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; fsf_req->qtcb->bottom.config.feature_selection = FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING | FSF_FEATURE_NOTIFICATION_LOST | FSF_FEATURE_UPDATE_ALERT; if (data) fsf_req->data = (unsigned long) data; zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(fsf_req); write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); if (retval) ZFCP_LOG_INFO("error: Could not send exchange config
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?