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 | ||