zfcp_erp.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,341 行 · 第 1/5 页
C
2,341 行
if (status == ZFCP_ERP_SUCCEEDED) ; /* no further action */ else zfcp_erp_port_reopen_internal(unit->port, 0); break; } return 0;}/* * function: * * purpose: * * returns: */static intzfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter){ int retval = 0; unsigned long flags; struct zfcp_port *nport = adapter->nameserver_port; read_lock_irqsave(&zfcp_data.config_lock, flags); read_lock(&adapter->erp_lock); if (list_empty(&adapter->erp_ready_head) && list_empty(&adapter->erp_running_head)) { if (nport && atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &nport->status)) { debug_text_event(adapter->erp_dbf, 4, "a_cq_nspsd"); /* taking down nameserver port */ zfcp_erp_port_reopen_internal(nport, ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED); } else { debug_text_event(adapter->erp_dbf, 4, "a_cq_wake"); atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); wake_up(&adapter->erp_done_wqh); } } else debug_text_event(adapter->erp_dbf, 5, "a_cq_notempty"); read_unlock(&adapter->erp_lock); read_unlock_irqrestore(&zfcp_data.config_lock, flags); return retval;}/** * zfcp_erp_wait - wait for completion of error recovery on an adapter * @adapter: adapter for which to wait for completion of its error recovery * Return: 0 */intzfcp_erp_wait(struct zfcp_adapter *adapter){ int retval = 0; wait_event(adapter->erp_done_wqh, !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status)); return retval;}/* * function: zfcp_erp_modify_adapter_status * * purpose: * */voidzfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u32 mask, int set_or_clear){ struct zfcp_port *port; u32 common_mask = mask & ZFCP_COMMON_FLAGS; if (set_or_clear == ZFCP_SET) { atomic_set_mask(mask, &adapter->status); debug_text_event(adapter->erp_dbf, 3, "a_mod_as_s"); } else { atomic_clear_mask(mask, &adapter->status); if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) atomic_set(&adapter->erp_counter, 0); debug_text_event(adapter->erp_dbf, 3, "a_mod_as_c"); } debug_event(adapter->erp_dbf, 3, &mask, sizeof (u32)); /* Deal with all underlying devices, only pass common_mask */ if (common_mask) list_for_each_entry(port, &adapter->port_list_head, list) zfcp_erp_modify_port_status(port, common_mask, set_or_clear);}/* * function: zfcp_erp_modify_port_status * * purpose: sets the port and all underlying devices to ERP_FAILED * */voidzfcp_erp_modify_port_status(struct zfcp_port *port, u32 mask, int set_or_clear){ struct zfcp_unit *unit; u32 common_mask = mask & ZFCP_COMMON_FLAGS; 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->stat
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?