diff options
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.c | 11 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 13 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 95 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 3 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 330 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.h | 51 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_sysfs_adapter.c | 4 |
7 files changed, 367 insertions, 140 deletions
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index fff1537335c7..64d9b90373fe 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -279,9 +279,18 @@ zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter, | |||
279 | break; | 279 | break; |
280 | 280 | ||
281 | case FSF_STATUS_READ_LINK_DOWN: | 281 | case FSF_STATUS_READ_LINK_DOWN: |
282 | rec->type.status.payload_size = sizeof(u64); | 282 | switch (status_buffer->status_subtype) { |
283 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: | ||
284 | case FSF_STATUS_READ_SUB_FDISC_FAILED: | ||
285 | rec->type.status.payload_size = | ||
286 | sizeof(struct fsf_link_down_info); | ||
287 | } | ||
283 | break; | 288 | break; |
284 | 289 | ||
290 | case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: | ||
291 | rec->type.status.payload_size = | ||
292 | ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT; | ||
293 | break; | ||
285 | } | 294 | } |
286 | memcpy(&rec->type.status.payload, | 295 | memcpy(&rec->type.status.payload, |
287 | &status_buffer->payload, rec->type.status.payload_size); | 296 | &status_buffer->payload, rec->type.status.payload_size); |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index fc5bb6f31808..4b6af8e07e8d 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -66,7 +66,7 @@ | |||
66 | /********************* GENERAL DEFINES *********************************/ | 66 | /********************* GENERAL DEFINES *********************************/ |
67 | 67 | ||
68 | /* zfcp version number, it consists of major, minor, and patch-level number */ | 68 | /* zfcp version number, it consists of major, minor, and patch-level number */ |
69 | #define ZFCP_VERSION "4.4.0" | 69 | #define ZFCP_VERSION "4.5.0" |
70 | 70 | ||
71 | /** | 71 | /** |
72 | * zfcp_sg_to_address - determine kernel address from struct scatterlist | 72 | * zfcp_sg_to_address - determine kernel address from struct scatterlist |
@@ -154,6 +154,11 @@ typedef u32 scsi_lun_t; | |||
154 | #define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100 | 154 | #define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100 |
155 | #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7 | 155 | #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7 |
156 | 156 | ||
157 | /* Retry 5 times every 2 second, then every minute */ | ||
158 | #define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5 | ||
159 | #define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200 | ||
160 | #define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000 | ||
161 | |||
157 | /* timeout value for "default timer" for fsf requests */ | 162 | /* timeout value for "default timer" for fsf requests */ |
158 | #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ); | 163 | #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ); |
159 | 164 | ||
@@ -638,6 +643,7 @@ do { \ | |||
638 | #define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080 | 643 | #define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080 |
639 | #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 | 644 | #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 |
640 | #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 | 645 | #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 |
646 | #define ZFCP_STATUS_ADAPTER_XPORT_OK 0x00000800 | ||
641 | 647 | ||
642 | #define ZFCP_STATUS_ADAPTER_SCSI_UP \ | 648 | #define ZFCP_STATUS_ADAPTER_SCSI_UP \ |
643 | (ZFCP_STATUS_COMMON_UNBLOCKED | \ | 649 | (ZFCP_STATUS_COMMON_UNBLOCKED | \ |
@@ -915,13 +921,16 @@ struct zfcp_adapter { | |||
915 | wwn_t peer_wwnn; /* P2P peer WWNN */ | 921 | wwn_t peer_wwnn; /* P2P peer WWNN */ |
916 | wwn_t peer_wwpn; /* P2P peer WWPN */ | 922 | wwn_t peer_wwpn; /* P2P peer WWPN */ |
917 | fc_id_t peer_d_id; /* P2P peer D_ID */ | 923 | fc_id_t peer_d_id; /* P2P peer D_ID */ |
924 | wwn_t physical_wwpn; /* WWPN of physical port */ | ||
925 | fc_id_t physical_s_id; /* local FC port ID */ | ||
918 | struct ccw_device *ccw_device; /* S/390 ccw device */ | 926 | struct ccw_device *ccw_device; /* S/390 ccw device */ |
919 | u8 fc_service_class; | 927 | u8 fc_service_class; |
920 | u32 fc_topology; /* FC topology */ | 928 | u32 fc_topology; /* FC topology */ |
921 | u32 fc_link_speed; /* FC interface speed */ | 929 | u32 fc_link_speed; /* FC interface speed */ |
922 | u32 hydra_version; /* Hydra version */ | 930 | u32 hydra_version; /* Hydra version */ |
923 | u32 fsf_lic_version; | 931 | u32 fsf_lic_version; |
924 | u32 supported_features;/* of FCP channel */ | 932 | u32 adapter_features; /* FCP channel features */ |
933 | u32 connection_features; /* host connection features */ | ||
925 | u32 hardware_version; /* of FCP channel */ | 934 | u32 hardware_version; /* of FCP channel */ |
926 | u8 serial_number[32]; /* of hardware */ | 935 | u8 serial_number[32]; /* of hardware */ |
927 | struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ | 936 | struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 376cb0f6cb74..c4a6799aed44 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 | ||
@@ -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 | /* |
@@ -2350,6 +2356,76 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) | |||
2350 | return retval; | 2356 | return retval; |
2351 | } | 2357 | } |
2352 | 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 | |||
2353 | /* | 2429 | /* |
2354 | * function: | 2430 | * function: |
2355 | * | 2431 | * |
@@ -3599,6 +3675,9 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) | |||
3599 | struct zfcp_port *port; | 3675 | struct zfcp_port *port; |
3600 | unsigned long flags; | 3676 | unsigned long flags; |
3601 | 3677 | ||
3678 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | ||
3679 | return; | ||
3680 | |||
3602 | debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); | 3681 | debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); |
3603 | debug_event(adapter->erp_dbf, 3, &adapter->name, 8); | 3682 | debug_event(adapter->erp_dbf, 3, &adapter->name, 8); |
3604 | 3683 | ||
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 104b7423fd4d..c3782261cb5c 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -96,7 +96,8 @@ extern int zfcp_fsf_open_unit(struct zfcp_erp_action *); | |||
96 | extern int zfcp_fsf_close_unit(struct zfcp_erp_action *); | 96 | extern int zfcp_fsf_close_unit(struct zfcp_erp_action *); |
97 | 97 | ||
98 | extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *); | 98 | extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *); |
99 | extern int zfcp_fsf_exchange_port_data(struct zfcp_adapter *, | 99 | extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *, |
100 | struct zfcp_adapter *, | ||
100 | struct fsf_qtcb_bottom_port *); | 101 | struct fsf_qtcb_bottom_port *); |
101 | extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, | 102 | extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, |
102 | u32, u32, struct zfcp_sg_list *); | 103 | u32, u32, struct zfcp_sg_list *); |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 80ab721ddfff..f994f453e2d2 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -59,6 +59,8 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *, struct timer_list *); | |||
59 | static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *); | 59 | static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *); |
60 | static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *); | 60 | static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *); |
61 | static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); | 61 | static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); |
62 | static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *, | ||
63 | struct fsf_link_down_info *); | ||
62 | static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); | 64 | static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); |
63 | static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); | 65 | static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); |
64 | 66 | ||
@@ -375,87 +377,19 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) | |||
375 | break; | 377 | break; |
376 | 378 | ||
377 | case FSF_PROT_DUPLICATE_REQUEST_ID: | 379 | case FSF_PROT_DUPLICATE_REQUEST_ID: |
378 | if (fsf_req->qtcb) { | ||
379 | ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx " | 380 | ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx " |
380 | "to the adapter %s is ambiguous. " | 381 | "to the adapter %s is ambiguous. " |
381 | "Stopping all operations on this " | 382 | "Stopping all operations on this adapter.\n", |
382 | "adapter.\n", | 383 | *(unsigned long long*) |
383 | *(unsigned long long *) | 384 | (&qtcb->bottom.support.req_handle), |
384 | (&fsf_req->qtcb->bottom.support. | ||
385 | req_handle), | ||
386 | zfcp_get_busid_by_adapter(adapter)); | ||
387 | } else { | ||
388 | ZFCP_LOG_NORMAL("bug: The request identifier %p " | ||
389 | "to the adapter %s is ambiguous. " | ||
390 | "Stopping all operations on this " | ||
391 | "adapter. " | ||
392 | "(bug: got this for an unsolicited " | ||
393 | "status read request)\n", | ||
394 | fsf_req, | ||
395 | zfcp_get_busid_by_adapter(adapter)); | 385 | zfcp_get_busid_by_adapter(adapter)); |
396 | } | ||
397 | zfcp_erp_adapter_shutdown(adapter, 0); | 386 | zfcp_erp_adapter_shutdown(adapter, 0); |
398 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 387 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
399 | break; | 388 | break; |
400 | 389 | ||
401 | case FSF_PROT_LINK_DOWN: | 390 | case FSF_PROT_LINK_DOWN: |
402 | /* | 391 | zfcp_fsf_link_down_info_eval(adapter, |
403 | * 'test and set' is not atomic here - | 392 | &prot_status_qual->link_down_info); |
404 | * it's ok as long as calls to our response queue handler | ||
405 | * (and thus execution of this code here) are serialized | ||
406 | * by the qdio module | ||
407 | */ | ||
408 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
409 | &adapter->status)) { | ||
410 | switch (fsf_req->qtcb->prefix.prot_status_qual. | ||
411 | locallink_error.code) { | ||
412 | case FSF_PSQ_LINK_NOLIGHT: | ||
413 | ZFCP_LOG_INFO("The local link to adapter %s " | ||
414 | "is down (no light detected).\n", | ||
415 | zfcp_get_busid_by_adapter( | ||
416 | adapter)); | ||
417 | break; | ||
418 | case FSF_PSQ_LINK_WRAPPLUG: | ||
419 | ZFCP_LOG_INFO("The local link to adapter %s " | ||
420 | "is down (wrap plug detected).\n", | ||
421 | zfcp_get_busid_by_adapter( | ||
422 | adapter)); | ||
423 | break; | ||
424 | case FSF_PSQ_LINK_NOFCP: | ||
425 | ZFCP_LOG_INFO("The local link to adapter %s " | ||
426 | "is down (adjacent node on " | ||
427 | "link does not support FCP).\n", | ||
428 | zfcp_get_busid_by_adapter( | ||
429 | adapter)); | ||
430 | break; | ||
431 | default: | ||
432 | ZFCP_LOG_INFO("The local link to adapter %s " | ||
433 | "is down " | ||
434 | "(warning: unknown reason " | ||
435 | "code).\n", | ||
436 | zfcp_get_busid_by_adapter( | ||
437 | adapter)); | ||
438 | break; | ||
439 | |||
440 | } | ||
441 | /* | ||
442 | * Due to the 'erp failed' flag the adapter won't | ||
443 | * be recovered but will be just set to 'blocked' | ||
444 | * state. All subordinary devices will have state | ||
445 | * 'blocked' and 'erp failed', too. | ||
446 | * Thus the adapter is still able to provide | ||
447 | * 'link up' status without being flooded with | ||
448 | * requests. | ||
449 | * (note: even 'close port' is not permitted) | ||
450 | */ | ||
451 | ZFCP_LOG_INFO("Stopping all operations for adapter " | ||
452 | "%s.\n", | ||
453 | zfcp_get_busid_by_adapter(adapter)); | ||
454 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | ||
455 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
456 | &adapter->status); | ||
457 | zfcp_erp_adapter_reopen(adapter, 0); | ||
458 | } | ||
459 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 393 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
460 | break; | 394 | break; |
461 | 395 | ||
@@ -613,6 +547,110 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) | |||
613 | return retval; | 547 | return retval; |
614 | } | 548 | } |
615 | 549 | ||
550 | /** | ||
551 | * zfcp_fsf_link_down_info_eval - evaluate link down information block | ||
552 | */ | ||
553 | static void | ||
554 | zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, | ||
555 | struct fsf_link_down_info *link_down) | ||
556 | { | ||
557 | switch (link_down->error_code) { | ||
558 | case FSF_PSQ_LINK_NO_LIGHT: | ||
559 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
560 | "(no light detected)\n", | ||
561 | zfcp_get_busid_by_adapter(adapter)); | ||
562 | break; | ||
563 | case FSF_PSQ_LINK_WRAP_PLUG: | ||
564 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
565 | "(wrap plug detected)\n", | ||
566 | zfcp_get_busid_by_adapter(adapter)); | ||
567 | break; | ||
568 | case FSF_PSQ_LINK_NO_FCP: | ||
569 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
570 | "(adjacent node on link does not support FCP)\n", | ||
571 | zfcp_get_busid_by_adapter(adapter)); | ||
572 | break; | ||
573 | case FSF_PSQ_LINK_FIRMWARE_UPDATE: | ||
574 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
575 | "(firmware update in progress)\n", | ||
576 | zfcp_get_busid_by_adapter(adapter)); | ||
577 | break; | ||
578 | case FSF_PSQ_LINK_INVALID_WWPN: | ||
579 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
580 | "(duplicate or invalid WWPN detected)\n", | ||
581 | zfcp_get_busid_by_adapter(adapter)); | ||
582 | break; | ||
583 | case FSF_PSQ_LINK_NO_NPIV_SUPPORT: | ||
584 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
585 | "(no support for NPIV by Fabric)\n", | ||
586 | zfcp_get_busid_by_adapter(adapter)); | ||
587 | break; | ||
588 | case FSF_PSQ_LINK_NO_FCP_RESOURCES: | ||
589 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
590 | "(out of resource in FCP daughtercard)\n", | ||
591 | zfcp_get_busid_by_adapter(adapter)); | ||
592 | break; | ||
593 | case FSF_PSQ_LINK_NO_FABRIC_RESOURCES: | ||
594 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
595 | "(out of resource in Fabric)\n", | ||
596 | zfcp_get_busid_by_adapter(adapter)); | ||
597 | break; | ||
598 | case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE: | ||
599 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
600 | "(unable to Fabric login)\n", | ||
601 | zfcp_get_busid_by_adapter(adapter)); | ||
602 | break; | ||
603 | case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED: | ||
604 | ZFCP_LOG_NORMAL("WWPN assignment file corrupted on adapter %s\n", | ||
605 | zfcp_get_busid_by_adapter(adapter)); | ||
606 | break; | ||
607 | case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED: | ||
608 | ZFCP_LOG_NORMAL("Mode table corrupted on adapter %s\n", | ||
609 | zfcp_get_busid_by_adapter(adapter)); | ||
610 | break; | ||
611 | case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT: | ||
612 | ZFCP_LOG_NORMAL("No WWPN for assignment table on adapter %s\n", | ||
613 | zfcp_get_busid_by_adapter(adapter)); | ||
614 | break; | ||
615 | default: | ||
616 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
617 | "(warning: unknown reason code %d)\n", | ||
618 | zfcp_get_busid_by_adapter(adapter), | ||
619 | link_down->error_code); | ||
620 | } | ||
621 | |||
622 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | ||
623 | ZFCP_LOG_DEBUG("Debug information to link down: " | ||
624 | "primary_status=0x%02x " | ||
625 | "ioerr_code=0x%02x " | ||
626 | "action_code=0x%02x " | ||
627 | "reason_code=0x%02x " | ||
628 | "explanation_code=0x%02x " | ||
629 | "vendor_specific_code=0x%02x\n", | ||
630 | link_down->primary_status, | ||
631 | link_down->ioerr_code, | ||
632 | link_down->action_code, | ||
633 | link_down->reason_code, | ||
634 | link_down->explanation_code, | ||
635 | link_down->vendor_specific_code); | ||
636 | |||
637 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
638 | &adapter->status)) { | ||
639 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
640 | &adapter->status); | ||
641 | switch (link_down->error_code) { | ||
642 | case FSF_PSQ_LINK_NO_LIGHT: | ||
643 | case FSF_PSQ_LINK_WRAP_PLUG: | ||
644 | case FSF_PSQ_LINK_NO_FCP: | ||
645 | case FSF_PSQ_LINK_FIRMWARE_UPDATE: | ||
646 | zfcp_erp_adapter_reopen(adapter, 0); | ||
647 | break; | ||
648 | default: | ||
649 | zfcp_erp_adapter_failed(adapter); | ||
650 | } | ||
651 | } | ||
652 | } | ||
653 | |||
616 | /* | 654 | /* |
617 | * function: zfcp_fsf_req_dispatch | 655 | * function: zfcp_fsf_req_dispatch |
618 | * | 656 | * |
@@ -877,17 +915,32 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
877 | break; | 915 | break; |
878 | 916 | ||
879 | case FSF_STATUS_READ_LINK_DOWN: | 917 | case FSF_STATUS_READ_LINK_DOWN: |
880 | debug_text_event(adapter->erp_dbf, 0, "unsol_link_down:"); | 918 | switch (status_buffer->status_subtype) { |
881 | ZFCP_LOG_INFO("Local link to adapter %s is down\n", | 919 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: |
920 | ZFCP_LOG_INFO("Physical link to adapter %s is down\n", | ||
921 | zfcp_get_busid_by_adapter(adapter)); | ||
922 | break; | ||
923 | case FSF_STATUS_READ_SUB_FDISC_FAILED: | ||
924 | ZFCP_LOG_INFO("Local link to adapter %s is down " | ||
925 | "due to failed FDISC login\n", | ||
882 | zfcp_get_busid_by_adapter(adapter)); | 926 | zfcp_get_busid_by_adapter(adapter)); |
883 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 927 | break; |
884 | &adapter->status); | 928 | case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: |
885 | zfcp_erp_adapter_failed(adapter); | 929 | ZFCP_LOG_INFO("Local link to adapter %s is down " |
930 | "due to firmware update on adapter\n", | ||
931 | zfcp_get_busid_by_adapter(adapter)); | ||
932 | break; | ||
933 | default: | ||
934 | ZFCP_LOG_INFO("Local link to adapter %s is down " | ||
935 | "due to unknown reason\n", | ||
936 | zfcp_get_busid_by_adapter(adapter)); | ||
937 | }; | ||
938 | zfcp_fsf_link_down_info_eval(adapter, | ||
939 | (struct fsf_link_down_info *) &status_buffer->payload); | ||
886 | break; | 940 | break; |
887 | 941 | ||
888 | case FSF_STATUS_READ_LINK_UP: | 942 | case FSF_STATUS_READ_LINK_UP: |
889 | debug_text_event(adapter->erp_dbf, 2, "unsol_link_up:"); | 943 | ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. " |
890 | ZFCP_LOG_INFO("Local link to adapter %s was replugged. " | ||
891 | "Restarting operations on this adapter\n", | 944 | "Restarting operations on this adapter\n", |
892 | zfcp_get_busid_by_adapter(adapter)); | 945 | zfcp_get_busid_by_adapter(adapter)); |
893 | /* All ports should be marked as ready to run again */ | 946 | /* All ports should be marked as ready to run again */ |
@@ -922,6 +975,16 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
922 | } | 975 | } |
923 | break; | 976 | break; |
924 | 977 | ||
978 | case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: | ||
979 | debug_text_event(adapter->erp_dbf, 2, "unsol_features:"); | ||
980 | ZFCP_LOG_INFO("List of supported features on adapter %s has " | ||
981 | "been changed from 0x%08X to 0x%08X\n", | ||
982 | zfcp_get_busid_by_adapter(adapter), | ||
983 | *(u32*) (status_buffer->payload + 4), | ||
984 | *(u32*) (status_buffer->payload)); | ||
985 | adapter->adapter_features = *(u32*) status_buffer->payload; | ||
986 | break; | ||
987 | |||
925 | default: | 988 | default: |
926 | ZFCP_LOG_NORMAL("warning: An unsolicited status packet of unknown " | 989 | ZFCP_LOG_NORMAL("warning: An unsolicited status packet of unknown " |
927 | "type was received (debug info 0x%x)\n", | 990 | "type was received (debug info 0x%x)\n", |
@@ -1281,7 +1344,7 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
1281 | sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]); | 1344 | sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]); |
1282 | sbale[3].length = ct->resp[0].length; | 1345 | sbale[3].length = ct->resp[0].length; |
1283 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; | 1346 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; |
1284 | } else if (adapter->supported_features & | 1347 | } else if (adapter->adapter_features & |
1285 | FSF_FEATURE_ELS_CT_CHAINED_SBALS) { | 1348 | FSF_FEATURE_ELS_CT_CHAINED_SBALS) { |
1286 | /* try to use chained SBALs */ | 1349 | /* try to use chained SBALs */ |
1287 | bytes = zfcp_qdio_sbals_from_sg(fsf_req, | 1350 | bytes = zfcp_qdio_sbals_from_sg(fsf_req, |
@@ -1584,7 +1647,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1584 | sbale[3].addr = zfcp_sg_to_address(&els->resp[0]); | 1647 | sbale[3].addr = zfcp_sg_to_address(&els->resp[0]); |
1585 | sbale[3].length = els->resp[0].length; | 1648 | sbale[3].length = els->resp[0].length; |
1586 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; | 1649 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; |
1587 | } else if (adapter->supported_features & | 1650 | } else if (adapter->adapter_features & |
1588 | FSF_FEATURE_ELS_CT_CHAINED_SBALS) { | 1651 | FSF_FEATURE_ELS_CT_CHAINED_SBALS) { |
1589 | /* try to use chained SBALs */ | 1652 | /* try to use chained SBALs */ |
1590 | bytes = zfcp_qdio_sbals_from_sg(fsf_req, | 1653 | bytes = zfcp_qdio_sbals_from_sg(fsf_req, |
@@ -1877,7 +1940,9 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | |||
1877 | 1940 | ||
1878 | erp_action->fsf_req->erp_action = erp_action; | 1941 | erp_action->fsf_req->erp_action = erp_action; |
1879 | erp_action->fsf_req->qtcb->bottom.config.feature_selection = | 1942 | erp_action->fsf_req->qtcb->bottom.config.feature_selection = |
1880 | (FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING); | 1943 | FSF_FEATURE_CFDC | |
1944 | FSF_FEATURE_LUN_SHARING | | ||
1945 | FSF_FEATURE_UPDATE_ALERT; | ||
1881 | 1946 | ||
1882 | /* start QDIO request for this FSF request */ | 1947 | /* start QDIO request for this FSF request */ |
1883 | retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); | 1948 | retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); |
@@ -1918,7 +1983,8 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) | |||
1918 | ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n", | 1983 | ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n", |
1919 | bottom->low_qtcb_version, bottom->high_qtcb_version); | 1984 | bottom->low_qtcb_version, bottom->high_qtcb_version); |
1920 | adapter->fsf_lic_version = bottom->lic_version; | 1985 | adapter->fsf_lic_version = bottom->lic_version; |
1921 | adapter->supported_features = bottom->supported_features; | 1986 | adapter->adapter_features = bottom->adapter_features; |
1987 | adapter->connection_features = bottom->connection_features; | ||
1922 | adapter->peer_wwpn = 0; | 1988 | adapter->peer_wwpn = 0; |
1923 | adapter->peer_wwnn = 0; | 1989 | adapter->peer_wwnn = 0; |
1924 | adapter->peer_d_id = 0; | 1990 | adapter->peer_d_id = 0; |
@@ -1930,6 +1996,10 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) | |||
1930 | adapter->fc_topology = bottom->fc_topology; | 1996 | adapter->fc_topology = bottom->fc_topology; |
1931 | adapter->fc_link_speed = bottom->fc_link_speed; | 1997 | adapter->fc_link_speed = bottom->fc_link_speed; |
1932 | adapter->hydra_version = bottom->adapter_type; | 1998 | adapter->hydra_version = bottom->adapter_type; |
1999 | if (adapter->physical_wwpn == 0) | ||
2000 | adapter->physical_wwpn = adapter->wwpn; | ||
2001 | if (adapter->physical_s_id == 0) | ||
2002 | adapter->physical_s_id = adapter->s_id; | ||
1933 | } else { | 2003 | } else { |
1934 | adapter->wwnn = 0; | 2004 | adapter->wwnn = 0; |
1935 | adapter->wwpn = 0; | 2005 | adapter->wwpn = 0; |
@@ -1945,7 +2015,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) | |||
1945 | adapter->peer_wwnn = bottom->plogi_payload.wwnn; | 2015 | adapter->peer_wwnn = bottom->plogi_payload.wwnn; |
1946 | } | 2016 | } |
1947 | 2017 | ||
1948 | if(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT){ | 2018 | if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { |
1949 | adapter->hardware_version = bottom->hardware_version; | 2019 | adapter->hardware_version = bottom->hardware_version; |
1950 | memcpy(adapter->serial_number, bottom->serial_number, 17); | 2020 | memcpy(adapter->serial_number, bottom->serial_number, 17); |
1951 | EBCASC(adapter->serial_number, sizeof(adapter->serial_number)); | 2021 | EBCASC(adapter->serial_number, sizeof(adapter->serial_number)); |
@@ -2001,11 +2071,12 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
2001 | { | 2071 | { |
2002 | struct fsf_qtcb_bottom_config *bottom; | 2072 | struct fsf_qtcb_bottom_config *bottom; |
2003 | struct zfcp_adapter *adapter = fsf_req->adapter; | 2073 | struct zfcp_adapter *adapter = fsf_req->adapter; |
2074 | struct fsf_qtcb *qtcb = fsf_req->qtcb; | ||
2004 | 2075 | ||
2005 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) | 2076 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) |
2006 | return -EIO; | 2077 | return -EIO; |
2007 | 2078 | ||
2008 | switch (fsf_req->qtcb->header.fsf_status) { | 2079 | switch (qtcb->header.fsf_status) { |
2009 | 2080 | ||
2010 | case FSF_GOOD: | 2081 | case FSF_GOOD: |
2011 | if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) | 2082 | if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) |
@@ -2035,7 +2106,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
2035 | zfcp_erp_adapter_shutdown(adapter, 0); | 2106 | zfcp_erp_adapter_shutdown(adapter, 0); |
2036 | return -EIO; | 2107 | return -EIO; |
2037 | case FSF_TOPO_FABRIC: | 2108 | case FSF_TOPO_FABRIC: |
2038 | ZFCP_LOG_INFO("Switched fabric fibrechannel " | 2109 | ZFCP_LOG_NORMAL("Switched fabric fibrechannel " |
2039 | "network detected at adapter %s.\n", | 2110 | "network detected at adapter %s.\n", |
2040 | zfcp_get_busid_by_adapter(adapter)); | 2111 | zfcp_get_busid_by_adapter(adapter)); |
2041 | break; | 2112 | break; |
@@ -2053,7 +2124,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
2053 | zfcp_erp_adapter_shutdown(adapter, 0); | 2124 | zfcp_erp_adapter_shutdown(adapter, 0); |
2054 | return -EIO; | 2125 | return -EIO; |
2055 | } | 2126 | } |
2056 | bottom = &fsf_req->qtcb->bottom.config; | 2127 | bottom = &qtcb->bottom.config; |
2057 | if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { | 2128 | if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { |
2058 | ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) " | 2129 | ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) " |
2059 | "allowed by the adapter %s " | 2130 | "allowed by the adapter %s " |
@@ -2078,12 +2149,10 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
2078 | if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0)) | 2149 | if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0)) |
2079 | return -EIO; | 2150 | return -EIO; |
2080 | 2151 | ||
2081 | ZFCP_LOG_INFO("Local link to adapter %s is down\n", | 2152 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); |
2082 | zfcp_get_busid_by_adapter(adapter)); | 2153 | |
2083 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | | 2154 | zfcp_fsf_link_down_info_eval(adapter, |
2084 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 2155 | &qtcb->header.fsf_status_qual.link_down_info); |
2085 | &adapter->status); | ||
2086 | zfcp_erp_adapter_failed(adapter); | ||
2087 | break; | 2156 | break; |
2088 | default: | 2157 | default: |
2089 | debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); | 2158 | debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); |
@@ -2097,11 +2166,13 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
2097 | 2166 | ||
2098 | /** | 2167 | /** |
2099 | * zfcp_fsf_exchange_port_data - request information about local port | 2168 | * zfcp_fsf_exchange_port_data - request information about local port |
2169 | * @erp_action: ERP action for the adapter for which port data is requested | ||
2100 | * @adapter: for which port data is requested | 2170 | * @adapter: for which port data is requested |
2101 | * @data: response to exchange port data request | 2171 | * @data: response to exchange port data request |
2102 | */ | 2172 | */ |
2103 | int | 2173 | int |
2104 | zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | 2174 | zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, |
2175 | struct zfcp_adapter *adapter, | ||
2105 | struct fsf_qtcb_bottom_port *data) | 2176 | struct fsf_qtcb_bottom_port *data) |
2106 | { | 2177 | { |
2107 | volatile struct qdio_buffer_element *sbale; | 2178 | volatile struct qdio_buffer_element *sbale; |
@@ -2110,7 +2181,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | |||
2110 | struct zfcp_fsf_req *fsf_req; | 2181 | struct zfcp_fsf_req *fsf_req; |
2111 | struct timer_list *timer; | 2182 | struct timer_list *timer; |
2112 | 2183 | ||
2113 | if(!(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT)){ | 2184 | if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) { |
2114 | ZFCP_LOG_INFO("error: exchange port data " | 2185 | ZFCP_LOG_INFO("error: exchange port data " |
2115 | "command not supported by adapter %s\n", | 2186 | "command not supported by adapter %s\n", |
2116 | zfcp_get_busid_by_adapter(adapter)); | 2187 | zfcp_get_busid_by_adapter(adapter)); |
@@ -2134,6 +2205,12 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | |||
2134 | goto out; | 2205 | goto out; |
2135 | } | 2206 | } |
2136 | 2207 | ||
2208 | if (erp_action) { | ||
2209 | erp_action->fsf_req = fsf_req; | ||
2210 | fsf_req->erp_action = erp_action; | ||
2211 | } | ||
2212 | |||
2213 | if (data) | ||
2137 | fsf_req->data = (unsigned long) data; | 2214 | fsf_req->data = (unsigned long) data; |
2138 | 2215 | ||
2139 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); | 2216 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); |
@@ -2151,6 +2228,8 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | |||
2151 | "command on the adapter %s\n", | 2228 | "command on the adapter %s\n", |
2152 | zfcp_get_busid_by_adapter(adapter)); | 2229 | zfcp_get_busid_by_adapter(adapter)); |
2153 | zfcp_fsf_req_free(fsf_req); | 2230 | zfcp_fsf_req_free(fsf_req); |
2231 | if (erp_action) | ||
2232 | erp_action->fsf_req = NULL; | ||
2154 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | 2233 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, |
2155 | lock_flags); | 2234 | lock_flags); |
2156 | goto out; | 2235 | goto out; |
@@ -2179,23 +2258,40 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | |||
2179 | static void | 2258 | static void |
2180 | zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) | 2259 | zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) |
2181 | { | 2260 | { |
2182 | struct fsf_qtcb_bottom_port *bottom; | 2261 | struct zfcp_adapter *adapter = fsf_req->adapter; |
2183 | struct fsf_qtcb_bottom_port *data; | 2262 | struct fsf_qtcb *qtcb = fsf_req->qtcb; |
2184 | 2263 | struct fsf_qtcb_bottom_port *bottom, *data; | |
2185 | data = (struct fsf_qtcb_bottom_port*) fsf_req->data; | ||
2186 | 2264 | ||
2187 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) | 2265 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) |
2188 | return; | 2266 | return; |
2189 | 2267 | ||
2190 | switch (fsf_req->qtcb->header.fsf_status) { | 2268 | switch (qtcb->header.fsf_status) { |
2191 | case FSF_GOOD: | 2269 | case FSF_GOOD: |
2192 | bottom = &fsf_req->qtcb->bottom.port; | 2270 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); |
2193 | memcpy(data, bottom, sizeof(*data)); | 2271 | |
2272 | bottom = &qtcb->bottom.port; | ||
2273 | data = (struct fsf_qtcb_bottom_port*) fsf_req->data; | ||
2274 | if (data) | ||
2275 | memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); | ||
2276 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { | ||
2277 | adapter->physical_wwpn = bottom->wwpn; | ||
2278 | adapter->physical_s_id = bottom->fc_port_id; | ||
2279 | } else { | ||
2280 | adapter->physical_wwpn = adapter->wwpn; | ||
2281 | adapter->physical_s_id = adapter->s_id; | ||
2282 | } | ||
2283 | break; | ||
2284 | |||
2285 | case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: | ||
2286 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | ||
2287 | |||
2288 | zfcp_fsf_link_down_info_eval(adapter, | ||
2289 | &qtcb->header.fsf_status_qual.link_down_info); | ||
2194 | break; | 2290 | break; |
2195 | 2291 | ||
2196 | default: | 2292 | default: |
2197 | debug_text_event(fsf_req->adapter->erp_dbf, 0, "xchg-port-ng"); | 2293 | debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng"); |
2198 | debug_event(fsf_req->adapter->erp_dbf, 0, | 2294 | debug_event(adapter->erp_dbf, 0, |
2199 | &fsf_req->qtcb->header.fsf_status, sizeof(u32)); | 2295 | &fsf_req->qtcb->header.fsf_status, sizeof(u32)); |
2200 | } | 2296 | } |
2201 | } | 2297 | } |
@@ -2629,7 +2725,7 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | |||
2629 | &erp_action->port->status); | 2725 | &erp_action->port->status); |
2630 | /* save a pointer to this port */ | 2726 | /* save a pointer to this port */ |
2631 | erp_action->fsf_req->data = (unsigned long) erp_action->port; | 2727 | erp_action->fsf_req->data = (unsigned long) erp_action->port; |
2632 | /* port to be closeed */ | 2728 | /* port to be closed */ |
2633 | erp_action->fsf_req->qtcb->header.port_handle = | 2729 | erp_action->fsf_req->qtcb->header.port_handle = |
2634 | erp_action->port->handle; | 2730 | erp_action->port->handle; |
2635 | erp_action->fsf_req->erp_action = erp_action; | 2731 | erp_action->fsf_req->erp_action = erp_action; |
@@ -2833,6 +2929,7 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
2833 | erp_action->port->handle; | 2929 | erp_action->port->handle; |
2834 | erp_action->fsf_req->qtcb->bottom.support.fcp_lun = | 2930 | erp_action->fsf_req->qtcb->bottom.support.fcp_lun = |
2835 | erp_action->unit->fcp_lun; | 2931 | erp_action->unit->fcp_lun; |
2932 | if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE)) | ||
2836 | erp_action->fsf_req->qtcb->bottom.support.option = | 2933 | erp_action->fsf_req->qtcb->bottom.support.option = |
2837 | FSF_OPEN_LUN_SUPPRESS_BOXING; | 2934 | FSF_OPEN_LUN_SUPPRESS_BOXING; |
2838 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); | 2935 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); |
@@ -2880,7 +2977,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
2880 | struct fsf_qtcb_bottom_support *bottom; | 2977 | struct fsf_qtcb_bottom_support *bottom; |
2881 | struct fsf_queue_designator *queue_designator; | 2978 | struct fsf_queue_designator *queue_designator; |
2882 | u16 subtable, rule, counter; | 2979 | u16 subtable, rule, counter; |
2883 | u32 allowed, exclusive, readwrite; | 2980 | int exclusive, readwrite; |
2884 | 2981 | ||
2885 | unit = (struct zfcp_unit *) fsf_req->data; | 2982 | unit = (struct zfcp_unit *) fsf_req->data; |
2886 | 2983 | ||
@@ -2894,10 +2991,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
2894 | bottom = &fsf_req->qtcb->bottom.support; | 2991 | bottom = &fsf_req->qtcb->bottom.support; |
2895 | queue_designator = &header->fsf_status_qual.fsf_queue_designator; | 2992 | queue_designator = &header->fsf_status_qual.fsf_queue_designator; |
2896 | 2993 | ||
2897 | allowed = bottom->lun_access_info & FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED; | ||
2898 | exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE; | ||
2899 | readwrite = bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER; | ||
2900 | |||
2901 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | | 2994 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | |
2902 | ZFCP_STATUS_UNIT_SHARED | | 2995 | ZFCP_STATUS_UNIT_SHARED | |
2903 | ZFCP_STATUS_UNIT_READONLY, | 2996 | ZFCP_STATUS_UNIT_READONLY, |
@@ -3071,10 +3164,15 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
3071 | unit->handle); | 3164 | unit->handle); |
3072 | /* mark unit as open */ | 3165 | /* mark unit as open */ |
3073 | atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); | 3166 | atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); |
3074 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | | 3167 | |
3075 | ZFCP_STATUS_COMMON_ACCESS_BOXED, | 3168 | if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) && |
3076 | &unit->status); | 3169 | (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) && |
3077 | if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){ | 3170 | (adapter->ccw_device->id.dev_model != ZFCP_DEVICE_MODEL_PRIV)) { |
3171 | exclusive = (bottom->lun_access_info & | ||
3172 | FSF_UNIT_ACCESS_EXCLUSIVE); | ||
3173 | readwrite = (bottom->lun_access_info & | ||
3174 | FSF_UNIT_ACCESS_OUTBOUND_TRANSFER); | ||
3175 | |||
3078 | if (!exclusive) | 3176 | if (!exclusive) |
3079 | atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, | 3177 | atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, |
3080 | &unit->status); | 3178 | &unit->status); |
@@ -4164,7 +4262,7 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter, | |||
4164 | int direction; | 4262 | int direction; |
4165 | int retval = 0; | 4263 | int retval = 0; |
4166 | 4264 | ||
4167 | if (!(adapter->supported_features & FSF_FEATURE_CFDC)) { | 4265 | if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) { |
4168 | ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n", | 4266 | ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n", |
4169 | zfcp_get_busid_by_adapter(adapter)); | 4267 | zfcp_get_busid_by_adapter(adapter)); |
4170 | retval = -EOPNOTSUPP; | 4268 | retval = -EOPNOTSUPP; |
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 57ce0706007e..48719f055952 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h | |||
@@ -140,9 +140,18 @@ | |||
140 | #define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004 | 140 | #define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004 |
141 | 141 | ||
142 | /* FSF status qualifier (most significant 4 bytes), local link down */ | 142 | /* FSF status qualifier (most significant 4 bytes), local link down */ |
143 | #define FSF_PSQ_LINK_NOLIGHT 0x00000004 | 143 | #define FSF_PSQ_LINK_NO_LIGHT 0x00000004 |
144 | #define FSF_PSQ_LINK_WRAPPLUG 0x00000008 | 144 | #define FSF_PSQ_LINK_WRAP_PLUG 0x00000008 |
145 | #define FSF_PSQ_LINK_NOFCP 0x00000010 | 145 | #define FSF_PSQ_LINK_NO_FCP 0x00000010 |
146 | #define FSF_PSQ_LINK_FIRMWARE_UPDATE 0x00000020 | ||
147 | #define FSF_PSQ_LINK_INVALID_WWPN 0x00000100 | ||
148 | #define FSF_PSQ_LINK_NO_NPIV_SUPPORT 0x00000200 | ||
149 | #define FSF_PSQ_LINK_NO_FCP_RESOURCES 0x00000400 | ||
150 | #define FSF_PSQ_LINK_NO_FABRIC_RESOURCES 0x00000800 | ||
151 | #define FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE 0x00001000 | ||
152 | #define FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED 0x00002000 | ||
153 | #define FSF_PSQ_LINK_MODE_TABLE_CURRUPTED 0x00004000 | ||
154 | #define FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT 0x00008000 | ||
146 | 155 | ||
147 | /* payload size in status read buffer */ | 156 | /* payload size in status read buffer */ |
148 | #define FSF_STATUS_READ_PAYLOAD_SIZE 4032 | 157 | #define FSF_STATUS_READ_PAYLOAD_SIZE 4032 |
@@ -155,15 +164,21 @@ | |||
155 | #define FSF_STATUS_READ_INCOMING_ELS 0x00000002 | 164 | #define FSF_STATUS_READ_INCOMING_ELS 0x00000002 |
156 | #define FSF_STATUS_READ_SENSE_DATA_AVAIL 0x00000003 | 165 | #define FSF_STATUS_READ_SENSE_DATA_AVAIL 0x00000003 |
157 | #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 | 166 | #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 |
158 | #define FSF_STATUS_READ_LINK_DOWN 0x00000005 /* FIXME: really? */ | 167 | #define FSF_STATUS_READ_LINK_DOWN 0x00000005 |
159 | #define FSF_STATUS_READ_LINK_UP 0x00000006 | 168 | #define FSF_STATUS_READ_LINK_UP 0x00000006 |
160 | #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A | 169 | #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A |
161 | #define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B | 170 | #define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B |
171 | #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C | ||
162 | 172 | ||
163 | /* status subtypes in status read buffer */ | 173 | /* status subtypes in status read buffer */ |
164 | #define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT 0x00000001 | 174 | #define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT 0x00000001 |
165 | #define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002 | 175 | #define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002 |
166 | 176 | ||
177 | /* status subtypes for link down */ | ||
178 | #define FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK 0x00000000 | ||
179 | #define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001 | ||
180 | #define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002 | ||
181 | |||
167 | /* status subtypes for CFDC */ | 182 | /* status subtypes for CFDC */ |
168 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 | 183 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 |
169 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F | 184 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F |
@@ -194,11 +209,15 @@ | |||
194 | #define FSF_QTCB_LOG_SIZE 1024 | 209 | #define FSF_QTCB_LOG_SIZE 1024 |
195 | 210 | ||
196 | /* channel features */ | 211 | /* channel features */ |
197 | #define FSF_FEATURE_QTCB_SUPPRESSION 0x00000001 | ||
198 | #define FSF_FEATURE_CFDC 0x00000002 | 212 | #define FSF_FEATURE_CFDC 0x00000002 |
199 | #define FSF_FEATURE_LUN_SHARING 0x00000004 | 213 | #define FSF_FEATURE_LUN_SHARING 0x00000004 |
200 | #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 | 214 | #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 |
201 | #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 | 215 | #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 |
216 | #define FSF_FEATURE_UPDATE_ALERT 0x00000100 | ||
217 | |||
218 | /* host connection features */ | ||
219 | #define FSF_FEATURE_NPIV_MODE 0x00000001 | ||
220 | #define FSF_FEATURE_VM_ASSIGNED_WWPN 0x00000002 | ||
202 | 221 | ||
203 | /* option */ | 222 | /* option */ |
204 | #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 | 223 | #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 |
@@ -306,16 +325,23 @@ struct fsf_qual_sequence_error { | |||
306 | u32 res1[3]; | 325 | u32 res1[3]; |
307 | } __attribute__ ((packed)); | 326 | } __attribute__ ((packed)); |
308 | 327 | ||
309 | struct fsf_qual_locallink_error { | 328 | struct fsf_link_down_info { |
310 | u32 code; | 329 | u32 error_code; |
311 | u32 res1[3]; | 330 | u32 res1; |
331 | u8 res2[2]; | ||
332 | u8 primary_status; | ||
333 | u8 ioerr_code; | ||
334 | u8 action_code; | ||
335 | u8 reason_code; | ||
336 | u8 explanation_code; | ||
337 | u8 vendor_specific_code; | ||
312 | } __attribute__ ((packed)); | 338 | } __attribute__ ((packed)); |
313 | 339 | ||
314 | union fsf_prot_status_qual { | 340 | union fsf_prot_status_qual { |
315 | u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)]; | 341 | u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)]; |
316 | struct fsf_qual_version_error version_error; | 342 | struct fsf_qual_version_error version_error; |
317 | struct fsf_qual_sequence_error sequence_error; | 343 | struct fsf_qual_sequence_error sequence_error; |
318 | struct fsf_qual_locallink_error locallink_error; | 344 | struct fsf_link_down_info link_down_info; |
319 | } __attribute__ ((packed)); | 345 | } __attribute__ ((packed)); |
320 | 346 | ||
321 | struct fsf_qtcb_prefix { | 347 | struct fsf_qtcb_prefix { |
@@ -335,6 +361,7 @@ union fsf_status_qual { | |||
335 | u32 word[FSF_STATUS_QUALIFIER_SIZE / sizeof (u32)]; | 361 | u32 word[FSF_STATUS_QUALIFIER_SIZE / sizeof (u32)]; |
336 | u64 doubleword[FSF_STATUS_QUALIFIER_SIZE / sizeof(u64)]; | 362 | u64 doubleword[FSF_STATUS_QUALIFIER_SIZE / sizeof(u64)]; |
337 | struct fsf_queue_designator fsf_queue_designator; | 363 | struct fsf_queue_designator fsf_queue_designator; |
364 | struct fsf_link_down_info link_down_info; | ||
338 | } __attribute__ ((packed)); | 365 | } __attribute__ ((packed)); |
339 | 366 | ||
340 | struct fsf_qtcb_header { | 367 | struct fsf_qtcb_header { |
@@ -409,8 +436,8 @@ struct fsf_qtcb_bottom_config { | |||
409 | u32 low_qtcb_version; | 436 | u32 low_qtcb_version; |
410 | u32 max_qtcb_size; | 437 | u32 max_qtcb_size; |
411 | u32 max_data_transfer_size; | 438 | u32 max_data_transfer_size; |
412 | u32 supported_features; | 439 | u32 adapter_features; |
413 | u8 res1[4]; | 440 | u32 connection_features; |
414 | u32 fc_topology; | 441 | u32 fc_topology; |
415 | u32 fc_link_speed; | 442 | u32 fc_link_speed; |
416 | u32 adapter_type; | 443 | u32 adapter_type; |
@@ -428,7 +455,7 @@ struct fsf_qtcb_bottom_config { | |||
428 | } __attribute__ ((packed)); | 455 | } __attribute__ ((packed)); |
429 | 456 | ||
430 | struct fsf_qtcb_bottom_port { | 457 | struct fsf_qtcb_bottom_port { |
431 | u8 res1[8]; | 458 | u64 wwpn; |
432 | u32 fc_port_id; | 459 | u32 fc_port_id; |
433 | u32 port_type; | 460 | u32 port_type; |
434 | u32 port_state; | 461 | u32 port_state; |
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index e7345a74800a..c406ea5c5e95 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c | |||
@@ -68,6 +68,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(s_id, "0x%06x\n", adapter->s_id); | |||
68 | ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn); | 68 | ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn); |
69 | ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn); | 69 | ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn); |
70 | ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id); | 70 | ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id); |
71 | ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn); | ||
72 | ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id); | ||
71 | ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); | 73 | ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); |
72 | ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); | 74 | ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); |
73 | ZFCP_DEFINE_ADAPTER_ATTR(fc_link_speed, "%d Gb/s\n", adapter->fc_link_speed); | 75 | ZFCP_DEFINE_ADAPTER_ATTR(fc_link_speed, "%d Gb/s\n", adapter->fc_link_speed); |
@@ -261,6 +263,8 @@ static struct attribute *zfcp_adapter_attrs[] = { | |||
261 | &dev_attr_peer_wwnn.attr, | 263 | &dev_attr_peer_wwnn.attr, |
262 | &dev_attr_peer_wwpn.attr, | 264 | &dev_attr_peer_wwpn.attr, |
263 | &dev_attr_peer_d_id.attr, | 265 | &dev_attr_peer_d_id.attr, |
266 | &dev_attr_physical_wwpn.attr, | ||
267 | &dev_attr_physical_s_id.attr, | ||
264 | &dev_attr_card_version.attr, | 268 | &dev_attr_card_version.attr, |
265 | &dev_attr_lic_version.attr, | 269 | &dev_attr_lic_version.attr, |
266 | &dev_attr_fc_link_speed.attr, | 270 | &dev_attr_fc_link_speed.attr, |