.. | .. |
---|
4 | 4 | * |
---|
5 | 5 | * Interface to Linux SCSI midlayer. |
---|
6 | 6 | * |
---|
7 | | - * Copyright IBM Corp. 2002, 2018 |
---|
| 7 | + * Copyright IBM Corp. 2002, 2020 |
---|
8 | 8 | */ |
---|
9 | 9 | |
---|
10 | 10 | #define KMSG_COMPONENT "zfcp" |
---|
.. | .. |
---|
27 | 27 | |
---|
28 | 28 | static bool enable_dif; |
---|
29 | 29 | module_param_named(dif, enable_dif, bool, 0400); |
---|
30 | | -MODULE_PARM_DESC(dif, "Enable DIF/DIX data integrity support"); |
---|
| 30 | +MODULE_PARM_DESC(dif, "Enable DIF data integrity support (default off)"); |
---|
| 31 | + |
---|
| 32 | +bool zfcp_experimental_dix; |
---|
| 33 | +module_param_named(dix, zfcp_experimental_dix, bool, 0400); |
---|
| 34 | +MODULE_PARM_DESC(dix, "Enable experimental DIX (data integrity extension) support which implies DIF support (default off)"); |
---|
31 | 35 | |
---|
32 | 36 | static bool allow_lun_scan = true; |
---|
33 | 37 | module_param(allow_lun_scan, bool, 0600); |
---|
.. | .. |
---|
235 | 239 | (struct zfcp_scsi_req_filter *)data; |
---|
236 | 240 | |
---|
237 | 241 | /* already aborted - prevent side-effects - or not a SCSI command */ |
---|
238 | | - if (old_req->data == NULL || old_req->fsf_command != FSF_QTCB_FCP_CMND) |
---|
| 242 | + if (old_req->data == NULL || |
---|
| 243 | + zfcp_fsf_req_is_status_read_buffer(old_req) || |
---|
| 244 | + old_req->qtcb->header.fsf_command != FSF_QTCB_FCP_CMND) |
---|
239 | 245 | return; |
---|
240 | 246 | |
---|
241 | 247 | /* (tmf_scope == FCP_TMF_TGT_RESET || tmf_scope == FCP_TMF_LUN_RESET) */ |
---|
.. | .. |
---|
435 | 441 | .max_sectors = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1) |
---|
436 | 442 | * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8, |
---|
437 | 443 | /* GCD, adjusted later */ |
---|
| 444 | + /* report size limit per scatter-gather segment */ |
---|
| 445 | + .max_segment_size = ZFCP_QDIO_SBALE_LEN, |
---|
438 | 446 | .dma_boundary = ZFCP_QDIO_SBALE_LEN - 1, |
---|
439 | | - .use_clustering = 1, |
---|
440 | 447 | .shost_attrs = zfcp_sysfs_shost_attrs, |
---|
441 | 448 | .sdev_attrs = zfcp_sysfs_sdev_attrs, |
---|
442 | 449 | .track_queue_depth = 1, |
---|
.. | .. |
---|
444 | 451 | }; |
---|
445 | 452 | |
---|
446 | 453 | /** |
---|
447 | | - * zfcp_scsi_adapter_register - Register SCSI and FC host with SCSI midlayer |
---|
| 454 | + * zfcp_scsi_adapter_register() - Allocate and register SCSI and FC host with |
---|
| 455 | + * SCSI midlayer |
---|
448 | 456 | * @adapter: The zfcp adapter to register with the SCSI midlayer |
---|
| 457 | + * |
---|
| 458 | + * Allocates the SCSI host object for the given adapter, sets basic properties |
---|
| 459 | + * (such as the transport template, QDIO limits, ...), and registers it with |
---|
| 460 | + * the midlayer. |
---|
| 461 | + * |
---|
| 462 | + * During registration with the midlayer the corresponding FC host object for |
---|
| 463 | + * the referenced transport class is also implicitely allocated. |
---|
| 464 | + * |
---|
| 465 | + * Upon success adapter->scsi_host is set, and upon failure it remains NULL. If |
---|
| 466 | + * adapter->scsi_host is already set, nothing is done. |
---|
| 467 | + * |
---|
| 468 | + * Return: |
---|
| 469 | + * * 0 - Allocation and registration was successful |
---|
| 470 | + * * -EEXIST - SCSI and FC host did already exist, nothing was done, nothing |
---|
| 471 | + * was changed |
---|
| 472 | + * * -EIO - Allocation or registration failed |
---|
449 | 473 | */ |
---|
450 | 474 | int zfcp_scsi_adapter_register(struct zfcp_adapter *adapter) |
---|
451 | 475 | { |
---|
452 | 476 | struct ccw_dev_id dev_id; |
---|
453 | 477 | |
---|
454 | 478 | if (adapter->scsi_host) |
---|
455 | | - return 0; |
---|
| 479 | + return -EEXIST; |
---|
456 | 480 | |
---|
457 | 481 | ccw_device_get_id(adapter->ccw_device, &dev_id); |
---|
458 | 482 | /* register adapter as SCSI host with mid layer of SCSI stack */ |
---|
459 | 483 | adapter->scsi_host = scsi_host_alloc(&zfcp_scsi_host_template, |
---|
460 | 484 | sizeof (struct zfcp_adapter *)); |
---|
461 | | - if (!adapter->scsi_host) { |
---|
462 | | - dev_err(&adapter->ccw_device->dev, |
---|
463 | | - "Registering the FCP device with the " |
---|
464 | | - "SCSI stack failed\n"); |
---|
465 | | - return -EIO; |
---|
466 | | - } |
---|
| 485 | + if (!adapter->scsi_host) |
---|
| 486 | + goto err_out; |
---|
467 | 487 | |
---|
468 | 488 | /* tell the SCSI stack some characteristics of this adapter */ |
---|
469 | 489 | adapter->scsi_host->max_id = 511; |
---|
.. | .. |
---|
473 | 493 | adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */ |
---|
474 | 494 | adapter->scsi_host->transportt = zfcp_scsi_transport_template; |
---|
475 | 495 | |
---|
| 496 | + /* make all basic properties known at registration time */ |
---|
| 497 | + zfcp_qdio_shost_update(adapter, adapter->qdio); |
---|
| 498 | + zfcp_scsi_set_prot(adapter); |
---|
| 499 | + |
---|
476 | 500 | adapter->scsi_host->hostdata[0] = (unsigned long) adapter; |
---|
477 | 501 | |
---|
478 | 502 | if (scsi_add_host(adapter->scsi_host, &adapter->ccw_device->dev)) { |
---|
479 | 503 | scsi_host_put(adapter->scsi_host); |
---|
480 | | - return -EIO; |
---|
| 504 | + goto err_out; |
---|
481 | 505 | } |
---|
482 | 506 | |
---|
483 | 507 | return 0; |
---|
| 508 | +err_out: |
---|
| 509 | + adapter->scsi_host = NULL; |
---|
| 510 | + dev_err(&adapter->ccw_device->dev, |
---|
| 511 | + "Registering the FCP device with the SCSI stack failed\n"); |
---|
| 512 | + return -EIO; |
---|
484 | 513 | } |
---|
485 | 514 | |
---|
486 | 515 | /** |
---|
.. | .. |
---|
598 | 627 | return NULL; |
---|
599 | 628 | |
---|
600 | 629 | ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data); |
---|
601 | | - if (ret) { |
---|
| 630 | + if (ret != 0 && ret != -EAGAIN) { |
---|
602 | 631 | kfree(data); |
---|
603 | 632 | return NULL; |
---|
604 | 633 | } |
---|
.. | .. |
---|
627 | 656 | return; |
---|
628 | 657 | |
---|
629 | 658 | ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data); |
---|
630 | | - if (ret) |
---|
| 659 | + if (ret != 0 && ret != -EAGAIN) |
---|
631 | 660 | kfree(data); |
---|
632 | 661 | else { |
---|
633 | 662 | adapter->stats_reset = jiffies/HZ; |
---|
.. | .. |
---|
801 | 830 | data_div = atomic_read(&adapter->status) & |
---|
802 | 831 | ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED; |
---|
803 | 832 | |
---|
804 | | - if (enable_dif && |
---|
| 833 | + if ((enable_dif || zfcp_experimental_dix) && |
---|
805 | 834 | adapter->adapter_features & FSF_FEATURE_DIF_PROT_TYPE1) |
---|
806 | 835 | mask |= SHOST_DIF_TYPE1_PROTECTION; |
---|
807 | 836 | |
---|
808 | | - if (enable_dif && data_div && |
---|
| 837 | + if (zfcp_experimental_dix && data_div && |
---|
809 | 838 | adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) { |
---|
810 | 839 | mask |= SHOST_DIX_TYPE1_PROTECTION; |
---|
811 | 840 | scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP); |
---|
.. | .. |
---|
834 | 863 | set_host_byte(scmd, DID_SOFT_ERROR); |
---|
835 | 864 | } |
---|
836 | 865 | |
---|
| 866 | +void zfcp_scsi_shost_update_config_data( |
---|
| 867 | + struct zfcp_adapter *const adapter, |
---|
| 868 | + const struct fsf_qtcb_bottom_config *const bottom, |
---|
| 869 | + const bool bottom_incomplete) |
---|
| 870 | +{ |
---|
| 871 | + struct Scsi_Host *const shost = adapter->scsi_host; |
---|
| 872 | + const struct fc_els_flogi *nsp, *plogi; |
---|
| 873 | + |
---|
| 874 | + if (shost == NULL) |
---|
| 875 | + return; |
---|
| 876 | + |
---|
| 877 | + snprintf(fc_host_firmware_version(shost), FC_VERSION_STRING_SIZE, |
---|
| 878 | + "0x%08x", bottom->lic_version); |
---|
| 879 | + |
---|
| 880 | + if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { |
---|
| 881 | + snprintf(fc_host_hardware_version(shost), |
---|
| 882 | + FC_VERSION_STRING_SIZE, |
---|
| 883 | + "0x%08x", bottom->hardware_version); |
---|
| 884 | + memcpy(fc_host_serial_number(shost), bottom->serial_number, |
---|
| 885 | + min(FC_SERIAL_NUMBER_SIZE, 17)); |
---|
| 886 | + EBCASC(fc_host_serial_number(shost), |
---|
| 887 | + min(FC_SERIAL_NUMBER_SIZE, 17)); |
---|
| 888 | + } |
---|
| 889 | + |
---|
| 890 | + /* adjust pointers for missing command code */ |
---|
| 891 | + nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param |
---|
| 892 | + - sizeof(u32)); |
---|
| 893 | + plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload |
---|
| 894 | + - sizeof(u32)); |
---|
| 895 | + |
---|
| 896 | + snprintf(fc_host_manufacturer(shost), FC_SERIAL_NUMBER_SIZE, "%s", |
---|
| 897 | + "IBM"); |
---|
| 898 | + fc_host_port_name(shost) = be64_to_cpu(nsp->fl_wwpn); |
---|
| 899 | + fc_host_node_name(shost) = be64_to_cpu(nsp->fl_wwnn); |
---|
| 900 | + fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; |
---|
| 901 | + |
---|
| 902 | + zfcp_scsi_set_prot(adapter); |
---|
| 903 | + |
---|
| 904 | + /* do not evaluate invalid fields */ |
---|
| 905 | + if (bottom_incomplete) |
---|
| 906 | + return; |
---|
| 907 | + |
---|
| 908 | + fc_host_port_id(shost) = ntoh24(bottom->s_id); |
---|
| 909 | + fc_host_speed(shost) = |
---|
| 910 | + zfcp_fsf_convert_portspeed(bottom->fc_link_speed); |
---|
| 911 | + |
---|
| 912 | + snprintf(fc_host_model(shost), FC_SYMBOLIC_NAME_SIZE, "0x%04x", |
---|
| 913 | + bottom->adapter_type); |
---|
| 914 | + |
---|
| 915 | + switch (bottom->fc_topology) { |
---|
| 916 | + case FSF_TOPO_P2P: |
---|
| 917 | + fc_host_port_type(shost) = FC_PORTTYPE_PTP; |
---|
| 918 | + fc_host_fabric_name(shost) = 0; |
---|
| 919 | + break; |
---|
| 920 | + case FSF_TOPO_FABRIC: |
---|
| 921 | + fc_host_fabric_name(shost) = be64_to_cpu(plogi->fl_wwnn); |
---|
| 922 | + if (bottom->connection_features & FSF_FEATURE_NPIV_MODE) |
---|
| 923 | + fc_host_port_type(shost) = FC_PORTTYPE_NPIV; |
---|
| 924 | + else |
---|
| 925 | + fc_host_port_type(shost) = FC_PORTTYPE_NPORT; |
---|
| 926 | + break; |
---|
| 927 | + case FSF_TOPO_AL: |
---|
| 928 | + fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; |
---|
| 929 | + fallthrough; |
---|
| 930 | + default: |
---|
| 931 | + fc_host_fabric_name(shost) = 0; |
---|
| 932 | + break; |
---|
| 933 | + } |
---|
| 934 | +} |
---|
| 935 | + |
---|
| 936 | +void zfcp_scsi_shost_update_port_data( |
---|
| 937 | + struct zfcp_adapter *const adapter, |
---|
| 938 | + const struct fsf_qtcb_bottom_port *const bottom) |
---|
| 939 | +{ |
---|
| 940 | + struct Scsi_Host *const shost = adapter->scsi_host; |
---|
| 941 | + |
---|
| 942 | + if (shost == NULL) |
---|
| 943 | + return; |
---|
| 944 | + |
---|
| 945 | + fc_host_permanent_port_name(shost) = bottom->wwpn; |
---|
| 946 | + fc_host_maxframe_size(shost) = bottom->maximum_frame_size; |
---|
| 947 | + fc_host_supported_speeds(shost) = |
---|
| 948 | + zfcp_fsf_convert_portspeed(bottom->supported_speed); |
---|
| 949 | + memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types, |
---|
| 950 | + FC_FC4_LIST_SIZE); |
---|
| 951 | + memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, |
---|
| 952 | + FC_FC4_LIST_SIZE); |
---|
| 953 | +} |
---|
| 954 | + |
---|
837 | 955 | struct fc_function_template zfcp_transport_functions = { |
---|
838 | 956 | .show_starget_port_id = 1, |
---|
839 | 957 | .show_starget_port_name = 1, |
---|
.. | .. |
---|
849 | 967 | .show_host_supported_speeds = 1, |
---|
850 | 968 | .show_host_maxframe_size = 1, |
---|
851 | 969 | .show_host_serial_number = 1, |
---|
| 970 | + .show_host_manufacturer = 1, |
---|
| 971 | + .show_host_model = 1, |
---|
| 972 | + .show_host_hardware_version = 1, |
---|
| 973 | + .show_host_firmware_version = 1, |
---|
852 | 974 | .get_fc_host_stats = zfcp_scsi_get_fc_host_stats, |
---|
853 | 975 | .reset_fc_host_stats = zfcp_scsi_reset_fc_host_stats, |
---|
854 | 976 | .set_rport_dev_loss_tmo = zfcp_scsi_set_rport_dev_loss_tmo, |
---|
.. | .. |
---|
864 | 986 | .show_host_symbolic_name = 1, |
---|
865 | 987 | .show_host_speed = 1, |
---|
866 | 988 | .show_host_port_id = 1, |
---|
| 989 | + .show_host_fabric_name = 1, |
---|
867 | 990 | .dd_bsg_size = sizeof(struct zfcp_fsf_ct_els), |
---|
868 | 991 | }; |
---|