static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) { switch (result) { case ZFCP_ERP_SUCCEEDED : atomic_set(&port->erp_counter, 0); zfcp_erp_port_unblock(port); break; case ZFCP_ERP_FAILED : if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) { zfcp_erp_port_block(port, 0); result = ZFCP_ERP_EXIT; } atomic_inc(&port->erp_counter); if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) { dev_err(&port->adapter->ccw_device->dev, "ERP failed for remote port 0x%016Lx\n", (unsigned long long)port->wwpn); zfcp_erp_port_failed(port, "erpsck1", NULL); } break; } if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { zfcp_erp_port_block(port, 0); result = ZFCP_ERP_EXIT; } return result; }
static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; if (port->wwpn != adapter->peer_wwpn) { zfcp_erp_port_failed(port, "eroptp1", NULL); return ZFCP_ERP_FAILED; } port->d_id = adapter->peer_d_id; return zfcp_erp_port_strategy_open_port(act); }
static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; if (port->wwpn != adapter->peer_wwpn) { zfcp_erp_port_failed(port, 25, NULL); return ZFCP_ERP_FAILED; } port->d_id = adapter->peer_d_id; atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); return zfcp_erp_port_strategy_open_port(act); }
static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, u8 id, void *ref) { zfcp_erp_port_block(port, clear); if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { /* ensure propagation of failed status to new devices */ zfcp_erp_port_failed(port, 14, NULL); return -EIO; } return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, port->adapter, port, NULL, id, ref); }
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) { queue_work(zfcp_data.work_queue, &port->gid_pn_work); return ZFCP_ERP_CONTINUES; } case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: if (!port->d_id) { if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) { zfcp_erp_port_failed(port, 26, NULL); return ZFCP_ERP_EXIT; } return ZFCP_ERP_FAILED; } 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; } /* fall through otherwise */ } } return ZFCP_ERP_FAILED; }