X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=drivers%2Fs390%2Fscsi%2Fzfcp_erp.c;h=cb4f612550baf459ed752ba385dbeca823574958;hb=bcdd3a911499abd65bf1f123b2a6ad9c1d5611ea;hp=cfc0d8c588dfb8a653cfdd517de4e453867bc046;hpb=1da177e4c3f41524e886b7f1b8a0c1fc7321cac2;p=~andy%2Flinux diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index cfc0d8c588d..cb4f612550b 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -35,7 +35,7 @@ #include "zfcp_ext.h" -static int zfcp_erp_adisc(struct zfcp_adapter *, fc_id_t); +static int zfcp_erp_adisc(struct zfcp_port *); static void zfcp_erp_adisc_handler(unsigned long); static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int); @@ -295,12 +295,12 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask) /** * zfcp_erp_adisc - send ADISC ELS command - * @adapter: adapter structure - * @d_id: d_id of port where ADISC is sent to + * @port: port structure */ int -zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) +zfcp_erp_adisc(struct zfcp_port *port) { + struct zfcp_adapter *adapter = port->adapter; struct zfcp_send_els *send_els; struct zfcp_ls_adisc *adisc; void *address = NULL; @@ -332,7 +332,8 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) send_els->req_count = send_els->resp_count = 1; send_els->adapter = adapter; - send_els->d_id = d_id; + send_els->port = port; + send_els->d_id = port->d_id; send_els->handler = zfcp_erp_adisc_handler; send_els->handler_data = (unsigned long) send_els; @@ -350,7 +351,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " "(wwpn=0x%016Lx, wwnn=0x%016Lx, " "hard_nport_id=0x%08x, nport_id=0x%08x)\n", - adapter->s_id, d_id, (wwn_t) adisc->wwpn, + adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn, adisc->hard_nport_id, adisc->nport_id); @@ -367,7 +368,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) retval = zfcp_fsf_send_els(send_els); if (retval != 0) { ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port " - "0x%08x on adapter %s\n", d_id, + "0x%08x on adapter %s\n", send_els->d_id, zfcp_get_busid_by_adapter(adapter)); del_timer(send_els->timer); goto freemem; @@ -411,14 +412,9 @@ zfcp_erp_adisc_handler(unsigned long data) del_timer(send_els->timer); adapter = send_els->adapter; + port = send_els->port; d_id = send_els->d_id; - read_lock(&zfcp_data.config_lock); - port = zfcp_get_port_by_did(send_els->adapter, send_els->d_id); - read_unlock(&zfcp_data.config_lock); - - BUG_ON(port == NULL); - /* request rejected or timed out */ if (send_els->status != 0) { ZFCP_LOG_NORMAL("ELS request rejected/timed out, " @@ -482,7 +478,7 @@ zfcp_test_link(struct zfcp_port *port) int retval; zfcp_port_get(port); - retval = zfcp_erp_adisc(port->adapter, port->d_id); + retval = zfcp_erp_adisc(port); if (retval != 0) { zfcp_port_put(port); ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx " @@ -895,7 +891,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) if (erp_action->fsf_req) { /* take lock to ensure that request is not being deleted meanwhile */ - write_lock(&adapter->fsf_req_list_lock); + spin_lock(&adapter->fsf_req_list_lock); /* check whether fsf req does still exist */ list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) if (fsf_req == erp_action->fsf_req) @@ -938,7 +934,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) */ erp_action->fsf_req = NULL; } - write_unlock(&adapter->fsf_req_list_lock); + spin_unlock(&adapter->fsf_req_list_lock); } else debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); @@ -2286,12 +2282,12 @@ zfcp_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); - retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES; - do { + 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"); @@ -2329,16 +2325,17 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) zfcp_get_busid_by_adapter(adapter)); break; } - if (atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, - &adapter->status)) { - ZFCP_LOG_DEBUG("host connection still initialising... " - "waiting and retrying...\n"); - /* sleep a little bit before retry */ - msleep(jiffies_to_msecs(ZFCP_EXCHANGE_CONFIG_DATA_SLEEP)); - } - } while ((retries--) && - atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, - &adapter->status)); + + 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; + } if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status)) { @@ -2568,6 +2565,23 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) case ZFCP_ERP_STEP_UNINITIALIZED: case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: case ZFCP_ERP_STEP_PORT_CLOSING: + if (adapter->fc_topology == FSF_TOPO_P2P) { + if (port->wwpn != adapter->peer_wwpn) { + ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx " + "on adapter %s.\nPeer WWPN " + "0x%016Lx does not match\n", + port->wwpn, + zfcp_get_busid_by_adapter(adapter), + adapter->peer_wwpn); + zfcp_erp_port_failed(port); + retval = ZFCP_ERP_FAILED; + break; + } + port->d_id = adapter->peer_d_id; + atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); + retval = zfcp_erp_port_strategy_open_port(erp_action); + break; + } if (!(adapter->nameserver_port)) { retval = zfcp_nameserver_enqueue(adapter); if (retval != 0) { @@ -3346,13 +3360,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, if ((result == ZFCP_ERP_SUCCEEDED) && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, &unit->status)) - && (!unit->device)) - scsi_add_device(unit->port->adapter->scsi_host, 0, - unit->port->scsi_id, unit->scsi_lun); + && !unit->device + && port->rport) + scsi_add_device(port->adapter->scsi_host, 0, + port->rport->scsi_target_id, + unit->scsi_lun); zfcp_unit_put(unit); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: + if ((result == ZFCP_ERP_SUCCEEDED) + && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, + &port->status) + && !port->rport) { + struct fc_rport_identifiers ids; + ids.node_name = port->wwnn; + ids.port_name = port->wwpn; + ids.port_id = port->d_id; + ids.roles = FC_RPORT_ROLE_FCP_TARGET; + port->rport = + fc_remote_port_add(adapter->scsi_host, 0, &ids); + if (!port->rport) + ZFCP_LOG_NORMAL("failed registration of rport" + "(adapter %s, wwpn=0x%016Lx)\n", + zfcp_get_busid_by_port(port), + port->wwpn); + } zfcp_port_put(port); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: @@ -3467,6 +3500,45 @@ zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) list_move(&erp_action->list, &erp_action->adapter->erp_ready_head); } +/* + * function: zfcp_erp_port_boxed + * + * purpose: + */ +void +zfcp_erp_port_boxed(struct zfcp_port *port) +{ + struct zfcp_adapter *adapter = port->adapter; + unsigned long flags; + + debug_text_event(adapter->erp_dbf, 3, "p_access_boxed"); + debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t)); + read_lock_irqsave(&zfcp_data.config_lock, flags); + zfcp_erp_modify_port_status(port, + ZFCP_STATUS_COMMON_ACCESS_BOXED, + ZFCP_SET); + read_unlock_irqrestore(&zfcp_data.config_lock, flags); + zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED); +} + +/* + * function: zfcp_erp_unit_boxed + * + * purpose: + */ +void +zfcp_erp_unit_boxed(struct zfcp_unit *unit) +{ + struct zfcp_adapter *adapter = unit->port->adapter; + + debug_text_event(adapter->erp_dbf, 3, "u_access_boxed"); + debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t)); + zfcp_erp_modify_unit_status(unit, + ZFCP_STATUS_COMMON_ACCESS_BOXED, + ZFCP_SET); + zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED); +} + /* * function: zfcp_erp_port_access_denied * @@ -3478,11 +3550,13 @@ zfcp_erp_port_access_denied(struct zfcp_port *port) struct zfcp_adapter *adapter = port->adapter; unsigned long flags; - debug_text_event(adapter->erp_dbf, 3, "p_access_block"); + debug_text_event(adapter->erp_dbf, 3, "p_access_denied"); debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t)); read_lock_irqsave(&zfcp_data.config_lock, flags); - zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED | - ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); + zfcp_erp_modify_port_status(port, + ZFCP_STATUS_COMMON_ERP_FAILED | + ZFCP_STATUS_COMMON_ACCESS_DENIED, + ZFCP_SET); read_unlock_irqrestore(&zfcp_data.config_lock, flags); } @@ -3496,10 +3570,12 @@ zfcp_erp_unit_access_denied(struct zfcp_unit *unit) { struct zfcp_adapter *adapter = unit->port->adapter; - debug_text_event(adapter->erp_dbf, 3, "u_access_block"); + debug_text_event(adapter->erp_dbf, 3, "u_access_denied"); debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t)); - zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_ERP_FAILED | - ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); + zfcp_erp_modify_unit_status(unit, + ZFCP_STATUS_COMMON_ERP_FAILED | + ZFCP_STATUS_COMMON_ACCESS_DENIED, + ZFCP_SET); } /* @@ -3513,11 +3589,12 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) struct zfcp_port *port; unsigned long flags; - debug_text_event(adapter->erp_dbf, 3, "a_access_unblock"); + debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); debug_event(adapter->erp_dbf, 3, &adapter->name, 8); - zfcp_erp_port_access_changed(adapter->nameserver_port); read_lock_irqsave(&zfcp_data.config_lock, flags); + if (adapter->nameserver_port) + zfcp_erp_port_access_changed(adapter->nameserver_port); list_for_each_entry(port, &adapter->port_list_head, list) if (port != adapter->nameserver_port) zfcp_erp_port_access_changed(port); @@ -3535,10 +3612,12 @@ zfcp_erp_port_access_changed(struct zfcp_port *port) struct zfcp_adapter *adapter = port->adapter; struct zfcp_unit *unit; - debug_text_event(adapter->erp_dbf, 3, "p_access_unblock"); + debug_text_event(adapter->erp_dbf, 3, "p_access_recover"); debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t)); if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, + &port->status) && + !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED, &port->status)) { if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) list_for_each_entry(unit, &port->unit_list_head, list) @@ -3565,10 +3644,13 @@ zfcp_erp_unit_access_changed(struct zfcp_unit *unit) { struct zfcp_adapter *adapter = unit->port->adapter; - debug_text_event(adapter->erp_dbf, 3, "u_access_unblock"); + debug_text_event(adapter->erp_dbf, 3, "u_access_recover"); debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t)); - if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status)) + if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, + &unit->status) && + !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED, + &unit->status)) return; ZFCP_LOG_NORMAL("reopen of unit 0x%016Lx on port 0x%016Lx "