📄 zfcp_erp.c
字号:
if (set_or_clear == ZFCP_SET) { atomic_set_mask(mask, &port->status); debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_s"); } else { atomic_clear_mask(mask, &port->status); if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) atomic_set(&port->erp_counter, 0); debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_c"); } debug_event(port->adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t)); debug_event(port->adapter->erp_dbf, 3, &mask, sizeof (u32)); /* Modify status of all underlying devices, only pass common mask */ if (common_mask) list_for_each_entry(unit, &port->unit_list_head, list) zfcp_erp_modify_unit_status(unit, common_mask, set_or_clear);}/* * function: zfcp_erp_modify_unit_status * * purpose: sets the unit to ERP_FAILED * */voidzfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear){ 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 succesfully * <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;}/* * function: * * purpose: * * returns: FIXME */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_erp_adapter_strategy_close_qdio(erp_action); zfcp_erp_adapter_strategy_close_fsf(erp_action); failed_qdio: out: return retval;}/* * function: zfcp_qdio_init * * purpose: setup QDIO operation for specified adapter * * returns: 0 - successful setup * !0 - failed setup */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 = 0; } 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;}/* * function: zfcp_qdio_cleanup * * purpose: cleans up QDIO operation for the specified adapter * * returns: 0 - successful cleanup * !0 - failed cleanup */intzfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action){ int retval = ZFCP_ERP_SUCCEEDED; int first_used; int used_count; struct zfcp_adapter *adapter = erp_action->adapter; if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) { ZFCP_LOG_DEBUG("error: attempt to shut down inactive QDIO " "queues on adapter %s\n", zfcp_get_busid_by_adapter(adapter)); retval = ZFCP_ERP_FAILED; goto out; } /* * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that * do_QDIO won't be called while qdio_shutdown is in progress. */ write_lock_irq(&adapter->request_queue.queue_lock); atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); write_unlock_irq(&adapter->request_queue.queue_lock); debug_text_event(adapter->erp_dbf, 3, "qdio_down2a"); while (qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS) msleep(1000); debug_text_event(adapter->erp_dbf, 3, "qdio_down2b"); /* * First we had to stop QDIO operation. * Now it is safe to take the following actions. */ /* Cleanup only necessary when there are unacknowledged buffers */ if (atomic_read(&adapter->request_queue.free_count) < QDIO_MAX_BUFFERS_PER_Q) { first_used = (adapter->request_queue.free_index + atomic_read(&adapter->request_queue.free_count)) % QDIO_MAX_BUFFERS_PER_Q; used_count = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&adapter->request_queue.free_count); zfcp_qdio_zero_sbals(adapter->request_queue.buffer, first_used, used_count); } adapter->response_queue.free_index = 0; atomic_set(&adapter->response_queue.free_count, 0); adapter->request_queue.free_index = 0; atomic_set(&adapter->request_queue.free_count, 0); adapter->request_queue.distance_from_int = 0; out: return retval;}static intzfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action){ int retval; if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &erp_action->adapter->status)) && (erp_action->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) { zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); atomic_set(&erp_action->adapter->erp_counter, 0); return ZFCP_ERP_FAILED; } 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);}/* * function: * * purpose: * * returns: */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(&adapter->erp_lock); zfcp_erp_action_to_running(erp_action); write_unlock(&adapter->erp_lock); zfcp_erp_timeout_init(erp_action); 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -