📄 zfcp_fsf.c
字号:
}static intzfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req){ struct fsf_status_read_buffer *status_buffer; struct zfcp_adapter *adapter; struct zfcp_port *port; unsigned long flags; status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; adapter = fsf_req->adapter; read_lock_irqsave(&zfcp_data.config_lock, flags); list_for_each_entry(port, &adapter->port_list_head, list) if (port->d_id == (status_buffer->d_id & ZFCP_DID_MASK)) break; read_unlock_irqrestore(&zfcp_data.config_lock, flags); if (!port || (port->d_id != (status_buffer->d_id & ZFCP_DID_MASK))) { ZFCP_LOG_NORMAL("bug: Reopen port indication received for" "nonexisting port with d_id 0x%08x on " "adapter %s. Ignored.\n", status_buffer->d_id & ZFCP_DID_MASK, zfcp_get_busid_by_adapter(adapter)); goto out; } switch (status_buffer->status_subtype) { case FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT: debug_text_event(adapter->erp_dbf, 3, "unsol_pc_phys:"); zfcp_erp_port_reopen(port, 0); break; case FSF_STATUS_READ_SUB_ERROR_PORT: debug_text_event(adapter->erp_dbf, 1, "unsol_pc_err:"); zfcp_erp_port_shutdown(port, 0); break; default: debug_text_event(adapter->erp_dbf, 0, "unsol_unk_sub:"); debug_exception(adapter->erp_dbf, 0, &status_buffer->status_subtype, sizeof (u32)); ZFCP_LOG_NORMAL("bug: Undefined status subtype received " "for a reopen indication on port with " "d_id 0x%08x on the adapter %s. " "Ignored. (debug info 0x%x)\n", status_buffer->d_id, zfcp_get_busid_by_adapter(adapter), status_buffer->status_subtype); } out: return 0;}/* * function: zfcp_fsf_status_read_handler * * purpose: is called for finished Open Port command * * returns: */static intzfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req){ int retval = 0; struct zfcp_adapter *adapter = fsf_req->adapter; struct fsf_status_read_buffer *status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer); mempool_free(status_buffer, adapter->pool.data_status_read); zfcp_fsf_req_free(fsf_req); goto out; } zfcp_hba_dbf_event_fsf_unsol("read", adapter, status_buffer); switch (status_buffer->status_type) { case FSF_STATUS_READ_PORT_CLOSED: zfcp_fsf_status_read_port_closed(fsf_req); break; case FSF_STATUS_READ_INCOMING_ELS: zfcp_fsf_incoming_els(fsf_req); break; case FSF_STATUS_READ_SENSE_DATA_AVAIL: ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n", zfcp_get_busid_by_adapter(adapter)); break; case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: ZFCP_LOG_NORMAL("Bit error threshold data received:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) status_buffer, sizeof (struct fsf_status_read_buffer)); break; case FSF_STATUS_READ_LINK_DOWN: switch (status_buffer->status_subtype) { case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: ZFCP_LOG_INFO("Physical link to adapter %s is down\n", zfcp_get_busid_by_adapter(adapter)); zfcp_fsf_link_down_info_eval(adapter, (struct fsf_link_down_info *) &status_buffer->payload); break; case FSF_STATUS_READ_SUB_FDISC_FAILED: ZFCP_LOG_INFO("Local link to adapter %s is down " "due to failed FDISC login\n", zfcp_get_busid_by_adapter(adapter)); zfcp_fsf_link_down_info_eval(adapter, (struct fsf_link_down_info *) &status_buffer->payload); break; case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: ZFCP_LOG_INFO("Local link to adapter %s is down " "due to firmware update on adapter\n", zfcp_get_busid_by_adapter(adapter)); zfcp_fsf_link_down_info_eval(adapter, NULL); break; default: ZFCP_LOG_INFO("Local link to adapter %s is down " "due to unknown reason\n", zfcp_get_busid_by_adapter(adapter)); zfcp_fsf_link_down_info_eval(adapter, NULL); }; break; case FSF_STATUS_READ_LINK_UP: ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. " "Restarting operations on this adapter\n", zfcp_get_busid_by_adapter(adapter)); /* All ports should be marked as ready to run again */ zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | ZFCP_STATUS_COMMON_ERP_FAILED); break; case FSF_STATUS_READ_CFDC_UPDATED: ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n", zfcp_get_busid_by_adapter(adapter)); zfcp_erp_adapter_access_changed(adapter); break; case FSF_STATUS_READ_CFDC_HARDENED: switch (status_buffer->status_subtype) { case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE: ZFCP_LOG_NORMAL("CFDC of adapter %s saved on SE\n", zfcp_get_busid_by_adapter(adapter)); break; case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2: ZFCP_LOG_NORMAL("CFDC of adapter %s has been copied " "to the secondary SE\n", zfcp_get_busid_by_adapter(adapter)); break; default: ZFCP_LOG_NORMAL("CFDC of adapter %s has been hardened\n", zfcp_get_busid_by_adapter(adapter)); } break; case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: debug_text_event(adapter->erp_dbf, 2, "unsol_features:"); ZFCP_LOG_INFO("List of supported features on adapter %s has " "been changed from 0x%08X to 0x%08X\n", zfcp_get_busid_by_adapter(adapter), *(u32*) (status_buffer->payload + 4), *(u32*) (status_buffer->payload)); adapter->adapter_features = *(u32*) status_buffer->payload; break; default: ZFCP_LOG_NORMAL("warning: An unsolicited status packet of unknown " "type was received (debug info 0x%x)\n", status_buffer->status_type); ZFCP_LOG_DEBUG("Dump of status_read_buffer %p:\n", status_buffer); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) status_buffer, sizeof (struct fsf_status_read_buffer)); break; } mempool_free(status_buffer, adapter->pool.data_status_read); zfcp_fsf_req_free(fsf_req); /* * recycle buffer and start new request repeat until outbound * queue is empty or adapter shutdown is requested */ /* * FIXME(qdio): * we may wait in the req_create for 5s during shutdown, so * qdio_cleanup will have to wait at least that long before returning * with failure to allow us a proper cleanup under all circumstances */ /* * FIXME: * allocation failure possible? (Is this code needed?) */ retval = zfcp_fsf_status_read(adapter, 0); if (retval < 0) { ZFCP_LOG_INFO("Failed to create unsolicited status read " "request for the adapter %s.\n", zfcp_get_busid_by_adapter(adapter)); /* temporary fix to avoid status read buffer shortage */ adapter->status_read_failed++; if ((ZFCP_STATUS_READS_RECOM - adapter->status_read_failed) < ZFCP_STATUS_READ_FAILED_THRESHOLD) { ZFCP_LOG_INFO("restart adapter %s due to status read " "buffer shortage\n", zfcp_get_busid_by_adapter(adapter)); zfcp_erp_adapter_reopen(adapter, 0); } } out: return retval;}/* * function: zfcp_fsf_abort_fcp_command * * purpose: tells FSF to abort a running SCSI command * * returns: address of initiated FSF request * NULL - request could not be initiated * * FIXME(design): should be watched by a timeout !!! * FIXME(design) shouldn't this be modified to return an int * also...don't know how though */struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, struct zfcp_adapter *adapter, struct zfcp_unit *unit, int req_flags){ volatile struct qdio_buffer_element *sbale; unsigned long lock_flags; struct zfcp_fsf_req *fsf_req = NULL; int retval = 0; /* setup new FSF request */ retval = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, req_flags, adapter->pool.fsf_req_abort, &lock_flags, &fsf_req); if (retval < 0) { ZFCP_LOG_INFO("error: Failed to create an abort command " "request for lun 0x%016Lx on port 0x%016Lx " "on adapter %s.\n", unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_adapter(adapter)); goto out; } 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->data = (unsigned long) unit; /* set handles of unit and its parent port in QTCB */ fsf_req->qtcb->header.lun_handle = unit->handle; fsf_req->qtcb->header.port_handle = unit->port->handle; /* set handle of request which should be aborted */ fsf_req->qtcb->bottom.support.req_handle = (u64) old_req_id; /* start QDIO request for this FSF request */ zfcp_fsf_start_scsi_er_timer(adapter); retval = zfcp_fsf_req_send(fsf_req, NULL); if (retval) { del_timer(&adapter->scsi_er_timer); ZFCP_LOG_INFO("error: Failed to send abort command request " "on adapter %s, port 0x%016Lx, unit 0x%016Lx\n", zfcp_get_busid_by_adapter(adapter), unit->port->wwpn, unit->fcp_lun); zfcp_fsf_req_free(fsf_req); fsf_req = NULL; goto out; } ZFCP_LOG_DEBUG("Abort FCP Command request initiated " "(adapter%s, port d_id=0x%08x, " "unit x%016Lx, old_req_id=0x%lx)\n", zfcp_get_busid_by_adapter(adapter), unit->port->d_id, unit->fcp_lun, old_req_id); out: write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); return fsf_req;}/* * function: zfcp_fsf_abort_fcp_command_handler * * purpose: is called for finished Abort FCP Command request * * returns: */static intzfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req){ int retval = -EINVAL; struct zfcp_unit *unit; unsigned char status_qual = new_fsf_req->qtcb->header.fsf_status_qual.word[0]; del_timer(&new_fsf_req->adapter->scsi_er_timer); if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { /* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */ goto skip_fsfstatus; } unit = (struct zfcp_unit *) new_fsf_req->data; /* evaluate FSF status in QTCB */ switch (new_fsf_req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: if (status_qual >> 4 != status_qual % 0xf) { debug_text_event(new_fsf_req->adapter->erp_dbf, 3, "fsf_s_phand_nv0"); /* * In this case a command that was sent prior to a port * reopen was aborted (handles are different). This is * fine. */ } else { ZFCP_LOG_INFO("Temporary port identifier 0x%x for " "port 0x%016Lx on adapter %s invalid. " "This may happen occasionally.\n", unit->port->handle, unit->port->wwpn, zfcp_get_busid_by_unit(unit)); ZFCP_LOG_INFO("status qualifier:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, (char *) &new_fsf_req->qtcb->header. fsf_status_qual, sizeof (union fsf_status_qual)); /* Let's hope this sorts out the mess */ debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_phand_nv1"); zfcp_erp_adapter_reopen(unit->port->adapter, 0); new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; } break; case FSF_LUN_HANDLE_NOT_VALID: if (status_qual >> 4 != status_qual % 0xf) { /* 2 */ debug_text_event(new_fsf_req->adapter->erp_dbf, 3, "fsf_s_lhand_nv0"); /* * In this case a command that was sent prior to a unit * reopen was aborted (handles are different). * This is fine. */ } else { ZFCP_LOG_INFO ("Warning: Temporary LUN identifier 0x%x of LUN " "0x%016Lx on port 0x%016Lx on adapter %s is " "invalid. This may happen in rare cases. " "Trying to re-establish link.\n", unit->handle, unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_unit(unit)); ZFCP_LOG_DEBUG("Status qualifier data:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) &new_fsf_req->qtcb->header. fsf_status_qual, sizeof (union fsf_status_qual)); /* Let's hope this sorts out the mess */ debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lhand_nv1"); zfcp_erp_port_reopen(unit->port, 0); new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; } break; case FSF_FCP_COMMAND_DOES_NOT_EXIST: retval = 0; debug_text_event(new_fsf_req->adapter->erp_dbf, 3, "fsf_s_no_exist"); new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED; break; case FSF_PORT_BOXED: ZFCP_LOG_INFO("Remote port 0x%016Lx on adapter %s needs to " "be reopened\n", unit->port->wwpn, zfcp_get_busid_by_unit(unit)); debug_text_event(new_fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed"); zfcp_erp_port_boxed(unit->port); new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; case FSF_LUN_BOXED: ZFCP_LOG_INFO( "unit 0x%016Lx on port 0x%016Lx on adapter %s needs "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -