1
0
Fork 0

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
  ...
pull/30/head
Linus Torvalds 2018-04-05 15:05:53 -07:00
commit 052c220da3
168 changed files with 6214 additions and 13066 deletions

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
/*

View File

@ -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,8 +1186,10 @@ 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;
}
}
/*
@ -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;
}

View File

@ -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;
}

View File

@ -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) {

View File

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

View File

@ -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) {

View File

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

View File

@ -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);
}

View File

@ -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 */

View File

@ -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(&reg->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(&reg->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(&reg->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);

View File

@ -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;
}

View File

@ -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;
}

View File

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

View File

@ -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, &param, &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",

View File

@ -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 *);

View File

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

View File

@ -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;
}
link_status = ntohl(pcmd->u.info.lstatus_to_modtype);
mod_type = FW_PORT_CMD_MODTYPE_G(link_status);
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);
hw->pport[port_id].link_status =
FW_PORT_CMD_LSTATUS_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;

View File

@ -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 *));

View File

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

View File

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

View File

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

View File

@ -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);
}
}

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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:
*/

View File

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

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

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

View File

@ -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);

View File

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

View File

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

View File

@ -33,7 +33,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
case ATA_CMD_FPDMA_RECV:
case ATA_CMD_FPDMA_SEND:
case ATA_CMD_NCQ_NON_DATA:
return HISI_SAS_SATA_PROTOCOL_FPDMA;
return HISI_SAS_SATA_PROTOCOL_FPDMA;
case ATA_CMD_DOWNLOAD_MICRO:
case ATA_CMD_ID_ATA:
@ -45,7 +45,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
case ATA_CMD_WRITE_LOG_EXT:
case ATA_CMD_PIO_WRITE:
case ATA_CMD_PIO_WRITE_EXT:
return HISI_SAS_SATA_PROTOCOL_PIO;
return HISI_SAS_SATA_PROTOCOL_PIO;
case ATA_CMD_DSM:
case ATA_CMD_DOWNLOAD_MICRO_DMA:
@ -64,7 +64,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
case ATA_CMD_WRITE_LOG_DMA_EXT:
case ATA_CMD_WRITE_STREAM_DMA_EXT:
case ATA_CMD_ZAC_MGMT_IN:
return HISI_SAS_SATA_PROTOCOL_DMA;
return HISI_SAS_SATA_PROTOCOL_DMA;
case ATA_CMD_CHK_POWER:
case ATA_CMD_DEV_RESET:
@ -77,21 +77,21 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
case ATA_CMD_STANDBY:
case ATA_CMD_STANDBYNOW1:
case ATA_CMD_ZAC_MGMT_OUT:
return HISI_SAS_SATA_PROTOCOL_NONDATA;
return HISI_SAS_SATA_PROTOCOL_NONDATA;
default:
{
if (fis->command == ATA_CMD_SET_MAX) {
switch (fis->features) {
case ATA_SET_MAX_PASSWD:
case ATA_SET_MAX_LOCK:
return HISI_SAS_SATA_PROTOCOL_PIO;
return HISI_SAS_SATA_PROTOCOL_PIO;
case ATA_SET_MAX_PASSWD_DMA:
case ATA_SET_MAX_UNLOCK_DMA:
return HISI_SAS_SATA_PROTOCOL_DMA;
return HISI_SAS_SATA_PROTOCOL_DMA;
default:
return HISI_SAS_SATA_PROTOCOL_NONDATA;
return HISI_SAS_SATA_PROTOCOL_NONDATA;
}
}
if (direction == DMA_NONE)
@ -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,

View File

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

View File

@ -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);

View File

@ -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);

View File

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

View File

@ -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,45 +3825,18 @@ 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);
kfree(sglist);
return NULL;
}
sg_set_page(&scatterlist[i], page, 0, 0);
sglist->scatterlist = sgl_alloc_order(buf_len, order, false, GFP_KERNEL,
&sglist->num_sg);
if (!sglist->scatterlist) {
kfree(sglist);
return NULL;
}
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;

View File

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

View File

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

View File

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

View File

@ -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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */

View File

@ -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,8 +3469,8 @@ 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,
"Max number of FCP commands we can queue to a specific target port");
LPFC_VPORT_ATTR_RW(tgt_queue_depth, 65535, 10, 65535,
"Max number of FCP commands we can queue to a specific target port");
/*
# hba_queue_depth: This parameter is used to limit the number of outstanding
@ -4104,23 +4115,32 @@ 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 &&
phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
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 "
"to %d. Speed is not supported in loop mode.\n",
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);
"0469 lpfc_link_speed attribute cannot be set to %d, "
"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;
}
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 */

View File

@ -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 */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,8 +696,9 @@ 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 */
set_bit(LPFC_DATA_READY, &phba->data_flags);
/* 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 ||
phba->link_flag & LS_MDS_LOOPBACK) {
@ -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) ||

View File

@ -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) */

View File

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

View File

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

View File

@ -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,
&reg_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,20 +7487,43 @@ 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 +
LPFC_SLIPORT_IF0_SMPHR;
phba->sli4_hba.ISRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
LPFC_HST_ISR0;
phba->sli4_hba.IMRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
LPFC_HST_IMR0;
phba->sli4_hba.ISCRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
LPFC_HST_ISCR0;
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;
phba->sli4_hba.IMRregaddr = phba->sli4_hba.ctrl_regs_memmap_p +
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;
}
} 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;

View File

@ -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);

View File

@ -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++;

View File

@ -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,12 +2014,16 @@ 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);
/* 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;
}
}
if (bf_get_be32(prli_recov, nvpr))
ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
"6029 NVME PRLI Cmpl w1 x%08x "
"w4 x%08x w5 x%08x flag x%x, "

View File

@ -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",
@ -274,14 +405,14 @@ lpfc_nvme_cmpl_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
static int
lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
struct lpfc_dmabuf *inp,
struct nvmefc_ls_req *pnvme_lsreq,
void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *,
struct lpfc_wcqe_complete *),
struct lpfc_nodelist *ndlp, uint32_t num_entry,
uint32_t tmo, uint8_t retry)
struct nvmefc_ls_req *pnvme_lsreq,
void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *,
struct lpfc_wcqe_complete *),
struct lpfc_nodelist *ndlp, uint32_t num_entry,
uint32_t tmo, uint8_t retry)
{
struct lpfc_hba *phba = vport->phba;
union lpfc_wqe *wqe;
struct lpfc_hba *phba = vport->phba;
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,6 +769,60 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
*/
sgl = lpfc_ncmd->nvme_sgl;
sgl->sge_len = cpu_to_le32(nCmd->cmdlen);
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 = 56;
wqe->generic.bde.addrHigh = 0;
wqe->generic.bde.addrLow = 64; /* Word 16 */
/* Word 10 - dbde is 0, wqes is 1 in template */
/*
* Embed the payload in the last half of the WQE
* WQE words 16-30 get the NVME CMD IU payload
*
* WQE words 16-19 get payload Words 1-4
* WQE words 20-21 get payload Words 6-7
* WQE words 22-29 get payload Words 16-23
*/
wptr = &wqe->words[16]; /* WQE ptr */
dptr = (uint32_t *)nCmd->cmdaddr; /* payload ptr */
dptr++; /* Skip Word 0 in payload */
*wptr++ = *dptr++; /* Word 1 */
*wptr++ = *dptr++; /* Word 2 */
*wptr++ = *dptr++; /* Word 3 */
*wptr++ = *dptr++; /* Word 4 */
dptr++; /* Skip Word 5 in payload */
*wptr++ = *dptr++; /* Word 6 */
*wptr++ = *dptr++; /* Word 7 */
dptr += 8; /* Skip Words 8-15 in payload */
*wptr++ = *dptr++; /* Word 16 */
*wptr++ = *dptr++; /* Word 17 */
*wptr++ = *dptr++; /* Word 18 */
*wptr++ = *dptr++; /* Word 19 */
*wptr++ = *dptr++; /* Word 20 */
*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++;
@ -641,58 +836,6 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
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;
/* 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.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);
/*
* Embed the payload in the last half of the WQE
* WQE words 16-30 get the NVME CMD IU payload
*
* WQE words 16-19 get payload Words 1-4
* WQE words 20-21 get payload Words 6-7
* WQE words 22-29 get payload Words 16-23
*/
wptr = &wqe->words[16]; /* WQE ptr */
dptr = (uint32_t *)nCmd->cmdaddr; /* payload ptr */
dptr++; /* Skip Word 0 in payload */
*wptr++ = *dptr++; /* Word 1 */
*wptr++ = *dptr++; /* Word 2 */
*wptr++ = *dptr++; /* Word 3 */
*wptr++ = *dptr++; /* Word 4 */
dptr++; /* Skip Word 5 in payload */
*wptr++ = *dptr++; /* Word 6 */
*wptr++ = *dptr++; /* Word 7 */
dptr += 8; /* Skip Words 8-15 in payload */
*wptr++ = *dptr++; /* Word 16 */
*wptr++ = *dptr++; /* Word 17 */
*wptr++ = *dptr++; /* Word 18 */
*wptr++ = *dptr++; /* Word 19 */
*wptr++ = *dptr++; /* Word 20 */
*wptr++ = *dptr++; /* Word 21 */
*wptr++ = *dptr++; /* Word 22 */
*wptr = *dptr; /* Word 23 */
}
#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);

View File

@ -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 */

View File

@ -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
nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
ctxp->flag &= ~LPFC_NVMET_DEFER_RCV_REPOST;
/* Free the nvmebuf since a new buffer already replaced it */
nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
}
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;

View File

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

View File

@ -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,16 +4138,11 @@ 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) &&
time_after(jiffies, pnode->last_change_time +
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->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);

View File

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

View File

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

View File

@ -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);

View File

@ -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."

View File

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

View File

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

View File

@ -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;
_base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
&ioc->scsi_lookup_lock);
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,135 +3521,45 @@ _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;
_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);
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);
}
/**
@ -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 (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, MPT_MAX_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, MPT_MAX_PHYS_SEGMENTS);
}
ioc->shost->sg_tablesize = sg_tablesize;
}
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;
/* calculate reply descriptor post queue depth */
ioc->reply_post_queue_depth = ioc->hba_queue_depth +
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);
/* 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;
/* 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

View File

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

View File

@ -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",

View File

@ -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);

View File

@ -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,11 +10424,18 @@ _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:
@ -10524,26 +10532,34 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
shost->transportt = mpt3sas_transport_template;
shost->unique_id = ioc->id;
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);
} 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);
} else {
shost->max_sectors = max_sectors & 0xFFFE;
pr_info(MPT3SAS_FMT
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);
} 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);
} else {
shost->max_sectors = max_sectors & 0xFFFE;
pr_info(MPT3SAS_FMT
"The max_sectors value is set to %d\n",
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 },

View File

@ -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)) {

View File

@ -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);

View File

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