SCSI for-linus on 20180404
This is mostly updates of the usual drivers: arcmsr, qla2xx, lpfc, ufs, mpt3sas, hisi_sas. In addition we have removed several really old drivers: sym53c416, NCR53c406a, fdomain, fdomain_cs and removed the old scsi_module.c initialization from all remaining drivers. Plus an assortment of bug fixes, initialization errors and other minor fixes. Signed-off-by: James E.J. Bottomley <jejb@linux.vnet.ibm.com> -----BEGIN PGP SIGNATURE----- iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCWsVSnSYcamFtZXMuYm90 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishbvbAP9ErpTZ OR5iJ5HIz4W3Bd8aTfEpJrDyeYwSUC+sra5SKQD/ZWyVB3fYFSg+ZROyT26pmtmd SdImhG7hLaHgVvF5qRQ= =SQ/n -----END PGP SIGNATURE----- Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI updates from James Bottomley: "This is mostly updates of the usual drivers: arcmsr, qla2xx, lpfc, ufs, mpt3sas, hisi_sas. In addition we have removed several really old drivers: sym53c416, NCR53c406a, fdomain, fdomain_cs and removed the old scsi_module.c initialization from all remaining drivers. Plus an assortment of bug fixes, initialization errors and other minor fixes" * tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (168 commits) scsi: ufs: Add support for Auto-Hibernate Idle Timer scsi: ufs: sysfs: reworking of the rpm_lvl and spm_lvl entries scsi: qla2xxx: fx00 copypaste typo scsi: qla2xxx: fix error message on <qla2400 scsi: smartpqi: update driver version scsi: smartpqi: workaround fw bug for oq deletion scsi: arcmsr: Change driver version to v1.40.00.05-20180309 scsi: arcmsr: Sleep to avoid CPU stuck too long for waiting adapter ready scsi: arcmsr: Handle adapter removed due to thunderbolt cable disconnection. scsi: arcmsr: Rename ACB_F_BUS_HANG_ON to ACB_F_ADAPTER_REMOVED for adapter hot-plug scsi: qla2xxx: Update driver version to 10.00.00.06-k scsi: qla2xxx: Fix Async GPN_FT for FCP and FC-NVMe scan scsi: qla2xxx: Cleanup code to improve FC-NVMe error handling scsi: qla2xxx: Fix FC-NVMe IO abort during driver reset scsi: qla2xxx: Fix retry for PRLI RJT with reason of BUSY scsi: qla2xxx: Remove nvme_done_list scsi: qla2xxx: Return busy if rport going away scsi: qla2xxx: Fix n2n_ae flag to prevent dev_loss on PDB change scsi: qla2xxx: Add FC-NVMe abort processing scsi: qla2xxx: Add changes for devloss timeout in driver ...
This commit is contained in:
commit
052c220da3
885
Documentation/ABI/testing/sysfs-driver-ufs
Normal file
885
Documentation/ABI/testing/sysfs-driver-ufs
Normal file
|
@ -0,0 +1,885 @@
|
|||
What: /sys/bus/*/drivers/ufshcd/*/auto_hibern8
|
||||
Date: March 2018
|
||||
Contact: linux-scsi@vger.kernel.org
|
||||
Description:
|
||||
This file contains the auto-hibernate idle timer setting of a
|
||||
UFS host controller. A value of '0' means auto-hibernate is not
|
||||
enabled. Otherwise the value is the number of microseconds of
|
||||
idle time before the UFS host controller will autonomously put
|
||||
the link into hibernate state. That will save power at the
|
||||
expense of increased latency. Note that the hardware supports
|
||||
10-bit values with a power-of-ten multiplier which allows a
|
||||
maximum value of 102300000. Refer to the UFS Host Controller
|
||||
Interface specification for more details.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_type
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the device type. This is one of the UFS
|
||||
device descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_class
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the device class. This is one of the UFS
|
||||
device descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_sub_class
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the UFS storage subclass. This is one of
|
||||
the UFS device descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/protocol
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the protocol supported by an UFS device.
|
||||
This is one of the UFS device descriptor parameters.
|
||||
The full information about the descriptor could be found
|
||||
at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_luns
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows number of logical units. This is one of
|
||||
the UFS device descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_wluns
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows number of well known logical units.
|
||||
This is one of the UFS device descriptor parameters.
|
||||
The full information about the descriptor could be found
|
||||
at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/boot_enable
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows value that indicates whether the device is
|
||||
enabled for boot. This is one of the UFS device descriptor
|
||||
parameters. The full information about the descriptor could
|
||||
be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/descriptor_access_enable
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows value that indicates whether the device
|
||||
descriptor could be read after partial initialization phase
|
||||
of the boot sequence. This is one of the UFS device descriptor
|
||||
parameters. The full information about the descriptor could
|
||||
be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/initial_power_mode
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows value that defines the power mode after
|
||||
device initialization or hardware reset. This is one of
|
||||
the UFS device descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/high_priority_lun
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the high priority lun. This is one of
|
||||
the UFS device descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/secure_removal_type
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the secure removal type. This is one of
|
||||
the UFS device descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/support_security_lun
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows whether the security lun is supported.
|
||||
This is one of the UFS device descriptor parameters.
|
||||
The full information about the descriptor could be found
|
||||
at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/bkops_termination_latency
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the background operations termination
|
||||
latency. This is one of the UFS device descriptor parameters.
|
||||
The full information about the descriptor could be found
|
||||
at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/initial_active_icc_level
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the initial active ICC level. This is one
|
||||
of the UFS device descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/specification_version
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the specification version. This is one
|
||||
of the UFS device descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/manufacturing_date
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the manufacturing date in BCD format.
|
||||
This is one of the UFS device descriptor parameters.
|
||||
The full information about the descriptor could be found
|
||||
at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/manufacturer_id
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the manufacturee ID. This is one of the
|
||||
UFS device descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/rtt_capability
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the maximum number of outstanding RTTs
|
||||
supported by the device. This is one of the UFS device
|
||||
descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/rtc_update
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the frequency and method of the realtime
|
||||
clock update. This is one of the UFS device descriptor
|
||||
parameters. The full information about the descriptor
|
||||
could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/ufs_features
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows which features are supported by the device.
|
||||
This is one of the UFS device descriptor parameters.
|
||||
The full information about the descriptor could be
|
||||
found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/ffu_timeout
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the FFU timeout. This is one of the
|
||||
UFS device descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/queue_depth
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the device queue depth. This is one of the
|
||||
UFS device descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_version
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the device version. This is one of the
|
||||
UFS device descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/number_of_secure_wpa
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows number of secure write protect areas
|
||||
supported by the device. This is one of the UFS device
|
||||
descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/psa_max_data_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the maximum amount of data that may be
|
||||
written during the pre-soldering phase of the PSA flow.
|
||||
This is one of the UFS device descriptor parameters.
|
||||
The full information about the descriptor could be found
|
||||
at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/psa_state_timeout
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the command maximum timeout for a change
|
||||
in PSA state. This is one of the UFS device descriptor
|
||||
parameters. The full information about the descriptor could
|
||||
be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/interconnect_descriptor/unipro_version
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the MIPI UniPro version number in BCD format.
|
||||
This is one of the UFS interconnect descriptor parameters.
|
||||
The full information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/interconnect_descriptor/mphy_version
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the MIPI M-PHY version number in BCD format.
|
||||
This is one of the UFS interconnect descriptor parameters.
|
||||
The full information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/raw_device_capacity
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the total memory quantity available to
|
||||
the user to configure the device logical units. This is one
|
||||
of the UFS geometry descriptor parameters. The full
|
||||
information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_number_of_luns
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the maximum number of logical units
|
||||
supported by the UFS device. This is one of the UFS
|
||||
geometry descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/segment_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the segment size. This is one of the UFS
|
||||
geometry descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/allocation_unit_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the allocation unit size. This is one of
|
||||
the UFS geometry descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/min_addressable_block_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the minimum addressable block size. This
|
||||
is one of the UFS geometry descriptor parameters. The full
|
||||
information about the descriptor could be found at UFS
|
||||
specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/optimal_read_block_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the optimal read block size. This is one
|
||||
of the UFS geometry descriptor parameters. The full
|
||||
information about the descriptor could be found at UFS
|
||||
specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/optimal_write_block_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the optimal write block size. This is one
|
||||
of the UFS geometry descriptor parameters. The full
|
||||
information about the descriptor could be found at UFS
|
||||
specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_in_buffer_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the maximum data-in buffer size. This
|
||||
is one of the UFS geometry descriptor parameters. The full
|
||||
information about the descriptor could be found at UFS
|
||||
specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_out_buffer_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the maximum data-out buffer size. This
|
||||
is one of the UFS geometry descriptor parameters. The full
|
||||
information about the descriptor could be found at UFS
|
||||
specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/rpmb_rw_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the maximum number of RPMB frames allowed
|
||||
in Security Protocol In/Out. This is one of the UFS geometry
|
||||
descriptor parameters. The full information about the
|
||||
descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/dyn_capacity_resource_policy
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the dynamic capacity resource policy. This
|
||||
is one of the UFS geometry descriptor parameters. The full
|
||||
information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/data_ordering
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows support for out-of-order data transfer.
|
||||
This is one of the UFS geometry descriptor parameters.
|
||||
The full information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/max_number_of_contexts
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows maximum available number of contexts which
|
||||
are supported by the device. This is one of the UFS geometry
|
||||
descriptor parameters. The full information about the
|
||||
descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/sys_data_tag_unit_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows system data tag unit size. This is one of
|
||||
the UFS geometry descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/sys_data_tag_resource_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows maximum storage area size allocated by
|
||||
the device to handle system data by the tagging mechanism.
|
||||
This is one of the UFS geometry descriptor parameters.
|
||||
The full information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/secure_removal_types
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows supported secure removal types. This is
|
||||
one of the UFS geometry descriptor parameters. The full
|
||||
information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/memory_types
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows supported memory types. This is one of
|
||||
the UFS geometry descriptor parameters. The full
|
||||
information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/*_memory_max_alloc_units
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the maximum number of allocation units for
|
||||
different memory types (system code, non persistent,
|
||||
enhanced type 1-4). This is one of the UFS geometry
|
||||
descriptor parameters. The full information about the
|
||||
descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/*_memory_capacity_adjustment_factor
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the memory capacity adjustment factor for
|
||||
different memory types (system code, non persistent,
|
||||
enhanced type 1-4). This is one of the UFS geometry
|
||||
descriptor parameters. The full information about the
|
||||
descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/health_descriptor/eol_info
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows preend of life information. This is one
|
||||
of the UFS health descriptor parameters. The full
|
||||
information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/health_descriptor/life_time_estimation_a
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows indication of the device life time
|
||||
(method a). This is one of the UFS health descriptor
|
||||
parameters. The full information about the descriptor
|
||||
could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/health_descriptor/life_time_estimation_b
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows indication of the device life time
|
||||
(method b). This is one of the UFS health descriptor
|
||||
parameters. The full information about the descriptor
|
||||
could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/power_descriptor/active_icc_levels_vcc*
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows maximum VCC, VCCQ and VCCQ2 value for
|
||||
active ICC levels from 0 to 15. This is one of the UFS
|
||||
power descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/manufacturer_name
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file contains a device manufactureer name string.
|
||||
The full information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/product_name
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file contains a product name string. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/oem_id
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file contains a OEM ID string. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/serial_number
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file contains a device serial number string. The full
|
||||
information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/product_revision
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file contains a product revision string. The full
|
||||
information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/boot_lun_id
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows boot LUN information. This is one of
|
||||
the UFS unit descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/lun_write_protect
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows LUN write protection status. This is one of
|
||||
the UFS unit descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/lun_queue_depth
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows LUN queue depth. This is one of the UFS
|
||||
unit descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/psa_sensitive
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows PSA sensitivity. This is one of the UFS
|
||||
unit descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/lun_memory_type
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows LUN memory type. This is one of the UFS
|
||||
unit descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/data_reliability
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file defines the device behavior when a power failure
|
||||
occurs during a write operation. This is one of the UFS
|
||||
unit descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/logical_block_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the size of addressable logical blocks
|
||||
(calculated as an exponent with base 2). This is one of
|
||||
the UFS unit descriptor parameters. The full information about
|
||||
the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/logical_block_count
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows total number of addressable logical blocks.
|
||||
This is one of the UFS unit descriptor parameters. The full
|
||||
information about the descriptor could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/erase_block_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the erase block size. This is one of
|
||||
the UFS unit descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/provisioning_type
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the thin provisioning type. This is one of
|
||||
the UFS unit descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/physical_memory_resourse_count
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the total physical memory resources. This is
|
||||
one of the UFS unit descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/context_capabilities
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the context capabilities. This is one of
|
||||
the UFS unit descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/class/scsi_device/*/device/unit_descriptor/large_unit_granularity
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the granularity of the LUN. This is one of
|
||||
the UFS unit descriptor parameters. The full information
|
||||
about the descriptor could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/flags/device_init
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the device init status. The full information
|
||||
about the flag could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/flags/permanent_wpe
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows whether permanent write protection is enabled.
|
||||
The full information about the flag could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/flags/power_on_wpe
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows whether write protection is enabled on all
|
||||
logical units configured as power on write protected. The
|
||||
full information about the flag could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/flags/bkops_enable
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows whether the device background operations are
|
||||
enabled. The full information about the flag could be
|
||||
found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/flags/life_span_mode_enable
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows whether the device life span mode is enabled.
|
||||
The full information about the flag could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/flags/phy_resource_removal
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows whether physical resource removal is enable.
|
||||
The full information about the flag could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/flags/busy_rtc
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows whether the device is executing internal
|
||||
operation related to real time clock. The full information
|
||||
about the flag could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/flags/disable_fw_update
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows whether the device FW update is permanently
|
||||
disabled. The full information about the flag could be found
|
||||
at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/boot_lun_enabled
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the boot lun enabled UFS device attribute.
|
||||
The full information about the attribute could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/current_power_mode
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the current power mode UFS device attribute.
|
||||
The full information about the attribute could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/active_icc_level
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the active icc level UFS device attribute.
|
||||
The full information about the attribute could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/ooo_data_enabled
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the out of order data transfer enabled UFS
|
||||
device attribute. The full information about the attribute
|
||||
could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/bkops_status
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the background operations status UFS device
|
||||
attribute. The full information about the attribute could
|
||||
be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/purge_status
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the purge operation status UFS device
|
||||
attribute. The full information about the attribute could
|
||||
be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_in_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the maximum data size in a DATA IN
|
||||
UPIU. The full information about the attribute could
|
||||
be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_out_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the maximum number of bytes that can be
|
||||
requested with a READY TO TRANSFER UPIU. The full information
|
||||
about the attribute could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/reference_clock_frequency
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the reference clock frequency UFS device
|
||||
attribute. The full information about the attribute could
|
||||
be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/configuration_descriptor_lock
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows whether the configuration descriptor is locked.
|
||||
The full information about the attribute could be found at
|
||||
UFS specifications 2.1. The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_number_of_rtt
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the maximum current number of
|
||||
outstanding RTTs in device that is allowed. The full
|
||||
information about the attribute could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_control
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the exception event control UFS device
|
||||
attribute. The full information about the attribute could
|
||||
be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_status
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the exception event status UFS device
|
||||
attribute. The full information about the attribute could
|
||||
be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/ffu_status
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file provides the ffu status UFS device attribute.
|
||||
The full information about the attribute could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/psa_state
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file show the PSA feature status. The full information
|
||||
about the attribute could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/attributes/psa_data_size
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the amount of data that the host plans to
|
||||
load to all logical units in pre-soldering state.
|
||||
The full information about the attribute could be found at
|
||||
UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
|
||||
What: /sys/class/scsi_device/*/device/dyn_cap_needed
|
||||
Date: February 2018
|
||||
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||
Description: This file shows the The amount of physical memory needed
|
||||
to be removed from the physical memory resources pool of
|
||||
the particular logical unit. The full information about
|
||||
the attribute could be found at UFS specifications 2.1.
|
||||
The file is read only.
|
||||
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/rpm_lvl
|
||||
Date: September 2014
|
||||
Contact: Subhash Jadavani <subhashj@codeaurora.org>
|
||||
Description: This entry could be used to set or show the UFS device
|
||||
runtime power management level. The current driver
|
||||
implementation supports 6 levels with next target states:
|
||||
0 - an UFS device will stay active, an UIC link will
|
||||
stay active
|
||||
1 - an UFS device will stay active, an UIC link will
|
||||
hibernate
|
||||
2 - an UFS device will moved to sleep, an UIC link will
|
||||
stay active
|
||||
3 - an UFS device will moved to sleep, an UIC link will
|
||||
hibernate
|
||||
4 - an UFS device will be powered off, an UIC link will
|
||||
hibernate
|
||||
5 - an UFS device will be powered off, an UIC link will
|
||||
be powered off
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
|
||||
Date: February 2018
|
||||
Contact: Subhash Jadavani <subhashj@codeaurora.org>
|
||||
Description: This entry shows the target power mode of an UFS device
|
||||
for the chosen runtime power management level.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/rpm_target_link_state
|
||||
Date: February 2018
|
||||
Contact: Subhash Jadavani <subhashj@codeaurora.org>
|
||||
Description: This entry shows the target state of an UFS UIC link
|
||||
for the chosen runtime power management level.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/spm_lvl
|
||||
Date: September 2014
|
||||
Contact: Subhash Jadavani <subhashj@codeaurora.org>
|
||||
Description: This entry could be used to set or show the UFS device
|
||||
system power management level. The current driver
|
||||
implementation supports 6 levels with next target states:
|
||||
0 - an UFS device will stay active, an UIC link will
|
||||
stay active
|
||||
1 - an UFS device will stay active, an UIC link will
|
||||
hibernate
|
||||
2 - an UFS device will moved to sleep, an UIC link will
|
||||
stay active
|
||||
3 - an UFS device will moved to sleep, an UIC link will
|
||||
hibernate
|
||||
4 - an UFS device will be powered off, an UIC link will
|
||||
hibernate
|
||||
5 - an UFS device will be powered off, an UIC link will
|
||||
be powered off
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
|
||||
Date: February 2018
|
||||
Contact: Subhash Jadavani <subhashj@codeaurora.org>
|
||||
Description: This entry shows the target power mode of an UFS device
|
||||
for the chosen system power management level.
|
||||
The file is read only.
|
||||
|
||||
What: /sys/bus/platform/drivers/ufshcd/*/spm_target_link_state
|
||||
Date: February 2018
|
||||
Contact: Subhash Jadavani <subhashj@codeaurora.org>
|
||||
Description: This entry shows the target state of an UFS UIC link
|
||||
for the chosen system power management level.
|
||||
The file is read only.
|
|
@ -53,6 +53,13 @@ Main node required properties:
|
|||
Optional main node properties:
|
||||
- hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has the
|
||||
"am-max-transmissions" limitation.
|
||||
- hisilicon,signal-attenuation : array of 3 32-bit values, containing de-emphasis,
|
||||
preshoot, and boost attenuation readings for the board. They
|
||||
are used to describe the signal attenuation of the board. These
|
||||
values' range is 7600 to 12400, and used to represent -24dB to
|
||||
24dB.
|
||||
The formula is "y = (x-10000)/10000". For example, 10478
|
||||
means 4.78dB.
|
||||
|
||||
Example:
|
||||
sas0: sas@c1000000 {
|
||||
|
|
|
@ -154,12 +154,6 @@ lists).
|
|||
.. kernel-doc:: drivers/scsi/scsi_lib_dma.c
|
||||
:export:
|
||||
|
||||
drivers/scsi/scsi_module.c
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The file drivers/scsi/scsi_module.c contains legacy support for
|
||||
old-style host templates. It should never be used by any new driver.
|
||||
|
||||
drivers/scsi/scsi_proc.c
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +0,0 @@
|
|||
Please see the file README.BusLogic for information about Linux support for
|
||||
Mylex (formerly BusLogic) MultiMaster and FlashPoint SCSI Host Adapters.
|
||||
|
||||
The Mylex DAC960 PCI RAID Controllers are now supported. Please consult
|
||||
http://sourceforge.net/projects/dandelion for further information on the DAC960 driver.
|
|
@ -34,11 +34,6 @@ parameters may be changed at runtime by the command
|
|||
See drivers/scsi/BusLogic.c, comment before function
|
||||
BusLogic_ParseDriverOptions().
|
||||
|
||||
eata= [HW,SCSI]
|
||||
|
||||
fdomain= [HW,SCSI]
|
||||
See header of drivers/scsi/fdomain.c.
|
||||
|
||||
gdth= [HW,SCSI]
|
||||
See header of drivers/scsi/gdth.c.
|
||||
|
||||
|
@ -70,8 +65,6 @@ parameters may be changed at runtime by the command
|
|||
ncr53c400a= [HW,SCSI]
|
||||
See Documentation/scsi/g_NCR5380.txt.
|
||||
|
||||
ncr53c406a= [HW,SCSI]
|
||||
|
||||
ncr53c8xx= [HW,SCSI]
|
||||
|
||||
osst= [HW,SCSI] SCSI Tape Driver
|
||||
|
@ -110,12 +103,5 @@ parameters may be changed at runtime by the command
|
|||
st= [HW,SCSI] SCSI tape parameters (buffers, etc.)
|
||||
See Documentation/scsi/st.txt.
|
||||
|
||||
sym53c416= [HW,SCSI]
|
||||
See header of drivers/scsi/sym53c416.c.
|
||||
|
||||
tmscsim= [HW,SCSI]
|
||||
See comment before function dc390_setup() in
|
||||
drivers/scsi/tmscsim.c.
|
||||
|
||||
wd33c93= [HW,SCSI]
|
||||
See header of drivers/scsi/wd33c93.c.
|
||||
|
|
|
@ -114,9 +114,7 @@ called "xxx" could be defined as
|
|||
"static int xxx_slave_alloc(struct scsi_device * sdev) { /* code */ }"
|
||||
|
||||
** the scsi_host_alloc() function is a replacement for the rather vaguely
|
||||
named scsi_register() function in most situations. The scsi_register()
|
||||
and scsi_unregister() functions remain to support legacy LLDs that use
|
||||
the passive initialization model.
|
||||
named scsi_register() function in most situations.
|
||||
|
||||
|
||||
Hotplug initialization model
|
||||
|
@ -228,79 +226,6 @@ slave_configure() callbacks). Such instances are "owned" by the mid-level.
|
|||
struct scsi_device instances are freed after slave_destroy().
|
||||
|
||||
|
||||
Passive initialization model
|
||||
============================
|
||||
These older LLDs include a file called "scsi_module.c" [yes the ".c" is a
|
||||
little surprising] in their source code. For that file to work an
|
||||
instance of struct scsi_host_template with the name "driver_template"
|
||||
needs to be defined. Here is a typical code sequence used in this model:
|
||||
static struct scsi_host_template driver_template = {
|
||||
...
|
||||
};
|
||||
#include "scsi_module.c"
|
||||
|
||||
The scsi_module.c file contains two functions:
|
||||
- init_this_scsi_driver() which is executed when the LLD is
|
||||
initialized (i.e. boot time or module load time)
|
||||
- exit_this_scsi_driver() which is executed when the LLD is shut
|
||||
down (i.e. module unload time)
|
||||
Note: since these functions are tagged with __init and __exit qualifiers
|
||||
an LLD should not call them explicitly (since the kernel does that).
|
||||
|
||||
Here is an example of an initialization sequence when two hosts are
|
||||
detected (so detect() returns 2) and the SCSI bus scan on each host
|
||||
finds 1 SCSI device (and a second device does not respond).
|
||||
|
||||
LLD mid level LLD
|
||||
===----------------------=========-----------------===------
|
||||
init_this_scsi_driver() ----+
|
||||
|
|
||||
detect() -----------------+
|
||||
| |
|
||||
| scsi_register()
|
||||
| scsi_register()
|
||||
|
|
||||
slave_alloc()
|
||||
slave_configure() --> scsi_change_queue_depth()
|
||||
slave_alloc() ***
|
||||
slave_destroy() ***
|
||||
|
|
||||
slave_alloc()
|
||||
slave_configure()
|
||||
slave_alloc() ***
|
||||
slave_destroy() ***
|
||||
------------------------------------------------------------
|
||||
|
||||
The mid level invokes scsi_change_queue_depth() with "cmd_per_lun" for that
|
||||
host as the queue length. These settings can be overridden by a
|
||||
slave_configure() supplied by the LLD.
|
||||
|
||||
*** For scsi devices that the mid level tries to scan but do not
|
||||
respond, a slave_alloc(), slave_destroy() pair is called.
|
||||
|
||||
Here is an LLD shutdown sequence:
|
||||
|
||||
LLD mid level LLD
|
||||
===----------------------=========-----------------===------
|
||||
exit_this_scsi_driver() ----+
|
||||
|
|
||||
slave_destroy()
|
||||
release() --> scsi_unregister()
|
||||
|
|
||||
slave_destroy()
|
||||
release() --> scsi_unregister()
|
||||
------------------------------------------------------------
|
||||
|
||||
An LLD need not define slave_destroy() (i.e. it is optional).
|
||||
|
||||
The shortcoming of the "passive initialization model" is that host
|
||||
registration and de-registration are (typically) tied to LLD initialization
|
||||
and shutdown. Once the LLD is initialized then a new host that appears
|
||||
(e.g. via hotplugging) cannot easily be added without a redundant
|
||||
driver shutdown and re-initialization. It may be possible to write an LLD
|
||||
that uses both initialization models.
|
||||
|
||||
|
||||
Reference Counting
|
||||
==================
|
||||
The Scsi_Host structure has had reference counting infrastructure added.
|
||||
|
@ -738,7 +663,6 @@ The interface functions are listed below in alphabetical order.
|
|||
|
||||
Summary:
|
||||
bios_param - fetch head, sector, cylinder info for a disk
|
||||
detect - detects HBAs this driver wants to control
|
||||
eh_timed_out - notify the host that a command timer expired
|
||||
eh_abort_handler - abort given command
|
||||
eh_bus_reset_handler - issue SCSI bus reset
|
||||
|
@ -748,7 +672,6 @@ Summary:
|
|||
ioctl - driver can respond to ioctls
|
||||
proc_info - supports /proc/scsi/{driver_name}/{host_no}
|
||||
queuecommand - queue scsi command, invoke 'done' on completion
|
||||
release - release all resources associated with given host
|
||||
slave_alloc - prior to any commands being sent to a new device
|
||||
slave_configure - driver fine tuning for given device after attach
|
||||
slave_destroy - given device is about to be shut down
|
||||
|
@ -784,28 +707,6 @@ Details:
|
|||
sector_t capacity, int params[3])
|
||||
|
||||
|
||||
/**
|
||||
* detect - detects HBAs this driver wants to control
|
||||
* @shtp: host template for this driver.
|
||||
*
|
||||
* Returns number of hosts this driver wants to control. 0 means no
|
||||
* suitable hosts found.
|
||||
*
|
||||
* Locks: none held
|
||||
*
|
||||
* Calling context: process [invoked from init_this_scsi_driver()]
|
||||
*
|
||||
* Notes: First function called from the SCSI mid level on this
|
||||
* driver. Upper level drivers (e.g. sd) may not (yet) be present.
|
||||
* For each host found, this method should call scsi_register()
|
||||
* [see hosts.c].
|
||||
*
|
||||
* Defined in: LLD (required if "passive initialization mode" is used,
|
||||
* not invoked in "hotplug initialization mode")
|
||||
**/
|
||||
int detect(struct scsi_host_template * shtp)
|
||||
|
||||
|
||||
/**
|
||||
* eh_timed_out - The timer for the command has just fired
|
||||
* @scp: identifies command timing out
|
||||
|
@ -1073,27 +974,6 @@ Details:
|
|||
int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp)
|
||||
|
||||
|
||||
/**
|
||||
* release - release all resources associated with given host
|
||||
* @shp: host to be released.
|
||||
*
|
||||
* Return value ignored (could soon be a function returning void).
|
||||
*
|
||||
* Locks: none held
|
||||
*
|
||||
* Calling context: process
|
||||
*
|
||||
* Notes: Invoked from scsi_module.c's exit_this_scsi_driver().
|
||||
* LLD's implementation of this function should call
|
||||
* scsi_unregister(shp) prior to returning.
|
||||
* Only needed for old-style host templates.
|
||||
*
|
||||
* Defined in: LLD (required in "passive initialization model",
|
||||
* should not be defined in hotplug model)
|
||||
**/
|
||||
int release(struct Scsi_Host * shp)
|
||||
|
||||
|
||||
/**
|
||||
* slave_alloc - prior to any commands being sent to a new device
|
||||
* (i.e. just prior to scan) this call is made
|
||||
|
|
22
Documentation/scsi/sd-parameters.txt
Normal file
22
Documentation/scsi/sd-parameters.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
Linux SCSI Disk Driver (sd) Parameters
|
||||
======================================
|
||||
|
||||
cache_type (RW)
|
||||
---------------
|
||||
Enable/disable drive write & read cache.
|
||||
|
||||
cache_type string | WCE RCD | Write cache | Read cache
|
||||
----------------------------+---------+-------------+------------
|
||||
write through | 0 0 | off | on
|
||||
none | 0 1 | off | off
|
||||
write back | 1 0 | on | on
|
||||
write back, no read (daft) | 1 1 | on | off
|
||||
|
||||
To set cache type to "write back" and save this setting to the drive:
|
||||
|
||||
# echo "write back" > cache_type
|
||||
|
||||
To modify the caching mode without making the change persistent, prepend
|
||||
"temporary " to the cache type string. E.g.:
|
||||
|
||||
# echo "temporary write back" > cache_type
|
|
@ -1,443 +0,0 @@
|
|||
The tmscsim driver
|
||||
==================
|
||||
|
||||
1. Purpose and history
|
||||
2. Installation
|
||||
3. Features
|
||||
4. Configuration via /proc/scsi/tmscsim/?
|
||||
5. Configuration via boot/module params
|
||||
6. Potential improvements
|
||||
7. Bug reports, debugging and updates
|
||||
8. Acknowledgements
|
||||
9. Copyright
|
||||
|
||||
|
||||
1. Purpose and history
|
||||
----------------------
|
||||
The tmscsim driver supports PCI SCSI Host Adapters based on the AM53C974
|
||||
chip. AM53C974 based SCSI adapters include:
|
||||
Tekram DC390, DC390T
|
||||
Dawicontrol 2974
|
||||
QLogic Fast! PCI Basic
|
||||
some on-board adapters
|
||||
(This is most probably not a complete list)
|
||||
|
||||
It has originally written by C.L. Huang from the Tekram corp. to support the
|
||||
Tekram DC390(T) adapter. This is where the name comes from: tm = Tekram
|
||||
scsi = SCSI driver, m = AMD (?) as opposed to w for the DC390W/U/F
|
||||
(NCR53c8X5, X=2/7) driver. Yes, there was also a driver for the latter,
|
||||
tmscsiw, which supported DC390W/U/F adapters. It's not maintained any more,
|
||||
as the ncr53c8xx is perfectly supporting these adapters since some time.
|
||||
|
||||
The driver first appeared in April 1996, exclusively supported the DC390
|
||||
and has been enhanced since then in various steps. In May 1998 support for
|
||||
general AM53C974 based adapters and some possibilities to configure it were
|
||||
added. The non-DC390 support works by assuming some values for the data
|
||||
normally taken from the DC390 EEPROM. See below (chapter 5) for details.
|
||||
|
||||
When using the DC390, the configuration is still be done using the DC390
|
||||
BIOS setup. The DC390 EEPROM is read and used by the driver, any boot or
|
||||
module parameters (chapter 5) are ignored! However, you can change settings
|
||||
dynamically, as described in chapter 4.
|
||||
|
||||
For a more detailed description of the driver's history, see the first lines
|
||||
of tmscsim.c.
|
||||
The numbering scheme isn't consistent. The first versions went from 1.00 to
|
||||
1.12, then 1.20a to 1.20t. Finally I decided to use the ncr53c8xx scheme. So
|
||||
the next revisions will be 2.0a to 2.0X (stable), 2.1a to 2.1X (experimental),
|
||||
2.2a to 2.2X (stable, again) etc. (X = anything between a and z.) If I send
|
||||
fixes to people for testing, I create intermediate versions with a digit
|
||||
appended, e.g. 2.0c3.
|
||||
|
||||
|
||||
2. Installation
|
||||
---------------
|
||||
If you got any recent kernel with this driver and document included in
|
||||
linux/drivers/scsi, you basically have to do nothing special to use this
|
||||
driver. Of course you have to choose to compile SCSI support and DC390(T)
|
||||
support into your kernel or as module when configuring your kernel for
|
||||
compiling.
|
||||
NEW: You may as well compile this module outside your kernel, using the
|
||||
supplied Makefile.
|
||||
|
||||
If you got an old kernel (pre 2.1.127, pre 2.0.37p1) with an old version of
|
||||
this driver: Get dc390-21125-20b.diff.gz or dc390-2036p21-20b1.diff.gz from
|
||||
my web page and apply the patch. Apply further patches to upgrade to the
|
||||
latest version of the driver.
|
||||
|
||||
If you want to do it manually, you should copy the files (dc390.h,
|
||||
tmscsim.h, tmscsim.c, scsiiom.c and README.tmscsim) from this directory to
|
||||
linux/drivers/scsi. You have to recompile your kernel/module of course.
|
||||
|
||||
You should apply the three patches included in dc390-120-kernel.diff
|
||||
(Applying them: cd /usr/src; patch -p0 <~/dc390-120-kernel.diff)
|
||||
The patches are against 2.1.125, so you might have to manually resolve
|
||||
rejections when applying to another kernel version.
|
||||
|
||||
The patches will update the kernel startup code to allow boot parameters to
|
||||
be passed to the driver, update the Documentation and finally offer you the
|
||||
possibility to omit the non-DC390 parts of the driver.
|
||||
(By selecting "Omit support for non DC390" you basically disable the
|
||||
emulation of a DC390 EEPROM for non DC390 adapters. This saves a few bytes
|
||||
of memory.)
|
||||
|
||||
If you got a very old kernel without the tmscsim driver (pre 2.0.31)
|
||||
I recommend upgrading your kernel. However, if you don't want to, please
|
||||
contact me to get the appropriate patches.
|
||||
|
||||
|
||||
Upgrading a SCSI driver is always a delicate thing to do. The 2.0 driver has
|
||||
proven stable on many systems, but it's still a good idea to take some
|
||||
precautions. In an ideal world you would have a full backup of your disks.
|
||||
The world isn't ideal and most people don't have full backups (me neither).
|
||||
So take at least the following measures:
|
||||
* make your kernel remount the FS read-only on detecting an error:
|
||||
tune2fs -e remount-ro /dev/sd??
|
||||
* have copies of your SCSI disk's partition tables on some safe location:
|
||||
dd if=/dev/sda of=/mnt/floppy/sda bs=512 count=1
|
||||
or just print it with:
|
||||
fdisk -l | lpr
|
||||
* make sure you are able to boot Linux (e.g. from floppy disk using InitRD)
|
||||
if your SCSI disk gets corrupted. You can use
|
||||
ftp://student.physik.uni-dortmund.de/pub/linux/kernel/bootdisk.gz
|
||||
|
||||
One more warning: I used to overclock my PCI bus to 41.67 MHz. My Tekram
|
||||
DC390F (Sym53c875) accepted this as well as my Millennium. But the Am53C974
|
||||
produced errors and started to corrupt my disks. So don't do that! A 37.50
|
||||
MHz PCI bus works for me, though, but I don't recommend using higher clocks
|
||||
than the 33.33 MHz being in the PCI spec.
|
||||
|
||||
|
||||
3.Features
|
||||
----------
|
||||
- SCSI
|
||||
* Tagged command queueing
|
||||
* Sync speed up to 10 MHz
|
||||
* Disconnection
|
||||
* Multiple LUNs
|
||||
|
||||
- General / Linux interface
|
||||
* Support for up to 4 AM53C974 adapters.
|
||||
* DC390 EEPROM usage or boot/module params
|
||||
* Information via cat /proc/scsi/tmscsim/?
|
||||
* Dynamically configurable by writing to /proc/scsi/tmscsim/?
|
||||
* Dynamic allocation of resources
|
||||
* SMP support: Locking on io_request lock (Linux 2.1/2.2) or adapter
|
||||
specific locks (Linux 2.5?)
|
||||
* Uniform source code for Linux-2.x.y
|
||||
* Support for dyn. addition/removal of devices via add/remove-single-device
|
||||
(Try: echo "scsi add-single-device C B T U" >/proc/scsi/scsi
|
||||
C = Controller, B = Bus, T = Target SCSI ID, U = Unit SCSI LUN.)
|
||||
Use with care!
|
||||
* Try to use the partition table for the determination of the mapping
|
||||
|
||||
|
||||
4. Configuration via /proc/scsi/tmscsim/?
|
||||
-----------------------------------------
|
||||
First of all look at the output of /proc/scsi/tmscsim/? by typing
|
||||
cat /proc/scsi/tmscsim/?
|
||||
The "?" should be replaced by the SCSI host number. (The shell might do this
|
||||
for you.)
|
||||
You will see some info regarding the adapter and, at the end, a listing of
|
||||
the attached devices and their settings.
|
||||
|
||||
Here's an example:
|
||||
garloff@kurt:/home/garloff > cat /proc/scsi/tmscsim/0
|
||||
Tekram DC390/AM53C974 PCI SCSI Host Adapter, Driver Version 2.0e7 2000-11-28
|
||||
SCSI Host Nr 1, AM53C974 Adapter Nr 0
|
||||
IOPortBase 0xb000, IRQ 10
|
||||
MaxID 8, MaxLUN 8, AdapterID 6, SelTimeout 250 ms, DelayReset 1 s
|
||||
TagMaxNum 16, Status 0x00, ACBFlag 0x00, GlitchEater 24 ns
|
||||
Statistics: Cmnds 1470165, Cmnds not sent directly 0, Out of SRB conds 0
|
||||
Lost arbitrations 587, Sel. connected 0, Connected: No
|
||||
Nr of attached devices: 4, Nr of DCBs: 4
|
||||
Map of attached LUNs: 01 00 00 03 01 00 00 00
|
||||
Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd
|
||||
00 00 00 Yes Yes Yes Yes Yes 100 ns 10.0 M 15 16
|
||||
01 03 00 Yes Yes Yes Yes No 100 ns 10.0 M 15 01
|
||||
02 03 01 Yes Yes Yes Yes No 100 ns 10.0 M 15 01
|
||||
03 04 00 Yes Yes Yes Yes No 100 ns 10.0 M 15 01
|
||||
|
||||
Note that the settings MaxID and MaxLUN are not zero- but one-based, which
|
||||
means that a setting MaxLUN=4, will result in the support of LUNs 0..3. This
|
||||
is somehow inconvenient, but the way the mid-level SCSI code expects it to be.
|
||||
|
||||
ACB and DCB are acronyms for Adapter Control Block and Device Control Block.
|
||||
These are data structures of the driver containing information about the
|
||||
adapter and the connected SCSI devices respectively.
|
||||
|
||||
Idx is the device index (just a consecutive number for the driver), ID and
|
||||
LUN are the SCSI ID and LUN, Prty means Parity checking, Sync synchronous
|
||||
negotiation, DsCn Disconnection, SndS Send Start command on startup (not
|
||||
used by the driver) and TagQ Tagged Command Queueing. NegoPeriod and
|
||||
SyncSpeed are somehow redundant, because they are reciprocal values
|
||||
(1 / 112 ns = 8.9 MHz). At least in theory. The driver is able to adjust the
|
||||
NegoPeriod more accurate (4ns) than the SyncSpeed (1 / 25ns). I don't know
|
||||
if certain devices will have problems with this discrepancy. Max. speed is
|
||||
10 MHz corresp. to a min. NegoPeriod of 100 ns.
|
||||
(The driver allows slightly higher speeds if the devices (Ultra SCSI) accept
|
||||
it, but that's out of adapter spec, on your own risk and unlikely to improve
|
||||
performance. You're likely to crash your disks.)
|
||||
SyncOffs is the offset used for synchronous negotiations; max. is 15.
|
||||
The last values are only shown, if Sync is enabled. (NegoPeriod is still
|
||||
displayed in brackets to show the values which will be used after enabling
|
||||
Sync.)
|
||||
MaxCmd ist the number of commands (=tags) which can be processed at the same
|
||||
time by the device.
|
||||
|
||||
If you want to change a setting, you can do that by writing to
|
||||
/proc/scsi/tmscsim/?. Basically you have to imitate the output of driver.
|
||||
(Don't use the brackets for NegoPeriod on Sync disabled devices.)
|
||||
You don't have to care about capitalisation. The driver will accept space,
|
||||
tab, comma, = and : as separators.
|
||||
|
||||
There are three kinds of changes:
|
||||
|
||||
(1) Change driver settings:
|
||||
You type the names of the parameters and the params following it.
|
||||
Example:
|
||||
echo "MaxLUN=8 seltimeout 200" >/proc/scsi/tmscsim/0
|
||||
|
||||
Note that you can only change MaxID, MaxLUN, AdapterID, SelTimeOut,
|
||||
TagMaxNum, ACBFlag, GlitchEater and DelayReset. Don't change ACBFlag
|
||||
unless you want to see what happens, if the driver hangs.
|
||||
|
||||
(2) Change device settings: You write a config line to the driver. The Nr
|
||||
must match the ID and LUN given. If you give "-" as parameter, it is
|
||||
ignored and the corresponding setting won't be changed.
|
||||
You can use "y" or "n" instead of "Yes" and "No" if you want to.
|
||||
You don't need to specify a full line. The driver automatically performs
|
||||
an INQUIRY on the device if necessary to check if it is capable to operate
|
||||
with the given settings (Sync, TagQ).
|
||||
Examples:
|
||||
echo "0 0 0 y y y - y - 10 " >/proc/scsi/tmscsim/0
|
||||
echo "3 5 0 y n y " >/proc/scsi/tmscsim/0
|
||||
|
||||
To give a short explanation of the first example:
|
||||
The first three numbers, "0 0 0" (Device index 0, SCSI ID 0, SCSI LUN 0),
|
||||
select the device to which the following parameters apply. Note that it
|
||||
would be sufficient to use the index or both SCSI ID and LUN, but I chose
|
||||
to require all three to have a syntax similar to the output.
|
||||
The following "y y y - y" enables Parity checking, enables Synchronous
|
||||
transfers, Disconnection, leaves Send Start (not used) untouched and
|
||||
enables Tagged Command Queueing for the selected device. The "-" skips
|
||||
the Negotiation Period setting but the "10" sets the max sync. speed to
|
||||
10 MHz. It's useless to specify both NegoPeriod and SyncSpeed as
|
||||
discussed above. The values used in this example will result in maximum
|
||||
performance.
|
||||
|
||||
(3) Special commands: You can force a SCSI bus reset, an INQUIRY command, the
|
||||
removal or the addition of a device's DCB and a SCSI register dump.
|
||||
This is only used for debugging when you meet problems. The parameter of
|
||||
the INQUIRY and REMOVE commands is the device index as shown by the
|
||||
output of /proc/scsi/tmscsim/? in the device listing in the first column
|
||||
(Idx). ADD takes the SCSI ID and LUN.
|
||||
Examples:
|
||||
echo "reset" >/proc/scsi/tmscsim/0
|
||||
echo "inquiry 1" >/proc/scsi/tmscsim/0
|
||||
echo "remove 2" >/proc/scsi/tmscsim/1
|
||||
echo "add 2 3" >/proc/scsi/tmscsim/?
|
||||
echo "dump" >/proc/scsi/tmscsim/0
|
||||
|
||||
Note that you will meet problems when you REMOVE a device's DCB with the
|
||||
remove command if it contains partitions which are mounted. Only use it
|
||||
after unmounting its partitions, telling the SCSI mid-level code to
|
||||
remove it (scsi remove-single-device) and you really need a few bytes of
|
||||
memory.
|
||||
The ADD command allows you to configure a device before you tell the
|
||||
mid-level code to try detection.
|
||||
|
||||
|
||||
I'd suggest reviewing the output of /proc/scsi/tmscsim/? after changing
|
||||
settings to see if everything changed as requested.
|
||||
|
||||
|
||||
5. Configuration via boot/module parameters
|
||||
-------------------------------------------
|
||||
With the DC390, the driver reads its EEPROM settings and tries to use them.
|
||||
But you may want to override the settings prior to being able to change the
|
||||
driver configuration via /proc/scsi/tmscsim/?.
|
||||
If you do have another AM53C974 based adapter, that's even the only
|
||||
possibility to adjust settings before you are able to write to the
|
||||
/proc/scsi/tmscsim/? pseudo-file, e.g. if you want to use another
|
||||
adapter ID than 7.
|
||||
(BTW, the log message "DC390: No EEPROM found!" is normal without a DC390.)
|
||||
For this purpose, you can pass options to the driver before it is initialised
|
||||
by using kernel or module parameters. See lilo(8) or modprobe(1) manual
|
||||
pages on how to pass params to the kernel or a module.
|
||||
[NOTE: Formerly, it was not possible to override the EEPROM supplied
|
||||
settings of the DC390 with cmd line parameters. This has changed since
|
||||
2.0e7]
|
||||
|
||||
The syntax of the params is much shorter than the syntax of the /proc/...
|
||||
interface. This makes it a little bit more difficult to use. However, long
|
||||
parameter lines have the risk to be misinterpreted and the length of kernel
|
||||
parameters is limited.
|
||||
|
||||
As the support for non-DC390 adapters works by simulating the values of the
|
||||
DC390 EEPROM, the settings are given in a DC390 BIOS' way.
|
||||
|
||||
Here's the syntax:
|
||||
tmscsim=AdaptID,SpdIdx,DevMode,AdaptMode,TaggedCmnds,DelayReset
|
||||
|
||||
Each of the parameters is a number, containing the described information:
|
||||
|
||||
* AdaptID: The SCSI ID of the host adapter. Must be in the range 0..7
|
||||
Default is 7.
|
||||
|
||||
* SpdIdx: The index of the maximum speed as in the DC390 BIOS. The values
|
||||
0..7 mean 10, 8.0, 6.7, 5.7, 5.0, 4.0, 3.1 and 2 MHz resp. Default is
|
||||
0 (10.0 MHz).
|
||||
|
||||
* DevMode is a bit mapped value describing the per-device features. It
|
||||
applies to all devices. (Sync, Disc and TagQ will only apply, if the
|
||||
device supports it.) The meaning of the bits (* = default):
|
||||
|
||||
Bit Val(hex) Val(dec) Meaning
|
||||
*0 0x01 1 Parity check
|
||||
*1 0x02 2 Synchronous Negotiation
|
||||
*2 0x04 4 Disconnection
|
||||
*3 0x08 8 Send Start command on startup. (Not used)
|
||||
*4 0x10 16 Tagged Command Queueing
|
||||
|
||||
As usual, the desired value is obtained by adding the wanted values. If
|
||||
you want to enable all values, e.g., you would use 31(0x1f). Default is 31.
|
||||
|
||||
* AdaptMode is a bit mapped value describing the enabled adapter features.
|
||||
|
||||
Bit Val(hex) Val(dec) Meaning
|
||||
*0 0x01 1 Support more than two drives. (Not used)
|
||||
*1 0x02 2 Use DOS compatible mapping for HDs greater than 1GB.
|
||||
*2 0x04 4 Reset SCSI Bus on startup.
|
||||
*3 0x08 8 Active Negation: Improves SCSI Bus noise immunity.
|
||||
4 0x10 16 Immediate return on BIOS seek command. (Not used)
|
||||
(*)5 0x20 32 Check for LUNs >= 1.
|
||||
|
||||
* TaggedCmnds is a number indicating the maximum number of Tagged Commands.
|
||||
It is the binary logarithm - 1 of the actual number. Max is 4 (32).
|
||||
Value Number of Tagged Commands
|
||||
0 2
|
||||
1 4
|
||||
2 8
|
||||
*3 16
|
||||
4 32
|
||||
|
||||
* DelayReset is the time in seconds (minus 0.5s), the adapter waits, after a
|
||||
bus reset. Default is 1 (corresp. to 1.5s).
|
||||
|
||||
Example:
|
||||
modprobe tmscsim tmscsim=6,2,31
|
||||
would set the adapter ID to 6, max. speed to 6.7 MHz, enable all device
|
||||
features and leave the adapter features, the number of Tagged Commands
|
||||
and the Delay after a reset to the defaults.
|
||||
|
||||
As you can see, you don't need to specify all of the six params.
|
||||
If you want values to be ignored (i.e. the EEprom settings or the defaults
|
||||
will be used), you may pass -2 (not 0!) at the corresponding position.
|
||||
|
||||
The defaults (7,0,31,15,3,1) are aggressive to allow good performance. You
|
||||
can use tmscsim=7,0,31,63,4,0 for maximum performance, if your SCSI chain
|
||||
allows it. If you meet problems, you can use tmscsim=-1 which is a shortcut
|
||||
for tmscsim=7,4,9,15,2,10.
|
||||
|
||||
|
||||
6. Potential improvements
|
||||
-------------------------
|
||||
Most of the intended work on the driver has been done. Here are a few ideas
|
||||
to further improve its usability:
|
||||
|
||||
* Cleanly separate per-Target and per-LUN properties (DCB)
|
||||
* More intelligent abort() routine
|
||||
* Use new_eh code (Linux-2.1+)
|
||||
* Have the mid-level (ML) code (and not the driver) handle more of the
|
||||
various conditions.
|
||||
* Command queueing in the driver: Eliminate Query list and use ML instead.
|
||||
* More user friendly boot/module param syntax
|
||||
|
||||
Further investigation on these problems:
|
||||
|
||||
* Driver hangs with sync readcdda (xcdroast) (most probably VIA PCI error)
|
||||
|
||||
Known problems:
|
||||
Please see http://www.garloff.de/kurt/linux/dc390/problems.html
|
||||
|
||||
* Changing the parameters of multi-lun by the tmscsim/? interface will
|
||||
cause problems, cause these settings are mostly per Target and not per LUN
|
||||
and should be updated accordingly. To be fixed for 2.0d24.
|
||||
* CDRs (eg Yam CRW4416) not recognized, because some buggy devices don't
|
||||
recover from a SCSI reset in time. Use a higher delay or don't issue
|
||||
a SCSI bus reset on driver initialization. See problems page.
|
||||
For the CRW4416S, this seems to be solved with firmware 1.0g (reported by
|
||||
Jean-Yves Barbier).
|
||||
* TEAC CD-532S not being recognized. (Works with 1.11).
|
||||
* Scanners (eg. Astra UMAX 1220S) don't work: Disable Sync Negotiation.
|
||||
If this does not help, try echo "INQUIRY t" >/proc/scsi/tmscsim/? (t
|
||||
replaced by the dev index of your scanner). You may try to reset your SCSI
|
||||
bus afterwards (echo "RESET" >/proc/scsi/tmscsim/?).
|
||||
The problem seems to be solved as of 2.0d18, thanks to Andreas Rick.
|
||||
* If there is a valid partition table, the driver will use it for determining
|
||||
the mapping. If there's none, a reasonable mapping (Symbios-like) will be
|
||||
assumed. Other operating systems may not like this mapping, though
|
||||
it's consistent with the BIOS' behaviour. Old DC390 drivers ignored the
|
||||
partition table and used a H/S = 64/32 or 255/63 translation. So if you
|
||||
want to be compatible to those, use this old mapping when creating
|
||||
partition tables. Even worse, on bootup the DC390 might complain if other
|
||||
mappings are found, so auto rebooting may fail.
|
||||
* In some situations, the driver will get stuck in an abort loop. This is a
|
||||
bad interaction between the Mid-Layer of Linux' SCSI code and the driver.
|
||||
Try to disable DsCn, if you meet this problem. Please contact me for
|
||||
further debugging.
|
||||
|
||||
|
||||
7. Bug reports, debugging and updates
|
||||
-------------------------------------
|
||||
Whenever you have problems with the driver, you are invited to ask the
|
||||
author for help. However, I'd suggest reading the docs and trying to solve
|
||||
the problem yourself, first.
|
||||
If you find something, which you believe to be a bug, please report it to me.
|
||||
Please append the output of /proc/scsi/scsi, /proc/scsi/tmscsim/? and
|
||||
maybe the DC390 log messages to the report.
|
||||
|
||||
Bug reports should be send to me (Kurt Garloff <dc390@garloff.de>) as well
|
||||
as to the linux-scsi list (<linux-scsi@vger.kernel.org>), as sometimes bugs
|
||||
are caused by the SCSI mid-level code.
|
||||
|
||||
I will ask you for some more details and probably I will also ask you to
|
||||
enable some of the DEBUG options in the driver (tmscsim.c:DC390_DEBUGXXX
|
||||
defines). The driver will produce some data for the syslog facility then.
|
||||
Beware: If your syslog gets written to a SCSI disk connected to your
|
||||
AM53C974, the logging might produce log output again, and you might end
|
||||
having your box spending most of its time doing the logging.
|
||||
|
||||
The latest version of the driver can be found at:
|
||||
http://www.garloff.de/kurt/linux/dc390/
|
||||
ftp://ftp.suse.com/pub/people/garloff/linux/dc390/
|
||||
|
||||
|
||||
8. Acknowledgements
|
||||
-------------------
|
||||
Thanks to Linus Torvalds, Alan Cox, the FSF people, the XFree86 team and
|
||||
all the others for the wonderful OS and software.
|
||||
Thanks to C.L. Huang and Philip Giang (Tekram) for the initial driver
|
||||
release and support.
|
||||
Thanks to Doug Ledford, Gérard Roudier for support with SCSI coding.
|
||||
Thanks to a lot of people (espec. Chiaki Ishikawa, Andreas Haumer, Hubert
|
||||
Tonneau) for intensively testing the driver (and even risking data loss
|
||||
doing this during early revisions).
|
||||
Recently, SuSE GmbH, Nuernberg, FRG, has been paying me for the driver
|
||||
development and maintenance. Special thanks!
|
||||
|
||||
|
||||
9. Copyright
|
||||
------------
|
||||
This driver is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
If you want to use any later version of the GNU GPL, you will probably
|
||||
be allowed to, but you have to ask me and Tekram <erich@tekram.com.tw>
|
||||
before.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
Written by Kurt Garloff <kurt@garloff.de> 1998/06/11
|
||||
Last updated 2000/11/28, driver revision 2.0e7
|
||||
$Id: README.tmscsim,v 2.25.2.7 2000/12/20 01:07:12 garloff Exp $
|
12
MAINTAINERS
12
MAINTAINERS
|
@ -4971,12 +4971,6 @@ T: git git://linuxtv.org/anttip/media_tree.git
|
|||
S: Maintained
|
||||
F: drivers/media/tuners/e4000*
|
||||
|
||||
EATA ISA/EISA/PCI SCSI DRIVER
|
||||
M: Dario Ballabio <ballabio_dario@emc.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/scsi/eata.c
|
||||
|
||||
EC100 MEDIA DRIVER
|
||||
M: Antti Palosaari <crope@iki.fi>
|
||||
L: linux-media@vger.kernel.org
|
||||
|
@ -5812,12 +5806,6 @@ F: tools/testing/selftests/futex/
|
|||
F: tools/perf/bench/futex*
|
||||
F: Documentation/*futex*
|
||||
|
||||
FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit)
|
||||
M: Rik Faith <faith@cs.unc.edu>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Odd Fixes (e.g., new signatures)
|
||||
F: drivers/scsi/fdomain.*
|
||||
|
||||
GCC PLUGINS
|
||||
M: Kees Cook <keescook@chromium.org>
|
||||
R: Emese Revfy <re.emese@gmail.com>
|
||||
|
|
|
@ -184,7 +184,6 @@ CONFIG_MEGARAID_NEWGEN=y
|
|||
CONFIG_MEGARAID_MM=m
|
||||
CONFIG_MEGARAID_MAILBOX=m
|
||||
CONFIG_MEGARAID_SAS=m
|
||||
CONFIG_SCSI_FUTURE_DOMAIN=m
|
||||
CONFIG_SCSI_GDTH=m
|
||||
CONFIG_SCSI_IPS=m
|
||||
CONFIG_SCSI_INITIO=m
|
||||
|
|
|
@ -640,88 +640,6 @@ config SCSI_DMX3191D
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called dmx3191d.
|
||||
|
||||
config SCSI_EATA
|
||||
tristate "EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support"
|
||||
depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API
|
||||
---help---
|
||||
This driver supports all EATA/DMA-compliant SCSI host adapters. DPT
|
||||
ISA and all EISA I/O addresses are probed looking for the "EATA"
|
||||
signature. The addresses of all the PCI SCSI controllers reported
|
||||
by the PCI subsystem are probed as well.
|
||||
|
||||
You want to read the start of <file:drivers/scsi/eata.c> and the
|
||||
SCSI-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called eata.
|
||||
|
||||
config SCSI_EATA_TAGGED_QUEUE
|
||||
bool "enable tagged command queueing"
|
||||
depends on SCSI_EATA
|
||||
help
|
||||
This is a feature of SCSI-2 which improves performance: the host
|
||||
adapter can send several SCSI commands to a device's queue even if
|
||||
previous commands haven't finished yet.
|
||||
This is equivalent to the "eata=tc:y" boot option.
|
||||
|
||||
config SCSI_EATA_LINKED_COMMANDS
|
||||
bool "enable elevator sorting"
|
||||
depends on SCSI_EATA
|
||||
help
|
||||
This option enables elevator sorting for all probed SCSI disks and
|
||||
CD-ROMs. It definitely reduces the average seek distance when doing
|
||||
random seeks, but this does not necessarily result in a noticeable
|
||||
performance improvement: your mileage may vary...
|
||||
This is equivalent to the "eata=lc:y" boot option.
|
||||
|
||||
config SCSI_EATA_MAX_TAGS
|
||||
int "maximum number of queued commands"
|
||||
depends on SCSI_EATA
|
||||
default "16"
|
||||
help
|
||||
This specifies how many SCSI commands can be maximally queued for
|
||||
each probed SCSI device. You should reduce the default value of 16
|
||||
only if you have disks with buggy or limited tagged command support.
|
||||
Minimum is 2 and maximum is 62. This value is also the window size
|
||||
used by the elevator sorting option above. The effective value used
|
||||
by the driver for each probed SCSI device is reported at boot time.
|
||||
This is equivalent to the "eata=mq:8" boot option.
|
||||
|
||||
config SCSI_EATA_PIO
|
||||
tristate "EATA-PIO (old DPT PM2001, PM2012A) support"
|
||||
depends on (ISA || EISA || PCI) && SCSI && BROKEN
|
||||
---help---
|
||||
This driver supports all EATA-PIO protocol compliant SCSI Host
|
||||
Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant
|
||||
host adapters could also use this driver but are discouraged from
|
||||
doing so, since this driver only supports hard disks and lacks
|
||||
numerous features. You might want to have a look at the SCSI-HOWTO,
|
||||
available from <http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called eata_pio.
|
||||
|
||||
config SCSI_FUTURE_DOMAIN
|
||||
tristate "Future Domain 16xx SCSI/AHA-2920A support"
|
||||
depends on (ISA || PCI) && SCSI
|
||||
select CHECK_SIGNATURE
|
||||
---help---
|
||||
This is support for Future Domain's 16-bit SCSI host adapters
|
||||
(TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and
|
||||
other adapters based on the Future Domain chipsets (Quantum
|
||||
ISA-200S, ISA-250MG; Adaptec AHA-2920A; and at least one IBM board).
|
||||
It is explained in section 3.7 of the SCSI-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip
|
||||
and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI
|
||||
controller support"). This Future Domain driver works with the older
|
||||
Adaptec AHA-2920A boards with a Future Domain chip on them.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called fdomain.
|
||||
|
||||
config SCSI_GDTH
|
||||
tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support"
|
||||
depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API
|
||||
|
@ -923,18 +841,6 @@ config SCSI_IZIP_SLOW_CTR
|
|||
|
||||
Generally, saying N is fine.
|
||||
|
||||
config SCSI_NCR53C406A
|
||||
tristate "NCR53c406a SCSI support"
|
||||
depends on ISA && SCSI
|
||||
help
|
||||
This is support for the NCR53c406a SCSI host adapter. For user
|
||||
configurable parameters, check out <file:drivers/scsi/NCR53c406a.c>
|
||||
in the kernel source. Also read the SCSI-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called NCR53c406.
|
||||
|
||||
config SCSI_NCR_D700
|
||||
tristate "NCR Dual 700 MCA SCSI support"
|
||||
depends on MCA && SCSI
|
||||
|
@ -1059,6 +965,7 @@ config SCSI_IPR
|
|||
depends on PCI && SCSI && ATA
|
||||
select FW_LOADER
|
||||
select IRQ_POLL
|
||||
select SGL_ALLOC
|
||||
---help---
|
||||
This driver supports the IBM Power Linux family RAID adapters.
|
||||
This includes IBM pSeries 5712, 5703, 5709, and 570A, as well
|
||||
|
@ -1265,24 +1172,6 @@ config SCSI_SIM710
|
|||
|
||||
It currently supports Compaq EISA cards and NCR MCA cards
|
||||
|
||||
config SCSI_SYM53C416
|
||||
tristate "Symbios 53c416 SCSI support"
|
||||
depends on ISA && SCSI
|
||||
---help---
|
||||
This is support for the sym53c416 SCSI host adapter, the SCSI
|
||||
adapter that comes with some HP scanners. This driver requires that
|
||||
the sym53c416 is configured first using some sort of PnP
|
||||
configuration program (e.g. isapnp) or by a PnP aware BIOS. If you
|
||||
are using isapnp then you need to compile this driver as a module
|
||||
and then load it using insmod after isapnp has run. The parameters
|
||||
of the configured card(s) should be passed to the driver. The format
|
||||
is:
|
||||
|
||||
insmod sym53c416 sym53c416=<base>,<irq> [sym53c416_1=<base>,<irq>]
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called sym53c416.
|
||||
|
||||
config SCSI_DC395x
|
||||
tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support"
|
||||
depends on PCI && SCSI
|
||||
|
@ -1576,6 +1465,7 @@ config ZFCP
|
|||
config SCSI_PMCRAID
|
||||
tristate "PMC SIERRA Linux MaxRAID adapter support"
|
||||
depends on PCI && SCSI && NET
|
||||
select SGL_ALLOC
|
||||
---help---
|
||||
This driver supports the PMC SIERRA MaxRAID adapters.
|
||||
|
||||
|
|
|
@ -74,12 +74,9 @@ obj-$(CONFIG_SCSI_AIC94XX) += aic94xx/
|
|||
obj-$(CONFIG_SCSI_PM8001) += pm8001/
|
||||
obj-$(CONFIG_SCSI_ISCI) += isci/
|
||||
obj-$(CONFIG_SCSI_IPS) += ips.o
|
||||
obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o
|
||||
obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o
|
||||
obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o
|
||||
obj-$(CONFIG_SCSI_NCR_D700) += 53c700.o NCR_D700.o
|
||||
obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o
|
||||
obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o
|
||||
obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o
|
||||
obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o
|
||||
obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o
|
||||
|
@ -93,8 +90,6 @@ obj-$(CONFIG_SCSI_HPSA) += hpsa.o
|
|||
obj-$(CONFIG_SCSI_SMARTPQI) += smartpqi/
|
||||
obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/
|
||||
obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o
|
||||
obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
|
||||
obj-$(CONFIG_SCSI_EATA) += eata.o
|
||||
obj-$(CONFIG_SCSI_DC395x) += dc395x.o
|
||||
obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o
|
||||
obj-$(CONFIG_CXLFLASH) += cxlflash/
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1231,6 +1231,7 @@ struct src_registers {
|
|||
|
||||
#define SRC_ODR_SHIFT 12
|
||||
#define SRC_IDR_SHIFT 9
|
||||
#define SRC_MSI_READ_MASK 0x1000
|
||||
|
||||
typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);
|
||||
|
||||
|
@ -1528,6 +1529,7 @@ struct aac_bus_info_response {
|
|||
#define AAC_COMM_MESSAGE_TYPE3 5
|
||||
|
||||
#define AAC_EXTOPT_SA_FIRMWARE cpu_to_le32(1<<1)
|
||||
#define AAC_EXTOPT_SOFT_RESET cpu_to_le32(1<<16)
|
||||
|
||||
/* MSIX context */
|
||||
struct aac_msix_ctx {
|
||||
|
@ -1662,6 +1664,7 @@ struct aac_dev
|
|||
u8 raw_io_64;
|
||||
u8 printf_enabled;
|
||||
u8 in_reset;
|
||||
u8 in_soft_reset;
|
||||
u8 msi;
|
||||
u8 sa_firmware;
|
||||
int management_fib_count;
|
||||
|
@ -2504,6 +2507,7 @@ struct aac_hba_info {
|
|||
#define RCV_TEMP_READINGS 0x00000025
|
||||
#define GET_COMM_PREFERRED_SETTINGS 0x00000026
|
||||
#define IOP_RESET_FW_FIB_DUMP 0x00000034
|
||||
#define DROP_IO 0x00000035
|
||||
#define IOP_RESET 0x00001000
|
||||
#define IOP_RESET_ALWAYS 0x00001001
|
||||
#define RE_INIT_ADAPTER 0x000000ee
|
||||
|
@ -2539,6 +2543,7 @@ struct aac_hba_info {
|
|||
#define FLASH_UPD_PENDING 0x00002000
|
||||
#define FLASH_UPD_SUCCESS 0x00004000
|
||||
#define FLASH_UPD_FAILED 0x00008000
|
||||
#define INVALID_OMR 0xffffffff
|
||||
#define FWUPD_TIMEOUT (5 * 60)
|
||||
|
||||
/*
|
||||
|
|
|
@ -255,7 +255,8 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command,
|
|||
*/
|
||||
src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT);
|
||||
|
||||
if (!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) {
|
||||
if ((!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) &&
|
||||
!dev->in_soft_reset) {
|
||||
ok = 0;
|
||||
start = jiffies;
|
||||
|
||||
|
@ -679,6 +680,25 @@ void aac_set_intx_mode(struct aac_dev *dev)
|
|||
}
|
||||
}
|
||||
|
||||
static void aac_clear_omr(struct aac_dev *dev)
|
||||
{
|
||||
u32 omr_value = 0;
|
||||
|
||||
omr_value = src_readl(dev, MUnit.OMR);
|
||||
|
||||
/*
|
||||
* Check for PCI Errors or Kernel Panic
|
||||
*/
|
||||
if ((omr_value == INVALID_OMR) || (omr_value & KERNEL_PANIC))
|
||||
omr_value = 0;
|
||||
|
||||
/*
|
||||
* Preserve MSIX Value if any
|
||||
*/
|
||||
src_writel(dev, MUnit.OMR, omr_value & AAC_INT_MODE_MSIX);
|
||||
src_readl(dev, MUnit.OMR);
|
||||
}
|
||||
|
||||
static void aac_dump_fw_fib_iop_reset(struct aac_dev *dev)
|
||||
{
|
||||
__le32 supported_options3;
|
||||
|
@ -739,6 +759,8 @@ static void aac_send_iop_reset(struct aac_dev *dev)
|
|||
|
||||
aac_set_intx_mode(dev);
|
||||
|
||||
aac_clear_omr(dev);
|
||||
|
||||
src_writel(dev, MUnit.IDR, IOP_SRC_RESET_MASK);
|
||||
|
||||
msleep(5000);
|
||||
|
@ -748,6 +770,7 @@ static void aac_send_hardware_soft_reset(struct aac_dev *dev)
|
|||
{
|
||||
u_int32_t val;
|
||||
|
||||
aac_clear_omr(dev);
|
||||
val = readl(((char *)(dev->base) + IBW_SWR_OFFSET));
|
||||
val |= 0x01;
|
||||
writel(val, ((char *)(dev->base) + IBW_SWR_OFFSET));
|
||||
|
@ -992,6 +1015,148 @@ error_iounmap:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int aac_src_wait_sync(struct aac_dev *dev, int *status)
|
||||
{
|
||||
unsigned long start = jiffies;
|
||||
unsigned long usecs = 0;
|
||||
int delay = 5 * HZ;
|
||||
int rc = 1;
|
||||
|
||||
while (time_before(jiffies, start+delay)) {
|
||||
/*
|
||||
* Delay 5 microseconds to let Mon960 get info.
|
||||
*/
|
||||
udelay(5);
|
||||
|
||||
/*
|
||||
* Mon960 will set doorbell0 bit when it has completed the
|
||||
* command.
|
||||
*/
|
||||
if (aac_src_get_sync_status(dev) & OUTBOUNDDOORBELL_0) {
|
||||
/*
|
||||
* Clear: the doorbell.
|
||||
*/
|
||||
if (dev->msi_enabled)
|
||||
aac_src_access_devreg(dev, AAC_CLEAR_SYNC_BIT);
|
||||
else
|
||||
src_writel(dev, MUnit.ODR_C,
|
||||
OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
|
||||
rc = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Yield the processor in case we are slow
|
||||
*/
|
||||
usecs = 1 * USEC_PER_MSEC;
|
||||
usleep_range(usecs, usecs + 50);
|
||||
}
|
||||
/*
|
||||
* Pull the synch status from Mailbox 0.
|
||||
*/
|
||||
if (status && !rc) {
|
||||
status[0] = readl(&dev->IndexRegs->Mailbox[0]);
|
||||
status[1] = readl(&dev->IndexRegs->Mailbox[1]);
|
||||
status[2] = readl(&dev->IndexRegs->Mailbox[2]);
|
||||
status[3] = readl(&dev->IndexRegs->Mailbox[3]);
|
||||
status[4] = readl(&dev->IndexRegs->Mailbox[4]);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* aac_src_soft_reset - perform soft reset to speed up
|
||||
* access
|
||||
*
|
||||
* Assumptions: That the controller is in a state where we can
|
||||
* bring it back to life with an init struct. We can only use
|
||||
* fast sync commands, as the timeout is 5 seconds.
|
||||
*
|
||||
* @dev: device to configure
|
||||
*
|
||||
*/
|
||||
|
||||
static int aac_src_soft_reset(struct aac_dev *dev)
|
||||
{
|
||||
u32 status_omr = src_readl(dev, MUnit.OMR);
|
||||
u32 status[5];
|
||||
int rc = 1;
|
||||
int state = 0;
|
||||
char *state_str[7] = {
|
||||
"GET_ADAPTER_PROPERTIES Failed",
|
||||
"GET_ADAPTER_PROPERTIES timeout",
|
||||
"SOFT_RESET not supported",
|
||||
"DROP_IO Failed",
|
||||
"DROP_IO timeout",
|
||||
"Check Health failed"
|
||||
};
|
||||
|
||||
if (status_omr == INVALID_OMR)
|
||||
return 1; // pcie hosed
|
||||
|
||||
if (!(status_omr & KERNEL_UP_AND_RUNNING))
|
||||
return 1; // not up and running
|
||||
|
||||
/*
|
||||
* We go into soft reset mode to allow us to handle response
|
||||
*/
|
||||
dev->in_soft_reset = 1;
|
||||
dev->msi_enabled = status_omr & AAC_INT_MODE_MSIX;
|
||||
|
||||
/* Get adapter properties */
|
||||
rc = aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, 0, 0, 0,
|
||||
0, 0, 0, status+0, status+1, status+2, status+3, status+4);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
state++;
|
||||
if (aac_src_wait_sync(dev, status)) {
|
||||
rc = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
state++;
|
||||
if (!(status[1] & le32_to_cpu(AAC_OPT_EXTENDED) &&
|
||||
(status[4] & le32_to_cpu(AAC_EXTOPT_SOFT_RESET)))) {
|
||||
rc = 2;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((status[1] & le32_to_cpu(AAC_OPT_EXTENDED)) &&
|
||||
(status[4] & le32_to_cpu(AAC_EXTOPT_SA_FIRMWARE)))
|
||||
dev->sa_firmware = 1;
|
||||
|
||||
state++;
|
||||
rc = aac_adapter_sync_cmd(dev, DROP_IO, 0, 0, 0, 0, 0, 0,
|
||||
status+0, status+1, status+2, status+3, status+4);
|
||||
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
state++;
|
||||
if (aac_src_wait_sync(dev, status)) {
|
||||
rc = 3;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (status[1])
|
||||
dev_err(&dev->pdev->dev, "%s: %d outstanding I/O pending\n",
|
||||
__func__, status[1]);
|
||||
|
||||
state++;
|
||||
rc = aac_src_check_health(dev);
|
||||
|
||||
out:
|
||||
dev->in_soft_reset = 0;
|
||||
dev->msi_enabled = 0;
|
||||
if (rc)
|
||||
dev_err(&dev->pdev->dev, "%s: %s status = %d", __func__,
|
||||
state_str[state], rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
/**
|
||||
* aac_srcv_init - initialize an SRCv card
|
||||
* @dev: device to configure
|
||||
|
@ -1021,9 +1186,11 @@ int aac_srcv_init(struct aac_dev *dev)
|
|||
|
||||
if (dev->init_reset) {
|
||||
dev->init_reset = false;
|
||||
if (!aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET))
|
||||
if (aac_src_soft_reset(dev)) {
|
||||
aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET);
|
||||
++restart;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if flash update is running.
|
||||
|
@ -1072,13 +1239,16 @@ int aac_srcv_init(struct aac_dev *dev)
|
|||
printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
|
||||
goto error_iounmap;
|
||||
}
|
||||
|
||||
start = jiffies;
|
||||
/*
|
||||
* Wait for the adapter to be up and running. Wait up to 3 minutes
|
||||
*/
|
||||
while (!((status = src_readl(dev, MUnit.OMR)) &
|
||||
KERNEL_UP_AND_RUNNING) ||
|
||||
status == 0xffffffff) {
|
||||
do {
|
||||
status = src_readl(dev, MUnit.OMR);
|
||||
if (status == INVALID_OMR)
|
||||
status = 0;
|
||||
|
||||
if ((restart &&
|
||||
(status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
|
||||
time_after(jiffies, start+HZ*startup_timeout)) {
|
||||
|
@ -1098,7 +1268,8 @@ int aac_srcv_init(struct aac_dev *dev)
|
|||
++restart;
|
||||
}
|
||||
msleep(1);
|
||||
}
|
||||
} while (!(status & KERNEL_UP_AND_RUNNING));
|
||||
|
||||
if (restart && aac_commit)
|
||||
aac_commit = 1;
|
||||
/*
|
||||
|
@ -1234,13 +1405,23 @@ void aac_src_access_devreg(struct aac_dev *dev, int mode)
|
|||
|
||||
static int aac_src_get_sync_status(struct aac_dev *dev)
|
||||
{
|
||||
int msix_val = 0;
|
||||
int legacy_val = 0;
|
||||
|
||||
int val;
|
||||
msix_val = src_readl(dev, MUnit.ODR_MSI) & SRC_MSI_READ_MASK ? 1 : 0;
|
||||
|
||||
if (dev->msi_enabled)
|
||||
val = src_readl(dev, MUnit.ODR_MSI) & 0x1000 ? 1 : 0;
|
||||
else
|
||||
val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT;
|
||||
if (!dev->msi_enabled) {
|
||||
/*
|
||||
* if Legacy int status indicates cmd is not complete
|
||||
* sample MSIx register to see if it indiactes cmd complete,
|
||||
* if yes set the controller in MSIx mode and consider cmd
|
||||
* completed
|
||||
*/
|
||||
legacy_val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT;
|
||||
if (!(legacy_val & 1) && msix_val)
|
||||
dev->msi_enabled = 1;
|
||||
return legacy_val;
|
||||
}
|
||||
|
||||
return val;
|
||||
return msix_val;
|
||||
}
|
||||
|
|
|
@ -592,7 +592,7 @@ static int aha1740_probe (struct device *dev)
|
|||
DMA_BIDIRECTIONAL);
|
||||
if (!host->ecb_dma_addr) {
|
||||
printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
|
||||
scsi_unregister (shpnt);
|
||||
scsi_host_put (shpnt);
|
||||
goto err_host_put;
|
||||
}
|
||||
|
||||
|
|
|
@ -9338,9 +9338,9 @@ ahd_dumpseq(struct ahd_softc* ahd)
|
|||
static void
|
||||
ahd_loadseq(struct ahd_softc *ahd)
|
||||
{
|
||||
struct cs cs_table[num_critical_sections];
|
||||
u_int begin_set[num_critical_sections];
|
||||
u_int end_set[num_critical_sections];
|
||||
struct cs cs_table[NUM_CRITICAL_SECTIONS];
|
||||
u_int begin_set[NUM_CRITICAL_SECTIONS];
|
||||
u_int end_set[NUM_CRITICAL_SECTIONS];
|
||||
const struct patch *cur_patch;
|
||||
u_int cs_count;
|
||||
u_int cur_cs;
|
||||
|
@ -9456,7 +9456,7 @@ ahd_loadseq(struct ahd_softc *ahd)
|
|||
* Move through the CS table until we find a CS
|
||||
* that might apply to this instruction.
|
||||
*/
|
||||
for (; cur_cs < num_critical_sections; cur_cs++) {
|
||||
for (; cur_cs < NUM_CRITICAL_SECTIONS; cur_cs++) {
|
||||
if (critical_sections[cur_cs].end <= i) {
|
||||
if (begin_set[cs_count] == TRUE
|
||||
&& end_set[cs_count] == FALSE) {
|
||||
|
|
|
@ -1186,5 +1186,4 @@ static const struct cs {
|
|||
{ 759, 763 }
|
||||
};
|
||||
|
||||
static const int num_critical_sections = sizeof(critical_sections)
|
||||
/ sizeof(*critical_sections);
|
||||
#define NUM_CRITICAL_SECTIONS ARRAY_SIZE(critical_sections)
|
||||
|
|
|
@ -6848,9 +6848,9 @@ ahc_dumpseq(struct ahc_softc* ahc)
|
|||
static int
|
||||
ahc_loadseq(struct ahc_softc *ahc)
|
||||
{
|
||||
struct cs cs_table[num_critical_sections];
|
||||
u_int begin_set[num_critical_sections];
|
||||
u_int end_set[num_critical_sections];
|
||||
struct cs cs_table[NUM_CRITICAL_SECTIONS];
|
||||
u_int begin_set[NUM_CRITICAL_SECTIONS];
|
||||
u_int end_set[NUM_CRITICAL_SECTIONS];
|
||||
const struct patch *cur_patch;
|
||||
u_int cs_count;
|
||||
u_int cur_cs;
|
||||
|
@ -6915,7 +6915,7 @@ ahc_loadseq(struct ahc_softc *ahc)
|
|||
* Move through the CS table until we find a CS
|
||||
* that might apply to this instruction.
|
||||
*/
|
||||
for (; cur_cs < num_critical_sections; cur_cs++) {
|
||||
for (; cur_cs < NUM_CRITICAL_SECTIONS; cur_cs++) {
|
||||
if (critical_sections[cur_cs].end <= i) {
|
||||
if (begin_set[cs_count] == TRUE
|
||||
&& end_set[cs_count] == FALSE) {
|
||||
|
|
|
@ -1304,5 +1304,4 @@ static const struct cs {
|
|||
{ 875, 877 }
|
||||
};
|
||||
|
||||
static const int num_critical_sections = sizeof(critical_sections)
|
||||
/ sizeof(*critical_sections);
|
||||
#define NUM_CRITICAL_SECTIONS ARRAY_SIZE(critical_sections)
|
||||
|
|
|
@ -451,8 +451,7 @@ output_code()
|
|||
fprintf(ofile, "\n};\n\n");
|
||||
|
||||
fprintf(ofile,
|
||||
"static const int num_critical_sections = sizeof(critical_sections)\n"
|
||||
" / sizeof(*critical_sections);\n");
|
||||
"#define NUM_CRITICAL_SECTIONS ARRAY_SIZE(critical_sections)\n");
|
||||
|
||||
fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ struct device_attribute;
|
|||
#define ARCMSR_MAX_OUTSTANDING_CMD 1024
|
||||
#define ARCMSR_DEFAULT_OUTSTANDING_CMD 128
|
||||
#define ARCMSR_MIN_OUTSTANDING_CMD 32
|
||||
#define ARCMSR_DRIVER_VERSION "v1.40.00.04-20171130"
|
||||
#define ARCMSR_DRIVER_VERSION "v1.40.00.05-20180309"
|
||||
#define ARCMSR_SCSI_INITIATOR_ID 255
|
||||
#define ARCMSR_MAX_XFER_SECTORS 512
|
||||
#define ARCMSR_MAX_XFER_SECTORS_B 4096
|
||||
|
@ -779,12 +779,12 @@ struct AdapterControlBlock
|
|||
/* message clear rqbuffer */
|
||||
#define ACB_F_MESSAGE_WQBUFFER_READED 0x0040
|
||||
#define ACB_F_BUS_RESET 0x0080
|
||||
#define ACB_F_BUS_HANG_ON 0x0800/* need hardware reset bus */
|
||||
|
||||
#define ACB_F_IOP_INITED 0x0100
|
||||
/* iop init */
|
||||
#define ACB_F_ABORT 0x0200
|
||||
#define ACB_F_FIRMWARE_TRAP 0x0400
|
||||
#define ACB_F_ADAPTER_REMOVED 0x0800
|
||||
#define ACB_F_MSG_GET_CONFIG 0x1000
|
||||
struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM];
|
||||
/* used for memory free */
|
||||
|
|
|
@ -1446,12 +1446,80 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
|
|||
}
|
||||
}
|
||||
|
||||
static void arcmsr_remove_scsi_devices(struct AdapterControlBlock *acb)
|
||||
{
|
||||
char *acb_dev_map = (char *)acb->device_map;
|
||||
int target, lun, i;
|
||||
struct scsi_device *psdev;
|
||||
struct CommandControlBlock *ccb;
|
||||
char temp;
|
||||
|
||||
for (i = 0; i < acb->maxFreeCCB; i++) {
|
||||
ccb = acb->pccb_pool[i];
|
||||
if (ccb->startdone == ARCMSR_CCB_START) {
|
||||
ccb->pcmd->result = DID_NO_CONNECT << 16;
|
||||
arcmsr_pci_unmap_dma(ccb);
|
||||
ccb->pcmd->scsi_done(ccb->pcmd);
|
||||
}
|
||||
}
|
||||
for (target = 0; target < ARCMSR_MAX_TARGETID; target++) {
|
||||
temp = *acb_dev_map;
|
||||
if (temp) {
|
||||
for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) {
|
||||
if (temp & 1) {
|
||||
psdev = scsi_device_lookup(acb->host,
|
||||
0, target, lun);
|
||||
if (psdev != NULL) {
|
||||
scsi_remove_device(psdev);
|
||||
scsi_device_put(psdev);
|
||||
}
|
||||
}
|
||||
temp >>= 1;
|
||||
}
|
||||
*acb_dev_map = 0;
|
||||
}
|
||||
acb_dev_map++;
|
||||
}
|
||||
}
|
||||
|
||||
static void arcmsr_free_pcidev(struct AdapterControlBlock *acb)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
struct Scsi_Host *host;
|
||||
|
||||
host = acb->host;
|
||||
arcmsr_free_sysfs_attr(acb);
|
||||
scsi_remove_host(host);
|
||||
flush_work(&acb->arcmsr_do_message_isr_bh);
|
||||
del_timer_sync(&acb->eternal_timer);
|
||||
if (set_date_time)
|
||||
del_timer_sync(&acb->refresh_timer);
|
||||
pdev = acb->pdev;
|
||||
arcmsr_free_irq(pdev, acb);
|
||||
arcmsr_free_ccb_pool(acb);
|
||||
arcmsr_free_mu(acb);
|
||||
arcmsr_unmap_pciregion(acb);
|
||||
pci_release_regions(pdev);
|
||||
scsi_host_put(host);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static void arcmsr_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *host = pci_get_drvdata(pdev);
|
||||
struct AdapterControlBlock *acb =
|
||||
(struct AdapterControlBlock *) host->hostdata;
|
||||
int poll_count = 0;
|
||||
uint16_t dev_id;
|
||||
|
||||
pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id);
|
||||
if (dev_id == 0xffff) {
|
||||
acb->acb_flags &= ~ACB_F_IOP_INITED;
|
||||
acb->acb_flags |= ACB_F_ADAPTER_REMOVED;
|
||||
arcmsr_remove_scsi_devices(acb);
|
||||
arcmsr_free_pcidev(acb);
|
||||
return;
|
||||
}
|
||||
arcmsr_free_sysfs_attr(acb);
|
||||
scsi_remove_host(host);
|
||||
flush_work(&acb->arcmsr_do_message_isr_bh);
|
||||
|
@ -1499,6 +1567,8 @@ static void arcmsr_shutdown(struct pci_dev *pdev)
|
|||
struct Scsi_Host *host = pci_get_drvdata(pdev);
|
||||
struct AdapterControlBlock *acb =
|
||||
(struct AdapterControlBlock *)host->hostdata;
|
||||
if (acb->acb_flags & ACB_F_ADAPTER_REMOVED)
|
||||
return;
|
||||
del_timer_sync(&acb->eternal_timer);
|
||||
if (set_date_time)
|
||||
del_timer_sync(&acb->refresh_timer);
|
||||
|
@ -2931,6 +3001,12 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd,
|
|||
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
|
||||
struct CommandControlBlock *ccb;
|
||||
int target = cmd->device->id;
|
||||
|
||||
if (acb->acb_flags & ACB_F_ADAPTER_REMOVED) {
|
||||
cmd->result = (DID_NO_CONNECT << 16);
|
||||
cmd->scsi_done(cmd);
|
||||
return 0;
|
||||
}
|
||||
cmd->scsi_done = done;
|
||||
cmd->host_scribble = NULL;
|
||||
cmd->result = 0;
|
||||
|
@ -3731,6 +3807,8 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
|
|||
case ACB_ADAPTER_TYPE_A: {
|
||||
struct MessageUnit_A __iomem *reg = acb->pmuA;
|
||||
do {
|
||||
if (!(acb->acb_flags & ACB_F_IOP_INITED))
|
||||
msleep(20);
|
||||
firmware_state = readl(®->outbound_msgaddr1);
|
||||
} while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0);
|
||||
}
|
||||
|
@ -3739,6 +3817,8 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
|
|||
case ACB_ADAPTER_TYPE_B: {
|
||||
struct MessageUnit_B *reg = acb->pmuB;
|
||||
do {
|
||||
if (!(acb->acb_flags & ACB_F_IOP_INITED))
|
||||
msleep(20);
|
||||
firmware_state = readl(reg->iop2drv_doorbell);
|
||||
} while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0);
|
||||
writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell);
|
||||
|
@ -3747,6 +3827,8 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
|
|||
case ACB_ADAPTER_TYPE_C: {
|
||||
struct MessageUnit_C __iomem *reg = acb->pmuC;
|
||||
do {
|
||||
if (!(acb->acb_flags & ACB_F_IOP_INITED))
|
||||
msleep(20);
|
||||
firmware_state = readl(®->outbound_msgaddr1);
|
||||
} while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0);
|
||||
}
|
||||
|
@ -3754,6 +3836,8 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
|
|||
case ACB_ADAPTER_TYPE_D: {
|
||||
struct MessageUnit_D *reg = acb->pmuD;
|
||||
do {
|
||||
if (!(acb->acb_flags & ACB_F_IOP_INITED))
|
||||
msleep(20);
|
||||
firmware_state = readl(reg->outbound_msgaddr1);
|
||||
} while ((firmware_state &
|
||||
ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK) == 0);
|
||||
|
@ -3762,6 +3846,8 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
|
|||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
do {
|
||||
if (!(acb->acb_flags & ACB_F_IOP_INITED))
|
||||
msleep(20);
|
||||
firmware_state = readl(®->outbound_msgaddr1);
|
||||
} while ((firmware_state & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0);
|
||||
}
|
||||
|
@ -4177,6 +4263,8 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
|
|||
int retry_count = 0;
|
||||
int rtn = FAILED;
|
||||
acb = (struct AdapterControlBlock *) cmd->device->host->hostdata;
|
||||
if (acb->acb_flags & ACB_F_ADAPTER_REMOVED)
|
||||
return SUCCESS;
|
||||
pr_notice("arcmsr: executing bus reset eh.....num_resets = %d,"
|
||||
" num_aborts = %d \n", acb->num_resets, acb->num_aborts);
|
||||
acb->num_resets++;
|
||||
|
@ -4243,6 +4331,8 @@ static int arcmsr_abort(struct scsi_cmnd *cmd)
|
|||
int rtn = FAILED;
|
||||
uint32_t intmask_org;
|
||||
|
||||
if (acb->acb_flags & ACB_F_ADAPTER_REMOVED)
|
||||
return SUCCESS;
|
||||
printk(KERN_NOTICE
|
||||
"arcmsr%d: abort device command of scsi id = %d lun = %d\n",
|
||||
acb->host->host_no, cmd->device->id, (u32)cmd->device->lun);
|
||||
|
|
|
@ -1413,11 +1413,11 @@ static void atp885_init(struct Scsi_Host *shpnt)
|
|||
atpdev->global_map[m] = 0;
|
||||
for (k = 0; k < 4; k++) {
|
||||
atp_writew_base(atpdev, 0x3c, n++);
|
||||
((unsigned long *)&setupdata[m][0])[k] = atp_readl_base(atpdev, 0x38);
|
||||
((u32 *)&setupdata[m][0])[k] = atp_readl_base(atpdev, 0x38);
|
||||
}
|
||||
for (k = 0; k < 4; k++) {
|
||||
atp_writew_base(atpdev, 0x3c, n++);
|
||||
((unsigned long *)&atpdev->sp[m][0])[k] = atp_readl_base(atpdev, 0x38);
|
||||
((u32 *)&atpdev->sp[m][0])[k] = atp_readl_base(atpdev, 0x38);
|
||||
}
|
||||
n += 8;
|
||||
}
|
||||
|
|
|
@ -891,7 +891,7 @@ bfad_iocmd_fabric_get_lports(struct bfad_s *bfad, void *cmd,
|
|||
|
||||
if (bfad_chk_iocmd_sz(payload_len,
|
||||
sizeof(struct bfa_bsg_fabric_get_lports_s),
|
||||
sizeof(wwn_t[iocmd->nports])) != BFA_STATUS_OK) {
|
||||
sizeof(wwn_t) * iocmd->nports) != BFA_STATUS_OK) {
|
||||
iocmd->status = BFA_STATUS_VERSION_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -274,12 +274,24 @@ csio_get_host_speed(struct Scsi_Host *shost)
|
|||
|
||||
spin_lock_irq(&hw->lock);
|
||||
switch (hw->pport[ln->portid].link_speed) {
|
||||
case FW_PORT_CAP_SPEED_1G:
|
||||
case FW_PORT_CAP32_SPEED_1G:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
|
||||
break;
|
||||
case FW_PORT_CAP_SPEED_10G:
|
||||
case FW_PORT_CAP32_SPEED_10G:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
|
||||
break;
|
||||
case FW_PORT_CAP32_SPEED_25G:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_25GBIT;
|
||||
break;
|
||||
case FW_PORT_CAP32_SPEED_40G:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_40GBIT;
|
||||
break;
|
||||
case FW_PORT_CAP32_SPEED_50G:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_50GBIT;
|
||||
break;
|
||||
case FW_PORT_CAP32_SPEED_100G:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_100GBIT;
|
||||
break;
|
||||
default:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
|
||||
break;
|
||||
|
|
|
@ -1409,6 +1409,235 @@ out:
|
|||
return rv;
|
||||
}
|
||||
|
||||
static inline enum cc_fec fwcap_to_cc_fec(fw_port_cap32_t fw_fec)
|
||||
{
|
||||
enum cc_fec cc_fec = 0;
|
||||
|
||||
if (fw_fec & FW_PORT_CAP32_FEC_RS)
|
||||
cc_fec |= FEC_RS;
|
||||
if (fw_fec & FW_PORT_CAP32_FEC_BASER_RS)
|
||||
cc_fec |= FEC_BASER_RS;
|
||||
|
||||
return cc_fec;
|
||||
}
|
||||
|
||||
static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
|
||||
{
|
||||
fw_port_cap32_t fw_pause = 0;
|
||||
|
||||
if (cc_pause & PAUSE_RX)
|
||||
fw_pause |= FW_PORT_CAP32_FC_RX;
|
||||
if (cc_pause & PAUSE_TX)
|
||||
fw_pause |= FW_PORT_CAP32_FC_TX;
|
||||
|
||||
return fw_pause;
|
||||
}
|
||||
|
||||
static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
|
||||
{
|
||||
fw_port_cap32_t fw_fec = 0;
|
||||
|
||||
if (cc_fec & FEC_RS)
|
||||
fw_fec |= FW_PORT_CAP32_FEC_RS;
|
||||
if (cc_fec & FEC_BASER_RS)
|
||||
fw_fec |= FW_PORT_CAP32_FEC_BASER_RS;
|
||||
|
||||
return fw_fec;
|
||||
}
|
||||
|
||||
/**
|
||||
* fwcap_to_fwspeed - return highest speed in Port Capabilities
|
||||
* @acaps: advertised Port Capabilities
|
||||
*
|
||||
* Get the highest speed for the port from the advertised Port
|
||||
* Capabilities.
|
||||
*/
|
||||
fw_port_cap32_t fwcap_to_fwspeed(fw_port_cap32_t acaps)
|
||||
{
|
||||
#define TEST_SPEED_RETURN(__caps_speed) \
|
||||
do { \
|
||||
if (acaps & FW_PORT_CAP32_SPEED_##__caps_speed) \
|
||||
return FW_PORT_CAP32_SPEED_##__caps_speed; \
|
||||
} while (0)
|
||||
|
||||
TEST_SPEED_RETURN(400G);
|
||||
TEST_SPEED_RETURN(200G);
|
||||
TEST_SPEED_RETURN(100G);
|
||||
TEST_SPEED_RETURN(50G);
|
||||
TEST_SPEED_RETURN(40G);
|
||||
TEST_SPEED_RETURN(25G);
|
||||
TEST_SPEED_RETURN(10G);
|
||||
TEST_SPEED_RETURN(1G);
|
||||
TEST_SPEED_RETURN(100M);
|
||||
|
||||
#undef TEST_SPEED_RETURN
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fwcaps16_to_caps32 - convert 16-bit Port Capabilities to 32-bits
|
||||
* @caps16: a 16-bit Port Capabilities value
|
||||
*
|
||||
* Returns the equivalent 32-bit Port Capabilities value.
|
||||
*/
|
||||
fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16)
|
||||
{
|
||||
fw_port_cap32_t caps32 = 0;
|
||||
|
||||
#define CAP16_TO_CAP32(__cap) \
|
||||
do { \
|
||||
if (caps16 & FW_PORT_CAP_##__cap) \
|
||||
caps32 |= FW_PORT_CAP32_##__cap; \
|
||||
} while (0)
|
||||
|
||||
CAP16_TO_CAP32(SPEED_100M);
|
||||
CAP16_TO_CAP32(SPEED_1G);
|
||||
CAP16_TO_CAP32(SPEED_25G);
|
||||
CAP16_TO_CAP32(SPEED_10G);
|
||||
CAP16_TO_CAP32(SPEED_40G);
|
||||
CAP16_TO_CAP32(SPEED_100G);
|
||||
CAP16_TO_CAP32(FC_RX);
|
||||
CAP16_TO_CAP32(FC_TX);
|
||||
CAP16_TO_CAP32(ANEG);
|
||||
CAP16_TO_CAP32(MDIX);
|
||||
CAP16_TO_CAP32(MDIAUTO);
|
||||
CAP16_TO_CAP32(FEC_RS);
|
||||
CAP16_TO_CAP32(FEC_BASER_RS);
|
||||
CAP16_TO_CAP32(802_3_PAUSE);
|
||||
CAP16_TO_CAP32(802_3_ASM_DIR);
|
||||
|
||||
#undef CAP16_TO_CAP32
|
||||
|
||||
return caps32;
|
||||
}
|
||||
|
||||
/**
|
||||
* lstatus_to_fwcap - translate old lstatus to 32-bit Port Capabilities
|
||||
* @lstatus: old FW_PORT_ACTION_GET_PORT_INFO lstatus value
|
||||
*
|
||||
* Translates old FW_PORT_ACTION_GET_PORT_INFO lstatus field into new
|
||||
* 32-bit Port Capabilities value.
|
||||
*/
|
||||
fw_port_cap32_t lstatus_to_fwcap(u32 lstatus)
|
||||
{
|
||||
fw_port_cap32_t linkattr = 0;
|
||||
|
||||
/* The format of the Link Status in the old
|
||||
* 16-bit Port Information message isn't the same as the
|
||||
* 16-bit Port Capabilities bitfield used everywhere else.
|
||||
*/
|
||||
if (lstatus & FW_PORT_CMD_RXPAUSE_F)
|
||||
linkattr |= FW_PORT_CAP32_FC_RX;
|
||||
if (lstatus & FW_PORT_CMD_TXPAUSE_F)
|
||||
linkattr |= FW_PORT_CAP32_FC_TX;
|
||||
if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M))
|
||||
linkattr |= FW_PORT_CAP32_SPEED_100M;
|
||||
if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G))
|
||||
linkattr |= FW_PORT_CAP32_SPEED_1G;
|
||||
if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G))
|
||||
linkattr |= FW_PORT_CAP32_SPEED_10G;
|
||||
if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_25G))
|
||||
linkattr |= FW_PORT_CAP32_SPEED_25G;
|
||||
if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G))
|
||||
linkattr |= FW_PORT_CAP32_SPEED_40G;
|
||||
if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100G))
|
||||
linkattr |= FW_PORT_CAP32_SPEED_100G;
|
||||
|
||||
return linkattr;
|
||||
}
|
||||
|
||||
/**
|
||||
* csio_init_link_config - initialize a link's SW state
|
||||
* @lc: pointer to structure holding the link state
|
||||
* @pcaps: link Port Capabilities
|
||||
* @acaps: link current Advertised Port Capabilities
|
||||
*
|
||||
* Initializes the SW state maintained for each link, including the link's
|
||||
* capabilities and default speed/flow-control/autonegotiation settings.
|
||||
*/
|
||||
static void csio_init_link_config(struct link_config *lc, fw_port_cap32_t pcaps,
|
||||
fw_port_cap32_t acaps)
|
||||
{
|
||||
lc->pcaps = pcaps;
|
||||
lc->def_acaps = acaps;
|
||||
lc->lpacaps = 0;
|
||||
lc->speed_caps = 0;
|
||||
lc->speed = 0;
|
||||
lc->requested_fc = PAUSE_RX | PAUSE_TX;
|
||||
lc->fc = lc->requested_fc;
|
||||
|
||||
/*
|
||||
* For Forward Error Control, we default to whatever the Firmware
|
||||
* tells us the Link is currently advertising.
|
||||
*/
|
||||
lc->requested_fec = FEC_AUTO;
|
||||
lc->fec = fwcap_to_cc_fec(lc->def_acaps);
|
||||
|
||||
/* If the Port is capable of Auto-Negtotiation, initialize it as
|
||||
* "enabled" and copy over all of the Physical Port Capabilities
|
||||
* to the Advertised Port Capabilities. Otherwise mark it as
|
||||
* Auto-Negotiate disabled and select the highest supported speed
|
||||
* for the link. Note parallel structure in t4_link_l1cfg_core()
|
||||
* and t4_handle_get_port_info().
|
||||
*/
|
||||
if (lc->pcaps & FW_PORT_CAP32_ANEG) {
|
||||
lc->acaps = lc->pcaps & ADVERT_MASK;
|
||||
lc->autoneg = AUTONEG_ENABLE;
|
||||
lc->requested_fc |= PAUSE_AUTONEG;
|
||||
} else {
|
||||
lc->acaps = 0;
|
||||
lc->autoneg = AUTONEG_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void csio_link_l1cfg(struct link_config *lc, uint16_t fw_caps,
|
||||
uint32_t *rcaps)
|
||||
{
|
||||
unsigned int fw_mdi = FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO);
|
||||
fw_port_cap32_t fw_fc, cc_fec, fw_fec, lrcap;
|
||||
|
||||
lc->link_ok = 0;
|
||||
|
||||
/*
|
||||
* Convert driver coding of Pause Frame Flow Control settings into the
|
||||
* Firmware's API.
|
||||
*/
|
||||
fw_fc = cc_to_fwcap_pause(lc->requested_fc);
|
||||
|
||||
/*
|
||||
* Convert Common Code Forward Error Control settings into the
|
||||
* Firmware's API. If the current Requested FEC has "Automatic"
|
||||
* (IEEE 802.3) specified, then we use whatever the Firmware
|
||||
* sent us as part of it's IEEE 802.3-based interpratation of
|
||||
* the Transceiver Module EPROM FEC parameters. Otherwise we
|
||||
* use whatever is in the current Requested FEC settings.
|
||||
*/
|
||||
if (lc->requested_fec & FEC_AUTO)
|
||||
cc_fec = fwcap_to_cc_fec(lc->def_acaps);
|
||||
else
|
||||
cc_fec = lc->requested_fec;
|
||||
fw_fec = cc_to_fwcap_fec(cc_fec);
|
||||
|
||||
/* Figure out what our Requested Port Capabilities are going to be.
|
||||
* Note parallel structure in t4_handle_get_port_info() and
|
||||
* init_link_config().
|
||||
*/
|
||||
if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
|
||||
lrcap = (lc->pcaps & ADVERT_MASK) | fw_fc | fw_fec;
|
||||
lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
|
||||
lc->fec = cc_fec;
|
||||
} else if (lc->autoneg == AUTONEG_DISABLE) {
|
||||
lrcap = lc->speed_caps | fw_fc | fw_fec | fw_mdi;
|
||||
lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
|
||||
lc->fec = cc_fec;
|
||||
} else {
|
||||
lrcap = lc->acaps | fw_fc | fw_fec | fw_mdi;
|
||||
}
|
||||
|
||||
*rcaps = lrcap;
|
||||
}
|
||||
|
||||
/*
|
||||
* csio_enable_ports - Bring up all available ports.
|
||||
* @hw: HW module.
|
||||
|
@ -1418,8 +1647,10 @@ static int
|
|||
csio_enable_ports(struct csio_hw *hw)
|
||||
{
|
||||
struct csio_mb *mbp;
|
||||
u16 fw_caps = FW_CAPS_UNKNOWN;
|
||||
enum fw_retval retval;
|
||||
uint8_t portid;
|
||||
fw_port_cap32_t pcaps, acaps, rcaps;
|
||||
int i;
|
||||
|
||||
mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
|
||||
|
@ -1431,9 +1662,39 @@ csio_enable_ports(struct csio_hw *hw)
|
|||
for (i = 0; i < hw->num_pports; i++) {
|
||||
portid = hw->pport[i].portid;
|
||||
|
||||
if (fw_caps == FW_CAPS_UNKNOWN) {
|
||||
u32 param, val;
|
||||
|
||||
param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) |
|
||||
FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_PORT_CAPS32));
|
||||
val = 1;
|
||||
|
||||
csio_mb_params(hw, mbp, CSIO_MB_DEFAULT_TMO,
|
||||
hw->pfn, 0, 1, ¶m, &val, false,
|
||||
NULL);
|
||||
|
||||
if (csio_mb_issue(hw, mbp)) {
|
||||
csio_err(hw, "failed to issue FW_PARAMS_CMD(r) port:%d\n",
|
||||
portid);
|
||||
mempool_free(mbp, hw->mb_mempool);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
csio_mb_process_read_params_rsp(hw, mbp, &retval, 1,
|
||||
&val);
|
||||
if (retval != FW_SUCCESS) {
|
||||
csio_err(hw, "FW_PARAMS_CMD(r) port:%d failed: 0x%x\n",
|
||||
portid, retval);
|
||||
mempool_free(mbp, hw->mb_mempool);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fw_caps = val;
|
||||
}
|
||||
|
||||
/* Read PORT information */
|
||||
csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid,
|
||||
false, 0, 0, NULL);
|
||||
false, 0, fw_caps, NULL);
|
||||
|
||||
if (csio_mb_issue(hw, mbp)) {
|
||||
csio_err(hw, "failed to issue FW_PORT_CMD(r) port:%d\n",
|
||||
|
@ -1442,8 +1703,8 @@ csio_enable_ports(struct csio_hw *hw)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
csio_mb_process_read_port_rsp(hw, mbp, &retval,
|
||||
&hw->pport[i].pcap);
|
||||
csio_mb_process_read_port_rsp(hw, mbp, &retval, fw_caps,
|
||||
&pcaps, &acaps);
|
||||
if (retval != FW_SUCCESS) {
|
||||
csio_err(hw, "FW_PORT_CMD(r) port:%d failed: 0x%x\n",
|
||||
portid, retval);
|
||||
|
@ -1451,9 +1712,13 @@ csio_enable_ports(struct csio_hw *hw)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
csio_init_link_config(&hw->pport[i].link_cfg, pcaps, acaps);
|
||||
|
||||
csio_link_l1cfg(&hw->pport[i].link_cfg, fw_caps, &rcaps);
|
||||
|
||||
/* Write back PORT information */
|
||||
csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid, true,
|
||||
(PAUSE_RX | PAUSE_TX), hw->pport[i].pcap, NULL);
|
||||
csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid,
|
||||
true, rcaps, fw_caps, NULL);
|
||||
|
||||
if (csio_mb_issue(hw, mbp)) {
|
||||
csio_err(hw, "failed to issue FW_PORT_CMD(w) port:%d\n",
|
||||
|
|
|
@ -268,8 +268,62 @@ struct csio_vpd {
|
|||
uint8_t id[ID_LEN + 1];
|
||||
};
|
||||
|
||||
/* Firmware Port Capabilities types. */
|
||||
|
||||
typedef u16 fw_port_cap16_t; /* 16-bit Port Capabilities integral value */
|
||||
typedef u32 fw_port_cap32_t; /* 32-bit Port Capabilities integral value */
|
||||
|
||||
enum fw_caps {
|
||||
FW_CAPS_UNKNOWN = 0, /* 0'ed out initial state */
|
||||
FW_CAPS16 = 1, /* old Firmware: 16-bit Port Capabilities */
|
||||
FW_CAPS32 = 2, /* new Firmware: 32-bit Port Capabilities */
|
||||
};
|
||||
|
||||
enum cc_pause {
|
||||
PAUSE_RX = 1 << 0,
|
||||
PAUSE_TX = 1 << 1,
|
||||
PAUSE_AUTONEG = 1 << 2
|
||||
};
|
||||
|
||||
enum cc_fec {
|
||||
FEC_AUTO = 1 << 0, /* IEEE 802.3 "automatic" */
|
||||
FEC_RS = 1 << 1, /* Reed-Solomon */
|
||||
FEC_BASER_RS = 1 << 2 /* BaseR/Reed-Solomon */
|
||||
};
|
||||
|
||||
struct link_config {
|
||||
fw_port_cap32_t pcaps; /* link capabilities */
|
||||
fw_port_cap32_t def_acaps; /* default advertised capabilities */
|
||||
fw_port_cap32_t acaps; /* advertised capabilities */
|
||||
fw_port_cap32_t lpacaps; /* peer advertised capabilities */
|
||||
|
||||
fw_port_cap32_t speed_caps; /* speed(s) user has requested */
|
||||
unsigned int speed; /* actual link speed (Mb/s) */
|
||||
|
||||
enum cc_pause requested_fc; /* flow control user has requested */
|
||||
enum cc_pause fc; /* actual link flow control */
|
||||
|
||||
enum cc_fec requested_fec; /* Forward Error Correction: */
|
||||
enum cc_fec fec; /* requested and actual in use */
|
||||
|
||||
unsigned char autoneg; /* autonegotiating? */
|
||||
|
||||
unsigned char link_ok; /* link up? */
|
||||
unsigned char link_down_rc; /* link down reason */
|
||||
};
|
||||
|
||||
#define FW_LEN16(fw_struct) FW_CMD_LEN16_V(sizeof(fw_struct) / 16)
|
||||
|
||||
#define ADVERT_MASK (FW_PORT_CAP32_SPEED_V(FW_PORT_CAP32_SPEED_M) | \
|
||||
FW_PORT_CAP32_ANEG)
|
||||
|
||||
/* Enable or disable autonegotiation. */
|
||||
#define AUTONEG_DISABLE 0x00
|
||||
#define AUTONEG_ENABLE 0x01
|
||||
|
||||
struct csio_pport {
|
||||
uint16_t pcap;
|
||||
uint16_t acap;
|
||||
uint8_t portid;
|
||||
uint8_t link_status;
|
||||
uint16_t link_speed;
|
||||
|
@ -278,6 +332,7 @@ struct csio_pport {
|
|||
uint8_t rsvd1;
|
||||
uint8_t rsvd2;
|
||||
uint8_t rsvd3;
|
||||
struct link_config link_cfg;
|
||||
};
|
||||
|
||||
/* fcoe resource information */
|
||||
|
@ -582,6 +637,10 @@ int csio_hw_slow_intr_handler(struct csio_hw *);
|
|||
int csio_handle_intr_status(struct csio_hw *, unsigned int,
|
||||
const struct intr_info *);
|
||||
|
||||
fw_port_cap32_t fwcap_to_fwspeed(fw_port_cap32_t acaps);
|
||||
fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16);
|
||||
fw_port_cap32_t lstatus_to_fwcap(u32 lstatus);
|
||||
|
||||
int csio_hw_start(struct csio_hw *);
|
||||
int csio_hw_stop(struct csio_hw *);
|
||||
int csio_hw_reset(struct csio_hw *);
|
||||
|
|
|
@ -352,6 +352,14 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
|
|||
val = htonl(FC_PORTSPEED_1GBIT);
|
||||
else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_10G)
|
||||
val = htonl(FC_PORTSPEED_10GBIT);
|
||||
else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_25G)
|
||||
val = htonl(FC_PORTSPEED_25GBIT);
|
||||
else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_40G)
|
||||
val = htonl(FC_PORTSPEED_40GBIT);
|
||||
else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_50G)
|
||||
val = htonl(FC_PORTSPEED_50GBIT);
|
||||
else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_100G)
|
||||
val = htonl(FC_PORTSPEED_100GBIT);
|
||||
else
|
||||
val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN);
|
||||
csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
|
||||
|
|
|
@ -326,10 +326,6 @@ csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
|
|||
cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_TARGET);
|
||||
}
|
||||
|
||||
#define CSIO_ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
|
||||
FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G |\
|
||||
FW_PORT_CAP_ANEG)
|
||||
|
||||
/*
|
||||
* csio_mb_port- FW PORT command helper
|
||||
* @hw: The HW structure
|
||||
|
@ -344,11 +340,10 @@ csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
|
|||
*/
|
||||
void
|
||||
csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
|
||||
uint8_t portid, bool wr, uint32_t fc, uint16_t caps,
|
||||
u8 portid, bool wr, uint32_t fc, uint16_t fw_caps,
|
||||
void (*cbfn) (struct csio_hw *, struct csio_mb *))
|
||||
{
|
||||
struct fw_port_cmd *cmdp = (struct fw_port_cmd *)(mbp->mb);
|
||||
unsigned int lfc = 0, mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO);
|
||||
|
||||
CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
|
||||
|
||||
|
@ -358,26 +353,24 @@ csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
|
|||
FW_PORT_CMD_PORTID_V(portid));
|
||||
if (!wr) {
|
||||
cmdp->action_to_len16 = htonl(
|
||||
FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) |
|
||||
FW_PORT_CMD_ACTION_V(fw_caps == FW_CAPS16
|
||||
? FW_PORT_ACTION_GET_PORT_INFO
|
||||
: FW_PORT_ACTION_GET_PORT_INFO32) |
|
||||
FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set port */
|
||||
cmdp->action_to_len16 = htonl(
|
||||
FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_L1_CFG) |
|
||||
FW_PORT_CMD_ACTION_V(fw_caps == FW_CAPS16
|
||||
? FW_PORT_ACTION_L1_CFG
|
||||
: FW_PORT_ACTION_L1_CFG32) |
|
||||
FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
|
||||
|
||||
if (fc & PAUSE_RX)
|
||||
lfc |= FW_PORT_CAP_FC_RX;
|
||||
if (fc & PAUSE_TX)
|
||||
lfc |= FW_PORT_CAP_FC_TX;
|
||||
|
||||
if (!(caps & FW_PORT_CAP_ANEG))
|
||||
cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | lfc);
|
||||
if (fw_caps == FW_CAPS16)
|
||||
cmdp->u.l1cfg.rcap = cpu_to_be32(fc);
|
||||
else
|
||||
cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) |
|
||||
lfc | mdi);
|
||||
cmdp->u.l1cfg32.rcap32 = cpu_to_be32(fc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -390,14 +383,22 @@ csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
|
|||
*/
|
||||
void
|
||||
csio_mb_process_read_port_rsp(struct csio_hw *hw, struct csio_mb *mbp,
|
||||
enum fw_retval *retval, uint16_t *caps)
|
||||
enum fw_retval *retval, uint16_t fw_caps,
|
||||
u32 *pcaps, u32 *acaps)
|
||||
{
|
||||
struct fw_port_cmd *rsp = (struct fw_port_cmd *)(mbp->mb);
|
||||
|
||||
*retval = FW_CMD_RETVAL_G(ntohl(rsp->action_to_len16));
|
||||
|
||||
if (*retval == FW_SUCCESS)
|
||||
*caps = ntohs(rsp->u.info.pcap);
|
||||
if (*retval == FW_SUCCESS) {
|
||||
if (fw_caps == FW_CAPS16) {
|
||||
*pcaps = fwcaps16_to_caps32(ntohs(rsp->u.info.pcap));
|
||||
*acaps = fwcaps16_to_caps32(ntohs(rsp->u.info.acap));
|
||||
} else {
|
||||
*pcaps = ntohs(rsp->u.info32.pcaps32);
|
||||
*acaps = ntohs(rsp->u.info32.acaps32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1409,6 +1410,7 @@ csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd)
|
|||
uint32_t link_status;
|
||||
uint16_t action;
|
||||
uint8_t mod_type;
|
||||
fw_port_cap32_t linkattr;
|
||||
|
||||
if (opcode == FW_PORT_CMD) {
|
||||
pcmd = (struct fw_port_cmd *)cmd;
|
||||
|
@ -1416,22 +1418,34 @@ csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd)
|
|||
ntohl(pcmd->op_to_portid));
|
||||
action = FW_PORT_CMD_ACTION_G(
|
||||
ntohl(pcmd->action_to_len16));
|
||||
if (action != FW_PORT_ACTION_GET_PORT_INFO) {
|
||||
if (action != FW_PORT_ACTION_GET_PORT_INFO &&
|
||||
action != FW_PORT_ACTION_GET_PORT_INFO32) {
|
||||
csio_err(hw, "Unhandled FW_PORT_CMD action: %u\n",
|
||||
action);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (action == FW_PORT_ACTION_GET_PORT_INFO) {
|
||||
link_status = ntohl(pcmd->u.info.lstatus_to_modtype);
|
||||
mod_type = FW_PORT_CMD_MODTYPE_G(link_status);
|
||||
linkattr = lstatus_to_fwcap(link_status);
|
||||
|
||||
hw->pport[port_id].link_status =
|
||||
FW_PORT_CMD_LSTATUS_G(link_status);
|
||||
hw->pport[port_id].link_speed =
|
||||
FW_PORT_CMD_LSPEED_G(link_status);
|
||||
} else {
|
||||
link_status =
|
||||
ntohl(pcmd->u.info32.lstatus32_to_cbllen32);
|
||||
mod_type = FW_PORT_CMD_MODTYPE32_G(link_status);
|
||||
linkattr = ntohl(pcmd->u.info32.linkattr32);
|
||||
|
||||
hw->pport[port_id].link_status =
|
||||
FW_PORT_CMD_LSTATUS32_G(link_status);
|
||||
}
|
||||
|
||||
hw->pport[port_id].link_speed = fwcap_to_fwspeed(linkattr);
|
||||
|
||||
csio_info(hw, "Port:%x - LINK %s\n", port_id,
|
||||
FW_PORT_CMD_LSTATUS_G(link_status) ? "UP" : "DOWN");
|
||||
hw->pport[port_id].link_status ? "UP" : "DOWN");
|
||||
|
||||
if (mod_type != hw->pport[port_id].mod_type) {
|
||||
hw->pport[port_id].mod_type = mod_type;
|
||||
|
|
|
@ -88,12 +88,6 @@ enum csio_dev_state {
|
|||
FW_PARAMS_PARAM_Y_V(0) | \
|
||||
FW_PARAMS_PARAM_Z_V(0))
|
||||
|
||||
enum {
|
||||
PAUSE_RX = 1 << 0,
|
||||
PAUSE_TX = 1 << 1,
|
||||
PAUSE_AUTONEG = 1 << 2
|
||||
};
|
||||
|
||||
#define CSIO_INIT_MBP(__mbp, __cp, __tmo, __priv, __fn, __clear) \
|
||||
do { \
|
||||
if (__clear) \
|
||||
|
@ -189,7 +183,8 @@ void csio_mb_port(struct csio_hw *, struct csio_mb *, uint32_t,
|
|||
void (*) (struct csio_hw *, struct csio_mb *));
|
||||
|
||||
void csio_mb_process_read_port_rsp(struct csio_hw *, struct csio_mb *,
|
||||
enum fw_retval *, uint16_t *);
|
||||
enum fw_retval *, uint16_t,
|
||||
uint32_t *, uint32_t *);
|
||||
|
||||
void csio_mb_initialize(struct csio_hw *, struct csio_mb *, uint32_t,
|
||||
void (*)(struct csio_hw *, struct csio_mb *));
|
||||
|
|
|
@ -138,12 +138,12 @@ static void release_port_group(struct kref *kref)
|
|||
static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
|
||||
int bufflen, struct scsi_sense_hdr *sshdr, int flags)
|
||||
{
|
||||
u8 cdb[COMMAND_SIZE(MAINTENANCE_IN)];
|
||||
u8 cdb[MAX_COMMAND_SIZE];
|
||||
int req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
REQ_FAILFAST_DRIVER;
|
||||
|
||||
/* Prepare the command. */
|
||||
memset(cdb, 0x0, COMMAND_SIZE(MAINTENANCE_IN));
|
||||
memset(cdb, 0x0, MAX_COMMAND_SIZE);
|
||||
cdb[0] = MAINTENANCE_IN;
|
||||
if (!(flags & ALUA_RTPG_EXT_HDR_UNSUPP))
|
||||
cdb[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
|
||||
|
@ -166,7 +166,7 @@ static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
|
|||
static int submit_stpg(struct scsi_device *sdev, int group_id,
|
||||
struct scsi_sense_hdr *sshdr)
|
||||
{
|
||||
u8 cdb[COMMAND_SIZE(MAINTENANCE_OUT)];
|
||||
u8 cdb[MAX_COMMAND_SIZE];
|
||||
unsigned char stpg_data[8];
|
||||
int stpg_len = 8;
|
||||
int req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
|
@ -178,7 +178,7 @@ static int submit_stpg(struct scsi_device *sdev, int group_id,
|
|||
put_unaligned_be16(group_id, &stpg_data[6]);
|
||||
|
||||
/* Prepare the command. */
|
||||
memset(cdb, 0x0, COMMAND_SIZE(MAINTENANCE_OUT));
|
||||
memset(cdb, 0x0, MAX_COMMAND_SIZE);
|
||||
cdb[0] = MAINTENANCE_OUT;
|
||||
cdb[1] = MO_SET_TARGET_PGS;
|
||||
put_unaligned_be32(stpg_len, &cdb[6]);
|
||||
|
@ -214,8 +214,8 @@ static struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size,
|
|||
/*
|
||||
* alua_alloc_pg - Allocate a new port_group structure
|
||||
* @sdev: scsi device
|
||||
* @h: alua device_handler data
|
||||
* @group_id: port group id
|
||||
* @tpgs: target port group settings
|
||||
*
|
||||
* Allocate a new port_group structure for a given
|
||||
* device.
|
||||
|
|
|
@ -249,7 +249,7 @@ static int send_trespass_cmd(struct scsi_device *sdev,
|
|||
struct clariion_dh_data *csdev)
|
||||
{
|
||||
unsigned char *page22;
|
||||
unsigned char cdb[COMMAND_SIZE(MODE_SELECT)];
|
||||
unsigned char cdb[MAX_COMMAND_SIZE];
|
||||
int err, res = SCSI_DH_OK, len;
|
||||
struct scsi_sense_hdr sshdr;
|
||||
u64 req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
|
|
|
@ -533,7 +533,7 @@ static void send_mode_select(struct work_struct *work)
|
|||
int err = SCSI_DH_OK, retry_cnt = RDAC_RETRY_COUNT;
|
||||
struct rdac_queue_data *tmp, *qdata;
|
||||
LIST_HEAD(list);
|
||||
unsigned char cdb[COMMAND_SIZE(MODE_SELECT_10)];
|
||||
unsigned char cdb[MAX_COMMAND_SIZE];
|
||||
struct scsi_sense_hdr sshdr;
|
||||
unsigned int data_size;
|
||||
u64 req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
|
|
|
@ -302,16 +302,14 @@ rebuild_sys_tab:
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* scsi_unregister will be called AFTER we return.
|
||||
*/
|
||||
static int adpt_release(struct Scsi_Host *host)
|
||||
static void adpt_release(adpt_hba *pHba)
|
||||
{
|
||||
adpt_hba* pHba = (adpt_hba*) host->hostdata[0];
|
||||
struct Scsi_Host *shost = pHba->host;
|
||||
|
||||
scsi_remove_host(shost);
|
||||
// adpt_i2o_quiesce_hba(pHba);
|
||||
adpt_i2o_delete_hba(pHba);
|
||||
scsi_unregister(host);
|
||||
return 0;
|
||||
scsi_host_put(shost);
|
||||
}
|
||||
|
||||
|
||||
|
@ -801,14 +799,17 @@ static int __adpt_reset(struct scsi_cmnd* cmd)
|
|||
{
|
||||
adpt_hba* pHba;
|
||||
int rcode;
|
||||
char name[32];
|
||||
|
||||
pHba = (adpt_hba*)cmd->device->host->hostdata[0];
|
||||
printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n",pHba->name,cmd->device->channel,pHba->channel[cmd->device->channel].tid );
|
||||
strncpy(name, pHba->name, sizeof(name));
|
||||
printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n", name, cmd->device->channel, pHba->channel[cmd->device->channel].tid);
|
||||
rcode = adpt_hba_reset(pHba);
|
||||
if(rcode == 0){
|
||||
printk(KERN_WARNING"%s: HBA reset complete\n",pHba->name);
|
||||
printk(KERN_WARNING"%s: HBA reset complete\n", name);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
printk(KERN_WARNING"%s: HBA reset failed (%x)\n",pHba->name, rcode);
|
||||
printk(KERN_WARNING"%s: HBA reset failed (%x)\n", name, rcode);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
@ -1087,8 +1088,6 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
|
|||
|
||||
|
||||
mutex_lock(&adpt_configuration_lock);
|
||||
// scsi_unregister calls our adpt_release which
|
||||
// does a quiese
|
||||
if(pHba->host){
|
||||
free_irq(pHba->host->irq, pHba);
|
||||
}
|
||||
|
@ -3595,11 +3594,9 @@ static void __exit adpt_exit(void)
|
|||
{
|
||||
adpt_hba *pHba, *next;
|
||||
|
||||
for (pHba = hba_chain; pHba; pHba = pHba->next)
|
||||
scsi_remove_host(pHba->host);
|
||||
for (pHba = hba_chain; pHba; pHba = next) {
|
||||
next = pHba->next;
|
||||
adpt_release(pHba->host);
|
||||
adpt_release(pHba);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ static int adpt_detect(struct scsi_host_template * sht);
|
|||
static int adpt_queue(struct Scsi_Host *h, struct scsi_cmnd * cmd);
|
||||
static int adpt_abort(struct scsi_cmnd * cmd);
|
||||
static int adpt_reset(struct scsi_cmnd* cmd);
|
||||
static int adpt_release(struct Scsi_Host *host);
|
||||
static int adpt_slave_configure(struct scsi_device *);
|
||||
|
||||
static const char *adpt_info(struct Scsi_Host *pSHost);
|
||||
|
|
2571
drivers/scsi/eata.c
2571
drivers/scsi/eata.c
File diff suppressed because it is too large
Load diff
|
@ -1,401 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/********************************************************
|
||||
* Header file for eata_dma.c and eata_pio.c *
|
||||
* Linux EATA SCSI drivers *
|
||||
* (c) 1993-96 Michael Neuffer *
|
||||
* mike@i-Connect.Net *
|
||||
* neuffer@mail.uni-mainz.de *
|
||||
*********************************************************
|
||||
* last change: 96/08/14 *
|
||||
********************************************************/
|
||||
|
||||
|
||||
#ifndef _EATA_GENERIC_H
|
||||
#define _EATA_GENERIC_H
|
||||
|
||||
|
||||
|
||||
/*********************************************
|
||||
* Misc. definitions *
|
||||
*********************************************/
|
||||
|
||||
#define R_LIMIT 0x20000
|
||||
|
||||
#define MAXISA 4
|
||||
#define MAXEISA 16
|
||||
#define MAXPCI 16
|
||||
#define MAXIRQ 16
|
||||
#define MAXTARGET 16
|
||||
#define MAXCHANNEL 3
|
||||
|
||||
#define IS_ISA 'I'
|
||||
#define IS_EISA 'E'
|
||||
#define IS_PCI 'P'
|
||||
|
||||
#define BROKEN_INQUIRY 1
|
||||
|
||||
#define BUSMASTER 0xff
|
||||
#define PIO 0xfe
|
||||
|
||||
#define EATA_SIGNATURE 0x45415441 /* BIG ENDIAN coded "EATA" sig. */
|
||||
|
||||
#define DPT_ID1 0x12
|
||||
#define DPT_ID2 0x14
|
||||
|
||||
#define ATT_ID1 0x06
|
||||
#define ATT_ID2 0x94
|
||||
#define ATT_ID3 0x0
|
||||
|
||||
#define NEC_ID1 0x38
|
||||
#define NEC_ID2 0xa3
|
||||
#define NEC_ID3 0x82
|
||||
|
||||
|
||||
#define EATA_CP_SIZE 44
|
||||
|
||||
#define MAX_PCI_DEVICES 32 /* Maximum # Of Devices Per Bus */
|
||||
#define MAX_METHOD_2 16 /* Max Devices For Method 2 */
|
||||
#define MAX_PCI_BUS 16 /* Maximum # Of Busses Allowed */
|
||||
|
||||
#define SG_SIZE 64
|
||||
#define SG_SIZE_BIG 252 /* max. 8096 elements, 64k */
|
||||
|
||||
#define UPPER_DEVICE_QUEUE_LIMIT 64 /* The limit we have to set for the
|
||||
* device queue to keep the broken
|
||||
* midlevel SCSI code from producing
|
||||
* bogus timeouts
|
||||
*/
|
||||
|
||||
#define TYPE_DISK_QUEUE 16
|
||||
#define TYPE_TAPE_QUEUE 4
|
||||
#define TYPE_ROM_QUEUE 4
|
||||
#define TYPE_OTHER_QUEUE 2
|
||||
|
||||
#define FREE 0
|
||||
#define OK 0
|
||||
#define NO_TIMEOUT 0
|
||||
#define USED 1
|
||||
#define TIMEOUT 2
|
||||
#define RESET 4
|
||||
#define LOCKED 8
|
||||
#define ABORTED 16
|
||||
|
||||
#define READ 0
|
||||
#define WRITE 1
|
||||
#define OTHER 2
|
||||
|
||||
#define HD(cmd) ((hostdata *)&(cmd->device->host->hostdata))
|
||||
#define CD(cmd) ((struct eata_ccb *)(cmd->host_scribble))
|
||||
#define SD(host) ((hostdata *)&(host->hostdata))
|
||||
|
||||
/***********************************************
|
||||
* EATA Command & Register definitions *
|
||||
***********************************************/
|
||||
#define PCI_REG_DPTconfig 0x40
|
||||
#define PCI_REG_PumpModeAddress 0x44
|
||||
#define PCI_REG_PumpModeData 0x48
|
||||
#define PCI_REG_ConfigParam1 0x50
|
||||
#define PCI_REG_ConfigParam2 0x54
|
||||
|
||||
|
||||
#define EATA_CMD_PIO_SETUPTEST 0xc6
|
||||
#define EATA_CMD_PIO_READ_CONFIG 0xf0
|
||||
#define EATA_CMD_PIO_SET_CONFIG 0xf1
|
||||
#define EATA_CMD_PIO_SEND_CP 0xf2
|
||||
#define EATA_CMD_PIO_RECEIVE_SP 0xf3
|
||||
#define EATA_CMD_PIO_TRUNC 0xf4
|
||||
|
||||
#define EATA_CMD_RESET 0xf9
|
||||
#define EATA_CMD_IMMEDIATE 0xfa
|
||||
|
||||
#define EATA_CMD_DMA_READ_CONFIG 0xfd
|
||||
#define EATA_CMD_DMA_SET_CONFIG 0xfe
|
||||
#define EATA_CMD_DMA_SEND_CP 0xff
|
||||
|
||||
#define ECS_EMULATE_SENSE 0xd4
|
||||
|
||||
#define EATA_GENERIC_ABORT 0x00
|
||||
#define EATA_SPECIFIC_RESET 0x01
|
||||
#define EATA_BUS_RESET 0x02
|
||||
#define EATA_SPECIFIC_ABORT 0x03
|
||||
#define EATA_QUIET_INTR 0x04
|
||||
#define EATA_COLD_BOOT_HBA 0x06 /* Only as a last resort */
|
||||
#define EATA_FORCE_IO 0x07
|
||||
|
||||
#define HA_CTRLREG 0x206 /* control register for HBA */
|
||||
#define HA_CTRL_DISINT 0x02 /* CTRLREG: disable interrupts */
|
||||
#define HA_CTRL_RESCPU 0x04 /* CTRLREG: reset processor */
|
||||
#define HA_CTRL_8HEADS 0x08 /* CTRLREG: set for drives with*
|
||||
* >=8 heads (WD1003 rudimentary :-) */
|
||||
|
||||
#define HA_WCOMMAND 0x07 /* command register offset */
|
||||
#define HA_WIFC 0x06 /* immediate command offset */
|
||||
#define HA_WCODE 0x05
|
||||
#define HA_WCODE2 0x04
|
||||
#define HA_WDMAADDR 0x02 /* DMA address LSB offset */
|
||||
#define HA_RAUXSTAT 0x08 /* aux status register offset*/
|
||||
#define HA_RSTATUS 0x07 /* status register offset */
|
||||
#define HA_RDATA 0x00 /* data register (16bit) */
|
||||
#define HA_WDATA 0x00 /* data register (16bit) */
|
||||
|
||||
#define HA_ABUSY 0x01 /* aux busy bit */
|
||||
#define HA_AIRQ 0x02 /* aux IRQ pending bit */
|
||||
#define HA_SERROR 0x01 /* pr. command ended in error*/
|
||||
#define HA_SMORE 0x02 /* more data soon to come */
|
||||
#define HA_SCORR 0x04 /* data corrected */
|
||||
#define HA_SDRQ 0x08 /* data request active */
|
||||
#define HA_SSC 0x10 /* seek complete */
|
||||
#define HA_SFAULT 0x20 /* write fault */
|
||||
#define HA_SREADY 0x40 /* drive ready */
|
||||
#define HA_SBUSY 0x80 /* drive busy */
|
||||
#define HA_SDRDY HA_SSC+HA_SREADY+HA_SDRQ
|
||||
|
||||
/**********************************************
|
||||
* Message definitions *
|
||||
**********************************************/
|
||||
|
||||
#define HA_NO_ERROR 0x00 /* No Error */
|
||||
#define HA_ERR_SEL_TO 0x01 /* Selection Timeout */
|
||||
#define HA_ERR_CMD_TO 0x02 /* Command Timeout */
|
||||
#define HA_BUS_RESET 0x03 /* SCSI Bus Reset Received */
|
||||
#define HA_INIT_POWERUP 0x04 /* Initial Controller Power-up */
|
||||
#define HA_UNX_BUSPHASE 0x05 /* Unexpected Bus Phase */
|
||||
#define HA_UNX_BUS_FREE 0x06 /* Unexpected Bus Free */
|
||||
#define HA_BUS_PARITY 0x07 /* Bus Parity Error */
|
||||
#define HA_SCSI_HUNG 0x08 /* SCSI Hung */
|
||||
#define HA_UNX_MSGRJCT 0x09 /* Unexpected Message Rejected */
|
||||
#define HA_RESET_STUCK 0x0a /* SCSI Bus Reset Stuck */
|
||||
#define HA_RSENSE_FAIL 0x0b /* Auto Request-Sense Failed */
|
||||
#define HA_PARITY_ERR 0x0c /* Controller Ram Parity Error */
|
||||
#define HA_CP_ABORT_NA 0x0d /* Abort Message sent to non-active cmd */
|
||||
#define HA_CP_ABORTED 0x0e /* Abort Message sent to active cmd */
|
||||
#define HA_CP_RESET_NA 0x0f /* Reset Message sent to non-active cmd */
|
||||
#define HA_CP_RESET 0x10 /* Reset Message sent to active cmd */
|
||||
#define HA_ECC_ERR 0x11 /* Controller Ram ECC Error */
|
||||
#define HA_PCI_PARITY 0x12 /* PCI Parity Error */
|
||||
#define HA_PCI_MABORT 0x13 /* PCI Master Abort */
|
||||
#define HA_PCI_TABORT 0x14 /* PCI Target Abort */
|
||||
#define HA_PCI_STABORT 0x15 /* PCI Signaled Target Abort */
|
||||
|
||||
/**********************************************
|
||||
* Other definitions *
|
||||
**********************************************/
|
||||
|
||||
struct reg_bit { /* reading this one will clear the interrupt */
|
||||
__u8 error:1; /* previous command ended in an error */
|
||||
__u8 more:1; /* more DATA coming soon, poll BSY & DRQ (PIO) */
|
||||
__u8 corr:1; /* data read was successfully corrected with ECC*/
|
||||
__u8 drq:1; /* data request active */
|
||||
__u8 sc:1; /* seek complete */
|
||||
__u8 fault:1; /* write fault */
|
||||
__u8 ready:1; /* drive ready */
|
||||
__u8 busy:1; /* controller busy */
|
||||
};
|
||||
|
||||
struct reg_abit { /* reading this won't clear the interrupt */
|
||||
__u8 abusy:1; /* auxiliary busy */
|
||||
__u8 irq:1; /* set when drive interrupt is asserted */
|
||||
__u8 dummy:6;
|
||||
};
|
||||
|
||||
struct eata_register { /* EATA register set */
|
||||
__u8 data_reg[2]; /* R, couldn't figure this one out */
|
||||
__u8 cp_addr[4]; /* W, CP address register */
|
||||
union {
|
||||
__u8 command; /* W, command code: [read|set] conf, send CP*/
|
||||
struct reg_bit status; /* R, see register_bit1 */
|
||||
__u8 statusbyte;
|
||||
} ovr;
|
||||
struct reg_abit aux_stat; /* R, see register_bit2 */
|
||||
};
|
||||
|
||||
struct get_conf { /* Read Configuration Array */
|
||||
__u32 len; /* Should return 0x22, 0x24, etc */
|
||||
__u32 signature; /* Signature MUST be "EATA" */
|
||||
__u8 version2:4,
|
||||
version:4; /* EATA Version level */
|
||||
__u8 OCS_enabled:1, /* Overlap Command Support enabled */
|
||||
TAR_support:1, /* SCSI Target Mode supported */
|
||||
TRNXFR:1, /* Truncate Transfer Cmd not necessary *
|
||||
* Only used in PIO Mode */
|
||||
MORE_support:1, /* MORE supported (only PIO Mode) */
|
||||
DMA_support:1, /* DMA supported Driver uses only *
|
||||
* this mode */
|
||||
DMA_valid:1, /* DRQ value in Byte 30 is valid */
|
||||
ATA:1, /* ATA device connected (not supported) */
|
||||
HAA_valid:1; /* Hostadapter Address is valid */
|
||||
|
||||
__u16 cppadlen; /* Number of pad bytes send after CD data *
|
||||
* set to zero for DMA commands */
|
||||
__u8 scsi_id[4]; /* SCSI ID of controller 2-0 Byte 0 res. *
|
||||
* if not, zero is returned */
|
||||
__u32 cplen; /* CP length: number of valid cp bytes */
|
||||
__u32 splen; /* Number of bytes returned after *
|
||||
* Receive SP command */
|
||||
__u16 queuesiz; /* max number of queueable CPs */
|
||||
__u16 dummy;
|
||||
__u16 SGsiz; /* max number of SG table entries */
|
||||
__u8 IRQ:4, /* IRQ used this HA */
|
||||
IRQ_TR:1, /* IRQ Trigger: 0=edge, 1=level */
|
||||
SECOND:1, /* This is a secondary controller */
|
||||
DMA_channel:2; /* DRQ index, DRQ is 2comp of DRQX */
|
||||
__u8 sync; /* device at ID 7 tru 0 is running in *
|
||||
* synchronous mode, this will disappear */
|
||||
__u8 DSBLE:1, /* ISA i/o addressing is disabled */
|
||||
FORCADR:1, /* i/o address has been forced */
|
||||
SG_64K:1,
|
||||
SG_UAE:1,
|
||||
:4;
|
||||
__u8 MAX_ID:5, /* Max number of SCSI target IDs */
|
||||
MAX_CHAN:3; /* Number of SCSI busses on HBA */
|
||||
__u8 MAX_LUN; /* Max number of LUNs */
|
||||
__u8 :3,
|
||||
AUTOTRM:1,
|
||||
M1_inst:1,
|
||||
ID_qest:1, /* Raidnum ID is questionable */
|
||||
is_PCI:1, /* HBA is PCI */
|
||||
is_EISA:1; /* HBA is EISA */
|
||||
__u8 RAIDNUM; /* unique HBA identifier */
|
||||
__u8 unused[474];
|
||||
};
|
||||
|
||||
struct eata_sg_list
|
||||
{
|
||||
__u32 data;
|
||||
__u32 len;
|
||||
};
|
||||
|
||||
struct eata_ccb { /* Send Command Packet structure */
|
||||
|
||||
__u8 SCSI_Reset:1, /* Cause a SCSI Bus reset on the cmd */
|
||||
HBA_Init:1, /* Cause Controller to reinitialize */
|
||||
Auto_Req_Sen:1, /* Do Auto Request Sense on errors */
|
||||
scatter:1, /* Data Ptr points to a SG Packet */
|
||||
Resrvd:1, /* RFU */
|
||||
Interpret:1, /* Interpret the SCSI cdb of own use */
|
||||
DataOut:1, /* Data Out phase with command */
|
||||
DataIn:1; /* Data In phase with command */
|
||||
__u8 reqlen; /* Request Sense Length *
|
||||
* Valid if Auto_Req_Sen=1 */
|
||||
__u8 unused[3];
|
||||
__u8 FWNEST:1, /* send cmd to phys RAID component */
|
||||
unused2:7;
|
||||
__u8 Phsunit:1, /* physical unit on mirrored pair */
|
||||
I_AT:1, /* inhibit address translation */
|
||||
I_HBA_C:1, /* HBA inhibit caching */
|
||||
unused3:5;
|
||||
|
||||
__u8 cp_id:5, /* SCSI Device ID of target */
|
||||
cp_channel:3; /* SCSI Channel # of HBA */
|
||||
__u8 cp_lun:3,
|
||||
:2,
|
||||
cp_luntar:1, /* CP is for target ROUTINE */
|
||||
cp_dispri:1, /* Grant disconnect privilege */
|
||||
cp_identify:1; /* Always TRUE */
|
||||
__u8 cp_msg1; /* Message bytes 0-3 */
|
||||
__u8 cp_msg2;
|
||||
__u8 cp_msg3;
|
||||
__u8 cp_cdb[12]; /* Command Descriptor Block */
|
||||
__u32 cp_datalen; /* Data Transfer Length *
|
||||
* If scatter=1 len of sg package */
|
||||
void *cp_viraddr; /* address of this ccb */
|
||||
__u32 cp_dataDMA; /* Data Address, if scatter=1 *
|
||||
* address of scatter packet */
|
||||
__u32 cp_statDMA; /* address for Status Packet */
|
||||
__u32 cp_reqDMA; /* Request Sense Address, used if *
|
||||
* CP command ends with error */
|
||||
/* Additional CP info begins here */
|
||||
__u32 timestamp; /* Needed to measure command latency */
|
||||
__u32 timeout;
|
||||
__u8 sizeindex;
|
||||
__u8 rw_latency;
|
||||
__u8 retries;
|
||||
__u8 status; /* status of this queueslot */
|
||||
struct scsi_cmnd *cmd; /* address of cmd */
|
||||
struct eata_sg_list *sg_list;
|
||||
};
|
||||
|
||||
|
||||
struct eata_sp {
|
||||
__u8 hba_stat:7, /* HBA status */
|
||||
EOC:1; /* True if command finished */
|
||||
__u8 scsi_stat; /* Target SCSI status */
|
||||
__u8 reserved[2];
|
||||
__u32 residue_len; /* Number of bytes not transferred */
|
||||
struct eata_ccb *ccb; /* Address set in COMMAND PACKET */
|
||||
__u8 msg[12];
|
||||
};
|
||||
|
||||
typedef struct hstd {
|
||||
__u8 vendor[9];
|
||||
__u8 name[18];
|
||||
__u8 revision[6];
|
||||
__u8 EATA_revision;
|
||||
__u32 firmware_revision;
|
||||
__u8 HBA_number;
|
||||
__u8 bustype; /* bustype of HBA */
|
||||
__u8 channel; /* # of avail. scsi channels */
|
||||
__u8 state; /* state of HBA */
|
||||
__u8 primary; /* true if primary */
|
||||
__u8 more_support:1, /* HBA supports MORE flag */
|
||||
immediate_support:1, /* HBA supports IMMEDIATE CMDs*/
|
||||
broken_INQUIRY:1; /* This is an EISA HBA with *
|
||||
* broken INQUIRY */
|
||||
__u8 do_latency; /* Latency measurement flag */
|
||||
__u32 reads[13];
|
||||
__u32 writes[13];
|
||||
__u32 reads_lat[12][4];
|
||||
__u32 writes_lat[12][4];
|
||||
__u32 all_lat[4];
|
||||
__u8 resetlevel[MAXCHANNEL];
|
||||
__u32 last_ccb; /* Last used ccb */
|
||||
__u32 cplen; /* size of CP in words */
|
||||
__u16 cppadlen; /* pad length of cp in words */
|
||||
__u16 queuesize;
|
||||
__u16 sgsize; /* # of entries in the SG list*/
|
||||
__u16 devflags; /* bits set for detected devices */
|
||||
__u8 hostid; /* SCSI ID of HBA */
|
||||
__u8 moresupport; /* HBA supports MORE flag */
|
||||
struct Scsi_Host *next;
|
||||
struct Scsi_Host *prev;
|
||||
struct pci_dev *pdev; /* PCI device or NULL for non PCI */
|
||||
struct eata_sp sp; /* status packet */
|
||||
struct eata_ccb ccb[0]; /* ccb array begins here */
|
||||
}hostdata;
|
||||
|
||||
/* structure for max. 2 emulated drives */
|
||||
struct drive_geom_emul {
|
||||
__u8 trans; /* translation flag 1=transl */
|
||||
__u8 channel; /* SCSI channel number */
|
||||
__u8 HBA; /* HBA number (prim/sec) */
|
||||
__u8 id; /* drive id */
|
||||
__u8 lun; /* drive lun */
|
||||
__u32 heads; /* number of heads */
|
||||
__u32 sectors; /* number of sectors */
|
||||
__u32 cylinder; /* number of cylinders */
|
||||
};
|
||||
|
||||
struct geom_emul {
|
||||
__u8 bios_drives; /* number of emulated drives */
|
||||
struct drive_geom_emul drv[2]; /* drive structures */
|
||||
};
|
||||
|
||||
#endif /* _EATA_GENERIC_H */
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we almost follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-indent-level: 4
|
||||
* c-brace-imaginary-offset: 0
|
||||
* c-brace-offset: -4
|
||||
* c-argdecl-indent: 4
|
||||
* c-label-offset: -4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: 0
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
|
@ -1,966 +0,0 @@
|
|||
/************************************************************
|
||||
* *
|
||||
* Linux EATA SCSI PIO driver *
|
||||
* *
|
||||
* based on the CAM document CAM/89-004 rev. 2.0c, *
|
||||
* DPT's driver kit, some internal documents and source, *
|
||||
* and several other Linux scsi drivers and kernel docs. *
|
||||
* *
|
||||
* The driver currently: *
|
||||
* -supports all EATA-PIO boards *
|
||||
* -only supports DASD devices *
|
||||
* *
|
||||
* (c)1993-96 Michael Neuffer, Alfred Arnold *
|
||||
* neuffer@goofy.zdv.uni-mainz.de *
|
||||
* a.arnold@kfa-juelich.de *
|
||||
* *
|
||||
* Updated 2002 by Alan Cox <alan@lxorguk.ukuu.org.uk> for *
|
||||
* Linux 2.5.x and the newer locking and error handling *
|
||||
* *
|
||||
* This program is free software; you can redistribute it *
|
||||
* and/or modify it under the terms of the GNU General *
|
||||
* Public License as published by the Free Software *
|
||||
* Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be *
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the *
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE. See the GNU General Public License *
|
||||
* for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General *
|
||||
* Public License along with this kernel; if not, write to *
|
||||
* the Free Software Foundation, Inc., 675 Mass Ave, *
|
||||
* Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
* For the avoidance of doubt the "preferred form" of this *
|
||||
* code is one which is in an open non patent encumbered *
|
||||
* format. Where cryptographic key signing forms part of *
|
||||
* the process of creating an executable the information *
|
||||
* including keys needed to generate an equivalently *
|
||||
* functional executable are deemed to be part of the *
|
||||
* source code are deemed to be part of the source code. *
|
||||
* *
|
||||
************************************************************
|
||||
* last change: 2002/11/02 OS: Linux 2.5.45 *
|
||||
************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#include "eata_generic.h"
|
||||
#include "eata_pio.h"
|
||||
|
||||
|
||||
static unsigned int ISAbases[MAXISA] = {
|
||||
0x1F0, 0x170, 0x330, 0x230
|
||||
};
|
||||
|
||||
static unsigned int ISAirqs[MAXISA] = {
|
||||
14, 12, 15, 11
|
||||
};
|
||||
|
||||
static unsigned char EISAbases[] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1
|
||||
};
|
||||
|
||||
static unsigned int registered_HBAs;
|
||||
static struct Scsi_Host *last_HBA;
|
||||
static struct Scsi_Host *first_HBA;
|
||||
static unsigned char reg_IRQ[16];
|
||||
static unsigned char reg_IRQL[16];
|
||||
static unsigned long int_counter;
|
||||
static unsigned long queue_counter;
|
||||
|
||||
static struct scsi_host_template driver_template;
|
||||
|
||||
static int eata_pio_show_info(struct seq_file *m, struct Scsi_Host *shost)
|
||||
{
|
||||
seq_printf(m, "EATA (Extended Attachment) PIO driver version: "
|
||||
"%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB);
|
||||
seq_printf(m, "queued commands: %10ld\n"
|
||||
"processed interrupts:%10ld\n", queue_counter, int_counter);
|
||||
seq_printf(m, "\nscsi%-2d: HBA %.10s\n",
|
||||
shost->host_no, SD(shost)->name);
|
||||
seq_printf(m, "Firmware revision: v%s\n",
|
||||
SD(shost)->revision);
|
||||
seq_puts(m, "IO: PIO\n");
|
||||
seq_printf(m, "Base IO : %#.4x\n", (u32) shost->base);
|
||||
seq_printf(m, "Host Bus: %s\n",
|
||||
(SD(shost)->bustype == 'P')?"PCI ":
|
||||
(SD(shost)->bustype == 'E')?"EISA":"ISA ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eata_pio_release(struct Scsi_Host *sh)
|
||||
{
|
||||
hostdata *hd = SD(sh);
|
||||
if (sh->irq && reg_IRQ[sh->irq] == 1)
|
||||
free_irq(sh->irq, NULL);
|
||||
else
|
||||
reg_IRQ[sh->irq]--;
|
||||
if (SD(sh)->channel == 0) {
|
||||
if (sh->io_port && sh->n_io_port)
|
||||
release_region(sh->io_port, sh->n_io_port);
|
||||
}
|
||||
/* At this point the PCI reference can go */
|
||||
if (hd->pdev)
|
||||
pci_dev_put(hd->pdev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void IncStat(struct scsi_pointer *SCp, unsigned int Increment)
|
||||
{
|
||||
SCp->ptr += Increment;
|
||||
if ((SCp->this_residual -= Increment) == 0) {
|
||||
if ((--SCp->buffers_residual) == 0)
|
||||
SCp->Status = 0;
|
||||
else {
|
||||
SCp->buffer++;
|
||||
SCp->ptr = sg_virt(SCp->buffer);
|
||||
SCp->this_residual = SCp->buffer->length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t eata_pio_int_handler(int irq, void *dev_id);
|
||||
|
||||
static irqreturn_t do_eata_pio_int_handler(int irq, void *dev_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct Scsi_Host *dev = dev_id;
|
||||
irqreturn_t ret;
|
||||
|
||||
spin_lock_irqsave(dev->host_lock, flags);
|
||||
ret = eata_pio_int_handler(irq, dev_id);
|
||||
spin_unlock_irqrestore(dev->host_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t eata_pio_int_handler(int irq, void *dev_id)
|
||||
{
|
||||
unsigned int eata_stat = 0xfffff;
|
||||
struct scsi_cmnd *cmd;
|
||||
hostdata *hd;
|
||||
struct eata_ccb *cp;
|
||||
unsigned long base;
|
||||
unsigned int x, z;
|
||||
struct Scsi_Host *sh;
|
||||
unsigned short zwickel = 0;
|
||||
unsigned char stat, odd;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev)
|
||||
{
|
||||
if (sh->irq != irq)
|
||||
continue;
|
||||
if (inb(sh->base + HA_RSTATUS) & HA_SBUSY)
|
||||
continue;
|
||||
|
||||
int_counter++;
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
hd = SD(sh);
|
||||
|
||||
cp = &hd->ccb[0];
|
||||
cmd = cp->cmd;
|
||||
base = cmd->device->host->base;
|
||||
|
||||
do {
|
||||
stat = inb(base + HA_RSTATUS);
|
||||
if (stat & HA_SDRQ) {
|
||||
if (cp->DataIn) {
|
||||
z = 256;
|
||||
odd = 0;
|
||||
while ((cmd->SCp.Status) && ((z > 0) || (odd))) {
|
||||
if (odd) {
|
||||
*(cmd->SCp.ptr) = zwickel >> 8;
|
||||
IncStat(&cmd->SCp, 1);
|
||||
odd = 0;
|
||||
}
|
||||
x = min_t(unsigned int, z, cmd->SCp.this_residual / 2);
|
||||
insw(base + HA_RDATA, cmd->SCp.ptr, x);
|
||||
z -= x;
|
||||
IncStat(&cmd->SCp, 2 * x);
|
||||
if ((z > 0) && (cmd->SCp.this_residual == 1)) {
|
||||
zwickel = inw(base + HA_RDATA);
|
||||
*(cmd->SCp.ptr) = zwickel & 0xff;
|
||||
IncStat(&cmd->SCp, 1);
|
||||
z--;
|
||||
odd = 1;
|
||||
}
|
||||
}
|
||||
while (z > 0) {
|
||||
zwickel = inw(base + HA_RDATA);
|
||||
z--;
|
||||
}
|
||||
} else { /* cp->DataOut */
|
||||
|
||||
odd = 0;
|
||||
z = 256;
|
||||
while ((cmd->SCp.Status) && ((z > 0) || (odd))) {
|
||||
if (odd) {
|
||||
zwickel += *(cmd->SCp.ptr) << 8;
|
||||
IncStat(&cmd->SCp, 1);
|
||||
outw(zwickel, base + HA_RDATA);
|
||||
z--;
|
||||
odd = 0;
|
||||
}
|
||||
x = min_t(unsigned int, z, cmd->SCp.this_residual / 2);
|
||||
outsw(base + HA_RDATA, cmd->SCp.ptr, x);
|
||||
z -= x;
|
||||
IncStat(&cmd->SCp, 2 * x);
|
||||
if ((z > 0) && (cmd->SCp.this_residual == 1)) {
|
||||
zwickel = *(cmd->SCp.ptr);
|
||||
zwickel &= 0xff;
|
||||
IncStat(&cmd->SCp, 1);
|
||||
odd = 1;
|
||||
}
|
||||
}
|
||||
while (z > 0 || odd) {
|
||||
outw(zwickel, base + HA_RDATA);
|
||||
z--;
|
||||
odd = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while ((stat & HA_SDRQ) || ((stat & HA_SMORE) && hd->moresupport));
|
||||
|
||||
/* terminate handler if HBA goes busy again, i.e. transfers
|
||||
* more data */
|
||||
|
||||
if (stat & HA_SBUSY)
|
||||
break;
|
||||
|
||||
/* OK, this is quite stupid, but I haven't found any correct
|
||||
* way to get HBA&SCSI status so far */
|
||||
|
||||
if (!(inb(base + HA_RSTATUS) & HA_SERROR)) {
|
||||
cmd->result = (DID_OK << 16);
|
||||
hd->devflags |= (1 << cp->cp_id);
|
||||
} else if (hd->devflags & (1 << cp->cp_id))
|
||||
cmd->result = (DID_OK << 16) + 0x02;
|
||||
else
|
||||
cmd->result = (DID_NO_CONNECT << 16);
|
||||
|
||||
if (cp->status == LOCKED) {
|
||||
cp->status = FREE;
|
||||
eata_stat = inb(base + HA_RSTATUS);
|
||||
printk(KERN_CRIT "eata_pio: int_handler, freeing locked " "queueslot\n");
|
||||
return ret;
|
||||
}
|
||||
#if DBG_INTR2
|
||||
if (stat != 0x50)
|
||||
printk(KERN_DEBUG "stat: %#.2x, result: %#.8x\n", stat, cmd->result);
|
||||
#endif
|
||||
|
||||
cp->status = FREE; /* now we can release the slot */
|
||||
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned int eata_pio_send_command(unsigned long base, unsigned char command)
|
||||
{
|
||||
unsigned int loop = 50;
|
||||
|
||||
while (inb(base + HA_RSTATUS) & HA_SBUSY)
|
||||
if (--loop == 0)
|
||||
return 1;
|
||||
|
||||
/* Enable interrupts for HBA. It is not the best way to do it at this
|
||||
* place, but I hope that it doesn't interfere with the IDE driver
|
||||
* initialization this way */
|
||||
|
||||
outb(HA_CTRL_8HEADS, base + HA_CTRLREG);
|
||||
|
||||
outb(command, base + HA_WCOMMAND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eata_pio_queue_lck(struct scsi_cmnd *cmd,
|
||||
void (*done)(struct scsi_cmnd *))
|
||||
{
|
||||
unsigned int x, y;
|
||||
unsigned long base;
|
||||
|
||||
hostdata *hd;
|
||||
struct Scsi_Host *sh;
|
||||
struct eata_ccb *cp;
|
||||
|
||||
queue_counter++;
|
||||
|
||||
hd = HD(cmd);
|
||||
sh = cmd->device->host;
|
||||
base = sh->base;
|
||||
|
||||
/* use only slot 0, as 2001 can handle only one cmd at a time */
|
||||
|
||||
y = x = 0;
|
||||
|
||||
if (hd->ccb[y].status != FREE) {
|
||||
|
||||
DBG(DBG_QUEUE, printk(KERN_EMERG "can_queue %d, x %d, y %d\n", sh->can_queue, x, y));
|
||||
#if DEBUG_EATA
|
||||
panic(KERN_EMERG "eata_pio: run out of queue slots cmdno:%ld " "intrno: %ld\n", queue_counter, int_counter);
|
||||
#else
|
||||
panic(KERN_EMERG "eata_pio: run out of queue slots....\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
cp = &hd->ccb[y];
|
||||
|
||||
memset(cp, 0, sizeof(struct eata_ccb));
|
||||
|
||||
cp->status = USED; /* claim free slot */
|
||||
|
||||
DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd,
|
||||
"eata_pio_queue 0x%p, y %d\n", cmd, y));
|
||||
|
||||
cmd->scsi_done = (void *) done;
|
||||
|
||||
if (cmd->sc_data_direction == DMA_TO_DEVICE)
|
||||
cp->DataOut = 1; /* Output mode */
|
||||
else
|
||||
cp->DataIn = 0; /* Input mode */
|
||||
|
||||
cp->Interpret = (cmd->device->id == hd->hostid);
|
||||
cp->cp_datalen = cpu_to_be32(scsi_bufflen(cmd));
|
||||
cp->Auto_Req_Sen = 0;
|
||||
cp->cp_reqDMA = 0;
|
||||
cp->reqlen = 0;
|
||||
|
||||
cp->cp_id = cmd->device->id;
|
||||
cp->cp_lun = cmd->device->lun;
|
||||
cp->cp_dispri = 0;
|
||||
cp->cp_identify = 1;
|
||||
memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
|
||||
|
||||
cp->cp_statDMA = 0;
|
||||
|
||||
cp->cp_viraddr = cp;
|
||||
cp->cmd = cmd;
|
||||
cmd->host_scribble = (char *) &hd->ccb[y];
|
||||
|
||||
if (!scsi_bufflen(cmd)) {
|
||||
cmd->SCp.buffers_residual = 1;
|
||||
cmd->SCp.ptr = NULL;
|
||||
cmd->SCp.this_residual = 0;
|
||||
cmd->SCp.buffer = NULL;
|
||||
} else {
|
||||
cmd->SCp.buffer = scsi_sglist(cmd);
|
||||
cmd->SCp.buffers_residual = scsi_sg_count(cmd);
|
||||
cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
|
||||
cmd->SCp.this_residual = cmd->SCp.buffer->length;
|
||||
}
|
||||
cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes
|
||||
* are to transfer */
|
||||
|
||||
if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) {
|
||||
cmd->result = DID_BUS_BUSY << 16;
|
||||
scmd_printk(KERN_NOTICE, cmd,
|
||||
"eata_pio_queue pid 0x%p, HBA busy, "
|
||||
"returning DID_BUS_BUSY, done.\n", cmd);
|
||||
done(cmd);
|
||||
cp->status = FREE;
|
||||
return 0;
|
||||
}
|
||||
/* FIXME: timeout */
|
||||
while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
|
||||
cpu_relax();
|
||||
outsw(base + HA_RDATA, cp, hd->cplen);
|
||||
outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
|
||||
for (x = 0; x < hd->cppadlen; x++)
|
||||
outw(0, base + HA_RDATA);
|
||||
|
||||
DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd,
|
||||
"Queued base %#.4lx cmd: 0x%p "
|
||||
"slot %d irq %d\n", sh->base, cmd, y, sh->irq));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEF_SCSI_QCMD(eata_pio_queue)
|
||||
|
||||
static int eata_pio_abort(struct scsi_cmnd *cmd)
|
||||
{
|
||||
unsigned int loop = 100;
|
||||
|
||||
DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd,
|
||||
"eata_pio_abort called pid: 0x%p\n", cmd));
|
||||
|
||||
while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY)
|
||||
if (--loop == 0) {
|
||||
printk(KERN_WARNING "eata_pio: abort, timeout error.\n");
|
||||
return FAILED;
|
||||
}
|
||||
if (CD(cmd)->status == FREE) {
|
||||
DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_NOT_RUNNING\n"));
|
||||
return FAILED;
|
||||
}
|
||||
if (CD(cmd)->status == USED) {
|
||||
DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_BUSY\n"));
|
||||
/* We want to sleep a bit more here */
|
||||
return FAILED; /* SNOOZE */
|
||||
}
|
||||
if (CD(cmd)->status == RESET) {
|
||||
printk(KERN_WARNING "eata_pio: abort, command reset error.\n");
|
||||
return FAILED;
|
||||
}
|
||||
if (CD(cmd)->status == LOCKED) {
|
||||
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio: abort, queue slot " "locked.\n"));
|
||||
return FAILED;
|
||||
}
|
||||
panic("eata_pio: abort: invalid slot status\n");
|
||||
}
|
||||
|
||||
static int eata_pio_host_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
unsigned int x, limit = 0;
|
||||
unsigned char success = 0;
|
||||
struct scsi_cmnd *sp;
|
||||
struct Scsi_Host *host = cmd->device->host;
|
||||
|
||||
DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd,
|
||||
"eata_pio_reset called\n"));
|
||||
|
||||
spin_lock_irq(host->host_lock);
|
||||
|
||||
if (HD(cmd)->state == RESET) {
|
||||
printk(KERN_WARNING "eata_pio_reset: exit, already in reset.\n");
|
||||
spin_unlock_irq(host->host_lock);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* force all slots to be free */
|
||||
|
||||
for (x = 0; x < cmd->device->host->can_queue; x++) {
|
||||
|
||||
if (HD(cmd)->ccb[x].status == FREE)
|
||||
continue;
|
||||
|
||||
sp = HD(cmd)->ccb[x].cmd;
|
||||
HD(cmd)->ccb[x].status = RESET;
|
||||
printk(KERN_WARNING "eata_pio_reset: slot %d in reset.\n", x);
|
||||
|
||||
if (sp == NULL)
|
||||
panic("eata_pio_reset: slot %d, sp==NULL.\n", x);
|
||||
}
|
||||
|
||||
/* hard reset the HBA */
|
||||
outb(EATA_CMD_RESET, cmd->device->host->base + HA_WCOMMAND);
|
||||
|
||||
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: board reset done.\n"));
|
||||
HD(cmd)->state = RESET;
|
||||
|
||||
spin_unlock_irq(host->host_lock);
|
||||
msleep(3000);
|
||||
spin_lock_irq(host->host_lock);
|
||||
|
||||
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " "loops %d.\n", limit));
|
||||
|
||||
for (x = 0; x < cmd->device->host->can_queue; x++) {
|
||||
|
||||
/* Skip slots already set free by interrupt */
|
||||
if (HD(cmd)->ccb[x].status != RESET)
|
||||
continue;
|
||||
|
||||
sp = HD(cmd)->ccb[x].cmd;
|
||||
sp->result = DID_RESET << 16;
|
||||
|
||||
/* This mailbox is terminated */
|
||||
printk(KERN_WARNING "eata_pio_reset: reset ccb %d.\n", x);
|
||||
HD(cmd)->ccb[x].status = FREE;
|
||||
|
||||
sp->scsi_done(sp);
|
||||
}
|
||||
|
||||
HD(cmd)->state = 0;
|
||||
|
||||
spin_unlock_irq(host->host_lock);
|
||||
|
||||
if (success) { /* hmmm... */
|
||||
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n"));
|
||||
return SUCCESS;
|
||||
} else {
|
||||
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, wakeup.\n"));
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static char *get_pio_board_data(unsigned long base, unsigned int irq, unsigned int id, unsigned long cplen, unsigned short cppadlen)
|
||||
{
|
||||
struct eata_ccb cp;
|
||||
static char buff[256];
|
||||
int z;
|
||||
|
||||
memset(&cp, 0, sizeof(struct eata_ccb));
|
||||
memset(buff, 0, sizeof(buff));
|
||||
|
||||
cp.DataIn = 1;
|
||||
cp.Interpret = 1; /* Interpret command */
|
||||
|
||||
cp.cp_datalen = cpu_to_be32(254);
|
||||
cp.cp_dataDMA = cpu_to_be32(0);
|
||||
|
||||
cp.cp_id = id;
|
||||
cp.cp_lun = 0;
|
||||
|
||||
cp.cp_cdb[0] = INQUIRY;
|
||||
cp.cp_cdb[1] = 0;
|
||||
cp.cp_cdb[2] = 0;
|
||||
cp.cp_cdb[3] = 0;
|
||||
cp.cp_cdb[4] = 254;
|
||||
cp.cp_cdb[5] = 0;
|
||||
|
||||
if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP))
|
||||
return NULL;
|
||||
|
||||
while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
|
||||
cpu_relax();
|
||||
|
||||
outsw(base + HA_RDATA, &cp, cplen);
|
||||
outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
|
||||
for (z = 0; z < cppadlen; z++)
|
||||
outw(0, base + HA_RDATA);
|
||||
|
||||
while (inb(base + HA_RSTATUS) & HA_SBUSY)
|
||||
cpu_relax();
|
||||
|
||||
if (inb(base + HA_RSTATUS) & HA_SERROR)
|
||||
return NULL;
|
||||
else if (!(inb(base + HA_RSTATUS) & HA_SDRQ))
|
||||
return NULL;
|
||||
else {
|
||||
insw(base + HA_RDATA, &buff, 127);
|
||||
while (inb(base + HA_RSTATUS) & HA_SDRQ)
|
||||
inw(base + HA_RDATA);
|
||||
return buff;
|
||||
}
|
||||
}
|
||||
|
||||
static int get_pio_conf_PIO(unsigned long base, struct get_conf *buf)
|
||||
{
|
||||
unsigned long loop = HZ / 2;
|
||||
int z;
|
||||
unsigned short *p;
|
||||
|
||||
if (!request_region(base, 9, "eata_pio"))
|
||||
return 0;
|
||||
|
||||
memset(buf, 0, sizeof(struct get_conf));
|
||||
|
||||
while (inb(base + HA_RSTATUS) & HA_SBUSY)
|
||||
if (--loop == 0)
|
||||
goto fail;
|
||||
|
||||
DBG(DBG_PIO && DBG_PROBE, printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#lx\n", base));
|
||||
eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG);
|
||||
|
||||
loop = 50;
|
||||
for (p = (unsigned short *) buf; (long) p <= ((long) buf + (sizeof(struct get_conf) / 2)); p++) {
|
||||
while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
|
||||
if (--loop == 0)
|
||||
goto fail;
|
||||
|
||||
loop = 50;
|
||||
*p = inw(base + HA_RDATA);
|
||||
}
|
||||
if (inb(base + HA_RSTATUS) & HA_SERROR) {
|
||||
DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during "
|
||||
"transfer for HBA at %lx\n", base));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (cpu_to_be32(EATA_SIGNATURE) != buf->signature)
|
||||
goto fail;
|
||||
|
||||
DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found "
|
||||
"at %#4lx EATA Level: %x\n",
|
||||
base, (unsigned int) (buf->version)));
|
||||
|
||||
while (inb(base + HA_RSTATUS) & HA_SDRQ)
|
||||
inw(base + HA_RDATA);
|
||||
|
||||
if (!ALLOW_DMA_BOARDS) {
|
||||
for (z = 0; z < MAXISA; z++)
|
||||
if (base == ISAbases[z]) {
|
||||
buf->IRQ = ISAirqs[z];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
release_region(base, 9);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_pio_config(struct get_conf *gc)
|
||||
{
|
||||
printk("Please check values: (read config data)\n");
|
||||
printk("LEN: %d ver:%d OCS:%d TAR:%d TRNXFR:%d MORES:%d\n", be32_to_cpu(gc->len), gc->version, gc->OCS_enabled, gc->TAR_support, gc->TRNXFR, gc->MORE_support);
|
||||
printk("HAAV:%d SCSIID0:%d ID1:%d ID2:%d QUEUE:%d SG:%d SEC:%d\n", gc->HAA_valid, gc->scsi_id[3], gc->scsi_id[2], gc->scsi_id[1], be16_to_cpu(gc->queuesiz), be16_to_cpu(gc->SGsiz), gc->SECOND);
|
||||
printk("IRQ:%d IRQT:%d FORCADR:%d MCH:%d RIDQ:%d\n", gc->IRQ, gc->IRQ_TR, gc->FORCADR, gc->MAX_CHAN, gc->ID_qest);
|
||||
}
|
||||
|
||||
static unsigned int print_selftest(unsigned int base)
|
||||
{
|
||||
unsigned char buffer[512];
|
||||
#ifdef VERBOSE_SETUP
|
||||
int z;
|
||||
#endif
|
||||
|
||||
printk("eata_pio: executing controller self test & setup...\n");
|
||||
while (inb(base + HA_RSTATUS) & HA_SBUSY);
|
||||
outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND);
|
||||
do {
|
||||
while (inb(base + HA_RSTATUS) & HA_SBUSY)
|
||||
/* nothing */ ;
|
||||
if (inb(base + HA_RSTATUS) & HA_SDRQ) {
|
||||
insw(base + HA_RDATA, &buffer, 256);
|
||||
#ifdef VERBOSE_SETUP
|
||||
/* no beeps please... */
|
||||
for (z = 0; z < 511 && buffer[z]; z++)
|
||||
if (buffer[z] != 7)
|
||||
printk("%c", buffer[z]);
|
||||
#endif
|
||||
}
|
||||
} while (inb(base + HA_RSTATUS) & (HA_SBUSY | HA_SDRQ));
|
||||
|
||||
return (!(inb(base + HA_RSTATUS) & HA_SERROR));
|
||||
}
|
||||
|
||||
static int register_pio_HBA(long base, struct get_conf *gc, struct pci_dev *pdev)
|
||||
{
|
||||
unsigned long size = 0;
|
||||
char *buff;
|
||||
unsigned long cplen;
|
||||
unsigned short cppadlen;
|
||||
struct Scsi_Host *sh;
|
||||
hostdata *hd;
|
||||
|
||||
DBG(DBG_REGISTER, print_pio_config(gc));
|
||||
|
||||
if (gc->DMA_support) {
|
||||
printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n", base);
|
||||
if (!ALLOW_DMA_BOARDS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((buff = get_pio_board_data(base, gc->IRQ, gc->scsi_id[3], cplen = (cpu_to_be32(gc->cplen) + 1) / 2, cppadlen = (cpu_to_be16(gc->cppadlen) + 1) / 2)) == NULL) {
|
||||
printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!print_selftest(base) && !ALLOW_DMA_BOARDS) {
|
||||
printk("HBA at %#lx failed while performing self test & setup.\n", base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = sizeof(hostdata) + (sizeof(struct eata_ccb) * be16_to_cpu(gc->queuesiz));
|
||||
|
||||
sh = scsi_register(&driver_template, size);
|
||||
if (sh == NULL)
|
||||
return 0;
|
||||
|
||||
if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */
|
||||
if (!request_irq(gc->IRQ, do_eata_pio_int_handler, 0, "EATA-PIO", sh)) {
|
||||
reg_IRQ[gc->IRQ]++;
|
||||
if (!gc->IRQ_TR)
|
||||
reg_IRQL[gc->IRQ] = 1; /* IRQ is edge triggered */
|
||||
} else {
|
||||
printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ);
|
||||
return 0;
|
||||
}
|
||||
} else { /* More than one HBA on this IRQ */
|
||||
if (reg_IRQL[gc->IRQ]) {
|
||||
printk("Can't support more than one HBA on this IRQ,\n" " if the IRQ is edge triggered. Sorry.\n");
|
||||
return 0;
|
||||
} else
|
||||
reg_IRQ[gc->IRQ]++;
|
||||
}
|
||||
|
||||
hd = SD(sh);
|
||||
|
||||
memset(hd->ccb, 0, (sizeof(struct eata_ccb) * be16_to_cpu(gc->queuesiz)));
|
||||
memset(hd->reads, 0, sizeof(hd->reads));
|
||||
|
||||
strlcpy(SD(sh)->vendor, &buff[8], sizeof(SD(sh)->vendor));
|
||||
strlcpy(SD(sh)->name, &buff[16], sizeof(SD(sh)->name));
|
||||
SD(sh)->revision[0] = buff[32];
|
||||
SD(sh)->revision[1] = buff[33];
|
||||
SD(sh)->revision[2] = buff[34];
|
||||
SD(sh)->revision[3] = '.';
|
||||
SD(sh)->revision[4] = buff[35];
|
||||
SD(sh)->revision[5] = 0;
|
||||
|
||||
switch (be32_to_cpu(gc->len)) {
|
||||
case 0x1c:
|
||||
SD(sh)->EATA_revision = 'a';
|
||||
break;
|
||||
case 0x1e:
|
||||
SD(sh)->EATA_revision = 'b';
|
||||
break;
|
||||
case 0x22:
|
||||
SD(sh)->EATA_revision = 'c';
|
||||
break;
|
||||
case 0x24:
|
||||
SD(sh)->EATA_revision = 'z';
|
||||
break;
|
||||
default:
|
||||
SD(sh)->EATA_revision = '?';
|
||||
}
|
||||
|
||||
if (be32_to_cpu(gc->len) >= 0x22) {
|
||||
if (gc->is_PCI)
|
||||
hd->bustype = IS_PCI;
|
||||
else if (gc->is_EISA)
|
||||
hd->bustype = IS_EISA;
|
||||
else
|
||||
hd->bustype = IS_ISA;
|
||||
} else {
|
||||
if (buff[21] == '4')
|
||||
hd->bustype = IS_PCI;
|
||||
else if (buff[21] == '2')
|
||||
hd->bustype = IS_EISA;
|
||||
else
|
||||
hd->bustype = IS_ISA;
|
||||
}
|
||||
|
||||
SD(sh)->cplen = cplen;
|
||||
SD(sh)->cppadlen = cppadlen;
|
||||
SD(sh)->hostid = gc->scsi_id[3];
|
||||
SD(sh)->devflags = 1 << gc->scsi_id[3];
|
||||
SD(sh)->moresupport = gc->MORE_support;
|
||||
sh->unique_id = base;
|
||||
sh->base = base;
|
||||
sh->io_port = base;
|
||||
sh->n_io_port = 9;
|
||||
sh->irq = gc->IRQ;
|
||||
sh->dma_channel = PIO;
|
||||
sh->this_id = gc->scsi_id[3];
|
||||
sh->can_queue = 1;
|
||||
sh->cmd_per_lun = 1;
|
||||
sh->sg_tablesize = SG_ALL;
|
||||
|
||||
hd->channel = 0;
|
||||
|
||||
hd->pdev = pci_dev_get(pdev); /* Keep a PCI reference */
|
||||
|
||||
sh->max_id = 8;
|
||||
sh->max_lun = 8;
|
||||
|
||||
if (gc->SECOND)
|
||||
hd->primary = 0;
|
||||
else
|
||||
hd->primary = 1;
|
||||
|
||||
hd->next = NULL; /* build a linked list of all HBAs */
|
||||
hd->prev = last_HBA;
|
||||
if (hd->prev != NULL)
|
||||
SD(hd->prev)->next = sh;
|
||||
last_HBA = sh;
|
||||
if (first_HBA == NULL)
|
||||
first_HBA = sh;
|
||||
registered_HBAs++;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void find_pio_ISA(struct get_conf *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXISA; i++) {
|
||||
if (!ISAbases[i])
|
||||
continue;
|
||||
if (!get_pio_conf_PIO(ISAbases[i], buf))
|
||||
continue;
|
||||
if (!register_pio_HBA(ISAbases[i], buf, NULL))
|
||||
release_region(ISAbases[i], 9);
|
||||
else
|
||||
ISAbases[i] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void find_pio_EISA(struct get_conf *buf)
|
||||
{
|
||||
u32 base;
|
||||
int i;
|
||||
|
||||
#ifdef CHECKPAL
|
||||
u8 pal1, pal2, pal3;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAXEISA; i++) {
|
||||
if (EISAbases[i]) { /* Still a possibility ? */
|
||||
|
||||
base = 0x1c88 + (i * 0x1000);
|
||||
#ifdef CHECKPAL
|
||||
pal1 = inb((u16) base - 8);
|
||||
pal2 = inb((u16) base - 7);
|
||||
pal3 = inb((u16) base - 6);
|
||||
|
||||
if (((pal1 == 0x12) && (pal2 == 0x14)) || ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || ((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) {
|
||||
DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: " "%x %x %x \n", (int) pal1, (int) pal2, (int) pal3));
|
||||
#endif
|
||||
if (get_pio_conf_PIO(base, buf)) {
|
||||
DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf));
|
||||
if (buf->IRQ) {
|
||||
if (!register_pio_HBA(base, buf, NULL))
|
||||
release_region(base, 9);
|
||||
} else {
|
||||
printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " "removed from list\n");
|
||||
release_region(base, 9);
|
||||
}
|
||||
}
|
||||
/* Nothing found here so we take it from the list */
|
||||
EISAbases[i] = 0;
|
||||
#ifdef CHECKPAL
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void find_pio_PCI(struct get_conf *buf)
|
||||
{
|
||||
#ifndef CONFIG_PCI
|
||||
printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n");
|
||||
#else
|
||||
struct pci_dev *dev = NULL;
|
||||
unsigned long base, x;
|
||||
|
||||
while ((dev = pci_get_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) {
|
||||
DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", pci_name(dev)));
|
||||
if (pci_enable_device(dev))
|
||||
continue;
|
||||
pci_set_master(dev);
|
||||
base = pci_resource_flags(dev, 0);
|
||||
if (base & IORESOURCE_MEM) {
|
||||
printk("eata_pio: invalid base address of device %s\n", pci_name(dev));
|
||||
continue;
|
||||
}
|
||||
base = pci_resource_start(dev, 0);
|
||||
/* EISA tag there ? */
|
||||
if ((inb(base) == 0x12) && (inb(base + 1) == 0x14))
|
||||
continue; /* Jep, it's forced, so move on */
|
||||
base += 0x10; /* Now, THIS is the real address */
|
||||
if (base != 0x1f8) {
|
||||
/* We didn't find it in the primary search */
|
||||
if (get_pio_conf_PIO(base, buf)) {
|
||||
if (buf->FORCADR) { /* If the address is forced */
|
||||
release_region(base, 9);
|
||||
continue; /* we'll find it later */
|
||||
}
|
||||
|
||||
/* OK. We made it till here, so we can go now
|
||||
* and register it. We only have to check and
|
||||
* eventually remove it from the EISA and ISA list
|
||||
*/
|
||||
|
||||
if (!register_pio_HBA(base, buf, dev)) {
|
||||
release_region(base, 9);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (base < 0x1000) {
|
||||
for (x = 0; x < MAXISA; ++x) {
|
||||
if (ISAbases[x] == base) {
|
||||
ISAbases[x] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((base & 0x0fff) == 0x0c88) {
|
||||
x = (base >> 12) & 0x0f;
|
||||
EISAbases[x] = 0;
|
||||
}
|
||||
}
|
||||
#ifdef CHECK_BLINK
|
||||
else if (check_blink_state(base)) {
|
||||
printk("eata_pio: HBA is in BLINK state.\n" "Consult your HBAs manual to correct this.\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* #ifndef CONFIG_PCI */
|
||||
}
|
||||
|
||||
static int eata_pio_detect(struct scsi_host_template *tpnt)
|
||||
{
|
||||
struct Scsi_Host *HBA_ptr;
|
||||
struct get_conf gc;
|
||||
int i;
|
||||
|
||||
find_pio_PCI(&gc);
|
||||
find_pio_EISA(&gc);
|
||||
find_pio_ISA(&gc);
|
||||
|
||||
for (i = 0; i < MAXIRQ; i++)
|
||||
if (reg_IRQ[i])
|
||||
request_irq(i, do_eata_pio_int_handler, 0, "EATA-PIO", NULL);
|
||||
|
||||
HBA_ptr = first_HBA;
|
||||
|
||||
if (registered_HBAs != 0) {
|
||||
printk("EATA (Extended Attachment) PIO driver version: %d.%d%s\n"
|
||||
"(c) 1993-95 Michael Neuffer, neuffer@goofy.zdv.uni-mainz.de\n" " Alfred Arnold, a.arnold@kfa-juelich.de\n" "This release only supports DASD devices (harddisks)\n", VER_MAJOR, VER_MINOR, VER_SUB);
|
||||
|
||||
printk("Registered HBAs:\n");
|
||||
printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:" " QS: SG: CPL:\n");
|
||||
for (i = 1; i <= registered_HBAs; i++) {
|
||||
printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4lx %2d %d %d %c"
|
||||
" %2d %2d %2d\n",
|
||||
HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
|
||||
SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P') ?
|
||||
"PCI " : (SD(HBA_ptr)->bustype == 'E') ? "EISA" : "ISA ",
|
||||
HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, HBA_ptr->this_id,
|
||||
SD(HBA_ptr)->primary ? 'Y' : 'N', HBA_ptr->can_queue,
|
||||
HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun);
|
||||
HBA_ptr = SD(HBA_ptr)->next;
|
||||
}
|
||||
}
|
||||
return (registered_HBAs);
|
||||
}
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.proc_name = "eata_pio",
|
||||
.name = "EATA (Extended Attachment) PIO driver",
|
||||
.show_info = eata_pio_show_info,
|
||||
.detect = eata_pio_detect,
|
||||
.release = eata_pio_release,
|
||||
.queuecommand = eata_pio_queue,
|
||||
.eh_abort_handler = eata_pio_abort,
|
||||
.eh_host_reset_handler = eata_pio_host_reset,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Michael Neuffer, Alfred Arnold");
|
||||
MODULE_DESCRIPTION("EATA SCSI PIO driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#include "scsi_module.c"
|
|
@ -1,54 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/********************************************************
|
||||
* Header file for eata_pio.c Linux EATA-PIO SCSI driver *
|
||||
* (c) 1993-96 Michael Neuffer *
|
||||
*********************************************************
|
||||
* last change: 2002/11/02 *
|
||||
********************************************************/
|
||||
|
||||
|
||||
#ifndef _EATA_PIO_H
|
||||
#define _EATA_PIO_H
|
||||
|
||||
#define VER_MAJOR 0
|
||||
#define VER_MINOR 0
|
||||
#define VER_SUB "1b"
|
||||
|
||||
/************************************************************************
|
||||
* Here you can switch parts of the code on and of *
|
||||
************************************************************************/
|
||||
|
||||
#define VERBOSE_SETUP /* show startup screen of 2001 */
|
||||
#define ALLOW_DMA_BOARDS 1
|
||||
|
||||
/************************************************************************
|
||||
* Debug options. *
|
||||
* Enable DEBUG and whichever options you require. *
|
||||
************************************************************************/
|
||||
#define DEBUG_EATA 1 /* Enable debug code. */
|
||||
#define DPT_DEBUG 0 /* Bobs special */
|
||||
#define DBG_DELAY 0 /* Build in delays so debug messages can be
|
||||
* be read before they vanish of the top of
|
||||
* the screen!
|
||||
*/
|
||||
#define DBG_PROBE 0 /* Debug probe routines. */
|
||||
#define DBG_ISA 0 /* Trace ISA routines */
|
||||
#define DBG_EISA 0 /* Trace EISA routines */
|
||||
#define DBG_PCI 0 /* Trace PCI routines */
|
||||
#define DBG_PIO 0 /* Trace get_config_PIO */
|
||||
#define DBG_COM 0 /* Trace command call */
|
||||
#define DBG_QUEUE 0 /* Trace command queueing. */
|
||||
#define DBG_INTR 0 /* Trace interrupt service routine. */
|
||||
#define DBG_INTR2 0 /* Trace interrupt service routine. */
|
||||
#define DBG_PROC 0 /* Debug proc-fs related statistics */
|
||||
#define DBG_PROC_WRITE 0
|
||||
#define DBG_REGISTER 0 /* */
|
||||
#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */
|
||||
|
||||
#if DEBUG_EATA
|
||||
#define DBG(x, y) if ((x)) {y;}
|
||||
#else
|
||||
#define DBG(x, y)
|
||||
#endif
|
||||
|
||||
#endif /* _EATA_PIO_H */
|
|
@ -962,7 +962,6 @@ struct esas2r_adapter {
|
|||
* Function Declarations
|
||||
* SCSI functions
|
||||
*/
|
||||
int esas2r_release(struct Scsi_Host *);
|
||||
const char *esas2r_info(struct Scsi_Host *);
|
||||
int esas2r_write_params(struct esas2r_adapter *a, struct esas2r_request *rq,
|
||||
struct esas2r_sas_nvram *data);
|
||||
|
@ -984,7 +983,6 @@ int esas2r_target_reset(struct scsi_cmnd *cmd);
|
|||
/* Internal functions */
|
||||
int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid,
|
||||
int index);
|
||||
int esas2r_cleanup(struct Scsi_Host *host);
|
||||
int esas2r_read_fw(struct esas2r_adapter *a, char *buf, long off, int count);
|
||||
int esas2r_write_fw(struct esas2r_adapter *a, const char *buf, long off,
|
||||
int count);
|
||||
|
|
|
@ -661,27 +661,6 @@ void esas2r_kill_adapter(int i)
|
|||
}
|
||||
}
|
||||
|
||||
int esas2r_cleanup(struct Scsi_Host *host)
|
||||
{
|
||||
struct esas2r_adapter *a;
|
||||
int index;
|
||||
|
||||
if (host == NULL) {
|
||||
int i;
|
||||
|
||||
esas2r_debug("esas2r_cleanup everything");
|
||||
for (i = 0; i < MAX_ADAPTERS; i++)
|
||||
esas2r_kill_adapter(i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
esas2r_debug("esas2r_cleanup called for host %p", host);
|
||||
a = (struct esas2r_adapter *)host->hostdata;
|
||||
index = a->index;
|
||||
esas2r_kill_adapter(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
int esas2r_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct Scsi_Host *host = pci_get_drvdata(pdev);
|
||||
|
|
|
@ -235,7 +235,6 @@ static struct scsi_host_template driver_template = {
|
|||
.module = THIS_MODULE,
|
||||
.show_info = esas2r_show_info,
|
||||
.name = ESAS2R_LONGNAME,
|
||||
.release = esas2r_release,
|
||||
.info = esas2r_info,
|
||||
.ioctl = esas2r_ioctl,
|
||||
.queuecommand = esas2r_queuecommand,
|
||||
|
@ -520,44 +519,16 @@ static int esas2r_probe(struct pci_dev *pcid,
|
|||
|
||||
static void esas2r_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *host;
|
||||
int index;
|
||||
|
||||
if (pdev == NULL) {
|
||||
esas2r_log(ESAS2R_LOG_WARN, "esas2r_remove pdev==NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
host = pci_get_drvdata(pdev);
|
||||
|
||||
if (host == NULL) {
|
||||
/*
|
||||
* this can happen if pci_set_drvdata was already called
|
||||
* to clear the host pointer. if this is the case, we
|
||||
* are okay; this channel has already been cleaned up.
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
struct Scsi_Host *host = pci_get_drvdata(pdev);
|
||||
struct esas2r_adapter *a = (struct esas2r_adapter *)host->hostdata;
|
||||
|
||||
esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev),
|
||||
"esas2r_remove(%p) called; "
|
||||
"host:%p", pdev,
|
||||
host);
|
||||
|
||||
index = esas2r_cleanup(host);
|
||||
|
||||
if (index < 0)
|
||||
esas2r_log_dev(ESAS2R_LOG_WARN, &(pdev->dev),
|
||||
"unknown host in %s",
|
||||
__func__);
|
||||
|
||||
esas2r_kill_adapter(a->index);
|
||||
found_adapters--;
|
||||
|
||||
/* if this was the last adapter, clean up the rest of the driver */
|
||||
|
||||
if (found_adapters == 0)
|
||||
esas2r_cleanup(NULL);
|
||||
}
|
||||
|
||||
static int __init esas2r_init(void)
|
||||
|
@ -638,30 +609,7 @@ static int __init esas2r_init(void)
|
|||
for (i = 0; i < MAX_ADAPTERS; i++)
|
||||
esas2r_adapters[i] = NULL;
|
||||
|
||||
/* initialize */
|
||||
|
||||
driver_template.module = THIS_MODULE;
|
||||
|
||||
if (pci_register_driver(&esas2r_pci_driver) != 0)
|
||||
esas2r_log(ESAS2R_LOG_CRIT, "pci_register_driver FAILED");
|
||||
else
|
||||
esas2r_log(ESAS2R_LOG_INFO, "pci_register_driver() OK");
|
||||
|
||||
if (!found_adapters) {
|
||||
pci_unregister_driver(&esas2r_pci_driver);
|
||||
esas2r_cleanup(NULL);
|
||||
|
||||
esas2r_log(ESAS2R_LOG_CRIT,
|
||||
"driver will not be loaded because no ATTO "
|
||||
"%s devices were found",
|
||||
ESAS2R_DRVR_NAME);
|
||||
return -1;
|
||||
} else {
|
||||
esas2r_log(ESAS2R_LOG_INFO, "found %d adapters",
|
||||
found_adapters);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return pci_register_driver(&esas2r_pci_driver);
|
||||
}
|
||||
|
||||
/* Handle ioctl calls to "/proc/scsi/esas2r/ATTOnode" */
|
||||
|
@ -753,18 +701,6 @@ int esas2r_show_info(struct seq_file *m, struct Scsi_Host *sh)
|
|||
|
||||
}
|
||||
|
||||
int esas2r_release(struct Scsi_Host *sh)
|
||||
{
|
||||
esas2r_log_dev(ESAS2R_LOG_INFO, &(sh->shost_gendev),
|
||||
"esas2r_release() called");
|
||||
|
||||
esas2r_cleanup(sh);
|
||||
if (sh->irq)
|
||||
free_irq(sh->irq, NULL);
|
||||
scsi_unregister(sh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *esas2r_info(struct Scsi_Host *sh)
|
||||
{
|
||||
struct esas2r_adapter *a = (struct esas2r_adapter *)sh->hostdata;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* fdomain.c -- Future Domain TMC-16x0 SCSI driver
|
||||
* Author: Rickard E. Faith, faith@cs.unc.edu
|
||||
* Copyright 1992-1996, 1998 Rickard E. Faith (faith@acm.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
extern struct scsi_host_template fdomain_driver_template;
|
||||
extern int fdomain_setup(char *str);
|
||||
extern struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt );
|
||||
extern int fdomain_16x0_host_reset(struct scsi_cmnd *SCpnt);
|
|
@ -1,6 +1,6 @@
|
|||
config SCSI_HISI_SAS
|
||||
tristate "HiSilicon SAS"
|
||||
depends on HAS_DMA && HAS_IOMEM
|
||||
depends on HAS_IOMEM
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
select SCSI_SAS_LIBSAS
|
||||
select BLK_DEV_INTEGRITY
|
||||
|
|
|
@ -175,7 +175,6 @@ struct hisi_sas_device {
|
|||
struct hisi_sas_dq *dq;
|
||||
struct list_head list;
|
||||
u64 attached_phy;
|
||||
atomic64_t running_req;
|
||||
enum sas_device_type dev_type;
|
||||
int device_id;
|
||||
int sata_idx;
|
||||
|
|
|
@ -200,8 +200,6 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
|
|||
|
||||
if (task) {
|
||||
struct device *dev = hisi_hba->dev;
|
||||
struct domain_device *device = task->dev;
|
||||
struct hisi_sas_device *sas_dev = device->lldd_dev;
|
||||
|
||||
if (!task->lldd_task)
|
||||
return;
|
||||
|
@ -213,9 +211,6 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
|
|||
dma_unmap_sg(dev, task->scatter,
|
||||
task->num_scatter,
|
||||
task->data_dir);
|
||||
|
||||
if (sas_dev)
|
||||
atomic64_dec(&sas_dev->running_req);
|
||||
}
|
||||
|
||||
if (slot->buf)
|
||||
|
@ -321,7 +316,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
|
|||
*/
|
||||
if (device->dev_type != SAS_SATA_DEV)
|
||||
task->task_done(task);
|
||||
return SAS_PHY_DOWN;
|
||||
return -ECOMM;
|
||||
}
|
||||
|
||||
if (DEV_IS_GONE(sas_dev)) {
|
||||
|
@ -332,7 +327,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
|
|||
dev_info(dev, "task prep: device %016llx not ready\n",
|
||||
SAS_ADDR(device->sas_addr));
|
||||
|
||||
return SAS_PHY_DOWN;
|
||||
return -ECOMM;
|
||||
}
|
||||
|
||||
port = to_hisi_sas_port(sas_port);
|
||||
|
@ -342,7 +337,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
|
|||
"SATA/STP" : "SAS",
|
||||
device->port->id);
|
||||
|
||||
return SAS_PHY_DOWN;
|
||||
return -ECOMM;
|
||||
}
|
||||
|
||||
if (!sas_protocol_ata(task->task_proto)) {
|
||||
|
@ -431,8 +426,6 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
|
|||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
dq->slot_prep = slot;
|
||||
|
||||
atomic64_inc(&sas_dev->running_req);
|
||||
++(*pass);
|
||||
|
||||
return 0;
|
||||
|
@ -683,6 +676,8 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no)
|
|||
|
||||
phy->hisi_hba = hisi_hba;
|
||||
phy->port = NULL;
|
||||
phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
|
||||
phy->maximum_linkrate = hisi_hba->hw->phy_get_max_linkrate();
|
||||
sas_phy->enabled = (phy_no < hisi_hba->n_phy) ? 1 : 0;
|
||||
sas_phy->class = SAS;
|
||||
sas_phy->iproto = SAS_PROTOCOL_ALL;
|
||||
|
@ -869,6 +864,7 @@ static void hisi_sas_tmf_timedout(struct timer_list *t)
|
|||
|
||||
#define TASK_TIMEOUT 20
|
||||
#define TASK_RETRY 3
|
||||
#define INTERNAL_ABORT_TIMEOUT 6
|
||||
static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
|
||||
void *parameter, u32 para_len,
|
||||
struct hisi_sas_tmf_task *tmf)
|
||||
|
@ -1514,8 +1510,6 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
|
|||
|
||||
dq->slot_prep = slot;
|
||||
|
||||
atomic64_inc(&sas_dev->running_req);
|
||||
|
||||
/* send abort command to the chip */
|
||||
hisi_hba->hw->start_delivery(dq);
|
||||
spin_unlock_irqrestore(&dq->lock, flags_dq);
|
||||
|
@ -1572,7 +1566,7 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
|
|||
task->task_proto = device->tproto;
|
||||
task->task_done = hisi_sas_task_done;
|
||||
task->slow_task->timer.function = hisi_sas_tmf_timedout;
|
||||
task->slow_task->timer.expires = jiffies + msecs_to_jiffies(110);
|
||||
task->slow_task->timer.expires = jiffies + INTERNAL_ABORT_TIMEOUT*HZ;
|
||||
add_timer(&task->slow_task->timer);
|
||||
|
||||
res = hisi_sas_internal_abort_task_exec(hisi_hba, sas_dev->device_id,
|
||||
|
|
|
@ -651,8 +651,10 @@ static int reset_hw_v1_hw(struct hisi_hba *hisi_hba)
|
|||
dev_err(dev, "De-reset failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
dev_warn(dev, "no reset method\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -873,7 +875,6 @@ static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no,
|
|||
sas_phy->phy->maximum_linkrate = max;
|
||||
sas_phy->phy->minimum_linkrate = min;
|
||||
|
||||
min -= SAS_LINK_RATE_1_5_GBPS;
|
||||
max -= SAS_LINK_RATE_1_5_GBPS;
|
||||
|
||||
for (i = 0; i <= max; i++)
|
||||
|
@ -882,10 +883,11 @@ static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no,
|
|||
prog_phy_link_rate &= ~0xff;
|
||||
prog_phy_link_rate |= rate_mask;
|
||||
|
||||
disable_phy_v1_hw(hisi_hba, phy_no);
|
||||
msleep(100);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
|
||||
prog_phy_link_rate);
|
||||
|
||||
phy_hard_reset_v1_hw(hisi_hba, phy_no);
|
||||
start_phy_v1_hw(hisi_hba, phy_no);
|
||||
}
|
||||
|
||||
static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id)
|
||||
|
@ -1407,9 +1409,6 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
|
|||
}
|
||||
|
||||
out:
|
||||
if (sas_dev)
|
||||
atomic64_dec(&sas_dev->running_req);
|
||||
|
||||
hisi_sas_slot_task_free(hisi_hba, task, slot);
|
||||
sts = ts->stat;
|
||||
|
||||
|
|
|
@ -406,6 +406,17 @@ struct hisi_sas_err_record_v2 {
|
|||
__le32 dma_rx_err_type;
|
||||
};
|
||||
|
||||
struct signal_attenuation_s {
|
||||
u32 de_emphasis;
|
||||
u32 preshoot;
|
||||
u32 boost;
|
||||
};
|
||||
|
||||
struct sig_atten_lu_s {
|
||||
const struct signal_attenuation_s *att;
|
||||
u32 sas_phy_ctrl;
|
||||
};
|
||||
|
||||
static const struct hisi_sas_hw_error one_bit_ecc_errors[] = {
|
||||
{
|
||||
.irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_1B_OFF),
|
||||
|
@ -1084,8 +1095,10 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
|
|||
dev_err(dev, "SAS de-reset fail.\n");
|
||||
return -EIO;
|
||||
}
|
||||
} else
|
||||
dev_warn(dev, "no reset method\n");
|
||||
} else {
|
||||
dev_err(dev, "no reset method\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1130,9 +1143,16 @@ static void phys_try_accept_stp_links_v2_hw(struct hisi_hba *hisi_hba)
|
|||
}
|
||||
}
|
||||
|
||||
static const struct signal_attenuation_s x6000 = {9200, 0, 10476};
|
||||
static const struct sig_atten_lu_s sig_atten_lu[] = {
|
||||
{ &x6000, 0x3016a68 },
|
||||
};
|
||||
|
||||
static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
struct device *dev = hisi_hba->dev;
|
||||
u32 sas_phy_ctrl = 0x30b9908;
|
||||
u32 signal[3];
|
||||
int i;
|
||||
|
||||
/* Global registers init */
|
||||
|
@ -1176,9 +1196,28 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
|
|||
hisi_sas_write32(hisi_hba, AXI_AHB_CLK_CFG, 1);
|
||||
hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);
|
||||
|
||||
/* Get sas_phy_ctrl value to deal with TX FFE issue. */
|
||||
if (!device_property_read_u32_array(dev, "hisilicon,signal-attenuation",
|
||||
signal, ARRAY_SIZE(signal))) {
|
||||
for (i = 0; i < ARRAY_SIZE(sig_atten_lu); i++) {
|
||||
const struct sig_atten_lu_s *lookup = &sig_atten_lu[i];
|
||||
const struct signal_attenuation_s *att = lookup->att;
|
||||
|
||||
if ((signal[0] == att->de_emphasis) &&
|
||||
(signal[1] == att->preshoot) &&
|
||||
(signal[2] == att->boost)) {
|
||||
sas_phy_ctrl = lookup->sas_phy_ctrl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(sig_atten_lu))
|
||||
dev_warn(dev, "unknown signal attenuation values, using default PHY ctrl config\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < hisi_hba->n_phy; i++) {
|
||||
hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, 0x30b9908);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, sas_phy_ctrl);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SL_CONTROL, 0x0);
|
||||
hisi_sas_phy_write32(hisi_hba, i, TXID_AUTO, 0x2);
|
||||
|
@ -1566,7 +1605,6 @@ static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no,
|
|||
sas_phy->phy->maximum_linkrate = max;
|
||||
sas_phy->phy->minimum_linkrate = min;
|
||||
|
||||
min -= SAS_LINK_RATE_1_5_GBPS;
|
||||
max -= SAS_LINK_RATE_1_5_GBPS;
|
||||
|
||||
for (i = 0; i <= max; i++)
|
||||
|
@ -1575,10 +1613,11 @@ static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no,
|
|||
prog_phy_link_rate &= ~0xff;
|
||||
prog_phy_link_rate |= rate_mask;
|
||||
|
||||
disable_phy_v2_hw(hisi_hba, phy_no);
|
||||
msleep(100);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
|
||||
prog_phy_link_rate);
|
||||
|
||||
phy_hard_reset_v2_hw(hisi_hba, phy_no);
|
||||
start_phy_v2_hw(hisi_hba, phy_no);
|
||||
}
|
||||
|
||||
static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id)
|
||||
|
@ -2371,7 +2410,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
|
|||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_sas_slot_task_free(hisi_hba, task, slot);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
return -1;
|
||||
return ts->stat;
|
||||
}
|
||||
|
||||
if (unlikely(!sas_dev)) {
|
||||
|
@ -2630,7 +2669,7 @@ static int prep_abort_v2_hw(struct hisi_hba *hisi_hba,
|
|||
/* dw0 */
|
||||
hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/
|
||||
(port->id << CMD_HDR_PORT_OFF) |
|
||||
((dev_is_sata(dev) ? 1:0) <<
|
||||
(dev_is_sata(dev) <<
|
||||
CMD_HDR_ABORT_DEVICE_TYPE_OFF) |
|
||||
(abort_flag << CMD_HDR_ABORT_FLAG_OFF));
|
||||
|
||||
|
@ -2647,7 +2686,7 @@ static int prep_abort_v2_hw(struct hisi_hba *hisi_hba,
|
|||
static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int i, res = IRQ_HANDLED;
|
||||
u32 port_id, link_rate, hard_phy_linkrate;
|
||||
u32 port_id, link_rate;
|
||||
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
|
||||
struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
||||
struct device *dev = hisi_hba->dev;
|
||||
|
@ -2686,11 +2725,6 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
|
|||
}
|
||||
|
||||
sas_phy->linkrate = link_rate;
|
||||
hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
|
||||
HARD_PHY_LINKRATE);
|
||||
phy->maximum_linkrate = hard_phy_linkrate & 0xf;
|
||||
phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
|
||||
|
||||
sas_phy->oob_mode = SAS_OOB_MODE;
|
||||
memcpy(sas_phy->attached_sas_addr, &id->sas_addr, SAS_ADDR_SIZE);
|
||||
dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate);
|
||||
|
|
|
@ -172,6 +172,7 @@
|
|||
#define CHL_INT1_MSK (PORT_BASE + 0x1c4)
|
||||
#define CHL_INT2_MSK (PORT_BASE + 0x1c8)
|
||||
#define CHL_INT_COAL_EN (PORT_BASE + 0x1d0)
|
||||
#define SAS_RX_TRAIN_TIMER (PORT_BASE + 0x2a4)
|
||||
#define PHY_CTRL_RDY_MSK (PORT_BASE + 0x2b0)
|
||||
#define PHYCTRL_NOT_RDY_MSK (PORT_BASE + 0x2b4)
|
||||
#define PHYCTRL_DWS_RESET_MSK (PORT_BASE + 0x2b8)
|
||||
|
@ -184,6 +185,8 @@
|
|||
#define DMA_RX_STATUS (PORT_BASE + 0x2e8)
|
||||
#define DMA_RX_STATUS_BUSY_OFF 0
|
||||
#define DMA_RX_STATUS_BUSY_MSK (0x1 << DMA_RX_STATUS_BUSY_OFF)
|
||||
|
||||
#define COARSETUNE_TIME (PORT_BASE + 0x304)
|
||||
#define ERR_CNT_DWS_LOST (PORT_BASE + 0x380)
|
||||
#define ERR_CNT_RESET_PROB (PORT_BASE + 0x384)
|
||||
#define ERR_CNT_INVLD_DW (PORT_BASE + 0x390)
|
||||
|
@ -340,12 +343,6 @@ struct hisi_sas_err_record_v3 {
|
|||
#define HISI_SAS_COMMAND_ENTRIES_V3_HW 4096
|
||||
#define HISI_SAS_MSI_COUNT_V3_HW 32
|
||||
|
||||
enum {
|
||||
HISI_SAS_PHY_PHY_UPDOWN,
|
||||
HISI_SAS_PHY_CHNL_INT,
|
||||
HISI_SAS_PHY_INT_NR
|
||||
};
|
||||
|
||||
#define DIR_NO_DATA 0
|
||||
#define DIR_TO_INI 1
|
||||
#define DIR_TO_DEVICE 2
|
||||
|
@ -423,10 +420,10 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
|
|||
hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK+0x4*i, 0);
|
||||
|
||||
hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);
|
||||
hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE, 0x30000);
|
||||
|
||||
for (i = 0; i < hisi_hba->n_phy; i++) {
|
||||
hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x801);
|
||||
hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SAS_RX_TRAIN_TIMER, 0x13e80);
|
||||
hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff);
|
||||
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff);
|
||||
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xffffffff);
|
||||
|
@ -438,17 +435,13 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
|
|||
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_DWS_RESET_MSK, 0x0);
|
||||
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_PHY_ENA_MSK, 0x0);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SL_RX_BCAST_CHK_MSK, 0x0);
|
||||
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x0);
|
||||
hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, 0x199b4fa);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SAS_SSP_CON_TIMER_CFG,
|
||||
0xa03e8);
|
||||
hisi_sas_phy_write32(hisi_hba, i, SAS_STP_CON_TIMER_CFG,
|
||||
0xa03e8);
|
||||
hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER,
|
||||
0x7f7a120);
|
||||
hisi_sas_phy_write32(hisi_hba, i, CON_CFG_DRIVER,
|
||||
0x2a0a80);
|
||||
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x1);
|
||||
hisi_sas_phy_write32(hisi_hba, i, STP_LINK_TIMER, 0x7f7a120);
|
||||
|
||||
/* used for 12G negotiate */
|
||||
hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e);
|
||||
}
|
||||
|
||||
for (i = 0; i < hisi_hba->queue_count; i++) {
|
||||
/* Delivery queue */
|
||||
hisi_sas_write32(hisi_hba,
|
||||
|
@ -676,8 +669,10 @@ static int reset_hw_v3_hw(struct hisi_hba *hisi_hba)
|
|||
dev_err(dev, "Reset failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
dev_err(dev, "no reset method!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -737,7 +732,7 @@ static void phy_hard_reset_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
|
|||
start_phy_v3_hw(hisi_hba, phy_no);
|
||||
}
|
||||
|
||||
enum sas_linkrate phy_get_max_linkrate_v3_hw(void)
|
||||
static enum sas_linkrate phy_get_max_linkrate_v3_hw(void)
|
||||
{
|
||||
return SAS_LINK_RATE_12_0_GBPS;
|
||||
}
|
||||
|
@ -1102,7 +1097,7 @@ static int prep_abort_v3_hw(struct hisi_hba *hisi_hba,
|
|||
/* dw0 */
|
||||
hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/
|
||||
(port->id << CMD_HDR_PORT_OFF) |
|
||||
((dev_is_sata(dev) ? 1:0)
|
||||
(dev_is_sata(dev)
|
||||
<< CMD_HDR_ABORT_DEVICE_TYPE_OFF) |
|
||||
(abort_flag
|
||||
<< CMD_HDR_ABORT_FLAG_OFF));
|
||||
|
@ -1118,10 +1113,10 @@ static int prep_abort_v3_hw(struct hisi_hba *hisi_hba,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
{
|
||||
int i, res = 0;
|
||||
u32 context, port_id, link_rate, hard_phy_linkrate;
|
||||
int i, res;
|
||||
u32 context, port_id, link_rate;
|
||||
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
|
||||
struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
||||
struct device *dev = hisi_hba->dev;
|
||||
|
@ -1139,10 +1134,6 @@ static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
|||
goto end;
|
||||
}
|
||||
sas_phy->linkrate = link_rate;
|
||||
hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
|
||||
HARD_PHY_LINKRATE);
|
||||
phy->maximum_linkrate = hard_phy_linkrate & 0xf;
|
||||
phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
|
||||
phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
|
||||
|
||||
/* Check for SATA dev */
|
||||
|
@ -1196,7 +1187,7 @@ static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
|||
phy->port_id = port_id;
|
||||
phy->phy_attached = 1;
|
||||
hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
|
||||
|
||||
res = IRQ_HANDLED;
|
||||
end:
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
|
||||
CHL_INT0_SL_PHY_ENABLE_MSK);
|
||||
|
@ -1205,7 +1196,7 @@ end:
|
|||
return res;
|
||||
}
|
||||
|
||||
static int phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
static irqreturn_t phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
{
|
||||
u32 phy_state, sl_ctrl, txid_auto;
|
||||
struct device *dev = hisi_hba->dev;
|
||||
|
@ -1227,10 +1218,10 @@ static int phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
|||
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 0);
|
||||
|
||||
return 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
static irqreturn_t phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
||||
{
|
||||
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
|
||||
struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
||||
|
@ -1241,6 +1232,8 @@ static void phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
|
|||
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
|
||||
CHL_INT0_SL_RX_BCST_ACK_MSK);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t int_phy_up_down_bcast_v3_hw(int irq_no, void *p)
|
||||
|
@ -1267,7 +1260,9 @@ static irqreturn_t int_phy_up_down_bcast_v3_hw(int irq_no, void *p)
|
|||
res = IRQ_HANDLED;
|
||||
if (irq_value & CHL_INT0_SL_RX_BCST_ACK_MSK)
|
||||
/* phy bcast */
|
||||
phy_bcast_v3_hw(phy_no, hisi_hba);
|
||||
if (phy_bcast_v3_hw(phy_no, hisi_hba)
|
||||
== IRQ_HANDLED)
|
||||
res = IRQ_HANDLED;
|
||||
} else {
|
||||
if (irq_value & CHL_INT0_NOT_RDY_MSK)
|
||||
/* phy down */
|
||||
|
@ -1583,7 +1578,7 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
|
|||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
hisi_sas_slot_task_free(hisi_hba, task, slot);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
return -1;
|
||||
return ts->stat;
|
||||
}
|
||||
|
||||
if (unlikely(!sas_dev)) {
|
||||
|
@ -1864,7 +1859,6 @@ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no,
|
|||
sas_phy->phy->maximum_linkrate = max;
|
||||
sas_phy->phy->minimum_linkrate = min;
|
||||
|
||||
min -= SAS_LINK_RATE_1_5_GBPS;
|
||||
max -= SAS_LINK_RATE_1_5_GBPS;
|
||||
|
||||
for (i = 0; i <= max; i++)
|
||||
|
@ -1873,10 +1867,11 @@ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no,
|
|||
prog_phy_link_rate &= ~0xff;
|
||||
prog_phy_link_rate |= rate_mask;
|
||||
|
||||
disable_phy_v3_hw(hisi_hba, phy_no);
|
||||
msleep(100);
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
|
||||
prog_phy_link_rate);
|
||||
|
||||
phy_hard_reset_v3_hw(hisi_hba, phy_no);
|
||||
start_phy_v3_hw(hisi_hba, phy_no);
|
||||
}
|
||||
|
||||
static void interrupt_disable_v3_hw(struct hisi_hba *hisi_hba)
|
||||
|
@ -2399,6 +2394,7 @@ static const struct pci_device_id sas_v3_pci_table[] = {
|
|||
{ PCI_VDEVICE(HUAWEI, 0xa230), hip08 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, sas_v3_pci_table);
|
||||
|
||||
static const struct pci_error_handlers hisi_sas_err_handler = {
|
||||
.error_detected = hisi_sas_error_detected_v3_hw,
|
||||
|
@ -2421,4 +2417,4 @@ module_pci_driver(sas_v3_pci_driver);
|
|||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("John Garry <john.garry@huawei.com>");
|
||||
MODULE_DESCRIPTION("HISILICON SAS controller v3 hw driver based on pci device");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
MODULE_ALIAS("pci:" DRV_NAME);
|
||||
|
|
|
@ -42,6 +42,12 @@
|
|||
#include "scsi_logging.h"
|
||||
|
||||
|
||||
static int shost_eh_deadline = -1;
|
||||
|
||||
module_param_named(eh_deadline, shost_eh_deadline, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(eh_deadline,
|
||||
"SCSI EH timeout in seconds (should be between 0 and 2^31-1)");
|
||||
|
||||
static DEFINE_IDA(host_index_ida);
|
||||
|
||||
|
||||
|
@ -148,7 +154,6 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
|
|||
scsi_host_state_name(state)));
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_host_set_state);
|
||||
|
||||
/**
|
||||
* scsi_remove_host - remove a scsi host
|
||||
|
@ -356,12 +361,6 @@ static void scsi_host_dev_release(struct device *dev)
|
|||
kfree(shost);
|
||||
}
|
||||
|
||||
static int shost_eh_deadline = -1;
|
||||
|
||||
module_param_named(eh_deadline, shost_eh_deadline, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(eh_deadline,
|
||||
"SCSI EH timeout in seconds (should be between 0 and 2^31-1)");
|
||||
|
||||
static struct device_type scsi_host_type = {
|
||||
.name = "scsi_host",
|
||||
.release = scsi_host_dev_release,
|
||||
|
@ -517,29 +516,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
|
|||
}
|
||||
EXPORT_SYMBOL(scsi_host_alloc);
|
||||
|
||||
struct Scsi_Host *scsi_register(struct scsi_host_template *sht, int privsize)
|
||||
{
|
||||
struct Scsi_Host *shost = scsi_host_alloc(sht, privsize);
|
||||
|
||||
if (!sht->detect) {
|
||||
printk(KERN_WARNING "scsi_register() called on new-style "
|
||||
"template for driver %s\n", sht->name);
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
if (shost)
|
||||
list_add_tail(&shost->sht_legacy_list, &sht->legacy_hosts);
|
||||
return shost;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_register);
|
||||
|
||||
void scsi_unregister(struct Scsi_Host *shost)
|
||||
{
|
||||
list_del(&shost->sht_legacy_list);
|
||||
scsi_host_put(shost);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_unregister);
|
||||
|
||||
static int __scsi_host_match(struct device *dev, const void *data)
|
||||
{
|
||||
struct Scsi_Host *p;
|
||||
|
|
|
@ -3816,10 +3816,8 @@ static struct device_attribute ipr_iopoll_weight_attr = {
|
|||
**/
|
||||
static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len)
|
||||
{
|
||||
int sg_size, order, bsize_elem, num_elem, i, j;
|
||||
int sg_size, order;
|
||||
struct ipr_sglist *sglist;
|
||||
struct scatterlist *scatterlist;
|
||||
struct page *page;
|
||||
|
||||
/* Get the minimum size per scatter/gather element */
|
||||
sg_size = buf_len / (IPR_MAX_SGLIST - 1);
|
||||
|
@ -3827,47 +3825,20 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len)
|
|||
/* Get the actual size per element */
|
||||
order = get_order(sg_size);
|
||||
|
||||
/* Determine the actual number of bytes per element */
|
||||
bsize_elem = PAGE_SIZE * (1 << order);
|
||||
|
||||
/* Determine the actual number of sg entries needed */
|
||||
if (buf_len % bsize_elem)
|
||||
num_elem = (buf_len / bsize_elem) + 1;
|
||||
else
|
||||
num_elem = buf_len / bsize_elem;
|
||||
|
||||
/* Allocate a scatter/gather list for the DMA */
|
||||
sglist = kzalloc(sizeof(struct ipr_sglist) +
|
||||
(sizeof(struct scatterlist) * (num_elem - 1)),
|
||||
GFP_KERNEL);
|
||||
|
||||
sglist = kzalloc(sizeof(struct ipr_sglist), GFP_KERNEL);
|
||||
if (sglist == NULL) {
|
||||
ipr_trace;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scatterlist = sglist->scatterlist;
|
||||
sg_init_table(scatterlist, num_elem);
|
||||
|
||||
sglist->order = order;
|
||||
sglist->num_sg = num_elem;
|
||||
|
||||
/* Allocate a bunch of sg elements */
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
page = alloc_pages(GFP_KERNEL, order);
|
||||
if (!page) {
|
||||
ipr_trace;
|
||||
|
||||
/* Free up what we already allocated */
|
||||
for (j = i - 1; j >= 0; j--)
|
||||
__free_pages(sg_page(&scatterlist[j]), order);
|
||||
sglist->scatterlist = sgl_alloc_order(buf_len, order, false, GFP_KERNEL,
|
||||
&sglist->num_sg);
|
||||
if (!sglist->scatterlist) {
|
||||
kfree(sglist);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sg_set_page(&scatterlist[i], page, 0, 0);
|
||||
}
|
||||
|
||||
return sglist;
|
||||
}
|
||||
|
||||
|
@ -3883,11 +3854,7 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len)
|
|||
**/
|
||||
static void ipr_free_ucode_buffer(struct ipr_sglist *sglist)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sglist->num_sg; i++)
|
||||
__free_pages(sg_page(&sglist->scatterlist[i]), sglist->order);
|
||||
|
||||
sgl_free_order(sglist->scatterlist, sglist->order);
|
||||
kfree(sglist);
|
||||
}
|
||||
|
||||
|
@ -9684,14 +9651,14 @@ static int ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
|
|||
}
|
||||
|
||||
for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
|
||||
ipr_cmd = dma_pool_alloc(ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
|
||||
ipr_cmd = dma_pool_zalloc(ioa_cfg->ipr_cmd_pool,
|
||||
GFP_KERNEL, &dma_addr);
|
||||
|
||||
if (!ipr_cmd) {
|
||||
ipr_free_cmd_blks(ioa_cfg);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(ipr_cmd, 0, sizeof(*ipr_cmd));
|
||||
ioa_cfg->ipr_cmnd_list[i] = ipr_cmd;
|
||||
ioa_cfg->ipr_cmnd_list_dma[i] = dma_addr;
|
||||
|
||||
|
|
|
@ -1454,7 +1454,7 @@ struct ipr_sglist {
|
|||
u32 num_sg;
|
||||
u32 num_dma_sg;
|
||||
u32 buffer_len;
|
||||
struct scatterlist scatterlist[1];
|
||||
struct scatterlist *scatterlist;
|
||||
};
|
||||
|
||||
enum ipr_sdt_state {
|
||||
|
|
|
@ -224,8 +224,6 @@ module_param(ips, charp, 0);
|
|||
/*
|
||||
* Function prototypes
|
||||
*/
|
||||
static int ips_detect(struct scsi_host_template *);
|
||||
static int ips_release(struct Scsi_Host *);
|
||||
static int ips_eh_abort(struct scsi_cmnd *);
|
||||
static int ips_eh_reset(struct scsi_cmnd *);
|
||||
static int ips_queue(struct Scsi_Host *, struct scsi_cmnd *);
|
||||
|
@ -355,8 +353,6 @@ static dma_addr_t ips_flashbusaddr;
|
|||
static long ips_FlashDataInUse; /* CD Boot - Flash Data In Use Flag */
|
||||
static uint32_t MaxLiteCmds = 32; /* Max Active Cmds for a Lite Adapter */
|
||||
static struct scsi_host_template ips_driver_template = {
|
||||
.detect = ips_detect,
|
||||
.release = ips_release,
|
||||
.info = ips_info,
|
||||
.queuecommand = ips_queue,
|
||||
.eh_abort_handler = ips_eh_abort,
|
||||
|
|
|
@ -2766,7 +2766,7 @@ static int sci_write_gpio_tx_gp(struct isci_host *ihost, u8 reg_index, u8 reg_co
|
|||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
int bit = (i << 2) + 2;
|
||||
int bit;
|
||||
|
||||
bit = try_test_sas_gpio_gp_bit(to_sas_gpio_od(d, i),
|
||||
write_data, reg_index,
|
||||
|
|
|
@ -147,7 +147,7 @@ static int esp_jazz_probe(struct platform_device *dev)
|
|||
esp = shost_priv(host);
|
||||
|
||||
esp->host = host;
|
||||
esp->dev = dev;
|
||||
esp->dev = &dev->dev;
|
||||
esp->ops = &jazz_esp_ops;
|
||||
|
||||
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
|
|
|
@ -731,7 +731,7 @@ static void fc_disc_stop_final(struct fc_lport *lport)
|
|||
*/
|
||||
void fc_disc_config(struct fc_lport *lport, void *priv)
|
||||
{
|
||||
struct fc_disc *disc = &lport->disc;
|
||||
struct fc_disc *disc;
|
||||
|
||||
if (!lport->tt.disc_start)
|
||||
lport->tt.disc_start = fc_disc_start;
|
||||
|
|
|
@ -709,7 +709,7 @@ void sas_resume_sata(struct asd_sas_port *port)
|
|||
}
|
||||
|
||||
/**
|
||||
* sas_discover_sata -- discover an STP/SATA domain device
|
||||
* sas_discover_sata - discover an STP/SATA domain device
|
||||
* @dev: pointer to struct domain_device of interest
|
||||
*
|
||||
* Devices directly attached to a HA port, have no parents. All other
|
||||
|
|
|
@ -55,7 +55,7 @@ void sas_init_dev(struct domain_device *dev)
|
|||
/* ---------- Domain device discovery ---------- */
|
||||
|
||||
/**
|
||||
* sas_get_port_device -- Discover devices which caused port creation
|
||||
* sas_get_port_device - Discover devices which caused port creation
|
||||
* @port: pointer to struct sas_port of interest
|
||||
*
|
||||
* Devices directly attached to a HA port, have no parent. This is
|
||||
|
@ -278,8 +278,8 @@ static void sas_resume_devices(struct work_struct *work)
|
|||
}
|
||||
|
||||
/**
|
||||
* sas_discover_end_dev -- discover an end device (SSP, etc)
|
||||
* @end: pointer to domain device of interest
|
||||
* sas_discover_end_dev - discover an end device (SSP, etc)
|
||||
* @dev: pointer to domain device of interest
|
||||
*
|
||||
* See comment in sas_discover_sata().
|
||||
*/
|
||||
|
@ -428,8 +428,8 @@ void sas_device_set_phy(struct domain_device *dev, struct sas_port *port)
|
|||
/* ---------- Discovery and Revalidation ---------- */
|
||||
|
||||
/**
|
||||
* sas_discover_domain -- discover the domain
|
||||
* @port: port to the domain of interest
|
||||
* sas_discover_domain - discover the domain
|
||||
* @work: work structure embedded in port domain device.
|
||||
*
|
||||
* NOTE: this process _must_ quit (return) as soon as any connection
|
||||
* errors are encountered. Connection recovery is done elsewhere.
|
||||
|
@ -572,7 +572,8 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev)
|
|||
}
|
||||
|
||||
/**
|
||||
* sas_init_disc -- initialize the discovery struct in the port
|
||||
* sas_init_disc - initialize the discovery struct in the port
|
||||
* @disc: port discovery structure
|
||||
* @port: pointer to struct port
|
||||
*
|
||||
* Called when the ports are being initialized.
|
||||
|
|
|
@ -1170,9 +1170,9 @@ static int sas_check_level_subtractive_boundary(struct domain_device *dev)
|
|||
return 0;
|
||||
}
|
||||
/**
|
||||
* sas_ex_discover_devices -- discover devices attached to this expander
|
||||
* dev: pointer to the expander domain device
|
||||
* single: if you want to do a single phy, else set to -1;
|
||||
* sas_ex_discover_devices - discover devices attached to this expander
|
||||
* @dev: pointer to the expander domain device
|
||||
* @single: if you want to do a single phy, else set to -1;
|
||||
*
|
||||
* Configure this expander for use with its devices and register the
|
||||
* devices of this expander.
|
||||
|
@ -1528,10 +1528,11 @@ static int sas_configure_phy(struct domain_device *dev, int phy_id,
|
|||
}
|
||||
|
||||
/**
|
||||
* sas_configure_parent -- configure routing table of parent
|
||||
* parent: parent expander
|
||||
* child: child expander
|
||||
* sas_addr: SAS port identifier of device directly attached to child
|
||||
* sas_configure_parent - configure routing table of parent
|
||||
* @parent: parent expander
|
||||
* @child: child expander
|
||||
* @sas_addr: SAS port identifier of device directly attached to child
|
||||
* @include: whether or not to include @child in the expander routing table
|
||||
*/
|
||||
static int sas_configure_parent(struct domain_device *parent,
|
||||
struct domain_device *child,
|
||||
|
@ -1570,9 +1571,9 @@ static int sas_configure_parent(struct domain_device *parent,
|
|||
}
|
||||
|
||||
/**
|
||||
* sas_configure_routing -- configure routing
|
||||
* dev: expander device
|
||||
* sas_addr: port identifier of device directly attached to the expander device
|
||||
* sas_configure_routing - configure routing
|
||||
* @dev: expander device
|
||||
* @sas_addr: port identifier of device directly attached to the expander device
|
||||
*/
|
||||
static int sas_configure_routing(struct domain_device *dev, u8 *sas_addr)
|
||||
{
|
||||
|
@ -1589,8 +1590,8 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr)
|
|||
}
|
||||
|
||||
/**
|
||||
* sas_discover_expander -- expander discovery
|
||||
* @ex: pointer to expander domain device
|
||||
* sas_discover_expander - expander discovery
|
||||
* @dev: pointer to expander domain device
|
||||
*
|
||||
* See comment in sas_discover_sata().
|
||||
*/
|
||||
|
@ -2111,8 +2112,8 @@ static int sas_rediscover(struct domain_device *dev, const int phy_id)
|
|||
}
|
||||
|
||||
/**
|
||||
* sas_revalidate_domain -- revalidate the domain
|
||||
* @port: port to the domain of interest
|
||||
* sas_ex_revalidate_domain - revalidate the domain
|
||||
* @port_dev: port domain device.
|
||||
*
|
||||
* NOTE: this process _must_ quit (return) as soon as any connection
|
||||
* errors are encountered. Connection recovery is done elsewhere.
|
||||
|
|
|
@ -234,7 +234,7 @@ int sas_try_ata_reset(struct asd_sas_phy *asd_phy)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* transport_sas_phy_reset - reset a phy and permit libata to manage the link
|
||||
*
|
||||
* phy reset request via sysfs in host workqueue context so we know we
|
||||
|
|
|
@ -84,7 +84,7 @@ static void sas_resume_port(struct asd_sas_phy *phy)
|
|||
}
|
||||
|
||||
/**
|
||||
* sas_form_port -- add this phy to a port
|
||||
* sas_form_port - add this phy to a port
|
||||
* @phy: the phy of interest
|
||||
*
|
||||
* This function adds this phy to an existing port, thus creating a wide
|
||||
|
@ -197,8 +197,9 @@ static void sas_form_port(struct asd_sas_phy *phy)
|
|||
}
|
||||
|
||||
/**
|
||||
* sas_deform_port -- remove this phy from the port it belongs to
|
||||
* sas_deform_port - remove this phy from the port it belongs to
|
||||
* @phy: the phy of interest
|
||||
* @gone: whether or not the PHY is gone
|
||||
*
|
||||
* This is called when the physical link to the other phy has been
|
||||
* lost (on this phy), in Event thread context. We cannot delay here.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -544,16 +544,10 @@ struct unsol_rcv_ct_ctx {
|
|||
#define LPFC_USER_LINK_SPEED_10G 10 /* 10 Gigabaud */
|
||||
#define LPFC_USER_LINK_SPEED_16G 16 /* 16 Gigabaud */
|
||||
#define LPFC_USER_LINK_SPEED_32G 32 /* 32 Gigabaud */
|
||||
#define LPFC_USER_LINK_SPEED_MAX LPFC_USER_LINK_SPEED_32G
|
||||
#define LPFC_USER_LINK_SPEED_BITMAP ((1ULL << LPFC_USER_LINK_SPEED_32G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_16G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_10G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_8G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_4G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_2G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_1G) | \
|
||||
(1 << LPFC_USER_LINK_SPEED_AUTO))
|
||||
#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16, 32"
|
||||
#define LPFC_USER_LINK_SPEED_64G 64 /* 64 Gigabaud */
|
||||
#define LPFC_USER_LINK_SPEED_MAX LPFC_USER_LINK_SPEED_64G
|
||||
|
||||
#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16, 32, 64"
|
||||
|
||||
enum nemb_type {
|
||||
nemb_mse = 1,
|
||||
|
@ -760,6 +754,7 @@ struct lpfc_hba {
|
|||
uint8_t mds_diags_support;
|
||||
uint32_t initial_imax;
|
||||
uint8_t bbcredit_support;
|
||||
uint8_t enab_exp_wqcq_pages;
|
||||
|
||||
/* HBA Config Parameters */
|
||||
uint32_t cfg_ack0;
|
||||
|
@ -787,6 +782,7 @@ struct lpfc_hba {
|
|||
uint32_t cfg_fcp_io_channel;
|
||||
uint32_t cfg_suppress_rsp;
|
||||
uint32_t cfg_nvme_oas;
|
||||
uint32_t cfg_nvme_embed_cmd;
|
||||
uint32_t cfg_nvme_io_channel;
|
||||
uint32_t cfg_nvmet_mrq;
|
||||
uint32_t cfg_enable_nvmet;
|
||||
|
@ -839,11 +835,14 @@ struct lpfc_hba {
|
|||
uint32_t cfg_enable_SmartSAN;
|
||||
uint32_t cfg_enable_mds_diags;
|
||||
uint32_t cfg_enable_fc4_type;
|
||||
uint32_t cfg_enable_bbcr; /*Enable BB Credit Recovery*/
|
||||
uint32_t cfg_enable_bbcr; /* Enable BB Credit Recovery */
|
||||
uint32_t cfg_enable_dpp; /* Enable Direct Packet Push */
|
||||
uint32_t cfg_xri_split;
|
||||
#define LPFC_ENABLE_FCP 1
|
||||
#define LPFC_ENABLE_NVME 2
|
||||
#define LPFC_ENABLE_BOTH 3
|
||||
uint32_t nvme_embed_pbde;
|
||||
uint32_t fcp_embed_pbde;
|
||||
uint32_t io_channel_irqs; /* number of irqs for io channels */
|
||||
struct nvmet_fc_target_port *targetport;
|
||||
lpfc_vpd_t vpd; /* vital product data */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -259,6 +259,12 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
|
|||
atomic_read(&tgtp->xmt_abort_rsp),
|
||||
atomic_read(&tgtp->xmt_abort_rsp_error));
|
||||
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
"DELAY: ctx %08x fod %08x wqfull %08x\n",
|
||||
atomic_read(&tgtp->defer_ctx),
|
||||
atomic_read(&tgtp->defer_fod),
|
||||
atomic_read(&tgtp->defer_wqfull));
|
||||
|
||||
/* Calculate outstanding IOs */
|
||||
tot = atomic_read(&tgtp->rcv_fcp_cmd_drop);
|
||||
tot += atomic_read(&tgtp->xmt_fcp_release);
|
||||
|
@ -905,7 +911,12 @@ lpfc_issue_lip(struct Scsi_Host *shost)
|
|||
LPFC_MBOXQ_t *pmboxq;
|
||||
int mbxstatus = MBXERR_ERROR;
|
||||
|
||||
/*
|
||||
* If the link is offline, disabled or BLOCK_MGMT_IO
|
||||
* it doesn't make any sense to allow issue_lip
|
||||
*/
|
||||
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
|
||||
(phba->hba_flag & LINK_DISABLED) ||
|
||||
(phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO))
|
||||
return -EPERM;
|
||||
|
||||
|
@ -3458,7 +3469,7 @@ LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 512,
|
|||
# tgt_queue_depth: This parameter is used to limit the number of outstanding
|
||||
# commands per target port. Value range is [10,65535]. Default value is 65535.
|
||||
*/
|
||||
LPFC_VPORT_ATTR_R(tgt_queue_depth, 65535, 10, 65535,
|
||||
LPFC_VPORT_ATTR_RW(tgt_queue_depth, 65535, 10, 65535,
|
||||
"Max number of FCP commands we can queue to a specific target port");
|
||||
|
||||
/*
|
||||
|
@ -4104,14 +4115,15 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
|
|||
((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) ||
|
||||
((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) ||
|
||||
((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb)) ||
|
||||
((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb))) {
|
||||
((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb)) ||
|
||||
((val == LPFC_USER_LINK_SPEED_64G) && !(phba->lmt & LMT_64Gb))) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"2879 lpfc_link_speed attribute cannot be set "
|
||||
"to %d. Speed is not supported by this port.\n",
|
||||
val);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (val == LPFC_USER_LINK_SPEED_16G &&
|
||||
if (val >= LPFC_USER_LINK_SPEED_16G &&
|
||||
phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"3112 lpfc_link_speed attribute cannot be set "
|
||||
|
@ -4119,8 +4131,16 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
|
|||
val);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) &&
|
||||
(LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {
|
||||
|
||||
switch (val) {
|
||||
case LPFC_USER_LINK_SPEED_AUTO:
|
||||
case LPFC_USER_LINK_SPEED_1G:
|
||||
case LPFC_USER_LINK_SPEED_2G:
|
||||
case LPFC_USER_LINK_SPEED_4G:
|
||||
case LPFC_USER_LINK_SPEED_8G:
|
||||
case LPFC_USER_LINK_SPEED_16G:
|
||||
case LPFC_USER_LINK_SPEED_32G:
|
||||
case LPFC_USER_LINK_SPEED_64G:
|
||||
prev_val = phba->cfg_link_speed;
|
||||
phba->cfg_link_speed = val;
|
||||
if (nolip)
|
||||
|
@ -4130,13 +4150,18 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
|
|||
if (err) {
|
||||
phba->cfg_link_speed = prev_val;
|
||||
return -EINVAL;
|
||||
} else
|
||||
return strlen(buf);
|
||||
}
|
||||
return strlen(buf);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"0469 lpfc_link_speed attribute cannot be set to %d, "
|
||||
"allowed values are ["LPFC_LINK_SPEED_STRING"]\n", val);
|
||||
"allowed values are [%s]\n",
|
||||
val, LPFC_LINK_SPEED_STRING);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
static int lpfc_link_speed = 0;
|
||||
|
@ -4163,24 +4188,33 @@ lpfc_param_show(link_speed)
|
|||
static int
|
||||
lpfc_link_speed_init(struct lpfc_hba *phba, int val)
|
||||
{
|
||||
if (val == LPFC_USER_LINK_SPEED_16G && phba->cfg_topology == 4) {
|
||||
if (val >= LPFC_USER_LINK_SPEED_16G && phba->cfg_topology == 4) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"3111 lpfc_link_speed of %d cannot "
|
||||
"support loop mode, setting topology to default.\n",
|
||||
val);
|
||||
phba->cfg_topology = 0;
|
||||
}
|
||||
if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) &&
|
||||
(LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {
|
||||
|
||||
switch (val) {
|
||||
case LPFC_USER_LINK_SPEED_AUTO:
|
||||
case LPFC_USER_LINK_SPEED_1G:
|
||||
case LPFC_USER_LINK_SPEED_2G:
|
||||
case LPFC_USER_LINK_SPEED_4G:
|
||||
case LPFC_USER_LINK_SPEED_8G:
|
||||
case LPFC_USER_LINK_SPEED_16G:
|
||||
case LPFC_USER_LINK_SPEED_32G:
|
||||
case LPFC_USER_LINK_SPEED_64G:
|
||||
phba->cfg_link_speed = val;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"0405 lpfc_link_speed attribute cannot "
|
||||
"be set to %d, allowed values are "
|
||||
"["LPFC_LINK_SPEED_STRING"]\n", val);
|
||||
phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(lpfc_link_speed);
|
||||
|
@ -5007,6 +5041,18 @@ LPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or "
|
|||
LPFC_ATTR_RW(nvme_oas, 0, 0, 1,
|
||||
"Use OAS bit on NVME IOs");
|
||||
|
||||
/*
|
||||
* lpfc_nvme_embed_cmd: Use the oas bit when sending NVME/NVMET IOs
|
||||
*
|
||||
* 0 = Put NVME Command in SGL
|
||||
* 1 = Embed NVME Command in WQE (unless G7)
|
||||
* 2 = Embed NVME Command in WQE (force)
|
||||
*
|
||||
* Value range is [0,2]. Default value is 1.
|
||||
*/
|
||||
LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2,
|
||||
"Embed NVME Command in WQE");
|
||||
|
||||
/*
|
||||
* lpfc_fcp_io_channel: Set the number of FCP IO channels the driver
|
||||
* will advertise it supports to the SCSI layer. This also will map to
|
||||
|
@ -5175,6 +5221,14 @@ LPFC_ATTR_R(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics");
|
|||
*/
|
||||
LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery");
|
||||
|
||||
/*
|
||||
* lpfc_enable_dpp: Enable DPP on G7
|
||||
* 0 = DPP on G7 disabled
|
||||
* 1 = DPP on G7 enabled (default)
|
||||
* Value range is [0,1]. Default value is 1.
|
||||
*/
|
||||
LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push");
|
||||
|
||||
struct device_attribute *lpfc_hba_attrs[] = {
|
||||
&dev_attr_nvme_info,
|
||||
&dev_attr_bg_info,
|
||||
|
@ -5240,6 +5294,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
|
|||
&dev_attr_lpfc_task_mgmt_tmo,
|
||||
&dev_attr_lpfc_use_msi,
|
||||
&dev_attr_lpfc_nvme_oas,
|
||||
&dev_attr_lpfc_nvme_embed_cmd,
|
||||
&dev_attr_lpfc_auto_imax,
|
||||
&dev_attr_lpfc_fcp_imax,
|
||||
&dev_attr_lpfc_fcp_cpu_map,
|
||||
|
@ -5283,6 +5338,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
|
|||
&dev_attr_lpfc_xlane_supported,
|
||||
&dev_attr_lpfc_enable_mds_diags,
|
||||
&dev_attr_lpfc_enable_bbcr,
|
||||
&dev_attr_lpfc_enable_dpp,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -5696,6 +5752,9 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
|
|||
case LPFC_LINK_SPEED_32GHZ:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_32GBIT;
|
||||
break;
|
||||
case LPFC_LINK_SPEED_64GHZ:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_64GBIT;
|
||||
break;
|
||||
default:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
|
||||
break;
|
||||
|
@ -6260,6 +6319,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
|||
lpfc_enable_SmartSAN_init(phba, lpfc_enable_SmartSAN);
|
||||
lpfc_use_msi_init(phba, lpfc_use_msi);
|
||||
lpfc_nvme_oas_init(phba, lpfc_nvme_oas);
|
||||
lpfc_nvme_embed_cmd_init(phba, lpfc_nvme_embed_cmd);
|
||||
lpfc_auto_imax_init(phba, lpfc_auto_imax);
|
||||
lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
|
||||
lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map);
|
||||
|
@ -6284,6 +6344,10 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
|||
phba->cfg_poll = 0;
|
||||
else
|
||||
phba->cfg_poll = lpfc_poll;
|
||||
|
||||
if (phba->cfg_enable_bg)
|
||||
phba->sli3_options |= LPFC_SLI3_BG_ENABLED;
|
||||
|
||||
lpfc_suppress_rsp_init(phba, lpfc_suppress_rsp);
|
||||
|
||||
lpfc_enable_fc4_type_init(phba, lpfc_enable_fc4_type);
|
||||
|
@ -6295,6 +6359,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
|||
lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel);
|
||||
lpfc_nvme_io_channel_init(phba, lpfc_nvme_io_channel);
|
||||
lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
|
||||
lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
|
||||
|
||||
if (phba->sli_rev != LPFC_SLI_REV4) {
|
||||
/* NVME only supported on SLI4 */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2009-2015 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -3867,7 +3867,7 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,
|
|||
"ext_buf_cnt:%d\n", ext_buf_cnt);
|
||||
} else {
|
||||
/* sanity check on interface type for support */
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <
|
||||
LPFC_SLI_INTF_IF_TYPE_2) {
|
||||
rc = -ENODEV;
|
||||
goto job_error;
|
||||
|
@ -4053,7 +4053,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,
|
|||
"ext_buf_cnt:%d\n", ext_buf_cnt);
|
||||
} else {
|
||||
/* sanity check on interface type for support */
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <
|
||||
LPFC_SLI_INTF_IF_TYPE_2)
|
||||
return -ENODEV;
|
||||
/* nemb_tp == nemb_hbd */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -254,6 +254,7 @@ void lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba,
|
|||
struct lpfc_nvmet_ctxbuf *ctxp);
|
||||
int lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport,
|
||||
struct fc_frame_header *fc_hdr);
|
||||
void lpfc_nvmet_wqfull_process(struct lpfc_hba *phba, struct lpfc_queue *wq);
|
||||
void lpfc_sli_flush_nvme_rings(struct lpfc_hba *phba);
|
||||
void lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba);
|
||||
void lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *, struct fcf_record *,
|
||||
|
@ -564,6 +565,8 @@ void lpfc_nvme_mod_param_dep(struct lpfc_hba *phba);
|
|||
void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba,
|
||||
struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_wcqe_complete *abts_cmpl);
|
||||
void lpfc_nvme_cmd_template(void);
|
||||
void lpfc_nvmet_cmd_template(void);
|
||||
extern int lpfc_enable_nvmet_cnt;
|
||||
extern unsigned long long lpfc_enable_nvmet[];
|
||||
extern int lpfc_no_hba_reset_cnt;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -471,7 +471,6 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type)
|
|||
"Parse GID_FTrsp: did:x%x flg:x%x x%x",
|
||||
Did, ndlp->nlp_flag, vport->fc_flag);
|
||||
|
||||
ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);
|
||||
/* By default, the driver expects to support FCP FC4 */
|
||||
if (fc4_type == FC_TYPE_FCP)
|
||||
ndlp->nlp_fc4_type |= NLP_FC4_FCP;
|
||||
|
@ -2130,6 +2129,8 @@ lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport,
|
|||
|
||||
ae->un.AttrInt = 0;
|
||||
if (!(phba->hba_flag & HBA_FCOE_MODE)) {
|
||||
if (phba->lmt & LMT_64Gb)
|
||||
ae->un.AttrInt |= HBA_PORTSPEED_64GFC;
|
||||
if (phba->lmt & LMT_32Gb)
|
||||
ae->un.AttrInt |= HBA_PORTSPEED_32GFC;
|
||||
if (phba->lmt & LMT_16Gb)
|
||||
|
@ -2201,6 +2202,9 @@ lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport,
|
|||
case LPFC_LINK_SPEED_32GHZ:
|
||||
ae->un.AttrInt = HBA_PORTSPEED_32GFC;
|
||||
break;
|
||||
case LPFC_LINK_SPEED_64GHZ:
|
||||
ae->un.AttrInt = HBA_PORTSPEED_64GFC;
|
||||
break;
|
||||
default:
|
||||
ae->un.AttrInt = HBA_PORTSPEED_UNKNOWN;
|
||||
break;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2007-2015 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -3944,10 +3944,15 @@ lpfc_idiag_drbacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
|
|||
return 0;
|
||||
|
||||
switch (drbregid) {
|
||||
case LPFC_DRB_EQCQ:
|
||||
len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
|
||||
"EQCQ-DRB-REG: 0x%08x\n",
|
||||
readl(phba->sli4_hba.EQCQDBregaddr));
|
||||
case LPFC_DRB_EQ:
|
||||
len += snprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE-len,
|
||||
"EQ-DRB-REG: 0x%08x\n",
|
||||
readl(phba->sli4_hba.EQDBregaddr));
|
||||
break;
|
||||
case LPFC_DRB_CQ:
|
||||
len += snprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE - len,
|
||||
"CQ-DRB-REG: 0x%08x\n",
|
||||
readl(phba->sli4_hba.CQDBregaddr));
|
||||
break;
|
||||
case LPFC_DRB_MQ:
|
||||
len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
|
||||
|
@ -4086,8 +4091,11 @@ lpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
|
|||
idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
|
||||
idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
|
||||
switch (drb_reg_id) {
|
||||
case LPFC_DRB_EQCQ:
|
||||
drb_reg = phba->sli4_hba.EQCQDBregaddr;
|
||||
case LPFC_DRB_EQ:
|
||||
drb_reg = phba->sli4_hba.EQDBregaddr;
|
||||
break;
|
||||
case LPFC_DRB_CQ:
|
||||
drb_reg = phba->sli4_hba.CQDBregaddr;
|
||||
break;
|
||||
case LPFC_DRB_MQ:
|
||||
drb_reg = phba->sli4_hba.MQDBregaddr;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2007-2011 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -126,12 +126,13 @@
|
|||
#define LPFC_DRB_ACC_WR_CMD_ARG 2
|
||||
#define LPFC_DRB_ACC_BUF_SIZE 256
|
||||
|
||||
#define LPFC_DRB_EQCQ 1
|
||||
#define LPFC_DRB_MQ 2
|
||||
#define LPFC_DRB_WQ 3
|
||||
#define LPFC_DRB_RQ 4
|
||||
#define LPFC_DRB_EQ 1
|
||||
#define LPFC_DRB_CQ 2
|
||||
#define LPFC_DRB_MQ 3
|
||||
#define LPFC_DRB_WQ 4
|
||||
#define LPFC_DRB_RQ 5
|
||||
|
||||
#define LPFC_DRB_MAX 4
|
||||
#define LPFC_DRB_MAX 5
|
||||
|
||||
#define IDIAG_DRBACC_REGID_INDX 0
|
||||
#define IDIAG_DRBACC_VALUE_INDX 1
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -1661,6 +1661,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
|
|||
if (ndlp->nrport) {
|
||||
ndlp->nrport = NULL;
|
||||
lpfc_nlp_put(ndlp);
|
||||
new_ndlp->nlp_fc4_type = ndlp->nlp_fc4_type;
|
||||
}
|
||||
|
||||
/* We shall actually free the ndlp with both nlp_DID and
|
||||
|
@ -2293,10 +2294,11 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
|||
if (phba->nvmet_support) {
|
||||
bf_set(prli_tgt, npr_nvme, 1);
|
||||
bf_set(prli_disc, npr_nvme, 1);
|
||||
|
||||
} else {
|
||||
bf_set(prli_init, npr_nvme, 1);
|
||||
bf_set(prli_conf, npr_nvme, 1);
|
||||
}
|
||||
|
||||
npr_nvme->word1 = cpu_to_be32(npr_nvme->word1);
|
||||
npr_nvme->word4 = cpu_to_be32(npr_nvme->word4);
|
||||
elsiocb->iocb_flag |= LPFC_PRLI_NVME_REQ;
|
||||
|
@ -5269,6 +5271,9 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
|
|||
case LPFC_LINK_SPEED_32GHZ:
|
||||
rdp_speed = RDP_PS_32GB;
|
||||
break;
|
||||
case LPFC_LINK_SPEED_64GHZ:
|
||||
rdp_speed = RDP_PS_64GB;
|
||||
break;
|
||||
default:
|
||||
rdp_speed = RDP_PS_UNKNOWN;
|
||||
break;
|
||||
|
@ -5276,6 +5281,8 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
|
|||
|
||||
desc->info.port_speed.speed = cpu_to_be16(rdp_speed);
|
||||
|
||||
if (phba->lmt & LMT_64Gb)
|
||||
rdp_cap |= RDP_PS_64GB;
|
||||
if (phba->lmt & LMT_32Gb)
|
||||
rdp_cap |= RDP_PS_32GB;
|
||||
if (phba->lmt & LMT_16Gb)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -696,7 +696,8 @@ lpfc_work_done(struct lpfc_hba *phba)
|
|||
phba->hba_flag & HBA_SP_QUEUE_EVT)) {
|
||||
if (pring->flag & LPFC_STOP_IOCB_EVENT) {
|
||||
pring->flag |= LPFC_DEFERRED_RING_EVENT;
|
||||
/* Set the lpfc data pending flag */
|
||||
/* Preserve legacy behavior. */
|
||||
if (!(phba->hba_flag & HBA_SP_QUEUE_EVT))
|
||||
set_bit(LPFC_DATA_READY, &phba->data_flags);
|
||||
} else {
|
||||
if (phba->link_state >= LPFC_LINK_UP ||
|
||||
|
@ -958,6 +959,7 @@ lpfc_linkup_cleanup_nodes(struct lpfc_vport *vport)
|
|||
struct lpfc_nodelist *ndlp;
|
||||
|
||||
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
|
||||
ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);
|
||||
if (!NLP_CHK_NODE_ACT(ndlp))
|
||||
continue;
|
||||
if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
|
||||
|
@ -3083,6 +3085,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
|
|||
case LPFC_LINK_SPEED_10GHZ:
|
||||
case LPFC_LINK_SPEED_16GHZ:
|
||||
case LPFC_LINK_SPEED_32GHZ:
|
||||
case LPFC_LINK_SPEED_64GHZ:
|
||||
break;
|
||||
default:
|
||||
phba->fc_linkspeed = LPFC_LINK_SPEED_UNKNOWN;
|
||||
|
@ -3873,6 +3876,10 @@ int
|
|||
lpfc_issue_gidft(struct lpfc_vport *vport)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
|
||||
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)
|
||||
ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);
|
||||
|
||||
/* Good status, issue CT Request to NameServer */
|
||||
if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -1177,6 +1177,9 @@ struct fc_rdp_link_error_status_desc {
|
|||
#define RDP_PS_8GB 0x0800
|
||||
#define RDP_PS_16GB 0x0400
|
||||
#define RDP_PS_32GB 0x0200
|
||||
#define RDP_PS_64GB 0x0100
|
||||
#define RDP_PS_128GB 0x0080
|
||||
#define RDP_PS_256GB 0x0040
|
||||
|
||||
#define RDP_CAP_USER_CONFIGURED 0x0002
|
||||
#define RDP_CAP_UNKNOWN 0x0001
|
||||
|
@ -1580,6 +1583,7 @@ struct lpfc_fdmi_reg_portattr {
|
|||
#define PCI_DEVICE_ID_LANCER_FCOE 0xe260
|
||||
#define PCI_DEVICE_ID_LANCER_FCOE_VF 0xe268
|
||||
#define PCI_DEVICE_ID_LANCER_G6_FC 0xe300
|
||||
#define PCI_DEVICE_ID_LANCER_G7_FC 0xf400
|
||||
#define PCI_DEVICE_ID_SAT_SMB 0xf011
|
||||
#define PCI_DEVICE_ID_SAT_MID 0xf015
|
||||
#define PCI_DEVICE_ID_RFLY 0xf095
|
||||
|
@ -2257,6 +2261,9 @@ typedef struct {
|
|||
#define LINK_SPEED_10G 0x10 /* 10 Gigabaud */
|
||||
#define LINK_SPEED_16G 0x11 /* 16 Gigabaud */
|
||||
#define LINK_SPEED_32G 0x14 /* 32 Gigabaud */
|
||||
#define LINK_SPEED_64G 0x17 /* 64 Gigabaud */
|
||||
#define LINK_SPEED_128G 0x1A /* 128 Gigabaud */
|
||||
#define LINK_SPEED_256G 0x1D /* 256 Gigabaud */
|
||||
|
||||
} INIT_LINK_VAR;
|
||||
|
||||
|
@ -2441,6 +2448,9 @@ typedef struct {
|
|||
#define LMT_10Gb 0x100
|
||||
#define LMT_16Gb 0x200
|
||||
#define LMT_32Gb 0x400
|
||||
#define LMT_64Gb 0x800
|
||||
#define LMT_128Gb 0x1000
|
||||
#define LMT_256Gb 0x2000
|
||||
uint32_t rsvd2;
|
||||
uint32_t rsvd3;
|
||||
uint32_t max_xri;
|
||||
|
@ -2965,6 +2975,9 @@ struct lpfc_mbx_read_top {
|
|||
#define LPFC_LINK_SPEED_10GHZ 0x40
|
||||
#define LPFC_LINK_SPEED_16GHZ 0x80
|
||||
#define LPFC_LINK_SPEED_32GHZ 0x90
|
||||
#define LPFC_LINK_SPEED_64GHZ 0xA0
|
||||
#define LPFC_LINK_SPEED_128GHZ 0xB0
|
||||
#define LPFC_LINK_SPEED_256GHZ 0xC0
|
||||
};
|
||||
|
||||
/* Structure for MB Command CLEAR_LA (22) */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2009-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -84,6 +84,7 @@ struct lpfc_sli_intf {
|
|||
#define LPFC_SLI_INTF_IF_TYPE_0 0
|
||||
#define LPFC_SLI_INTF_IF_TYPE_1 1
|
||||
#define LPFC_SLI_INTF_IF_TYPE_2 2
|
||||
#define LPFC_SLI_INTF_IF_TYPE_6 6
|
||||
#define lpfc_sli_intf_sli_family_SHIFT 8
|
||||
#define lpfc_sli_intf_sli_family_MASK 0x0000000F
|
||||
#define lpfc_sli_intf_sli_family_WORD word0
|
||||
|
@ -731,11 +732,13 @@ struct lpfc_register {
|
|||
* register sets depending on the UCNA Port's reported if_type
|
||||
* value. For UCNA ports running SLI4 and if_type 0, they reside in
|
||||
* BAR4. For UCNA ports running SLI4 and if_type 2, they reside in
|
||||
* BAR0. The offsets are the same so the driver must account for
|
||||
* any base address difference.
|
||||
* BAR0. For FC ports running SLI4 and if_type 6, they reside in
|
||||
* BAR2. The offsets and base address are different, so the driver
|
||||
* has to compute the register addresses accordingly
|
||||
*/
|
||||
#define LPFC_ULP0_RQ_DOORBELL 0x00A0
|
||||
#define LPFC_ULP1_RQ_DOORBELL 0x00C0
|
||||
#define LPFC_IF6_RQ_DOORBELL 0x0080
|
||||
#define lpfc_rq_db_list_fm_num_posted_SHIFT 24
|
||||
#define lpfc_rq_db_list_fm_num_posted_MASK 0x00FF
|
||||
#define lpfc_rq_db_list_fm_num_posted_WORD word0
|
||||
|
@ -770,6 +773,20 @@ struct lpfc_register {
|
|||
#define lpfc_wq_db_ring_fm_id_MASK 0xFFFF
|
||||
#define lpfc_wq_db_ring_fm_id_WORD word0
|
||||
|
||||
#define LPFC_IF6_WQ_DOORBELL 0x0040
|
||||
#define lpfc_if6_wq_db_list_fm_num_posted_SHIFT 24
|
||||
#define lpfc_if6_wq_db_list_fm_num_posted_MASK 0x00FF
|
||||
#define lpfc_if6_wq_db_list_fm_num_posted_WORD word0
|
||||
#define lpfc_if6_wq_db_list_fm_dpp_SHIFT 23
|
||||
#define lpfc_if6_wq_db_list_fm_dpp_MASK 0x0001
|
||||
#define lpfc_if6_wq_db_list_fm_dpp_WORD word0
|
||||
#define lpfc_if6_wq_db_list_fm_dpp_id_SHIFT 16
|
||||
#define lpfc_if6_wq_db_list_fm_dpp_id_MASK 0x001F
|
||||
#define lpfc_if6_wq_db_list_fm_dpp_id_WORD word0
|
||||
#define lpfc_if6_wq_db_list_fm_id_SHIFT 0
|
||||
#define lpfc_if6_wq_db_list_fm_id_MASK 0xFFFF
|
||||
#define lpfc_if6_wq_db_list_fm_id_WORD word0
|
||||
|
||||
#define LPFC_EQCQ_DOORBELL 0x0120
|
||||
#define lpfc_eqcq_doorbell_se_SHIFT 31
|
||||
#define lpfc_eqcq_doorbell_se_MASK 0x0001
|
||||
|
@ -805,6 +822,38 @@ struct lpfc_register {
|
|||
#define LPFC_CQID_HI_FIELD_SHIFT 10
|
||||
#define LPFC_EQID_HI_FIELD_SHIFT 9
|
||||
|
||||
#define LPFC_IF6_CQ_DOORBELL 0x00C0
|
||||
#define lpfc_if6_cq_doorbell_se_SHIFT 31
|
||||
#define lpfc_if6_cq_doorbell_se_MASK 0x0001
|
||||
#define lpfc_if6_cq_doorbell_se_WORD word0
|
||||
#define LPFC_IF6_CQ_SOLICIT_ENABLE_OFF 0
|
||||
#define LPFC_IF6_CQ_SOLICIT_ENABLE_ON 1
|
||||
#define lpfc_if6_cq_doorbell_arm_SHIFT 29
|
||||
#define lpfc_if6_cq_doorbell_arm_MASK 0x0001
|
||||
#define lpfc_if6_cq_doorbell_arm_WORD word0
|
||||
#define lpfc_if6_cq_doorbell_num_released_SHIFT 16
|
||||
#define lpfc_if6_cq_doorbell_num_released_MASK 0x1FFF
|
||||
#define lpfc_if6_cq_doorbell_num_released_WORD word0
|
||||
#define lpfc_if6_cq_doorbell_cqid_SHIFT 0
|
||||
#define lpfc_if6_cq_doorbell_cqid_MASK 0xFFFF
|
||||
#define lpfc_if6_cq_doorbell_cqid_WORD word0
|
||||
|
||||
#define LPFC_IF6_EQ_DOORBELL 0x0120
|
||||
#define lpfc_if6_eq_doorbell_io_SHIFT 31
|
||||
#define lpfc_if6_eq_doorbell_io_MASK 0x0001
|
||||
#define lpfc_if6_eq_doorbell_io_WORD word0
|
||||
#define LPFC_IF6_EQ_INTR_OVERRIDE_OFF 0
|
||||
#define LPFC_IF6_EQ_INTR_OVERRIDE_ON 1
|
||||
#define lpfc_if6_eq_doorbell_arm_SHIFT 29
|
||||
#define lpfc_if6_eq_doorbell_arm_MASK 0x0001
|
||||
#define lpfc_if6_eq_doorbell_arm_WORD word0
|
||||
#define lpfc_if6_eq_doorbell_num_released_SHIFT 16
|
||||
#define lpfc_if6_eq_doorbell_num_released_MASK 0x1FFF
|
||||
#define lpfc_if6_eq_doorbell_num_released_WORD word0
|
||||
#define lpfc_if6_eq_doorbell_eqid_SHIFT 0
|
||||
#define lpfc_if6_eq_doorbell_eqid_MASK 0x0FFF
|
||||
#define lpfc_if6_eq_doorbell_eqid_WORD word0
|
||||
|
||||
#define LPFC_BMBX 0x0160
|
||||
#define lpfc_bmbx_addr_SHIFT 2
|
||||
#define lpfc_bmbx_addr_MASK 0x3FFFFFFF
|
||||
|
@ -817,6 +866,7 @@ struct lpfc_register {
|
|||
#define lpfc_bmbx_rdy_WORD word0
|
||||
|
||||
#define LPFC_MQ_DOORBELL 0x0140
|
||||
#define LPFC_IF6_MQ_DOORBELL 0x0160
|
||||
#define lpfc_mq_doorbell_num_posted_SHIFT 16
|
||||
#define lpfc_mq_doorbell_num_posted_MASK 0x3FFF
|
||||
#define lpfc_mq_doorbell_num_posted_WORD word0
|
||||
|
@ -990,6 +1040,9 @@ struct eq_context {
|
|||
#define lpfc_eq_context_valid_SHIFT 29
|
||||
#define lpfc_eq_context_valid_MASK 0x00000001
|
||||
#define lpfc_eq_context_valid_WORD word0
|
||||
#define lpfc_eq_context_autovalid_SHIFT 28
|
||||
#define lpfc_eq_context_autovalid_MASK 0x00000001
|
||||
#define lpfc_eq_context_autovalid_WORD word0
|
||||
uint32_t word1;
|
||||
#define lpfc_eq_context_count_SHIFT 26
|
||||
#define lpfc_eq_context_count_MASK 0x00000003
|
||||
|
@ -1123,6 +1176,9 @@ struct cq_context {
|
|||
#define LPFC_CQ_CNT_512 0x1
|
||||
#define LPFC_CQ_CNT_1024 0x2
|
||||
#define LPFC_CQ_CNT_WORD7 0x3
|
||||
#define lpfc_cq_context_autovalid_SHIFT 15
|
||||
#define lpfc_cq_context_autovalid_MASK 0x00000001
|
||||
#define lpfc_cq_context_autovalid_WORD word0
|
||||
uint32_t word1;
|
||||
#define lpfc_cq_eq_id_SHIFT 22 /* Version 0 Only */
|
||||
#define lpfc_cq_eq_id_MASK 0x000000FF
|
||||
|
@ -1181,9 +1237,9 @@ struct lpfc_mbx_cq_create_set {
|
|||
#define lpfc_mbx_cq_create_set_cqe_size_SHIFT 25
|
||||
#define lpfc_mbx_cq_create_set_cqe_size_MASK 0x00000003
|
||||
#define lpfc_mbx_cq_create_set_cqe_size_WORD word1
|
||||
#define lpfc_mbx_cq_create_set_auto_SHIFT 15
|
||||
#define lpfc_mbx_cq_create_set_auto_MASK 0x0000001
|
||||
#define lpfc_mbx_cq_create_set_auto_WORD word1
|
||||
#define lpfc_mbx_cq_create_set_autovalid_SHIFT 15
|
||||
#define lpfc_mbx_cq_create_set_autovalid_MASK 0x0000001
|
||||
#define lpfc_mbx_cq_create_set_autovalid_WORD word1
|
||||
#define lpfc_mbx_cq_create_set_nodelay_SHIFT 14
|
||||
#define lpfc_mbx_cq_create_set_nodelay_MASK 0x00000001
|
||||
#define lpfc_mbx_cq_create_set_nodelay_WORD word1
|
||||
|
@ -1322,6 +1378,15 @@ struct lpfc_mbx_wq_create {
|
|||
#define lpfc_mbx_wq_create_page_size_MASK 0x000000FF
|
||||
#define lpfc_mbx_wq_create_page_size_WORD word1
|
||||
#define LPFC_WQ_PAGE_SIZE_4096 0x1
|
||||
#define lpfc_mbx_wq_create_dpp_req_SHIFT 15
|
||||
#define lpfc_mbx_wq_create_dpp_req_MASK 0x00000001
|
||||
#define lpfc_mbx_wq_create_dpp_req_WORD word1
|
||||
#define lpfc_mbx_wq_create_doe_SHIFT 14
|
||||
#define lpfc_mbx_wq_create_doe_MASK 0x00000001
|
||||
#define lpfc_mbx_wq_create_doe_WORD word1
|
||||
#define lpfc_mbx_wq_create_toe_SHIFT 13
|
||||
#define lpfc_mbx_wq_create_toe_MASK 0x00000001
|
||||
#define lpfc_mbx_wq_create_toe_WORD word1
|
||||
#define lpfc_mbx_wq_create_wqe_size_SHIFT 8
|
||||
#define lpfc_mbx_wq_create_wqe_size_MASK 0x0000000F
|
||||
#define lpfc_mbx_wq_create_wqe_size_WORD word1
|
||||
|
@ -1350,6 +1415,28 @@ struct lpfc_mbx_wq_create {
|
|||
#define lpfc_mbx_wq_create_db_format_MASK 0x0000FFFF
|
||||
#define lpfc_mbx_wq_create_db_format_WORD word2
|
||||
} response;
|
||||
struct {
|
||||
uint32_t word0;
|
||||
#define lpfc_mbx_wq_create_dpp_rsp_SHIFT 31
|
||||
#define lpfc_mbx_wq_create_dpp_rsp_MASK 0x00000001
|
||||
#define lpfc_mbx_wq_create_dpp_rsp_WORD word0
|
||||
#define lpfc_mbx_wq_create_v1_q_id_SHIFT 0
|
||||
#define lpfc_mbx_wq_create_v1_q_id_MASK 0x0000FFFF
|
||||
#define lpfc_mbx_wq_create_v1_q_id_WORD word0
|
||||
uint32_t word1;
|
||||
#define lpfc_mbx_wq_create_v1_bar_set_SHIFT 0
|
||||
#define lpfc_mbx_wq_create_v1_bar_set_MASK 0x0000000F
|
||||
#define lpfc_mbx_wq_create_v1_bar_set_WORD word1
|
||||
uint32_t doorbell_offset;
|
||||
uint32_t word3;
|
||||
#define lpfc_mbx_wq_create_dpp_id_SHIFT 16
|
||||
#define lpfc_mbx_wq_create_dpp_id_MASK 0x0000001F
|
||||
#define lpfc_mbx_wq_create_dpp_id_WORD word3
|
||||
#define lpfc_mbx_wq_create_dpp_bar_SHIFT 0
|
||||
#define lpfc_mbx_wq_create_dpp_bar_MASK 0x0000000F
|
||||
#define lpfc_mbx_wq_create_dpp_bar_WORD word3
|
||||
uint32_t dpp_offset;
|
||||
} response_1;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
@ -2154,6 +2241,7 @@ struct lpfc_mbx_redisc_fcf_tbl {
|
|||
* command.
|
||||
*/
|
||||
#define ADD_STATUS_OPERATION_ALREADY_ACTIVE 0x67
|
||||
#define ADD_STATUS_FW_NOT_SUPPORTED 0xEB
|
||||
|
||||
struct lpfc_mbx_sli4_config {
|
||||
struct mbox_header header;
|
||||
|
@ -2590,6 +2678,7 @@ struct lpfc_mbx_read_rev {
|
|||
#define lpfc_mbx_rd_rev_vpd_MASK 0x00000001
|
||||
#define lpfc_mbx_rd_rev_vpd_WORD word1
|
||||
uint32_t first_hw_rev;
|
||||
#define LPFC_G7_ASIC_1 0xd
|
||||
uint32_t second_hw_rev;
|
||||
uint32_t word4_rsvd;
|
||||
uint32_t third_hw_rev;
|
||||
|
@ -3207,11 +3296,20 @@ struct lpfc_sli4_parameters {
|
|||
#define cfg_sli_hint_2_MASK 0x0000001f
|
||||
#define cfg_sli_hint_2_WORD word1
|
||||
uint32_t word2;
|
||||
#define cfg_eqav_SHIFT 31
|
||||
#define cfg_eqav_MASK 0x00000001
|
||||
#define cfg_eqav_WORD word2
|
||||
uint32_t word3;
|
||||
uint32_t word4;
|
||||
#define cfg_cqv_SHIFT 14
|
||||
#define cfg_cqv_MASK 0x00000003
|
||||
#define cfg_cqv_WORD word4
|
||||
#define cfg_cqpsize_SHIFT 16
|
||||
#define cfg_cqpsize_MASK 0x000000ff
|
||||
#define cfg_cqpsize_WORD word4
|
||||
#define cfg_cqav_SHIFT 31
|
||||
#define cfg_cqav_MASK 0x00000001
|
||||
#define cfg_cqav_WORD word4
|
||||
uint32_t word5;
|
||||
uint32_t word6;
|
||||
#define cfg_mqv_SHIFT 14
|
||||
|
@ -3290,6 +3388,9 @@ struct lpfc_sli4_parameters {
|
|||
#define cfg_eqdr_SHIFT 8
|
||||
#define cfg_eqdr_MASK 0x00000001
|
||||
#define cfg_eqdr_WORD word19
|
||||
#define cfg_nosr_SHIFT 9
|
||||
#define cfg_nosr_MASK 0x00000001
|
||||
#define cfg_nosr_WORD word19
|
||||
#define LPFC_NODELAY_MAX_IO 32
|
||||
};
|
||||
|
||||
|
@ -3874,6 +3975,9 @@ struct lpfc_acqe_fc_la {
|
|||
#define LPFC_FC_LA_SPEED_10G 0xA
|
||||
#define LPFC_FC_LA_SPEED_16G 0x10
|
||||
#define LPFC_FC_LA_SPEED_32G 0x20
|
||||
#define LPFC_FC_LA_SPEED_64G 0x21
|
||||
#define LPFC_FC_LA_SPEED_128G 0x22
|
||||
#define LPFC_FC_LA_SPEED_256G 0x23
|
||||
#define lpfc_acqe_fc_la_topology_SHIFT 16
|
||||
#define lpfc_acqe_fc_la_topology_MASK 0x000000FF
|
||||
#define lpfc_acqe_fc_la_topology_WORD word0
|
||||
|
@ -4079,6 +4183,7 @@ struct wqe_common {
|
|||
#define wqe_iod_SHIFT 13
|
||||
#define wqe_iod_MASK 0x00000001
|
||||
#define wqe_iod_WORD word10
|
||||
#define LPFC_WQE_IOD_NONE 0
|
||||
#define LPFC_WQE_IOD_WRITE 0
|
||||
#define LPFC_WQE_IOD_READ 1
|
||||
#define wqe_dbde_SHIFT 14
|
||||
|
@ -4123,6 +4228,9 @@ struct wqe_common {
|
|||
#define wqe_irsp_SHIFT 4
|
||||
#define wqe_irsp_MASK 0x00000001
|
||||
#define wqe_irsp_WORD word11
|
||||
#define wqe_pbde_SHIFT 5
|
||||
#define wqe_pbde_MASK 0x00000001
|
||||
#define wqe_pbde_WORD word11
|
||||
#define wqe_sup_SHIFT 6
|
||||
#define wqe_sup_MASK 0x00000001
|
||||
#define wqe_sup_WORD word11
|
||||
|
@ -4343,9 +4451,9 @@ struct lpfc_nvme_prli {
|
|||
#define prli_init_SHIFT 5
|
||||
#define prli_init_MASK 0x00000001
|
||||
#define prli_init_WORD word4
|
||||
#define prli_recov_SHIFT 8
|
||||
#define prli_recov_MASK 0x00000001
|
||||
#define prli_recov_WORD word4
|
||||
#define prli_conf_SHIFT 7
|
||||
#define prli_conf_MASK 0x00000001
|
||||
#define prli_conf_WORD word4
|
||||
uint32_t word5;
|
||||
#define prli_fb_sz_SHIFT 0
|
||||
#define prli_fb_sz_MASK 0x0000ffff
|
||||
|
@ -4494,17 +4602,20 @@ union lpfc_wqe128 {
|
|||
struct fcp_icmnd64_wqe fcp_icmd;
|
||||
struct fcp_iread64_wqe fcp_iread;
|
||||
struct fcp_iwrite64_wqe fcp_iwrite;
|
||||
struct abort_cmd_wqe abort_cmd;
|
||||
struct create_xri_wqe create_xri;
|
||||
struct xmit_bcast64_wqe xmit_bcast64;
|
||||
struct xmit_seq64_wqe xmit_sequence;
|
||||
struct xmit_bls_rsp64_wqe xmit_bls_rsp;
|
||||
struct xmit_els_rsp64_wqe xmit_els_rsp;
|
||||
struct els_request64_wqe els_req;
|
||||
struct gen_req64_wqe gen_req;
|
||||
struct fcp_trsp64_wqe fcp_trsp;
|
||||
struct fcp_tsend64_wqe fcp_tsend;
|
||||
struct fcp_treceive64_wqe fcp_treceive;
|
||||
struct xmit_seq64_wqe xmit_sequence;
|
||||
struct gen_req64_wqe gen_req;
|
||||
struct send_frame_wqe send_frame;
|
||||
};
|
||||
|
||||
#define LPFC_GROUP_OJECT_MAGIC_G5 0xfeaa0001
|
||||
#define LPFC_GROUP_OJECT_MAGIC_G6 0xfeaa0003
|
||||
#define LPFC_FILE_TYPE_GROUP 0xf7
|
||||
#define LPFC_FILE_ID_GROUP 0xa2
|
||||
struct lpfc_grp_hdr {
|
||||
uint32_t size;
|
||||
uint32_t magic_number;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -116,6 +116,8 @@ const struct pci_device_id lpfc_id_table[] = {
|
|||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G6_FC,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G7_FC,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK_VF,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -731,7 +731,9 @@ lpfc_hba_init_link_fc_topology(struct lpfc_hba *phba, uint32_t fc_topology,
|
|||
((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G) &&
|
||||
!(phba->lmt & LMT_16Gb)) ||
|
||||
((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_32G) &&
|
||||
!(phba->lmt & LMT_32Gb))) {
|
||||
!(phba->lmt & LMT_32Gb)) ||
|
||||
((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_64G) &&
|
||||
!(phba->lmt & LMT_64Gb))) {
|
||||
/* Reset link speed to auto */
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
|
||||
"1302 Invalid speed for this board:%d "
|
||||
|
@ -958,6 +960,7 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba *phba)
|
|||
struct lpfc_sli_ring *pring;
|
||||
LIST_HEAD(completions);
|
||||
int i;
|
||||
struct lpfc_iocbq *piocb, *next_iocb;
|
||||
|
||||
if (phba->sli_rev != LPFC_SLI_REV4) {
|
||||
for (i = 0; i < psli->num_rings; i++) {
|
||||
|
@ -983,6 +986,9 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba *phba)
|
|||
if (!pring)
|
||||
continue;
|
||||
spin_lock_irq(&pring->ring_lock);
|
||||
list_for_each_entry_safe(piocb, next_iocb,
|
||||
&pring->txcmplq, list)
|
||||
piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
|
||||
list_splice_init(&pring->txcmplq, &completions);
|
||||
pring->txcmplq_cnt = 0;
|
||||
spin_unlock_irq(&pring->ring_lock);
|
||||
|
@ -1757,7 +1763,7 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action,
|
|||
int rc;
|
||||
uint32_t intr_mode;
|
||||
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >=
|
||||
LPFC_SLI_INTF_IF_TYPE_2) {
|
||||
/*
|
||||
* On error status condition, driver need to wait for port
|
||||
|
@ -1888,6 +1894,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
|
|||
break;
|
||||
|
||||
case LPFC_SLI_INTF_IF_TYPE_2:
|
||||
case LPFC_SLI_INTF_IF_TYPE_6:
|
||||
pci_rd_rc1 = lpfc_readl(
|
||||
phba->sli4_hba.u.if_type2.STATUSregaddr,
|
||||
&portstat_reg.word0);
|
||||
|
@ -2269,7 +2276,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
|||
&& descp && descp[0] != '\0')
|
||||
return;
|
||||
|
||||
if (phba->lmt & LMT_32Gb)
|
||||
if (phba->lmt & LMT_64Gb)
|
||||
max_speed = 64;
|
||||
else if (phba->lmt & LMT_32Gb)
|
||||
max_speed = 32;
|
||||
else if (phba->lmt & LMT_16Gb)
|
||||
max_speed = 16;
|
||||
|
@ -2468,6 +2477,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
|||
case PCI_DEVICE_ID_LANCER_G6_FC:
|
||||
m = (typeof(m)){"LPe32000", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LANCER_G7_FC:
|
||||
m = (typeof(m)){"LPe36000", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SKYHAWK:
|
||||
case PCI_DEVICE_ID_SKYHAWK_VF:
|
||||
oneConnect = 1;
|
||||
|
@ -4104,6 +4116,8 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
|
|||
sizeof fc_host_symbolic_name(shost));
|
||||
|
||||
fc_host_supported_speeds(shost) = 0;
|
||||
if (phba->lmt & LMT_64Gb)
|
||||
fc_host_supported_speeds(shost) |= FC_PORTSPEED_64GBIT;
|
||||
if (phba->lmt & LMT_32Gb)
|
||||
fc_host_supported_speeds(shost) |= FC_PORTSPEED_32GBIT;
|
||||
if (phba->lmt & LMT_16Gb)
|
||||
|
@ -4440,6 +4454,9 @@ lpfc_sli4_port_speed_parse(struct lpfc_hba *phba, uint32_t evt_code,
|
|||
case LPFC_FC_LA_SPEED_32G:
|
||||
port_speed = 32000;
|
||||
break;
|
||||
case LPFC_FC_LA_SPEED_64G:
|
||||
port_speed = 64000;
|
||||
break;
|
||||
default:
|
||||
port_speed = 0;
|
||||
}
|
||||
|
@ -5895,7 +5912,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
|||
* Since lpfc_sg_seg_cnt is module param, the sg_dma_buf_size
|
||||
* used to create the sg_dma_buf_pool must be calculated.
|
||||
*/
|
||||
if (phba->cfg_enable_bg) {
|
||||
if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) {
|
||||
/*
|
||||
* The scsi_buf for a T10-DIF I/O holds the FCP cmnd,
|
||||
* the FCP rsp, and a SGE. Sice we have no control
|
||||
|
@ -6014,7 +6031,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
|||
return -ENOMEM;
|
||||
|
||||
/* IF Type 2 ports get initialized now. */
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >=
|
||||
LPFC_SLI_INTF_IF_TYPE_2) {
|
||||
rc = lpfc_pci_function_reset(phba);
|
||||
if (unlikely(rc)) {
|
||||
|
@ -7344,6 +7361,7 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba)
|
|||
}
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_2:
|
||||
case LPFC_SLI_INTF_IF_TYPE_6:
|
||||
/* Final checks. The port status should be clean. */
|
||||
if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
|
||||
®_data.word0) ||
|
||||
|
@ -7426,13 +7444,36 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type)
|
|||
phba->sli4_hba.WQDBregaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p +
|
||||
LPFC_ULP0_WQ_DOORBELL;
|
||||
phba->sli4_hba.EQCQDBregaddr =
|
||||
phba->sli4_hba.CQDBregaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p + LPFC_EQCQ_DOORBELL;
|
||||
phba->sli4_hba.EQDBregaddr = phba->sli4_hba.CQDBregaddr;
|
||||
phba->sli4_hba.MQDBregaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p + LPFC_MQ_DOORBELL;
|
||||
phba->sli4_hba.BMBXregaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p + LPFC_BMBX;
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_6:
|
||||
phba->sli4_hba.u.if_type2.EQDregaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p +
|
||||
LPFC_CTL_PORT_EQ_DELAY_OFFSET;
|
||||
phba->sli4_hba.u.if_type2.ERR1regaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p +
|
||||
LPFC_CTL_PORT_ER1_OFFSET;
|
||||
phba->sli4_hba.u.if_type2.ERR2regaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p +
|
||||
LPFC_CTL_PORT_ER2_OFFSET;
|
||||
phba->sli4_hba.u.if_type2.CTRLregaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p +
|
||||
LPFC_CTL_PORT_CTL_OFFSET;
|
||||
phba->sli4_hba.u.if_type2.STATUSregaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p +
|
||||
LPFC_CTL_PORT_STA_OFFSET;
|
||||
phba->sli4_hba.PSMPHRregaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p +
|
||||
LPFC_CTL_PORT_SEM_OFFSET;
|
||||
phba->sli4_hba.BMBXregaddr =
|
||||
phba->sli4_hba.conf_regs_memmap_p + LPFC_BMBX;
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_1:
|
||||
default:
|
||||
dev_printk(KERN_ERR, &phba->pcidev->dev,
|
||||
|
@ -7446,13 +7487,15 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type)
|
|||
* lpfc_sli4_bar1_register_memmap - Set up SLI4 BAR1 register memory map.
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
*
|
||||
* This routine is invoked to set up SLI4 BAR1 control status register (CSR)
|
||||
* memory map.
|
||||
* This routine is invoked to set up SLI4 BAR1 register memory map.
|
||||
**/
|
||||
static void
|
||||
lpfc_sli4_bar1_register_memmap(struct lpfc_hba *phba)
|
||||
lpfc_sli4_bar1_register_memmap(struct lpfc_hba *phba, uint32_t if_type)
|
||||
{
|
||||
phba->sli4_hba.PSMPHRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
|
||||
switch (if_type) {
|
||||
case LPFC_SLI_INTF_IF_TYPE_0:
|
||||
phba->sli4_hba.PSMPHRregaddr =
|
||||
phba->sli4_hba.ctrl_regs_memmap_p +
|
||||
LPFC_SLIPORT_IF0_SMPHR;
|
||||
phba->sli4_hba.ISRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
|
||||
LPFC_HST_ISR0;
|
||||
|
@ -7460,6 +7503,27 @@ lpfc_sli4_bar1_register_memmap(struct lpfc_hba *phba)
|
|||
LPFC_HST_IMR0;
|
||||
phba->sli4_hba.ISCRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
|
||||
LPFC_HST_ISCR0;
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_6:
|
||||
phba->sli4_hba.RQDBregaddr = phba->sli4_hba.drbl_regs_memmap_p +
|
||||
LPFC_IF6_RQ_DOORBELL;
|
||||
phba->sli4_hba.WQDBregaddr = phba->sli4_hba.drbl_regs_memmap_p +
|
||||
LPFC_IF6_WQ_DOORBELL;
|
||||
phba->sli4_hba.CQDBregaddr = phba->sli4_hba.drbl_regs_memmap_p +
|
||||
LPFC_IF6_CQ_DOORBELL;
|
||||
phba->sli4_hba.EQDBregaddr = phba->sli4_hba.drbl_regs_memmap_p +
|
||||
LPFC_IF6_EQ_DOORBELL;
|
||||
phba->sli4_hba.MQDBregaddr = phba->sli4_hba.drbl_regs_memmap_p +
|
||||
LPFC_IF6_MQ_DOORBELL;
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_2:
|
||||
case LPFC_SLI_INTF_IF_TYPE_1:
|
||||
default:
|
||||
dev_err(&phba->pcidev->dev,
|
||||
"FATAL - unsupported SLI4 interface type - %d\n",
|
||||
if_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7484,8 +7548,10 @@ lpfc_sli4_bar2_register_memmap(struct lpfc_hba *phba, uint32_t vf)
|
|||
phba->sli4_hba.WQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
|
||||
vf * LPFC_VFR_PAGE_SIZE +
|
||||
LPFC_ULP0_WQ_DOORBELL);
|
||||
phba->sli4_hba.EQCQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
|
||||
vf * LPFC_VFR_PAGE_SIZE + LPFC_EQCQ_DOORBELL);
|
||||
phba->sli4_hba.CQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
|
||||
vf * LPFC_VFR_PAGE_SIZE +
|
||||
LPFC_EQCQ_DOORBELL);
|
||||
phba->sli4_hba.EQDBregaddr = phba->sli4_hba.CQDBregaddr;
|
||||
phba->sli4_hba.MQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
|
||||
vf * LPFC_VFR_PAGE_SIZE + LPFC_MQ_DOORBELL);
|
||||
phba->sli4_hba.BMBXregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
|
||||
|
@ -7722,7 +7788,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
|
|||
|
||||
/* Update link speed if forced link speed is supported */
|
||||
if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
|
||||
if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
|
||||
if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) {
|
||||
forced_link_speed =
|
||||
bf_get(lpfc_mbx_rd_conf_link_speed, rd_config);
|
||||
if (forced_link_speed) {
|
||||
|
@ -7757,6 +7823,10 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
|
|||
phba->cfg_link_speed =
|
||||
LPFC_USER_LINK_SPEED_32G;
|
||||
break;
|
||||
case LINK_SPEED_64G:
|
||||
phba->cfg_link_speed =
|
||||
LPFC_USER_LINK_SPEED_64G;
|
||||
break;
|
||||
case 0xffff:
|
||||
phba->cfg_link_speed =
|
||||
LPFC_USER_LINK_SPEED_AUTO;
|
||||
|
@ -7782,7 +7852,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
|
|||
phba->cfg_hba_queue_depth = length;
|
||||
}
|
||||
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <
|
||||
LPFC_SLI_INTF_IF_TYPE_2)
|
||||
goto read_cfg_out;
|
||||
|
||||
|
@ -7896,6 +7966,7 @@ lpfc_setup_endian_order(struct lpfc_hba *phba)
|
|||
}
|
||||
mempool_free(mboxq, phba->mbox_mem_pool);
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_6:
|
||||
case LPFC_SLI_INTF_IF_TYPE_2:
|
||||
case LPFC_SLI_INTF_IF_TYPE_1:
|
||||
default:
|
||||
|
@ -7992,6 +8063,7 @@ lpfc_alloc_nvme_wq_cq(struct lpfc_hba *phba, int wqidx)
|
|||
wqidx);
|
||||
return 1;
|
||||
}
|
||||
qdesc->qe_valid = 1;
|
||||
phba->sli4_hba.nvme_cq[wqidx] = qdesc;
|
||||
|
||||
qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE,
|
||||
|
@ -8011,9 +8083,10 @@ static int
|
|||
lpfc_alloc_fcp_wq_cq(struct lpfc_hba *phba, int wqidx)
|
||||
{
|
||||
struct lpfc_queue *qdesc;
|
||||
uint32_t wqesize;
|
||||
|
||||
/* Create Fast Path FCP CQs */
|
||||
if (phba->fcp_embed_io)
|
||||
if (phba->enab_exp_wqcq_pages)
|
||||
/* Increase the CQ size when WQEs contain an embedded cdb */
|
||||
qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE,
|
||||
phba->sli4_hba.cq_esize,
|
||||
|
@ -8028,18 +8101,22 @@ lpfc_alloc_fcp_wq_cq(struct lpfc_hba *phba, int wqidx)
|
|||
"0499 Failed allocate fast-path FCP CQ (%d)\n", wqidx);
|
||||
return 1;
|
||||
}
|
||||
qdesc->qe_valid = 1;
|
||||
phba->sli4_hba.fcp_cq[wqidx] = qdesc;
|
||||
|
||||
/* Create Fast Path FCP WQs */
|
||||
if (phba->fcp_embed_io)
|
||||
if (phba->enab_exp_wqcq_pages) {
|
||||
/* Increase the WQ size when WQEs contain an embedded cdb */
|
||||
wqesize = (phba->fcp_embed_io) ?
|
||||
LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize;
|
||||
qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE,
|
||||
LPFC_WQE128_SIZE,
|
||||
wqesize,
|
||||
LPFC_WQE_EXP_COUNT);
|
||||
else
|
||||
} else
|
||||
qdesc = lpfc_sli4_queue_alloc(phba, LPFC_DEFAULT_PAGE_SIZE,
|
||||
phba->sli4_hba.wq_esize,
|
||||
phba->sli4_hba.wq_ecount);
|
||||
|
||||
if (!qdesc) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"0503 Failed allocate fast-path FCP WQ (%d)\n",
|
||||
|
@ -8218,6 +8295,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
|
|||
"0497 Failed allocate EQ (%d)\n", idx);
|
||||
goto out_error;
|
||||
}
|
||||
qdesc->qe_valid = 1;
|
||||
phba->sli4_hba.hba_eq[idx] = qdesc;
|
||||
}
|
||||
|
||||
|
@ -8243,6 +8321,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
|
|||
"CQ Set (%d)\n", idx);
|
||||
goto out_error;
|
||||
}
|
||||
qdesc->qe_valid = 1;
|
||||
phba->sli4_hba.nvmet_cqset[idx] = qdesc;
|
||||
}
|
||||
}
|
||||
|
@ -8260,6 +8339,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
|
|||
"0500 Failed allocate slow-path mailbox CQ\n");
|
||||
goto out_error;
|
||||
}
|
||||
qdesc->qe_valid = 1;
|
||||
phba->sli4_hba.mbx_cq = qdesc;
|
||||
|
||||
/* Create slow-path ELS Complete Queue */
|
||||
|
@ -8271,6 +8351,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
|
|||
"0501 Failed allocate slow-path ELS CQ\n");
|
||||
goto out_error;
|
||||
}
|
||||
qdesc->qe_valid = 1;
|
||||
phba->sli4_hba.els_cq = qdesc;
|
||||
|
||||
|
||||
|
@ -8316,6 +8397,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
|
|||
"6079 Failed allocate NVME LS CQ\n");
|
||||
goto out_error;
|
||||
}
|
||||
qdesc->qe_valid = 1;
|
||||
phba->sli4_hba.nvmels_cq = qdesc;
|
||||
|
||||
/* Create NVME LS Work Queue */
|
||||
|
@ -9303,6 +9385,7 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
|
|||
}
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_2:
|
||||
case LPFC_SLI_INTF_IF_TYPE_6:
|
||||
wait:
|
||||
/*
|
||||
* Poll the Port Status Register and wait for RDY for
|
||||
|
@ -9458,7 +9541,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
|
|||
} else {
|
||||
phba->pci_bar0_map = pci_resource_start(pdev, 1);
|
||||
bar0map_len = pci_resource_len(pdev, 1);
|
||||
if (if_type == LPFC_SLI_INTF_IF_TYPE_2) {
|
||||
if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) {
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"FATAL - No BAR0 mapping for SLI4, if_type 2\n");
|
||||
goto out;
|
||||
|
@ -9495,13 +9578,32 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
|
|||
}
|
||||
phba->pci_bar2_memmap_p =
|
||||
phba->sli4_hba.ctrl_regs_memmap_p;
|
||||
lpfc_sli4_bar1_register_memmap(phba);
|
||||
lpfc_sli4_bar1_register_memmap(phba, if_type);
|
||||
} else {
|
||||
error = -ENOMEM;
|
||||
goto out_iounmap_conf;
|
||||
}
|
||||
}
|
||||
|
||||
if ((if_type == LPFC_SLI_INTF_IF_TYPE_6) &&
|
||||
(pci_resource_start(pdev, PCI_64BIT_BAR2))) {
|
||||
/*
|
||||
* Map SLI4 if type 6 HBA Doorbell Register base to a kernel
|
||||
* virtual address and setup the registers.
|
||||
*/
|
||||
phba->pci_bar1_map = pci_resource_start(pdev, PCI_64BIT_BAR2);
|
||||
bar1map_len = pci_resource_len(pdev, PCI_64BIT_BAR2);
|
||||
phba->sli4_hba.drbl_regs_memmap_p =
|
||||
ioremap(phba->pci_bar1_map, bar1map_len);
|
||||
if (!phba->sli4_hba.drbl_regs_memmap_p) {
|
||||
dev_err(&pdev->dev,
|
||||
"ioremap failed for SLI4 HBA doorbell registers.\n");
|
||||
goto out_iounmap_conf;
|
||||
}
|
||||
phba->pci_bar2_memmap_p = phba->sli4_hba.drbl_regs_memmap_p;
|
||||
lpfc_sli4_bar1_register_memmap(phba, if_type);
|
||||
}
|
||||
|
||||
if (if_type == LPFC_SLI_INTF_IF_TYPE_0) {
|
||||
if (pci_resource_start(pdev, PCI_64BIT_BAR4)) {
|
||||
/*
|
||||
|
@ -9532,6 +9634,41 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
|
|||
}
|
||||
}
|
||||
|
||||
if (if_type == LPFC_SLI_INTF_IF_TYPE_6 &&
|
||||
pci_resource_start(pdev, PCI_64BIT_BAR4)) {
|
||||
/*
|
||||
* Map SLI4 if type 6 HBA DPP Register base to a kernel
|
||||
* virtual address and setup the registers.
|
||||
*/
|
||||
phba->pci_bar2_map = pci_resource_start(pdev, PCI_64BIT_BAR4);
|
||||
bar2map_len = pci_resource_len(pdev, PCI_64BIT_BAR4);
|
||||
phba->sli4_hba.dpp_regs_memmap_p =
|
||||
ioremap(phba->pci_bar2_map, bar2map_len);
|
||||
if (!phba->sli4_hba.dpp_regs_memmap_p) {
|
||||
dev_err(&pdev->dev,
|
||||
"ioremap failed for SLI4 HBA dpp registers.\n");
|
||||
goto out_iounmap_ctrl;
|
||||
}
|
||||
phba->pci_bar4_memmap_p = phba->sli4_hba.dpp_regs_memmap_p;
|
||||
}
|
||||
|
||||
/* Set up the EQ/CQ register handeling functions now */
|
||||
switch (if_type) {
|
||||
case LPFC_SLI_INTF_IF_TYPE_0:
|
||||
case LPFC_SLI_INTF_IF_TYPE_2:
|
||||
phba->sli4_hba.sli4_eq_clr_intr = lpfc_sli4_eq_clr_intr;
|
||||
phba->sli4_hba.sli4_eq_release = lpfc_sli4_eq_release;
|
||||
phba->sli4_hba.sli4_cq_release = lpfc_sli4_cq_release;
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_6:
|
||||
phba->sli4_hba.sli4_eq_clr_intr = lpfc_sli4_if6_eq_clr_intr;
|
||||
phba->sli4_hba.sli4_eq_release = lpfc_sli4_if6_eq_release;
|
||||
phba->sli4_hba.sli4_cq_release = lpfc_sli4_if6_cq_release;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_iounmap_all:
|
||||
|
@ -9566,6 +9703,10 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba)
|
|||
case LPFC_SLI_INTF_IF_TYPE_2:
|
||||
iounmap(phba->sli4_hba.conf_regs_memmap_p);
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_6:
|
||||
iounmap(phba->sli4_hba.drbl_regs_memmap_p);
|
||||
iounmap(phba->sli4_hba.conf_regs_memmap_p);
|
||||
break;
|
||||
case LPFC_SLI_INTF_IF_TYPE_1:
|
||||
default:
|
||||
dev_printk(KERN_ERR, &phba->pcidev->dev,
|
||||
|
@ -10435,6 +10576,8 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
|
|||
sli4_params->mqv = bf_get(cfg_mqv, mbx_sli4_parameters);
|
||||
sli4_params->wqv = bf_get(cfg_wqv, mbx_sli4_parameters);
|
||||
sli4_params->rqv = bf_get(cfg_rqv, mbx_sli4_parameters);
|
||||
sli4_params->eqav = bf_get(cfg_eqav, mbx_sli4_parameters);
|
||||
sli4_params->cqav = bf_get(cfg_cqav, mbx_sli4_parameters);
|
||||
sli4_params->wqsize = bf_get(cfg_wqsize, mbx_sli4_parameters);
|
||||
sli4_params->sgl_pages_max = bf_get(cfg_sgl_page_cnt,
|
||||
mbx_sli4_parameters);
|
||||
|
@ -10465,8 +10608,32 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
|
|||
phba->cfg_enable_fc4_type = LPFC_ENABLE_FCP;
|
||||
}
|
||||
|
||||
if (bf_get(cfg_xib, mbx_sli4_parameters) && phba->cfg_suppress_rsp)
|
||||
/* Only embed PBDE for if_type 6 */
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
|
||||
LPFC_SLI_INTF_IF_TYPE_6) {
|
||||
phba->fcp_embed_pbde = 1;
|
||||
phba->nvme_embed_pbde = 1;
|
||||
}
|
||||
|
||||
/* PBDE support requires xib be set */
|
||||
if (!bf_get(cfg_xib, mbx_sli4_parameters)) {
|
||||
phba->fcp_embed_pbde = 0;
|
||||
phba->nvme_embed_pbde = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* To support Suppress Response feature we must satisfy 3 conditions.
|
||||
* lpfc_suppress_rsp module parameter must be set (default).
|
||||
* In SLI4-Parameters Descriptor:
|
||||
* Extended Inline Buffers (XIB) must be supported.
|
||||
* Suppress Response IU Not Supported (SRIUNS) must NOT be supported
|
||||
* (double negative).
|
||||
*/
|
||||
if (phba->cfg_suppress_rsp && bf_get(cfg_xib, mbx_sli4_parameters) &&
|
||||
!(bf_get(cfg_nosr, mbx_sli4_parameters)))
|
||||
phba->sli.sli_flag |= LPFC_SLI_SUPPRESS_RSP;
|
||||
else
|
||||
phba->cfg_suppress_rsp = 0;
|
||||
|
||||
if (bf_get(cfg_eqdr, mbx_sli4_parameters))
|
||||
phba->sli.sli_flag |= LPFC_SLI_USE_EQDR;
|
||||
|
@ -10476,15 +10643,28 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
|
|||
sli4_params->sge_supp_len = LPFC_MAX_SGE_SIZE;
|
||||
|
||||
/*
|
||||
* Issue IOs with CDB embedded in WQE to minimized the number
|
||||
* of DMAs the firmware has to do. Setting this to 1 also forces
|
||||
* the driver to use 128 bytes WQEs for FCP IOs.
|
||||
* Check whether the adapter supports an embedded copy of the
|
||||
* FCP CMD IU within the WQE for FCP_Ixxx commands. In order
|
||||
* to use this option, 128-byte WQEs must be used.
|
||||
*/
|
||||
if (bf_get(cfg_ext_embed_cb, mbx_sli4_parameters))
|
||||
phba->fcp_embed_io = 1;
|
||||
else
|
||||
phba->fcp_embed_io = 0;
|
||||
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_NVME,
|
||||
"6422 XIB %d: FCP %d %d NVME %d %d %d %d\n",
|
||||
bf_get(cfg_xib, mbx_sli4_parameters),
|
||||
phba->fcp_embed_pbde, phba->fcp_embed_io,
|
||||
phba->nvme_support, phba->nvme_embed_pbde,
|
||||
phba->cfg_nvme_embed_cmd, phba->cfg_suppress_rsp);
|
||||
|
||||
if ((bf_get(cfg_cqpsize, mbx_sli4_parameters) & LPFC_CQ_16K_PAGE_SZ) &&
|
||||
(bf_get(cfg_wqpsize, mbx_sli4_parameters) & LPFC_WQ_16K_PAGE_SZ) &&
|
||||
(sli4_params->wqsize & LPFC_WQ_SZ128_SUPPORT))
|
||||
phba->enab_exp_wqcq_pages = 1;
|
||||
else
|
||||
phba->enab_exp_wqcq_pages = 0;
|
||||
/*
|
||||
* Check if the SLI port supports MDS Diagnostics
|
||||
*/
|
||||
|
@ -11137,6 +11317,27 @@ lpfc_sli4_get_iocb_cnt(struct lpfc_hba *phba)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset,
|
||||
uint32_t magic_number, uint32_t ftype, uint32_t fid, uint32_t fsize,
|
||||
const struct firmware *fw)
|
||||
{
|
||||
if (offset == ADD_STATUS_FW_NOT_SUPPORTED)
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"3030 This firmware version is not supported on "
|
||||
"this HBA model. Device:%x Magic:%x Type:%x "
|
||||
"ID:%x Size %d %zd\n",
|
||||
phba->pcidev->device, magic_number, ftype, fid,
|
||||
fsize, fw->size);
|
||||
else
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"3022 FW Download failed. Device:%x Magic:%x Type:%x "
|
||||
"ID:%x Size %d %zd\n",
|
||||
phba->pcidev->device, magic_number, ftype, fid,
|
||||
fsize, fw->size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lpfc_write_firmware - attempt to write a firmware image to the port
|
||||
* @fw: pointer to firmware image returned from request_firmware.
|
||||
|
@ -11164,20 +11365,10 @@ lpfc_write_firmware(const struct firmware *fw, void *context)
|
|||
|
||||
magic_number = be32_to_cpu(image->magic_number);
|
||||
ftype = bf_get_be32(lpfc_grp_hdr_file_type, image);
|
||||
fid = bf_get_be32(lpfc_grp_hdr_id, image),
|
||||
fid = bf_get_be32(lpfc_grp_hdr_id, image);
|
||||
fsize = be32_to_cpu(image->size);
|
||||
|
||||
INIT_LIST_HEAD(&dma_buffer_list);
|
||||
if ((magic_number != LPFC_GROUP_OJECT_MAGIC_G5 &&
|
||||
magic_number != LPFC_GROUP_OJECT_MAGIC_G6) ||
|
||||
ftype != LPFC_FILE_TYPE_GROUP || fsize != fw->size) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"3022 Invalid FW image found. "
|
||||
"Magic:%x Type:%x ID:%x Size %d %zd\n",
|
||||
magic_number, ftype, fid, fsize, fw->size);
|
||||
rc = -EINVAL;
|
||||
goto release_out;
|
||||
}
|
||||
lpfc_decode_firmware_rev(phba, fwrev, 1);
|
||||
if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
|
@ -11218,11 +11409,18 @@ lpfc_write_firmware(const struct firmware *fw, void *context)
|
|||
}
|
||||
rc = lpfc_wr_object(phba, &dma_buffer_list,
|
||||
(fw->size - offset), &offset);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
lpfc_log_write_firmware_error(phba, offset,
|
||||
magic_number, ftype, fid, fsize, fw);
|
||||
goto release_out;
|
||||
}
|
||||
rc = offset;
|
||||
}
|
||||
rc = offset;
|
||||
} else
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"3029 Skipped Firmware update, Current "
|
||||
"Version:%s New Version:%s\n",
|
||||
fwrev, image->revision);
|
||||
|
||||
release_out:
|
||||
list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) {
|
||||
|
@ -11253,7 +11451,7 @@ lpfc_sli4_request_firmware_update(struct lpfc_hba *phba, uint8_t fw_upgrade)
|
|||
const struct firmware *fw;
|
||||
|
||||
/* Only supported on SLI4 interface type 2 for now */
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <
|
||||
LPFC_SLI_INTF_IF_TYPE_2)
|
||||
return -EPERM;
|
||||
|
||||
|
@ -11493,13 +11691,6 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
|
|||
/* Remove FC host and then SCSI host with the physical port */
|
||||
fc_remove_host(shost);
|
||||
scsi_remove_host(shost);
|
||||
/*
|
||||
* Bring down the SLI Layer. This step disables all interrupts,
|
||||
* clears the rings, discards all mailbox commands, and resets
|
||||
* the HBA FCoE function.
|
||||
*/
|
||||
lpfc_debugfs_terminate(vport);
|
||||
lpfc_sli4_hba_unset(phba);
|
||||
|
||||
/* Perform ndlp cleanup on the physical port. The nvme and nvmet
|
||||
* localports are destroyed after to cleanup all transport memory.
|
||||
|
@ -11508,6 +11699,13 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
|
|||
lpfc_nvmet_destroy_targetport(phba);
|
||||
lpfc_nvme_destroy_localport(vport);
|
||||
|
||||
/*
|
||||
* Bring down the SLI Layer. This step disables all interrupts,
|
||||
* clears the rings, discards all mailbox commands, and resets
|
||||
* the HBA FCoE function.
|
||||
*/
|
||||
lpfc_debugfs_terminate(vport);
|
||||
lpfc_sli4_hba_unset(phba);
|
||||
|
||||
lpfc_stop_hba_timers(phba);
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
|
@ -12227,6 +12425,7 @@ int
|
|||
lpfc_fof_queue_create(struct lpfc_hba *phba)
|
||||
{
|
||||
struct lpfc_queue *qdesc;
|
||||
uint32_t wqesize;
|
||||
|
||||
/* Create FOF EQ */
|
||||
qdesc = lpfc_sli4_queue_alloc(phba, LPFC_DEFAULT_PAGE_SIZE,
|
||||
|
@ -12235,12 +12434,13 @@ lpfc_fof_queue_create(struct lpfc_hba *phba)
|
|||
if (!qdesc)
|
||||
goto out_error;
|
||||
|
||||
qdesc->qe_valid = 1;
|
||||
phba->sli4_hba.fof_eq = qdesc;
|
||||
|
||||
if (phba->cfg_fof) {
|
||||
|
||||
/* Create OAS CQ */
|
||||
if (phba->fcp_embed_io)
|
||||
if (phba->enab_exp_wqcq_pages)
|
||||
qdesc = lpfc_sli4_queue_alloc(phba,
|
||||
LPFC_EXPANDED_PAGE_SIZE,
|
||||
phba->sli4_hba.cq_esize,
|
||||
|
@ -12253,19 +12453,23 @@ lpfc_fof_queue_create(struct lpfc_hba *phba)
|
|||
if (!qdesc)
|
||||
goto out_error;
|
||||
|
||||
qdesc->qe_valid = 1;
|
||||
phba->sli4_hba.oas_cq = qdesc;
|
||||
|
||||
/* Create OAS WQ */
|
||||
if (phba->fcp_embed_io)
|
||||
if (phba->enab_exp_wqcq_pages) {
|
||||
wqesize = (phba->fcp_embed_io) ?
|
||||
LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize;
|
||||
qdesc = lpfc_sli4_queue_alloc(phba,
|
||||
LPFC_EXPANDED_PAGE_SIZE,
|
||||
LPFC_WQE128_SIZE,
|
||||
wqesize,
|
||||
LPFC_WQE_EXP_COUNT);
|
||||
else
|
||||
} else
|
||||
qdesc = lpfc_sli4_queue_alloc(phba,
|
||||
LPFC_DEFAULT_PAGE_SIZE,
|
||||
phba->sli4_hba.wq_esize,
|
||||
phba->sli4_hba.wq_ecount);
|
||||
|
||||
if (!qdesc)
|
||||
goto out_error;
|
||||
|
||||
|
@ -12379,6 +12583,8 @@ lpfc_init(void)
|
|||
fc_release_transport(lpfc_transport_template);
|
||||
return -ENOMEM;
|
||||
}
|
||||
lpfc_nvme_cmd_template();
|
||||
lpfc_nvmet_cmd_template();
|
||||
|
||||
/* Initialize in case vector mapping is needed */
|
||||
lpfc_used_cpu = NULL;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -557,6 +557,10 @@ lpfc_init_link(struct lpfc_hba * phba,
|
|||
mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
|
||||
mb->un.varInitLnk.link_speed = LINK_SPEED_32G;
|
||||
break;
|
||||
case LPFC_USER_LINK_SPEED_64G:
|
||||
mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
|
||||
mb->un.varInitLnk.link_speed = LINK_SPEED_64G;
|
||||
break;
|
||||
case LPFC_USER_LINK_SPEED_AUTO:
|
||||
default:
|
||||
mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO;
|
||||
|
@ -2170,10 +2174,8 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys)
|
|||
/* Only FC supports upd bit */
|
||||
if ((phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) &&
|
||||
(vport->fc_flag & FC_VFI_REGISTERED) &&
|
||||
(!phba->fc_topology_changed)) {
|
||||
bf_set(lpfc_reg_vfi_vp, reg_vfi, 0);
|
||||
(!phba->fc_topology_changed))
|
||||
bf_set(lpfc_reg_vfi_upd, reg_vfi, 1);
|
||||
}
|
||||
|
||||
bf_set(lpfc_reg_vfi_bbcr, reg_vfi, 0);
|
||||
bf_set(lpfc_reg_vfi_bbscn, reg_vfi, 0);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2014 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -753,12 +753,16 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
|
|||
drqe.address_hi = putPaddrHigh(rqb_entry->dbuf.phys);
|
||||
rc = lpfc_sli4_rq_put(rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe);
|
||||
if (rc < 0) {
|
||||
(rqbp->rqb_free_buffer)(phba, rqb_entry);
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"6409 Cannot post to RQ %d: %x %x\n",
|
||||
"6409 Cannot post to HRQ %d: %x %x %x "
|
||||
"DRQ %x %x\n",
|
||||
rqb_entry->hrq->queue_id,
|
||||
rqb_entry->hrq->host_index,
|
||||
rqb_entry->hrq->hba_index);
|
||||
(rqbp->rqb_free_buffer)(phba, rqb_entry);
|
||||
rqb_entry->hrq->hba_index,
|
||||
rqb_entry->hrq->entry_count,
|
||||
rqb_entry->drq->host_index,
|
||||
rqb_entry->drq->hba_index);
|
||||
} else {
|
||||
list_add_tail(&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list);
|
||||
rqbp->buffer_count++;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -1998,8 +1998,14 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
|||
ndlp->nlp_type |= NLP_NVME_TARGET;
|
||||
if (bf_get_be32(prli_disc, nvpr))
|
||||
ndlp->nlp_type |= NLP_NVME_DISCOVERY;
|
||||
|
||||
/*
|
||||
* If prli_fba is set, the Target supports FirstBurst.
|
||||
* If prli_fb_sz is 0, the FirstBurst size is unlimited,
|
||||
* otherwise it defines the actual size supported by
|
||||
* the NVME Target.
|
||||
*/
|
||||
if ((bf_get_be32(prli_fba, nvpr) == 1) &&
|
||||
(bf_get_be32(prli_fb_sz, nvpr) > 0) &&
|
||||
(phba->cfg_nvme_enable_fb) &&
|
||||
(!phba->nvmet_support)) {
|
||||
/* Both sides support FB. The target's first
|
||||
|
@ -2008,11 +2014,15 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
|||
ndlp->nlp_flag |= NLP_FIRSTBURST;
|
||||
ndlp->nvme_fb_size = bf_get_be32(prli_fb_sz,
|
||||
nvpr);
|
||||
}
|
||||
}
|
||||
|
||||
if (bf_get_be32(prli_recov, nvpr))
|
||||
ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
|
||||
/* Expressed in units of 512 bytes */
|
||||
if (ndlp->nvme_fb_size)
|
||||
ndlp->nvme_fb_size <<=
|
||||
LPFC_NVME_FB_SHIFT;
|
||||
else
|
||||
ndlp->nvme_fb_size = LPFC_NVME_MAX_FB;
|
||||
}
|
||||
}
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
|
||||
"6029 NVME PRLI Cmpl w1 x%08x "
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -65,6 +65,136 @@ lpfc_release_nvme_buf(struct lpfc_hba *, struct lpfc_nvme_buf *);
|
|||
|
||||
static struct nvme_fc_port_template lpfc_nvme_template;
|
||||
|
||||
static union lpfc_wqe128 lpfc_iread_cmd_template;
|
||||
static union lpfc_wqe128 lpfc_iwrite_cmd_template;
|
||||
static union lpfc_wqe128 lpfc_icmnd_cmd_template;
|
||||
|
||||
/* Setup WQE templates for NVME IOs */
|
||||
void
|
||||
lpfc_nvme_cmd_template(void)
|
||||
{
|
||||
union lpfc_wqe128 *wqe;
|
||||
|
||||
/* IREAD template */
|
||||
wqe = &lpfc_iread_cmd_template;
|
||||
memset(wqe, 0, sizeof(union lpfc_wqe128));
|
||||
|
||||
/* Word 0, 1, 2 - BDE is variable */
|
||||
|
||||
/* Word 3 - cmd_buff_len, payload_offset_len is zero */
|
||||
|
||||
/* Word 4 - total_xfer_len is variable */
|
||||
|
||||
/* Word 5 - is zero */
|
||||
|
||||
/* Word 6 - ctxt_tag, xri_tag is variable */
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_cmnd, &wqe->fcp_iread.wqe_com, CMD_FCP_IREAD64_WQE);
|
||||
bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, PARM_READ_CHECK);
|
||||
bf_set(wqe_class, &wqe->fcp_iread.wqe_com, CLASS3);
|
||||
bf_set(wqe_ct, &wqe->fcp_iread.wqe_com, SLI4_CT_RPI);
|
||||
|
||||
/* Word 8 - abort_tag is variable */
|
||||
|
||||
/* Word 9 - reqtag is variable */
|
||||
|
||||
/* Word 10 - dbde, wqes is variable */
|
||||
bf_set(wqe_qosd, &wqe->fcp_iread.wqe_com, 0);
|
||||
bf_set(wqe_nvme, &wqe->fcp_iread.wqe_com, 1);
|
||||
bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, LPFC_WQE_LENLOC_WORD4);
|
||||
bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 0);
|
||||
bf_set(wqe_wqes, &wqe->fcp_iread.wqe_com, 1);
|
||||
|
||||
/* Word 11 - pbde is variable */
|
||||
bf_set(wqe_cmd_type, &wqe->fcp_iread.wqe_com, NVME_READ_CMD);
|
||||
bf_set(wqe_cqid, &wqe->fcp_iread.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
|
||||
bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 1);
|
||||
|
||||
/* Word 12 - is zero */
|
||||
|
||||
/* Word 13, 14, 15 - PBDE is variable */
|
||||
|
||||
/* IWRITE template */
|
||||
wqe = &lpfc_iwrite_cmd_template;
|
||||
memset(wqe, 0, sizeof(union lpfc_wqe128));
|
||||
|
||||
/* Word 0, 1, 2 - BDE is variable */
|
||||
|
||||
/* Word 3 - cmd_buff_len, payload_offset_len is zero */
|
||||
|
||||
/* Word 4 - total_xfer_len is variable */
|
||||
|
||||
/* Word 5 - initial_xfer_len is variable */
|
||||
|
||||
/* Word 6 - ctxt_tag, xri_tag is variable */
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_cmnd, &wqe->fcp_iwrite.wqe_com, CMD_FCP_IWRITE64_WQE);
|
||||
bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, PARM_READ_CHECK);
|
||||
bf_set(wqe_class, &wqe->fcp_iwrite.wqe_com, CLASS3);
|
||||
bf_set(wqe_ct, &wqe->fcp_iwrite.wqe_com, SLI4_CT_RPI);
|
||||
|
||||
/* Word 8 - abort_tag is variable */
|
||||
|
||||
/* Word 9 - reqtag is variable */
|
||||
|
||||
/* Word 10 - dbde, wqes is variable */
|
||||
bf_set(wqe_qosd, &wqe->fcp_iwrite.wqe_com, 0);
|
||||
bf_set(wqe_nvme, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_LENLOC_WORD4);
|
||||
bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 0);
|
||||
bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
|
||||
/* Word 11 - pbde is variable */
|
||||
bf_set(wqe_cmd_type, &wqe->fcp_iwrite.wqe_com, NVME_WRITE_CMD);
|
||||
bf_set(wqe_cqid, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
|
||||
bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
|
||||
/* Word 12 - is zero */
|
||||
|
||||
/* Word 13, 14, 15 - PBDE is variable */
|
||||
|
||||
/* ICMND template */
|
||||
wqe = &lpfc_icmnd_cmd_template;
|
||||
memset(wqe, 0, sizeof(union lpfc_wqe128));
|
||||
|
||||
/* Word 0, 1, 2 - BDE is variable */
|
||||
|
||||
/* Word 3 - payload_offset_len is variable */
|
||||
|
||||
/* Word 4, 5 - is zero */
|
||||
|
||||
/* Word 6 - ctxt_tag, xri_tag is variable */
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_cmnd, &wqe->fcp_icmd.wqe_com, CMD_FCP_ICMND64_WQE);
|
||||
bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0);
|
||||
bf_set(wqe_class, &wqe->fcp_icmd.wqe_com, CLASS3);
|
||||
bf_set(wqe_ct, &wqe->fcp_icmd.wqe_com, SLI4_CT_RPI);
|
||||
|
||||
/* Word 8 - abort_tag is variable */
|
||||
|
||||
/* Word 9 - reqtag is variable */
|
||||
|
||||
/* Word 10 - dbde, wqes is variable */
|
||||
bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1);
|
||||
bf_set(wqe_nvme, &wqe->fcp_icmd.wqe_com, 1);
|
||||
bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_NONE);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, LPFC_WQE_LENLOC_NONE);
|
||||
bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 0);
|
||||
bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1);
|
||||
|
||||
/* Word 11 */
|
||||
bf_set(wqe_cmd_type, &wqe->fcp_icmd.wqe_com, FCP_COMMAND);
|
||||
bf_set(wqe_cqid, &wqe->fcp_icmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
|
||||
bf_set(wqe_pbde, &wqe->fcp_icmd.wqe_com, 0);
|
||||
|
||||
/* Word 12, 13, 14, 15 - is zero */
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_nvme_create_queue -
|
||||
* @lpfc_pnvme: Pointer to the driver's nvme instance data
|
||||
|
@ -241,10 +371,11 @@ lpfc_nvme_cmpl_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
|
|||
ndlp = (struct lpfc_nodelist *)cmdwqe->context1;
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
|
||||
"6047 nvme cmpl Enter "
|
||||
"Data %p DID %x Xri: %x status %x cmd:%p lsreg:%p "
|
||||
"bmp:%p ndlp:%p\n",
|
||||
"Data %p DID %x Xri: %x status %x reason x%x cmd:%p "
|
||||
"lsreg:%p bmp:%p ndlp:%p\n",
|
||||
pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0,
|
||||
cmdwqe->sli4_xritag, status,
|
||||
(wcqe->parameter & 0xffff),
|
||||
cmdwqe, pnvme_lsreq, cmdwqe->context3, ndlp);
|
||||
|
||||
lpfc_nvmeio_data(phba, "NVME LS CMPL: xri x%x stat x%x parm x%x\n",
|
||||
|
@ -281,7 +412,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
|
|||
uint32_t tmo, uint8_t retry)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
union lpfc_wqe *wqe;
|
||||
union lpfc_wqe128 *wqe;
|
||||
struct lpfc_iocbq *genwqe;
|
||||
struct ulp_bde64 *bpl;
|
||||
struct ulp_bde64 bde;
|
||||
|
@ -419,6 +550,7 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
|
|||
{
|
||||
int ret = 0;
|
||||
struct lpfc_nvme_lport *lport;
|
||||
struct lpfc_nvme_rport *rport;
|
||||
struct lpfc_vport *vport;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
struct ulp_bde64 *bpl;
|
||||
|
@ -437,19 +569,18 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
|
|||
*/
|
||||
|
||||
lport = (struct lpfc_nvme_lport *)pnvme_lport->private;
|
||||
rport = (struct lpfc_nvme_rport *)pnvme_rport->private;
|
||||
vport = lport->vport;
|
||||
|
||||
if (vport->load_flag & FC_UNLOADING)
|
||||
return -ENODEV;
|
||||
|
||||
if (vport->load_flag & FC_UNLOADING)
|
||||
return -ENODEV;
|
||||
|
||||
ndlp = lpfc_findnode_did(vport, pnvme_rport->port_id);
|
||||
/* Need the ndlp. It is stored in the driver's rport. */
|
||||
ndlp = rport->ndlp;
|
||||
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
|
||||
"6051 DID x%06x not an active rport.\n",
|
||||
pnvme_rport->port_id);
|
||||
"6051 Remoteport %p, rport has invalid ndlp. "
|
||||
"Failing LS Req\n", pnvme_rport);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -500,8 +631,9 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
|
|||
|
||||
/* Expand print to include key fields. */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
|
||||
"6149 ENTER. lport %p, rport %p lsreq%p rqstlen:%d "
|
||||
"rsplen:%d %pad %pad\n",
|
||||
"6149 Issue LS Req to DID 0x%06x lport %p, rport %p "
|
||||
"lsreq%p rqstlen:%d rsplen:%d %pad %pad\n",
|
||||
ndlp->nlp_DID,
|
||||
pnvme_lport, pnvme_rport,
|
||||
pnvme_lsreq, pnvme_lsreq->rqstlen,
|
||||
pnvme_lsreq->rsplen, &pnvme_lsreq->rqstdma,
|
||||
|
@ -517,7 +649,7 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
|
|||
ndlp, 2, 30, 0);
|
||||
if (ret != WQE_SUCCESS) {
|
||||
atomic_inc(&lport->xmt_ls_err);
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC,
|
||||
"6052 EXIT. issue ls wqe failed lport %p, "
|
||||
"rport %p lsreq%p Status %x DID %x\n",
|
||||
pnvme_lport, pnvme_rport, pnvme_lsreq,
|
||||
|
@ -610,15 +742,24 @@ lpfc_nvme_ls_abort(struct nvme_fc_local_port *pnvme_lport,
|
|||
}
|
||||
|
||||
/* Fix up the existing sgls for NVME IO. */
|
||||
static void
|
||||
static inline void
|
||||
lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
|
||||
struct lpfc_nvme_buf *lpfc_ncmd,
|
||||
struct nvmefc_fcp_req *nCmd)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct sli4_sge *sgl;
|
||||
union lpfc_wqe128 *wqe;
|
||||
uint32_t *wptr, *dptr;
|
||||
|
||||
/*
|
||||
* Get a local pointer to the built-in wqe and correct
|
||||
* the cmd size to match NVME's 96 bytes and fix
|
||||
* the dma address.
|
||||
*/
|
||||
|
||||
wqe = &lpfc_ncmd->cur_iocbq.wqe;
|
||||
|
||||
/*
|
||||
* Adjust the FCP_CMD and FCP_RSP DMA data and sge_len to
|
||||
* match NVME. NVME sends 96 bytes. Also, use the
|
||||
|
@ -628,42 +769,17 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
|
|||
*/
|
||||
sgl = lpfc_ncmd->nvme_sgl;
|
||||
sgl->sge_len = cpu_to_le32(nCmd->cmdlen);
|
||||
|
||||
sgl++;
|
||||
|
||||
/* Setup the physical region for the FCP RSP */
|
||||
sgl->addr_hi = cpu_to_le32(putPaddrHigh(nCmd->rspdma));
|
||||
sgl->addr_lo = cpu_to_le32(putPaddrLow(nCmd->rspdma));
|
||||
sgl->word2 = le32_to_cpu(sgl->word2);
|
||||
if (nCmd->sg_cnt)
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 0);
|
||||
else
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 1);
|
||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||
sgl->sge_len = cpu_to_le32(nCmd->rsplen);
|
||||
|
||||
/*
|
||||
* Get a local pointer to the built-in wqe and correct
|
||||
* the cmd size to match NVME's 96 bytes and fix
|
||||
* the dma address.
|
||||
*/
|
||||
|
||||
/* 128 byte wqe support here */
|
||||
wqe = (union lpfc_wqe128 *)&lpfc_ncmd->cur_iocbq.wqe;
|
||||
if (phba->cfg_nvme_embed_cmd) {
|
||||
sgl->addr_hi = 0;
|
||||
sgl->addr_lo = 0;
|
||||
|
||||
/* Word 0-2 - NVME CMND IU (embedded payload) */
|
||||
wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_IMMED;
|
||||
wqe->generic.bde.tus.f.bdeSize = 60;
|
||||
wqe->generic.bde.tus.f.bdeSize = 56;
|
||||
wqe->generic.bde.addrHigh = 0;
|
||||
wqe->generic.bde.addrLow = 64; /* Word 16 */
|
||||
|
||||
/* Word 3 */
|
||||
bf_set(payload_offset_len, &wqe->fcp_icmd,
|
||||
(nCmd->rsplen + nCmd->cmdlen));
|
||||
|
||||
/* Word 10 */
|
||||
bf_set(wqe_nvme, &wqe->fcp_icmd.wqe_com, 1);
|
||||
bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1);
|
||||
/* Word 10 - dbde is 0, wqes is 1 in template */
|
||||
|
||||
/*
|
||||
* Embed the payload in the last half of the WQE
|
||||
|
@ -693,6 +809,33 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
|
|||
*wptr++ = *dptr++; /* Word 21 */
|
||||
*wptr++ = *dptr++; /* Word 22 */
|
||||
*wptr = *dptr; /* Word 23 */
|
||||
} else {
|
||||
sgl->addr_hi = cpu_to_le32(putPaddrHigh(nCmd->cmddma));
|
||||
sgl->addr_lo = cpu_to_le32(putPaddrLow(nCmd->cmddma));
|
||||
|
||||
/* Word 0-2 - NVME CMND IU Inline BDE */
|
||||
wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
|
||||
wqe->generic.bde.tus.f.bdeSize = nCmd->cmdlen;
|
||||
wqe->generic.bde.addrHigh = sgl->addr_hi;
|
||||
wqe->generic.bde.addrLow = sgl->addr_lo;
|
||||
|
||||
/* Word 10 */
|
||||
bf_set(wqe_dbde, &wqe->generic.wqe_com, 1);
|
||||
bf_set(wqe_wqes, &wqe->generic.wqe_com, 0);
|
||||
}
|
||||
|
||||
sgl++;
|
||||
|
||||
/* Setup the physical region for the FCP RSP */
|
||||
sgl->addr_hi = cpu_to_le32(putPaddrHigh(nCmd->rspdma));
|
||||
sgl->addr_lo = cpu_to_le32(putPaddrLow(nCmd->rspdma));
|
||||
sgl->word2 = le32_to_cpu(sgl->word2);
|
||||
if (nCmd->sg_cnt)
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 0);
|
||||
else
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 1);
|
||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||
sgl->sge_len = cpu_to_le32(nCmd->rsplen);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
|
@ -980,14 +1123,14 @@ out_err:
|
|||
phba->cpucheck_cmpl_io[lpfc_ncmd->cpu]++;
|
||||
}
|
||||
#endif
|
||||
freqpriv = nCmd->private;
|
||||
freqpriv->nvme_buf = NULL;
|
||||
|
||||
/* NVME targets need completion held off until the abort exchange
|
||||
* completes unless the NVME Rport is getting unregistered.
|
||||
*/
|
||||
|
||||
if (!(lpfc_ncmd->flags & LPFC_SBUF_XBUSY)) {
|
||||
freqpriv = nCmd->private;
|
||||
freqpriv->nvme_buf = NULL;
|
||||
nCmd->done(nCmd);
|
||||
lpfc_ncmd->nvmeCmd = NULL;
|
||||
}
|
||||
|
@ -1025,7 +1168,7 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
|
|||
struct lpfc_hba *phba = vport->phba;
|
||||
struct nvmefc_fcp_req *nCmd = lpfc_ncmd->nvmeCmd;
|
||||
struct lpfc_iocbq *pwqeq = &(lpfc_ncmd->cur_iocbq);
|
||||
union lpfc_wqe128 *wqe = (union lpfc_wqe128 *)&pwqeq->wqe;
|
||||
union lpfc_wqe128 *wqe = &pwqeq->wqe;
|
||||
uint32_t req_len;
|
||||
|
||||
if (!pnode || !NLP_CHK_NODE_ACT(pnode))
|
||||
|
@ -1035,9 +1178,16 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
|
|||
* There are three possibilities here - use scatter-gather segment, use
|
||||
* the single mapping, or neither.
|
||||
*/
|
||||
wqe->fcp_iwrite.initial_xfer_len = 0;
|
||||
if (nCmd->sg_cnt) {
|
||||
if (nCmd->io_dir == NVMEFC_FCP_WRITE) {
|
||||
/* From the iwrite template, initialize words 7 - 11 */
|
||||
memcpy(&wqe->words[7],
|
||||
&lpfc_iwrite_cmd_template.words[7],
|
||||
sizeof(uint32_t) * 5);
|
||||
|
||||
/* Word 4 */
|
||||
wqe->fcp_iwrite.total_xfer_len = nCmd->payload_length;
|
||||
|
||||
/* Word 5 */
|
||||
if ((phba->cfg_nvme_enable_fb) &&
|
||||
(pnode->nlp_flag & NLP_FIRSTBURST)) {
|
||||
|
@ -1048,69 +1198,28 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
|
|||
else
|
||||
wqe->fcp_iwrite.initial_xfer_len =
|
||||
pnode->nvme_fb_size;
|
||||
} else {
|
||||
wqe->fcp_iwrite.initial_xfer_len = 0;
|
||||
}
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_cmnd, &wqe->generic.wqe_com,
|
||||
CMD_FCP_IWRITE64_WQE);
|
||||
bf_set(wqe_pu, &wqe->generic.wqe_com,
|
||||
PARM_READ_CHECK);
|
||||
|
||||
/* Word 10 */
|
||||
bf_set(wqe_qosd, &wqe->fcp_iwrite.wqe_com, 0);
|
||||
bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com,
|
||||
LPFC_WQE_IOD_WRITE);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com,
|
||||
LPFC_WQE_LENLOC_WORD4);
|
||||
if (phba->cfg_nvme_oas)
|
||||
bf_set(wqe_oas, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
|
||||
/* Word 11 */
|
||||
bf_set(wqe_cmd_type, &wqe->generic.wqe_com,
|
||||
NVME_WRITE_CMD);
|
||||
|
||||
atomic_inc(&phba->fc4NvmeOutputRequests);
|
||||
} else {
|
||||
/* Word 7 */
|
||||
bf_set(wqe_cmnd, &wqe->generic.wqe_com,
|
||||
CMD_FCP_IREAD64_WQE);
|
||||
bf_set(wqe_pu, &wqe->generic.wqe_com,
|
||||
PARM_READ_CHECK);
|
||||
/* From the iread template, initialize words 7 - 11 */
|
||||
memcpy(&wqe->words[7],
|
||||
&lpfc_iread_cmd_template.words[7],
|
||||
sizeof(uint32_t) * 5);
|
||||
|
||||
/* Word 10 */
|
||||
bf_set(wqe_qosd, &wqe->fcp_iread.wqe_com, 0);
|
||||
bf_set(wqe_iod, &wqe->fcp_iread.wqe_com,
|
||||
LPFC_WQE_IOD_READ);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com,
|
||||
LPFC_WQE_LENLOC_WORD4);
|
||||
if (phba->cfg_nvme_oas)
|
||||
bf_set(wqe_oas, &wqe->fcp_iread.wqe_com, 1);
|
||||
/* Word 4 */
|
||||
wqe->fcp_iread.total_xfer_len = nCmd->payload_length;
|
||||
|
||||
/* Word 11 */
|
||||
bf_set(wqe_cmd_type, &wqe->generic.wqe_com,
|
||||
NVME_READ_CMD);
|
||||
/* Word 5 */
|
||||
wqe->fcp_iread.rsrvd5 = 0;
|
||||
|
||||
atomic_inc(&phba->fc4NvmeInputRequests);
|
||||
}
|
||||
} else {
|
||||
/* Word 4 */
|
||||
wqe->fcp_icmd.rsrvd4 = 0;
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_cmnd, &wqe->generic.wqe_com, CMD_FCP_ICMND64_WQE);
|
||||
bf_set(wqe_pu, &wqe->generic.wqe_com, 0);
|
||||
|
||||
/* Word 10 */
|
||||
bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1);
|
||||
bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_WRITE);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com,
|
||||
LPFC_WQE_LENLOC_NONE);
|
||||
if (phba->cfg_nvme_oas)
|
||||
bf_set(wqe_oas, &wqe->fcp_icmd.wqe_com, 1);
|
||||
|
||||
/* Word 11 */
|
||||
bf_set(wqe_cmd_type, &wqe->generic.wqe_com, NVME_READ_CMD);
|
||||
|
||||
/* From the icmnd template, initialize words 4 - 11 */
|
||||
memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4],
|
||||
sizeof(uint32_t) * 8);
|
||||
atomic_inc(&phba->fc4NvmeControlRequests);
|
||||
}
|
||||
/*
|
||||
|
@ -1118,25 +1227,21 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
|
|||
* of the nvme_cmnd request_buffer
|
||||
*/
|
||||
|
||||
/* Word 3 */
|
||||
bf_set(payload_offset_len, &wqe->fcp_icmd,
|
||||
(nCmd->rsplen + nCmd->cmdlen));
|
||||
|
||||
/* Word 6 */
|
||||
bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com,
|
||||
phba->sli4_hba.rpi_ids[pnode->nlp_rpi]);
|
||||
bf_set(wqe_xri_tag, &wqe->generic.wqe_com, pwqeq->sli4_xritag);
|
||||
|
||||
/* Word 7 */
|
||||
/* Preserve Class data in the ndlp. */
|
||||
bf_set(wqe_class, &wqe->generic.wqe_com,
|
||||
(pnode->nlp_fcp_info & 0x0f));
|
||||
|
||||
/* Word 8 */
|
||||
wqe->generic.wqe_com.abort_tag = pwqeq->iotag;
|
||||
|
||||
/* Word 9 */
|
||||
bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag);
|
||||
|
||||
/* Word 11 */
|
||||
bf_set(wqe_cqid, &wqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
|
||||
|
||||
pwqeq->vport = vport;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1164,10 +1269,11 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport,
|
|||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct nvmefc_fcp_req *nCmd = lpfc_ncmd->nvmeCmd;
|
||||
union lpfc_wqe128 *wqe = (union lpfc_wqe128 *)&lpfc_ncmd->cur_iocbq.wqe;
|
||||
union lpfc_wqe128 *wqe = &lpfc_ncmd->cur_iocbq.wqe;
|
||||
struct sli4_sge *sgl = lpfc_ncmd->nvme_sgl;
|
||||
struct scatterlist *data_sg;
|
||||
struct sli4_sge *first_data_sgl;
|
||||
struct ulp_bde64 *bde;
|
||||
dma_addr_t physaddr;
|
||||
uint32_t num_bde = 0;
|
||||
uint32_t dma_len;
|
||||
|
@ -1235,7 +1341,26 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport,
|
|||
data_sg = sg_next(data_sg);
|
||||
sgl++;
|
||||
}
|
||||
if (phba->nvme_embed_pbde) {
|
||||
/* Use PBDE support for first SGL only, offset == 0 */
|
||||
/* Words 13-15 */
|
||||
bde = (struct ulp_bde64 *)
|
||||
&wqe->words[13];
|
||||
bde->addrLow = first_data_sgl->addr_lo;
|
||||
bde->addrHigh = first_data_sgl->addr_hi;
|
||||
bde->tus.f.bdeSize =
|
||||
le32_to_cpu(first_data_sgl->sge_len);
|
||||
bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
|
||||
bde->tus.w = cpu_to_le32(bde->tus.w);
|
||||
/* wqe_pbde is 1 in template */
|
||||
} else {
|
||||
memset(&wqe->words[13], 0, (sizeof(uint32_t) * 3));
|
||||
bf_set(wqe_pbde, &wqe->generic.wqe_com, 0);
|
||||
}
|
||||
} else {
|
||||
bf_set(wqe_pbde, &wqe->generic.wqe_com, 0);
|
||||
memset(&wqe->words[13], 0, (sizeof(uint32_t) * 3));
|
||||
|
||||
/* For this clause to be valid, the payload_length
|
||||
* and sg_cnt must zero.
|
||||
*/
|
||||
|
@ -1247,12 +1372,6 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport,
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Due to difference in data length between DIF/non-DIF paths,
|
||||
* we need to set word 4 of WQE here
|
||||
*/
|
||||
wqe->fcp_iread.total_xfer_len = nCmd->payload_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1554,7 +1673,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport,
|
|||
struct lpfc_iocbq *abts_buf;
|
||||
struct lpfc_iocbq *nvmereq_wqe;
|
||||
struct lpfc_nvme_fcpreq_priv *freqpriv;
|
||||
union lpfc_wqe *abts_wqe;
|
||||
union lpfc_wqe128 *abts_wqe;
|
||||
unsigned long flags;
|
||||
int ret_val;
|
||||
|
||||
|
@ -2098,7 +2217,7 @@ lpfc_new_nvme_buf(struct lpfc_vport *vport, int num_to_alloc)
|
|||
break;
|
||||
}
|
||||
pwqeq = &(lpfc_ncmd->cur_iocbq);
|
||||
wqe = (union lpfc_wqe128 *)&pwqeq->wqe;
|
||||
wqe = &pwqeq->wqe;
|
||||
|
||||
/* Allocate iotag for lpfc_ncmd->cur_iocbq. */
|
||||
iotag = lpfc_sli_next_iotag(phba, pwqeq);
|
||||
|
@ -2135,14 +2254,8 @@ lpfc_new_nvme_buf(struct lpfc_vport *vport, int num_to_alloc)
|
|||
|
||||
lpfc_ncmd->cur_iocbq.context1 = lpfc_ncmd;
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_erp, &wqe->generic.wqe_com, 0);
|
||||
/* NVME upper layers will time things out, if needed */
|
||||
bf_set(wqe_tmo, &wqe->generic.wqe_com, 0);
|
||||
|
||||
/* Word 10 */
|
||||
bf_set(wqe_ebde_cnt, &wqe->generic.wqe_com, 0);
|
||||
bf_set(wqe_dbde, &wqe->generic.wqe_com, 1);
|
||||
/* Initialize WQE */
|
||||
memset(wqe, 0, sizeof(union lpfc_wqe));
|
||||
|
||||
/* add the nvme buffer to a post list */
|
||||
list_add_tail(&lpfc_ncmd->list, &post_nblist);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -27,6 +27,8 @@
|
|||
|
||||
#define LPFC_NVME_WAIT_TMO 10
|
||||
#define LPFC_NVME_EXPEDITE_XRICNT 8
|
||||
#define LPFC_NVME_FB_SHIFT 9
|
||||
#define LPFC_NVME_MAX_FB (1 << 20) /* 1M */
|
||||
|
||||
struct lpfc_nvme_qhandle {
|
||||
uint32_t index; /* WQ index to use */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channsel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -36,7 +36,7 @@
|
|||
#include <scsi/scsi_transport_fc.h>
|
||||
#include <scsi/fc/fc_fs.h>
|
||||
|
||||
#include <../drivers/nvme/host/nvme.h>
|
||||
#include <linux/nvme.h>
|
||||
#include <linux/nvme-fc-driver.h>
|
||||
#include <linux/nvme-fc.h>
|
||||
|
||||
|
@ -71,6 +71,151 @@ static int lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *,
|
|||
static int lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *,
|
||||
struct lpfc_nvmet_rcv_ctx *,
|
||||
uint32_t, uint16_t);
|
||||
static void lpfc_nvmet_wqfull_flush(struct lpfc_hba *, struct lpfc_queue *,
|
||||
struct lpfc_nvmet_rcv_ctx *);
|
||||
|
||||
static union lpfc_wqe128 lpfc_tsend_cmd_template;
|
||||
static union lpfc_wqe128 lpfc_treceive_cmd_template;
|
||||
static union lpfc_wqe128 lpfc_trsp_cmd_template;
|
||||
|
||||
/* Setup WQE templates for NVME IOs */
|
||||
void
|
||||
lpfc_nvmet_cmd_template(void)
|
||||
{
|
||||
union lpfc_wqe128 *wqe;
|
||||
|
||||
/* TSEND template */
|
||||
wqe = &lpfc_tsend_cmd_template;
|
||||
memset(wqe, 0, sizeof(union lpfc_wqe128));
|
||||
|
||||
/* Word 0, 1, 2 - BDE is variable */
|
||||
|
||||
/* Word 3 - payload_offset_len is zero */
|
||||
|
||||
/* Word 4 - relative_offset is variable */
|
||||
|
||||
/* Word 5 - is zero */
|
||||
|
||||
/* Word 6 - ctxt_tag, xri_tag is variable */
|
||||
|
||||
/* Word 7 - wqe_ar is variable */
|
||||
bf_set(wqe_cmnd, &wqe->fcp_tsend.wqe_com, CMD_FCP_TSEND64_WQE);
|
||||
bf_set(wqe_pu, &wqe->fcp_tsend.wqe_com, PARM_REL_OFF);
|
||||
bf_set(wqe_class, &wqe->fcp_tsend.wqe_com, CLASS3);
|
||||
bf_set(wqe_ct, &wqe->fcp_tsend.wqe_com, SLI4_CT_RPI);
|
||||
bf_set(wqe_ar, &wqe->fcp_tsend.wqe_com, 1);
|
||||
|
||||
/* Word 8 - abort_tag is variable */
|
||||
|
||||
/* Word 9 - reqtag, rcvoxid is variable */
|
||||
|
||||
/* Word 10 - wqes, xc is variable */
|
||||
bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
|
||||
bf_set(wqe_dbde, &wqe->fcp_tsend.wqe_com, 1);
|
||||
bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, 1);
|
||||
bf_set(wqe_iod, &wqe->fcp_tsend.wqe_com, LPFC_WQE_IOD_WRITE);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_tsend.wqe_com, LPFC_WQE_LENLOC_WORD12);
|
||||
|
||||
/* Word 11 - sup, irsp, irsplen is variable */
|
||||
bf_set(wqe_cmd_type, &wqe->fcp_tsend.wqe_com, FCP_COMMAND_TSEND);
|
||||
bf_set(wqe_cqid, &wqe->fcp_tsend.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
|
||||
bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_pbde, &wqe->fcp_tsend.wqe_com, 0);
|
||||
|
||||
/* Word 12 - fcp_data_len is variable */
|
||||
|
||||
/* Word 13, 14, 15 - PBDE is zero */
|
||||
|
||||
/* TRECEIVE template */
|
||||
wqe = &lpfc_treceive_cmd_template;
|
||||
memset(wqe, 0, sizeof(union lpfc_wqe128));
|
||||
|
||||
/* Word 0, 1, 2 - BDE is variable */
|
||||
|
||||
/* Word 3 */
|
||||
wqe->fcp_treceive.payload_offset_len = TXRDY_PAYLOAD_LEN;
|
||||
|
||||
/* Word 4 - relative_offset is variable */
|
||||
|
||||
/* Word 5 - is zero */
|
||||
|
||||
/* Word 6 - ctxt_tag, xri_tag is variable */
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_cmnd, &wqe->fcp_treceive.wqe_com, CMD_FCP_TRECEIVE64_WQE);
|
||||
bf_set(wqe_pu, &wqe->fcp_treceive.wqe_com, PARM_REL_OFF);
|
||||
bf_set(wqe_class, &wqe->fcp_treceive.wqe_com, CLASS3);
|
||||
bf_set(wqe_ct, &wqe->fcp_treceive.wqe_com, SLI4_CT_RPI);
|
||||
bf_set(wqe_ar, &wqe->fcp_treceive.wqe_com, 0);
|
||||
|
||||
/* Word 8 - abort_tag is variable */
|
||||
|
||||
/* Word 9 - reqtag, rcvoxid is variable */
|
||||
|
||||
/* Word 10 - xc is variable */
|
||||
bf_set(wqe_dbde, &wqe->fcp_treceive.wqe_com, 1);
|
||||
bf_set(wqe_wqes, &wqe->fcp_treceive.wqe_com, 0);
|
||||
bf_set(wqe_nvme, &wqe->fcp_treceive.wqe_com, 1);
|
||||
bf_set(wqe_iod, &wqe->fcp_treceive.wqe_com, LPFC_WQE_IOD_READ);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_treceive.wqe_com, LPFC_WQE_LENLOC_WORD12);
|
||||
bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, 1);
|
||||
|
||||
/* Word 11 - pbde is variable */
|
||||
bf_set(wqe_cmd_type, &wqe->fcp_treceive.wqe_com, FCP_COMMAND_TRECEIVE);
|
||||
bf_set(wqe_cqid, &wqe->fcp_treceive.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
|
||||
bf_set(wqe_sup, &wqe->fcp_treceive.wqe_com, 0);
|
||||
bf_set(wqe_irsp, &wqe->fcp_treceive.wqe_com, 0);
|
||||
bf_set(wqe_irsplen, &wqe->fcp_treceive.wqe_com, 0);
|
||||
bf_set(wqe_pbde, &wqe->fcp_treceive.wqe_com, 1);
|
||||
|
||||
/* Word 12 - fcp_data_len is variable */
|
||||
|
||||
/* Word 13, 14, 15 - PBDE is variable */
|
||||
|
||||
/* TRSP template */
|
||||
wqe = &lpfc_trsp_cmd_template;
|
||||
memset(wqe, 0, sizeof(union lpfc_wqe128));
|
||||
|
||||
/* Word 0, 1, 2 - BDE is variable */
|
||||
|
||||
/* Word 3 - response_len is variable */
|
||||
|
||||
/* Word 4, 5 - is zero */
|
||||
|
||||
/* Word 6 - ctxt_tag, xri_tag is variable */
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_cmnd, &wqe->fcp_trsp.wqe_com, CMD_FCP_TRSP64_WQE);
|
||||
bf_set(wqe_pu, &wqe->fcp_trsp.wqe_com, PARM_UNUSED);
|
||||
bf_set(wqe_class, &wqe->fcp_trsp.wqe_com, CLASS3);
|
||||
bf_set(wqe_ct, &wqe->fcp_trsp.wqe_com, SLI4_CT_RPI);
|
||||
bf_set(wqe_ag, &wqe->fcp_trsp.wqe_com, 1); /* wqe_ar */
|
||||
|
||||
/* Word 8 - abort_tag is variable */
|
||||
|
||||
/* Word 9 - reqtag is variable */
|
||||
|
||||
/* Word 10 wqes, xc is variable */
|
||||
bf_set(wqe_dbde, &wqe->fcp_trsp.wqe_com, 1);
|
||||
bf_set(wqe_nvme, &wqe->fcp_trsp.wqe_com, 1);
|
||||
bf_set(wqe_wqes, &wqe->fcp_trsp.wqe_com, 0);
|
||||
bf_set(wqe_xc, &wqe->fcp_trsp.wqe_com, 0);
|
||||
bf_set(wqe_iod, &wqe->fcp_trsp.wqe_com, LPFC_WQE_IOD_NONE);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_trsp.wqe_com, LPFC_WQE_LENLOC_WORD3);
|
||||
|
||||
/* Word 11 irsp, irsplen is variable */
|
||||
bf_set(wqe_cmd_type, &wqe->fcp_trsp.wqe_com, FCP_COMMAND_TRSP);
|
||||
bf_set(wqe_cqid, &wqe->fcp_trsp.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
|
||||
bf_set(wqe_sup, &wqe->fcp_trsp.wqe_com, 0);
|
||||
bf_set(wqe_irsp, &wqe->fcp_trsp.wqe_com, 0);
|
||||
bf_set(wqe_irsplen, &wqe->fcp_trsp.wqe_com, 0);
|
||||
bf_set(wqe_pbde, &wqe->fcp_trsp.wqe_com, 0);
|
||||
|
||||
/* Word 12, 13, 14, 15 - is zero */
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_nvmet_defer_release(struct lpfc_hba *phba, struct lpfc_nvmet_rcv_ctx *ctxp)
|
||||
|
@ -130,7 +275,7 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
|
|||
if (tgtp) {
|
||||
if (status) {
|
||||
atomic_inc(&tgtp->xmt_ls_rsp_error);
|
||||
if (status == IOERR_ABORT_REQUESTED)
|
||||
if (result == IOERR_ABORT_REQUESTED)
|
||||
atomic_inc(&tgtp->xmt_ls_rsp_aborted);
|
||||
if (bf_get(lpfc_wcqe_c_xb, wcqe))
|
||||
atomic_inc(&tgtp->xmt_ls_rsp_xb_set);
|
||||
|
@ -268,8 +413,6 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
|
|||
"NVMET RCV BUSY: xri x%x sz %d "
|
||||
"from %06x\n",
|
||||
oxid, size, sid);
|
||||
/* defer repost rcv buffer till .defer_rcv callback */
|
||||
ctxp->flag &= ~LPFC_NVMET_DEFER_RCV_REPOST;
|
||||
atomic_inc(&tgtp->rcv_fcp_cmd_out);
|
||||
return;
|
||||
}
|
||||
|
@ -541,7 +684,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
|
|||
rsp->transferred_length = 0;
|
||||
if (tgtp) {
|
||||
atomic_inc(&tgtp->xmt_fcp_rsp_error);
|
||||
if (status == IOERR_ABORT_REQUESTED)
|
||||
if (result == IOERR_ABORT_REQUESTED)
|
||||
atomic_inc(&tgtp->xmt_fcp_rsp_aborted);
|
||||
}
|
||||
|
||||
|
@ -741,7 +884,10 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
|
|||
struct lpfc_nvmet_rcv_ctx *ctxp =
|
||||
container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
|
||||
struct lpfc_hba *phba = ctxp->phba;
|
||||
struct lpfc_queue *wq;
|
||||
struct lpfc_iocbq *nvmewqeq;
|
||||
struct lpfc_sli_ring *pring;
|
||||
unsigned long iflags;
|
||||
int rc;
|
||||
|
||||
if (phba->pport->load_flag & FC_UNLOADING) {
|
||||
|
@ -820,6 +966,22 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (rc == -EBUSY) {
|
||||
/*
|
||||
* WQ was full, so queue nvmewqeq to be sent after
|
||||
* WQE release CQE
|
||||
*/
|
||||
ctxp->flag |= LPFC_NVMET_DEFER_WQFULL;
|
||||
wq = phba->sli4_hba.nvme_wq[rsp->hwqid];
|
||||
pring = wq->pring;
|
||||
spin_lock_irqsave(&pring->ring_lock, iflags);
|
||||
list_add_tail(&nvmewqeq->list, &wq->wqfull_list);
|
||||
wq->q_flag |= HBA_NVMET_WQFULL;
|
||||
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
||||
atomic_inc(&lpfc_nvmep->defer_wqfull);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Give back resources */
|
||||
atomic_inc(&lpfc_nvmep->xmt_fcp_drop);
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
|
||||
|
@ -851,6 +1013,7 @@ lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port *tgtport,
|
|||
struct lpfc_nvmet_rcv_ctx *ctxp =
|
||||
container_of(req, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
|
||||
struct lpfc_hba *phba = ctxp->phba;
|
||||
struct lpfc_queue *wq;
|
||||
unsigned long flags;
|
||||
|
||||
if (phba->pport->load_flag & FC_UNLOADING)
|
||||
|
@ -880,6 +1043,15 @@ lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port *tgtport,
|
|||
}
|
||||
ctxp->flag |= LPFC_NVMET_ABORT_OP;
|
||||
|
||||
if (ctxp->flag & LPFC_NVMET_DEFER_WQFULL) {
|
||||
lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, ctxp->sid,
|
||||
ctxp->oxid);
|
||||
wq = phba->sli4_hba.nvme_wq[ctxp->wqeq->hba_wqidx];
|
||||
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
|
||||
lpfc_nvmet_wqfull_flush(phba, wq, ctxp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* An state of LPFC_NVMET_STE_RCV means we have just received
|
||||
* the NVME command and have not started processing it.
|
||||
* (by issuing any IO WQEs on this exchange yet)
|
||||
|
@ -946,11 +1118,9 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport,
|
|||
|
||||
tgtp = phba->targetport->private;
|
||||
atomic_inc(&tgtp->rcv_fcp_cmd_defer);
|
||||
if (ctxp->flag & LPFC_NVMET_DEFER_RCV_REPOST)
|
||||
lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
|
||||
else
|
||||
|
||||
/* Free the nvmebuf since a new buffer already replaced it */
|
||||
nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
|
||||
ctxp->flag &= ~LPFC_NVMET_DEFER_RCV_REPOST;
|
||||
}
|
||||
|
||||
static struct nvmet_fc_target_template lpfc_tgttemplate = {
|
||||
|
@ -1124,16 +1294,10 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba)
|
|||
}
|
||||
ctx_buf->iocbq->iocb_flag = LPFC_IO_NVMET;
|
||||
nvmewqe = ctx_buf->iocbq;
|
||||
wqe = (union lpfc_wqe128 *)&nvmewqe->wqe;
|
||||
wqe = &nvmewqe->wqe;
|
||||
|
||||
/* Initialize WQE */
|
||||
memset(wqe, 0, sizeof(union lpfc_wqe));
|
||||
/* Word 7 */
|
||||
bf_set(wqe_ct, &wqe->generic.wqe_com, SLI4_CT_RPI);
|
||||
bf_set(wqe_class, &wqe->generic.wqe_com, CLASS3);
|
||||
/* Word 10 */
|
||||
bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
|
||||
bf_set(wqe_ebde_cnt, &wqe->generic.wqe_com, 0);
|
||||
bf_set(wqe_qosd, &wqe->generic.wqe_com, 0);
|
||||
|
||||
ctx_buf->iocbq->context1 = NULL;
|
||||
spin_lock(&phba->sli4_hba.sgl_list_lock);
|
||||
|
@ -1280,6 +1444,9 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
|
|||
atomic_set(&tgtp->xmt_abort_sol, 0);
|
||||
atomic_set(&tgtp->xmt_abort_rsp, 0);
|
||||
atomic_set(&tgtp->xmt_abort_rsp_error, 0);
|
||||
atomic_set(&tgtp->defer_ctx, 0);
|
||||
atomic_set(&tgtp->defer_fod, 0);
|
||||
atomic_set(&tgtp->defer_wqfull, 0);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -1435,16 +1602,103 @@ lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_nvmet_wqfull_flush(struct lpfc_hba *phba, struct lpfc_queue *wq,
|
||||
struct lpfc_nvmet_rcv_ctx *ctxp)
|
||||
{
|
||||
struct lpfc_sli_ring *pring;
|
||||
struct lpfc_iocbq *nvmewqeq;
|
||||
struct lpfc_iocbq *next_nvmewqeq;
|
||||
unsigned long iflags;
|
||||
struct lpfc_wcqe_complete wcqe;
|
||||
struct lpfc_wcqe_complete *wcqep;
|
||||
|
||||
pring = wq->pring;
|
||||
wcqep = &wcqe;
|
||||
|
||||
/* Fake an ABORT error code back to cmpl routine */
|
||||
memset(wcqep, 0, sizeof(struct lpfc_wcqe_complete));
|
||||
bf_set(lpfc_wcqe_c_status, wcqep, IOSTAT_LOCAL_REJECT);
|
||||
wcqep->parameter = IOERR_ABORT_REQUESTED;
|
||||
|
||||
spin_lock_irqsave(&pring->ring_lock, iflags);
|
||||
list_for_each_entry_safe(nvmewqeq, next_nvmewqeq,
|
||||
&wq->wqfull_list, list) {
|
||||
if (ctxp) {
|
||||
/* Checking for a specific IO to flush */
|
||||
if (nvmewqeq->context2 == ctxp) {
|
||||
list_del(&nvmewqeq->list);
|
||||
spin_unlock_irqrestore(&pring->ring_lock,
|
||||
iflags);
|
||||
lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq,
|
||||
wcqep);
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
/* Flush all IOs */
|
||||
list_del(&nvmewqeq->list);
|
||||
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
||||
lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, wcqep);
|
||||
spin_lock_irqsave(&pring->ring_lock, iflags);
|
||||
}
|
||||
}
|
||||
if (!ctxp)
|
||||
wq->q_flag &= ~HBA_NVMET_WQFULL;
|
||||
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_nvmet_wqfull_process(struct lpfc_hba *phba,
|
||||
struct lpfc_queue *wq)
|
||||
{
|
||||
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
|
||||
struct lpfc_sli_ring *pring;
|
||||
struct lpfc_iocbq *nvmewqeq;
|
||||
unsigned long iflags;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Some WQE slots are available, so try to re-issue anything
|
||||
* on the WQ wqfull_list.
|
||||
*/
|
||||
pring = wq->pring;
|
||||
spin_lock_irqsave(&pring->ring_lock, iflags);
|
||||
while (!list_empty(&wq->wqfull_list)) {
|
||||
list_remove_head(&wq->wqfull_list, nvmewqeq, struct lpfc_iocbq,
|
||||
list);
|
||||
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
||||
rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, nvmewqeq);
|
||||
spin_lock_irqsave(&pring->ring_lock, iflags);
|
||||
if (rc == -EBUSY) {
|
||||
/* WQ was full again, so put it back on the list */
|
||||
list_add(&nvmewqeq->list, &wq->wqfull_list);
|
||||
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
wq->q_flag &= ~HBA_NVMET_WQFULL;
|
||||
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
|
||||
{
|
||||
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
|
||||
struct lpfc_nvmet_tgtport *tgtp;
|
||||
struct lpfc_queue *wq;
|
||||
uint32_t qidx;
|
||||
|
||||
if (phba->nvmet_support == 0)
|
||||
return;
|
||||
if (phba->targetport) {
|
||||
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
|
||||
for (qidx = 0; qidx < phba->cfg_nvme_io_channel; qidx++) {
|
||||
wq = phba->sli4_hba.nvme_wq[qidx];
|
||||
lpfc_nvmet_wqfull_flush(phba, wq, NULL);
|
||||
}
|
||||
init_completion(&tgtp->tport_unreg_done);
|
||||
nvmet_fc_unregister_targetport(phba->targetport);
|
||||
wait_for_completion_timeout(&tgtp->tport_unreg_done, 5);
|
||||
|
@ -1694,6 +1948,8 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
|
|||
lpfc_nvmeio_data(phba, "NVMET FCP RCV: xri x%x sz %d CPU %02x\n",
|
||||
oxid, size, smp_processor_id());
|
||||
|
||||
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
|
||||
|
||||
if (!ctx_buf) {
|
||||
/* Queue this NVME IO to process later */
|
||||
spin_lock_irqsave(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
|
||||
|
@ -1709,10 +1965,11 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
|
|||
lpfc_post_rq_buffer(
|
||||
phba, phba->sli4_hba.nvmet_mrq_hdr[qno],
|
||||
phba->sli4_hba.nvmet_mrq_data[qno], 1, qno);
|
||||
|
||||
atomic_inc(&tgtp->defer_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
|
||||
payload = (uint32_t *)(nvmebuf->dbuf.virt);
|
||||
sid = sli4_sid_from_fc_hdr(fc_hdr);
|
||||
|
||||
|
@ -1776,12 +2033,20 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
|
|||
|
||||
/* Processing of FCP command is deferred */
|
||||
if (rc == -EOVERFLOW) {
|
||||
/*
|
||||
* Post a brand new DMA buffer to RQ and defer
|
||||
* freeing rcv buffer till .defer_rcv callback
|
||||
*/
|
||||
qno = nvmebuf->idx;
|
||||
lpfc_post_rq_buffer(
|
||||
phba, phba->sli4_hba.nvmet_mrq_hdr[qno],
|
||||
phba->sli4_hba.nvmet_mrq_data[qno], 1, qno);
|
||||
|
||||
lpfc_nvmeio_data(phba,
|
||||
"NVMET RCV BUSY: xri x%x sz %d from %06x\n",
|
||||
oxid, size, sid);
|
||||
/* defer reposting rcv buffer till .defer_rcv callback */
|
||||
ctxp->flag |= LPFC_NVMET_DEFER_RCV_REPOST;
|
||||
atomic_inc(&tgtp->rcv_fcp_cmd_out);
|
||||
atomic_inc(&tgtp->defer_fod);
|
||||
return;
|
||||
}
|
||||
ctxp->rqb_buffer = nvmebuf;
|
||||
|
@ -1897,7 +2162,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba,
|
|||
{
|
||||
struct lpfc_nodelist *ndlp;
|
||||
struct lpfc_iocbq *nvmewqe;
|
||||
union lpfc_wqe *wqe;
|
||||
union lpfc_wqe128 *wqe;
|
||||
|
||||
if (!lpfc_is_link_up(phba)) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
|
||||
|
@ -2023,9 +2288,11 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
struct lpfc_iocbq *nvmewqe;
|
||||
struct scatterlist *sgel;
|
||||
union lpfc_wqe128 *wqe;
|
||||
struct ulp_bde64 *bde;
|
||||
uint32_t *txrdy;
|
||||
dma_addr_t physaddr;
|
||||
int i, cnt;
|
||||
int do_pbde;
|
||||
int xc = 1;
|
||||
|
||||
if (!lpfc_is_link_up(phba)) {
|
||||
|
@ -2078,7 +2345,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
if (((ctxp->state == LPFC_NVMET_STE_RCV) &&
|
||||
(ctxp->entry_cnt == 1)) ||
|
||||
(ctxp->state == LPFC_NVMET_STE_DATA)) {
|
||||
wqe = (union lpfc_wqe128 *)&nvmewqe->wqe;
|
||||
wqe = &nvmewqe->wqe;
|
||||
} else {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
|
||||
"6111 Wrong state NVMET FCP: %d cnt %d\n",
|
||||
|
@ -2090,6 +2357,11 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
switch (rsp->op) {
|
||||
case NVMET_FCOP_READDATA:
|
||||
case NVMET_FCOP_READDATA_RSP:
|
||||
/* From the tsend template, initialize words 7 - 11 */
|
||||
memcpy(&wqe->words[7],
|
||||
&lpfc_tsend_cmd_template.words[7],
|
||||
sizeof(uint32_t) * 5);
|
||||
|
||||
/* Words 0 - 2 : The first sg segment */
|
||||
sgel = &rsp->sg[0];
|
||||
physaddr = sg_dma_address(sgel);
|
||||
|
@ -2106,6 +2378,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
wqe->fcp_tsend.relative_offset = ctxp->offset;
|
||||
|
||||
/* Word 5 */
|
||||
wqe->fcp_tsend.reserved = 0;
|
||||
|
||||
/* Word 6 */
|
||||
bf_set(wqe_ctxt_tag, &wqe->fcp_tsend.wqe_com,
|
||||
|
@ -2113,9 +2386,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
bf_set(wqe_xri_tag, &wqe->fcp_tsend.wqe_com,
|
||||
nvmewqe->sli4_xritag);
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_pu, &wqe->fcp_tsend.wqe_com, 1);
|
||||
bf_set(wqe_cmnd, &wqe->fcp_tsend.wqe_com, CMD_FCP_TSEND64_WQE);
|
||||
/* Word 7 - set ar later */
|
||||
|
||||
/* Word 8 */
|
||||
wqe->fcp_tsend.wqe_com.abort_tag = nvmewqe->iotag;
|
||||
|
@ -2124,23 +2395,12 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
bf_set(wqe_reqtag, &wqe->fcp_tsend.wqe_com, nvmewqe->iotag);
|
||||
bf_set(wqe_rcvoxid, &wqe->fcp_tsend.wqe_com, ctxp->oxid);
|
||||
|
||||
/* Word 10 */
|
||||
bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
|
||||
bf_set(wqe_dbde, &wqe->fcp_tsend.wqe_com, 1);
|
||||
bf_set(wqe_iod, &wqe->fcp_tsend.wqe_com, LPFC_WQE_IOD_WRITE);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_tsend.wqe_com,
|
||||
LPFC_WQE_LENLOC_WORD12);
|
||||
bf_set(wqe_ebde_cnt, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, xc);
|
||||
bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
|
||||
if (phba->cfg_nvme_oas)
|
||||
bf_set(wqe_oas, &wqe->fcp_tsend.wqe_com, 1);
|
||||
/* Word 10 - set wqes later, in template xc=1 */
|
||||
if (!xc)
|
||||
bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, 0);
|
||||
|
||||
/* Word 11 */
|
||||
bf_set(wqe_cqid, &wqe->fcp_tsend.wqe_com,
|
||||
LPFC_WQE_CQ_ID_DEFAULT);
|
||||
bf_set(wqe_cmd_type, &wqe->fcp_tsend.wqe_com,
|
||||
FCP_COMMAND_TSEND);
|
||||
/* Word 11 - set sup, irsp, irsplen later */
|
||||
do_pbde = 0;
|
||||
|
||||
/* Word 12 */
|
||||
wqe->fcp_tsend.fcp_data_len = rsp->transfer_length;
|
||||
|
@ -2162,15 +2422,14 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
sgl++;
|
||||
if (rsp->op == NVMET_FCOP_READDATA_RSP) {
|
||||
atomic_inc(&tgtp->xmt_fcp_read_rsp);
|
||||
bf_set(wqe_ar, &wqe->fcp_tsend.wqe_com, 1);
|
||||
if ((ndlp->nlp_flag & NLP_SUPPRESS_RSP) &&
|
||||
(rsp->rsplen == 12)) {
|
||||
bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 1);
|
||||
bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, 0);
|
||||
|
||||
/* In template ar=1 wqes=0 sup=0 irsp=0 irsplen=0 */
|
||||
|
||||
if (rsp->rsplen == LPFC_NVMET_SUCCESS_LEN) {
|
||||
if (ndlp->nlp_flag & NLP_SUPPRESS_RSP)
|
||||
bf_set(wqe_sup,
|
||||
&wqe->fcp_tsend.wqe_com, 1);
|
||||
} else {
|
||||
bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 1);
|
||||
bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 1);
|
||||
bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com,
|
||||
|
@ -2181,15 +2440,17 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
} else {
|
||||
atomic_inc(&tgtp->xmt_fcp_read);
|
||||
|
||||
bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 0);
|
||||
/* In template ar=1 wqes=0 sup=0 irsp=0 irsplen=0 */
|
||||
bf_set(wqe_ar, &wqe->fcp_tsend.wqe_com, 0);
|
||||
bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case NVMET_FCOP_WRITEDATA:
|
||||
/* From the treceive template, initialize words 3 - 11 */
|
||||
memcpy(&wqe->words[3],
|
||||
&lpfc_treceive_cmd_template.words[3],
|
||||
sizeof(uint32_t) * 9);
|
||||
|
||||
/* Words 0 - 2 : The first sg segment */
|
||||
txrdy = dma_pool_alloc(phba->txrdy_payload_pool,
|
||||
GFP_KERNEL, &physaddr);
|
||||
|
@ -2208,14 +2469,9 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
wqe->fcp_treceive.bde.addrHigh =
|
||||
cpu_to_le32(putPaddrHigh(physaddr));
|
||||
|
||||
/* Word 3 */
|
||||
wqe->fcp_treceive.payload_offset_len = TXRDY_PAYLOAD_LEN;
|
||||
|
||||
/* Word 4 */
|
||||
wqe->fcp_treceive.relative_offset = ctxp->offset;
|
||||
|
||||
/* Word 5 */
|
||||
|
||||
/* Word 6 */
|
||||
bf_set(wqe_ctxt_tag, &wqe->fcp_treceive.wqe_com,
|
||||
phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
|
||||
|
@ -2223,10 +2479,6 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
nvmewqe->sli4_xritag);
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_pu, &wqe->fcp_treceive.wqe_com, 1);
|
||||
bf_set(wqe_ar, &wqe->fcp_treceive.wqe_com, 0);
|
||||
bf_set(wqe_cmnd, &wqe->fcp_treceive.wqe_com,
|
||||
CMD_FCP_TRECEIVE64_WQE);
|
||||
|
||||
/* Word 8 */
|
||||
wqe->fcp_treceive.wqe_com.abort_tag = nvmewqe->iotag;
|
||||
|
@ -2235,26 +2487,17 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
bf_set(wqe_reqtag, &wqe->fcp_treceive.wqe_com, nvmewqe->iotag);
|
||||
bf_set(wqe_rcvoxid, &wqe->fcp_treceive.wqe_com, ctxp->oxid);
|
||||
|
||||
/* Word 10 */
|
||||
bf_set(wqe_nvme, &wqe->fcp_treceive.wqe_com, 1);
|
||||
bf_set(wqe_dbde, &wqe->fcp_treceive.wqe_com, 1);
|
||||
bf_set(wqe_iod, &wqe->fcp_treceive.wqe_com, LPFC_WQE_IOD_READ);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_treceive.wqe_com,
|
||||
LPFC_WQE_LENLOC_WORD12);
|
||||
bf_set(wqe_xc, &wqe->fcp_treceive.wqe_com, xc);
|
||||
bf_set(wqe_wqes, &wqe->fcp_treceive.wqe_com, 0);
|
||||
bf_set(wqe_irsp, &wqe->fcp_treceive.wqe_com, 0);
|
||||
bf_set(wqe_irsplen, &wqe->fcp_treceive.wqe_com, 0);
|
||||
bf_set(wqe_nvme, &wqe->fcp_treceive.wqe_com, 1);
|
||||
if (phba->cfg_nvme_oas)
|
||||
bf_set(wqe_oas, &wqe->fcp_treceive.wqe_com, 1);
|
||||
/* Word 10 - in template xc=1 */
|
||||
if (!xc)
|
||||
bf_set(wqe_xc, &wqe->fcp_treceive.wqe_com, 0);
|
||||
|
||||
/* Word 11 */
|
||||
bf_set(wqe_cqid, &wqe->fcp_treceive.wqe_com,
|
||||
LPFC_WQE_CQ_ID_DEFAULT);
|
||||
bf_set(wqe_cmd_type, &wqe->fcp_treceive.wqe_com,
|
||||
FCP_COMMAND_TRECEIVE);
|
||||
bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0);
|
||||
/* Word 11 - set pbde later */
|
||||
if (phba->nvme_embed_pbde) {
|
||||
do_pbde = 1;
|
||||
} else {
|
||||
bf_set(wqe_pbde, &wqe->fcp_treceive.wqe_com, 0);
|
||||
do_pbde = 0;
|
||||
}
|
||||
|
||||
/* Word 12 */
|
||||
wqe->fcp_tsend.fcp_data_len = rsp->transfer_length;
|
||||
|
@ -2282,6 +2525,11 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
break;
|
||||
|
||||
case NVMET_FCOP_RSP:
|
||||
/* From the treceive template, initialize words 4 - 11 */
|
||||
memcpy(&wqe->words[4],
|
||||
&lpfc_trsp_cmd_template.words[4],
|
||||
sizeof(uint32_t) * 8);
|
||||
|
||||
/* Words 0 - 2 */
|
||||
physaddr = rsp->rspdma;
|
||||
wqe->fcp_trsp.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
|
||||
|
@ -2294,12 +2542,6 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
/* Word 3 */
|
||||
wqe->fcp_trsp.response_len = rsp->rsplen;
|
||||
|
||||
/* Word 4 */
|
||||
wqe->fcp_trsp.rsvd_4_5[0] = 0;
|
||||
|
||||
|
||||
/* Word 5 */
|
||||
|
||||
/* Word 6 */
|
||||
bf_set(wqe_ctxt_tag, &wqe->fcp_trsp.wqe_com,
|
||||
phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
|
||||
|
@ -2307,9 +2549,6 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
nvmewqe->sli4_xritag);
|
||||
|
||||
/* Word 7 */
|
||||
bf_set(wqe_pu, &wqe->fcp_trsp.wqe_com, 0);
|
||||
bf_set(wqe_ag, &wqe->fcp_trsp.wqe_com, 1);
|
||||
bf_set(wqe_cmnd, &wqe->fcp_trsp.wqe_com, CMD_FCP_TRSP64_WQE);
|
||||
|
||||
/* Word 8 */
|
||||
wqe->fcp_trsp.wqe_com.abort_tag = nvmewqe->iotag;
|
||||
|
@ -2319,35 +2558,23 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
bf_set(wqe_rcvoxid, &wqe->fcp_trsp.wqe_com, ctxp->oxid);
|
||||
|
||||
/* Word 10 */
|
||||
bf_set(wqe_nvme, &wqe->fcp_trsp.wqe_com, 1);
|
||||
bf_set(wqe_dbde, &wqe->fcp_trsp.wqe_com, 0);
|
||||
bf_set(wqe_iod, &wqe->fcp_trsp.wqe_com, LPFC_WQE_IOD_WRITE);
|
||||
bf_set(wqe_lenloc, &wqe->fcp_trsp.wqe_com,
|
||||
LPFC_WQE_LENLOC_WORD3);
|
||||
bf_set(wqe_xc, &wqe->fcp_trsp.wqe_com, xc);
|
||||
bf_set(wqe_nvme, &wqe->fcp_trsp.wqe_com, 1);
|
||||
if (phba->cfg_nvme_oas)
|
||||
bf_set(wqe_oas, &wqe->fcp_trsp.wqe_com, 1);
|
||||
if (xc)
|
||||
bf_set(wqe_xc, &wqe->fcp_trsp.wqe_com, 1);
|
||||
|
||||
/* Word 11 */
|
||||
bf_set(wqe_cqid, &wqe->fcp_trsp.wqe_com,
|
||||
LPFC_WQE_CQ_ID_DEFAULT);
|
||||
bf_set(wqe_cmd_type, &wqe->fcp_trsp.wqe_com,
|
||||
FCP_COMMAND_TRSP);
|
||||
bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0);
|
||||
|
||||
if (rsp->rsplen == LPFC_NVMET_SUCCESS_LEN) {
|
||||
/* Good response - all zero's on wire */
|
||||
bf_set(wqe_wqes, &wqe->fcp_trsp.wqe_com, 0);
|
||||
bf_set(wqe_irsp, &wqe->fcp_trsp.wqe_com, 0);
|
||||
bf_set(wqe_irsplen, &wqe->fcp_trsp.wqe_com, 0);
|
||||
} else {
|
||||
/* In template wqes=0 irsp=0 irsplen=0 - good response */
|
||||
if (rsp->rsplen != LPFC_NVMET_SUCCESS_LEN) {
|
||||
/* Bad response - embed it */
|
||||
bf_set(wqe_wqes, &wqe->fcp_trsp.wqe_com, 1);
|
||||
bf_set(wqe_irsp, &wqe->fcp_trsp.wqe_com, 1);
|
||||
bf_set(wqe_irsplen, &wqe->fcp_trsp.wqe_com,
|
||||
((rsp->rsplen >> 2) - 1));
|
||||
memcpy(&wqe->words[16], rsp->rspaddr, rsp->rsplen);
|
||||
}
|
||||
do_pbde = 0;
|
||||
|
||||
/* Word 12 */
|
||||
wqe->fcp_trsp.rsvd_12_15[0] = 0;
|
||||
|
||||
/* Use rspbuf, NOT sg list */
|
||||
rsp->sg_cnt = 0;
|
||||
|
@ -2380,6 +2607,17 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
|
|||
bf_set(lpfc_sli4_sge_last, sgl, 1);
|
||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||
sgl->sge_len = cpu_to_le32(cnt);
|
||||
if (do_pbde && i == 0) {
|
||||
bde = (struct ulp_bde64 *)&wqe->words[13];
|
||||
memset(bde, 0, sizeof(struct ulp_bde64));
|
||||
/* Words 13-15 (PBDE)*/
|
||||
bde->addrLow = sgl->addr_lo;
|
||||
bde->addrHigh = sgl->addr_hi;
|
||||
bde->tus.f.bdeSize =
|
||||
le32_to_cpu(sgl->sge_len);
|
||||
bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
|
||||
bde->tus.w = cpu_to_le32(bde->tus.w);
|
||||
}
|
||||
sgl++;
|
||||
ctxp->offset += cnt;
|
||||
}
|
||||
|
@ -2597,7 +2835,7 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba,
|
|||
{
|
||||
struct lpfc_nvmet_tgtport *tgtp;
|
||||
struct lpfc_iocbq *abts_wqeq;
|
||||
union lpfc_wqe *wqe_abts;
|
||||
union lpfc_wqe128 *wqe_abts;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
|
||||
|
@ -2692,7 +2930,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
|
|||
{
|
||||
struct lpfc_nvmet_tgtport *tgtp;
|
||||
struct lpfc_iocbq *abts_wqeq;
|
||||
union lpfc_wqe *abts_wqe;
|
||||
union lpfc_wqe128 *abts_wqe;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
@ -2882,7 +3120,7 @@ lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *phba,
|
|||
{
|
||||
struct lpfc_nvmet_tgtport *tgtp;
|
||||
struct lpfc_iocbq *abts_wqeq;
|
||||
union lpfc_wqe *wqe_abts;
|
||||
union lpfc_wqe128 *wqe_abts;
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -72,7 +72,6 @@ struct lpfc_nvmet_tgtport {
|
|||
atomic_t xmt_fcp_rsp_aborted;
|
||||
atomic_t xmt_fcp_rsp_drop;
|
||||
|
||||
|
||||
/* Stats counters - lpfc_nvmet_xmt_fcp_abort */
|
||||
atomic_t xmt_fcp_xri_abort_cqe;
|
||||
atomic_t xmt_fcp_abort;
|
||||
|
@ -81,6 +80,11 @@ struct lpfc_nvmet_tgtport {
|
|||
atomic_t xmt_abort_unsol;
|
||||
atomic_t xmt_abort_rsp;
|
||||
atomic_t xmt_abort_rsp_error;
|
||||
|
||||
/* Stats counters - defer IO */
|
||||
atomic_t defer_ctx;
|
||||
atomic_t defer_fod;
|
||||
atomic_t defer_wqfull;
|
||||
};
|
||||
|
||||
struct lpfc_nvmet_ctx_info {
|
||||
|
@ -131,7 +135,7 @@ struct lpfc_nvmet_rcv_ctx {
|
|||
#define LPFC_NVMET_XBUSY 0x4 /* XB bit set on IO cmpl */
|
||||
#define LPFC_NVMET_CTX_RLS 0x8 /* ctx free requested */
|
||||
#define LPFC_NVMET_ABTS_RCV 0x10 /* ABTS received on exchange */
|
||||
#define LPFC_NVMET_DEFER_RCV_REPOST 0x20 /* repost to RQ on defer rcv */
|
||||
#define LPFC_NVMET_DEFER_WQFULL 0x40 /* Waiting on a free WQE */
|
||||
struct rqb_dmabuf *rqb_buffer;
|
||||
struct lpfc_nvmet_ctxbuf *ctxbuf;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -837,8 +837,13 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
|
|||
* 4K Page alignment is CRITICAL to BlockGuard, double check
|
||||
* to be sure.
|
||||
*/
|
||||
if (phba->cfg_enable_bg && (((unsigned long)(psb->data) &
|
||||
if ((phba->sli3_options & LPFC_SLI3_BG_ENABLED) &&
|
||||
(((unsigned long)(psb->data) &
|
||||
(unsigned long)(SLI4_PAGE_SIZE - 1)) != 0)) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
||||
"3369 Memory alignment error "
|
||||
"addr=%lx\n",
|
||||
(unsigned long)psb->data);
|
||||
dma_pool_free(phba->lpfc_sg_dma_buf_pool,
|
||||
psb->data, psb->dma_handle);
|
||||
kfree(psb);
|
||||
|
@ -3304,8 +3309,12 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
|
|||
dma_offset += dma_len;
|
||||
sgl++;
|
||||
}
|
||||
/* setup the performance hint (first data BDE) if enabled */
|
||||
if (phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) {
|
||||
/*
|
||||
* Setup the first Payload BDE. For FCoE we just key off
|
||||
* Performance Hints, for FC we utilize fcp_embed_pbde.
|
||||
*/
|
||||
if ((phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) ||
|
||||
phba->fcp_embed_pbde) {
|
||||
bde = (struct ulp_bde64 *)
|
||||
&(iocb_cmd->unsli3.sli3Words[5]);
|
||||
bde->addrLow = first_data_sgl->addr_lo;
|
||||
|
@ -3772,20 +3781,18 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
|
|||
scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId));
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_UNDER,
|
||||
"9025 FCP Read Underrun, expected %d, "
|
||||
"9025 FCP Underrun, expected %d, "
|
||||
"residual %d Data: x%x x%x x%x\n",
|
||||
fcpDl,
|
||||
scsi_get_resid(cmnd), fcpi_parm, cmnd->cmnd[0],
|
||||
cmnd->underflow);
|
||||
|
||||
/*
|
||||
* If there is an under run check if under run reported by
|
||||
* If there is an under run, check if under run reported by
|
||||
* storage array is same as the under run reported by HBA.
|
||||
* If this is not same, there is a dropped frame.
|
||||
*/
|
||||
if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
|
||||
fcpi_parm &&
|
||||
(scsi_get_resid(cmnd) != fcpi_parm)) {
|
||||
if (fcpi_parm && (scsi_get_resid(cmnd) != fcpi_parm)) {
|
||||
lpfc_printf_vlog(vport, KERN_WARNING,
|
||||
LOG_FCP | LOG_FCP_ERROR,
|
||||
"9026 FCP Read Check Error "
|
||||
|
@ -3926,7 +3933,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|||
struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
|
||||
struct lpfc_nodelist *pnode = rdata->pnode;
|
||||
struct scsi_cmnd *cmd;
|
||||
int depth;
|
||||
unsigned long flags;
|
||||
struct lpfc_fast_path_event *fast_path_evt;
|
||||
struct Scsi_Host *shost;
|
||||
|
@ -4132,15 +4138,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|||
}
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
} else if (pnode && NLP_CHK_NODE_ACT(pnode)) {
|
||||
if ((pnode->cmd_qdepth < vport->cfg_tgt_queue_depth) &&
|
||||
if ((pnode->cmd_qdepth != vport->cfg_tgt_queue_depth) &&
|
||||
time_after(jiffies, pnode->last_change_time +
|
||||
msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) {
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
depth = pnode->cmd_qdepth * LPFC_TGTQ_RAMPUP_PCENT
|
||||
/ 100;
|
||||
depth = depth ? depth : 1;
|
||||
pnode->cmd_qdepth += depth;
|
||||
if (pnode->cmd_qdepth > vport->cfg_tgt_queue_depth)
|
||||
pnode->cmd_qdepth = vport->cfg_tgt_queue_depth;
|
||||
pnode->last_change_time = jiffies;
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
@ -4564,9 +4565,32 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
|
|||
*/
|
||||
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
|
||||
goto out_tgt_busy;
|
||||
if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth)
|
||||
if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_ERROR,
|
||||
"3377 Target Queue Full, scsi Id:%d Qdepth:%d"
|
||||
" Pending command:%d"
|
||||
" WWNN:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, "
|
||||
" WWPN:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ndlp->nlp_sid, ndlp->cmd_qdepth,
|
||||
atomic_read(&ndlp->cmd_pending),
|
||||
ndlp->nlp_nodename.u.wwn[0],
|
||||
ndlp->nlp_nodename.u.wwn[1],
|
||||
ndlp->nlp_nodename.u.wwn[2],
|
||||
ndlp->nlp_nodename.u.wwn[3],
|
||||
ndlp->nlp_nodename.u.wwn[4],
|
||||
ndlp->nlp_nodename.u.wwn[5],
|
||||
ndlp->nlp_nodename.u.wwn[6],
|
||||
ndlp->nlp_nodename.u.wwn[7],
|
||||
ndlp->nlp_portname.u.wwn[0],
|
||||
ndlp->nlp_portname.u.wwn[1],
|
||||
ndlp->nlp_portname.u.wwn[2],
|
||||
ndlp->nlp_portname.u.wwn[3],
|
||||
ndlp->nlp_portname.u.wwn[4],
|
||||
ndlp->nlp_portname.u.wwn[5],
|
||||
ndlp->nlp_portname.u.wwn[6],
|
||||
ndlp->nlp_portname.u.wwn[7]);
|
||||
goto out_tgt_busy;
|
||||
|
||||
}
|
||||
lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp);
|
||||
if (lpfc_cmd == NULL) {
|
||||
lpfc_rampdown_queue_depth(phba);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -61,9 +61,8 @@ struct lpfc_iocbq {
|
|||
struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */
|
||||
uint64_t isr_timestamp;
|
||||
|
||||
/* Be careful here */
|
||||
union lpfc_wqe wqe; /* WQE cmd */
|
||||
IOCB_t iocb; /* For IOCB cmd or if we want 128 byte WQE */
|
||||
union lpfc_wqe128 wqe; /* SLI-4 */
|
||||
IOCB_t iocb; /* SLI-3 */
|
||||
|
||||
uint8_t rsvd2;
|
||||
uint8_t priority; /* OAS priority */
|
||||
|
@ -148,6 +147,7 @@ typedef struct lpfcMboxq {
|
|||
struct lpfc_vport *vport;/* virtual port pointer */
|
||||
void *context1; /* caller context information */
|
||||
void *context2; /* caller context information */
|
||||
void *context3;
|
||||
|
||||
void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
|
||||
uint8_t mbox_flag;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2009-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -145,6 +145,7 @@ struct lpfc_rqb {
|
|||
struct lpfc_queue {
|
||||
struct list_head list;
|
||||
struct list_head wq_list;
|
||||
struct list_head wqfull_list;
|
||||
enum lpfc_sli4_queue_type type;
|
||||
enum lpfc_sli4_queue_subtype subtype;
|
||||
struct lpfc_hba *phba;
|
||||
|
@ -173,10 +174,16 @@ struct lpfc_queue {
|
|||
#define LPFC_EXPANDED_PAGE_SIZE 16384
|
||||
#define LPFC_DEFAULT_PAGE_SIZE 4096
|
||||
uint16_t chann; /* IO channel this queue is associated with */
|
||||
uint16_t db_format;
|
||||
uint8_t db_format;
|
||||
#define LPFC_DB_RING_FORMAT 0x01
|
||||
#define LPFC_DB_LIST_FORMAT 0x02
|
||||
uint8_t q_flag;
|
||||
#define HBA_NVMET_WQFULL 0x1 /* We hit WQ Full condition for NVMET */
|
||||
void __iomem *db_regaddr;
|
||||
uint16_t dpp_enable;
|
||||
uint16_t dpp_id;
|
||||
void __iomem *dpp_regaddr;
|
||||
|
||||
/* For q stats */
|
||||
uint32_t q_cnt_1;
|
||||
uint32_t q_cnt_2;
|
||||
|
@ -209,6 +216,7 @@ struct lpfc_queue {
|
|||
struct work_struct spwork;
|
||||
|
||||
uint64_t isr_timestamp;
|
||||
uint8_t qe_valid;
|
||||
struct lpfc_queue *assoc_qp;
|
||||
union sli4_qe qe[1]; /* array to index entries (must be last) */
|
||||
};
|
||||
|
@ -479,12 +487,19 @@ struct lpfc_pc_sli4_params {
|
|||
uint8_t mqv;
|
||||
uint8_t wqv;
|
||||
uint8_t rqv;
|
||||
uint8_t eqav;
|
||||
uint8_t cqav;
|
||||
uint8_t wqsize;
|
||||
#define LPFC_WQ_SZ64_SUPPORT 1
|
||||
#define LPFC_WQ_SZ128_SUPPORT 2
|
||||
uint8_t wqpcnt;
|
||||
};
|
||||
|
||||
#define LPFC_CQ_4K_PAGE_SZ 0x1
|
||||
#define LPFC_CQ_16K_PAGE_SZ 0x4
|
||||
#define LPFC_WQ_4K_PAGE_SZ 0x1
|
||||
#define LPFC_WQ_16K_PAGE_SZ 0x4
|
||||
|
||||
struct lpfc_iov {
|
||||
uint32_t pf_number;
|
||||
uint32_t vf_number;
|
||||
|
@ -516,11 +531,17 @@ struct lpfc_vector_map_info {
|
|||
/* SLI4 HBA data structure entries */
|
||||
struct lpfc_sli4_hba {
|
||||
void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for
|
||||
PCI BAR0, config space registers */
|
||||
* config space registers
|
||||
*/
|
||||
void __iomem *ctrl_regs_memmap_p; /* Kernel memory mapped address for
|
||||
PCI BAR1, control registers */
|
||||
* control registers
|
||||
*/
|
||||
void __iomem *drbl_regs_memmap_p; /* Kernel memory mapped address for
|
||||
PCI BAR2, doorbell registers */
|
||||
* doorbell registers
|
||||
*/
|
||||
void __iomem *dpp_regs_memmap_p; /* Kernel memory mapped address for
|
||||
* dpp registers
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
/* IF Type 0, BAR 0 PCI cfg space reg mem map */
|
||||
|
@ -561,7 +582,8 @@ struct lpfc_sli4_hba {
|
|||
/* IF type 0, BAR 0 and if type 2, BAR 0 doorbell register memory map */
|
||||
void __iomem *RQDBregaddr; /* RQ_DOORBELL register */
|
||||
void __iomem *WQDBregaddr; /* WQ_DOORBELL register */
|
||||
void __iomem *EQCQDBregaddr; /* EQCQ_DOORBELL register */
|
||||
void __iomem *CQDBregaddr; /* CQ_DOORBELL register */
|
||||
void __iomem *EQDBregaddr; /* EQ_DOORBELL register */
|
||||
void __iomem *MQDBregaddr; /* MQ_DOORBELL register */
|
||||
void __iomem *BMBXregaddr; /* BootStrap MBX register */
|
||||
|
||||
|
@ -574,6 +596,10 @@ struct lpfc_sli4_hba {
|
|||
struct lpfc_bbscn_params bbscn_params;
|
||||
struct lpfc_hba_eq_hdl *hba_eq_hdl; /* HBA per-WQ handle */
|
||||
|
||||
void (*sli4_eq_clr_intr)(struct lpfc_queue *q);
|
||||
uint32_t (*sli4_eq_release)(struct lpfc_queue *q, bool arm);
|
||||
uint32_t (*sli4_cq_release)(struct lpfc_queue *q, bool arm);
|
||||
|
||||
/* Pointers to the constructed SLI4 queues */
|
||||
struct lpfc_queue **hba_eq; /* Event queues for HBA */
|
||||
struct lpfc_queue **fcp_cq; /* Fast-path FCP compl queue */
|
||||
|
@ -840,8 +866,12 @@ void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *);
|
|||
int lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *);
|
||||
int lpfc_sli4_get_iocb_cnt(struct lpfc_hba *phba);
|
||||
int lpfc_sli4_init_vpi(struct lpfc_vport *);
|
||||
inline void lpfc_sli4_eq_clr_intr(struct lpfc_queue *);
|
||||
uint32_t lpfc_sli4_cq_release(struct lpfc_queue *, bool);
|
||||
uint32_t lpfc_sli4_eq_release(struct lpfc_queue *, bool);
|
||||
inline void lpfc_sli4_if6_eq_clr_intr(struct lpfc_queue *q);
|
||||
uint32_t lpfc_sli4_if6_cq_release(struct lpfc_queue *q, bool arm);
|
||||
uint32_t lpfc_sli4_if6_eq_release(struct lpfc_queue *q, bool arm);
|
||||
void lpfc_sli4_fcfi_unreg(struct lpfc_hba *, uint16_t);
|
||||
int lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *, uint16_t);
|
||||
int lpfc_sli4_fcf_rr_read_fcf_rec(struct lpfc_hba *, uint16_t);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
@ -20,7 +20,7 @@
|
|||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "11.4.0.6"
|
||||
#define LPFC_DRIVER_VERSION "12.0.0.1"
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
/* Used for SLI 2/3 */
|
||||
|
@ -32,6 +32,6 @@
|
|||
|
||||
#define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
|
||||
LPFC_DRIVER_VERSION
|
||||
#define LPFC_COPYRIGHT "Copyright (C) 2017 Broadcom. All Rights Reserved. " \
|
||||
"The term \"Broadcom\" refers to Broadcom Limited " \
|
||||
#define LPFC_COPYRIGHT "Copyright (C) 2017-2018 Broadcom. All Rights " \
|
||||
"Reserved. The term \"Broadcom\" refers to Broadcom Limited " \
|
||||
"and/or its subsidiaries."
|
||||
|
|
|
@ -4022,7 +4022,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
|
|||
|
||||
cmd = instance->cmd_list[i];
|
||||
|
||||
cmd->frame = dma_pool_alloc(instance->frame_dma_pool,
|
||||
cmd->frame = dma_pool_zalloc(instance->frame_dma_pool,
|
||||
GFP_KERNEL, &cmd->frame_phys_addr);
|
||||
|
||||
cmd->sense = dma_pool_alloc(instance->sense_dma_pool,
|
||||
|
@ -4038,7 +4038,6 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(cmd->frame, 0, instance->mfi_frame_size);
|
||||
cmd->frame->io.context = cpu_to_le32(cmd->index);
|
||||
cmd->frame->io.pad_0 = 0;
|
||||
if ((instance->adapter_type == MFI_SERIES) && reset_devices)
|
||||
|
|
|
@ -524,6 +524,7 @@ typedef struct _MPI2_CONFIG_REPLY {
|
|||
#define MPI2_MFGPAGE_DEVID_SAS2308_1 (0x0086)
|
||||
#define MPI2_MFGPAGE_DEVID_SAS2308_2 (0x0087)
|
||||
#define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E)
|
||||
#define MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP (0x02B0)
|
||||
|
||||
/*MPI v2.5 SAS products */
|
||||
#define MPI25_MFGPAGE_DEVID_SAS3004 (0x0096)
|
||||
|
|
|
@ -125,6 +125,362 @@ _scsih_set_fwfault_debug(const char *val, const struct kernel_param *kp)
|
|||
module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug,
|
||||
param_get_int, &mpt3sas_fwfault_debug, 0644);
|
||||
|
||||
/**
|
||||
* _base_clone_reply_to_sys_mem - copies reply to reply free iomem
|
||||
* in BAR0 space.
|
||||
*
|
||||
* @ioc: per adapter object
|
||||
* @reply: reply message frame(lower 32bit addr)
|
||||
* @index: System request message index.
|
||||
*
|
||||
* @Returns - Nothing
|
||||
*/
|
||||
static void
|
||||
_base_clone_reply_to_sys_mem(struct MPT3SAS_ADAPTER *ioc, u32 reply,
|
||||
u32 index)
|
||||
{
|
||||
/*
|
||||
* 256 is offset within sys register.
|
||||
* 256 offset MPI frame starts. Max MPI frame supported is 32.
|
||||
* 32 * 128 = 4K. From here, Clone of reply free for mcpu starts
|
||||
*/
|
||||
u16 cmd_credit = ioc->facts.RequestCredit + 1;
|
||||
void __iomem *reply_free_iomem = (void __iomem *)ioc->chip +
|
||||
MPI_FRAME_START_OFFSET +
|
||||
(cmd_credit * ioc->request_sz) + (index * sizeof(u32));
|
||||
|
||||
writel(reply, reply_free_iomem);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_clone_mpi_to_sys_mem - Writes/copies MPI frames
|
||||
* to system/BAR0 region.
|
||||
*
|
||||
* @dst_iomem: Pointer to the destinaltion location in BAR0 space.
|
||||
* @src: Pointer to the Source data.
|
||||
* @size: Size of data to be copied.
|
||||
*/
|
||||
static void
|
||||
_base_clone_mpi_to_sys_mem(void *dst_iomem, void *src, u32 size)
|
||||
{
|
||||
int i;
|
||||
u32 *src_virt_mem = (u32 *)src;
|
||||
|
||||
for (i = 0; i < size/4; i++)
|
||||
writel((u32)src_virt_mem[i],
|
||||
(void __iomem *)dst_iomem + (i * 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region
|
||||
*
|
||||
* @dst_iomem: Pointer to the destination location in BAR0 space.
|
||||
* @src: Pointer to the Source data.
|
||||
* @size: Size of data to be copied.
|
||||
*/
|
||||
static void
|
||||
_base_clone_to_sys_mem(void __iomem *dst_iomem, void *src, u32 size)
|
||||
{
|
||||
int i;
|
||||
u32 *src_virt_mem = (u32 *)(src);
|
||||
|
||||
for (i = 0; i < size/4; i++)
|
||||
writel((u32)src_virt_mem[i],
|
||||
(void __iomem *)dst_iomem + (i * 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_get_chain - Calculates and Returns virtual chain address
|
||||
* for the provided smid in BAR0 space.
|
||||
*
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
* @sge_chain_count: Scatter gather chain count.
|
||||
*
|
||||
* @Return: chain address.
|
||||
*/
|
||||
static inline void __iomem*
|
||||
_base_get_chain(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
u8 sge_chain_count)
|
||||
{
|
||||
void __iomem *base_chain, *chain_virt;
|
||||
u16 cmd_credit = ioc->facts.RequestCredit + 1;
|
||||
|
||||
base_chain = (void __iomem *)ioc->chip + MPI_FRAME_START_OFFSET +
|
||||
(cmd_credit * ioc->request_sz) +
|
||||
REPLY_FREE_POOL_SIZE;
|
||||
chain_virt = base_chain + (smid * ioc->facts.MaxChainDepth *
|
||||
ioc->request_sz) + (sge_chain_count * ioc->request_sz);
|
||||
return chain_virt;
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_get_chain_phys - Calculates and Returns physical address
|
||||
* in BAR0 for scatter gather chains, for
|
||||
* the provided smid.
|
||||
*
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
* @sge_chain_count: Scatter gather chain count.
|
||||
*
|
||||
* @Return - Physical chain address.
|
||||
*/
|
||||
static inline phys_addr_t
|
||||
_base_get_chain_phys(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
u8 sge_chain_count)
|
||||
{
|
||||
phys_addr_t base_chain_phys, chain_phys;
|
||||
u16 cmd_credit = ioc->facts.RequestCredit + 1;
|
||||
|
||||
base_chain_phys = ioc->chip_phys + MPI_FRAME_START_OFFSET +
|
||||
(cmd_credit * ioc->request_sz) +
|
||||
REPLY_FREE_POOL_SIZE;
|
||||
chain_phys = base_chain_phys + (smid * ioc->facts.MaxChainDepth *
|
||||
ioc->request_sz) + (sge_chain_count * ioc->request_sz);
|
||||
return chain_phys;
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_get_buffer_bar0 - Calculates and Returns BAR0 mapped Host
|
||||
* buffer address for the provided smid.
|
||||
* (Each smid can have 64K starts from 17024)
|
||||
*
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
*
|
||||
* @Returns - Pointer to buffer location in BAR0.
|
||||
*/
|
||||
|
||||
static void __iomem *
|
||||
_base_get_buffer_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||
{
|
||||
u16 cmd_credit = ioc->facts.RequestCredit + 1;
|
||||
// Added extra 1 to reach end of chain.
|
||||
void __iomem *chain_end = _base_get_chain(ioc,
|
||||
cmd_credit + 1,
|
||||
ioc->facts.MaxChainDepth);
|
||||
return chain_end + (smid * 64 * 1024);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_get_buffer_phys_bar0 - Calculates and Returns BAR0 mapped
|
||||
* Host buffer Physical address for the provided smid.
|
||||
* (Each smid can have 64K starts from 17024)
|
||||
*
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
*
|
||||
* @Returns - Pointer to buffer location in BAR0.
|
||||
*/
|
||||
static phys_addr_t
|
||||
_base_get_buffer_phys_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||
{
|
||||
u16 cmd_credit = ioc->facts.RequestCredit + 1;
|
||||
phys_addr_t chain_end_phys = _base_get_chain_phys(ioc,
|
||||
cmd_credit + 1,
|
||||
ioc->facts.MaxChainDepth);
|
||||
return chain_end_phys + (smid * 64 * 1024);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_get_chain_buffer_dma_to_chain_buffer - Iterates chain
|
||||
* lookup list and Provides chain_buffer
|
||||
* address for the matching dma address.
|
||||
* (Each smid can have 64K starts from 17024)
|
||||
*
|
||||
* @ioc: per adapter object
|
||||
* @chain_buffer_dma: Chain buffer dma address.
|
||||
*
|
||||
* @Returns - Pointer to chain buffer. Or Null on Failure.
|
||||
*/
|
||||
static void *
|
||||
_base_get_chain_buffer_dma_to_chain_buffer(struct MPT3SAS_ADAPTER *ioc,
|
||||
dma_addr_t chain_buffer_dma)
|
||||
{
|
||||
u16 index;
|
||||
|
||||
for (index = 0; index < ioc->chain_depth; index++) {
|
||||
if (ioc->chain_lookup[index].chain_buffer_dma ==
|
||||
chain_buffer_dma)
|
||||
return ioc->chain_lookup[index].chain_buffer;
|
||||
}
|
||||
pr_info(MPT3SAS_FMT
|
||||
"Provided chain_buffer_dma address is not in the lookup list\n",
|
||||
ioc->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* _clone_sg_entries - MPI EP's scsiio and config requests
|
||||
* are handled here. Base function for
|
||||
* double buffering, before submitting
|
||||
* the requests.
|
||||
*
|
||||
* @ioc: per adapter object.
|
||||
* @mpi_request: mf request pointer.
|
||||
* @smid: system request message index.
|
||||
*
|
||||
* @Returns: Nothing.
|
||||
*/
|
||||
static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc,
|
||||
void *mpi_request, u16 smid)
|
||||
{
|
||||
Mpi2SGESimple32_t *sgel, *sgel_next;
|
||||
u32 sgl_flags, sge_chain_count = 0;
|
||||
bool is_write = 0;
|
||||
u16 i = 0;
|
||||
void __iomem *buffer_iomem;
|
||||
phys_addr_t buffer_iomem_phys;
|
||||
void __iomem *buff_ptr;
|
||||
phys_addr_t buff_ptr_phys;
|
||||
void __iomem *dst_chain_addr[MCPU_MAX_CHAINS_PER_IO];
|
||||
void *src_chain_addr[MCPU_MAX_CHAINS_PER_IO];
|
||||
phys_addr_t dst_addr_phys;
|
||||
MPI2RequestHeader_t *request_hdr;
|
||||
struct scsi_cmnd *scmd;
|
||||
struct scatterlist *sg_scmd = NULL;
|
||||
int is_scsiio_req = 0;
|
||||
|
||||
request_hdr = (MPI2RequestHeader_t *) mpi_request;
|
||||
|
||||
if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
|
||||
Mpi25SCSIIORequest_t *scsiio_request =
|
||||
(Mpi25SCSIIORequest_t *)mpi_request;
|
||||
sgel = (Mpi2SGESimple32_t *) &scsiio_request->SGL;
|
||||
is_scsiio_req = 1;
|
||||
} else if (request_hdr->Function == MPI2_FUNCTION_CONFIG) {
|
||||
Mpi2ConfigRequest_t *config_req =
|
||||
(Mpi2ConfigRequest_t *)mpi_request;
|
||||
sgel = (Mpi2SGESimple32_t *) &config_req->PageBufferSGE;
|
||||
} else
|
||||
return;
|
||||
|
||||
/* From smid we can get scsi_cmd, once we have sg_scmd,
|
||||
* we just need to get sg_virt and sg_next to get virual
|
||||
* address associated with sgel->Address.
|
||||
*/
|
||||
|
||||
if (is_scsiio_req) {
|
||||
/* Get scsi_cmd using smid */
|
||||
scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);
|
||||
if (scmd == NULL) {
|
||||
pr_err(MPT3SAS_FMT "scmd is NULL\n", ioc->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get sg_scmd from scmd provided */
|
||||
sg_scmd = scsi_sglist(scmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* 0 - 255 System register
|
||||
* 256 - 4352 MPI Frame. (This is based on maxCredit 32)
|
||||
* 4352 - 4864 Reply_free pool (512 byte is reserved
|
||||
* considering maxCredit 32. Reply need extra
|
||||
* room, for mCPU case kept four times of
|
||||
* maxCredit).
|
||||
* 4864 - 17152 SGE chain element. (32cmd * 3 chain of
|
||||
* 128 byte size = 12288)
|
||||
* 17152 - x Host buffer mapped with smid.
|
||||
* (Each smid can have 64K Max IO.)
|
||||
* BAR0+Last 1K MSIX Addr and Data
|
||||
* Total size in use 2113664 bytes of 4MB BAR0
|
||||
*/
|
||||
|
||||
buffer_iomem = _base_get_buffer_bar0(ioc, smid);
|
||||
buffer_iomem_phys = _base_get_buffer_phys_bar0(ioc, smid);
|
||||
|
||||
buff_ptr = buffer_iomem;
|
||||
buff_ptr_phys = buffer_iomem_phys;
|
||||
WARN_ON(buff_ptr_phys > U32_MAX);
|
||||
|
||||
if (sgel->FlagsLength &
|
||||
(MPI2_SGE_FLAGS_HOST_TO_IOC << MPI2_SGE_FLAGS_SHIFT))
|
||||
is_write = 1;
|
||||
|
||||
for (i = 0; i < MPT_MIN_PHYS_SEGMENTS + ioc->facts.MaxChainDepth; i++) {
|
||||
|
||||
sgl_flags = (sgel->FlagsLength >> MPI2_SGE_FLAGS_SHIFT);
|
||||
|
||||
switch (sgl_flags & MPI2_SGE_FLAGS_ELEMENT_MASK) {
|
||||
case MPI2_SGE_FLAGS_CHAIN_ELEMENT:
|
||||
/*
|
||||
* Helper function which on passing
|
||||
* chain_buffer_dma returns chain_buffer. Get
|
||||
* the virtual address for sgel->Address
|
||||
*/
|
||||
sgel_next =
|
||||
_base_get_chain_buffer_dma_to_chain_buffer(ioc,
|
||||
sgel->Address);
|
||||
if (sgel_next == NULL)
|
||||
return;
|
||||
/*
|
||||
* This is coping 128 byte chain
|
||||
* frame (not a host buffer)
|
||||
*/
|
||||
dst_chain_addr[sge_chain_count] =
|
||||
_base_get_chain(ioc,
|
||||
smid, sge_chain_count);
|
||||
src_chain_addr[sge_chain_count] =
|
||||
(void *) sgel_next;
|
||||
dst_addr_phys = _base_get_chain_phys(ioc,
|
||||
smid, sge_chain_count);
|
||||
WARN_ON(dst_addr_phys > U32_MAX);
|
||||
sgel->Address = (u32)dst_addr_phys;
|
||||
sgel = sgel_next;
|
||||
sge_chain_count++;
|
||||
break;
|
||||
case MPI2_SGE_FLAGS_SIMPLE_ELEMENT:
|
||||
if (is_write) {
|
||||
if (is_scsiio_req) {
|
||||
_base_clone_to_sys_mem(buff_ptr,
|
||||
sg_virt(sg_scmd),
|
||||
(sgel->FlagsLength & 0x00ffffff));
|
||||
/*
|
||||
* FIXME: this relies on a a zero
|
||||
* PCI mem_offset.
|
||||
*/
|
||||
sgel->Address = (u32)buff_ptr_phys;
|
||||
} else {
|
||||
_base_clone_to_sys_mem(buff_ptr,
|
||||
ioc->config_vaddr,
|
||||
(sgel->FlagsLength & 0x00ffffff));
|
||||
sgel->Address = (u32)buff_ptr_phys;
|
||||
}
|
||||
}
|
||||
buff_ptr += (sgel->FlagsLength & 0x00ffffff);
|
||||
buff_ptr_phys += (sgel->FlagsLength & 0x00ffffff);
|
||||
if ((sgel->FlagsLength &
|
||||
(MPI2_SGE_FLAGS_END_OF_BUFFER
|
||||
<< MPI2_SGE_FLAGS_SHIFT)))
|
||||
goto eob_clone_chain;
|
||||
else {
|
||||
/*
|
||||
* Every single element in MPT will have
|
||||
* associated sg_next. Better to sanity that
|
||||
* sg_next is not NULL, but it will be a bug
|
||||
* if it is null.
|
||||
*/
|
||||
if (is_scsiio_req) {
|
||||
sg_scmd = sg_next(sg_scmd);
|
||||
if (sg_scmd)
|
||||
sgel++;
|
||||
else
|
||||
goto eob_clone_chain;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eob_clone_chain:
|
||||
for (i = 0; i < sge_chain_count; i++) {
|
||||
if (is_scsiio_req)
|
||||
_base_clone_to_sys_mem(dst_chain_addr[i],
|
||||
src_chain_addr[i], ioc->request_sz);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_remove_dead_ioc_func - kthread context to remove dead ioc
|
||||
* @arg: input argument, used to derive ioc
|
||||
|
@ -875,7 +1231,7 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
|
|||
ack_request->EventContext = mpi_reply->EventContext;
|
||||
ack_request->VF_ID = 0; /* TODO */
|
||||
ack_request->VP_ID = 0;
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
|
||||
out:
|
||||
|
||||
|
@ -1075,6 +1431,10 @@ _base_interrupt(int irq, void *bus_id)
|
|||
0 : ioc->reply_free_host_index + 1;
|
||||
ioc->reply_free[ioc->reply_free_host_index] =
|
||||
cpu_to_le32(reply);
|
||||
if (ioc->is_mcpu_endpoint)
|
||||
_base_clone_reply_to_sys_mem(ioc,
|
||||
cpu_to_le32(reply),
|
||||
ioc->reply_free_host_index);
|
||||
writel(ioc->reply_free_host_index,
|
||||
&ioc->chip->ReplyFreeHostIndex);
|
||||
}
|
||||
|
@ -2214,6 +2574,9 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
|
|||
struct sysinfo s;
|
||||
u64 consistent_dma_mask;
|
||||
|
||||
if (ioc->is_mcpu_endpoint)
|
||||
goto try_32bit;
|
||||
|
||||
if (ioc->dma_mask)
|
||||
consistent_dma_mask = DMA_BIT_MASK(64);
|
||||
else
|
||||
|
@ -2232,6 +2595,7 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
try_32bit:
|
||||
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
|
||||
&& !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
|
||||
ioc->base_add_sg_single = &_base_add_sg_single_32;
|
||||
|
@ -2581,7 +2945,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
|
|||
u32 pio_sz;
|
||||
int i, r = 0;
|
||||
u64 pio_chip = 0;
|
||||
u64 chip_phys = 0;
|
||||
phys_addr_t chip_phys = 0;
|
||||
struct adapter_reply_queue *reply_q;
|
||||
|
||||
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n",
|
||||
|
@ -2629,7 +2993,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
|
|||
if (memap_sz)
|
||||
continue;
|
||||
ioc->chip_phys = pci_resource_start(pdev, i);
|
||||
chip_phys = (u64)ioc->chip_phys;
|
||||
chip_phys = ioc->chip_phys;
|
||||
memap_sz = pci_resource_len(pdev, i);
|
||||
ioc->chip = ioremap(ioc->chip_phys, memap_sz);
|
||||
}
|
||||
|
@ -2704,8 +3068,8 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
|
|||
"IO-APIC enabled"),
|
||||
pci_irq_vector(ioc->pdev, reply_q->msix_index));
|
||||
|
||||
pr_info(MPT3SAS_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
|
||||
ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
|
||||
pr_info(MPT3SAS_FMT "iomem(%pap), mapped(0x%p), size(%d)\n",
|
||||
ioc->name, &chip_phys, ioc->chip, memap_sz);
|
||||
pr_info(MPT3SAS_FMT "ioport(0x%016llx), size(%d)\n",
|
||||
ioc->name, (unsigned long long)pio_chip, pio_sz);
|
||||
|
||||
|
@ -2960,6 +3324,29 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
|||
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_mpi_ep_writeq - 32 bit write to MMIO
|
||||
* @b: data payload
|
||||
* @addr: address in MMIO space
|
||||
* @writeq_lock: spin lock
|
||||
*
|
||||
* This special handling for MPI EP to take care of 32 bit
|
||||
* environment where its not quarenteed to send the entire word
|
||||
* in one transfer.
|
||||
*/
|
||||
static inline void
|
||||
_base_mpi_ep_writeq(__u64 b, volatile void __iomem *addr,
|
||||
spinlock_t *writeq_lock)
|
||||
{
|
||||
unsigned long flags;
|
||||
__u64 data_out = cpu_to_le64(b);
|
||||
|
||||
spin_lock_irqsave(writeq_lock, flags);
|
||||
writel((u32)(data_out), addr);
|
||||
writel((u32)(data_out >> 32), (addr + 4));
|
||||
spin_unlock_irqrestore(writeq_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_writeq - 64 bit write to MMIO
|
||||
* @ioc: per adapter object
|
||||
|
@ -2981,16 +3368,40 @@ _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
|
|||
static inline void
|
||||
_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
|
||||
{
|
||||
unsigned long flags;
|
||||
__u64 data_out = cpu_to_le64(b);
|
||||
|
||||
spin_lock_irqsave(writeq_lock, flags);
|
||||
writel((u32)(data_out), addr);
|
||||
writel((u32)(data_out >> 32), (addr + 4));
|
||||
spin_unlock_irqrestore(writeq_lock, flags);
|
||||
_base_mpi_ep_writeq(b, addr, writeq_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* _base_put_smid_mpi_ep_scsi_io - send SCSI_IO request to firmware
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
* @handle: device handle
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
static void
|
||||
_base_put_smid_mpi_ep_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle)
|
||||
{
|
||||
Mpi2RequestDescriptorUnion_t descriptor;
|
||||
u64 *request = (u64 *)&descriptor;
|
||||
void *mpi_req_iomem;
|
||||
__le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid);
|
||||
|
||||
_clone_sg_entries(ioc, (void *) mfp, smid);
|
||||
mpi_req_iomem = (void *)ioc->chip +
|
||||
MPI_FRAME_START_OFFSET + (smid * ioc->request_sz);
|
||||
_base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp,
|
||||
ioc->request_sz);
|
||||
descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
|
||||
descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc);
|
||||
descriptor.SCSIIO.SMID = cpu_to_le16(smid);
|
||||
descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
|
||||
descriptor.SCSIIO.LMID = 0;
|
||||
_base_mpi_ep_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
|
||||
&ioc->scsi_lookup_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_put_smid_scsi_io - send SCSI_IO request to firmware
|
||||
* @ioc: per adapter object
|
||||
|
@ -3016,15 +3427,15 @@ _base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle)
|
|||
}
|
||||
|
||||
/**
|
||||
* _base_put_smid_fast_path - send fast path request to firmware
|
||||
* mpt3sas_base_put_smid_fast_path - send fast path request to firmware
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
* @handle: device handle
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
static void
|
||||
_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
void
|
||||
mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
u16 handle)
|
||||
{
|
||||
Mpi2RequestDescriptorUnion_t descriptor;
|
||||
|
@ -3041,18 +3452,34 @@ _base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
|||
}
|
||||
|
||||
/**
|
||||
* _base_put_smid_hi_priority - send Task Management request to firmware
|
||||
* mpt3sas_base_put_smid_hi_priority - send Task Management request to firmware
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
* @msix_task: msix_task will be same as msix of IO incase of task abort else 0.
|
||||
* Return nothing.
|
||||
*/
|
||||
static void
|
||||
_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
void
|
||||
mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
u16 msix_task)
|
||||
{
|
||||
Mpi2RequestDescriptorUnion_t descriptor;
|
||||
u64 *request = (u64 *)&descriptor;
|
||||
void *mpi_req_iomem;
|
||||
u64 *request;
|
||||
|
||||
if (ioc->is_mcpu_endpoint) {
|
||||
MPI2RequestHeader_t *request_hdr;
|
||||
|
||||
__le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid);
|
||||
|
||||
request_hdr = (MPI2RequestHeader_t *)mfp;
|
||||
/* TBD 256 is offset within sys register. */
|
||||
mpi_req_iomem = (void *)ioc->chip + MPI_FRAME_START_OFFSET
|
||||
+ (smid * ioc->request_sz);
|
||||
_base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp,
|
||||
ioc->request_sz);
|
||||
}
|
||||
|
||||
request = (u64 *)&descriptor;
|
||||
|
||||
descriptor.HighPriority.RequestFlags =
|
||||
MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
|
||||
|
@ -3060,20 +3487,25 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
|||
descriptor.HighPriority.SMID = cpu_to_le16(smid);
|
||||
descriptor.HighPriority.LMID = 0;
|
||||
descriptor.HighPriority.Reserved1 = 0;
|
||||
if (ioc->is_mcpu_endpoint)
|
||||
_base_mpi_ep_writeq(*request,
|
||||
&ioc->chip->RequestDescriptorPostLow,
|
||||
&ioc->scsi_lookup_lock);
|
||||
else
|
||||
_base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
|
||||
&ioc->scsi_lookup_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_put_smid_nvme_encap - send NVMe encapsulated request to
|
||||
* mpt3sas_base_put_smid_nvme_encap - send NVMe encapsulated request to
|
||||
* firmware
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
static void
|
||||
_base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||
void
|
||||
mpt3sas_base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||
{
|
||||
Mpi2RequestDescriptorUnion_t descriptor;
|
||||
u64 *request = (u64 *)&descriptor;
|
||||
|
@ -3089,137 +3521,47 @@ _base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
|||
}
|
||||
|
||||
/**
|
||||
* _base_put_smid_default - Default, primarily used for config pages
|
||||
* mpt3sas_base_put_smid_default - Default, primarily used for config pages
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
static void
|
||||
_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||
void
|
||||
mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||
{
|
||||
Mpi2RequestDescriptorUnion_t descriptor;
|
||||
u64 *request = (u64 *)&descriptor;
|
||||
void *mpi_req_iomem;
|
||||
u64 *request;
|
||||
MPI2RequestHeader_t *request_hdr;
|
||||
|
||||
if (ioc->is_mcpu_endpoint) {
|
||||
__le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid);
|
||||
|
||||
request_hdr = (MPI2RequestHeader_t *)mfp;
|
||||
|
||||
_clone_sg_entries(ioc, (void *) mfp, smid);
|
||||
/* TBD 256 is offset within sys register */
|
||||
mpi_req_iomem = (void *)ioc->chip +
|
||||
MPI_FRAME_START_OFFSET + (smid * ioc->request_sz);
|
||||
_base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp,
|
||||
ioc->request_sz);
|
||||
}
|
||||
request = (u64 *)&descriptor;
|
||||
descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
descriptor.Default.MSIxIndex = _base_get_msix_index(ioc);
|
||||
descriptor.Default.SMID = cpu_to_le16(smid);
|
||||
descriptor.Default.LMID = 0;
|
||||
descriptor.Default.DescriptorTypeDependent = 0;
|
||||
if (ioc->is_mcpu_endpoint)
|
||||
_base_mpi_ep_writeq(*request,
|
||||
&ioc->chip->RequestDescriptorPostLow,
|
||||
&ioc->scsi_lookup_lock);
|
||||
else
|
||||
_base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
|
||||
&ioc->scsi_lookup_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_put_smid_scsi_io_atomic - send SCSI_IO request to firmware using
|
||||
* Atomic Request Descriptor
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
* @handle: device handle, unused in this function, for function type match
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
static void
|
||||
_base_put_smid_scsi_io_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
u16 handle)
|
||||
{
|
||||
Mpi26AtomicRequestDescriptor_t descriptor;
|
||||
u32 *request = (u32 *)&descriptor;
|
||||
|
||||
descriptor.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
|
||||
descriptor.MSIxIndex = _base_get_msix_index(ioc);
|
||||
descriptor.SMID = cpu_to_le16(smid);
|
||||
|
||||
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_put_smid_fast_path_atomic - send fast path request to firmware
|
||||
* using Atomic Request Descriptor
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
* @handle: device handle, unused in this function, for function type match
|
||||
* Return nothing
|
||||
*/
|
||||
static void
|
||||
_base_put_smid_fast_path_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
u16 handle)
|
||||
{
|
||||
Mpi26AtomicRequestDescriptor_t descriptor;
|
||||
u32 *request = (u32 *)&descriptor;
|
||||
|
||||
descriptor.RequestFlags = MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
|
||||
descriptor.MSIxIndex = _base_get_msix_index(ioc);
|
||||
descriptor.SMID = cpu_to_le16(smid);
|
||||
|
||||
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_put_smid_hi_priority_atomic - send Task Management request to
|
||||
* firmware using Atomic Request Descriptor
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
* @msix_task: msix_task will be same as msix of IO incase of task abort else 0
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
static void
|
||||
_base_put_smid_hi_priority_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
u16 msix_task)
|
||||
{
|
||||
Mpi26AtomicRequestDescriptor_t descriptor;
|
||||
u32 *request = (u32 *)&descriptor;
|
||||
|
||||
descriptor.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
|
||||
descriptor.MSIxIndex = msix_task;
|
||||
descriptor.SMID = cpu_to_le16(smid);
|
||||
|
||||
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_put_smid_nvme_encap_atomic - send NVMe encapsulated request to
|
||||
* firmware using Atomic Request Descriptor
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
static void
|
||||
_base_put_smid_nvme_encap_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||
{
|
||||
Mpi26AtomicRequestDescriptor_t descriptor;
|
||||
u32 *request = (u32 *)&descriptor;
|
||||
|
||||
descriptor.RequestFlags = MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED;
|
||||
descriptor.MSIxIndex = _base_get_msix_index(ioc);
|
||||
descriptor.SMID = cpu_to_le16(smid);
|
||||
|
||||
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_put_smid_default - Default, primarily used for config pages
|
||||
* use Atomic Request Descriptor
|
||||
* @ioc: per adapter object
|
||||
* @smid: system request message index
|
||||
*
|
||||
* Return nothing.
|
||||
*/
|
||||
static void
|
||||
_base_put_smid_default_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||
{
|
||||
Mpi26AtomicRequestDescriptor_t descriptor;
|
||||
u32 *request = (u32 *)&descriptor;
|
||||
|
||||
descriptor.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
descriptor.MSIxIndex = _base_get_msix_index(ioc);
|
||||
descriptor.SMID = cpu_to_le16(smid);
|
||||
|
||||
writel(cpu_to_le32(*request), &ioc->chip->AtomicRequestDescriptorPost);
|
||||
}
|
||||
|
||||
/**
|
||||
* _base_display_OEMs_branding - Display branding string
|
||||
* @ioc: per adapter object
|
||||
|
@ -3890,17 +4232,21 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
|
|||
sg_tablesize = min_t(unsigned short, sg_tablesize,
|
||||
MPT_KDUMP_MIN_PHYS_SEGMENTS);
|
||||
|
||||
if (ioc->is_mcpu_endpoint)
|
||||
ioc->shost->sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
|
||||
else {
|
||||
if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS)
|
||||
sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
|
||||
else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) {
|
||||
sg_tablesize = min_t(unsigned short, sg_tablesize,
|
||||
SG_MAX_SEGMENTS);
|
||||
pr_warn(MPT3SAS_FMT
|
||||
"sg_tablesize(%u) is bigger than kernel"
|
||||
" defined SG_CHUNK_SIZE(%u)\n", ioc->name,
|
||||
"sg_tablesize(%u) is bigger than kernel "
|
||||
"defined SG_CHUNK_SIZE(%u)\n", ioc->name,
|
||||
sg_tablesize, MPT_MAX_PHYS_SEGMENTS);
|
||||
}
|
||||
ioc->shost->sg_tablesize = sg_tablesize;
|
||||
}
|
||||
|
||||
ioc->internal_depth = min_t(int, (facts->HighPriorityCredit + (5)),
|
||||
(facts->RequestCredit / 4));
|
||||
|
@ -3985,13 +4331,18 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
|
|||
/* reply free queue sizing - taking into account for 64 FW events */
|
||||
ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
|
||||
|
||||
/* mCPU manage single counters for simplicity */
|
||||
if (ioc->is_mcpu_endpoint)
|
||||
ioc->reply_post_queue_depth = ioc->reply_free_queue_depth;
|
||||
else {
|
||||
/* calculate reply descriptor post queue depth */
|
||||
ioc->reply_post_queue_depth = ioc->hba_queue_depth +
|
||||
ioc->reply_free_queue_depth + 1 ;
|
||||
ioc->reply_free_queue_depth + 1;
|
||||
/* align the reply post queue on the next 16 count boundary */
|
||||
if (ioc->reply_post_queue_depth % 16)
|
||||
ioc->reply_post_queue_depth += 16 -
|
||||
(ioc->reply_post_queue_depth % 16);
|
||||
}
|
||||
|
||||
if (ioc->reply_post_queue_depth >
|
||||
facts->MaxReplyDescriptorPostQueueDepth) {
|
||||
|
@ -4789,7 +5140,7 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc,
|
|||
mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET)
|
||||
ioc->ioc_link_reset_in_progress = 1;
|
||||
init_completion(&ioc->base_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->base_cmds.done,
|
||||
msecs_to_jiffies(10000));
|
||||
if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
|
||||
|
@ -4889,7 +5240,7 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc,
|
|||
ioc->base_cmds.smid = smid;
|
||||
memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
|
||||
init_completion(&ioc->base_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->base_cmds.done,
|
||||
msecs_to_jiffies(10000));
|
||||
if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
|
@ -5074,8 +5425,6 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc)
|
|||
if ((facts->IOCCapabilities &
|
||||
MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE) && (!reset_devices))
|
||||
ioc->rdpq_array_capable = 1;
|
||||
if (facts->IOCCapabilities & MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ)
|
||||
ioc->atomic_desc_capable = 1;
|
||||
facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
|
||||
facts->IOCRequestFrameSize =
|
||||
le16_to_cpu(mpi_reply.IOCRequestFrameSize);
|
||||
|
@ -5317,7 +5666,7 @@ _base_send_port_enable(struct MPT3SAS_ADAPTER *ioc)
|
|||
mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
|
||||
|
||||
init_completion(&ioc->port_enable_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->port_enable_cmds.done, 300*HZ);
|
||||
if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
|
@ -5380,7 +5729,7 @@ mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc)
|
|||
memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
|
||||
mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
|
||||
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5499,7 +5848,7 @@ _base_event_notification(struct MPT3SAS_ADAPTER *ioc)
|
|||
mpi_request->EventMasks[i] =
|
||||
cpu_to_le32(ioc->event_masks[i]);
|
||||
init_completion(&ioc->base_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
|
||||
if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
|
@ -5819,8 +6168,12 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
|
|||
/* initialize Reply Free Queue */
|
||||
for (i = 0, reply_address = (u32)ioc->reply_dma ;
|
||||
i < ioc->reply_free_queue_depth ; i++, reply_address +=
|
||||
ioc->reply_sz)
|
||||
ioc->reply_sz) {
|
||||
ioc->reply_free[i] = cpu_to_le32(reply_address);
|
||||
if (ioc->is_mcpu_endpoint)
|
||||
_base_clone_reply_to_sys_mem(ioc,
|
||||
(__le32)reply_address, i);
|
||||
}
|
||||
|
||||
/* initialize reply queues */
|
||||
if (ioc->is_driver_loading)
|
||||
|
@ -6009,20 +6362,10 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
|
|||
break;
|
||||
}
|
||||
|
||||
if (ioc->atomic_desc_capable) {
|
||||
ioc->put_smid_default = &_base_put_smid_default_atomic;
|
||||
ioc->put_smid_scsi_io = &_base_put_smid_scsi_io_atomic;
|
||||
ioc->put_smid_fast_path = &_base_put_smid_fast_path_atomic;
|
||||
ioc->put_smid_hi_priority = &_base_put_smid_hi_priority_atomic;
|
||||
ioc->put_smid_nvme_encap = &_base_put_smid_nvme_encap_atomic;
|
||||
} else {
|
||||
ioc->put_smid_default = &_base_put_smid_default;
|
||||
if (ioc->is_mcpu_endpoint)
|
||||
ioc->put_smid_scsi_io = &_base_put_smid_mpi_ep_scsi_io;
|
||||
else
|
||||
ioc->put_smid_scsi_io = &_base_put_smid_scsi_io;
|
||||
ioc->put_smid_fast_path = &_base_put_smid_fast_path;
|
||||
ioc->put_smid_hi_priority = &_base_put_smid_hi_priority;
|
||||
ioc->put_smid_nvme_encap = &_base_put_smid_nvme_encap;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These function pointers for other requests that don't
|
||||
|
|
|
@ -95,6 +95,8 @@
|
|||
#define MPT_MIN_PHYS_SEGMENTS 16
|
||||
#define MPT_KDUMP_MIN_PHYS_SEGMENTS 32
|
||||
|
||||
#define MCPU_MAX_CHAINS_PER_IO 3
|
||||
|
||||
#ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE
|
||||
#define MPT3SAS_SG_DEPTH CONFIG_SCSI_MPT3SAS_MAX_SGE
|
||||
#else
|
||||
|
@ -120,6 +122,8 @@
|
|||
#define MPT3SAS_NVME_QUEUE_DEPTH 128
|
||||
#define MPT_NAME_LENGTH 32 /* generic length of strings */
|
||||
#define MPT_STRING_LENGTH 64
|
||||
#define MPI_FRAME_START_OFFSET 256
|
||||
#define REPLY_FREE_POOL_SIZE 512 /*(32 maxcredix *4)*(4 times)*/
|
||||
|
||||
#define MPT_MAX_CALLBACKS 32
|
||||
|
||||
|
@ -1099,7 +1103,7 @@ struct MPT3SAS_ADAPTER {
|
|||
char tmp_string[MPT_STRING_LENGTH];
|
||||
struct pci_dev *pdev;
|
||||
Mpi2SystemInterfaceRegs_t __iomem *chip;
|
||||
resource_size_t chip_phys;
|
||||
phys_addr_t chip_phys;
|
||||
int logging_level;
|
||||
int fwfault_debug;
|
||||
u8 ir_firmware;
|
||||
|
@ -1236,6 +1240,7 @@ struct MPT3SAS_ADAPTER {
|
|||
u16 config_page_sz;
|
||||
void *config_page;
|
||||
dma_addr_t config_page_dma;
|
||||
void *config_vaddr;
|
||||
|
||||
/* scsiio request */
|
||||
u16 hba_queue_depth;
|
||||
|
@ -1336,6 +1341,7 @@ struct MPT3SAS_ADAPTER {
|
|||
u32 ring_buffer_offset;
|
||||
u32 ring_buffer_sz;
|
||||
u8 is_warpdrive;
|
||||
u8 is_mcpu_endpoint;
|
||||
u8 hide_ir_msg;
|
||||
u8 mfg_pg10_hide_flag;
|
||||
u8 hide_drives;
|
||||
|
@ -1348,12 +1354,7 @@ struct MPT3SAS_ADAPTER {
|
|||
void *device_remove_in_progress;
|
||||
u16 device_remove_in_progress_sz;
|
||||
u8 is_gen35_ioc;
|
||||
u8 atomic_desc_capable;
|
||||
PUT_SMID_IO_FP_HIP put_smid_scsi_io;
|
||||
PUT_SMID_IO_FP_HIP put_smid_fast_path;
|
||||
PUT_SMID_IO_FP_HIP put_smid_hi_priority;
|
||||
PUT_SMID_DEFAULT put_smid_default;
|
||||
PUT_SMID_DEFAULT put_smid_nvme_encap;
|
||||
|
||||
};
|
||||
|
||||
|
@ -1394,6 +1395,12 @@ void *mpt3sas_base_get_pcie_sgl(struct MPT3SAS_ADAPTER *ioc, u16 smid);
|
|||
dma_addr_t mpt3sas_base_get_pcie_sgl_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid);
|
||||
void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc);
|
||||
|
||||
void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
u16 handle);
|
||||
void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
u16 msix_task);
|
||||
void mpt3sas_base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid);
|
||||
void mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid);
|
||||
/* hi-priority queue */
|
||||
u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx);
|
||||
u16 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx,
|
||||
|
|
|
@ -219,6 +219,7 @@ _config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
|
|||
mem->page = ioc->config_page;
|
||||
mem->page_dma = ioc->config_page_dma;
|
||||
}
|
||||
ioc->config_vaddr = mem->page;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -402,7 +403,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
|
|||
memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
|
||||
_config_display_some_debug(ioc, smid, "config_request", NULL);
|
||||
init_completion(&ioc->config_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ);
|
||||
if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
|
|
|
@ -820,7 +820,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ioc->put_smid_nvme_encap(ioc, smid);
|
||||
mpt3sas_base_put_smid_nvme_encap(ioc, smid);
|
||||
break;
|
||||
}
|
||||
case MPI2_FUNCTION_SCSI_IO_REQUEST:
|
||||
|
@ -845,7 +845,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)
|
||||
ioc->put_smid_scsi_io(ioc, smid, device_handle);
|
||||
else
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
break;
|
||||
}
|
||||
case MPI2_FUNCTION_SCSI_TASK_MGMT:
|
||||
|
@ -882,7 +882,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
tm_request->DevHandle));
|
||||
ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
|
||||
data_in_dma, data_in_sz);
|
||||
ioc->put_smid_hi_priority(ioc, smid, 0);
|
||||
mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
|
||||
break;
|
||||
}
|
||||
case MPI2_FUNCTION_SMP_PASSTHROUGH:
|
||||
|
@ -913,7 +913,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
}
|
||||
ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
|
||||
data_in_sz);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
break;
|
||||
}
|
||||
case MPI2_FUNCTION_SATA_PASSTHROUGH:
|
||||
|
@ -928,7 +928,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
}
|
||||
ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
|
||||
data_in_sz);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
break;
|
||||
}
|
||||
case MPI2_FUNCTION_FW_DOWNLOAD:
|
||||
|
@ -936,7 +936,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
{
|
||||
ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
|
||||
data_in_sz);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
break;
|
||||
}
|
||||
case MPI2_FUNCTION_TOOLBOX:
|
||||
|
@ -951,7 +951,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
|
||||
data_in_dma, data_in_sz);
|
||||
}
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
break;
|
||||
}
|
||||
case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
|
||||
|
@ -970,7 +970,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
|||
default:
|
||||
ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
|
||||
data_in_dma, data_in_sz);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1601,7 +1601,7 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
|
|||
cpu_to_le32(ioc->product_specific[buffer_type][i]);
|
||||
|
||||
init_completion(&ioc->ctl_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
|
@ -1948,7 +1948,7 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
|
|||
mpi_request->VP_ID = 0;
|
||||
|
||||
init_completion(&ioc->ctl_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
|
@ -2215,7 +2215,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
|||
mpi_request->VP_ID = 0;
|
||||
|
||||
init_completion(&ioc->ctl_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->ctl_cmds.done,
|
||||
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
|
||||
|
||||
|
|
|
@ -2679,7 +2679,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
|
|||
int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
|
||||
mpt3sas_scsih_set_tm_flag(ioc, handle);
|
||||
init_completion(&ioc->tm_cmds.done);
|
||||
ioc->put_smid_hi_priority(ioc, smid, msix_task);
|
||||
mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task);
|
||||
wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
|
||||
if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
pr_err(MPT3SAS_FMT "%s: timeout\n",
|
||||
|
@ -3641,7 +3641,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
|
|||
mpi_request->DevHandle = cpu_to_le16(handle);
|
||||
mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
|
||||
set_bit(handle, ioc->device_remove_in_progress);
|
||||
ioc->put_smid_hi_priority(ioc, smid, 0);
|
||||
mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
|
||||
mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
|
||||
|
||||
out:
|
||||
|
@ -3742,7 +3742,7 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
|
|||
mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
|
||||
mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
|
||||
mpi_request->DevHandle = mpi_request_tm->DevHandle;
|
||||
ioc->put_smid_default(ioc, smid_sas_ctrl);
|
||||
mpt3sas_base_put_smid_default(ioc, smid_sas_ctrl);
|
||||
|
||||
return _scsih_check_for_pending_tm(ioc, smid);
|
||||
}
|
||||
|
@ -3837,7 +3837,7 @@ _scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
|
|||
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
|
||||
mpi_request->DevHandle = cpu_to_le16(handle);
|
||||
mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
|
||||
ioc->put_smid_hi_priority(ioc, smid, 0);
|
||||
mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3929,7 +3929,7 @@ _scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event,
|
|||
ack_request->EventContext = event_context;
|
||||
ack_request->VF_ID = 0; /* TODO */
|
||||
ack_request->VP_ID = 0;
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3986,7 +3986,7 @@ _scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc,
|
|||
mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
|
||||
mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
|
||||
mpi_request->DevHandle = handle;
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4715,12 +4715,12 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
|
|||
if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
|
||||
mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len |
|
||||
MPI25_SCSIIO_IOFLAGS_FAST_PATH);
|
||||
ioc->put_smid_fast_path(ioc, smid, handle);
|
||||
mpt3sas_base_put_smid_fast_path(ioc, smid, handle);
|
||||
} else
|
||||
ioc->put_smid_scsi_io(ioc, smid,
|
||||
le16_to_cpu(mpi_request->DevHandle));
|
||||
} else
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
|
@ -7609,7 +7609,7 @@ _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
|
|||
handle, phys_disk_num));
|
||||
|
||||
init_completion(&ioc->scsih_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
|
||||
|
||||
if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
|
@ -9700,7 +9700,7 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
|
|||
if (!ioc->hide_ir_msg)
|
||||
pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
|
||||
init_completion(&ioc->scsih_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
|
||||
|
||||
if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
|
@ -10346,6 +10346,7 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev)
|
|||
case MPI2_MFGPAGE_DEVID_SAS2308_1:
|
||||
case MPI2_MFGPAGE_DEVID_SAS2308_2:
|
||||
case MPI2_MFGPAGE_DEVID_SAS2308_3:
|
||||
case MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP:
|
||||
return MPI2_VERSION;
|
||||
case MPI25_MFGPAGE_DEVID_SAS3004:
|
||||
case MPI25_MFGPAGE_DEVID_SAS3008:
|
||||
|
@ -10423,12 +10424,19 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
ioc->hba_mpi_version_belonged = hba_mpi_version;
|
||||
ioc->id = mpt2_ids++;
|
||||
sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME);
|
||||
if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) {
|
||||
switch (pdev->device) {
|
||||
case MPI2_MFGPAGE_DEVID_SSS6200:
|
||||
ioc->is_warpdrive = 1;
|
||||
ioc->hide_ir_msg = 1;
|
||||
} else
|
||||
break;
|
||||
case MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP:
|
||||
ioc->is_mcpu_endpoint = 1;
|
||||
break;
|
||||
default:
|
||||
ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MPI25_VERSION:
|
||||
case MPI26_VERSION:
|
||||
/* Use mpt3sas driver host template for SAS 3.0 HBA's */
|
||||
|
@ -10524,18 +10532,26 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
shost->transportt = mpt3sas_transport_template;
|
||||
shost->unique_id = ioc->id;
|
||||
|
||||
if (ioc->is_mcpu_endpoint) {
|
||||
/* mCPU MPI support 64K max IO */
|
||||
shost->max_sectors = 128;
|
||||
pr_info(MPT3SAS_FMT
|
||||
"The max_sectors value is set to %d\n",
|
||||
ioc->name, shost->max_sectors);
|
||||
} else {
|
||||
if (max_sectors != 0xFFFF) {
|
||||
if (max_sectors < 64) {
|
||||
shost->max_sectors = 64;
|
||||
pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
|
||||
"for max_sectors, range is 64 to 32767. Assigning "
|
||||
"value of 64.\n", ioc->name, max_sectors);
|
||||
"for max_sectors, range is 64 to 32767. " \
|
||||
"Assigning value of 64.\n", \
|
||||
ioc->name, max_sectors);
|
||||
} else if (max_sectors > 32767) {
|
||||
shost->max_sectors = 32767;
|
||||
pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
|
||||
"for max_sectors, range is 64 to 32767. Assigning "
|
||||
"default value of 32767.\n", ioc->name,
|
||||
max_sectors);
|
||||
"for max_sectors, range is 64 to 32767." \
|
||||
"Assigning default value of 32767.\n", \
|
||||
ioc->name, max_sectors);
|
||||
} else {
|
||||
shost->max_sectors = max_sectors & 0xFFFE;
|
||||
pr_info(MPT3SAS_FMT
|
||||
|
@ -10543,7 +10559,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
ioc->name, shost->max_sectors);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/* register EEDP capabilities with SCSI layer */
|
||||
if (prot_mask > 0)
|
||||
scsi_host_set_prot(shost, prot_mask);
|
||||
|
@ -10856,6 +10872,8 @@ static const struct pci_device_id mpt3sas_pci_table[] = {
|
|||
PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
|
||||
PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP,
|
||||
PCI_ANY_ID, PCI_ANY_ID },
|
||||
/* SSS6200 */
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
|
||||
PCI_ANY_ID, PCI_ANY_ID },
|
||||
|
|
|
@ -392,7 +392,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
|
|||
"report_manufacture - send to sas_addr(0x%016llx)\n",
|
||||
ioc->name, (unsigned long long)sas_address));
|
||||
init_completion(&ioc->transport_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
|
||||
|
||||
if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
|
@ -1198,7 +1198,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
|
|||
ioc->name, (unsigned long long)phy->identify.sas_address,
|
||||
phy->number));
|
||||
init_completion(&ioc->transport_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
|
||||
|
||||
if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
|
@ -1514,7 +1514,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
|
|||
ioc->name, (unsigned long long)phy->identify.sas_address,
|
||||
phy->number, phy_operation));
|
||||
init_completion(&ioc->transport_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
|
||||
|
||||
if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
|
@ -2014,7 +2014,7 @@ _transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
|
|||
"%s - sending smp request\n", ioc->name, __func__));
|
||||
|
||||
init_completion(&ioc->transport_cmds.done);
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
mpt3sas_base_put_smid_default(ioc, smid);
|
||||
wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
|
||||
|
||||
if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
@ -14,9 +17,6 @@
|
|||
#include "wd33c93.h"
|
||||
#include "mvme147.h"
|
||||
|
||||
#include <linux/stat.h>
|
||||
|
||||
|
||||
static irqreturn_t mvme147_intr(int irq, void *data)
|
||||
{
|
||||
struct Scsi_Host *instance = data;
|
||||
|
@ -65,40 +65,57 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
|
|||
m147_pcc->dma_cntrl = 0;
|
||||
}
|
||||
|
||||
int mvme147_detect(struct scsi_host_template *tpnt)
|
||||
static struct scsi_host_template mvme147_host_template = {
|
||||
.module = THIS_MODULE,
|
||||
.proc_name = "MVME147",
|
||||
.name = "MVME147 built-in SCSI",
|
||||
.queuecommand = wd33c93_queuecommand,
|
||||
.eh_abort_handler = wd33c93_abort,
|
||||
.eh_host_reset_handler = wd33c93_host_reset,
|
||||
.show_info = wd33c93_show_info,
|
||||
.write_info = wd33c93_write_info,
|
||||
.can_queue = CAN_QUEUE,
|
||||
.this_id = 7,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = CMD_PER_LUN,
|
||||
.use_clustering = ENABLE_CLUSTERING
|
||||
};
|
||||
|
||||
static struct Scsi_Host *mvme147_shost;
|
||||
|
||||
static int __init mvme147_init(void)
|
||||
{
|
||||
static unsigned char called = 0;
|
||||
struct Scsi_Host *instance;
|
||||
wd33c93_regs regs;
|
||||
struct WD33C93_hostdata *hdata;
|
||||
int error = -ENOMEM;
|
||||
|
||||
if (!MACH_IS_MVME147 || called)
|
||||
if (!MACH_IS_MVME147)
|
||||
return 0;
|
||||
called++;
|
||||
|
||||
tpnt->proc_name = "MVME147";
|
||||
tpnt->show_info = wd33c93_show_info,
|
||||
tpnt->write_info = wd33c93_write_info,
|
||||
|
||||
instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
|
||||
if (!instance)
|
||||
mvme147_shost = scsi_host_alloc(&mvme147_host_template,
|
||||
sizeof(struct WD33C93_hostdata));
|
||||
if (!mvme147_shost)
|
||||
goto err_out;
|
||||
mvme147_shost->base = 0xfffe4000;
|
||||
mvme147_shost->irq = MVME147_IRQ_SCSI_PORT;
|
||||
|
||||
instance->base = 0xfffe4000;
|
||||
instance->irq = MVME147_IRQ_SCSI_PORT;
|
||||
regs.SASR = (volatile unsigned char *)0xfffe4000;
|
||||
regs.SCMD = (volatile unsigned char *)0xfffe4001;
|
||||
hdata = shost_priv(instance);
|
||||
|
||||
hdata = shost_priv(mvme147_shost);
|
||||
hdata->no_sync = 0xff;
|
||||
hdata->fast = 0;
|
||||
hdata->dma_mode = CTRL_DMA;
|
||||
wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
|
||||
|
||||
if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0,
|
||||
"MVME147 SCSI PORT", instance))
|
||||
wd33c93_init(mvme147_shost, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
|
||||
|
||||
error = request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0,
|
||||
"MVME147 SCSI PORT", mvme147_shost);
|
||||
if (error)
|
||||
goto err_unregister;
|
||||
if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0,
|
||||
"MVME147 SCSI DMA", instance))
|
||||
error = request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0,
|
||||
"MVME147 SCSI DMA", mvme147_shost);
|
||||
if (error)
|
||||
goto err_free_irq;
|
||||
#if 0 /* Disabled; causes problems booting */
|
||||
m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */
|
||||
|
@ -112,40 +129,30 @@ int mvme147_detect(struct scsi_host_template *tpnt)
|
|||
m147_pcc->dma_cntrl = 0x00; /* ensure DMA is stopped */
|
||||
m147_pcc->dma_intr = 0x89; /* Ack and enable ints */
|
||||
|
||||
return 1;
|
||||
error = scsi_add_host(mvme147_shost, NULL);
|
||||
if (error)
|
||||
goto err_free_irq;
|
||||
scsi_scan_host(mvme147_shost);
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr);
|
||||
free_irq(MVME147_IRQ_SCSI_PORT, mvme147_shost);
|
||||
err_unregister:
|
||||
scsi_unregister(instance);
|
||||
scsi_host_put(mvme147_shost);
|
||||
err_out:
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.proc_name = "MVME147",
|
||||
.name = "MVME147 built-in SCSI",
|
||||
.detect = mvme147_detect,
|
||||
.release = mvme147_release,
|
||||
.queuecommand = wd33c93_queuecommand,
|
||||
.eh_abort_handler = wd33c93_abort,
|
||||
.eh_host_reset_handler = wd33c93_host_reset,
|
||||
.can_queue = CAN_QUEUE,
|
||||
.this_id = 7,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = CMD_PER_LUN,
|
||||
.use_clustering = ENABLE_CLUSTERING
|
||||
};
|
||||
|
||||
|
||||
#include "scsi_module.c"
|
||||
|
||||
int mvme147_release(struct Scsi_Host *instance)
|
||||
static void __exit mvme147_exit(void)
|
||||
{
|
||||
#ifdef MODULE
|
||||
scsi_remove_host(mvme147_shost);
|
||||
|
||||
/* XXX Make sure DMA is stopped! */
|
||||
free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr);
|
||||
free_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr);
|
||||
#endif
|
||||
return 1;
|
||||
free_irq(MVME147_IRQ_SCSI_PORT, mvme147_shost);
|
||||
free_irq(MVME147_IRQ_SCSI_DMA, mvme147_shost);
|
||||
|
||||
scsi_host_put(mvme147_shost);
|
||||
}
|
||||
|
||||
module_init(mvme147_init);
|
||||
module_exit(mvme147_exit);
|
||||
|
|
|
@ -1080,16 +1080,16 @@ static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv,
|
|||
void __iomem *regs = mvi->regs_ex - 0x10200;
|
||||
|
||||
int drive = (i/3) & (4-1); /* drive number on host */
|
||||
u32 block = mr32(MVS_SGPIO_DCTRL +
|
||||
int driveshift = drive * 8; /* bit offset of drive */
|
||||
u32 block = ioread32be(regs + MVS_SGPIO_DCTRL +
|
||||
MVS_SGPIO_HOST_OFFSET * mvi->id);
|
||||
|
||||
|
||||
/*
|
||||
* if bit is set then create a mask with the first
|
||||
* bit of the drive set in the mask ...
|
||||
*/
|
||||
u32 bit = (write_data[i/8] & (1 << (i&(8-1)))) ?
|
||||
1<<(24-drive*8) : 0;
|
||||
u32 bit = get_unaligned_be32(write_data) & (1 << i) ?
|
||||
1 << driveshift : 0;
|
||||
|
||||
/*
|
||||
* ... and then shift it to the right position based
|
||||
|
@ -1098,26 +1098,27 @@ static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv,
|
|||
switch (i%3) {
|
||||
case 0: /* activity */
|
||||
block &= ~((0x7 << MVS_SGPIO_DCTRL_ACT_SHIFT)
|
||||
<< (24-drive*8));
|
||||
<< driveshift);
|
||||
/* hardwire activity bit to SOF */
|
||||
block |= LED_BLINKA_SOF << (
|
||||
MVS_SGPIO_DCTRL_ACT_SHIFT +
|
||||
(24-drive*8));
|
||||
driveshift);
|
||||
break;
|
||||
case 1: /* id */
|
||||
block &= ~((0x3 << MVS_SGPIO_DCTRL_LOC_SHIFT)
|
||||
<< (24-drive*8));
|
||||
<< driveshift);
|
||||
block |= bit << MVS_SGPIO_DCTRL_LOC_SHIFT;
|
||||
break;
|
||||
case 2: /* fail */
|
||||
block &= ~((0x7 << MVS_SGPIO_DCTRL_ERR_SHIFT)
|
||||
<< (24-drive*8));
|
||||
<< driveshift);
|
||||
block |= bit << MVS_SGPIO_DCTRL_ERR_SHIFT;
|
||||
break;
|
||||
}
|
||||
|
||||
mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id,
|
||||
block);
|
||||
iowrite32be(block,
|
||||
regs + MVS_SGPIO_DCTRL +
|
||||
MVS_SGPIO_HOST_OFFSET * mvi->id);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1132,7 +1133,7 @@ static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv,
|
|||
void __iomem *regs = mvi->regs_ex - 0x10200;
|
||||
|
||||
mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id,
|
||||
be32_to_cpu(((u32 *) write_data)[i]));
|
||||
((u32 *) write_data)[i]);
|
||||
}
|
||||
return reg_count;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue