zfcp_erp.c
来自「linux 内核源代码」· C语言 代码 · 共 2,247 行 · 第 1/5 页
C
2,247 行
if (set_or_clear == ZFCP_SET) { atomic_set_mask(mask, &unit->status); debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_s"); } else { atomic_clear_mask(mask, &unit->status); if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) { atomic_set(&unit->erp_counter, 0); } debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_c"); } debug_event(unit->port->adapter->erp_dbf, 3, &unit->fcp_lun, sizeof (fcp_lun_t)); debug_event(unit->port->adapter->erp_dbf, 3, &mask, sizeof (u32));}/* * function: * * purpose: Wrappper for zfcp_erp_port_reopen_all_internal * used to ensure the correct locking * * returns: 0 - initiated action successfully * <0 - failed to initiate action */intzfcp_erp_port_reopen_all(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_port_reopen_all_internal(adapter, clear_mask); write_unlock(&adapter->erp_lock); read_unlock_irqrestore(&zfcp_data.config_lock, flags); return retval;}static intzfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask){ int retval = 0; struct zfcp_port *port; list_for_each_entry(port, &adapter->port_list_head, list) if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) zfcp_erp_port_reopen_internal(port, clear_mask); return retval;}/* * function: * * purpose: * * returns: FIXME */static intzfcp_erp_unit_reopen_all_internal(struct zfcp_port *port, int clear_mask){ int retval = 0; struct zfcp_unit *unit; list_for_each_entry(unit, &port->unit_list_head, list) zfcp_erp_unit_reopen_internal(unit, clear_mask); return retval;}/* * function: * * purpose: this routine executes the 'Reopen Adapter' action * (the entire action is processed synchronously, since * there are no actions which might be run concurrently * per definition) * * returns: ZFCP_ERP_SUCCEEDED - action finished successfully * ZFCP_ERP_FAILED - action finished unsuccessfully */static intzfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action){ int retval; struct zfcp_adapter *adapter = erp_action->adapter; retval = zfcp_erp_adapter_strategy_close(erp_action); if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) retval = ZFCP_ERP_EXIT; else retval = zfcp_erp_adapter_strategy_open(erp_action); debug_text_event(adapter->erp_dbf, 3, "a_ast/ret"); debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int)); debug_event(adapter->erp_dbf, 3, &retval, sizeof (int)); if (retval == ZFCP_ERP_FAILED) { ZFCP_LOG_INFO("Waiting to allow the adapter %s " "to recover itself\n", zfcp_get_busid_by_adapter(adapter)); msleep(jiffies_to_msecs(ZFCP_TYPE2_RECOVERY_TIME)); } return retval;}/* * function: * * purpose: * * returns: ZFCP_ERP_SUCCEEDED - action finished successfully * ZFCP_ERP_FAILED - action finished unsuccessfully */static intzfcp_erp_adapter_strategy_close(struct zfcp_erp_action *erp_action){ int retval; atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->adapter->status); retval = zfcp_erp_adapter_strategy_generic(erp_action, 1); atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->adapter->status); return retval;}/* * function: * * purpose: * * returns: ZFCP_ERP_SUCCEEDED - action finished successfully * ZFCP_ERP_FAILED - action finished unsuccessfully */static intzfcp_erp_adapter_strategy_open(struct zfcp_erp_action *erp_action){ int retval; atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->adapter->status); retval = zfcp_erp_adapter_strategy_generic(erp_action, 0); atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->adapter->status); return retval;}/* * function: zfcp_register_adapter * * purpose: allocate the irq associated with this devno and register * the FSF adapter with the SCSI stack * * returns: */static intzfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close){ int retval = ZFCP_ERP_SUCCEEDED; if (close) goto close_only; retval = zfcp_erp_adapter_strategy_open_qdio(erp_action); if (retval != ZFCP_ERP_SUCCEEDED) goto failed_qdio; retval = zfcp_erp_adapter_strategy_open_fsf(erp_action); if (retval != ZFCP_ERP_SUCCEEDED) goto failed_openfcp; atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &erp_action->adapter->status); goto out; close_only: atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &erp_action->adapter->status); failed_openfcp: zfcp_close_fsf(erp_action->adapter); failed_qdio: atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | ZFCP_STATUS_ADAPTER_XPORT_OK, &erp_action->adapter->status); out: return retval;}/* * function: zfcp_qdio_init * * purpose: setup QDIO operation for specified adapter * * returns: 0 - successful setup * !0 - failed setup */static intzfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action){ int retval; int i; volatile struct qdio_buffer_element *sbale; struct zfcp_adapter *adapter = erp_action->adapter; if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) { ZFCP_LOG_NORMAL("bug: second attempt to set up QDIO on " "adapter %s\n", zfcp_get_busid_by_adapter(adapter)); goto failed_sanity; } if (qdio_establish(&adapter->qdio_init_data) != 0) { ZFCP_LOG_INFO("error: establishment of QDIO queues failed " "on adapter %s\n", zfcp_get_busid_by_adapter(adapter)); goto failed_qdio_establish; } debug_text_event(adapter->erp_dbf, 3, "qdio_est"); if (qdio_activate(adapter->ccw_device, 0) != 0) { ZFCP_LOG_INFO("error: activation of QDIO queues failed " "on adapter %s\n", zfcp_get_busid_by_adapter(adapter)); goto failed_qdio_activate; } debug_text_event(adapter->erp_dbf, 3, "qdio_act"); /* * put buffers into response queue, */ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) { sbale = &(adapter->response_queue.buffer[i]->element[0]); sbale->length = 0; sbale->flags = SBAL_FLAGS_LAST_ENTRY; sbale->addr = NULL; } ZFCP_LOG_TRACE("calling do_QDIO on adapter %s (flags=0x%x, " "queue_no=%i, index_in_queue=%i, count=%i)\n", zfcp_get_busid_by_adapter(adapter), QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q); retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q, NULL); if (retval) { ZFCP_LOG_NORMAL("bug: setup of QDIO failed (retval=%d)\n", retval); goto failed_do_qdio; } else { adapter->response_queue.free_index = 0; atomic_set(&adapter->response_queue.free_count, 0); ZFCP_LOG_DEBUG("%i buffers successfully enqueued to " "response queue\n", QDIO_MAX_BUFFERS_PER_Q); } /* set index of first avalable SBALS / number of available SBALS */ adapter->request_queue.free_index = 0; atomic_set(&adapter->request_queue.free_count, QDIO_MAX_BUFFERS_PER_Q); adapter->request_queue.distance_from_int = 0; /* initialize waitqueue used to wait for free SBALs in requests queue */ init_waitqueue_head(&adapter->request_wq); /* ok, we did it - skip all cleanups for different failures */ atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); retval = ZFCP_ERP_SUCCEEDED; goto out; failed_do_qdio: /* NOP */ failed_qdio_activate: debug_text_event(adapter->erp_dbf, 3, "qdio_down1a"); while (qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS) msleep(1000); debug_text_event(adapter->erp_dbf, 3, "qdio_down1b"); failed_qdio_establish: failed_sanity: retval = ZFCP_ERP_FAILED; out: return retval;}static intzfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action){ int retval; retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); if (retval == ZFCP_ERP_FAILED) return ZFCP_ERP_FAILED; retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); if (retval == ZFCP_ERP_FAILED) return ZFCP_ERP_FAILED; return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);}static intzfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action){ int retval = ZFCP_ERP_SUCCEEDED; int retries; int sleep = ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP; struct zfcp_adapter *adapter = erp_action->adapter; atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); for (retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES; retries; retries--) { atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, &adapter->status); ZFCP_LOG_DEBUG("Doing exchange config data\n"); write_lock_irq(&adapter->erp_lock); zfcp_erp_action_to_running(erp_action); write_unlock_irq(&adapter->erp_lock); if (zfcp_fsf_exchange_config_data(erp_action)) { retval = ZFCP_ERP_FAILED; debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf"); ZFCP_LOG_INFO("error: initiation of exchange of " "configuration data failed for " "adapter %s\n", zfcp_get_busid_by_adapter(adapter)); break; } debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok"); ZFCP_LOG_DEBUG("Xchange underway\n"); /* * Why this works: * Both the normal completion handler as well as the timeout * handler will do an 'up' when the 'exchange config data' * request completes or times out. Thus, the signal to go on * won't be lost utilizing this semaphore. * Furthermore, this 'adapter_reopen' action is * guaranteed to be the only action being there (highest action * which prevents other actions from being created). * Resulting from that, the wake signal recognized here * _must_ be the one belonging to the 'exchange config * data' request. */ down(&adapter->erp_ready_sem); if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { ZFCP_LOG_INFO("error: exchange of configuration data " "for adapter %s timed out\n", zfcp_get_busid_by_adapter(adapter)); break; } if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, &adapter->status)) break; ZFCP_LOG_DEBUG("host connection still initialising... " "waiting and retrying...\n"); /* sleep a little bit before retry */ msleep(jiffies_to_msecs(sleep)); sleep *= 2; } atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, &adapter->status); if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status)) { ZFCP_LOG_INFO("error: exchange of configuration data for " "adapter %s failed\n", zfcp_get_busid_by_adapter(adapter)); retval = ZFCP_ERP_FAILED; } return retval;}static intzfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action){ int ret; struct zfcp_adapter *adapter; adapter = erp_action->adapter; atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); write_lock_irq(&adapter->erp_lock); zfcp_erp_action_to_running(erp_action); write_unlock_irq(&adapter->erp_lock); ret = zfcp_fsf_exchange_port_data(erp_action); if (ret == -EOPNOTSUPP) { debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); return ZFCP_ERP_SUCCEEDED; } else if (ret) { debug_text_event(adapter->erp_dbf, 3, "a_xport_failed"); return ZFCP_ERP_FAILED; } debug_text_event(adapter->erp_dbf, 6, "a_xport_ok"); ret = ZFCP_ERP_SUCCEEDED; down(&adapter->erp_ready_sem); if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { ZFCP_LOG_INFO("error: exchange port data timed out (adapter " "%s)\n", zfcp_get_busid_by_adapter(adapter)); ret = ZFCP_ERP_FAILED; } /* don't treat as error for the sake of compatibility */ if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) ZFCP_LOG_INFO("warning: exchange port data failed (adapter " "%s\n", zfcp_get_busid_by_adapter(adapter)); return ret;}static intzfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action *erp_action){ int retval = ZFCP_ERP_SUCCEEDED; int temp_ret; struct zfcp_adapter *adapter = erp_action->adapter; int i; adapter->status_read_failed = 0; for (i = 0; i < ZFCP_STATUS_READS_RECOM; i++) { temp_ret = zfcp_fsf_status_read(adapter, ZFCP_WAIT_FOR_SBAL); if (temp_ret < 0) { ZFCP_LOG_INFO("error: set-up of unsolicited status " "notification failed on adapter %s\n", zfcp_get_busid_by_adapter(adapter)); retval = ZFCP_ERP_FAILED; i--; break; } } return retva
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?