static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear, char *id, void *ref) { struct zfcp_port *port; list_for_each_entry(port, &adapter->port_list_head, list) _zfcp_erp_port_reopen(port, clear, id, ref); }
static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) { struct zfcp_port *port; port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0, adapter->peer_d_id); if (IS_ERR(port)) /* error or port already attached */ return; _zfcp_erp_port_reopen(port, 0, "ereptp1", NULL); }
static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) { struct zfcp_port *port; port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0, adapter->peer_d_id); if (IS_ERR(port)) return; _zfcp_erp_port_reopen(port, 0, "ereptp1"); }
static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear, char *id) { struct zfcp_port *port; read_lock(&adapter->port_list_lock); list_for_each_entry(port, &adapter->port_list, list) _zfcp_erp_port_reopen(port, clear, id); read_unlock(&adapter->port_list_lock); }
int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) { int retval; unsigned long flags; struct zfcp_adapter *adapter = port->adapter; write_lock_irqsave(&adapter->erp_lock, flags); retval = _zfcp_erp_port_reopen(port, clear, id); write_unlock_irqrestore(&adapter->erp_lock, flags); return retval; }
static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act) { switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1", NULL); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: _zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL); break; case ZFCP_ERP_ACTION_REOPEN_PORT: _zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL); break; } }
/** * zfcp_erp_port_reopen - trigger remote port recovery * @port: port to recover * @clear_mask: flags in port status to be cleared * * Returns 0 if recovery has been triggered, < 0 if not. */ int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) { unsigned long flags; int retval; struct zfcp_adapter *adapter = port->adapter; read_lock_irqsave(&zfcp_data.config_lock, flags); write_lock(&adapter->erp_lock); retval = _zfcp_erp_port_reopen(port, clear, id, ref); write_unlock(&adapter->erp_lock); read_unlock_irqrestore(&zfcp_data.config_lock, flags); return retval; }
static void zfcp_erp_strategy_followup_actions(struct zfcp_erp_action *act) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; struct zfcp_unit *unit = act->unit; u32 status = act->status; /* initiate follow-up actions depending on success of finished action */ switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (status == ZFCP_ERP_SUCCEEDED) _zfcp_erp_port_reopen_all(adapter, 0, "ersfa_1", NULL); else _zfcp_erp_adapter_reopen(adapter, 0, "ersfa_2", NULL); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: if (status == ZFCP_ERP_SUCCEEDED) _zfcp_erp_port_reopen(port, 0, "ersfa_3", NULL); else _zfcp_erp_adapter_reopen(adapter, 0, "ersfa_4", NULL); break; case ZFCP_ERP_ACTION_REOPEN_PORT: if (status == ZFCP_ERP_SUCCEEDED) _zfcp_erp_unit_reopen_all(port, 0, "ersfa_5", NULL); else _zfcp_erp_port_forced_reopen(port, 0, "ersfa_6", NULL); break; case ZFCP_ERP_ACTION_REOPEN_UNIT: if (status != ZFCP_ERP_SUCCEEDED) _zfcp_erp_port_reopen(unit->port, 0, "ersfa_7", NULL); break; } }
static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) { switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1", NULL); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2", NULL); break; case ZFCP_ERP_ACTION_REOPEN_PORT: _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL); break; case ZFCP_ERP_ACTION_REOPEN_UNIT: _zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL); break; } }
static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) { int action = act->action; struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; struct scsi_device *sdev = act->sdev; struct zfcp_scsi_dev *zfcp_sdev; u32 erp_status = act->status; switch (action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) { _zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, "ersscg1"); return ZFCP_ERP_EXIT; } break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: if (zfcp_erp_strat_change_det(&port->status, erp_status)) { _zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "ersscg2"); return ZFCP_ERP_EXIT; } break; case ZFCP_ERP_ACTION_REOPEN_LUN: zfcp_sdev = sdev_to_zfcp(sdev); if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) { _zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, "ersscg3", 0); return ZFCP_ERP_EXIT; } break; } return ret; }
static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; int p_status = atomic_read(&port->status); switch (act->step) { case ZFCP_ERP_STEP_UNINITIALIZED: case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: case ZFCP_ERP_STEP_PORT_CLOSING: if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) return zfcp_erp_open_ptp_port(act); if (!port->d_id) { zfcp_port_get(port); if (!queue_work(adapter->work_queue, &port->gid_pn_work)) zfcp_port_put(port); return ZFCP_ERP_EXIT; } return zfcp_erp_port_strategy_open_port(act); case ZFCP_ERP_STEP_PORT_OPENING: /* D_ID might have changed during open */ if (p_status & ZFCP_STATUS_COMMON_OPEN) { if (port->d_id) return ZFCP_ERP_SUCCEEDED; else { act->step = ZFCP_ERP_STEP_PORT_CLOSING; return ZFCP_ERP_CONTINUES; } } if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) { port->d_id = 0; _zfcp_erp_port_reopen(port, 0, "erpsoc1", NULL); return ZFCP_ERP_EXIT; } /* fall through otherwise */ } return ZFCP_ERP_FAILED; }
static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) { int action = act->action; struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; struct zfcp_unit *unit = act->unit; u32 erp_status = act->status; switch (action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) { _zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, "ersscg1", NULL); return ZFCP_ERP_EXIT; } break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: if (zfcp_erp_strat_change_det(&port->status, erp_status)) { _zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "ersscg2", NULL); return ZFCP_ERP_EXIT; } break; case ZFCP_ERP_ACTION_REOPEN_UNIT: if (zfcp_erp_strat_change_det(&unit->status, erp_status)) { _zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, "ersscg3", NULL); return ZFCP_ERP_EXIT; } break; } return ret; }