diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_erp.c')
| -rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 135 |
1 files changed, 112 insertions, 23 deletions
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index cb4f612550ba..023f4e558ae4 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
| @@ -82,6 +82,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); | |||
| 82 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); | 82 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); |
| 83 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); | 83 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); |
| 84 | static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *); | 84 | static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *); |
| 85 | static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *); | ||
| 85 | static int zfcp_erp_adapter_strategy_open_fsf_statusread( | 86 | static int zfcp_erp_adapter_strategy_open_fsf_statusread( |
| 86 | struct zfcp_erp_action *); | 87 | struct zfcp_erp_action *); |
| 87 | 88 | ||
| @@ -345,13 +346,13 @@ zfcp_erp_adisc(struct zfcp_port *port) | |||
| 345 | 346 | ||
| 346 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports | 347 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports |
| 347 | without FC-AL-2 capability, so we don't set it */ | 348 | without FC-AL-2 capability, so we don't set it */ |
| 348 | adisc->wwpn = adapter->wwpn; | 349 | adisc->wwpn = fc_host_port_name(adapter->scsi_host); |
| 349 | adisc->wwnn = adapter->wwnn; | 350 | adisc->wwnn = fc_host_node_name(adapter->scsi_host); |
| 350 | adisc->nport_id = adapter->s_id; | 351 | adisc->nport_id = fc_host_port_id(adapter->scsi_host); |
| 351 | ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " | 352 | ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " |
| 352 | "(wwpn=0x%016Lx, wwnn=0x%016Lx, " | 353 | "(wwpn=0x%016Lx, wwnn=0x%016Lx, " |
| 353 | "hard_nport_id=0x%08x, nport_id=0x%08x)\n", | 354 | "hard_nport_id=0x%08x, nport_id=0x%08x)\n", |
| 354 | adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn, | 355 | adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn, |
| 355 | (wwn_t) adisc->wwnn, adisc->hard_nport_id, | 356 | (wwn_t) adisc->wwnn, adisc->hard_nport_id, |
| 356 | adisc->nport_id); | 357 | adisc->nport_id); |
| 357 | 358 | ||
| @@ -404,7 +405,7 @@ zfcp_erp_adisc_handler(unsigned long data) | |||
| 404 | struct zfcp_send_els *send_els; | 405 | struct zfcp_send_els *send_els; |
| 405 | struct zfcp_port *port; | 406 | struct zfcp_port *port; |
| 406 | struct zfcp_adapter *adapter; | 407 | struct zfcp_adapter *adapter; |
| 407 | fc_id_t d_id; | 408 | u32 d_id; |
| 408 | struct zfcp_ls_adisc_acc *adisc; | 409 | struct zfcp_ls_adisc_acc *adisc; |
| 409 | 410 | ||
| 410 | send_els = (struct zfcp_send_els *) data; | 411 | send_els = (struct zfcp_send_els *) data; |
| @@ -435,9 +436,9 @@ zfcp_erp_adisc_handler(unsigned long data) | |||
| 435 | ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " | 436 | ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " |
| 436 | "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " | 437 | "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " |
| 437 | "hard_nport_id=0x%08x, nport_id=0x%08x)\n", | 438 | "hard_nport_id=0x%08x, nport_id=0x%08x)\n", |
| 438 | d_id, adapter->s_id, (wwn_t) adisc->wwpn, | 439 | d_id, fc_host_port_id(adapter->scsi_host), |
| 439 | (wwn_t) adisc->wwnn, adisc->hard_nport_id, | 440 | (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn, |
| 440 | adisc->nport_id); | 441 | adisc->hard_nport_id, adisc->nport_id); |
| 441 | 442 | ||
| 442 | /* set wwnn for port */ | 443 | /* set wwnn for port */ |
| 443 | if (port->wwnn == 0) | 444 | if (port->wwnn == 0) |
| @@ -886,7 +887,7 @@ static int | |||
| 886 | zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | 887 | zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) |
| 887 | { | 888 | { |
| 888 | int retval = 0; | 889 | int retval = 0; |
| 889 | struct zfcp_fsf_req *fsf_req; | 890 | struct zfcp_fsf_req *fsf_req = NULL; |
| 890 | struct zfcp_adapter *adapter = erp_action->adapter; | 891 | struct zfcp_adapter *adapter = erp_action->adapter; |
| 891 | 892 | ||
| 892 | if (erp_action->fsf_req) { | 893 | if (erp_action->fsf_req) { |
| @@ -896,7 +897,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | |||
| 896 | list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) | 897 | list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) |
| 897 | if (fsf_req == erp_action->fsf_req) | 898 | if (fsf_req == erp_action->fsf_req) |
| 898 | break; | 899 | break; |
| 899 | if (fsf_req == erp_action->fsf_req) { | 900 | if (fsf_req && (fsf_req->erp_action == erp_action)) { |
| 900 | /* fsf_req still exists */ | 901 | /* fsf_req still exists */ |
| 901 | debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); | 902 | debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); |
| 902 | debug_event(adapter->erp_dbf, 3, &fsf_req, | 903 | debug_event(adapter->erp_dbf, 3, &fsf_req, |
| @@ -2258,16 +2259,21 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | |||
| 2258 | static int | 2259 | static int |
| 2259 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) | 2260 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) |
| 2260 | { | 2261 | { |
| 2261 | int retval; | 2262 | int xconfig, xport; |
| 2263 | |||
| 2264 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
| 2265 | &erp_action->adapter->status)) { | ||
| 2266 | zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | ||
| 2267 | atomic_set(&erp_action->adapter->erp_counter, 0); | ||
| 2268 | return ZFCP_ERP_FAILED; | ||
| 2269 | } | ||
| 2262 | 2270 | ||
| 2263 | /* do 'exchange configuration data' */ | 2271 | xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); |
| 2264 | retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); | 2272 | xport = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); |
| 2265 | if (retval == ZFCP_ERP_FAILED) | 2273 | if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED)) |
| 2266 | return retval; | 2274 | return ZFCP_ERP_FAILED; |
| 2267 | 2275 | ||
| 2268 | /* start the desired number of Status Reads */ | 2276 | return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); |
| 2269 | retval = zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); | ||
| 2270 | return retval; | ||
| 2271 | } | 2277 | } |
| 2272 | 2278 | ||
| 2273 | /* | 2279 | /* |
| @@ -2291,7 +2297,9 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) | |||
| 2291 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | 2297 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, |
| 2292 | &adapter->status); | 2298 | &adapter->status); |
| 2293 | ZFCP_LOG_DEBUG("Doing exchange config data\n"); | 2299 | ZFCP_LOG_DEBUG("Doing exchange config data\n"); |
| 2300 | write_lock(&adapter->erp_lock); | ||
| 2294 | zfcp_erp_action_to_running(erp_action); | 2301 | zfcp_erp_action_to_running(erp_action); |
| 2302 | write_unlock(&adapter->erp_lock); | ||
| 2295 | zfcp_erp_timeout_init(erp_action); | 2303 | zfcp_erp_timeout_init(erp_action); |
| 2296 | if (zfcp_fsf_exchange_config_data(erp_action)) { | 2304 | if (zfcp_fsf_exchange_config_data(erp_action)) { |
| 2297 | retval = ZFCP_ERP_FAILED; | 2305 | retval = ZFCP_ERP_FAILED; |
| @@ -2348,6 +2356,76 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) | |||
| 2348 | return retval; | 2356 | return retval; |
| 2349 | } | 2357 | } |
| 2350 | 2358 | ||
| 2359 | static int | ||
| 2360 | zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | ||
| 2361 | { | ||
| 2362 | int retval = ZFCP_ERP_SUCCEEDED; | ||
| 2363 | int retries; | ||
| 2364 | int sleep; | ||
| 2365 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
| 2366 | |||
| 2367 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | ||
| 2368 | |||
| 2369 | for (retries = 0; ; retries++) { | ||
| 2370 | ZFCP_LOG_DEBUG("Doing exchange port data\n"); | ||
| 2371 | zfcp_erp_action_to_running(erp_action); | ||
| 2372 | zfcp_erp_timeout_init(erp_action); | ||
| 2373 | if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) { | ||
| 2374 | retval = ZFCP_ERP_FAILED; | ||
| 2375 | debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf"); | ||
| 2376 | ZFCP_LOG_INFO("error: initiation of exchange of " | ||
| 2377 | "port data failed for adapter %s\n", | ||
| 2378 | zfcp_get_busid_by_adapter(adapter)); | ||
| 2379 | break; | ||
| 2380 | } | ||
| 2381 | debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok"); | ||
| 2382 | ZFCP_LOG_DEBUG("Xchange underway\n"); | ||
| 2383 | |||
| 2384 | /* | ||
| 2385 | * Why this works: | ||
| 2386 | * Both the normal completion handler as well as the timeout | ||
| 2387 | * handler will do an 'up' when the 'exchange port data' | ||
| 2388 | * request completes or times out. Thus, the signal to go on | ||
| 2389 | * won't be lost utilizing this semaphore. | ||
| 2390 | * Furthermore, this 'adapter_reopen' action is | ||
| 2391 | * guaranteed to be the only action being there (highest action | ||
| 2392 | * which prevents other actions from being created). | ||
| 2393 | * Resulting from that, the wake signal recognized here | ||
| 2394 | * _must_ be the one belonging to the 'exchange port | ||
| 2395 | * data' request. | ||
| 2396 | */ | ||
| 2397 | down(&adapter->erp_ready_sem); | ||
| 2398 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { | ||
| 2399 | ZFCP_LOG_INFO("error: exchange of port data " | ||
| 2400 | "for adapter %s timed out\n", | ||
| 2401 | zfcp_get_busid_by_adapter(adapter)); | ||
| 2402 | break; | ||
| 2403 | } | ||
| 2404 | |||
| 2405 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
| 2406 | &adapter->status)) | ||
| 2407 | break; | ||
| 2408 | |||
| 2409 | ZFCP_LOG_DEBUG("host connection still initialising... " | ||
| 2410 | "waiting and retrying...\n"); | ||
| 2411 | /* sleep a little bit before retry */ | ||
| 2412 | sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ? | ||
| 2413 | ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP : | ||
| 2414 | ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; | ||
| 2415 | msleep(jiffies_to_msecs(sleep)); | ||
| 2416 | } | ||
| 2417 | |||
| 2418 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
| 2419 | &adapter->status)) { | ||
| 2420 | ZFCP_LOG_INFO("error: exchange of port data for " | ||
| 2421 | "adapter %s failed\n", | ||
| 2422 | zfcp_get_busid_by_adapter(adapter)); | ||
| 2423 | retval = ZFCP_ERP_FAILED; | ||
| 2424 | } | ||
| 2425 | |||
| 2426 | return retval; | ||
| 2427 | } | ||
| 2428 | |||
| 2351 | /* | 2429 | /* |
| 2352 | * function: | 2430 | * function: |
| 2353 | * | 2431 | * |
| @@ -3194,11 +3272,19 @@ zfcp_erp_action_enqueue(int action, | |||
| 3194 | /* fall through !!! */ | 3272 | /* fall through !!! */ |
| 3195 | 3273 | ||
| 3196 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 3274 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
| 3197 | if (atomic_test_mask | 3275 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
| 3198 | (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status) | 3276 | &port->status)) { |
| 3199 | && port->erp_action.action == | 3277 | if (port->erp_action.action != |
| 3200 | ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) { | 3278 | ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) { |
| 3201 | debug_text_event(adapter->erp_dbf, 4, "pf_actenq_drp"); | 3279 | ZFCP_LOG_INFO("dropped erp action %i (port " |
| 3280 | "0x%016Lx, action in use: %i)\n", | ||
| 3281 | action, port->wwpn, | ||
| 3282 | port->erp_action.action); | ||
| 3283 | debug_text_event(adapter->erp_dbf, 4, | ||
| 3284 | "pf_actenq_drp"); | ||
| 3285 | } else | ||
| 3286 | debug_text_event(adapter->erp_dbf, 4, | ||
| 3287 | "pf_actenq_drpcp"); | ||
| 3202 | debug_event(adapter->erp_dbf, 4, &port->wwpn, | 3288 | debug_event(adapter->erp_dbf, 4, &port->wwpn, |
| 3203 | sizeof (wwn_t)); | 3289 | sizeof (wwn_t)); |
| 3204 | goto out; | 3290 | goto out; |
| @@ -3589,6 +3675,9 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) | |||
| 3589 | struct zfcp_port *port; | 3675 | struct zfcp_port *port; |
| 3590 | unsigned long flags; | 3676 | unsigned long flags; |
| 3591 | 3677 | ||
| 3678 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | ||
| 3679 | return; | ||
| 3680 | |||
| 3592 | debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); | 3681 | debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); |
| 3593 | debug_event(adapter->erp_dbf, 3, &adapter->name, 8); | 3682 | debug_event(adapter->erp_dbf, 3, &adapter->name, 8); |
| 3594 | 3683 | ||
