.. | .. |
---|
4 | 4 | * |
---|
5 | 5 | * Implementation of FSF commands. |
---|
6 | 6 | * |
---|
7 | | - * Copyright IBM Corp. 2002, 2018 |
---|
| 7 | + * Copyright IBM Corp. 2002, 2020 |
---|
8 | 8 | */ |
---|
9 | 9 | |
---|
10 | 10 | #define KMSG_COMPONENT "zfcp" |
---|
11 | 11 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
---|
12 | 12 | |
---|
13 | 13 | #include <linux/blktrace_api.h> |
---|
| 14 | +#include <linux/jiffies.h> |
---|
| 15 | +#include <linux/types.h> |
---|
14 | 16 | #include <linux/slab.h> |
---|
15 | 17 | #include <scsi/fc/fc_els.h> |
---|
16 | 18 | #include "zfcp_ext.h" |
---|
.. | .. |
---|
18 | 20 | #include "zfcp_dbf.h" |
---|
19 | 21 | #include "zfcp_qdio.h" |
---|
20 | 22 | #include "zfcp_reqlist.h" |
---|
| 23 | +#include "zfcp_diag.h" |
---|
| 24 | + |
---|
| 25 | +/* timeout for FSF requests sent during scsi_eh: abort or FCP TMF */ |
---|
| 26 | +#define ZFCP_FSF_SCSI_ER_TIMEOUT (10*HZ) |
---|
| 27 | +/* timeout for: exchange config/port data outside ERP, or open/close WKA port */ |
---|
| 28 | +#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ) |
---|
21 | 29 | |
---|
22 | 30 | struct kmem_cache *zfcp_fsf_qtcb_cache; |
---|
23 | 31 | |
---|
.. | .. |
---|
79 | 87 | |
---|
80 | 88 | /** |
---|
81 | 89 | * zfcp_fsf_req_free - free memory used by fsf request |
---|
82 | | - * @fsf_req: pointer to struct zfcp_fsf_req |
---|
| 90 | + * @req: pointer to struct zfcp_fsf_req |
---|
83 | 91 | */ |
---|
84 | 92 | void zfcp_fsf_req_free(struct zfcp_fsf_req *req) |
---|
85 | 93 | { |
---|
86 | 94 | if (likely(req->pool)) { |
---|
87 | | - if (likely(req->qtcb)) |
---|
| 95 | + if (likely(!zfcp_fsf_req_is_status_read_buffer(req))) |
---|
88 | 96 | mempool_free(req->qtcb, req->adapter->pool.qtcb_pool); |
---|
89 | 97 | mempool_free(req, req->pool); |
---|
90 | 98 | return; |
---|
91 | 99 | } |
---|
92 | 100 | |
---|
93 | | - if (likely(req->qtcb)) |
---|
| 101 | + if (likely(!zfcp_fsf_req_is_status_read_buffer(req))) |
---|
94 | 102 | kmem_cache_free(zfcp_fsf_qtcb_cache, req->qtcb); |
---|
95 | 103 | kfree(req); |
---|
96 | 104 | } |
---|
.. | .. |
---|
112 | 120 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
---|
113 | 121 | } |
---|
114 | 122 | |
---|
| 123 | +void zfcp_fsf_fc_host_link_down(struct zfcp_adapter *adapter) |
---|
| 124 | +{ |
---|
| 125 | + struct Scsi_Host *shost = adapter->scsi_host; |
---|
| 126 | + |
---|
| 127 | + adapter->hydra_version = 0; |
---|
| 128 | + adapter->peer_wwpn = 0; |
---|
| 129 | + adapter->peer_wwnn = 0; |
---|
| 130 | + adapter->peer_d_id = 0; |
---|
| 131 | + |
---|
| 132 | + /* if there is no shost yet, we have nothing to zero-out */ |
---|
| 133 | + if (shost == NULL) |
---|
| 134 | + return; |
---|
| 135 | + |
---|
| 136 | + fc_host_port_id(shost) = 0; |
---|
| 137 | + fc_host_fabric_name(shost) = 0; |
---|
| 138 | + fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; |
---|
| 139 | + fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; |
---|
| 140 | + snprintf(fc_host_model(shost), FC_SYMBOLIC_NAME_SIZE, "0x%04x", 0); |
---|
| 141 | + memset(fc_host_active_fc4s(shost), 0, FC_FC4_LIST_SIZE); |
---|
| 142 | +} |
---|
| 143 | + |
---|
115 | 144 | static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, |
---|
116 | 145 | struct fsf_link_down_info *link_down) |
---|
117 | 146 | { |
---|
.. | .. |
---|
123 | 152 | atomic_or(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); |
---|
124 | 153 | |
---|
125 | 154 | zfcp_scsi_schedule_rports_block(adapter); |
---|
| 155 | + |
---|
| 156 | + zfcp_fsf_fc_host_link_down(adapter); |
---|
126 | 157 | |
---|
127 | 158 | if (!link_down) |
---|
128 | 159 | goto out; |
---|
.. | .. |
---|
389 | 420 | |
---|
390 | 421 | /** |
---|
391 | 422 | * zfcp_fsf_req_complete - process completion of a FSF request |
---|
392 | | - * @fsf_req: The FSF request that has been completed. |
---|
| 423 | + * @req: The FSF request that has been completed. |
---|
393 | 424 | * |
---|
394 | 425 | * When a request has been completed either from the FCP adapter, |
---|
395 | 426 | * or it has been dismissed due to a queue shutdown, this function |
---|
396 | 427 | * is called to process the completion status and trigger further |
---|
397 | 428 | * events related to the FSF request. |
---|
| 429 | + * Caller must ensure that the request has been removed from |
---|
| 430 | + * adapter->req_list, to protect against concurrent modification |
---|
| 431 | + * by zfcp_erp_strategy_check_fsfreq(). |
---|
398 | 432 | */ |
---|
399 | 433 | static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) |
---|
400 | 434 | { |
---|
401 | | - if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) { |
---|
| 435 | + struct zfcp_erp_action *erp_action; |
---|
| 436 | + |
---|
| 437 | + if (unlikely(zfcp_fsf_req_is_status_read_buffer(req))) { |
---|
402 | 438 | zfcp_fsf_status_read_handler(req); |
---|
403 | 439 | return; |
---|
404 | 440 | } |
---|
.. | .. |
---|
408 | 444 | zfcp_fsf_fsfstatus_eval(req); |
---|
409 | 445 | req->handler(req); |
---|
410 | 446 | |
---|
411 | | - if (req->erp_action) |
---|
412 | | - zfcp_erp_notify(req->erp_action, 0); |
---|
| 447 | + erp_action = req->erp_action; |
---|
| 448 | + if (erp_action) |
---|
| 449 | + zfcp_erp_notify(erp_action, 0); |
---|
413 | 450 | |
---|
414 | 451 | if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) |
---|
415 | 452 | zfcp_fsf_req_free(req); |
---|
.. | .. |
---|
452 | 489 | #define ZFCP_FSF_PORTSPEED_128GBIT (1 << 8) |
---|
453 | 490 | #define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15) |
---|
454 | 491 | |
---|
455 | | -static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed) |
---|
| 492 | +u32 zfcp_fsf_convert_portspeed(u32 fsf_speed) |
---|
456 | 493 | { |
---|
457 | 494 | u32 fdmi_speed = 0; |
---|
458 | 495 | if (fsf_speed & ZFCP_FSF_PORTSPEED_1GBIT) |
---|
.. | .. |
---|
482 | 519 | { |
---|
483 | 520 | struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config; |
---|
484 | 521 | struct zfcp_adapter *adapter = req->adapter; |
---|
485 | | - struct Scsi_Host *shost = adapter->scsi_host; |
---|
486 | | - struct fc_els_flogi *nsp, *plogi; |
---|
| 522 | + struct fc_els_flogi *plogi; |
---|
487 | 523 | |
---|
488 | 524 | /* adjust pointers for missing command code */ |
---|
489 | | - nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param |
---|
490 | | - - sizeof(u32)); |
---|
491 | 525 | plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload |
---|
492 | 526 | - sizeof(u32)); |
---|
493 | 527 | |
---|
494 | 528 | if (req->data) |
---|
495 | 529 | memcpy(req->data, bottom, sizeof(*bottom)); |
---|
496 | 530 | |
---|
497 | | - fc_host_port_name(shost) = be64_to_cpu(nsp->fl_wwpn); |
---|
498 | | - fc_host_node_name(shost) = be64_to_cpu(nsp->fl_wwnn); |
---|
499 | | - fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; |
---|
500 | | - |
---|
501 | 531 | adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK; |
---|
502 | 532 | adapter->stat_read_buf_num = max(bottom->status_read_buf_num, |
---|
503 | 533 | (u16)FSF_STATUS_READS_RECOM); |
---|
504 | | - |
---|
505 | | - if (fc_host_permanent_port_name(shost) == -1) |
---|
506 | | - fc_host_permanent_port_name(shost) = fc_host_port_name(shost); |
---|
507 | | - |
---|
508 | | - zfcp_scsi_set_prot(adapter); |
---|
509 | 534 | |
---|
510 | 535 | /* no error return above here, otherwise must fix call chains */ |
---|
511 | 536 | /* do not evaluate invalid fields */ |
---|
512 | 537 | if (req->qtcb->header.fsf_status == FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE) |
---|
513 | 538 | return 0; |
---|
514 | | - |
---|
515 | | - fc_host_port_id(shost) = ntoh24(bottom->s_id); |
---|
516 | | - fc_host_speed(shost) = |
---|
517 | | - zfcp_fsf_convert_portspeed(bottom->fc_link_speed); |
---|
518 | 539 | |
---|
519 | 540 | adapter->hydra_version = bottom->adapter_type; |
---|
520 | 541 | |
---|
.. | .. |
---|
523 | 544 | adapter->peer_d_id = ntoh24(bottom->peer_d_id); |
---|
524 | 545 | adapter->peer_wwpn = be64_to_cpu(plogi->fl_wwpn); |
---|
525 | 546 | adapter->peer_wwnn = be64_to_cpu(plogi->fl_wwnn); |
---|
526 | | - fc_host_port_type(shost) = FC_PORTTYPE_PTP; |
---|
527 | 547 | break; |
---|
528 | 548 | case FSF_TOPO_FABRIC: |
---|
529 | | - if (bottom->connection_features & FSF_FEATURE_NPIV_MODE) |
---|
530 | | - fc_host_port_type(shost) = FC_PORTTYPE_NPIV; |
---|
531 | | - else |
---|
532 | | - fc_host_port_type(shost) = FC_PORTTYPE_NPORT; |
---|
533 | 549 | break; |
---|
534 | 550 | case FSF_TOPO_AL: |
---|
535 | | - fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; |
---|
536 | | - /* fall through */ |
---|
537 | 551 | default: |
---|
538 | 552 | dev_err(&adapter->ccw_device->dev, |
---|
539 | 553 | "Unknown or unsupported arbitrated loop " |
---|
.. | .. |
---|
548 | 562 | static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) |
---|
549 | 563 | { |
---|
550 | 564 | struct zfcp_adapter *adapter = req->adapter; |
---|
| 565 | + struct zfcp_diag_header *const diag_hdr = |
---|
| 566 | + &adapter->diagnostics->config_data.header; |
---|
551 | 567 | struct fsf_qtcb *qtcb = req->qtcb; |
---|
552 | 568 | struct fsf_qtcb_bottom_config *bottom = &qtcb->bottom.config; |
---|
553 | | - struct Scsi_Host *shost = adapter->scsi_host; |
---|
554 | 569 | |
---|
555 | 570 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
---|
556 | 571 | return; |
---|
.. | .. |
---|
564 | 579 | |
---|
565 | 580 | switch (qtcb->header.fsf_status) { |
---|
566 | 581 | case FSF_GOOD: |
---|
| 582 | + /* |
---|
| 583 | + * usually we wait with an update till the cache is too old, |
---|
| 584 | + * but because we have the data available, update it anyway |
---|
| 585 | + */ |
---|
| 586 | + zfcp_diag_update_xdata(diag_hdr, bottom, false); |
---|
| 587 | + |
---|
| 588 | + zfcp_scsi_shost_update_config_data(adapter, bottom, false); |
---|
567 | 589 | if (zfcp_fsf_exchange_config_evaluate(req)) |
---|
568 | 590 | return; |
---|
569 | 591 | |
---|
.. | .. |
---|
579 | 601 | &adapter->status); |
---|
580 | 602 | break; |
---|
581 | 603 | case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: |
---|
582 | | - fc_host_node_name(shost) = 0; |
---|
583 | | - fc_host_port_name(shost) = 0; |
---|
584 | | - fc_host_port_id(shost) = 0; |
---|
585 | | - fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; |
---|
586 | | - fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; |
---|
587 | | - adapter->hydra_version = 0; |
---|
| 604 | + zfcp_diag_update_xdata(diag_hdr, bottom, true); |
---|
| 605 | + req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE; |
---|
588 | 606 | |
---|
589 | 607 | /* avoids adapter shutdown to be able to recognize |
---|
590 | 608 | * events such as LINK UP */ |
---|
.. | .. |
---|
592 | 610 | &adapter->status); |
---|
593 | 611 | zfcp_fsf_link_down_info_eval(req, |
---|
594 | 612 | &qtcb->header.fsf_status_qual.link_down_info); |
---|
| 613 | + |
---|
| 614 | + zfcp_scsi_shost_update_config_data(adapter, bottom, true); |
---|
595 | 615 | if (zfcp_fsf_exchange_config_evaluate(req)) |
---|
596 | 616 | return; |
---|
597 | 617 | break; |
---|
.. | .. |
---|
600 | 620 | return; |
---|
601 | 621 | } |
---|
602 | 622 | |
---|
603 | | - if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { |
---|
| 623 | + if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) |
---|
604 | 624 | adapter->hardware_version = bottom->hardware_version; |
---|
605 | | - memcpy(fc_host_serial_number(shost), bottom->serial_number, |
---|
606 | | - min(FC_SERIAL_NUMBER_SIZE, 17)); |
---|
607 | | - EBCASC(fc_host_serial_number(shost), |
---|
608 | | - min(FC_SERIAL_NUMBER_SIZE, 17)); |
---|
609 | | - } |
---|
610 | 625 | |
---|
611 | 626 | if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) { |
---|
612 | 627 | dev_err(&adapter->ccw_device->dev, |
---|
.. | .. |
---|
623 | 638 | } |
---|
624 | 639 | } |
---|
625 | 640 | |
---|
| 641 | +/* |
---|
| 642 | + * Mapping of FC Endpoint Security flag masks to mnemonics |
---|
| 643 | + * |
---|
| 644 | + * NOTE: Update macro ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH when making any |
---|
| 645 | + * changes. |
---|
| 646 | + */ |
---|
| 647 | +static const struct { |
---|
| 648 | + u32 mask; |
---|
| 649 | + char *name; |
---|
| 650 | +} zfcp_fsf_fc_security_mnemonics[] = { |
---|
| 651 | + { FSF_FC_SECURITY_AUTH, "Authentication" }, |
---|
| 652 | + { FSF_FC_SECURITY_ENC_FCSP2 | |
---|
| 653 | + FSF_FC_SECURITY_ENC_ERAS, "Encryption" }, |
---|
| 654 | +}; |
---|
| 655 | + |
---|
| 656 | +/* maximum strlen(zfcp_fsf_fc_security_mnemonics[...].name) + 1 */ |
---|
| 657 | +#define ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH 15 |
---|
| 658 | + |
---|
| 659 | +/** |
---|
| 660 | + * zfcp_fsf_scnprint_fc_security() - translate FC Endpoint Security flags into |
---|
| 661 | + * mnemonics and place in a buffer |
---|
| 662 | + * @buf : the buffer to place the translated FC Endpoint Security flag(s) |
---|
| 663 | + * into |
---|
| 664 | + * @size : the size of the buffer, including the trailing null space |
---|
| 665 | + * @fc_security: one or more FC Endpoint Security flags, or zero |
---|
| 666 | + * @fmt : specifies whether a list or a single item is to be put into the |
---|
| 667 | + * buffer |
---|
| 668 | + * |
---|
| 669 | + * The Fibre Channel (FC) Endpoint Security flags are translated into mnemonics. |
---|
| 670 | + * If the FC Endpoint Security flags are zero "none" is placed into the buffer. |
---|
| 671 | + * |
---|
| 672 | + * With ZFCP_FSF_PRINT_FMT_LIST the mnemonics are placed as a list separated by |
---|
| 673 | + * a comma followed by a space into the buffer. If one or more FC Endpoint |
---|
| 674 | + * Security flags cannot be translated into a mnemonic, as they are undefined |
---|
| 675 | + * in zfcp_fsf_fc_security_mnemonics, their bitwise ORed value in hexadecimal |
---|
| 676 | + * representation is placed into the buffer. |
---|
| 677 | + * |
---|
| 678 | + * With ZFCP_FSF_PRINT_FMT_SINGLEITEM only one single mnemonic is placed into |
---|
| 679 | + * the buffer. If the FC Endpoint Security flag cannot be translated, as it is |
---|
| 680 | + * undefined in zfcp_fsf_fc_security_mnemonics, its value in hexadecimal |
---|
| 681 | + * representation is placed into the buffer. If more than one FC Endpoint |
---|
| 682 | + * Security flag was specified, their value in hexadecimal representation is |
---|
| 683 | + * placed into the buffer. The macro ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH |
---|
| 684 | + * can be used to define a buffer that is large enough to hold one mnemonic. |
---|
| 685 | + * |
---|
| 686 | + * Return: The number of characters written into buf not including the trailing |
---|
| 687 | + * '\0'. If size is == 0 the function returns 0. |
---|
| 688 | + */ |
---|
| 689 | +ssize_t zfcp_fsf_scnprint_fc_security(char *buf, size_t size, u32 fc_security, |
---|
| 690 | + enum zfcp_fsf_print_fmt fmt) |
---|
| 691 | +{ |
---|
| 692 | + const char *prefix = ""; |
---|
| 693 | + ssize_t len = 0; |
---|
| 694 | + int i; |
---|
| 695 | + |
---|
| 696 | + if (fc_security == 0) |
---|
| 697 | + return scnprintf(buf, size, "none"); |
---|
| 698 | + if (fmt == ZFCP_FSF_PRINT_FMT_SINGLEITEM && hweight32(fc_security) != 1) |
---|
| 699 | + return scnprintf(buf, size, "0x%08x", fc_security); |
---|
| 700 | + |
---|
| 701 | + for (i = 0; i < ARRAY_SIZE(zfcp_fsf_fc_security_mnemonics); i++) { |
---|
| 702 | + if (!(fc_security & zfcp_fsf_fc_security_mnemonics[i].mask)) |
---|
| 703 | + continue; |
---|
| 704 | + |
---|
| 705 | + len += scnprintf(buf + len, size - len, "%s%s", prefix, |
---|
| 706 | + zfcp_fsf_fc_security_mnemonics[i].name); |
---|
| 707 | + prefix = ", "; |
---|
| 708 | + fc_security &= ~zfcp_fsf_fc_security_mnemonics[i].mask; |
---|
| 709 | + } |
---|
| 710 | + |
---|
| 711 | + if (fc_security != 0) |
---|
| 712 | + len += scnprintf(buf + len, size - len, "%s0x%08x", |
---|
| 713 | + prefix, fc_security); |
---|
| 714 | + |
---|
| 715 | + return len; |
---|
| 716 | +} |
---|
| 717 | + |
---|
| 718 | +static void zfcp_fsf_dbf_adapter_fc_security(struct zfcp_adapter *adapter, |
---|
| 719 | + struct zfcp_fsf_req *req) |
---|
| 720 | +{ |
---|
| 721 | + if (adapter->fc_security_algorithms == |
---|
| 722 | + adapter->fc_security_algorithms_old) { |
---|
| 723 | + /* no change, no trace */ |
---|
| 724 | + return; |
---|
| 725 | + } |
---|
| 726 | + |
---|
| 727 | + zfcp_dbf_hba_fsf_fces("fsfcesa", req, ZFCP_DBF_INVALID_WWPN, |
---|
| 728 | + adapter->fc_security_algorithms_old, |
---|
| 729 | + adapter->fc_security_algorithms); |
---|
| 730 | + |
---|
| 731 | + adapter->fc_security_algorithms_old = adapter->fc_security_algorithms; |
---|
| 732 | +} |
---|
| 733 | + |
---|
626 | 734 | static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) |
---|
627 | 735 | { |
---|
628 | 736 | struct zfcp_adapter *adapter = req->adapter; |
---|
629 | 737 | struct fsf_qtcb_bottom_port *bottom = &req->qtcb->bottom.port; |
---|
630 | | - struct Scsi_Host *shost = adapter->scsi_host; |
---|
631 | 738 | |
---|
632 | 739 | if (req->data) |
---|
633 | 740 | memcpy(req->data, bottom, sizeof(*bottom)); |
---|
634 | 741 | |
---|
635 | | - if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { |
---|
636 | | - fc_host_permanent_port_name(shost) = bottom->wwpn; |
---|
637 | | - } else |
---|
638 | | - fc_host_permanent_port_name(shost) = fc_host_port_name(shost); |
---|
639 | | - fc_host_maxframe_size(shost) = bottom->maximum_frame_size; |
---|
640 | | - fc_host_supported_speeds(shost) = |
---|
641 | | - zfcp_fsf_convert_portspeed(bottom->supported_speed); |
---|
642 | | - memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types, |
---|
643 | | - FC_FC4_LIST_SIZE); |
---|
644 | | - memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, |
---|
645 | | - FC_FC4_LIST_SIZE); |
---|
| 742 | + if (adapter->adapter_features & FSF_FEATURE_FC_SECURITY) |
---|
| 743 | + adapter->fc_security_algorithms = |
---|
| 744 | + bottom->fc_security_algorithms; |
---|
| 745 | + else |
---|
| 746 | + adapter->fc_security_algorithms = 0; |
---|
| 747 | + zfcp_fsf_dbf_adapter_fc_security(adapter, req); |
---|
646 | 748 | } |
---|
647 | 749 | |
---|
648 | 750 | static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) |
---|
649 | 751 | { |
---|
| 752 | + struct zfcp_diag_header *const diag_hdr = |
---|
| 753 | + &req->adapter->diagnostics->port_data.header; |
---|
650 | 754 | struct fsf_qtcb *qtcb = req->qtcb; |
---|
| 755 | + struct fsf_qtcb_bottom_port *bottom = &qtcb->bottom.port; |
---|
651 | 756 | |
---|
652 | 757 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
---|
653 | 758 | return; |
---|
654 | 759 | |
---|
655 | 760 | switch (qtcb->header.fsf_status) { |
---|
656 | 761 | case FSF_GOOD: |
---|
| 762 | + /* |
---|
| 763 | + * usually we wait with an update till the cache is too old, |
---|
| 764 | + * but because we have the data available, update it anyway |
---|
| 765 | + */ |
---|
| 766 | + zfcp_diag_update_xdata(diag_hdr, bottom, false); |
---|
| 767 | + |
---|
| 768 | + zfcp_scsi_shost_update_port_data(req->adapter, bottom); |
---|
657 | 769 | zfcp_fsf_exchange_port_evaluate(req); |
---|
658 | 770 | break; |
---|
659 | 771 | case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: |
---|
660 | | - zfcp_fsf_exchange_port_evaluate(req); |
---|
| 772 | + zfcp_diag_update_xdata(diag_hdr, bottom, true); |
---|
| 773 | + req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE; |
---|
| 774 | + |
---|
661 | 775 | zfcp_fsf_link_down_info_eval(req, |
---|
662 | 776 | &qtcb->header.fsf_status_qual.link_down_info); |
---|
| 777 | + |
---|
| 778 | + zfcp_scsi_shost_update_port_data(req->adapter, bottom); |
---|
| 779 | + zfcp_fsf_exchange_port_evaluate(req); |
---|
663 | 780 | break; |
---|
664 | 781 | } |
---|
665 | 782 | } |
---|
.. | .. |
---|
715 | 832 | init_completion(&req->completion); |
---|
716 | 833 | |
---|
717 | 834 | req->adapter = adapter; |
---|
718 | | - req->fsf_command = fsf_cmd; |
---|
719 | 835 | req->req_id = adapter->req_no; |
---|
720 | 836 | |
---|
721 | 837 | if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) { |
---|
.. | .. |
---|
730 | 846 | return ERR_PTR(-ENOMEM); |
---|
731 | 847 | } |
---|
732 | 848 | |
---|
733 | | - req->seq_no = adapter->fsf_req_seq_no; |
---|
734 | 849 | req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; |
---|
735 | 850 | req->qtcb->prefix.req_id = req->req_id; |
---|
736 | 851 | req->qtcb->prefix.ulp_info = 26; |
---|
737 | | - req->qtcb->prefix.qtcb_type = fsf_qtcb_type[req->fsf_command]; |
---|
| 852 | + req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_cmd]; |
---|
738 | 853 | req->qtcb->prefix.qtcb_version = FSF_QTCB_CURRENT_VERSION; |
---|
739 | 854 | req->qtcb->header.req_handle = req->req_id; |
---|
740 | | - req->qtcb->header.fsf_command = req->fsf_command; |
---|
| 855 | + req->qtcb->header.fsf_command = fsf_cmd; |
---|
741 | 856 | } |
---|
742 | 857 | |
---|
743 | 858 | zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype, |
---|
.. | .. |
---|
748 | 863 | |
---|
749 | 864 | static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) |
---|
750 | 865 | { |
---|
| 866 | + const bool is_srb = zfcp_fsf_req_is_status_read_buffer(req); |
---|
751 | 867 | struct zfcp_adapter *adapter = req->adapter; |
---|
752 | 868 | struct zfcp_qdio *qdio = adapter->qdio; |
---|
753 | | - int with_qtcb = (req->qtcb != NULL); |
---|
754 | | - int req_id = req->req_id; |
---|
| 869 | + unsigned long req_id = req->req_id; |
---|
755 | 870 | |
---|
756 | 871 | zfcp_reqlist_add(adapter->req_list, req); |
---|
757 | 872 | |
---|
.. | .. |
---|
765 | 880 | return -EIO; |
---|
766 | 881 | } |
---|
767 | 882 | |
---|
| 883 | + /* |
---|
| 884 | + * NOTE: DO NOT TOUCH ASYNC req PAST THIS POINT. |
---|
| 885 | + * ONLY TOUCH SYNC req AGAIN ON req->completion. |
---|
| 886 | + * |
---|
| 887 | + * The request might complete and be freed concurrently at any point |
---|
| 888 | + * now. This is not protected by the QDIO-lock (req_q_lock). So any |
---|
| 889 | + * uncontrolled access after this might result in an use-after-free bug. |
---|
| 890 | + * Only if the request doesn't have ZFCP_STATUS_FSFREQ_CLEANUP set, and |
---|
| 891 | + * when it is completed via req->completion, is it safe to use req |
---|
| 892 | + * again. |
---|
| 893 | + */ |
---|
| 894 | + |
---|
768 | 895 | /* Don't increase for unsolicited status */ |
---|
769 | | - if (with_qtcb) |
---|
| 896 | + if (!is_srb) |
---|
770 | 897 | adapter->fsf_req_seq_no++; |
---|
771 | 898 | adapter->req_no++; |
---|
772 | 899 | |
---|
.. | .. |
---|
775 | 902 | |
---|
776 | 903 | /** |
---|
777 | 904 | * zfcp_fsf_status_read - send status read request |
---|
778 | | - * @adapter: pointer to struct zfcp_adapter |
---|
779 | | - * @req_flags: request flags |
---|
| 905 | + * @qdio: pointer to struct zfcp_qdio |
---|
780 | 906 | * Returns: 0 on success, ERROR otherwise |
---|
781 | 907 | */ |
---|
782 | 908 | int zfcp_fsf_status_read(struct zfcp_qdio *qdio) |
---|
.. | .. |
---|
814 | 940 | retval = zfcp_fsf_req_send(req); |
---|
815 | 941 | if (retval) |
---|
816 | 942 | goto failed_req_send; |
---|
| 943 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
817 | 944 | |
---|
818 | 945 | goto out; |
---|
819 | 946 | |
---|
.. | .. |
---|
873 | 1000 | switch (fsq->word[0]) { |
---|
874 | 1001 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
---|
875 | 1002 | zfcp_fc_test_link(zfcp_sdev->port); |
---|
876 | | - /* fall through */ |
---|
| 1003 | + fallthrough; |
---|
877 | 1004 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
---|
878 | 1005 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
879 | 1006 | break; |
---|
.. | .. |
---|
922 | 1049 | req->qtcb->header.port_handle = zfcp_sdev->port->handle; |
---|
923 | 1050 | req->qtcb->bottom.support.req_handle = (u64) old_req_id; |
---|
924 | 1051 | |
---|
925 | | - zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); |
---|
926 | | - if (!zfcp_fsf_req_send(req)) |
---|
| 1052 | + zfcp_fsf_start_timer(req, ZFCP_FSF_SCSI_ER_TIMEOUT); |
---|
| 1053 | + if (!zfcp_fsf_req_send(req)) { |
---|
| 1054 | + /* NOTE: DO NOT TOUCH req, UNTIL IT COMPLETES! */ |
---|
927 | 1055 | goto out; |
---|
| 1056 | + } |
---|
928 | 1057 | |
---|
929 | 1058 | out_error_free: |
---|
930 | 1059 | zfcp_fsf_req_free(req); |
---|
.. | .. |
---|
966 | 1095 | break; |
---|
967 | 1096 | case FSF_PORT_HANDLE_NOT_VALID: |
---|
968 | 1097 | zfcp_erp_adapter_reopen(adapter, 0, "fsscth1"); |
---|
969 | | - /* fall through */ |
---|
| 1098 | + fallthrough; |
---|
970 | 1099 | case FSF_GENERIC_COMMAND_REJECTED: |
---|
971 | 1100 | case FSF_PAYLOAD_SIZE_MISMATCH: |
---|
972 | 1101 | case FSF_REQUEST_SIZE_TOO_LARGE: |
---|
.. | .. |
---|
1067 | 1196 | |
---|
1068 | 1197 | /** |
---|
1069 | 1198 | * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS) |
---|
| 1199 | + * @wka_port: pointer to zfcp WKA port to send CT/GS to |
---|
1070 | 1200 | * @ct: pointer to struct zfcp_send_ct with data for request |
---|
1071 | 1201 | * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req |
---|
| 1202 | + * @timeout: timeout that hardware should use, and a later software timeout |
---|
1072 | 1203 | */ |
---|
1073 | 1204 | int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port, |
---|
1074 | 1205 | struct zfcp_fsf_ct_els *ct, mempool_t *pool, |
---|
.. | .. |
---|
1105 | 1236 | ret = zfcp_fsf_req_send(req); |
---|
1106 | 1237 | if (ret) |
---|
1107 | 1238 | goto failed_send; |
---|
| 1239 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
1108 | 1240 | |
---|
1109 | 1241 | goto out; |
---|
1110 | 1242 | |
---|
.. | .. |
---|
1149 | 1281 | break; |
---|
1150 | 1282 | case FSF_SBAL_MISMATCH: |
---|
1151 | 1283 | /* should never occur, avoided in zfcp_fsf_send_els */ |
---|
1152 | | - /* fall through */ |
---|
| 1284 | + fallthrough; |
---|
1153 | 1285 | default: |
---|
1154 | 1286 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
1155 | 1287 | break; |
---|
.. | .. |
---|
1161 | 1293 | |
---|
1162 | 1294 | /** |
---|
1163 | 1295 | * zfcp_fsf_send_els - initiate an ELS command (FC-FS) |
---|
| 1296 | + * @adapter: pointer to zfcp adapter |
---|
| 1297 | + * @d_id: N_Port_ID to send ELS to |
---|
1164 | 1298 | * @els: pointer to struct zfcp_send_els with data for the command |
---|
| 1299 | + * @timeout: timeout that hardware should use, and a later software timeout |
---|
1165 | 1300 | */ |
---|
1166 | 1301 | int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id, |
---|
1167 | 1302 | struct zfcp_fsf_ct_els *els, unsigned int timeout) |
---|
.. | .. |
---|
1202 | 1337 | ret = zfcp_fsf_req_send(req); |
---|
1203 | 1338 | if (ret) |
---|
1204 | 1339 | goto failed_send; |
---|
| 1340 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
1205 | 1341 | |
---|
1206 | 1342 | goto out; |
---|
1207 | 1343 | |
---|
.. | .. |
---|
1236 | 1372 | |
---|
1237 | 1373 | req->qtcb->bottom.config.feature_selection = |
---|
1238 | 1374 | FSF_FEATURE_NOTIFICATION_LOST | |
---|
1239 | | - FSF_FEATURE_UPDATE_ALERT; |
---|
| 1375 | + FSF_FEATURE_UPDATE_ALERT | |
---|
| 1376 | + FSF_FEATURE_REQUEST_SFP_DATA | |
---|
| 1377 | + FSF_FEATURE_FC_SECURITY; |
---|
1240 | 1378 | req->erp_action = erp_action; |
---|
1241 | 1379 | req->handler = zfcp_fsf_exchange_config_data_handler; |
---|
1242 | 1380 | erp_action->fsf_req_id = req->req_id; |
---|
.. | .. |
---|
1247 | 1385 | zfcp_fsf_req_free(req); |
---|
1248 | 1386 | erp_action->fsf_req_id = 0; |
---|
1249 | 1387 | } |
---|
| 1388 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
1250 | 1389 | out: |
---|
1251 | 1390 | spin_unlock_irq(&qdio->req_q_lock); |
---|
1252 | 1391 | return retval; |
---|
1253 | 1392 | } |
---|
1254 | 1393 | |
---|
| 1394 | + |
---|
| 1395 | +/** |
---|
| 1396 | + * zfcp_fsf_exchange_config_data_sync() - Request information about FCP channel. |
---|
| 1397 | + * @qdio: pointer to the QDIO-Queue to use for sending the command. |
---|
| 1398 | + * @data: pointer to the QTCB-Bottom for storing the result of the command, |
---|
| 1399 | + * might be %NULL. |
---|
| 1400 | + * |
---|
| 1401 | + * Returns: |
---|
| 1402 | + * * 0 - Exchange Config Data was successful, @data is complete |
---|
| 1403 | + * * -EIO - Exchange Config Data was not successful, @data is invalid |
---|
| 1404 | + * * -EAGAIN - @data contains incomplete data |
---|
| 1405 | + * * -ENOMEM - Some memory allocation failed along the way |
---|
| 1406 | + */ |
---|
1255 | 1407 | int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, |
---|
1256 | 1408 | struct fsf_qtcb_bottom_config *data) |
---|
1257 | 1409 | { |
---|
.. | .. |
---|
1275 | 1427 | |
---|
1276 | 1428 | req->qtcb->bottom.config.feature_selection = |
---|
1277 | 1429 | FSF_FEATURE_NOTIFICATION_LOST | |
---|
1278 | | - FSF_FEATURE_UPDATE_ALERT; |
---|
| 1430 | + FSF_FEATURE_UPDATE_ALERT | |
---|
| 1431 | + FSF_FEATURE_REQUEST_SFP_DATA | |
---|
| 1432 | + FSF_FEATURE_FC_SECURITY; |
---|
1279 | 1433 | |
---|
1280 | 1434 | if (data) |
---|
1281 | 1435 | req->data = data; |
---|
.. | .. |
---|
1283 | 1437 | zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); |
---|
1284 | 1438 | retval = zfcp_fsf_req_send(req); |
---|
1285 | 1439 | spin_unlock_irq(&qdio->req_q_lock); |
---|
1286 | | - if (!retval) |
---|
| 1440 | + |
---|
| 1441 | + if (!retval) { |
---|
| 1442 | + /* NOTE: ONLY TOUCH SYNC req AGAIN ON req->completion. */ |
---|
1287 | 1443 | wait_for_completion(&req->completion); |
---|
| 1444 | + |
---|
| 1445 | + if (req->status & |
---|
| 1446 | + (ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_DISMISSED)) |
---|
| 1447 | + retval = -EIO; |
---|
| 1448 | + else if (req->status & ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE) |
---|
| 1449 | + retval = -EAGAIN; |
---|
| 1450 | + } |
---|
1288 | 1451 | |
---|
1289 | 1452 | zfcp_fsf_req_free(req); |
---|
1290 | 1453 | return retval; |
---|
.. | .. |
---|
1334 | 1497 | zfcp_fsf_req_free(req); |
---|
1335 | 1498 | erp_action->fsf_req_id = 0; |
---|
1336 | 1499 | } |
---|
| 1500 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
1337 | 1501 | out: |
---|
1338 | 1502 | spin_unlock_irq(&qdio->req_q_lock); |
---|
1339 | 1503 | return retval; |
---|
1340 | 1504 | } |
---|
1341 | 1505 | |
---|
1342 | 1506 | /** |
---|
1343 | | - * zfcp_fsf_exchange_port_data_sync - request information about local port |
---|
1344 | | - * @qdio: pointer to struct zfcp_qdio |
---|
1345 | | - * @data: pointer to struct fsf_qtcb_bottom_port |
---|
1346 | | - * Returns: 0 on success, error otherwise |
---|
| 1507 | + * zfcp_fsf_exchange_port_data_sync() - Request information about local port. |
---|
| 1508 | + * @qdio: pointer to the QDIO-Queue to use for sending the command. |
---|
| 1509 | + * @data: pointer to the QTCB-Bottom for storing the result of the command, |
---|
| 1510 | + * might be %NULL. |
---|
| 1511 | + * |
---|
| 1512 | + * Returns: |
---|
| 1513 | + * * 0 - Exchange Port Data was successful, @data is complete |
---|
| 1514 | + * * -EIO - Exchange Port Data was not successful, @data is invalid |
---|
| 1515 | + * * -EAGAIN - @data contains incomplete data |
---|
| 1516 | + * * -ENOMEM - Some memory allocation failed along the way |
---|
| 1517 | + * * -EOPNOTSUPP - This operation is not supported |
---|
1347 | 1518 | */ |
---|
1348 | 1519 | int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio, |
---|
1349 | 1520 | struct fsf_qtcb_bottom_port *data) |
---|
.. | .. |
---|
1376 | 1547 | retval = zfcp_fsf_req_send(req); |
---|
1377 | 1548 | spin_unlock_irq(&qdio->req_q_lock); |
---|
1378 | 1549 | |
---|
1379 | | - if (!retval) |
---|
| 1550 | + if (!retval) { |
---|
| 1551 | + /* NOTE: ONLY TOUCH SYNC req AGAIN ON req->completion. */ |
---|
1380 | 1552 | wait_for_completion(&req->completion); |
---|
1381 | 1553 | |
---|
1382 | | - zfcp_fsf_req_free(req); |
---|
| 1554 | + if (req->status & |
---|
| 1555 | + (ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_DISMISSED)) |
---|
| 1556 | + retval = -EIO; |
---|
| 1557 | + else if (req->status & ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE) |
---|
| 1558 | + retval = -EAGAIN; |
---|
| 1559 | + } |
---|
1383 | 1560 | |
---|
| 1561 | + zfcp_fsf_req_free(req); |
---|
1384 | 1562 | return retval; |
---|
1385 | 1563 | |
---|
1386 | 1564 | out_unlock: |
---|
.. | .. |
---|
1388 | 1566 | return retval; |
---|
1389 | 1567 | } |
---|
1390 | 1568 | |
---|
| 1569 | +static void zfcp_fsf_log_port_fc_security(struct zfcp_port *port, |
---|
| 1570 | + struct zfcp_fsf_req *req) |
---|
| 1571 | +{ |
---|
| 1572 | + char mnemonic_old[ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH]; |
---|
| 1573 | + char mnemonic_new[ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH]; |
---|
| 1574 | + |
---|
| 1575 | + if (port->connection_info == port->connection_info_old) { |
---|
| 1576 | + /* no change, no log nor trace */ |
---|
| 1577 | + return; |
---|
| 1578 | + } |
---|
| 1579 | + |
---|
| 1580 | + zfcp_dbf_hba_fsf_fces("fsfcesp", req, port->wwpn, |
---|
| 1581 | + port->connection_info_old, |
---|
| 1582 | + port->connection_info); |
---|
| 1583 | + |
---|
| 1584 | + zfcp_fsf_scnprint_fc_security(mnemonic_old, sizeof(mnemonic_old), |
---|
| 1585 | + port->connection_info_old, |
---|
| 1586 | + ZFCP_FSF_PRINT_FMT_SINGLEITEM); |
---|
| 1587 | + zfcp_fsf_scnprint_fc_security(mnemonic_new, sizeof(mnemonic_new), |
---|
| 1588 | + port->connection_info, |
---|
| 1589 | + ZFCP_FSF_PRINT_FMT_SINGLEITEM); |
---|
| 1590 | + |
---|
| 1591 | + if (strncmp(mnemonic_old, mnemonic_new, |
---|
| 1592 | + ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH) == 0) { |
---|
| 1593 | + /* no change in string representation, no log */ |
---|
| 1594 | + goto out; |
---|
| 1595 | + } |
---|
| 1596 | + |
---|
| 1597 | + if (port->connection_info_old == 0) { |
---|
| 1598 | + /* activation */ |
---|
| 1599 | + dev_info(&port->adapter->ccw_device->dev, |
---|
| 1600 | + "FC Endpoint Security of connection to remote port 0x%16llx enabled: %s\n", |
---|
| 1601 | + port->wwpn, mnemonic_new); |
---|
| 1602 | + } else if (port->connection_info == 0) { |
---|
| 1603 | + /* deactivation */ |
---|
| 1604 | + dev_warn(&port->adapter->ccw_device->dev, |
---|
| 1605 | + "FC Endpoint Security of connection to remote port 0x%16llx disabled: was %s\n", |
---|
| 1606 | + port->wwpn, mnemonic_old); |
---|
| 1607 | + } else { |
---|
| 1608 | + /* change */ |
---|
| 1609 | + dev_warn(&port->adapter->ccw_device->dev, |
---|
| 1610 | + "FC Endpoint Security of connection to remote port 0x%16llx changed: from %s to %s\n", |
---|
| 1611 | + port->wwpn, mnemonic_old, mnemonic_new); |
---|
| 1612 | + } |
---|
| 1613 | + |
---|
| 1614 | +out: |
---|
| 1615 | + port->connection_info_old = port->connection_info; |
---|
| 1616 | +} |
---|
| 1617 | + |
---|
| 1618 | +static void zfcp_fsf_log_security_error(const struct device *dev, u32 fsf_sqw0, |
---|
| 1619 | + u64 wwpn) |
---|
| 1620 | +{ |
---|
| 1621 | + switch (fsf_sqw0) { |
---|
| 1622 | + |
---|
| 1623 | + /* |
---|
| 1624 | + * Open Port command error codes |
---|
| 1625 | + */ |
---|
| 1626 | + |
---|
| 1627 | + case FSF_SQ_SECURITY_REQUIRED: |
---|
| 1628 | + dev_warn_ratelimited(dev, |
---|
| 1629 | + "FC Endpoint Security error: FC security is required but not supported or configured on remote port 0x%016llx\n", |
---|
| 1630 | + wwpn); |
---|
| 1631 | + break; |
---|
| 1632 | + case FSF_SQ_SECURITY_TIMEOUT: |
---|
| 1633 | + dev_warn_ratelimited(dev, |
---|
| 1634 | + "FC Endpoint Security error: a timeout prevented opening remote port 0x%016llx\n", |
---|
| 1635 | + wwpn); |
---|
| 1636 | + break; |
---|
| 1637 | + case FSF_SQ_SECURITY_KM_UNAVAILABLE: |
---|
| 1638 | + dev_warn_ratelimited(dev, |
---|
| 1639 | + "FC Endpoint Security error: opening remote port 0x%016llx failed because local and external key manager cannot communicate\n", |
---|
| 1640 | + wwpn); |
---|
| 1641 | + break; |
---|
| 1642 | + case FSF_SQ_SECURITY_RKM_UNAVAILABLE: |
---|
| 1643 | + dev_warn_ratelimited(dev, |
---|
| 1644 | + "FC Endpoint Security error: opening remote port 0x%016llx failed because it cannot communicate with the external key manager\n", |
---|
| 1645 | + wwpn); |
---|
| 1646 | + break; |
---|
| 1647 | + case FSF_SQ_SECURITY_AUTH_FAILURE: |
---|
| 1648 | + dev_warn_ratelimited(dev, |
---|
| 1649 | + "FC Endpoint Security error: the device could not verify the identity of remote port 0x%016llx\n", |
---|
| 1650 | + wwpn); |
---|
| 1651 | + break; |
---|
| 1652 | + |
---|
| 1653 | + /* |
---|
| 1654 | + * Send FCP command error codes |
---|
| 1655 | + */ |
---|
| 1656 | + |
---|
| 1657 | + case FSF_SQ_SECURITY_ENC_FAILURE: |
---|
| 1658 | + dev_warn_ratelimited(dev, |
---|
| 1659 | + "FC Endpoint Security error: FC connection to remote port 0x%016llx closed because encryption broke down\n", |
---|
| 1660 | + wwpn); |
---|
| 1661 | + break; |
---|
| 1662 | + |
---|
| 1663 | + /* |
---|
| 1664 | + * Unknown error codes |
---|
| 1665 | + */ |
---|
| 1666 | + |
---|
| 1667 | + default: |
---|
| 1668 | + dev_warn_ratelimited(dev, |
---|
| 1669 | + "FC Endpoint Security error: the device issued an unknown error code 0x%08x related to the FC connection to remote port 0x%016llx\n", |
---|
| 1670 | + fsf_sqw0, wwpn); |
---|
| 1671 | + } |
---|
| 1672 | +} |
---|
| 1673 | + |
---|
1391 | 1674 | static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) |
---|
1392 | 1675 | { |
---|
| 1676 | + struct zfcp_adapter *adapter = req->adapter; |
---|
1393 | 1677 | struct zfcp_port *port = req->data; |
---|
1394 | 1678 | struct fsf_qtcb_header *header = &req->qtcb->header; |
---|
| 1679 | + struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support; |
---|
1395 | 1680 | struct fc_els_flogi *plogi; |
---|
1396 | 1681 | |
---|
1397 | 1682 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
---|
.. | .. |
---|
1401 | 1686 | case FSF_PORT_ALREADY_OPEN: |
---|
1402 | 1687 | break; |
---|
1403 | 1688 | case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: |
---|
1404 | | - dev_warn(&req->adapter->ccw_device->dev, |
---|
| 1689 | + dev_warn(&adapter->ccw_device->dev, |
---|
1405 | 1690 | "Not enough FCP adapter resources to open " |
---|
1406 | 1691 | "remote port 0x%016Lx\n", |
---|
1407 | 1692 | (unsigned long long)port->wwpn); |
---|
.. | .. |
---|
1409 | 1694 | ZFCP_STATUS_COMMON_ERP_FAILED); |
---|
1410 | 1695 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
1411 | 1696 | break; |
---|
| 1697 | + case FSF_SECURITY_ERROR: |
---|
| 1698 | + zfcp_fsf_log_security_error(&req->adapter->ccw_device->dev, |
---|
| 1699 | + header->fsf_status_qual.word[0], |
---|
| 1700 | + port->wwpn); |
---|
| 1701 | + req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
| 1702 | + break; |
---|
1412 | 1703 | case FSF_ADAPTER_STATUS_AVAILABLE: |
---|
1413 | 1704 | switch (header->fsf_status_qual.word[0]) { |
---|
1414 | 1705 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
---|
1415 | 1706 | /* no zfcp_fc_test_link() with failed open port */ |
---|
1416 | | - /* fall through */ |
---|
| 1707 | + fallthrough; |
---|
1417 | 1708 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
---|
1418 | 1709 | case FSF_SQ_NO_RETRY_POSSIBLE: |
---|
1419 | 1710 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
.. | .. |
---|
1422 | 1713 | break; |
---|
1423 | 1714 | case FSF_GOOD: |
---|
1424 | 1715 | port->handle = header->port_handle; |
---|
| 1716 | + if (adapter->adapter_features & FSF_FEATURE_FC_SECURITY) |
---|
| 1717 | + port->connection_info = bottom->connection_info; |
---|
| 1718 | + else |
---|
| 1719 | + port->connection_info = 0; |
---|
| 1720 | + zfcp_fsf_log_port_fc_security(port, req); |
---|
1425 | 1721 | atomic_or(ZFCP_STATUS_COMMON_OPEN | |
---|
1426 | 1722 | ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); |
---|
1427 | 1723 | atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_BOXED, |
---|
.. | .. |
---|
1441 | 1737 | * another GID_PN straight after a port has been opened. |
---|
1442 | 1738 | * Alternately, an ADISC/PDISC ELS should suffice, as well. |
---|
1443 | 1739 | */ |
---|
1444 | | - plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els; |
---|
1445 | | - if (req->qtcb->bottom.support.els1_length >= |
---|
1446 | | - FSF_PLOGI_MIN_LEN) |
---|
1447 | | - zfcp_fc_plogi_evaluate(port, plogi); |
---|
| 1740 | + plogi = (struct fc_els_flogi *) bottom->els; |
---|
| 1741 | + if (bottom->els1_length >= FSF_PLOGI_MIN_LEN) |
---|
| 1742 | + zfcp_fc_plogi_evaluate(port, plogi); |
---|
1448 | 1743 | break; |
---|
1449 | 1744 | case FSF_UNKNOWN_OP_SUBTYPE: |
---|
1450 | 1745 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
.. | .. |
---|
1497 | 1792 | erp_action->fsf_req_id = 0; |
---|
1498 | 1793 | put_device(&port->dev); |
---|
1499 | 1794 | } |
---|
| 1795 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
1500 | 1796 | out: |
---|
1501 | 1797 | spin_unlock_irq(&qdio->req_q_lock); |
---|
1502 | 1798 | return retval; |
---|
.. | .. |
---|
1561 | 1857 | zfcp_fsf_req_free(req); |
---|
1562 | 1858 | erp_action->fsf_req_id = 0; |
---|
1563 | 1859 | } |
---|
| 1860 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
1564 | 1861 | out: |
---|
1565 | 1862 | spin_unlock_irq(&qdio->req_q_lock); |
---|
1566 | 1863 | return retval; |
---|
.. | .. |
---|
1580 | 1877 | case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: |
---|
1581 | 1878 | dev_warn(&req->adapter->ccw_device->dev, |
---|
1582 | 1879 | "Opening WKA port 0x%x failed\n", wka_port->d_id); |
---|
1583 | | - /* fall through */ |
---|
| 1880 | + fallthrough; |
---|
1584 | 1881 | case FSF_ADAPTER_STATUS_AVAILABLE: |
---|
1585 | 1882 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
1586 | 1883 | wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; |
---|
1587 | 1884 | break; |
---|
1588 | 1885 | case FSF_GOOD: |
---|
1589 | 1886 | wka_port->handle = header->port_handle; |
---|
1590 | | - /* fall through */ |
---|
| 1887 | + fallthrough; |
---|
1591 | 1888 | case FSF_PORT_ALREADY_OPEN: |
---|
1592 | 1889 | wka_port->status = ZFCP_FC_WKA_PORT_ONLINE; |
---|
1593 | 1890 | } |
---|
1594 | 1891 | out: |
---|
1595 | | - wake_up(&wka_port->completion_wq); |
---|
| 1892 | + wake_up(&wka_port->opened); |
---|
1596 | 1893 | } |
---|
1597 | 1894 | |
---|
1598 | 1895 | /** |
---|
.. | .. |
---|
1633 | 1930 | retval = zfcp_fsf_req_send(req); |
---|
1634 | 1931 | if (retval) |
---|
1635 | 1932 | zfcp_fsf_req_free(req); |
---|
| 1933 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
1636 | 1934 | out: |
---|
1637 | 1935 | spin_unlock_irq(&qdio->req_q_lock); |
---|
1638 | 1936 | if (!retval) |
---|
.. | .. |
---|
1650 | 1948 | } |
---|
1651 | 1949 | |
---|
1652 | 1950 | wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; |
---|
1653 | | - wake_up(&wka_port->completion_wq); |
---|
| 1951 | + wake_up(&wka_port->closed); |
---|
1654 | 1952 | } |
---|
1655 | 1953 | |
---|
1656 | 1954 | /** |
---|
.. | .. |
---|
1691 | 1989 | retval = zfcp_fsf_req_send(req); |
---|
1692 | 1990 | if (retval) |
---|
1693 | 1991 | zfcp_fsf_req_free(req); |
---|
| 1992 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
1694 | 1993 | out: |
---|
1695 | 1994 | spin_unlock_irq(&qdio->req_q_lock); |
---|
1696 | 1995 | if (!retval) |
---|
.. | .. |
---|
1728 | 2027 | case FSF_ADAPTER_STATUS_AVAILABLE: |
---|
1729 | 2028 | switch (header->fsf_status_qual.word[0]) { |
---|
1730 | 2029 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
---|
1731 | | - /* fall through */ |
---|
1732 | 2030 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
---|
1733 | 2031 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
1734 | 2032 | break; |
---|
.. | .. |
---|
1786 | 2084 | zfcp_fsf_req_free(req); |
---|
1787 | 2085 | erp_action->fsf_req_id = 0; |
---|
1788 | 2086 | } |
---|
| 2087 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
1789 | 2088 | out: |
---|
1790 | 2089 | spin_unlock_irq(&qdio->req_q_lock); |
---|
1791 | 2090 | return retval; |
---|
.. | .. |
---|
1812 | 2111 | |
---|
1813 | 2112 | case FSF_PORT_HANDLE_NOT_VALID: |
---|
1814 | 2113 | zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1"); |
---|
1815 | | - /* fall through */ |
---|
| 2114 | + fallthrough; |
---|
1816 | 2115 | case FSF_LUN_ALREADY_OPEN: |
---|
1817 | 2116 | break; |
---|
1818 | 2117 | case FSF_PORT_BOXED: |
---|
.. | .. |
---|
1825 | 2124 | case FSF_LUN_SHARING_VIOLATION: |
---|
1826 | 2125 | if (qual->word[0]) |
---|
1827 | 2126 | dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev, |
---|
1828 | | - "LUN 0x%Lx on port 0x%Lx is already in " |
---|
| 2127 | + "LUN 0x%016Lx on port 0x%016Lx is already in " |
---|
1829 | 2128 | "use by CSS%d, MIF Image ID %x\n", |
---|
1830 | 2129 | zfcp_scsi_dev_lun(sdev), |
---|
1831 | 2130 | (unsigned long long)zfcp_sdev->port->wwpn, |
---|
.. | .. |
---|
1843 | 2142 | (unsigned long long)zfcp_scsi_dev_lun(sdev), |
---|
1844 | 2143 | (unsigned long long)zfcp_sdev->port->wwpn); |
---|
1845 | 2144 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED); |
---|
1846 | | - /* fall through */ |
---|
| 2145 | + fallthrough; |
---|
1847 | 2146 | case FSF_INVALID_COMMAND_OPTION: |
---|
1848 | 2147 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
1849 | 2148 | break; |
---|
.. | .. |
---|
1851 | 2150 | switch (header->fsf_status_qual.word[0]) { |
---|
1852 | 2151 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
---|
1853 | 2152 | zfcp_fc_test_link(zfcp_sdev->port); |
---|
1854 | | - /* fall through */ |
---|
| 2153 | + fallthrough; |
---|
1855 | 2154 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
---|
1856 | 2155 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
1857 | 2156 | break; |
---|
.. | .. |
---|
1909 | 2208 | zfcp_fsf_req_free(req); |
---|
1910 | 2209 | erp_action->fsf_req_id = 0; |
---|
1911 | 2210 | } |
---|
| 2211 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
1912 | 2212 | out: |
---|
1913 | 2213 | spin_unlock_irq(&qdio->req_q_lock); |
---|
1914 | 2214 | return retval; |
---|
.. | .. |
---|
1944 | 2244 | switch (req->qtcb->header.fsf_status_qual.word[0]) { |
---|
1945 | 2245 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
---|
1946 | 2246 | zfcp_fc_test_link(zfcp_sdev->port); |
---|
1947 | | - /* fall through */ |
---|
| 2247 | + fallthrough; |
---|
1948 | 2248 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
---|
1949 | 2249 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
1950 | 2250 | break; |
---|
.. | .. |
---|
1997 | 2297 | zfcp_fsf_req_free(req); |
---|
1998 | 2298 | erp_action->fsf_req_id = 0; |
---|
1999 | 2299 | } |
---|
| 2300 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
2000 | 2301 | out: |
---|
2001 | 2302 | spin_unlock_irq(&qdio->req_q_lock); |
---|
2002 | 2303 | return retval; |
---|
2003 | 2304 | } |
---|
2004 | 2305 | |
---|
2005 | | -static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat) |
---|
| 2306 | +static void zfcp_fsf_update_lat(struct zfcp_latency_record *lat_rec, u32 lat) |
---|
2006 | 2307 | { |
---|
2007 | 2308 | lat_rec->sum += lat; |
---|
2008 | 2309 | lat_rec->min = min(lat_rec->min, lat); |
---|
.. | .. |
---|
2012 | 2313 | static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) |
---|
2013 | 2314 | { |
---|
2014 | 2315 | struct fsf_qual_latency_info *lat_in; |
---|
2015 | | - struct latency_cont *lat = NULL; |
---|
| 2316 | + struct zfcp_latency_cont *lat = NULL; |
---|
2016 | 2317 | struct zfcp_scsi_dev *zfcp_sdev; |
---|
2017 | 2318 | struct zfcp_blk_drv_data blktrc; |
---|
2018 | 2319 | int ticks = req->adapter->timer_ticks; |
---|
.. | .. |
---|
2126 | 2427 | if (header->fsf_status_qual.word[0] == |
---|
2127 | 2428 | FSF_SQ_INVOKE_LINK_TEST_PROCEDURE) |
---|
2128 | 2429 | zfcp_fc_test_link(zfcp_sdev->port); |
---|
| 2430 | + req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
| 2431 | + break; |
---|
| 2432 | + case FSF_SECURITY_ERROR: |
---|
| 2433 | + zfcp_fsf_log_security_error(&req->adapter->ccw_device->dev, |
---|
| 2434 | + header->fsf_status_qual.word[0], |
---|
| 2435 | + zfcp_sdev->port->wwpn); |
---|
| 2436 | + zfcp_erp_port_forced_reopen(zfcp_sdev->port, 0, "fssfch7"); |
---|
2129 | 2437 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
---|
2130 | 2438 | break; |
---|
2131 | 2439 | } |
---|
.. | .. |
---|
2309 | 2617 | retval = zfcp_fsf_req_send(req); |
---|
2310 | 2618 | if (unlikely(retval)) |
---|
2311 | 2619 | goto failed_scsi_cmnd; |
---|
| 2620 | + /* NOTE: DO NOT TOUCH req PAST THIS POINT! */ |
---|
2312 | 2621 | |
---|
2313 | 2622 | goto out; |
---|
2314 | 2623 | |
---|
.. | .. |
---|
2382 | 2691 | fcp_cmnd = &req->qtcb->bottom.io.fcp_cmnd.iu; |
---|
2383 | 2692 | zfcp_fc_fcp_tm(fcp_cmnd, sdev, tm_flags); |
---|
2384 | 2693 | |
---|
2385 | | - zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); |
---|
2386 | | - if (!zfcp_fsf_req_send(req)) |
---|
| 2694 | + zfcp_fsf_start_timer(req, ZFCP_FSF_SCSI_ER_TIMEOUT); |
---|
| 2695 | + if (!zfcp_fsf_req_send(req)) { |
---|
| 2696 | + /* NOTE: DO NOT TOUCH req, UNTIL IT COMPLETES! */ |
---|
2387 | 2697 | goto out; |
---|
| 2698 | + } |
---|
2388 | 2699 | |
---|
2389 | 2700 | zfcp_fsf_req_free(req); |
---|
2390 | 2701 | req = NULL; |
---|
.. | .. |
---|
2395 | 2706 | |
---|
2396 | 2707 | /** |
---|
2397 | 2708 | * zfcp_fsf_reqid_check - validate req_id contained in SBAL returned by QDIO |
---|
2398 | | - * @adapter: pointer to struct zfcp_adapter |
---|
| 2709 | + * @qdio: pointer to struct zfcp_qdio |
---|
2399 | 2710 | * @sbal_idx: response queue index of SBAL to be processed |
---|
2400 | 2711 | */ |
---|
2401 | 2712 | void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) |
---|
.. | .. |
---|
2410 | 2721 | for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) { |
---|
2411 | 2722 | |
---|
2412 | 2723 | sbale = &sbal->element[idx]; |
---|
2413 | | - req_id = (unsigned long) sbale->addr; |
---|
| 2724 | + req_id = sbale->addr; |
---|
2414 | 2725 | fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id); |
---|
2415 | 2726 | |
---|
2416 | 2727 | if (!fsf_req) { |
---|