diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-03 02:03:53 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-03 02:03:53 +0200 |
commit | 79f51b7b9c4719303f758ae8406c4e5997ed6aa3 (patch) | |
tree | 33ca1c3ee11848e75d90f811038fcd149e69d258 | |
parent | Merge tag 'mtd/for-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/... (diff) | |
parent | scsi: aic7xxx: aic97xx: Remove FreeBSD-specific code (diff) | |
download | linux-79f51b7b9c4719303f758ae8406c4e5997ed6aa3.tar.xz linux-79f51b7b9c4719303f758ae8406c4e5997ed6aa3.zip |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This series has a huge amount of churn because it pulls in Mauro's doc
update changing all our txt files to rst ones.
Excluding that, we have the usual driver updates (qla2xxx, ufs, lpfc,
zfcp, ibmvfc, pm80xx, aacraid), a treewide update for scnprintf and
some other minor updates.
The major core change is Hannes moving functions out of the aacraid
driver and into the core"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (223 commits)
scsi: aic7xxx: aic97xx: Remove FreeBSD-specific code
scsi: ufs: Do not rely on prefetched data
scsi: dc395x: remove dc395x_bios_param
scsi: libiscsi: Fix error count for active session
scsi: hpsa: correct race condition in offload enabled
scsi: message: fusion: Replace zero-length array with flexible-array member
scsi: qedi: Add PCI shutdown handler support
scsi: qedi: Add MFW error recovery process
scsi: ufs: Enable block layer runtime PM for well-known logical units
scsi: ufs-qcom: Override devfreq parameters
scsi: ufshcd: Let vendor override devfreq parameters
scsi: ufshcd: Update the set frequency to devfreq
scsi: ufs: Resume ufs host before accessing ufs device
scsi: ufs-mediatek: customize the delay for enabling host
scsi: ufs: make HCE polling more compact to improve initialization latency
scsi: ufs: allow custom delay prior to host enabling
scsi: ufs-mediatek: use common delay function
scsi: ufs: introduce common and flexible delay function
scsi: ufs: use an enum for host capabilities
scsi: ufs: fix uninitialized tx_lanes in ufshcd_disable_tx_lcc()
...
264 files changed, 13002 insertions, 8510 deletions
diff --git a/Documentation/driver-api/libata.rst b/Documentation/driver-api/libata.rst index 207f0d24de69..e2f87b82b074 100644 --- a/Documentation/driver-api/libata.rst +++ b/Documentation/driver-api/libata.rst @@ -401,7 +401,7 @@ Error handling ============== This chapter describes how errors are handled under libata. Readers are -advised to read SCSI EH (Documentation/scsi/scsi_eh.txt) and ATA +advised to read SCSI EH (Documentation/scsi/scsi_eh.rst) and ATA exceptions doc first. Origins of commands diff --git a/Documentation/index.rst b/Documentation/index.rst index 9df95bab4de8..01795a40da29 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -131,6 +131,7 @@ needed). bpf/index usb/index PCI/index + scsi/index misc-devices/index scheduler/index diff --git a/Documentation/scsi/53c700.txt b/Documentation/scsi/53c700.rst index e31aceb6df15..53a0e9f9c198 100644 --- a/Documentation/scsi/53c700.txt +++ b/Documentation/scsi/53c700.rst @@ -1,3 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======================= +The 53c700 Driver Notes +======================= + General Description =================== @@ -16,9 +22,9 @@ fill in to get the driver working. Compile Time Flags ================== -A compile time flag is: +A compile time flag is:: -CONFIG_53C700_LE_ON_BE + CONFIG_53C700_LE_ON_BE define if the chipset must be supported in little endian mode on a big endian architecture (used for the 700 on parisc). @@ -51,9 +57,11 @@ consistent with the best operation of the chip (although some choose to drive it off the CPU or bus clock rather than going to the expense of an extra clock chip). The best operation clock speeds are: -53c700 - 25MHz -53c700-66 - 50MHz -53c710 - 40Mhz +========= ===== +53c700 25MHz +53c700-66 50MHz +53c710 40Mhz +========= ===== Writing Your Glue Driver ======================== @@ -69,7 +77,7 @@ parameters that matter to you (see below), plumb the NCR_700_intr routine into the interrupt line and call NCR_700_detect with the host template and the new parameters as arguments. You should also call the relevant request_*_region function and place the register base -address into the `base' pointer of the host parameters. +address into the 'base' pointer of the host parameters. In the release routine, you must free the NCR_700_Host_Parameters that you allocated, call the corresponding release_*_region and free the @@ -78,7 +86,7 @@ interrupt. Handling Interrupts ------------------- -In general, you should just plumb the card's interrupt line in with +In general, you should just plumb the card's interrupt line in with request_irq(irq, NCR_700_intr, <irq flags>, <driver name>, host); @@ -95,41 +103,32 @@ Settable NCR_700_Host_Parameters The following are a list of the user settable parameters: clock: (MANDATORY) - -Set to the clock speed of the chip in MHz. + Set to the clock speed of the chip in MHz. base: (MANDATORY) - -set to the base of the io or mem region for the register set. On 64 -bit architectures this is only 32 bits wide, so the registers must be -mapped into the low 32 bits of memory. + Set to the base of the io or mem region for the register set. On 64 + bit architectures this is only 32 bits wide, so the registers must be + mapped into the low 32 bits of memory. pci_dev: (OPTIONAL) - -set to the PCI board device. Leave NULL for a non-pci board. This is -used for the pci_alloc_consistent() and pci_map_*() functions. + Set to the PCI board device. Leave NULL for a non-pci board. This is + used for the pci_alloc_consistent() and pci_map_*() functions. dmode_extra: (OPTIONAL, 53c710 only) - -extra flags for the DMODE register. These are used to control bus -output pins on the 710. The settings should be a combination of -DMODE_FC1 and DMODE_FC2. What these pins actually do is entirely up -to the board designer. Usually it is safe to ignore this setting. + Extra flags for the DMODE register. These are used to control bus + output pins on the 710. The settings should be a combination of + DMODE_FC1 and DMODE_FC2. What these pins actually do is entirely up + to the board designer. Usually it is safe to ignore this setting. differential: (OPTIONAL) - -set to 1 if the chip drives a differential bus. + Set to 1 if the chip drives a differential bus. force_le_on_be: (OPTIONAL, only if CONFIG_53C700_LE_ON_BE is set) - -set to 1 if the chip is operating in little endian mode on a big -endian architecture. + Set to 1 if the chip is operating in little endian mode on a big + endian architecture. chip710: (OPTIONAL) - -set to 1 if the chip is a 53c710. + Set to 1 if the chip is a 53c710. burst_disable: (OPTIONAL, 53c710 only) - -disable 8 byte bursting for DMA transfers. - + Disable 8 byte bursting for DMA transfers. diff --git a/Documentation/scsi/BusLogic.txt b/Documentation/scsi/BusLogic.rst index 48e982cd6fe7..b60169812358 100644 --- a/Documentation/scsi/BusLogic.txt +++ b/Documentation/scsi/BusLogic.rst @@ -1,6 +1,11 @@ - BusLogic MultiMaster and FlashPoint SCSI Driver for Linux +.. SPDX-License-Identifier: GPL-2.0 + +========================================================= +BusLogic MultiMaster and FlashPoint SCSI Driver for Linux +========================================================= Version 2.0.15 for Linux 2.0 + Version 2.1.15 for Linux 2.1 PRODUCTION RELEASE @@ -8,13 +13,16 @@ 17 August 1998 Leonard N. Zubkoff + Dandelion Digital + lnz@dandelion.com Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com> - INTRODUCTION +Introduction +============ BusLogic, Inc. designed and manufactured a variety of high performance SCSI host adapters which share a common programming interface across a diverse @@ -86,9 +94,11 @@ Contact information for offices in Europe and Japan is available on the Web site. - DRIVER FEATURES +Driver Features +=============== -o Configuration Reporting and Testing +Configuration Reporting and Testing +----------------------------------- During system initialization, the driver reports extensively on the host adapter hardware configuration, including the synchronous transfer parameters @@ -130,7 +140,8 @@ o Configuration Reporting and Testing The status of Wide Negotiation, Disconnect/Reconnect, and Tagged Queuing are reported as "Enabled", Disabled", or a sequence of "Y" and "N" letters. -o Performance Features +Performance Features +-------------------- BusLogic SCSI Host Adapters directly implement SCSI-2 Tagged Queuing, and so support has been included in the driver to utilize tagged queuing with any @@ -150,7 +161,8 @@ o Performance Features queue depth of 1 is selected. Tagged queuing is also disabled for individual target devices if disconnect/reconnect is disabled for that device. -o Robustness Features +Robustness Features +------------------- The driver implements extensive error recovery procedures. When the higher level parts of the SCSI subsystem request that a timed out command be reset, @@ -174,7 +186,8 @@ o Robustness Features lock up or crash, and thereby allowing a clean shutdown and restart after the offending component is removed. -o PCI Configuration Support +PCI Configuration Support +------------------------- On PCI systems running kernels compiled with PCI BIOS support enabled, this driver will interrogate the PCI configuration space and use the I/O port @@ -184,19 +197,22 @@ o PCI Configuration Support used to disable the ISA compatible I/O port entirely as it is not necessary. The ISA compatible I/O port is disabled by default on the BT-948/958/958D. -o /proc File System Support +/proc File System Support +------------------------- Copies of the host adapter configuration information together with updated data transfer and error recovery statistics are available through the /proc/scsi/BusLogic/<N> interface. -o Shared Interrupts Support +Shared Interrupts Support +------------------------- On systems that support shared interrupts, any number of BusLogic Host Adapters may share the same interrupt request channel. - SUPPORTED HOST ADAPTERS +Supported Host Adapters +======================= The following list comprises the supported BusLogic SCSI Host Adapters as of the date of this document. It is recommended that anyone purchasing a BusLogic @@ -205,6 +221,7 @@ that it is or will be supported. FlashPoint Series PCI Host Adapters: +======================= ============================================= FlashPoint LT (BT-930) Ultra SCSI-3 FlashPoint LT (BT-930R) Ultra SCSI-3 with RAIDPlus FlashPoint LT (BT-920) Ultra SCSI-3 (BT-930 without BIOS) @@ -214,15 +231,19 @@ FlashPoint LW (BT-950) Wide Ultra SCSI-3 FlashPoint LW (BT-950R) Wide Ultra SCSI-3 with RAIDPlus FlashPoint DW (BT-952) Dual Channel Wide Ultra SCSI-3 FlashPoint DW (BT-952R) Dual Channel Wide Ultra SCSI-3 with RAIDPlus +======================= ============================================= MultiMaster "W" Series Host Adapters: +======= === ============================== BT-948 PCI Ultra SCSI-3 BT-958 PCI Wide Ultra SCSI-3 BT-958D PCI Wide Differential Ultra SCSI-3 +======= === ============================== MultiMaster "C" Series Host Adapters: +======== ==== ============================== BT-946C PCI Fast SCSI-2 BT-956C PCI Wide Fast SCSI-2 BT-956CD PCI Wide Differential Fast SCSI-2 @@ -232,9 +253,11 @@ BT-757C EISA Wide Fast SCSI-2 BT-757CD EISA Wide Differential Fast SCSI-2 BT-545C ISA Fast SCSI-2 BT-540CF ISA Fast SCSI-2 +======== ==== ============================== MultiMaster "S" Series Host Adapters: +======= ==== ============================== BT-445S VLB Fast SCSI-2 BT-747S EISA Fast SCSI-2 BT-747D EISA Differential Fast SCSI-2 @@ -244,11 +267,14 @@ BT-545S ISA Fast SCSI-2 BT-542D ISA Differential Fast SCSI-2 BT-742A EISA SCSI-2 (742A revision H) BT-542B ISA SCSI-2 (542B revision H) +======= ==== ============================== MultiMaster "A" Series Host Adapters: +======= ==== ============================== BT-742A EISA SCSI-2 (742A revisions A - G) BT-542B ISA SCSI-2 (542B revisions A - G) +======= ==== ============================== AMI FastDisk Host Adapters that are true BusLogic MultiMaster clones are also supported by this driver. @@ -260,9 +286,11 @@ list. The retail kit includes the bare board and manual as well as cabling and driver media and documentation that are not provided with bare boards. - FLASHPOINT INSTALLATION NOTES +FlashPoint Installation Notes +============================= -o RAIDPlus Support +RAIDPlus Support +---------------- FlashPoint Host Adapters now include RAIDPlus, Mylex's bootable software RAID. RAIDPlus is not supported on Linux, and there are no plans to support @@ -273,7 +301,8 @@ o RAIDPlus Support than RAIDPlus, so there is little impetus to include RAIDPlus support in the BusLogic driver. -o Enabling UltraSCSI Transfers +Enabling UltraSCSI Transfers +---------------------------- FlashPoint Host Adapters ship with their configuration set to "Factory Default" settings that are conservative and do not allow for UltraSCSI speed @@ -287,12 +316,14 @@ o Enabling UltraSCSI Transfers the "Optimum Performance" settings are loaded. - BT-948/958/958D INSTALLATION NOTES +BT-948/958/958D Installation Notes +================================== The BT-948/958/958D PCI Ultra SCSI Host Adapters have some features which may require attention in some circumstances when installing Linux. -o PCI I/O Port Assignments +PCI I/O Port Assignments +------------------------ When configured to factory default settings, the BT-948/958/958D will only recognize the PCI I/O port assignments made by the motherboard's PCI BIOS. @@ -312,7 +343,8 @@ o PCI I/O Port Assignments possible future I/O port conflicts. The older BT-946C/956C/956CD also have this configuration option, but the factory default setting is "Primary". -o PCI Slot Scanning Order +PCI Slot Scanning Order +----------------------- In systems with multiple BusLogic PCI Host Adapters, the order in which the PCI slots are scanned may appear reversed with the BT-948/958/958D as @@ -339,7 +371,8 @@ o PCI Slot Scanning Order so as to recognize the host adapters in the same order as they are enumerated by the host adapter's BIOS. -o Enabling UltraSCSI Transfers +Enabling UltraSCSI Transfers +---------------------------- The BT-948/958/958D ship with their configuration set to "Factory Default" settings that are conservative and do not allow for UltraSCSI speed to be @@ -353,7 +386,8 @@ o Enabling UltraSCSI Transfers "Optimum Performance" settings are loaded. - DRIVER OPTIONS +Driver Options +============== BusLogic Driver Options may be specified either via the Linux Kernel Command Line or via the Loadable Kernel Module Installation Facility. Driver Options @@ -520,30 +554,34 @@ The following examples demonstrate setting the Queue Depth for Target Devices Devices on the second host adapter to 31, and the Bus Settle Time on the second host adapter to 30 seconds. -Linux Kernel Command Line: +Linux Kernel Command Line:: linux BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30 -LILO Linux Boot Loader (in /etc/lilo.conf): +LILO Linux Boot Loader (in /etc/lilo.conf):: append = "BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30" -INSMOD Loadable Kernel Module Installation Facility: +INSMOD Loadable Kernel Module Installation Facility:: insmod BusLogic.o \ 'BusLogic="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"' -NOTE: Module Utilities 2.1.71 or later is required for correct parsing + +.. Note:: + + Module Utilities 2.1.71 or later is required for correct parsing of driver options containing commas. - DRIVER INSTALLATION +Driver Installation +=================== This distribution was prepared for Linux kernel version 2.0.35, but should be compatible with 2.0.4 or any later 2.0 series kernel. To install the new BusLogic SCSI driver, you may use the following commands, -replacing "/usr/src" with wherever you keep your Linux kernel source tree: +replacing "/usr/src" with wherever you keep your Linux kernel source tree:: cd /usr/src tar -xvzf BusLogic-2.0.15.tar.gz @@ -557,7 +595,8 @@ Then install "arch/x86/boot/zImage" as your standard kernel, run lilo if appropriate, and reboot. - BUSLOGIC ANNOUNCEMENTS MAILING LIST +BusLogic Announcements Mailing List +=================================== The BusLogic Announcements Mailing List provides a forum for informing Linux users of new driver releases and other announcements regarding Linux support diff --git a/Documentation/scsi/FlashPoint.rst b/Documentation/scsi/FlashPoint.rst new file mode 100644 index 000000000000..ef3c07e94ad6 --- /dev/null +++ b/Documentation/scsi/FlashPoint.rst @@ -0,0 +1,176 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================================== +The BusLogic FlashPoint SCSI Driver +=================================== + +The BusLogic FlashPoint SCSI Host Adapters are now fully supported on Linux. +The upgrade program described below has been officially terminated effective +31 March 1997 since it is no longer needed. + +:: + + MYLEX INTRODUCES LINUX OPERATING SYSTEM SUPPORT FOR ITS + BUSLOGIC FLASHPOINT LINE OF SCSI HOST ADAPTERS + + + FREMONT, CA, -- October 8, 1996 -- Mylex Corporation has expanded Linux + operating system support to its BusLogic brand of FlashPoint Ultra SCSI + host adapters. All of BusLogic's other SCSI host adapters, including the + MultiMaster line, currently support the Linux operating system. Linux + drivers and information will be available on October 15th at + http://sourceforge.net/projects/dandelion/. + + "Mylex is committed to supporting the Linux community," says Peter Shambora, + vice president of marketing for Mylex. "We have supported Linux driver + development and provided technical support for our host adapters for several + years, and are pleased to now make our FlashPoint products available to this + user base." + +The Linux Operating System +========================== + +Linux is a freely-distributed implementation of UNIX for Intel x86, Sun +SPARC, SGI MIPS, Motorola 68k, Digital Alpha AXP and Motorola PowerPC +machines. It supports a wide range of software, including the X Window +System, Emacs, and TCP/IP networking. Further information is available at +http://www.linux.org and http://www.ssc.com/. + +FlashPoint Host Adapters +======================== + +The FlashPoint family of Ultra SCSI host adapters, designed for workstation +and file server environments, are available in narrow, wide, dual channel, +and dual channel wide versions. These adapters feature SeqEngine +automation technology, which minimizes SCSI command overhead and reduces +the number of interrupts generated to the CPU. + +About Mylex +=========== + +Mylex Corporation (NASDAQ/NM SYMBOL: MYLX), founded in 1983, is a leading +producer of RAID technology and network management products. The company +produces high performance disk array (RAID) controllers, and complementary +computer products for network servers, mass storage systems, workstations +and system boards. Through its wide range of RAID controllers and its +BusLogic line of Ultra SCSI host adapter products, Mylex provides enabling +intelligent I/O technologies that increase network management control, +enhance CPU utilization, optimize I/O performance, and ensure data security +and availability. Products are sold globally through a network of OEMs, +major distributors, VARs, and system integrators. Mylex Corporation is +headquartered at 34551 Ardenwood Blvd., Fremont, CA. + +Contact: +======== + +:: + + Peter Shambora + Vice President of Marketing + Mylex Corp. + 510/796-6100 + peters@mylex.com + + +:: + + ANNOUNCEMENT + BusLogic FlashPoint LT/BT-948 Upgrade Program + 1 February 1996 + + ADDITIONAL ANNOUNCEMENT + BusLogic FlashPoint LW/BT-958 Upgrade Program + 14 June 1996 + + Ever since its introduction last October, the BusLogic FlashPoint LT has + been problematic for members of the Linux community, in that no Linux + drivers have been available for this new Ultra SCSI product. Despite its + officially being positioned as a desktop workstation product, and not being + particularly well suited for a high performance multitasking operating + system like Linux, the FlashPoint LT has been touted by computer system + vendors as the latest thing, and has been sold even on many of their high + end systems, to the exclusion of the older MultiMaster products. This has + caused grief for many people who inadvertently purchased a system expecting + that all BusLogic SCSI Host Adapters were supported by Linux, only to + discover that the FlashPoint was not supported and would not be for quite + some time, if ever. + + After this problem was identified, BusLogic contacted its major OEM + customers to make sure the BT-946C/956C MultiMaster cards would still be + made available, and that Linux users who mistakenly ordered systems with + the FlashPoint would be able to upgrade to the BT-946C. While this helped + many purchasers of new systems, it was only a partial solution to the + overall problem of FlashPoint support for Linux users. It did nothing to + assist the people who initially purchased a FlashPoint for a supported + operating system and then later decided to run Linux, or those who had + ended up with a FlashPoint LT, believing it was supported, and were unable + to return it. + + In the middle of December, I asked to meet with BusLogic's senior + management to discuss the issues related to Linux and free software support + for the FlashPoint. Rumors of varying accuracy had been circulating + publicly about BusLogic's attitude toward the Linux community, and I felt + it was best that these issues be addressed directly. I sent an email + message after 11pm one evening, and the meeting took place the next + afternoon. Unfortunately, corporate wheels sometimes grind slowly, + especially when a company is being acquired, and so it's taken until now + before the details were completely determined and a public statement could + be made. + + BusLogic is not prepared at this time to release the information necessary + for third parties to write drivers for the FlashPoint. The only existing + FlashPoint drivers have been written directly by BusLogic Engineering, and + there is no FlashPoint documentation sufficiently detailed to allow outside + developers to write a driver without substantial assistance. While there + are people at BusLogic who would rather not release the details of the + FlashPoint architecture at all, that debate has not yet been settled either + way. In any event, even if documentation were available today it would + take quite a while for a usable driver to be written, especially since I'm + not convinced that the effort required would be worthwhile. + + However, BusLogic does remain committed to providing a high performance + SCSI solution for the Linux community, and does not want to see anyone left + unable to run Linux because they have a Flashpoint LT. Therefore, BusLogic + has put in place a direct upgrade program to allow any Linux user worldwide + to trade in their FlashPoint LT for the new BT-948 MultiMaster PCI Ultra + SCSI Host Adapter. The BT-948 is the Ultra SCSI successor to the BT-946C + and has all the best features of both the BT-946C and FlashPoint LT, + including smart termination and a flash PROM for easy firmware updates, and + is of course compatible with the present Linux driver. The price for this + upgrade has been set at US $45 plus shipping and handling, and the upgrade + program will be administered through BusLogic Technical Support, which can + be reached by electronic mail at techsup@buslogic.com, by Voice at +1 408 + 654-0760, or by FAX at +1 408 492-1542. + + As of 14 June 1996, the original BusLogic FlashPoint LT to BT-948 upgrade + program has now been extended to encompass the FlashPoint LW Wide Ultra + SCSI Host Adapter. Any Linux user worldwide may trade in their FlashPoint + LW (BT-950) for a BT-958 MultiMaster PCI Ultra SCSI Host Adapter. The + price for this upgrade has been set at US $65 plus shipping and handling. + + I was a beta test site for the BT-948/958, and versions 1.2.1 and 1.3.1 of + my BusLogic driver already included latent support for the BT-948/958. + Additional cosmetic support for the Ultra SCSI MultiMaster cards was added + subsequent releases. As a result of this cooperative testing process, + several firmware bugs were found and corrected. My heavily loaded Linux + test system provided an ideal environment for testing error recovery + processes that are much more rarely exercised in production systems, but + are crucial to overall system stability. It was especially convenient + being able to work directly with their firmware engineer in demonstrating + the problems under control of the firmware debugging environment; things + sure have come a long way since the last time I worked on firmware for an + embedded system. I am presently working on some performance testing and + expect to have some data to report in the not too distant future. + + BusLogic asked me to send this announcement since a large percentage of the + questions regarding support for the FlashPoint have either been sent to me + directly via email, or have appeared in the Linux newsgroups in which I + participate. To summarize, BusLogic is offering Linux users an upgrade + from the unsupported FlashPoint LT (BT-930) to the supported BT-948 for US + $45 plus shipping and handling, or from the unsupported FlashPoint LW + (BT-950) to the supported BT-958 for $65 plus shipping and handling. + Contact BusLogic Technical Support at techsup@buslogic.com or +1 408 + 654-0760 to take advantage of their offer. + + Leonard N. Zubkoff + lnz@dandelion.com diff --git a/Documentation/scsi/FlashPoint.txt b/Documentation/scsi/FlashPoint.txt deleted file mode 100644 index 5b5f29cb9f8b..000000000000 --- a/Documentation/scsi/FlashPoint.txt +++ /dev/null @@ -1,163 +0,0 @@ -The BusLogic FlashPoint SCSI Host Adapters are now fully supported on Linux. -The upgrade program described below has been officially terminated effective -31 March 1997 since it is no longer needed. - - - - MYLEX INTRODUCES LINUX OPERATING SYSTEM SUPPORT FOR ITS - BUSLOGIC FLASHPOINT LINE OF SCSI HOST ADAPTERS - - -FREMONT, CA, -- October 8, 1996 -- Mylex Corporation has expanded Linux -operating system support to its BusLogic brand of FlashPoint Ultra SCSI -host adapters. All of BusLogic's other SCSI host adapters, including the -MultiMaster line, currently support the Linux operating system. Linux -drivers and information will be available on October 15th at -http://sourceforge.net/projects/dandelion/. - -"Mylex is committed to supporting the Linux community," says Peter Shambora, -vice president of marketing for Mylex. "We have supported Linux driver -development and provided technical support for our host adapters for several -years, and are pleased to now make our FlashPoint products available to this -user base." - -The Linux Operating System - -Linux is a freely-distributed implementation of UNIX for Intel x86, Sun -SPARC, SGI MIPS, Motorola 68k, Digital Alpha AXP and Motorola PowerPC -machines. It supports a wide range of software, including the X Window -System, Emacs, and TCP/IP networking. Further information is available at -http://www.linux.org and http://www.ssc.com/. - -FlashPoint Host Adapters - -The FlashPoint family of Ultra SCSI host adapters, designed for workstation -and file server environments, are available in narrow, wide, dual channel, -and dual channel wide versions. These adapters feature SeqEngine -automation technology, which minimizes SCSI command overhead and reduces -the number of interrupts generated to the CPU. - -About Mylex - -Mylex Corporation (NASDAQ/NM SYMBOL: MYLX), founded in 1983, is a leading -producer of RAID technology and network management products. The company -produces high performance disk array (RAID) controllers, and complementary -computer products for network servers, mass storage systems, workstations -and system boards. Through its wide range of RAID controllers and its -BusLogic line of Ultra SCSI host adapter products, Mylex provides enabling -intelligent I/O technologies that increase network management control, -enhance CPU utilization, optimize I/O performance, and ensure data security -and availability. Products are sold globally through a network of OEMs, -major distributors, VARs, and system integrators. Mylex Corporation is -headquartered at 34551 Ardenwood Blvd., Fremont, CA. - - #### - -Contact: - -Peter Shambora -Vice President of Marketing -Mylex Corp. -510/796-6100 -peters@mylex.com - - ANNOUNCEMENT - BusLogic FlashPoint LT/BT-948 Upgrade Program - 1 February 1996 - - ADDITIONAL ANNOUNCEMENT - BusLogic FlashPoint LW/BT-958 Upgrade Program - 14 June 1996 - -Ever since its introduction last October, the BusLogic FlashPoint LT has -been problematic for members of the Linux community, in that no Linux -drivers have been available for this new Ultra SCSI product. Despite its -officially being positioned as a desktop workstation product, and not being -particularly well suited for a high performance multitasking operating -system like Linux, the FlashPoint LT has been touted by computer system -vendors as the latest thing, and has been sold even on many of their high -end systems, to the exclusion of the older MultiMaster products. This has -caused grief for many people who inadvertently purchased a system expecting -that all BusLogic SCSI Host Adapters were supported by Linux, only to -discover that the FlashPoint was not supported and would not be for quite -some time, if ever. - -After this problem was identified, BusLogic contacted its major OEM -customers to make sure the BT-946C/956C MultiMaster cards would still be -made available, and that Linux users who mistakenly ordered systems with -the FlashPoint would be able to upgrade to the BT-946C. While this helped -many purchasers of new systems, it was only a partial solution to the -overall problem of FlashPoint support for Linux users. It did nothing to -assist the people who initially purchased a FlashPoint for a supported -operating system and then later decided to run Linux, or those who had -ended up with a FlashPoint LT, believing it was supported, and were unable -to return it. - -In the middle of December, I asked to meet with BusLogic's senior -management to discuss the issues related to Linux and free software support -for the FlashPoint. Rumors of varying accuracy had been circulating -publicly about BusLogic's attitude toward the Linux community, and I felt -it was best that these issues be addressed directly. I sent an email -message after 11pm one evening, and the meeting took place the next -afternoon. Unfortunately, corporate wheels sometimes grind slowly, -especially when a company is being acquired, and so it's taken until now -before the details were completely determined and a public statement could -be made. - -BusLogic is not prepared at this time to release the information necessary -for third parties to write drivers for the FlashPoint. The only existing -FlashPoint drivers have been written directly by BusLogic Engineering, and -there is no FlashPoint documentation sufficiently detailed to allow outside -developers to write a driver without substantial assistance. While there -are people at BusLogic who would rather not release the details of the -FlashPoint architecture at all, that debate has not yet been settled either -way. In any event, even if documentation were available today it would -take quite a while for a usable driver to be written, especially since I'm -not convinced that the effort required would be worthwhile. - -However, BusLogic does remain committed to providing a high performance -SCSI solution for the Linux community, and does not want to see anyone left -unable to run Linux because they have a Flashpoint LT. Therefore, BusLogic -has put in place a direct upgrade program to allow any Linux user worldwide -to trade in their FlashPoint LT for the new BT-948 MultiMaster PCI Ultra -SCSI Host Adapter. The BT-948 is the Ultra SCSI successor to the BT-946C -and has all the best features of both the BT-946C and FlashPoint LT, -including smart termination and a flash PROM for easy firmware updates, and -is of course compatible with the present Linux driver. The price for this -upgrade has been set at US $45 plus shipping and handling, and the upgrade -program will be administered through BusLogic Technical Support, which can -be reached by electronic mail at techsup@buslogic.com, by Voice at +1 408 -654-0760, or by FAX at +1 408 492-1542. - -As of 14 June 1996, the original BusLogic FlashPoint LT to BT-948 upgrade -program has now been extended to encompass the FlashPoint LW Wide Ultra -SCSI Host Adapter. Any Linux user worldwide may trade in their FlashPoint -LW (BT-950) for a BT-958 MultiMaster PCI Ultra SCSI Host Adapter. The -price for this upgrade has been set at US $65 plus shipping and handling. - -I was a beta test site for the BT-948/958, and versions 1.2.1 and 1.3.1 of -my BusLogic driver already included latent support for the BT-948/958. -Additional cosmetic support for the Ultra SCSI MultiMaster cards was added -subsequent releases. As a result of this cooperative testing process, -several firmware bugs were found and corrected. My heavily loaded Linux -test system provided an ideal environment for testing error recovery -processes that are much more rarely exercised in production systems, but -are crucial to overall system stability. It was especially convenient -being able to work directly with their firmware engineer in demonstrating -the problems under control of the firmware debugging environment; things -sure have come a long way since the last time I worked on firmware for an -embedded system. I am presently working on some performance testing and -expect to have some data to report in the not too distant future. - -BusLogic asked me to send this announcement since a large percentage of the -questions regarding support for the FlashPoint have either been sent to me -directly via email, or have appeared in the Linux newsgroups in which I -participate. To summarize, BusLogic is offering Linux users an upgrade -from the unsupported FlashPoint LT (BT-930) to the supported BT-948 for US -$45 plus shipping and handling, or from the unsupported FlashPoint LW -(BT-950) to the supported BT-958 for $65 plus shipping and handling. -Contact BusLogic Technical Support at techsup@buslogic.com or +1 408 -654-0760 to take advantage of their offer. - - Leonard N. Zubkoff - lnz@dandelion.com diff --git a/Documentation/scsi/NinjaSCSI.rst b/Documentation/scsi/NinjaSCSI.rst new file mode 100644 index 000000000000..999a6ed5bf7e --- /dev/null +++ b/Documentation/scsi/NinjaSCSI.rst @@ -0,0 +1,164 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================================= +WorkBiT NinjaSCSI-3/32Bi driver for Linux +========================================= + +1. Comment +========== + +This is Workbit corp.'s(http://www.workbit.co.jp/) NinjaSCSI-3 +for Linux. + +2. My Linux environment +======================= + +:Linux kernel: 2.4.7 / 2.2.19 +:pcmcia-cs: 3.1.27 +:gcc: gcc-2.95.4 +:PC card: I-O data PCSC-F (NinjaSCSI-3), + I-O data CBSC-II in 16 bit mode (NinjaSCSI-32Bi) +:SCSI device: I-O data CDPS-PX24 (CD-ROM drive), + Media Intelligent MMO-640GT (Optical disk drive) + +3. Install +========== + +(a) Check your PC card is true "NinjaSCSI-3" card. + + If you installed pcmcia-cs already, pcmcia reports your card as UNKNOWN + card, and write ["WBT", "NinjaSCSI-3", "R1.0"] or some other string to + your console or log file. + + You can also use "cardctl" program (this program is in pcmcia-cs source + code) to get more info. + + :: + + # cat /var/log/messages + ... + Jan 2 03:45:06 lindberg cardmgr[78]: unsupported card in socket 1 + Jan 2 03:45:06 lindberg cardmgr[78]: product info: "WBT", "NinjaSCSI-3", "R1.0" + ... + # cardctl ident + Socket 0: + no product info available + Socket 1: + product info: "IO DATA", "CBSC16 ", "1" + + +(b) Get the Linux kernel source, and extract it to /usr/src. + Because the NinjaSCSI driver requires some SCSI header files in Linux + kernel source, I recommend rebuilding your kernel; this eliminates + some versioning problems. + + :: + + $ cd /usr/src + $ tar -zxvf linux-x.x.x.tar.gz + $ cd linux + $ make config + ... + +(c) If you use this driver with Kernel 2.2, unpack pcmcia-cs in some directory + and make & install. This driver requires the pcmcia-cs header file. + + :: + + $ cd /usr/src + $ tar zxvf cs-pcmcia-cs-3.x.x.tar.gz + ... + +(d) Extract this driver's archive somewhere, and edit Makefile, then do make:: + + $ tar -zxvf nsp_cs-x.x.tar.gz + $ cd nsp_cs-x.x + $ emacs Makefile + ... + $ make + +(e) Copy nsp_cs.ko to suitable place, like /lib/modules/<Kernel version>/pcmcia/ . + +(f) Add these lines to /etc/pcmcia/config . + + If you use pcmcia-cs-3.1.8 or later, we can use "nsp_cs.conf" file. + So, you don't need to edit file. Just copy to /etc/pcmcia/ . + + :: + + device "nsp_cs" + class "scsi" module "nsp_cs" + + card "WorkBit NinjaSCSI-3" + version "WBT", "NinjaSCSI-3", "R1.0" + bind "nsp_cs" + + card "WorkBit NinjaSCSI-32Bi (16bit)" + version "WORKBIT", "UltraNinja-16", "1" + bind "nsp_cs" + + # OEM + card "WorkBit NinjaSCSI-32Bi (16bit) / IO-DATA" + version "IO DATA", "CBSC16 ", "1" + bind "nsp_cs" + + # OEM + card "WorkBit NinjaSCSI-32Bi (16bit) / KME-1" + version "KME ", "SCSI-CARD-001", "1" + bind "nsp_cs" + card "WorkBit NinjaSCSI-32Bi (16bit) / KME-2" + version "KME ", "SCSI-CARD-002", "1" + bind "nsp_cs" + card "WorkBit NinjaSCSI-32Bi (16bit) / KME-3" + version "KME ", "SCSI-CARD-003", "1" + bind "nsp_cs" + card "WorkBit NinjaSCSI-32Bi (16bit) / KME-4" + version "KME ", "SCSI-CARD-004", "1" + bind "nsp_cs" + +(f) Start (or restart) pcmcia-cs:: + + # /etc/rc.d/rc.pcmcia start (BSD style) + + or:: + + # /etc/init.d/pcmcia start (SYSV style) + + +4. History +========== + +See README.nin_cs . + +5. Caution +========== + +If you eject card when doing some operation for your SCSI device or suspend +your computer, you encount some *BAD* error like disk crash. + +It works good when I using this driver right way. But I'm not guarantee +your data. Please backup your data when you use this driver. + +6. Known Bugs +============= + +In 2.4 kernel, you can't use 640MB Optical disk. This error comes from +high level SCSI driver. + +7. Testing +========== + +Please send me some reports(bug reports etc..) of this software. +When you send report, please tell me these or more. + + - card name + - kernel version + - your SCSI device name(hard drive, CD-ROM, etc...) + +8. Copyright +============ + + See GPL. + + +2001/08/08 yokota@netlab.is.tsukuba.ac.jp <YOKOTA Hiroshi> diff --git a/Documentation/scsi/NinjaSCSI.txt b/Documentation/scsi/NinjaSCSI.txt deleted file mode 100644 index ac8db8ceec77..000000000000 --- a/Documentation/scsi/NinjaSCSI.txt +++ /dev/null @@ -1,128 +0,0 @@ - - WorkBiT NinjaSCSI-3/32Bi driver for Linux - -1. Comment - This is Workbit corp.'s(http://www.workbit.co.jp/) NinjaSCSI-3 -for Linux. - -2. My Linux environment -Linux kernel: 2.4.7 / 2.2.19 -pcmcia-cs: 3.1.27 -gcc: gcc-2.95.4 -PC card: I-O data PCSC-F (NinjaSCSI-3) - I-O data CBSC-II in 16 bit mode (NinjaSCSI-32Bi) -SCSI device: I-O data CDPS-PX24 (CD-ROM drive) - Media Intelligent MMO-640GT (Optical disk drive) - -3. Install -[1] Check your PC card is true "NinjaSCSI-3" card. - If you installed pcmcia-cs already, pcmcia reports your card as UNKNOWN - card, and write ["WBT", "NinjaSCSI-3", "R1.0"] or some other string to - your console or log file. - You can also use "cardctl" program (this program is in pcmcia-cs source - code) to get more info. - -# cat /var/log/messages -... -Jan 2 03:45:06 lindberg cardmgr[78]: unsupported card in socket 1 -Jan 2 03:45:06 lindberg cardmgr[78]: product info: "WBT", "NinjaSCSI-3", "R1.0" -... -# cardctl ident -Socket 0: - no product info available -Socket 1: - product info: "IO DATA", "CBSC16 ", "1" - - -[2] Get the Linux kernel source, and extract it to /usr/src. - Because the NinjaSCSI driver requires some SCSI header files in Linux - kernel source, I recommend rebuilding your kernel; this eliminates - some versioning problems. -$ cd /usr/src -$ tar -zxvf linux-x.x.x.tar.gz -$ cd linux -$ make config -... - -[3] If you use this driver with Kernel 2.2, unpack pcmcia-cs in some directory - and make & install. This driver requires the pcmcia-cs header file. -$ cd /usr/src -$ tar zxvf cs-pcmcia-cs-3.x.x.tar.gz -... - -[4] Extract this driver's archive somewhere, and edit Makefile, then do make. -$ tar -zxvf nsp_cs-x.x.tar.gz -$ cd nsp_cs-x.x -$ emacs Makefile -... -$ make - -[5] Copy nsp_cs.ko to suitable place, like /lib/modules/<Kernel version>/pcmcia/ . - -[6] Add these lines to /etc/pcmcia/config . - If you use pcmcia-cs-3.1.8 or later, we can use "nsp_cs.conf" file. - So, you don't need to edit file. Just copy to /etc/pcmcia/ . - -------------------------------------- -device "nsp_cs" - class "scsi" module "nsp_cs" - -card "WorkBit NinjaSCSI-3" - version "WBT", "NinjaSCSI-3", "R1.0" - bind "nsp_cs" - -card "WorkBit NinjaSCSI-32Bi (16bit)" - version "WORKBIT", "UltraNinja-16", "1" - bind "nsp_cs" - -# OEM -card "WorkBit NinjaSCSI-32Bi (16bit) / IO-DATA" - version "IO DATA", "CBSC16 ", "1" - bind "nsp_cs" - -# OEM -card "WorkBit NinjaSCSI-32Bi (16bit) / KME-1" - version "KME ", "SCSI-CARD-001", "1" - bind "nsp_cs" -card "WorkBit NinjaSCSI-32Bi (16bit) / KME-2" - version "KME ", "SCSI-CARD-002", "1" - bind "nsp_cs" -card "WorkBit NinjaSCSI-32Bi (16bit) / KME-3" - version "KME ", "SCSI-CARD-003", "1" - bind "nsp_cs" -card "WorkBit NinjaSCSI-32Bi (16bit) / KME-4" - version "KME ", "SCSI-CARD-004", "1" - bind "nsp_cs" -------------------------------------- - -[7] Start (or restart) pcmcia-cs. -# /etc/rc.d/rc.pcmcia start (BSD style) -or -# /etc/init.d/pcmcia start (SYSV style) - - -4. History -See README.nin_cs . - -5. Caution - If you eject card when doing some operation for your SCSI device or suspend -your computer, you encount some *BAD* error like disk crash. - It works good when I using this driver right way. But I'm not guarantee -your data. Please backup your data when you use this driver. - -6. Known Bugs - In 2.4 kernel, you can't use 640MB Optical disk. This error comes from -high level SCSI driver. - -7. Testing - Please send me some reports(bug reports etc..) of this software. -When you send report, please tell me these or more. - card name - kernel version - your SCSI device name(hard drive, CD-ROM, etc...) - -8. Copyright - See GPL. - - -2001/08/08 yokota@netlab.is.tsukuba.ac.jp <YOKOTA Hiroshi> diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.rst index 30f643f611b2..1904674b94f3 100644 --- a/Documentation/scsi/aacraid.txt +++ b/Documentation/scsi/aacraid.rst @@ -1,7 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================================== AACRAID Driver for Linux (take two) +=================================== Introduction -------------------------- +============ The aacraid driver adds support for Adaptec (http://www.adaptec.com) RAID controllers. This is a major rewrite from the original Adaptec supplied driver. It has significantly cleaned up both the code @@ -9,8 +13,11 @@ and the running binary size (the module is less than half the size of the original). Supported Cards/Chipsets -------------------------- +======================== + + =================== ======= ======================================= PCI ID (pci.ids) OEM Product + =================== ======= ======================================= 9005:0285:9005:0285 Adaptec 2200S (Vulcan) 9005:0285:9005:0286 Adaptec 2120S (Crusader) 9005:0285:9005:0287 Adaptec 2200S (Vulcan-2m) @@ -117,34 +124,54 @@ Supported Cards/Chipsets 9005:0285:108e:0286 SUN STK RAID INT (Cougar) 9005:0285:108e:0287 SUN STK RAID EXT (Prometheus) 9005:0285:108e:7aae SUN STK RAID EM (Narvi) + =================== ======= ======================================= People -------------------------- +====== + Alan Cox <alan@lxorguk.ukuu.org.uk> -Christoph Hellwig <hch@infradead.org> (updates for new-style PCI probing and SCSI host registration, - small cleanups/fixes) -Matt Domsch <matt_domsch@dell.com> (revision ioctl, adapter messages) -Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers - added new ioctls, changed scsi interface to use new error handler, - increased the number of fibs and outstanding commands to a container) - - (fixed 64bit and 64G memory model, changed confusing naming convention - where fibs that go to the hardware are consistently called hw_fibs and - not just fibs like the name of the driver tracking structure) -Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations. + +Christoph Hellwig <hch@infradead.org> + +- updates for new-style PCI probing and SCSI host registration, + small cleanups/fixes + +Matt Domsch <matt_domsch@dell.com> + +- revision ioctl, adapter messages + +Deanna Bonds + +- non-DASD support, PAE fibs and 64 bit, added new adaptec controllers + added new ioctls, changed scsi interface to use new error handler, + increased the number of fibs and outstanding commands to a container +- fixed 64bit and 64G memory model, changed confusing naming convention + where fibs that go to the hardware are consistently called hw_fibs and + not just fibs like the name of the driver tracking structure + +Mark Salyzyn <Mark_Salyzyn@adaptec.com> + +- Fixed panic issues and added some new product ids for upcoming hbas. +- Performance tuning, card failover and bug mitigations. + Achim Leubner <Achim_Leubner@adaptec.com> -Original Driver +- Original Driver + ------------------------- + Adaptec Unix OEM Product Group Mailing List -------------------------- +============ + linux-scsi@vger.kernel.org (Interested parties troll here) Also note this is very different to Brian's original driver so don't expect him to support it. + Adaptec does support this driver. Contact Adaptec tech support or aacraid@adaptec.com Original by Brian Boerner February 2001 + Rewritten by Alan Cox, November 2001 diff --git a/Documentation/scsi/advansys.txt b/Documentation/scsi/advansys.rst index 4a3db62b7424..e0367e179696 100644 --- a/Documentation/scsi/advansys.txt +++ b/Documentation/scsi/advansys.rst @@ -1,3 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===================== +AdvanSys Driver Notes +===================== + AdvanSys (Advanced System Products, Inc.) manufactures the following RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow (8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI @@ -12,50 +18,51 @@ adapter detected. The number of CDBs used by the driver can be lowered in the BIOS by changing the 'Host Queue Size' adapter setting. Laptop Products: - ABP-480 - Bus-Master CardBus (16 CDB) + - ABP-480 - Bus-Master CardBus (16 CDB) Connectivity Products: - ABP510/5150 - Bus-Master ISA (240 CDB) - ABP5140 - Bus-Master ISA PnP (16 CDB) - ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) - ABP902/3902 - Bus-Master PCI (16 CDB) - ABP3905 - Bus-Master PCI (16 CDB) - ABP915 - Bus-Master PCI (16 CDB) - ABP920 - Bus-Master PCI (16 CDB) - ABP3922 - Bus-Master PCI (16 CDB) - ABP3925 - Bus-Master PCI (16 CDB) - ABP930 - Bus-Master PCI (16 CDB) - ABP930U - Bus-Master PCI Ultra (16 CDB) - ABP930UA - Bus-Master PCI Ultra (16 CDB) - ABP960 - Bus-Master PCI MAC/PC (16 CDB) - ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) + - ABP510/5150 - Bus-Master ISA (240 CDB) + - ABP5140 - Bus-Master ISA PnP (16 CDB) + - ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) + - ABP902/3902 - Bus-Master PCI (16 CDB) + - ABP3905 - Bus-Master PCI (16 CDB) + - ABP915 - Bus-Master PCI (16 CDB) + - ABP920 - Bus-Master PCI (16 CDB) + - ABP3922 - Bus-Master PCI (16 CDB) + - ABP3925 - Bus-Master PCI (16 CDB) + - ABP930 - Bus-Master PCI (16 CDB) + - ABP930U - Bus-Master PCI Ultra (16 CDB) + - ABP930UA - Bus-Master PCI Ultra (16 CDB) + - ABP960 - Bus-Master PCI MAC/PC (16 CDB) + - ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) Single Channel Products: - ABP542 - Bus-Master ISA with floppy (240 CDB) - ABP742 - Bus-Master EISA (240 CDB) - ABP842 - Bus-Master VL (240 CDB) - ABP940 - Bus-Master PCI (240 CDB) - ABP940U - Bus-Master PCI Ultra (240 CDB) - ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB) - ABP970 - Bus-Master PCI MAC/PC (240 CDB) - ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) - ABP3960UA - Bus-Master PCI MAC/PC Ultra (240 CDB) - ABP940UW/3940UW - Bus-Master PCI Ultra-Wide (253 CDB) - ABP970UW - Bus-Master PCI MAC/PC Ultra-Wide (253 CDB) - ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB) + - ABP542 - Bus-Master ISA with floppy (240 CDB) + - ABP742 - Bus-Master EISA (240 CDB) + - ABP842 - Bus-Master VL (240 CDB) + - ABP940 - Bus-Master PCI (240 CDB) + - ABP940U - Bus-Master PCI Ultra (240 CDB) + - ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB) + - ABP970 - Bus-Master PCI MAC/PC (240 CDB) + - ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) + - ABP3960UA - Bus-Master PCI MAC/PC Ultra (240 CDB) + - ABP940UW/3940UW - Bus-Master PCI Ultra-Wide (253 CDB) + - ABP970UW - Bus-Master PCI MAC/PC Ultra-Wide (253 CDB) + - ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB) Multi-Channel Products: - ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel) - ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel) - ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) - ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB Per Channel) - ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel) - ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel) - ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.) - ABP3950U2W - Bus-Master PCI LVD/Ultra2-Wide and Ultra-Wide (253 CDB) - ABP3950U3W - Bus-Master PCI Dual LVD2/Ultra3-Wide (253 CDB) + - ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel) + - ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel) + - ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) + - ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB Per Channel) + - ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel) + - ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel) + - ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.) + - ABP3950U2W - Bus-Master PCI LVD/Ultra2-Wide and Ultra-Wide (253 CDB) + - ABP3950U3W - Bus-Master PCI Dual LVD2/Ultra3-Wide (253 CDB) Driver Compile Time Options and Debugging +========================================= The following constants can be defined in the source file. @@ -88,26 +95,30 @@ The following constants can be defined in the source file. first three hex digits of the pseudo I/O Port must be set to 'deb' and the fourth hex digit specifies the debug level: 0 - F. The following command line will look for an adapter at 0x330 - and set the debug level to 2. + and set the debug level to 2:: linux advansys=0x330,0,0,0,0xdeb2 If the driver is built as a loadable module this variable can be defined when the driver is loaded. The following insmod command - will set the debug level to one. + will set the debug level to one:: insmod advansys.o asc_dbglvl=1 Debugging Message Levels: - 0: Errors Only - 1: High-Level Tracing - 2-N: Verbose Tracing + + + ==== ================== + 0 Errors Only + 1 High-Level Tracing + 2-N Verbose Tracing + ==== ================== To enable debug output to console, please make sure that: a. System and kernel logging is enabled (syslogd, klogd running). b. Kernel messages are routed to console output. Check - /etc/syslog.conf for an entry similar to this: + /etc/syslog.conf for an entry similar to this:: kern.* /dev/console @@ -120,8 +131,11 @@ The following constants can be defined in the source file. Alternatively you can enable printk() to console with this program. However, this is not the 'official' way to do this. + Debug output is logged in /var/log/messages. + :: + main() { syscall(103, 7, 0, 0); @@ -144,11 +158,11 @@ The following constants can be defined in the source file. Statistics are only available for kernels greater than or equal to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured. - AdvanSys SCSI adapter files have the following path name format: + AdvanSys SCSI adapter files have the following path name format:: /proc/scsi/advansys/{0,1,2,3,...} - This information can be displayed with cat. For example: + This information can be displayed with cat. For example:: cat /proc/scsi/advansys/0 @@ -156,6 +170,7 @@ The following constants can be defined in the source file. contain adapter and device configuration information. Driver LILO Option +================== If init/main.c is modified as described in the 'Directions for Adding the AdvanSys Driver to Linux' section (B.4.) above, the driver will @@ -167,17 +182,30 @@ affects searching for ISA and VL boards. Examples: 1. Eliminate I/O port scanning: - boot: linux advansys= - or - boot: linux advansys=0x0 + + boot:: + + linux advansys= + + or:: + + boot: linux advansys=0x0 + 2. Limit I/O port scanning to one I/O port: - boot: linux advansys=0x110 + + boot:: + + linux advansys=0x110 + 3. Limit I/O port scanning to four I/O ports: - boot: linux advansys=0x110,0x210,0x230,0x330 + + boot:: + + linux advansys=0x110,0x210,0x230,0x330 For a loadable module the same effect can be achieved by setting the 'asc_iopflag' variable and 'asc_ioport' array when loading -the driver, e.g. +the driver, e.g.:: insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330 @@ -187,6 +215,7 @@ the 'Driver Compile Time Options and Debugging' section above for more information. Credits (Chronological Order) +============================= Bob Frey <bfrey@turbolinux.com.cn> wrote the AdvanSys SCSI driver and maintained it up to 3.3F. He continues to answer questions diff --git a/Documentation/scsi/aha152x.txt b/Documentation/scsi/aha152x.rst index 94848734ac66..7012b5c46d5d 100644 --- a/Documentation/scsi/aha152x.txt +++ b/Documentation/scsi/aha152x.rst @@ -1,7 +1,12 @@ -$Id: README.aha152x,v 1.2 1999/12/25 15:32:30 fischer Exp fischer $ +.. SPDX-License-Identifier: GPL-2.0 +.. include:: <isonum.txt> + +===================================================== Adaptec AHA-1520/1522 SCSI driver for Linux (aha152x) +===================================================== + +Copyright |copy| 1993-1999 Jürgen Fischer <fischer@norbit.de> -Copyright 1993-1999 Jürgen Fischer <fischer@norbit.de> TC1550 patches by Luuk van Dijk (ldz@xs4all.nl) @@ -14,8 +19,10 @@ less polling loops), has slightly higher throughput (at least on my ancient test box; a i486/33Mhz/20MB). -CONFIGURATION ARGUMENTS: +Configuration Arguments +======================= +============ ======================================== ====================== IOPORT base io address (0x340/0x140) IRQ interrupt level (9-12; default 11) SCSI_ID scsi id of controller (0-7; default 7) @@ -25,31 +32,38 @@ SYNCHRONOUS enable synchronous transfers (0/1; default 1 [on]) DELAY: bus reset delay (default 100) EXT_TRANS: enable extended translation (0/1: default 0 [off]) (see NOTES) +============ ======================================== ====================== + +Compile Time Configuration +========================== + +(go into AHA152X in drivers/scsi/Makefile): -COMPILE TIME CONFIGURATION (go into AHA152X in drivers/scsi/Makefile): +- DAUTOCONF + use configuration the controller reports (AHA-152x only) --DAUTOCONF - use configuration the controller reports (AHA-152x only) +- DSKIP_BIOSTEST + Don't test for BIOS signature (AHA-1510 or disabled BIOS) --DSKIP_BIOSTEST - Don't test for BIOS signature (AHA-1510 or disabled BIOS) +- DSETUP0="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }" + override for the first controller --DSETUP0="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }" - override for the first controller +- DSETUP1="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }" + override for the second controller --DSETUP1="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }" - override for the second controller +- DAHA152X_DEBUG + enable debugging output --DAHA152X_DEBUG - enable debugging output +- DAHA152X_STAT + enable some statistics --DAHA152X_STAT - enable some statistics +LILO Command Line Options +========================= -LILO COMMAND LINE OPTIONS: + :: -aha152x=<IOPORT>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY> [,<EXT_TRANS]]]]]]] + aha152x=<IOPORT>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY> [,<EXT_TRANS]]]]]]] The normal configuration can be overridden by specifying a command line. When you do this, the BIOS test is skipped. Entered values have to be @@ -58,17 +72,21 @@ aha152x=<IOPORT>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY For two controllers use the aha152x statement twice. -SYMBOLS FOR MODULE CONFIGURATION: +Symbols for Module Configuration +================================ Choose from 2 alternatives: -1. specify everything (old) +1. specify everything (old):: + + aha152x=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS -aha152x=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS configuration override for first controller + :: + + aha152x1=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS -aha152x1=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS configuration override for second controller 2. specify only what you need to (irq or io is required; new) @@ -101,7 +119,8 @@ exttrans=EXTTRANS0[,EXTTRANS1] If you use both alternatives the first will be taken. -NOTES ON EXT_TRANS: +Notes on EXT_TRANS +================== SCSI uses block numbers to address blocks/sectors on a device. The BIOS uses a cylinder/head/sector addressing scheme (C/H/S) @@ -150,8 +169,9 @@ geometry right in most cases: - for disks<1GB: use default translation (C/32/64) - for disks>1GB: + - take current geometry from the partition table - (using scsicam_bios_param and accept only `valid' geometries, + (using scsicam_bios_param and accept only 'valid' geometries, ie. either (C/32/64) or (C/63/255)). This can be extended translation even if it's not enabled in the driver. @@ -161,7 +181,8 @@ geometry right in most cases: disks. -REFERENCES USED: +References Used +=============== "AIC-6260 SCSI Chip Specification", Adaptec Corporation. @@ -177,7 +198,7 @@ REFERENCES USED: Drew Eckhardt (drew@cs.colorado.edu) - Eric Youngdale (eric@andante.org) + Eric Youngdale (eric@andante.org) special thanks to Eric Youngdale for the free(!) supplying the documentation on the chip. diff --git a/Documentation/scsi/aic79xx.rst b/Documentation/scsi/aic79xx.rst new file mode 100644 index 000000000000..071ff5111a4f --- /dev/null +++ b/Documentation/scsi/aic79xx.rst @@ -0,0 +1,593 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. include:: <isonum.txt> + +=================================== +Adaptec Ultra320 Family Manager Set +=================================== + +README for The Linux Operating System + +.. The following information is available in this file: + + 1. Supported Hardware + 2. Version History + 3. Command Line Options + 4. Additional Notes + 5. Contacting Adaptec + + +1. Supported Hardware +===================== + + The following Adaptec SCSI Host Adapters are supported by this + driver set. + + ============= ========================================= + Ultra320 ASIC Description + ============= ========================================= + AIC-7901A Single Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC + AIC-7901B Single Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC with Retained Training + AIC-7902A4 Dual Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC + AIC-7902B Dual Channel 64-bit PCI-X 133MHz to + Ultra320 SCSI ASIC with Retained Training + ============= ========================================= + + ========================== ===================================== ============ + Ultra320 Adapters Description ASIC + ========================== ===================================== ============ + Adaptec SCSI Card 39320 Dual Channel 64-bit PCI-X 133MHz to 7902A4/7902B + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin) + Adaptec SCSI Card 39320A Dual Channel 64-bit PCI-X 133MHz to 7902B + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin) + Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to 7902A4 + Ultra320 SCSI Card (two external VHDC + and one internal 68-pin) + Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to 7902A4 + Ultra320 SCSI Card (two external VHDC + and one internal 68-pin) based on the + AIC-7902B ASIC + Adaptec SCSI Card 29320 Single Channel 64-bit PCI-X 133MHz to 7901A + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin, one + internal 50-pin) + Adaptec SCSI Card 29320A Single Channel 64-bit PCI-X 133MHz to 7901B + Ultra320 SCSI Card (one external + 68-pin, two internal 68-pin, one + internal 50-pin) + Adaptec SCSI Card 29320LP Single Channel 64-bit Low Profile 7901A + PCI-X 133MHz to Ultra320 SCSI Card + (One external VHDC, one internal + 68-pin) + Adaptec SCSI Card 29320ALP Single Channel 64-bit Low Profile 7901B + PCI-X 133MHz to Ultra320 SCSI Card + (One external VHDC, one internal + 68-pin) + ========================== ===================================== ============ + +2. Version History +================== + + + * 3.0 (December 1st, 2005) + - Updated driver to use SCSI transport class infrastructure + - Upported sequencer and core fixes from adaptec released + version 2.0.15 of the driver. + + * 1.3.11 (July 11, 2003) + - Fix several deadlock issues. + - Add 29320ALP and 39320B Id's. + + * 1.3.10 (June 3rd, 2003) + - Align the SCB_TAG field on a 16byte boundary. This avoids + SCB corruption on some PCI-33 busses. + - Correct non-zero luns on Rev B. hardware. + - Update for change in 2.5.X SCSI proc FS interface. + - When negotiation async via an 8bit WDTR message, send + an SDTR with an offset of 0 to be sure the target + knows we are async. This works around a firmware defect + in the Quantum Atlas 10K. + - Implement controller suspend and resume. + - Clear PCI error state during driver attach so that we + don't disable memory mapped I/O due to a stray write + by some other driver probe that occurred before we + claimed the controller. + + * 1.3.9 (May 22nd, 2003) + - Fix compiler errors. + - Remove S/G splitting for segments that cross a 4GB boundary. + This is guaranteed not to happen in Linux. + - Add support for scsi_report_device_reset() found in + 2.5.X kernels. + - Add 7901B support. + - Simplify handling of the packetized lun Rev A workaround. + - Correct and simplify handling of the ignore wide residue + message. The previous code would fail to report a residual + if the transaction data length was even and we received + an IWR message. + + * 1.3.8 (April 29th, 2003) + - Fix types accessed via the command line interface code. + - Perform a few firmware optimizations. + - Fix "Unexpected PKT busfree" errors. + - Use a sequencer interrupt to notify the host of + commands with bad status. We defer the notification + until there are no outstanding selections to ensure + that the host is interrupted for as short a time as + possible. + - Remove pre-2.2.X support. + - Add support for new 2.5.X interrupt API. + - Correct big-endian architecture support. + + * 1.3.7 (April 16th, 2003) + - Use del_timer_sync() to ensure that no timeouts + are pending during controller shutdown. + - For pre-2.5.X kernels, carefully adjust our segment + list size to avoid SCSI malloc pool fragmentation. + - Cleanup channel display in our /proc output. + - Workaround duplicate device entries in the mid-layer + device list during add-single-device. + + * 1.3.6 (March 28th, 2003) + - Correct a double free in the Domain Validation code. + - Correct a reference to free'ed memory during controller + shutdown. + - Reset the bus on an SE->LVD change. This is required + to reset our transceivers. + + * 1.3.5 (March 24th, 2003) + - Fix a few register window mode bugs. + - Include read streaming in the PPR flags we display in + diagnostics as well as /proc. + - Add PCI hot plug support for 2.5.X kernels. + - Correct default precompensation value for RevA hardware. + - Fix Domain Validation thread shutdown. + - Add a firmware workaround to make the LED blink + brighter during packetized operations on the H2A4. + - Correct /proc display of user read streaming settings. + - Simplify driver locking by releasing the io_request_lock + upon driver entry from the mid-layer. + - Cleanup command line parsing and move much of this code + to aiclib. + + * 1.3.4 (February 28th, 2003) + - Correct a race condition in our error recovery handler. + - Allow Test Unit Ready commands to take a full 5 seconds + during Domain Validation. + + * 1.3.2 (February 19th, 2003) + - Correct a Rev B. regression due to the GEM318 + compatibility fix included in 1.3.1. + + * 1.3.1 (February 11th, 2003) + - Add support for the 39320A. + - Improve recovery for certain PCI-X errors. + - Fix handling of LQ/DATA/LQ/DATA for the + same write transaction that can occur without + interveining training. + - Correct compatibility issues with the GEM318 + enclosure services device. + - Correct data corruption issue that occurred under + high tag depth write loads. + - Adapt to a change in the 2.5.X daemonize() API. + - Correct a "Missing case in ahd_handle_scsiint" panic. + + * 1.3.0 (January 21st, 2003) + - Full regression testing for all U320 products completed. + - Added abort and target/lun reset error recovery handler and + interrupt coalescing. + + * 1.2.0 (November 14th, 2002) + - Added support for Domain Validation + - Add support for the Hewlett-Packard version of the 39320D + and AIC-7902 adapters. + + Support for previous adapters has not been fully tested and should + only be used at the customer's own risk. + + * 1.1.1 (September 24th, 2002) + - Added support for the Linux 2.5.X kernel series + + * 1.1.0 (September 17th, 2002) + - Added support for four additional SCSI products: + ASC-39320, ASC-29320, ASC-29320LP, AIC-7901. + + * 1.0.0 (May 30th, 2002) + - Initial driver release. + + * 2.1. Software/Hardware Features + - Support for the SPI-4 "Ultra320" standard: + - 320MB/s transfer rates + - Packetized SCSI Protocol at 160MB/s and 320MB/s + - Quick Arbitration Selection (QAS) + - Retained Training Information (Rev B. ASIC only) + - Interrupt Coalescing + - Initiator Mode (target mode not currently + supported) + - Support for the PCI-X standard up to 133MHz + - Support for the PCI v2.2 standard + - Domain Validation + + * 2.2. Operating System Support: + - Redhat Linux 7.2, 7.3, 8.0, Advanced Server 2.1 + - SuSE Linux 7.3, 8.0, 8.1, Enterprise Server 7 + - only Intel and AMD x86 supported at this time + - >4GB memory configurations supported. + + Refer to the User's Guide for more details on this. + +3. Command Line Options +======================= + + .. Warning:: + + ALTERING OR ADDING THESE DRIVER PARAMETERS + INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. + USE THEM WITH CAUTION. + + Put a .conf file in the /etc/modprobe.d/ directory and add/edit a + line containing ``options aic79xx aic79xx=[command[,command...]]`` where + ``command`` is one or more of the following: + + +verbose + :Definition: enable additional informative messages during driver operation. + :Possible Values: This option is a flag + :Default Value: disabled + +debug:[value] + :Definition: Enables various levels of debugging information + The bit definitions for the debugging mask can + be found in drivers/scsi/aic7xxx/aic79xx.h under + the "Debug" heading. + :Possible Values: 0x0000 = no debugging, 0xffff = full debugging + :Default Value: 0x0000 + +no_reset + :Definition: Do not reset the bus during the initial probe + phase + :Possible Values: This option is a flag + :Default Value: disabled + +extended + :Definition: Force extended translation on the controller + :Possible Values: This option is a flag + :Default Value: disabled + +periodic_otag + :Definition: Send an ordered tag periodically to prevent + tag starvation. Needed for some older devices + :Possible Values: This option is a flag + :Default Value: disabled + +reverse_scan + :Definition: Probe the scsi bus in reverse order, starting with target 15 + :Possible Values: This option is a flag + :Default Value: disabled + +global_tag_depth + :Definition: Global tag depth for all targets on all busses. + This option sets the default tag depth which + may be selectively overridden vi the tag_info + option. + + :Possible Values: 1 - 253 + :Default Value: 32 + +tag_info:{{value[,value...]}[,{value[,value...]}...]} + :Definition: Set the per-target tagged queue depth on a + per controller basis. Both controllers and targets + may be omitted indicating that they should retain + the default tag depth. + + :Possible Values: 1 - 253 + :Default Value: 32 + + Examples: + + + :: + + tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32} + + On Controller 0 + + - specifies a tag depth of 16 for target 0 + - specifies a tag depth of 64 for target 3 + - specifies a tag depth of 8 for targets 4 and 5 + - leaves target 6 at the default + - specifies a tag depth of 32 for targets 1,2,7-15 + + All other targets retain the default depth. + + :: + + tag_info:{{},{32,,32}} + + On Controller 1 + + - specifies a tag depth of 32 for targets 0 and 2 + + All other targets retain the default depth. + + +rd_strm: {rd_strm_bitmask[,rd_strm_bitmask...]} + :Definition: Enable read streaming on a per target basis. + The rd_strm_bitmask is a 16 bit hex value in which + each bit represents a target. Setting the target's + bit to '1' enables read streaming for that + target. Controllers may be omitted indicating that + they should retain the default read streaming setting. + + Examples: + + :: + + rd_strm:{0x0041} + + On Controller 0 + + - enables read streaming for targets 0 and 6. + - disables read streaming for targets 1-5,7-15. + + All other targets retain the default read + streaming setting. + + :: + + rd_strm:{0x0023,,0xFFFF} + + On Controller 0 + + - enables read streaming for targets 1,2, and 5. + - disables read streaming for targets 3,4,6-15. + + On Controller 2 + + - enables read streaming for all targets. + + All other targets retain the default read + streaming setting. + + :Possible Values: 0x0000 - 0xffff + :Default Value: 0x0000 + +dv: {value[,value...]} + :Definition: Set Domain Validation Policy on a per-controller basis. + Controllers may be omitted indicating that + they should retain the default read streaming setting. + + :Possible Values: + + ==== =============================== + < 0 Use setting from serial EEPROM. + 0 Disable DV + > 0 Enable DV + ==== =============================== + + :Default Value: DV Serial EEPROM configuration setting. + + Example: + + :: + + dv:{-1,0,,1,1,0} + + - On Controller 0 leave DV at its default setting. + - On Controller 1 disable DV. + - Skip configuration on Controller 2. + - On Controllers 3 and 4 enable DV. + - On Controller 5 disable DV. + +seltime:[value] + :Definition: Specifies the selection timeout value + :Possible Values: 0 = 256ms, 1 = 128ms, 2 = 64ms, 3 = 32ms + :Default Value: 0 + +.. Warning: + + The following three options should only be changed at + the direction of a technical support representative. + + +precomp: {value[,value...]} + :Definition: Set IO Cell precompensation value on a per-controller basis. + Controllers may be omitted indicating that + they should retain the default precompensation setting. + + :Possible Values: 0 - 7 + :Default Value: Varies based on chip revision + + Examples: + + :: + + precomp:{0x1} + + On Controller 0 set precompensation to 1. + + :: + + precomp:{1,,7} + + - On Controller 0 set precompensation to 1. + - On Controller 2 set precompensation to 8. + +slewrate: {value[,value...]} + :Definition: Set IO Cell slew rate on a per-controller basis. + Controllers may be omitted indicating that + they should retain the default slew rate setting. + + :Possible Values: 0 - 15 + :Default Value: Varies based on chip revision + + Examples: + + :: + + slewrate:{0x1} + + - On Controller 0 set slew rate to 1. + + :: + + slewrate :{1,,8} + + - On Controller 0 set slew rate to 1. + - On Controller 2 set slew rate to 8. + +amplitude: {value[,value...]} + :Definition: Set IO Cell signal amplitude on a per-controller basis. + Controllers may be omitted indicating that + they should retain the default read streaming setting. + + :Possible Values: 1 - 7 + :Default Value: Varies based on chip revision + + Examples: + + :: + + amplitude:{0x1} + + On Controller 0 set amplitude to 1. + + :: + + amplitude :{1,,7} + + - On Controller 0 set amplitude to 1. + - On Controller 2 set amplitude to 7. + +Example:: + + options aic79xx aic79xx=verbose,rd_strm:{{0x0041}} + +enables verbose output in the driver and turns read streaming on +for targets 0 and 6 of Controller 0. + +4. Additional Notes +=================== + +4.1. Known/Unresolved or FYI Issues +----------------------------------- + + * Under SuSE Linux Enterprise 7, the driver may fail to operate + correctly due to a problem with PCI interrupt routing in the + Linux kernel. Please contact SuSE for an updated Linux + kernel. + +4.2. Third-Party Compatibility Issues +------------------------------------- + + * Adaptec only supports Ultra320 hard drives running + the latest firmware available. Please check with + your hard drive manufacturer to ensure you have the + latest version. + +4.3. Operating System or Technology Limitations +----------------------------------------------- + + * PCI Hot Plug is untested and may cause the operating system + to stop responding. + * Luns that are not numbered contiguously starting with 0 might not + be automatically probed during system startup. This is a limitation + of the OS. Please contact your Linux vendor for instructions on + manually probing non-contiguous luns. + * Using the Driver Update Disk version of this package during OS + installation under RedHat might result in two versions of this + driver being installed into the system module directory. This + might cause problems with the /sbin/mkinitrd program and/or + other RPM packages that try to install system modules. The best + way to correct this once the system is running is to install + the latest RPM package version of this driver, available from + http://www.adaptec.com. + + +5. Adaptec Customer Support +=========================== + + A Technical Support Identification (TSID) Number is required for + Adaptec technical support. + + - The 12-digit TSID can be found on the white barcode-type label + included inside the box with your product. The TSID helps us + provide more efficient service by accurately identifying your + product and support status. + + Support Options + - Search the Adaptec Support Knowledgebase (ASK) at + http://ask.adaptec.com for articles, troubleshooting tips, and + frequently asked questions about your product. + - For support via Email, submit your question to Adaptec's + Technical Support Specialists at http://ask.adaptec.com/. + + North America + - Visit our Web site at http://www.adaptec.com/. + - For information about Adaptec's support options, call + 408-957-2550, 24 hours a day, 7 days a week. + - To speak with a Technical Support Specialist, + + * For hardware products, call 408-934-7274, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + * For RAID and Fibre Channel products, call 321-207-2000, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + + To expedite your service, have your computer with you. + - To order Adaptec products, including accessories and cables, + call 408-957-7274. To order cables online go to + http://www.adaptec.com/buy-cables/. + + Europe + - Visit our Web site at http://www.adaptec.com/en-US/_common/world_index. + - To speak with a Technical Support Specialist, call, or email, + + * German: +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET, + http://ask-de.adaptec.com/. + * French: +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET, + http://ask-fr.adaptec.com/. + * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT, + http://ask.adaptec.com/. + + - You can order Adaptec cables online at + http://www.adaptec.com/buy-cables/. + + Japan + - Visit our web site at http://www.adaptec.co.jp/. + - To speak with a Technical Support Specialist, call + +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m., + 1:00 p.m. to 6:00 p.m. + +Copyright |copy| 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA. +All rights reserved. + +You are permitted to redistribute, use and modify this README file in whole +or in part in conjunction with redistribution of software governed by the +General Public License, provided that the following conditions are met: + +1. Redistributions of README file must retain the above copyright + notice, this list of conditions, and the following disclaimer, + without modification. +2. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. +3. Modifications or new contributions must be attributed in a copyright + notice identifying the author ("Contributor") and added below the + original copyright notice. The copyright notice is for purposes of + identifying contributors and should not be deemed as permission to alter + the permissions given by Adaptec. + +THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS`` AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY +WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README +FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt deleted file mode 100644 index e2d3273000d4..000000000000 --- a/Documentation/scsi/aic79xx.txt +++ /dev/null @@ -1,497 +0,0 @@ -==================================================================== -= Adaptec Ultra320 Family Manager Set = -= = -= README for = -= The Linux Operating System = -==================================================================== - -The following information is available in this file: - - 1. Supported Hardware - 2. Version History - 3. Command Line Options - 4. Additional Notes - 5. Contacting Adaptec - - -1. Supported Hardware - - The following Adaptec SCSI Host Adapters are supported by this - driver set. - - Ultra320 ASIC Description - ---------------------------------------------------------------- - AIC-7901A Single Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC - AIC-7901B Single Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC with Retained Training - AIC-7902A4 Dual Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC - AIC-7902B Dual Channel 64-bit PCI-X 133MHz to - Ultra320 SCSI ASIC with Retained Training - - Ultra320 Adapters Description ASIC - -------------------------------------------------------------------------- - Adaptec SCSI Card 39320 Dual Channel 64-bit PCI-X 133MHz to 7902A4/7902B - Ultra320 SCSI Card (one external - 68-pin, two internal 68-pin) - Adaptec SCSI Card 39320A Dual Channel 64-bit PCI-X 133MHz to 7902B - Ultra320 SCSI Card (one external - 68-pin, two internal 68-pin) - Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to 7902A4 - Ultra320 SCSI Card (two external VHDC - and one internal 68-pin) - Adaptec SCSI Card 39320D Dual Channel 64-bit PCI-X 133MHz to 7902A4 - Ultra320 SCSI Card (two external VHDC - and one internal 68-pin) based on the - AIC-7902B ASIC - Adaptec SCSI Card 29320 Single Channel 64-bit PCI-X 133MHz to 7901A - Ultra320 SCSI Card (one external - 68-pin, two internal 68-pin, one - internal 50-pin) - Adaptec SCSI Card 29320A Single Channel 64-bit PCI-X 133MHz to 7901B - Ultra320 SCSI Card (one external - 68-pin, two internal 68-pin, one - internal 50-pin) - Adaptec SCSI Card 29320LP Single Channel 64-bit Low Profile 7901A - PCI-X 133MHz to Ultra320 SCSI Card - (One external VHDC, one internal - 68-pin) - Adaptec SCSI Card 29320ALP Single Channel 64-bit Low Profile 7901B - PCI-X 133MHz to Ultra320 SCSI Card - (One external VHDC, one internal - 68-pin) -2. Version History - - 3.0 (December 1st, 2005) - - Updated driver to use SCSI transport class infrastructure - - Upported sequencer and core fixes from adaptec released - version 2.0.15 of the driver. - - 1.3.11 (July 11, 2003) - - Fix several deadlock issues. - - Add 29320ALP and 39320B Id's. - - 1.3.10 (June 3rd, 2003) - - Align the SCB_TAG field on a 16byte boundary. This avoids - SCB corruption on some PCI-33 busses. - - Correct non-zero luns on Rev B. hardware. - - Update for change in 2.5.X SCSI proc FS interface. - - When negotiation async via an 8bit WDTR message, send - an SDTR with an offset of 0 to be sure the target - knows we are async. This works around a firmware defect - in the Quantum Atlas 10K. - - Implement controller suspend and resume. - - Clear PCI error state during driver attach so that we - don't disable memory mapped I/O due to a stray write - by some other driver probe that occurred before we - claimed the controller. - - 1.3.9 (May 22nd, 2003) - - Fix compiler errors. - - Remove S/G splitting for segments that cross a 4GB boundary. - This is guaranteed not to happen in Linux. - - Add support for scsi_report_device_reset() found in - 2.5.X kernels. - - Add 7901B support. - - Simplify handling of the packetized lun Rev A workaround. - - Correct and simplify handling of the ignore wide residue - message. The previous code would fail to report a residual - if the transaction data length was even and we received - an IWR message. - - 1.3.8 (April 29th, 2003) - - Fix types accessed via the command line interface code. - - Perform a few firmware optimizations. - - Fix "Unexpected PKT busfree" errors. - - Use a sequencer interrupt to notify the host of - commands with bad status. We defer the notification - until there are no outstanding selections to ensure - that the host is interrupted for as short a time as - possible. - - Remove pre-2.2.X support. - - Add support for new 2.5.X interrupt API. - - Correct big-endian architecture support. - - 1.3.7 (April 16th, 2003) - - Use del_timer_sync() to ensure that no timeouts - are pending during controller shutdown. - - For pre-2.5.X kernels, carefully adjust our segment - list size to avoid SCSI malloc pool fragmentation. - - Cleanup channel display in our /proc output. - - Workaround duplicate device entries in the mid-layer - device list during add-single-device. - - 1.3.6 (March 28th, 2003) - - Correct a double free in the Domain Validation code. - - Correct a reference to free'ed memory during controller - shutdown. - - Reset the bus on an SE->LVD change. This is required - to reset our transceivers. - - 1.3.5 (March 24th, 2003) - - Fix a few register window mode bugs. - - Include read streaming in the PPR flags we display in - diagnostics as well as /proc. - - Add PCI hot plug support for 2.5.X kernels. - - Correct default precompensation value for RevA hardware. - - Fix Domain Validation thread shutdown. - - Add a firmware workaround to make the LED blink - brighter during packetized operations on the H2A4. - - Correct /proc display of user read streaming settings. - - Simplify driver locking by releasing the io_request_lock - upon driver entry from the mid-layer. - - Cleanup command line parsing and move much of this code - to aiclib. - - 1.3.4 (February 28th, 2003) - - Correct a race condition in our error recovery handler. - - Allow Test Unit Ready commands to take a full 5 seconds - during Domain Validation. - - 1.3.2 (February 19th, 2003) - - Correct a Rev B. regression due to the GEM318 - compatibility fix included in 1.3.1. - - 1.3.1 (February 11th, 2003) - - Add support for the 39320A. - - Improve recovery for certain PCI-X errors. - - Fix handling of LQ/DATA/LQ/DATA for the - same write transaction that can occur without - interveining training. - - Correct compatibility issues with the GEM318 - enclosure services device. - - Correct data corruption issue that occurred under - high tag depth write loads. - - Adapt to a change in the 2.5.X daemonize() API. - - Correct a "Missing case in ahd_handle_scsiint" panic. - - 1.3.0 (January 21st, 2003) - - Full regression testing for all U320 products completed. - - Added abort and target/lun reset error recovery handler and - interrupt coalescing. - - 1.2.0 (November 14th, 2002) - - Added support for Domain Validation - - Add support for the Hewlett-Packard version of the 39320D - and AIC-7902 adapters. - Support for previous adapters has not been fully tested and should - only be used at the customer's own risk. - - 1.1.1 (September 24th, 2002) - - Added support for the Linux 2.5.X kernel series - - 1.1.0 (September 17th, 2002) - - Added support for four additional SCSI products: - ASC-39320, ASC-29320, ASC-29320LP, AIC-7901. - - 1.0.0 (May 30th, 2002) - - Initial driver release. - - 2.1. Software/Hardware Features - - Support for the SPI-4 "Ultra320" standard: - - 320MB/s transfer rates - - Packetized SCSI Protocol at 160MB/s and 320MB/s - - Quick Arbitration Selection (QAS) - - Retained Training Information (Rev B. ASIC only) - - Interrupt Coalescing - - Initiator Mode (target mode not currently - supported) - - Support for the PCI-X standard up to 133MHz - - Support for the PCI v2.2 standard - - Domain Validation - - 2.2. Operating System Support: - - Redhat Linux 7.2, 7.3, 8.0, Advanced Server 2.1 - - SuSE Linux 7.3, 8.0, 8.1, Enterprise Server 7 - - only Intel and AMD x86 supported at this time - - >4GB memory configurations supported. - - Refer to the User's Guide for more details on this. - -3. Command Line Options - - WARNING: ALTERING OR ADDING THESE DRIVER PARAMETERS - INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. - USE THEM WITH CAUTION. - - Put a .conf file in the /etc/modprobe.d/ directory and add/edit a - line containing 'options aic79xx aic79xx=[command[,command...]]' where - 'command' is one or more of the following: - ----------------------------------------------------------------- - Option: verbose - Definition: enable additional informative messages during - driver operation. - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: debug:[value] - Definition: Enables various levels of debugging information - The bit definitions for the debugging mask can - be found in drivers/scsi/aic7xxx/aic79xx.h under - the "Debug" heading. - Possible Values: 0x0000 = no debugging, 0xffff = full debugging - Default Value: 0x0000 - ----------------------------------------------------------------- - Option: no_reset - Definition: Do not reset the bus during the initial probe - phase - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: extended - Definition: Force extended translation on the controller - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: periodic_otag - Definition: Send an ordered tag periodically to prevent - tag starvation. Needed for some older devices - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: reverse_scan - Definition: Probe the scsi bus in reverse order, starting - with target 15 - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: global_tag_depth - Definition: Global tag depth for all targets on all busses. - This option sets the default tag depth which - may be selectively overridden vi the tag_info - option. - Possible Values: 1 - 253 - Default Value: 32 - ----------------------------------------------------------------- - Option: tag_info:{{value[,value...]}[,{value[,value...]}...]} - Definition: Set the per-target tagged queue depth on a - per controller basis. Both controllers and targets - may be omitted indicating that they should retain - the default tag depth. - Examples: tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32} - On Controller 0 - specifies a tag depth of 16 for target 0 - specifies a tag depth of 64 for target 3 - specifies a tag depth of 8 for targets 4 and 5 - leaves target 6 at the default - specifies a tag depth of 32 for targets 1,2,7-15 - All other targets retain the default depth. - - tag_info:{{},{32,,32}} - On Controller 1 - specifies a tag depth of 32 for targets 0 and 2 - All other targets retain the default depth. - - Possible Values: 1 - 253 - Default Value: 32 - ----------------------------------------------------------------- - Option: rd_strm: {rd_strm_bitmask[,rd_strm_bitmask...]} - Definition: Enable read streaming on a per target basis. - The rd_strm_bitmask is a 16 bit hex value in which - each bit represents a target. Setting the target's - bit to '1' enables read streaming for that - target. Controllers may be omitted indicating that - they should retain the default read streaming setting. - Example: rd_strm:{0x0041} - On Controller 0 - enables read streaming for targets 0 and 6. - disables read streaming for targets 1-5,7-15. - All other targets retain the default read - streaming setting. - Example: rd_strm:{0x0023,,0xFFFF} - On Controller 0 - enables read streaming for targets 1,2, and 5. - disables read streaming for targets 3,4,6-15. - On Controller 2 - enables read streaming for all targets. - All other targets retain the default read - streaming setting. - - Possible Values: 0x0000 - 0xffff - Default Value: 0x0000 - ----------------------------------------------------------------- - Option: dv: {value[,value...]} - Definition: Set Domain Validation Policy on a per-controller basis. - Controllers may be omitted indicating that - they should retain the default read streaming setting. - Example: dv:{-1,0,,1,1,0} - On Controller 0 leave DV at its default setting. - On Controller 1 disable DV. - Skip configuration on Controller 2. - On Controllers 3 and 4 enable DV. - On Controller 5 disable DV. - - Possible Values: < 0 Use setting from serial EEPROM. - 0 Disable DV - > 0 Enable DV - Default Value: DV Serial EEPROM configuration setting. - ----------------------------------------------------------------- - Option: seltime:[value] - Definition: Specifies the selection timeout value - Possible Values: 0 = 256ms, 1 = 128ms, 2 = 64ms, 3 = 32ms - Default Value: 0 - ----------------------------------------------------------------- - - *** The following three options should only be changed at *** - *** the direction of a technical support representative. *** - - ----------------------------------------------------------------- - Option: precomp: {value[,value...]} - Definition: Set IO Cell precompensation value on a per-controller - basis. - Controllers may be omitted indicating that - they should retain the default precompensation setting. - Example: precomp:{0x1} - On Controller 0 set precompensation to 1. - Example: precomp:{1,,7} - On Controller 0 set precompensation to 1. - On Controller 2 set precompensation to 8. - - Possible Values: 0 - 7 - Default Value: Varies based on chip revision - ----------------------------------------------------------------- - Option: slewrate: {value[,value...]} - Definition: Set IO Cell slew rate on a per-controller basis. - Controllers may be omitted indicating that - they should retain the default slew rate setting. - Example: slewrate:{0x1} - On Controller 0 set slew rate to 1. - Example: slewrate :{1,,8} - On Controller 0 set slew rate to 1. - On Controller 2 set slew rate to 8. - - Possible Values: 0 - 15 - Default Value: Varies based on chip revision - ----------------------------------------------------------------- - Option: amplitude: {value[,value...]} - Definition: Set IO Cell signal amplitude on a per-controller basis. - Controllers may be omitted indicating that - they should retain the default read streaming setting. - Example: amplitude:{0x1} - On Controller 0 set amplitude to 1. - Example: amplitude :{1,,7} - On Controller 0 set amplitude to 1. - On Controller 2 set amplitude to 7. - - Possible Values: 1 - 7 - Default Value: Varies based on chip revision - ----------------------------------------------------------------- - - Example: 'options aic79xx aic79xx=verbose,rd_strm:{{0x0041}}' - enables verbose output in the driver and turns read streaming on - for targets 0 and 6 of Controller 0. - -4. Additional Notes - - 4.1. Known/Unresolved or FYI Issues - - * Under SuSE Linux Enterprise 7, the driver may fail to operate - correctly due to a problem with PCI interrupt routing in the - Linux kernel. Please contact SuSE for an updated Linux - kernel. - - 4.2. Third-Party Compatibility Issues - - * Adaptec only supports Ultra320 hard drives running - the latest firmware available. Please check with - your hard drive manufacturer to ensure you have the - latest version. - - 4.3. Operating System or Technology Limitations - - * PCI Hot Plug is untested and may cause the operating system - to stop responding. - * Luns that are not numbered contiguously starting with 0 might not - be automatically probed during system startup. This is a limitation - of the OS. Please contact your Linux vendor for instructions on - manually probing non-contiguous luns. - * Using the Driver Update Disk version of this package during OS - installation under RedHat might result in two versions of this - driver being installed into the system module directory. This - might cause problems with the /sbin/mkinitrd program and/or - other RPM packages that try to install system modules. The best - way to correct this once the system is running is to install - the latest RPM package version of this driver, available from - http://www.adaptec.com. - - -5. Adaptec Customer Support - - A Technical Support Identification (TSID) Number is required for - Adaptec technical support. - - The 12-digit TSID can be found on the white barcode-type label - included inside the box with your product. The TSID helps us - provide more efficient service by accurately identifying your - product and support status. - - Support Options - - Search the Adaptec Support Knowledgebase (ASK) at - http://ask.adaptec.com for articles, troubleshooting tips, and - frequently asked questions about your product. - - For support via Email, submit your question to Adaptec's - Technical Support Specialists at http://ask.adaptec.com/. - - North America - - Visit our Web site at http://www.adaptec.com/. - - For information about Adaptec's support options, call - 408-957-2550, 24 hours a day, 7 days a week. - - To speak with a Technical Support Specialist, - * For hardware products, call 408-934-7274, - Monday to Friday, 3:00 am to 5:00 pm, PDT. - * For RAID and Fibre Channel products, call 321-207-2000, - Monday to Friday, 3:00 am to 5:00 pm, PDT. - To expedite your service, have your computer with you. - - To order Adaptec products, including accessories and cables, - call 408-957-7274. To order cables online go to - http://www.adaptec.com/buy-cables/. - - Europe - - Visit our Web site at http://www.adaptec.com/en-US/_common/world_index. - - To speak with a Technical Support Specialist, call, or email, - * German: +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET, - http://ask-de.adaptec.com/. - * French: +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET, - http://ask-fr.adaptec.com/. - * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT, - http://ask.adaptec.com/. - - You can order Adaptec cables online at - http://www.adaptec.com/buy-cables/. - - Japan - - Visit our web site at http://www.adaptec.co.jp/. - - To speak with a Technical Support Specialist, call - +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m., - 1:00 p.m. to 6:00 p.m. - -------------------------------------------------------------------- -/* - * Copyright (c) 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA. - * All rights reserved. - * - * You are permitted to redistribute, use and modify this README file in whole - * or in part in conjunction with redistribution of software governed by the - * General Public License, provided that the following conditions are met: - * 1. Redistributions of README file must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * 3. Modifications or new contributions must be attributed in a copyright - * notice identifying the author ("Contributor") and added below the - * original copyright notice. The copyright notice is for purposes of - * identifying contributors and should not be deemed as permission to alter - * the permissions given by Adaptec. - * - * THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY - * WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README - * FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/Documentation/scsi/aic7xxx.rst b/Documentation/scsi/aic7xxx.rst new file mode 100644 index 000000000000..bad0e5567b21 --- /dev/null +++ b/Documentation/scsi/aic7xxx.rst @@ -0,0 +1,458 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. include:: <isonum.txt> + +======================================================== +Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v7.0 +======================================================== + +README for The Linux Operating System + +The following information is available in this file: + + 1. Supported Hardware + 2. Version History + 3. Command Line Options + 4. Contacting Adaptec + +1. Supported Hardware +===================== + + The following Adaptec SCSI Chips and Host Adapters are supported by + the aic7xxx driver. + + ======== ===== ========= ======== ========= ===== =============== + Chip MIPS Host Bus MaxSync MaxWidth SCBs Notes + ======== ===== ========= ======== ========= ===== =============== + aic7770 10 EISA/VL 10MHz 16Bit 4 1 + aic7850 10 PCI/32 10MHz 8Bit 3 + aic7855 10 PCI/32 10MHz 8Bit 3 + aic7856 10 PCI/32 10MHz 8Bit 3 + aic7859 10 PCI/32 20MHz 8Bit 3 + aic7860 10 PCI/32 20MHz 8Bit 3 + aic7870 10 PCI/32 10MHz 16Bit 16 + aic7880 10 PCI/32 20MHz 16Bit 16 + aic7890 20 PCI/32 40MHz 16Bit 16 3 4 5 6 7 8 + aic7891 20 PCI/64 40MHz 16Bit 16 3 4 5 6 7 8 + aic7892 20 PCI/64-66 80MHz 16Bit 16 3 4 5 6 7 8 + aic7895 15 PCI/32 20MHz 16Bit 16 2 3 4 5 + aic7895C 15 PCI/32 20MHz 16Bit 16 2 3 4 5 8 + aic7896 20 PCI/32 40MHz 16Bit 16 2 3 4 5 6 7 8 + aic7897 20 PCI/64 40MHz 16Bit 16 2 3 4 5 6 7 8 + aic7899 20 PCI/64-66 80MHz 16Bit 16 2 3 4 5 6 7 8 + ======== ===== ========= ======== ========= ===== =============== + + 1. Multiplexed Twin Channel Device - One controller servicing two + busses. + 2. Multi-function Twin Channel Device - Two controllers on one chip. + 3. Command Channel Secondary DMA Engine - Allows scatter gather list + and SCB prefetch. + 4. 64 Byte SCB Support - Allows disconnected, untagged request table + for all possible target/lun combinations. + 5. Block Move Instruction Support - Doubles the speed of certain + sequencer operations. + 6. 'Bayonet' style Scatter Gather Engine - Improves S/G prefetch + performance. + 7. Queuing Registers - Allows queuing of new transactions without + pausing the sequencer. + 8. Multiple Target IDs - Allows the controller to respond to selection + as a target on multiple SCSI IDs. + + ============== ======= =========== =============== =============== ========= + Controller Chip Host-Bus Int-Connectors Ext-Connectors Notes + ============== ======= =========== =============== =============== ========= + AHA-274X[A] aic7770 EISA SE-50M SE-HD50F + AHA-274X[A]W aic7770 EISA SE-HD68F SE-HD68F + SE-50M + AHA-274X[A]T aic7770 EISA 2 X SE-50M SE-HD50F + AHA-2842 aic7770 VL SE-50M SE-HD50F + AHA-2940AU aic7860 PCI/32 SE-50M SE-HD50F + AVA-2902I aic7860 PCI/32 SE-50M + AVA-2902E aic7860 PCI/32 SE-50M + AVA-2906 aic7856 PCI/32 SE-50M SE-DB25F + APC-7850 aic7850 PCI/32 SE-50M 1 + AVA-2940 aic7860 PCI/32 SE-50M + AHA-2920B aic7860 PCI/32 SE-50M + AHA-2930B aic7860 PCI/32 SE-50M + AHA-2920C aic7856 PCI/32 SE-50M SE-HD50F + AHA-2930C aic7860 PCI/32 SE-50M + AHA-2930C aic7860 PCI/32 SE-50M + AHA-2910C aic7860 PCI/32 SE-50M + AHA-2915C aic7860 PCI/32 SE-50M + AHA-2940AU/CN aic7860 PCI/32 SE-50M SE-HD50F + AHA-2944W aic7870 PCI/32 HVD-HD68F HVD-HD68F + HVD-50M + AHA-3940W aic7870 PCI/32 2 X SE-HD68F SE-HD68F 2 + AHA-2940UW aic7880 PCI/32 SE-HD68F + SE-50M SE-HD68F + AHA-2940U aic7880 PCI/32 SE-50M SE-HD50F + AHA-2940D aic7880 PCI/32 + aHA-2940 A/T aic7880 PCI/32 + AHA-2940D A/T aic7880 PCI/32 + AHA-3940UW aic7880 PCI/32 2 X SE-HD68F SE-HD68F 3 + AHA-3940UWD aic7880 PCI/32 2 X SE-HD68F 2 X SE-VHD68F 3 + AHA-3940U aic7880 PCI/32 2 X SE-50M SE-HD50F 3 + AHA-2944UW aic7880 PCI/32 HVD-HD68F HVD-HD68F + HVD-50M + AHA-3944UWD aic7880 PCI/32 2 X HVD-HD68F 2 X HVD-VHD68F 3 + AHA-4944UW aic7880 PCI/32 + AHA-2930UW aic7880 PCI/32 + AHA-2940UW Pro aic7880 PCI/32 SE-HD68F SE-HD68F 4 + SE-50M + AHA-2940UW/CN aic7880 PCI/32 + AHA-2940UDual aic7895 PCI/32 + AHA-2940UWDual aic7895 PCI/32 + AHA-3940UWD aic7895 PCI/32 + AHA-3940AUW aic7895 PCI/32 + AHA-3940AUWD aic7895 PCI/32 + AHA-3940AU aic7895 PCI/32 + AHA-3944AUWD aic7895 PCI/32 2 X HVD-HD68F 2 X HVD-VHD68F + AHA-2940U2B aic7890 PCI/32 LVD-HD68F LVD-HD68F + AHA-2940U2 OEM aic7891 PCI/64 + AHA-2940U2W aic7890 PCI/32 LVD-HD68F LVD-HD68F + SE-HD68F + SE-50M + AHA-2950U2B aic7891 PCI/64 LVD-HD68F LVD-HD68F + AHA-2930U2 aic7890 PCI/32 LVD-HD68F SE-HD50F + SE-50M + AHA-3950U2B aic7897 PCI/64 + AHA-3950U2D aic7897 PCI/64 + AHA-29160 aic7892 PCI/64-66 + AHA-29160 CPQ aic7892 PCI/64-66 + AHA-29160N aic7892 PCI/32 LVD-HD68F SE-HD50F + SE-50M + AHA-29160LP aic7892 PCI/64-66 + AHA-19160 aic7892 PCI/64-66 + AHA-29150LP aic7892 PCI/64-66 + AHA-29130LP aic7892 PCI/64-66 + AHA-3960D aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F + LVD-50M + AHA-3960D CPQ aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F + LVD-50M + AHA-39160 aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F + LVD-50M + ============== ======= =========== =============== =============== ========= + + 1. No BIOS support + 2. DEC21050 PCI-PCI bridge with multiple controller chips on secondary bus + 3. DEC2115X PCI-PCI bridge with multiple controller chips on secondary bus + 4. All three SCSI connectors may be used simultaneously without + SCSI "stub" effects. + +2. Version History +================== + + * 7.0 (4th August, 2005) + - Updated driver to use SCSI transport class infrastructure + - Upported sequencer and core fixes from last adaptec released + version of the driver. + + * 6.2.36 (June 3rd, 2003) + - Correct code that disables PCI parity error checking. + - Correct and simplify handling of the ignore wide residue + message. The previous code would fail to report a residual + if the transaction data length was even and we received + an IWR message. + - Add support for the 2.5.X EISA framework. + - Update for change in 2.5.X SCSI proc FS interface. + - Correct Domain Validation command-line option parsing. + - When negotiation async via an 8bit WDTR message, send + an SDTR with an offset of 0 to be sure the target + knows we are async. This works around a firmware defect + in the Quantum Atlas 10K. + - Clear PCI error state during driver attach so that we + don't disable memory mapped I/O due to a stray write + by some other driver probe that occurred before we + claimed the controller. + + * 6.2.35 (May 14th, 2003) + - Fix a few GCC 3.3 compiler warnings. + - Correct operation on EISA Twin Channel controller. + - Add support for 2.5.X's scsi_report_device_reset(). + + * 6.2.34 (May 5th, 2003) + - Fix locking regression introduced in 6.2.29 that + could cause a lock order reversal between the io_request_lock + and our per-softc lock. This was only possible on RH9, + SuSE, and kernel.org 2.4.X kernels. + + * 6.2.33 (April 30th, 2003) + - Dynamically disable PCI parity error reporting after + 10 errors are reported to the user. These errors are + the result of some other device issuing PCI transactions + with bad parity. Once the user has been informed of the + problem, continuing to report the errors just degrades + our performance. + + * 6.2.32 (March 28th, 2003) + - Dynamically sized S/G lists to avoid SCSI malloc + pool fragmentation and SCSI mid-layer deadlock. + + * 6.2.28 (January 20th, 2003) + - Domain Validation Fixes + - Add ability to disable PCI parity error checking. + - Enhanced Memory Mapped I/O probe + + * 6.2.20 (November 7th, 2002) + - Added Domain Validation. + +3. Command Line Options +======================= + + + .. Warning:: + + ALTERING OR ADDING THESE DRIVER PARAMETERS + INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. + USE THEM WITH CAUTION. + + Put a .conf file in the /etc/modprobe.d directory and add/edit a + line containing ``options aic7xxx aic7xxx=[command[,command...]]`` where + ``command`` is one or more of the following: + +verbose + + :Definition: enable additional informative messages during driver operation. + :Possible Values: This option is a flag + :Default Value: disabled + + +debug:[value] + + :Definition: Enables various levels of debugging information + :Possible Values: 0x0000 = no debugging, 0xffff = full debugging + :Default Value: 0x0000 + +no_probe + +probe_eisa_vl + + :Definition: Do not probe for EISA/VLB controllers. + This is a toggle. If the driver is compiled + to not probe EISA/VLB controllers by default, + specifying "no_probe" will enable this probing. + If the driver is compiled to probe EISA/VLB + controllers by default, specifying "no_probe" + will disable this probing. + + :Possible Values: This option is a toggle + :Default Value: EISA/VLB probing is disabled by default. + +pci_parity + + :Definition: Toggles the detection of PCI parity errors. + On many motherboards with VIA chipsets, + PCI parity is not generated correctly on the + PCI bus. It is impossible for the hardware to + differentiate between these "spurious" parity + errors and real parity errors. The symptom of + this problem is a stream of the message:: + + "scsi0: Data Parity Error Detected during address or write data phase" + + output by the driver. + + :Possible Values: This option is a toggle + :Default Value: PCI Parity Error reporting is disabled + +no_reset + + :Definition: Do not reset the bus during the initial probe + phase + + :Possible Values: This option is a flag + :Default Value: disabled + +extended + + :Definition: Force extended translation on the controller + :Possible Values: This option is a flag + :Default Value: disabled + +periodic_otag + + :Definition: Send an ordered tag periodically to prevent + tag starvation. Needed for some older devices + + :Possible Values: This option is a flag + :Default Value: disabled + +reverse_scan + + :Definition: Probe the scsi bus in reverse order, starting + with target 15 + + :Possible Values: This option is a flag + :Default Value: disabled + +global_tag_depth:[value] + + :Definition: Global tag depth for all targets on all busses. + This option sets the default tag depth which + may be selectively overridden vi the tag_info + option. + + :Possible Values: 1 - 253 + :Default Value: 32 + +tag_info:{{value[,value...]}[,{value[,value...]}...]} + + :Definition: Set the per-target tagged queue depth on a + per controller basis. Both controllers and targets + may be omitted indicating that they should retain + the default tag depth. + + :Possible Values: 1 - 253 + :Default Value: 32 + + Examples: + + :: + + tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32} + + On Controller 0: + + - specifies a tag depth of 16 for target 0 + - specifies a tag depth of 64 for target 3 + - specifies a tag depth of 8 for targets 4 and 5 + - leaves target 6 at the default + - specifies a tag depth of 32 for targets 1,2,7-15 + - All other targets retain the default depth. + + :: + + tag_info:{{},{32,,32}} + + On Controller 1: + + - specifies a tag depth of 32 for targets 0 and 2 + - All other targets retain the default depth. + +seltime:[value] + + :Definition: Specifies the selection timeout value + :Possible Values: 0 = 256ms, 1 = 128ms, 2 = 64ms, 3 = 32ms + :Default Value: 0 + +dv: {value[,value...]} + + :Definition: Set Domain Validation Policy on a per-controller basis. + Controllers may be omitted indicating that + they should retain the default read streaming setting. + + :Possible Values: + + ==== =============================== + < 0 Use setting from serial EEPROM. + 0 Disable DV + > 0 Enable DV + ==== =============================== + + + :Default Value: SCSI-Select setting on controllers with a SCSI Select + option for DV. Otherwise, on for controllers supporting + U160 speeds and off for all other controller types. + + Example: + + :: + + dv:{-1,0,,1,1,0} + + - On Controller 0 leave DV at its default setting. + - On Controller 1 disable DV. + - Skip configuration on Controller 2. + - On Controllers 3 and 4 enable DV. + - On Controller 5 disable DV. + +Example:: + + options aic7xxx aic7xxx=verbose,no_probe,tag_info:{{},{,,10}},seltime:1 + +enables verbose logging, Disable EISA/VLB probing, +and set tag depth on Controller 1/Target 2 to 10 tags. + +4. Adaptec Customer Support +=========================== + + A Technical Support Identification (TSID) Number is required for + Adaptec technical support. + + - The 12-digit TSID can be found on the white barcode-type label + included inside the box with your product. The TSID helps us + provide more efficient service by accurately identifying your + product and support status. + + Support Options + - Search the Adaptec Support Knowledgebase (ASK) at + http://ask.adaptec.com for articles, troubleshooting tips, and + frequently asked questions about your product. + - For support via Email, submit your question to Adaptec's + Technical Support Specialists at http://ask.adaptec.com/. + + North America + - Visit our Web site at http://www.adaptec.com/. + - For information about Adaptec's support options, call + 408-957-2550, 24 hours a day, 7 days a week. + - To speak with a Technical Support Specialist, + + * For hardware products, call 408-934-7274, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + * For RAID and Fibre Channel products, call 321-207-2000, + Monday to Friday, 3:00 am to 5:00 pm, PDT. + + To expedite your service, have your computer with you. + - To order Adaptec products, including accessories and cables, + call 408-957-7274. To order cables online go to + http://www.adaptec.com/buy-cables/. + + Europe + - Visit our Web site at http://www.adaptec.com/en-US/_common/world_index. + - To speak with a Technical Support Specialist, call, or email, + + * German: +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET, + http://ask-de.adaptec.com/. + * French: +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET, + http://ask-fr.adaptec.com/. + * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT, + http://ask.adaptec.com/. + + - You can order Adaptec cables online at + http://www.adaptec.com/buy-cables/. + + Japan + - Visit our web site at http://www.adaptec.co.jp/. + - To speak with a Technical Support Specialist, call + +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m., + 1:00 p.m. to 6:00 p.m. + +Copyright |copy| 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA. + +All rights reserved. + +You are permitted to redistribute, use and modify this README file in whole +or in part in conjunction with redistribution of software governed by the +General Public License, provided that the following conditions are met: + +1. Redistributions of README file must retain the above copyright + notice, this list of conditions, and the following disclaimer, + without modification. +2. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. +3. Modifications or new contributions must be attributed in a copyright + notice identifying the author ("Contributor") and added below the + original copyright notice. The copyright notice is for purposes of + identifying contributors and should not be deemed as permission to alter + the permissions given by Adaptec. + +THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS`` AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY +WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README +FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt deleted file mode 100644 index 7c5d0223d444..000000000000 --- a/Documentation/scsi/aic7xxx.txt +++ /dev/null @@ -1,394 +0,0 @@ -==================================================================== -= Adaptec Aic7xxx Fast -> Ultra160 Family Manager Set v7.0 = -= README for = -= The Linux Operating System = -==================================================================== - -The following information is available in this file: - - 1. Supported Hardware - 2. Version History - 3. Command Line Options - 4. Contacting Adaptec - -1. Supported Hardware - - The following Adaptec SCSI Chips and Host Adapters are supported by - the aic7xxx driver. - - Chip MIPS Host Bus MaxSync MaxWidth SCBs Notes - --------------------------------------------------------------- - aic7770 10 EISA/VL 10MHz 16Bit 4 1 - aic7850 10 PCI/32 10MHz 8Bit 3 - aic7855 10 PCI/32 10MHz 8Bit 3 - aic7856 10 PCI/32 10MHz 8Bit 3 - aic7859 10 PCI/32 20MHz 8Bit 3 - aic7860 10 PCI/32 20MHz 8Bit 3 - aic7870 10 PCI/32 10MHz 16Bit 16 - aic7880 10 PCI/32 20MHz 16Bit 16 - aic7890 20 PCI/32 40MHz 16Bit 16 3 4 5 6 7 8 - aic7891 20 PCI/64 40MHz 16Bit 16 3 4 5 6 7 8 - aic7892 20 PCI/64-66 80MHz 16Bit 16 3 4 5 6 7 8 - aic7895 15 PCI/32 20MHz 16Bit 16 2 3 4 5 - aic7895C 15 PCI/32 20MHz 16Bit 16 2 3 4 5 8 - aic7896 20 PCI/32 40MHz 16Bit 16 2 3 4 5 6 7 8 - aic7897 20 PCI/64 40MHz 16Bit 16 2 3 4 5 6 7 8 - aic7899 20 PCI/64-66 80MHz 16Bit 16 2 3 4 5 6 7 8 - - 1. Multiplexed Twin Channel Device - One controller servicing two - busses. - 2. Multi-function Twin Channel Device - Two controllers on one chip. - 3. Command Channel Secondary DMA Engine - Allows scatter gather list - and SCB prefetch. - 4. 64 Byte SCB Support - Allows disconnected, untagged request table - for all possible target/lun combinations. - 5. Block Move Instruction Support - Doubles the speed of certain - sequencer operations. - 6. `Bayonet' style Scatter Gather Engine - Improves S/G prefetch - performance. - 7. Queuing Registers - Allows queuing of new transactions without - pausing the sequencer. - 8. Multiple Target IDs - Allows the controller to respond to selection - as a target on multiple SCSI IDs. - - Controller Chip Host-Bus Int-Connectors Ext-Connectors Notes - -------------------------------------------------------------------------- - AHA-274X[A] aic7770 EISA SE-50M SE-HD50F - AHA-274X[A]W aic7770 EISA SE-HD68F SE-HD68F - SE-50M - AHA-274X[A]T aic7770 EISA 2 X SE-50M SE-HD50F - AHA-2842 aic7770 VL SE-50M SE-HD50F - AHA-2940AU aic7860 PCI/32 SE-50M SE-HD50F - AVA-2902I aic7860 PCI/32 SE-50M - AVA-2902E aic7860 PCI/32 SE-50M - AVA-2906 aic7856 PCI/32 SE-50M SE-DB25F - APC-7850 aic7850 PCI/32 SE-50M 1 - AVA-2940 aic7860 PCI/32 SE-50M - AHA-2920B aic7860 PCI/32 SE-50M - AHA-2930B aic7860 PCI/32 SE-50M - AHA-2920C aic7856 PCI/32 SE-50M SE-HD50F - AHA-2930C aic7860 PCI/32 SE-50M - AHA-2930C aic7860 PCI/32 SE-50M - AHA-2910C aic7860 PCI/32 SE-50M - AHA-2915C aic7860 PCI/32 SE-50M - AHA-2940AU/CN aic7860 PCI/32 SE-50M SE-HD50F - AHA-2944W aic7870 PCI/32 HVD-HD68F HVD-HD68F - HVD-50M - AHA-3940W aic7870 PCI/32 2 X SE-HD68F SE-HD68F 2 - AHA-2940UW aic7880 PCI/32 SE-HD68F - SE-50M SE-HD68F - AHA-2940U aic7880 PCI/32 SE-50M SE-HD50F - AHA-2940D aic7880 PCI/32 - aHA-2940 A/T aic7880 PCI/32 - AHA-2940D A/T aic7880 PCI/32 - AHA-3940UW aic7880 PCI/32 2 X SE-HD68F SE-HD68F 3 - AHA-3940UWD aic7880 PCI/32 2 X SE-HD68F 2 X SE-VHD68F 3 - AHA-3940U aic7880 PCI/32 2 X SE-50M SE-HD50F 3 - AHA-2944UW aic7880 PCI/32 HVD-HD68F HVD-HD68F - HVD-50M - AHA-3944UWD aic7880 PCI/32 2 X HVD-HD68F 2 X HVD-VHD68F 3 - AHA-4944UW aic7880 PCI/32 - AHA-2930UW aic7880 PCI/32 - AHA-2940UW Pro aic7880 PCI/32 SE-HD68F SE-HD68F 4 - SE-50M - AHA-2940UW/CN aic7880 PCI/32 - AHA-2940UDual aic7895 PCI/32 - AHA-2940UWDual aic7895 PCI/32 - AHA-3940UWD aic7895 PCI/32 - AHA-3940AUW aic7895 PCI/32 - AHA-3940AUWD aic7895 PCI/32 - AHA-3940AU aic7895 PCI/32 - AHA-3944AUWD aic7895 PCI/32 2 X HVD-HD68F 2 X HVD-VHD68F - AHA-2940U2B aic7890 PCI/32 LVD-HD68F LVD-HD68F - AHA-2940U2 OEM aic7891 PCI/64 - AHA-2940U2W aic7890 PCI/32 LVD-HD68F LVD-HD68F - SE-HD68F - SE-50M - AHA-2950U2B aic7891 PCI/64 LVD-HD68F LVD-HD68F - AHA-2930U2 aic7890 PCI/32 LVD-HD68F SE-HD50F - SE-50M - AHA-3950U2B aic7897 PCI/64 - AHA-3950U2D aic7897 PCI/64 - AHA-29160 aic7892 PCI/64-66 - AHA-29160 CPQ aic7892 PCI/64-66 - AHA-29160N aic7892 PCI/32 LVD-HD68F SE-HD50F - SE-50M - AHA-29160LP aic7892 PCI/64-66 - AHA-19160 aic7892 PCI/64-66 - AHA-29150LP aic7892 PCI/64-66 - AHA-29130LP aic7892 PCI/64-66 - AHA-3960D aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F - LVD-50M - AHA-3960D CPQ aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F - LVD-50M - AHA-39160 aic7899 PCI/64-66 2 X LVD-HD68F 2 X LVD-VHD68F - LVD-50M - - 1. No BIOS support - 2. DEC21050 PCI-PCI bridge with multiple controller chips on secondary bus - 3. DEC2115X PCI-PCI bridge with multiple controller chips on secondary bus - 4. All three SCSI connectors may be used simultaneously without - SCSI "stub" effects. - -2. Version History - 7.0 (4th August, 2005) - - Updated driver to use SCSI transport class infrastructure - - Upported sequencer and core fixes from last adaptec released - version of the driver. - 6.2.36 (June 3rd, 2003) - - Correct code that disables PCI parity error checking. - - Correct and simplify handling of the ignore wide residue - message. The previous code would fail to report a residual - if the transaction data length was even and we received - an IWR message. - - Add support for the 2.5.X EISA framework. - - Update for change in 2.5.X SCSI proc FS interface. - - Correct Domain Validation command-line option parsing. - - When negotiation async via an 8bit WDTR message, send - an SDTR with an offset of 0 to be sure the target - knows we are async. This works around a firmware defect - in the Quantum Atlas 10K. - - Clear PCI error state during driver attach so that we - don't disable memory mapped I/O due to a stray write - by some other driver probe that occurred before we - claimed the controller. - - 6.2.35 (May 14th, 2003) - - Fix a few GCC 3.3 compiler warnings. - - Correct operation on EISA Twin Channel controller. - - Add support for 2.5.X's scsi_report_device_reset(). - - 6.2.34 (May 5th, 2003) - - Fix locking regression introduced in 6.2.29 that - could cause a lock order reversal between the io_request_lock - and our per-softc lock. This was only possible on RH9, - SuSE, and kernel.org 2.4.X kernels. - - 6.2.33 (April 30th, 2003) - - Dynamically disable PCI parity error reporting after - 10 errors are reported to the user. These errors are - the result of some other device issuing PCI transactions - with bad parity. Once the user has been informed of the - problem, continuing to report the errors just degrades - our performance. - - 6.2.32 (March 28th, 2003) - - Dynamically sized S/G lists to avoid SCSI malloc - pool fragmentation and SCSI mid-layer deadlock. - - 6.2.28 (January 20th, 2003) - - Domain Validation Fixes - - Add ability to disable PCI parity error checking. - - Enhanced Memory Mapped I/O probe - - 6.2.20 (November 7th, 2002) - - Added Domain Validation. - -3. Command Line Options - - WARNING: ALTERING OR ADDING THESE DRIVER PARAMETERS - INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. - USE THEM WITH CAUTION. - - Put a .conf file in the /etc/modprobe.d directory and add/edit a - line containing 'options aic7xxx aic7xxx=[command[,command...]]' where - 'command' is one or more of the following: - ----------------------------------------------------------------- - Option: verbose - Definition: enable additional informative messages during - driver operation. - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: debug:[value] - Definition: Enables various levels of debugging information - Possible Values: 0x0000 = no debugging, 0xffff = full debugging - Default Value: 0x0000 - ----------------------------------------------------------------- - Option: no_probe - Option: probe_eisa_vl - Definition: Do not probe for EISA/VLB controllers. - This is a toggle. If the driver is compiled - to not probe EISA/VLB controllers by default, - specifying "no_probe" will enable this probing. - If the driver is compiled to probe EISA/VLB - controllers by default, specifying "no_probe" - will disable this probing. - Possible Values: This option is a toggle - Default Value: EISA/VLB probing is disabled by default. - ----------------------------------------------------------------- - Option: pci_parity - Definition: Toggles the detection of PCI parity errors. - On many motherboards with VIA chipsets, - PCI parity is not generated correctly on the - PCI bus. It is impossible for the hardware to - differentiate between these "spurious" parity - errors and real parity errors. The symptom of - this problem is a stream of the message: - "scsi0: Data Parity Error Detected during address or write data phase" - output by the driver. - Possible Values: This option is a toggle - Default Value: PCI Parity Error reporting is disabled - ----------------------------------------------------------------- - Option: no_reset - Definition: Do not reset the bus during the initial probe - phase - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: extended - Definition: Force extended translation on the controller - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: periodic_otag - Definition: Send an ordered tag periodically to prevent - tag starvation. Needed for some older devices - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: reverse_scan - Definition: Probe the scsi bus in reverse order, starting - with target 15 - Possible Values: This option is a flag - Default Value: disabled - ----------------------------------------------------------------- - Option: global_tag_depth:[value] - Definition: Global tag depth for all targets on all busses. - This option sets the default tag depth which - may be selectively overridden vi the tag_info - option. - Possible Values: 1 - 253 - Default Value: 32 - ----------------------------------------------------------------- - Option: tag_info:{{value[,value...]}[,{value[,value...]}...]} - Definition: Set the per-target tagged queue depth on a - per controller basis. Both controllers and targets - may be omitted indicating that they should retain - the default tag depth. - Examples: tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32} - On Controller 0 - specifies a tag depth of 16 for target 0 - specifies a tag depth of 64 for target 3 - specifies a tag depth of 8 for targets 4 and 5 - leaves target 6 at the default - specifies a tag depth of 32 for targets 1,2,7-15 - All other targets retain the default depth. - - tag_info:{{},{32,,32}} - On Controller 1 - specifies a tag depth of 32 for targets 0 and 2 - All other targets retain the default depth. - - Possible Values: 1 - 253 - Default Value: 32 - ----------------------------------------------------------------- - Option: seltime:[value] - Definition: Specifies the selection timeout value - Possible Values: 0 = 256ms, 1 = 128ms, 2 = 64ms, 3 = 32ms - Default Value: 0 - ----------------------------------------------------------------- - Option: dv: {value[,value...]} - Definition: Set Domain Validation Policy on a per-controller basis. - Controllers may be omitted indicating that - they should retain the default read streaming setting. - Example: dv:{-1,0,,1,1,0} - On Controller 0 leave DV at its default setting. - On Controller 1 disable DV. - Skip configuration on Controller 2. - On Controllers 3 and 4 enable DV. - On Controller 5 disable DV. - - Possible Values: < 0 Use setting from serial EEPROM. - 0 Disable DV - > 0 Enable DV - - Default Value: SCSI-Select setting on controllers with a SCSI Select - option for DV. Otherwise, on for controllers supporting - U160 speeds and off for all other controller types. - ----------------------------------------------------------------- - - Example: - 'options aic7xxx aic7xxx=verbose,no_probe,tag_info:{{},{,,10}},seltime:1' - enables verbose logging, Disable EISA/VLB probing, - and set tag depth on Controller 1/Target 2 to 10 tags. - -4. Adaptec Customer Support - - A Technical Support Identification (TSID) Number is required for - Adaptec technical support. - - The 12-digit TSID can be found on the white barcode-type label - included inside the box with your product. The TSID helps us - provide more efficient service by accurately identifying your - product and support status. - - Support Options - - Search the Adaptec Support Knowledgebase (ASK) at - http://ask.adaptec.com for articles, troubleshooting tips, and - frequently asked questions about your product. - - For support via Email, submit your question to Adaptec's - Technical Support Specialists at http://ask.adaptec.com/. - - North America - - Visit our Web site at http://www.adaptec.com/. - - For information about Adaptec's support options, call - 408-957-2550, 24 hours a day, 7 days a week. - - To speak with a Technical Support Specialist, - * For hardware products, call 408-934-7274, - Monday to Friday, 3:00 am to 5:00 pm, PDT. - * For RAID and Fibre Channel products, call 321-207-2000, - Monday to Friday, 3:00 am to 5:00 pm, PDT. - To expedite your service, have your computer with you. - - To order Adaptec products, including accessories and cables, - call 408-957-7274. To order cables online go to - http://www.adaptec.com/buy-cables/. - - Europe - - Visit our Web site at http://www.adaptec.com/en-US/_common/world_index. - - To speak with a Technical Support Specialist, call, or email, - * German: +49 89 4366 5522, Monday-Friday, 9:00-17:00 CET, - http://ask-de.adaptec.com/. - * French: +49 89 4366 5533, Monday-Friday, 9:00-17:00 CET, - http://ask-fr.adaptec.com/. - * English: +49 89 4366 5544, Monday-Friday, 9:00-17:00 GMT, - http://ask.adaptec.com/. - - You can order Adaptec cables online at - http://www.adaptec.com/buy-cables/. - - Japan - - Visit our web site at http://www.adaptec.co.jp/. - - To speak with a Technical Support Specialist, call - +81 3 5308 6120, Monday-Friday, 9:00 a.m. to 12:00 p.m., - 1:00 p.m. to 6:00 p.m. - -------------------------------------------------------------------- -/* - * Copyright (c) 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA. - * All rights reserved. - * - * You are permitted to redistribute, use and modify this README file in whole - * or in part in conjunction with redistribution of software governed by the - * General Public License, provided that the following conditions are met: - * 1. Redistributions of README file must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * 3. Modifications or new contributions must be attributed in a copyright - * notice identifying the author ("Contributor") and added below the - * original copyright notice. The copyright notice is for purposes of - * identifying contributors and should not be deemed as permission to alter - * the permissions given by Adaptec. - * - * THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY - * WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README - * FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/Documentation/scsi/arcmsr_spec.rst b/Documentation/scsi/arcmsr_spec.rst new file mode 100644 index 000000000000..83dd53bcff78 --- /dev/null +++ b/Documentation/scsi/arcmsr_spec.rst @@ -0,0 +1,907 @@ +ARECA FIRMWARE SPEC +=================== + +Usage of IOP331 adapter +======================= + +(All In/Out is in IOP331's view) + +1. Message 0 +------------ + +- InitThread message and return code + +2. Doorbell is used for RS-232 emulation +---------------------------------------- + +inDoorBell + bit0 + data in ready + zDRIVER DATA WRITE OK) + bit1 + data out has been read + (DRIVER DATA READ OK) + +outDooeBell: + bit0 + data out ready + (IOP331 DATA WRITE OK) + bit1 + data in has been read + (IOP331 DATA READ OK) + +3. Index Memory Usage +--------------------- + +============ ========================================== +offset 0xf00 for RS232 out (request buffer) +offset 0xe00 for RS232 in (scratch buffer) +offset 0xa00 for inbound message code message_rwbuffer + (driver send to IOP331) +offset 0xa00 for outbound message code message_rwbuffer + (IOP331 send to driver) +============ ========================================== + +4. RS-232 emulation +------------------- + +Currently 128 byte buffer is used: + +============ ===================== +1st uint32_t Data length (1--124) +Byte 4--127 Max 124 bytes of data +============ ===================== + +5. PostQ +-------- + +All SCSI Command must be sent through postQ: + + (inbound queue port) + Request frame must be 32 bytes aligned: + + #bit27--bit31 + flag for post ccb + #bit0--bit26 + real address (bit27--bit31) of post arcmsr_cdb + + ===== =================== + bit31 == =============== + 0 256 bytes frame + 1 512 bytes frame + == =============== + bit30 == ============== + 0 normal request + 1 BIOS request + == ============== + bit29 reserved + bit28 reserved + bit27 reserved + ===== =================== + + (outbount queue port) + Request reply: + + #bit27--bit31 + flag for reply + #bit0--bit26 + real address (bit27--bit31) of reply arcmsr_cdb + + ===== ======================================================= + bit31 must be 0 (for this type of reply) + bit30 reserved for BIOS handshake + bit29 reserved + bit28 == =================================================== + 0 no error, ignore AdapStatus/DevStatus/SenseData + 1 Error, error code in AdapStatus/DevStatus/SenseData + == =================================================== + bit27 reserved + ===== ======================================================= + +6. BIOS request +--------------- + +All BIOS request is the same with request from PostQ + +Except: + +Request frame is sent from configuration space: + + ============ ========================== + offset: 0x78 Request Frame (bit30 == 1) + offset: 0x18 writeonly to generate + IRQ to IOP331 + ============ ========================== + +Completion of request:: + + (bit30 == 0, bit28==err flag) + +7. Definition of SGL entry (structure) +-------------------------------------- + +8. Message1 Out - Diag Status Code (????) +----------------------------------------- + +9. Message0 message code +------------------------ + +====== ================================================================= +0x00 NOP +0x01 Get Config + ->offset 0xa00 :for outbound message code message_rwbuffer + (IOP331 send to driver) + + ===================== ========================================== + Signature 0x87974060(4) + Request len 0x00000200(4) + numbers of queue 0x00000100(4) + SDRAM Size 0x00000100(4)-->256 MB + IDE Channels 0x00000008(4) + vendor 40 bytes char + model 8 bytes char + FirmVer 16 bytes char + Device Map 16 bytes char + FirmwareVersion DWORD + + - Added for checking of + new firmware capability + ===================== ========================================== +0x02 Set Config + ->offset 0xa00 :for inbound message code message_rwbuffer + (driver send to IOP331) + + ========================= ================== + Signature 0x87974063(4) + UPPER32 of Request Frame (4)-->Driver Only + ========================= ================== +0x03 Reset (Abort all queued Command) +0x04 Stop Background Activity +0x05 Flush Cache +0x06 Start Background Activity + (re-start if background is halted) +0x07 Check If Host Command Pending + (Novell May Need This Function) +0x08 Set controller time + ->offset 0xa00 for inbound message code message_rwbuffer + (driver to IOP331) + + ====== ================== + byte 0 0xaa <-- signature + byte 1 0x55 <-- signature + byte 2 year (04) + byte 3 month (1..12) + byte 4 date (1..31) + byte 5 hour (0..23) + byte 6 minute (0..59) + byte 7 second (0..59) + ====== ================== +====== ================================================================= + + +RS-232 Interface for Areca Raid Controller +========================================== + + The low level command interface is exclusive with VT100 terminal + +1. Sequence of command execution +-------------------------------- + + (A) Header + 3 bytes sequence (0x5E, 0x01, 0x61) + + (B) Command block + variable length of data including length, + command code, data and checksum byte + + (C) Return data + variable length of data + +2. Command block +---------------- + + (A) 1st byte + command block length (low byte) + + (B) 2nd byte + command block length (high byte) + + .. Note:: command block length shouldn't > 2040 bytes, + length excludes these two bytes + + (C) 3rd byte + command code + + (D) 4th and following bytes + variable length data bytes + + depends on command code + + (E) last byte + checksum byte (sum of 1st byte until last data byte) + +3. Command code and associated data +----------------------------------- + +The following are command code defined in raid controller Command +code 0x10--0x1? are used for system level management, +no password checking is needed and should be implemented in separate +well controlled utility and not for end user access. +Command code 0x20--0x?? always check the password, +password must be entered to enable these command:: + + enum + { + GUI_SET_SERIAL=0x10, + GUI_SET_VENDOR, + GUI_SET_MODEL, + GUI_IDENTIFY, + GUI_CHECK_PASSWORD, + GUI_LOGOUT, + GUI_HTTP, + GUI_SET_ETHERNET_ADDR, + GUI_SET_LOGO, + GUI_POLL_EVENT, + GUI_GET_EVENT, + GUI_GET_HW_MONITOR, + // GUI_QUICK_CREATE=0x20, (function removed) + GUI_GET_INFO_R=0x20, + GUI_GET_INFO_V, + GUI_GET_INFO_P, + GUI_GET_INFO_S, + GUI_CLEAR_EVENT, + GUI_MUTE_BEEPER=0x30, + GUI_BEEPER_SETTING, + GUI_SET_PASSWORD, + GUI_HOST_INTERFACE_MODE, + GUI_REBUILD_PRIORITY, + GUI_MAX_ATA_MODE, + GUI_RESET_CONTROLLER, + GUI_COM_PORT_SETTING, + GUI_NO_OPERATION, + GUI_DHCP_IP, + GUI_CREATE_PASS_THROUGH=0x40, + GUI_MODIFY_PASS_THROUGH, + GUI_DELETE_PASS_THROUGH, + GUI_IDENTIFY_DEVICE, + GUI_CREATE_RAIDSET=0x50, + GUI_DELETE_RAIDSET, + GUI_EXPAND_RAIDSET, + GUI_ACTIVATE_RAIDSET, + GUI_CREATE_HOT_SPARE, + GUI_DELETE_HOT_SPARE, + GUI_CREATE_VOLUME=0x60, + GUI_MODIFY_VOLUME, + GUI_DELETE_VOLUME, + GUI_START_CHECK_VOLUME, + GUI_STOP_CHECK_VOLUME + }; + +Command description +^^^^^^^^^^^^^^^^^^^ + +GUI_SET_SERIAL + Set the controller serial# + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x10 + byte 3 password length (should be 0x0f) + byte 4-0x13 should be "ArEcATecHnoLogY" + byte 0x14--0x23 Serial number string (must be 16 bytes) + ================ ============================================= + +GUI_SET_VENDOR + Set vendor string for the controller + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x11 + byte 3 password length (should be 0x08) + byte 4-0x13 should be "ArEcAvAr" + byte 0x14--0x3B vendor string (must be 40 bytes) + ================ ============================================= + +GUI_SET_MODEL + Set the model name of the controller + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x12 + byte 3 password length (should be 0x08) + byte 4-0x13 should be "ArEcAvAr" + byte 0x14--0x1B model string (must be 8 bytes) + ================ ============================================= + +GUI_IDENTIFY + Identify device + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x13 + return "Areca RAID Subsystem " + ================ ============================================= + +GUI_CHECK_PASSWORD + Verify password + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x14 + byte 3 password length + byte 4-0x?? user password to be checked + ================ ============================================= + +GUI_LOGOUT + Logout GUI (force password checking on next command) + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x15 + ================ ============================================= + +GUI_HTTP + HTTP interface (reserved for Http proxy service)(0x16) + +GUI_SET_ETHERNET_ADDR + Set the ethernet MAC address + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x17 + byte 3 password length (should be 0x08) + byte 4-0x13 should be "ArEcAvAr" + byte 0x14--0x19 Ethernet MAC address (must be 6 bytes) + ================ ============================================= + +GUI_SET_LOGO + Set logo in HTTP + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x18 + byte 3 Page# (0/1/2/3) (0xff --> clear OEM logo) + byte 4/5/6/7 0x55/0xaa/0xa5/0x5a + byte 8 TITLE.JPG data (each page must be 2000 bytes) + + .. Note:: page0 1st 2 byte must be + actual length of the JPG file + ================ ============================================= + +GUI_POLL_EVENT + Poll If Event Log Changed + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x19 + ================ ============================================= + +GUI_GET_EVENT + Read Event + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x1a + byte 3 Event Page (0:1st page/1/2/3:last page) + ================ ============================================= + +GUI_GET_HW_MONITOR + Get HW monitor data + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x1b + byte 3 # of FANs(example 2) + byte 4 # of Voltage sensor(example 3) + byte 5 # of temperature sensor(example 2) + byte 6 # of power + byte 7/8 Fan#0 (RPM) + byte 9/10 Fan#1 + byte 11/12 Voltage#0 original value in ``*1000`` + byte 13/14 Voltage#0 value + byte 15/16 Voltage#1 org + byte 17/18 Voltage#1 + byte 19/20 Voltage#2 org + byte 21/22 Voltage#2 + byte 23 Temp#0 + byte 24 Temp#1 + byte 25 Power indicator (bit0 power#0, + bit1 power#1) + byte 26 UPS indicator + ================ ============================================= + +GUI_QUICK_CREATE + Quick create raid/volume set + + ================ ============================================== + byte 0,1 length + byte 2 command code 0x20 + byte 3/4/5/6 raw capacity + byte 7 raid level + byte 8 stripe size + byte 9 spare + byte 10/11/12/13 device mask (the devices to create raid/volume) + ================ ============================================== + + This function is removed, application like + to implement quick create function + + need to use GUI_CREATE_RAIDSET and GUI_CREATE_VOLUMESET function. + +GUI_GET_INFO_R + Get Raid Set Information + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x20 + byte 3 raidset# + ================ ============================================= + + :: + + typedef struct sGUI_RAIDSET + { + BYTE grsRaidSetName[16]; + DWORD grsCapacity; + DWORD grsCapacityX; + DWORD grsFailMask; + BYTE grsDevArray[32]; + BYTE grsMemberDevices; + BYTE grsNewMemberDevices; + BYTE grsRaidState; + BYTE grsVolumes; + BYTE grsVolumeList[16]; + BYTE grsRes1; + BYTE grsRes2; + BYTE grsRes3; + BYTE grsFreeSegments; + DWORD grsRawStripes[8]; + DWORD grsRes4; + DWORD grsRes5; // Total to 128 bytes + DWORD grsRes6; // Total to 128 bytes + } sGUI_RAIDSET, *pGUI_RAIDSET; + +GUI_GET_INFO_V + Get Volume Set Information + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x21 + byte 3 volumeset# + ================ ============================================= + + :: + + typedef struct sGUI_VOLUMESET + { + BYTE gvsVolumeName[16]; // 16 + DWORD gvsCapacity; + DWORD gvsCapacityX; + DWORD gvsFailMask; + DWORD gvsStripeSize; + DWORD gvsNewFailMask; + DWORD gvsNewStripeSize; + DWORD gvsVolumeStatus; + DWORD gvsProgress; // 32 + sSCSI_ATTR gvsScsi; + BYTE gvsMemberDisks; + BYTE gvsRaidLevel; // 8 + BYTE gvsNewMemberDisks; + BYTE gvsNewRaidLevel; + BYTE gvsRaidSetNumber; + BYTE gvsRes0; // 4 + BYTE gvsRes1[4]; // 64 bytes + } sGUI_VOLUMESET, *pGUI_VOLUMESET; + +GUI_GET_INFO_P + Get Physical Drive Information + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x22 + byte 3 drive # (from 0 to max-channels - 1) + ================ ============================================= + + :: + + typedef struct sGUI_PHY_DRV + { + BYTE gpdModelName[40]; + BYTE gpdSerialNumber[20]; + BYTE gpdFirmRev[8]; + DWORD gpdCapacity; + DWORD gpdCapacityX; // Reserved for expansion + BYTE gpdDeviceState; + BYTE gpdPioMode; + BYTE gpdCurrentUdmaMode; + BYTE gpdUdmaMode; + BYTE gpdDriveSelect; + BYTE gpdRaidNumber; // 0xff if not belongs to a raid set + sSCSI_ATTR gpdScsi; + BYTE gpdReserved[40]; // Total to 128 bytes + } sGUI_PHY_DRV, *pGUI_PHY_DRV; + +GUI_GET_INFO_S + Get System Information + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x23 + ================ ============================================= + + :: + + typedef struct sCOM_ATTR + { + BYTE comBaudRate; + BYTE comDataBits; + BYTE comStopBits; + BYTE comParity; + BYTE comFlowControl; + } sCOM_ATTR, *pCOM_ATTR; + typedef struct sSYSTEM_INFO + { + BYTE gsiVendorName[40]; + BYTE gsiSerialNumber[16]; + BYTE gsiFirmVersion[16]; + BYTE gsiBootVersion[16]; + BYTE gsiMbVersion[16]; + BYTE gsiModelName[8]; + BYTE gsiLocalIp[4]; + BYTE gsiCurrentIp[4]; + DWORD gsiTimeTick; + DWORD gsiCpuSpeed; + DWORD gsiICache; + DWORD gsiDCache; + DWORD gsiScache; + DWORD gsiMemorySize; + DWORD gsiMemorySpeed; + DWORD gsiEvents; + BYTE gsiMacAddress[6]; + BYTE gsiDhcp; + BYTE gsiBeeper; + BYTE gsiChannelUsage; + BYTE gsiMaxAtaMode; + BYTE gsiSdramEcc; // 1:if ECC enabled + BYTE gsiRebuildPriority; + sCOM_ATTR gsiComA; // 5 bytes + sCOM_ATTR gsiComB; // 5 bytes + BYTE gsiIdeChannels; + BYTE gsiScsiHostChannels; + BYTE gsiIdeHostChannels; + BYTE gsiMaxVolumeSet; + BYTE gsiMaxRaidSet; + BYTE gsiEtherPort; // 1:if ether net port supported + BYTE gsiRaid6Engine; // 1:Raid6 engine supported + BYTE gsiRes[75]; + } sSYSTEM_INFO, *pSYSTEM_INFO; + +GUI_CLEAR_EVENT + Clear System Event + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x24 + ================ ============================================= + +GUI_MUTE_BEEPER + Mute current beeper + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x30 + ================ ============================================= +GUI_BEEPER_SETTING + Disable beeper + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x31 + byte 3 0->disable, 1->enable + ================ ============================================= + +GUI_SET_PASSWORD + Change password + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x32 + byte 3 pass word length ( must <= 15 ) + byte 4 password (must be alpha-numerical) + ================ ============================================= + +GUI_HOST_INTERFACE_MODE + Set host interface mode + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x33 + byte 3 0->Independent, 1->cluster + ================ ============================================= + +GUI_REBUILD_PRIORITY + Set rebuild priority + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x34 + byte 3 0/1/2/3 (low->high) + ================ ============================================= + +GUI_MAX_ATA_MODE + Set maximum ATA mode to be used + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x35 + byte 3 0/1/2/3 (133/100/66/33) + ================ ============================================= + +GUI_RESET_CONTROLLER + Reset Controller + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x36 + * Response with VT100 screen (discard it) + ================ ============================================= + +GUI_COM_PORT_SETTING + COM port setting + + ================ ================================================= + byte 0,1 length + byte 2 command code 0x37 + byte 3 0->COMA (term port), + 1->COMB (debug port) + byte 4 0/1/2/3/4/5/6/7 + (1200/2400/4800/9600/19200/38400/57600/115200) + byte 5 data bit + (0:7 bit, 1:8 bit must be 8 bit) + byte 6 stop bit (0:1, 1:2 stop bits) + byte 7 parity (0:none, 1:off, 2:even) + byte 8 flow control + (0:none, 1:xon/xoff, 2:hardware => must use none) + ================ ================================================= + +GUI_NO_OPERATION + No operation + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x38 + ================ ============================================= + +GUI_DHCP_IP + Set DHCP option and local IP address + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x39 + byte 3 0:dhcp disabled, 1:dhcp enabled + byte 4/5/6/7 IP address + ================ ============================================= + +GUI_CREATE_PASS_THROUGH + Create pass through disk + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x40 + byte 3 device # + byte 4 scsi channel (0/1) + byte 5 scsi id (0-->15) + byte 6 scsi lun (0-->7) + byte 7 tagged queue (1 enabled) + byte 8 cache mode (1 enabled) + byte 9 max speed (0/1/2/3/4, + async/20/40/80/160 for scsi) + (0/1/2/3/4, 33/66/100/133/150 for ide ) + ================ ============================================= + +GUI_MODIFY_PASS_THROUGH + Modify pass through disk + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x41 + byte 3 device # + byte 4 scsi channel (0/1) + byte 5 scsi id (0-->15) + byte 6 scsi lun (0-->7) + byte 7 tagged queue (1 enabled) + byte 8 cache mode (1 enabled) + byte 9 max speed (0/1/2/3/4, + async/20/40/80/160 for scsi) + (0/1/2/3/4, 33/66/100/133/150 for ide ) + ================ ============================================= + +GUI_DELETE_PASS_THROUGH + Delete pass through disk + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x42 + byte 3 device# to be deleted + ================ ============================================= +GUI_IDENTIFY_DEVICE + Identify Device + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x43 + byte 3 Flash Method + (0:flash selected, 1:flash not selected) + byte 4/5/6/7 IDE device mask to be flashed + .. Note:: no response data available + ================ ============================================= + +GUI_CREATE_RAIDSET + Create Raid Set + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x50 + byte 3/4/5/6 device mask + byte 7-22 raidset name (if byte 7 == 0:use default) + ================ ============================================= + +GUI_DELETE_RAIDSET + Delete Raid Set + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x51 + byte 3 raidset# + ================ ============================================= + +GUI_EXPAND_RAIDSET + Expand Raid Set + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x52 + byte 3 raidset# + byte 4/5/6/7 device mask for expansion + byte 8/9/10 (8:0 no change, 1 change, 0xff:terminate, + 9:new raid level, + 10:new stripe size + 0/1/2/3/4/5->4/8/16/32/64/128K ) + byte 11/12/13 repeat for each volume in the raidset + ================ ============================================= + +GUI_ACTIVATE_RAIDSET + Activate incomplete raid set + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x53 + byte 3 raidset# + ================ ============================================= + +GUI_CREATE_HOT_SPARE + Create hot spare disk + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x54 + byte 3/4/5/6 device mask for hot spare creation + ================ ============================================= + +GUI_DELETE_HOT_SPARE + Delete hot spare disk + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x55 + byte 3/4/5/6 device mask for hot spare deletion + ================ ============================================= + +GUI_CREATE_VOLUME + Create volume set + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x60 + byte 3 raidset# + byte 4-19 volume set name + (if byte4 == 0, use default) + byte 20-27 volume capacity (blocks) + byte 28 raid level + byte 29 stripe size + (0/1/2/3/4/5->4/8/16/32/64/128K) + byte 30 channel + byte 31 ID + byte 32 LUN + byte 33 1 enable tag + byte 34 1 enable cache + byte 35 speed + (0/1/2/3/4->async/20/40/80/160 for scsi) + (0/1/2/3/4->33/66/100/133/150 for IDE ) + byte 36 1 to select quick init + ================ ============================================= + +GUI_MODIFY_VOLUME + Modify volume Set + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x61 + byte 3 volumeset# + byte 4-19 new volume set name + (if byte4 == 0, not change) + byte 20-27 new volume capacity (reserved) + byte 28 new raid level + byte 29 new stripe size + (0/1/2/3/4/5->4/8/16/32/64/128K) + byte 30 new channel + byte 31 new ID + byte 32 new LUN + byte 33 1 enable tag + byte 34 1 enable cache + byte 35 speed + (0/1/2/3/4->async/20/40/80/160 for scsi) + (0/1/2/3/4->33/66/100/133/150 for IDE ) + ================ ============================================= + +GUI_DELETE_VOLUME + Delete volume set + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x62 + byte 3 volumeset# + ================ ============================================= + +GUI_START_CHECK_VOLUME + Start volume consistency check + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x63 + byte 3 volumeset# + ================ ============================================= + +GUI_STOP_CHECK_VOLUME + Stop volume consistency check + + ================ ============================================= + byte 0,1 length + byte 2 command code 0x64 + ================ ============================================= + +4. Returned data +---------------- + +(A) Header + 3 bytes sequence (0x5E, 0x01, 0x61) +(B) Length + 2 bytes + (low byte 1st, excludes length and checksum byte) +(C) + status or data: + + 1) If length == 1 ==> 1 byte status code:: + + #define GUI_OK 0x41 + #define GUI_RAIDSET_NOT_NORMAL 0x42 + #define GUI_VOLUMESET_NOT_NORMAL 0x43 + #define GUI_NO_RAIDSET 0x44 + #define GUI_NO_VOLUMESET 0x45 + #define GUI_NO_PHYSICAL_DRIVE 0x46 + #define GUI_PARAMETER_ERROR 0x47 + #define GUI_UNSUPPORTED_COMMAND 0x48 + #define GUI_DISK_CONFIG_CHANGED 0x49 + #define GUI_INVALID_PASSWORD 0x4a + #define GUI_NO_DISK_SPACE 0x4b + #define GUI_CHECKSUM_ERROR 0x4c + #define GUI_PASSWORD_REQUIRED 0x4d + + 2) If length > 1: + + data block returned from controller + and the contents depends on the command code + +(E) Checksum + checksum of length and status or data byte + diff --git a/Documentation/scsi/arcmsr_spec.txt b/Documentation/scsi/arcmsr_spec.txt deleted file mode 100644 index 45d9482c1517..000000000000 --- a/Documentation/scsi/arcmsr_spec.txt +++ /dev/null @@ -1,574 +0,0 @@ -******************************************************************************* -** ARECA FIRMWARE SPEC -******************************************************************************* -** Usage of IOP331 adapter -** (All In/Out is in IOP331's view) -** 1. Message 0 --> InitThread message and return code -** 2. Doorbell is used for RS-232 emulation -** inDoorBell : bit0 -- data in ready -** (DRIVER DATA WRITE OK) -** bit1 -- data out has been read -** (DRIVER DATA READ OK) -** outDooeBell: bit0 -- data out ready -** (IOP331 DATA WRITE OK) -** bit1 -- data in has been read -** (IOP331 DATA READ OK) -** 3. Index Memory Usage -** offset 0xf00 : for RS232 out (request buffer) -** offset 0xe00 : for RS232 in (scratch buffer) -** offset 0xa00 : for inbound message code message_rwbuffer -** (driver send to IOP331) -** offset 0xa00 : for outbound message code message_rwbuffer -** (IOP331 send to driver) -** 4. RS-232 emulation -** Currently 128 byte buffer is used -** 1st uint32_t : Data length (1--124) -** Byte 4--127 : Max 124 bytes of data -** 5. PostQ -** All SCSI Command must be sent through postQ: -** (inbound queue port) Request frame must be 32 bytes aligned -** #bit27--bit31 => flag for post ccb -** #bit0--bit26 => real address (bit27--bit31) of post arcmsr_cdb -** bit31 : -** 0 : 256 bytes frame -** 1 : 512 bytes frame -** bit30 : -** 0 : normal request -** 1 : BIOS request -** bit29 : reserved -** bit28 : reserved -** bit27 : reserved -** --------------------------------------------------------------------------- -** (outbount queue port) Request reply -** #bit27--bit31 -** => flag for reply -** #bit0--bit26 -** => real address (bit27--bit31) of reply arcmsr_cdb -** bit31 : must be 0 (for this type of reply) -** bit30 : reserved for BIOS handshake -** bit29 : reserved -** bit28 : -** 0 : no error, ignore AdapStatus/DevStatus/SenseData -** 1 : Error, error code in AdapStatus/DevStatus/SenseData -** bit27 : reserved -** 6. BIOS request -** All BIOS request is the same with request from PostQ -** Except : -** Request frame is sent from configuration space -** offset: 0x78 : Request Frame (bit30 == 1) -** offset: 0x18 : writeonly to generate -** IRQ to IOP331 -** Completion of request: -** (bit30 == 0, bit28==err flag) -** 7. Definition of SGL entry (structure) -** 8. Message1 Out - Diag Status Code (????) -** 9. Message0 message code : -** 0x00 : NOP -** 0x01 : Get Config -** ->offset 0xa00 :for outbound message code message_rwbuffer -** (IOP331 send to driver) -** Signature 0x87974060(4) -** Request len 0x00000200(4) -** numbers of queue 0x00000100(4) -** SDRAM Size 0x00000100(4)-->256 MB -** IDE Channels 0x00000008(4) -** vendor 40 bytes char -** model 8 bytes char -** FirmVer 16 bytes char -** Device Map 16 bytes char -** FirmwareVersion DWORD <== Added for checking of -** new firmware capability -** 0x02 : Set Config -** ->offset 0xa00 :for inbound message code message_rwbuffer -** (driver send to IOP331) -** Signature 0x87974063(4) -** UPPER32 of Request Frame (4)-->Driver Only -** 0x03 : Reset (Abort all queued Command) -** 0x04 : Stop Background Activity -** 0x05 : Flush Cache -** 0x06 : Start Background Activity -** (re-start if background is halted) -** 0x07 : Check If Host Command Pending -** (Novell May Need This Function) -** 0x08 : Set controller time -** ->offset 0xa00 : for inbound message code message_rwbuffer -** (driver to IOP331) -** byte 0 : 0xaa <-- signature -** byte 1 : 0x55 <-- signature -** byte 2 : year (04) -** byte 3 : month (1..12) -** byte 4 : date (1..31) -** byte 5 : hour (0..23) -** byte 6 : minute (0..59) -** byte 7 : second (0..59) -******************************************************************************* -******************************************************************************* -** RS-232 Interface for Areca Raid Controller -** The low level command interface is exclusive with VT100 terminal -** -------------------------------------------------------------------- -** 1. Sequence of command execution -** -------------------------------------------------------------------- -** (A) Header : 3 bytes sequence (0x5E, 0x01, 0x61) -** (B) Command block : variable length of data including length, -** command code, data and checksum byte -** (C) Return data : variable length of data -** -------------------------------------------------------------------- -** 2. Command block -** -------------------------------------------------------------------- -** (A) 1st byte : command block length (low byte) -** (B) 2nd byte : command block length (high byte) -** note ..command block length shouldn't > 2040 bytes, -** length excludes these two bytes -** (C) 3rd byte : command code -** (D) 4th and following bytes : variable length data bytes -** depends on command code -** (E) last byte : checksum byte (sum of 1st byte until last data byte) -** -------------------------------------------------------------------- -** 3. Command code and associated data -** -------------------------------------------------------------------- -** The following are command code defined in raid controller Command -** code 0x10--0x1? are used for system level management, -** no password checking is needed and should be implemented in separate -** well controlled utility and not for end user access. -** Command code 0x20--0x?? always check the password, -** password must be entered to enable these command. -** enum -** { -** GUI_SET_SERIAL=0x10, -** GUI_SET_VENDOR, -** GUI_SET_MODEL, -** GUI_IDENTIFY, -** GUI_CHECK_PASSWORD, -** GUI_LOGOUT, -** GUI_HTTP, -** GUI_SET_ETHERNET_ADDR, -** GUI_SET_LOGO, -** GUI_POLL_EVENT, -** GUI_GET_EVENT, -** GUI_GET_HW_MONITOR, -** // GUI_QUICK_CREATE=0x20, (function removed) -** GUI_GET_INFO_R=0x20, -** GUI_GET_INFO_V, -** GUI_GET_INFO_P, -** GUI_GET_INFO_S, -** GUI_CLEAR_EVENT, -** GUI_MUTE_BEEPER=0x30, -** GUI_BEEPER_SETTING, -** GUI_SET_PASSWORD, -** GUI_HOST_INTERFACE_MODE, -** GUI_REBUILD_PRIORITY, -** GUI_MAX_ATA_MODE, -** GUI_RESET_CONTROLLER, -** GUI_COM_PORT_SETTING, -** GUI_NO_OPERATION, -** GUI_DHCP_IP, -** GUI_CREATE_PASS_THROUGH=0x40, -** GUI_MODIFY_PASS_THROUGH, -** GUI_DELETE_PASS_THROUGH, -** GUI_IDENTIFY_DEVICE, -** GUI_CREATE_RAIDSET=0x50, -** GUI_DELETE_RAIDSET, -** GUI_EXPAND_RAIDSET, -** GUI_ACTIVATE_RAIDSET, -** GUI_CREATE_HOT_SPARE, -** GUI_DELETE_HOT_SPARE, -** GUI_CREATE_VOLUME=0x60, -** GUI_MODIFY_VOLUME, -** GUI_DELETE_VOLUME, -** GUI_START_CHECK_VOLUME, -** GUI_STOP_CHECK_VOLUME -** }; -** Command description : -** GUI_SET_SERIAL : Set the controller serial# -** byte 0,1 : length -** byte 2 : command code 0x10 -** byte 3 : password length (should be 0x0f) -** byte 4-0x13 : should be "ArEcATecHnoLogY" -** byte 0x14--0x23 : Serial number string (must be 16 bytes) -** GUI_SET_VENDOR : Set vendor string for the controller -** byte 0,1 : length -** byte 2 : command code 0x11 -** byte 3 : password length (should be 0x08) -** byte 4-0x13 : should be "ArEcAvAr" -** byte 0x14--0x3B : vendor string (must be 40 bytes) -** GUI_SET_MODEL : Set the model name of the controller -** byte 0,1 : length -** byte 2 : command code 0x12 -** byte 3 : password length (should be 0x08) -** byte 4-0x13 : should be "ArEcAvAr" -** byte 0x14--0x1B : model string (must be 8 bytes) -** GUI_IDENTIFY : Identify device -** byte 0,1 : length -** byte 2 : command code 0x13 -** return "Areca RAID Subsystem " -** GUI_CHECK_PASSWORD : Verify password -** byte 0,1 : length -** byte 2 : command code 0x14 -** byte 3 : password length -** byte 4-0x?? : user password to be checked -** GUI_LOGOUT : Logout GUI (force password checking on next command) -** byte 0,1 : length -** byte 2 : command code 0x15 -** GUI_HTTP : HTTP interface (reserved for Http proxy service)(0x16) -** -** GUI_SET_ETHERNET_ADDR : Set the ethernet MAC address -** byte 0,1 : length -** byte 2 : command code 0x17 -** byte 3 : password length (should be 0x08) -** byte 4-0x13 : should be "ArEcAvAr" -** byte 0x14--0x19 : Ethernet MAC address (must be 6 bytes) -** GUI_SET_LOGO : Set logo in HTTP -** byte 0,1 : length -** byte 2 : command code 0x18 -** byte 3 : Page# (0/1/2/3) (0xff --> clear OEM logo) -** byte 4/5/6/7 : 0x55/0xaa/0xa5/0x5a -** byte 8 : TITLE.JPG data (each page must be 2000 bytes) -** note page0 1st 2 byte must be -** actual length of the JPG file -** GUI_POLL_EVENT : Poll If Event Log Changed -** byte 0,1 : length -** byte 2 : command code 0x19 -** GUI_GET_EVENT : Read Event -** byte 0,1 : length -** byte 2 : command code 0x1a -** byte 3 : Event Page (0:1st page/1/2/3:last page) -** GUI_GET_HW_MONITOR : Get HW monitor data -** byte 0,1 : length -** byte 2 : command code 0x1b -** byte 3 : # of FANs(example 2) -** byte 4 : # of Voltage sensor(example 3) -** byte 5 : # of temperature sensor(example 2) -** byte 6 : # of power -** byte 7/8 : Fan#0 (RPM) -** byte 9/10 : Fan#1 -** byte 11/12 : Voltage#0 original value in *1000 -** byte 13/14 : Voltage#0 value -** byte 15/16 : Voltage#1 org -** byte 17/18 : Voltage#1 -** byte 19/20 : Voltage#2 org -** byte 21/22 : Voltage#2 -** byte 23 : Temp#0 -** byte 24 : Temp#1 -** byte 25 : Power indicator (bit0 : power#0, -** bit1 : power#1) -** byte 26 : UPS indicator -** GUI_QUICK_CREATE : Quick create raid/volume set -** byte 0,1 : length -** byte 2 : command code 0x20 -** byte 3/4/5/6 : raw capacity -** byte 7 : raid level -** byte 8 : stripe size -** byte 9 : spare -** byte 10/11/12/13: device mask (the devices to create raid/volume) -** This function is removed, application like -** to implement quick create function -** need to use GUI_CREATE_RAIDSET and GUI_CREATE_VOLUMESET function. -** GUI_GET_INFO_R : Get Raid Set Information -** byte 0,1 : length -** byte 2 : command code 0x20 -** byte 3 : raidset# -** typedef struct sGUI_RAIDSET -** { -** BYTE grsRaidSetName[16]; -** DWORD grsCapacity; -** DWORD grsCapacityX; -** DWORD grsFailMask; -** BYTE grsDevArray[32]; -** BYTE grsMemberDevices; -** BYTE grsNewMemberDevices; -** BYTE grsRaidState; -** BYTE grsVolumes; -** BYTE grsVolumeList[16]; -** BYTE grsRes1; -** BYTE grsRes2; -** BYTE grsRes3; -** BYTE grsFreeSegments; -** DWORD grsRawStripes[8]; -** DWORD grsRes4; -** DWORD grsRes5; // Total to 128 bytes -** DWORD grsRes6; // Total to 128 bytes -** } sGUI_RAIDSET, *pGUI_RAIDSET; -** GUI_GET_INFO_V : Get Volume Set Information -** byte 0,1 : length -** byte 2 : command code 0x21 -** byte 3 : volumeset# -** typedef struct sGUI_VOLUMESET -** { -** BYTE gvsVolumeName[16]; // 16 -** DWORD gvsCapacity; -** DWORD gvsCapacityX; -** DWORD gvsFailMask; -** DWORD gvsStripeSize; -** DWORD gvsNewFailMask; -** DWORD gvsNewStripeSize; -** DWORD gvsVolumeStatus; -** DWORD gvsProgress; // 32 -** sSCSI_ATTR gvsScsi; -** BYTE gvsMemberDisks; -** BYTE gvsRaidLevel; // 8 -** BYTE gvsNewMemberDisks; -** BYTE gvsNewRaidLevel; -** BYTE gvsRaidSetNumber; -** BYTE gvsRes0; // 4 -** BYTE gvsRes1[4]; // 64 bytes -** } sGUI_VOLUMESET, *pGUI_VOLUMESET; -** GUI_GET_INFO_P : Get Physical Drive Information -** byte 0,1 : length -** byte 2 : command code 0x22 -** byte 3 : drive # (from 0 to max-channels - 1) -** typedef struct sGUI_PHY_DRV -** { -** BYTE gpdModelName[40]; -** BYTE gpdSerialNumber[20]; -** BYTE gpdFirmRev[8]; -** DWORD gpdCapacity; -** DWORD gpdCapacityX; // Reserved for expansion -** BYTE gpdDeviceState; -** BYTE gpdPioMode; -** BYTE gpdCurrentUdmaMode; -** BYTE gpdUdmaMode; -** BYTE gpdDriveSelect; -** BYTE gpdRaidNumber; // 0xff if not belongs to a raid set -** sSCSI_ATTR gpdScsi; -** BYTE gpdReserved[40]; // Total to 128 bytes -** } sGUI_PHY_DRV, *pGUI_PHY_DRV; -** GUI_GET_INFO_S : Get System Information -** byte 0,1 : length -** byte 2 : command code 0x23 -** typedef struct sCOM_ATTR -** { -** BYTE comBaudRate; -** BYTE comDataBits; -** BYTE comStopBits; -** BYTE comParity; -** BYTE comFlowControl; -** } sCOM_ATTR, *pCOM_ATTR; -** typedef struct sSYSTEM_INFO -** { -** BYTE gsiVendorName[40]; -** BYTE gsiSerialNumber[16]; -** BYTE gsiFirmVersion[16]; -** BYTE gsiBootVersion[16]; -** BYTE gsiMbVersion[16]; -** BYTE gsiModelName[8]; -** BYTE gsiLocalIp[4]; -** BYTE gsiCurrentIp[4]; -** DWORD gsiTimeTick; -** DWORD gsiCpuSpeed; -** DWORD gsiICache; -** DWORD gsiDCache; -** DWORD gsiScache; -** DWORD gsiMemorySize; -** DWORD gsiMemorySpeed; -** DWORD gsiEvents; -** BYTE gsiMacAddress[6]; -** BYTE gsiDhcp; -** BYTE gsiBeeper; -** BYTE gsiChannelUsage; -** BYTE gsiMaxAtaMode; -** BYTE gsiSdramEcc; // 1:if ECC enabled -** BYTE gsiRebuildPriority; -** sCOM_ATTR gsiComA; // 5 bytes -** sCOM_ATTR gsiComB; // 5 bytes -** BYTE gsiIdeChannels; -** BYTE gsiScsiHostChannels; -** BYTE gsiIdeHostChannels; -** BYTE gsiMaxVolumeSet; -** BYTE gsiMaxRaidSet; -** BYTE gsiEtherPort; // 1:if ether net port supported -** BYTE gsiRaid6Engine; // 1:Raid6 engine supported -** BYTE gsiRes[75]; -** } sSYSTEM_INFO, *pSYSTEM_INFO; -** GUI_CLEAR_EVENT : Clear System Event -** byte 0,1 : length -** byte 2 : command code 0x24 -** GUI_MUTE_BEEPER : Mute current beeper -** byte 0,1 : length -** byte 2 : command code 0x30 -** GUI_BEEPER_SETTING : Disable beeper -** byte 0,1 : length -** byte 2 : command code 0x31 -** byte 3 : 0->disable, 1->enable -** GUI_SET_PASSWORD : Change password -** byte 0,1 : length -** byte 2 : command code 0x32 -** byte 3 : pass word length ( must <= 15 ) -** byte 4 : password (must be alpha-numerical) -** GUI_HOST_INTERFACE_MODE : Set host interface mode -** byte 0,1 : length -** byte 2 : command code 0x33 -** byte 3 : 0->Independent, 1->cluster -** GUI_REBUILD_PRIORITY : Set rebuild priority -** byte 0,1 : length -** byte 2 : command code 0x34 -** byte 3 : 0/1/2/3 (low->high) -** GUI_MAX_ATA_MODE : Set maximum ATA mode to be used -** byte 0,1 : length -** byte 2 : command code 0x35 -** byte 3 : 0/1/2/3 (133/100/66/33) -** GUI_RESET_CONTROLLER : Reset Controller -** byte 0,1 : length -** byte 2 : command code 0x36 -** *Response with VT100 screen (discard it) -** GUI_COM_PORT_SETTING : COM port setting -** byte 0,1 : length -** byte 2 : command code 0x37 -** byte 3 : 0->COMA (term port), -** 1->COMB (debug port) -** byte 4 : 0/1/2/3/4/5/6/7 -** (1200/2400/4800/9600/19200/38400/57600/115200) -** byte 5 : data bit -** (0:7 bit, 1:8 bit : must be 8 bit) -** byte 6 : stop bit (0:1, 1:2 stop bits) -** byte 7 : parity (0:none, 1:off, 2:even) -** byte 8 : flow control -** (0:none, 1:xon/xoff, 2:hardware => must use none) -** GUI_NO_OPERATION : No operation -** byte 0,1 : length -** byte 2 : command code 0x38 -** GUI_DHCP_IP : Set DHCP option and local IP address -** byte 0,1 : length -** byte 2 : command code 0x39 -** byte 3 : 0:dhcp disabled, 1:dhcp enabled -** byte 4/5/6/7 : IP address -** GUI_CREATE_PASS_THROUGH : Create pass through disk -** byte 0,1 : length -** byte 2 : command code 0x40 -** byte 3 : device # -** byte 4 : scsi channel (0/1) -** byte 5 : scsi id (0-->15) -** byte 6 : scsi lun (0-->7) -** byte 7 : tagged queue (1 : enabled) -** byte 8 : cache mode (1 : enabled) -** byte 9 : max speed (0/1/2/3/4, -** async/20/40/80/160 for scsi) -** (0/1/2/3/4, 33/66/100/133/150 for ide ) -** GUI_MODIFY_PASS_THROUGH : Modify pass through disk -** byte 0,1 : length -** byte 2 : command code 0x41 -** byte 3 : device # -** byte 4 : scsi channel (0/1) -** byte 5 : scsi id (0-->15) -** byte 6 : scsi lun (0-->7) -** byte 7 : tagged queue (1 : enabled) -** byte 8 : cache mode (1 : enabled) -** byte 9 : max speed (0/1/2/3/4, -** async/20/40/80/160 for scsi) -** (0/1/2/3/4, 33/66/100/133/150 for ide ) -** GUI_DELETE_PASS_THROUGH : Delete pass through disk -** byte 0,1 : length -** byte 2 : command code 0x42 -** byte 3 : device# to be deleted -** GUI_IDENTIFY_DEVICE : Identify Device -** byte 0,1 : length -** byte 2 : command code 0x43 -** byte 3 : Flash Method -** (0:flash selected, 1:flash not selected) -** byte 4/5/6/7 : IDE device mask to be flashed -** note .... no response data available -** GUI_CREATE_RAIDSET : Create Raid Set -** byte 0,1 : length -** byte 2 : command code 0x50 -** byte 3/4/5/6 : device mask -** byte 7-22 : raidset name (if byte 7 == 0:use default) -** GUI_DELETE_RAIDSET : Delete Raid Set -** byte 0,1 : length -** byte 2 : command code 0x51 -** byte 3 : raidset# -** GUI_EXPAND_RAIDSET : Expand Raid Set -** byte 0,1 : length -** byte 2 : command code 0x52 -** byte 3 : raidset# -** byte 4/5/6/7 : device mask for expansion -** byte 8/9/10 : (8:0 no change, 1 change, 0xff:terminate, -** 9:new raid level, -** 10:new stripe size -** 0/1/2/3/4/5->4/8/16/32/64/128K ) -** byte 11/12/13 : repeat for each volume in the raidset -** GUI_ACTIVATE_RAIDSET : Activate incomplete raid set -** byte 0,1 : length -** byte 2 : command code 0x53 -** byte 3 : raidset# -** GUI_CREATE_HOT_SPARE : Create hot spare disk -** byte 0,1 : length -** byte 2 : command code 0x54 -** byte 3/4/5/6 : device mask for hot spare creation -** GUI_DELETE_HOT_SPARE : Delete hot spare disk -** byte 0,1 : length -** byte 2 : command code 0x55 -** byte 3/4/5/6 : device mask for hot spare deletion -** GUI_CREATE_VOLUME : Create volume set -** byte 0,1 : length -** byte 2 : command code 0x60 -** byte 3 : raidset# -** byte 4-19 : volume set name -** (if byte4 == 0, use default) -** byte 20-27 : volume capacity (blocks) -** byte 28 : raid level -** byte 29 : stripe size -** (0/1/2/3/4/5->4/8/16/32/64/128K) -** byte 30 : channel -** byte 31 : ID -** byte 32 : LUN -** byte 33 : 1 enable tag -** byte 34 : 1 enable cache -** byte 35 : speed -** (0/1/2/3/4->async/20/40/80/160 for scsi) -** (0/1/2/3/4->33/66/100/133/150 for IDE ) -** byte 36 : 1 to select quick init -** -** GUI_MODIFY_VOLUME : Modify volume Set -** byte 0,1 : length -** byte 2 : command code 0x61 -** byte 3 : volumeset# -** byte 4-19 : new volume set name -** (if byte4 == 0, not change) -** byte 20-27 : new volume capacity (reserved) -** byte 28 : new raid level -** byte 29 : new stripe size -** (0/1/2/3/4/5->4/8/16/32/64/128K) -** byte 30 : new channel -** byte 31 : new ID -** byte 32 : new LUN -** byte 33 : 1 enable tag -** byte 34 : 1 enable cache -** byte 35 : speed -** (0/1/2/3/4->async/20/40/80/160 for scsi) -** (0/1/2/3/4->33/66/100/133/150 for IDE ) -** GUI_DELETE_VOLUME : Delete volume set -** byte 0,1 : length -** byte 2 : command code 0x62 -** byte 3 : volumeset# -** GUI_START_CHECK_VOLUME : Start volume consistency check -** byte 0,1 : length -** byte 2 : command code 0x63 -** byte 3 : volumeset# -** GUI_STOP_CHECK_VOLUME : Stop volume consistency check -** byte 0,1 : length -** byte 2 : command code 0x64 -** --------------------------------------------------------------------- -** 4. Returned data -** --------------------------------------------------------------------- -** (A) Header : 3 bytes sequence (0x5E, 0x01, 0x61) -** (B) Length : 2 bytes -** (low byte 1st, excludes length and checksum byte) -** (C) status or data : -** <1> If length == 1 ==> 1 byte status code -** #define GUI_OK 0x41 -** #define GUI_RAIDSET_NOT_NORMAL 0x42 -** #define GUI_VOLUMESET_NOT_NORMAL 0x43 -** #define GUI_NO_RAIDSET 0x44 -** #define GUI_NO_VOLUMESET 0x45 -** #define GUI_NO_PHYSICAL_DRIVE 0x46 -** #define GUI_PARAMETER_ERROR 0x47 -** #define GUI_UNSUPPORTED_COMMAND 0x48 -** #define GUI_DISK_CONFIG_CHANGED 0x49 -** #define GUI_INVALID_PASSWORD 0x4a -** #define GUI_NO_DISK_SPACE 0x4b -** #define GUI_CHECKSUM_ERROR 0x4c -** #define GUI_PASSWORD_REQUIRED 0x4d -** <2> If length > 1 ==> -** data block returned from controller -** and the contents depends on the command code -** (E) Checksum : checksum of length and status or data byte -************************************************************************** diff --git a/Documentation/scsi/bfa.txt b/Documentation/scsi/bfa.rst index 3cc4d80d6092..3abc0411857d 100644 --- a/Documentation/scsi/bfa.txt +++ b/Documentation/scsi/bfa.rst @@ -1,5 +1,8 @@ -Linux driver for Brocade FC/FCOE adapters +.. SPDX-License-Identifier: GPL-2.0 +========================================= +Linux driver for Brocade FC/FCOE adapters +========================================= Supported Hardware ------------------ @@ -7,8 +10,9 @@ Supported Hardware bfa 3.0.2.2 driver supports all Brocade FC/FCOE adapters. Below is a list of adapter models with corresponding PCIIDs. - PCIID Model - + =================== =========================================== + PCIID Model + =================== =========================================== 1657:0013:1657:0014 425 4Gbps dual port FC HBA 1657:0013:1657:0014 825 8Gbps PCIe dual port FC HBA 1657:0013:103c:1742 HP 82B 8Gbps PCIedual port FC HBA @@ -26,6 +30,7 @@ adapter models with corresponding PCIIDs. 1657:0022:1657:0024 1860 16Gbps FC HBA 1657:0022:1657:0022 1860 10Gbps CNA - FCOE + =================== =========================================== Firmware download @@ -37,9 +42,11 @@ http://www.brocade.com/services-support/drivers-downloads/adapters/Linux.page and then click following respective util package link: - Version Link - + ========= ======================================================= + Version Link + ========= ======================================================= v3.0.0.0 Linux Adapter Firmware package for RHEL 6.2, SLES 11SP2 + ========= ======================================================= Configuration & Management utility download @@ -52,9 +59,11 @@ http://www.brocade.com/services-support/drivers-downloads/adapters/Linux.page and then click following respective util package link - Version Link - + ========= ======================================================= + Version Link + ========= ======================================================= v3.0.2.0 Linux Adapter Firmware package for RHEL 6.2, SLES 11SP2 + ========= ======================================================= Documentation @@ -69,10 +78,11 @@ http://www.brocade.com/services-support/drivers-downloads/adapters/Linux.page and use the following inbox and out-of-box driver version mapping to find the corresponding documentation: + ============= ================== Inbox Version Out-of-box Version - + ============= ================== v3.0.2.2 v3.0.0.0 - + ============= ================== Support ------- diff --git a/Documentation/scsi/bnx2fc.txt b/Documentation/scsi/bnx2fc.rst index 80823556d62f..2fef2dff80c7 100644 --- a/Documentation/scsi/bnx2fc.txt +++ b/Documentation/scsi/bnx2fc.rst @@ -1,3 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=========================== Operating FCoE using bnx2fc =========================== Broadcom FCoE offload through bnx2fc is full stateful hardware offload that @@ -24,6 +27,7 @@ Driver Usage Model: 2. Configure the interfaces on which bnx2fc driver has to operate on. Here are the steps to configure: + a. cd /etc/fcoe b. copy cfg-ethx to cfg-eth5 if FCoE has to be enabled on eth5. c. Repeat this for all the interfaces where FCoE has to be enabled. @@ -39,8 +43,10 @@ discovery and log into the targets. 5. "Symbolic Name" in 'fcoeadm -i' output would display if bnx2fc has claimed the interface. -Eg: -[root@bh2 ~]# fcoeadm -i + +Eg:: + + [root@bh2 ~]# fcoeadm -i Description: NetXtreme II BCM57712 10 Gigabit Ethernet Revision: 01 Manufacturer: Broadcom Corporation @@ -60,16 +66,16 @@ Eg: State: Online 6. Verify the vlan discovery is performed by running ifconfig and notice -<INTERFACE>.<VLAN>-fcoe interfaces are automatically created. + <INTERFACE>.<VLAN>-fcoe interfaces are automatically created. Refer to fcoeadm manpage for more information on fcoeadm operations to create/destroy interfaces or to display lun/target information. -NOTE: +NOTE ==== ** Broadcom FCoE capable devices implement a DCBX/LLDP client on-chip. Only one LLDP client is allowed per interface. For proper operation all host software based DCBX/LLDP clients (e.g. lldpad) must be disabled. To disable lldpad on a -given interface, run the following command: +given interface, run the following command:: -lldptool set-lldp -i <interface_name> adminStatus=disabled + lldptool set-lldp -i <interface_name> adminStatus=disabled diff --git a/Documentation/scsi/cxgb3i.txt b/Documentation/scsi/cxgb3i.rst index 7ac8032ee9b2..e01f18fbfa9f 100644 --- a/Documentation/scsi/cxgb3i.txt +++ b/Documentation/scsi/cxgb3i.rst @@ -1,4 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================================= Chelsio S3 iSCSI Driver for Linux +================================= Introduction ============ @@ -49,7 +53,8 @@ The following steps need to be taken to accelerates the open-iscsi initiator: The cxgb3i module registers a new transport class "cxgb3i" with open-iscsi. - * in the case of recompiling the kernel, the cxgb3i selection is located at + * in the case of recompiling the kernel, the cxgb3i selection is located at:: + Device Drivers SCSI device support ---> [*] SCSI low-level drivers ---> @@ -58,25 +63,26 @@ The following steps need to be taken to accelerates the open-iscsi initiator: 2. Create an interface file located under /etc/iscsi/ifaces/ for the new transport class "cxgb3i". - The content of the file should be in the following format: + The content of the file should be in the following format:: + iface.transport_name = cxgb3i iface.net_ifacename = <ethX> iface.ipaddress = <iscsi ip address> * if iface.ipaddress is specified, <iscsi ip address> needs to be either the - same as the ethX's ip address or an address on the same subnet. Make - sure the ip address is unique in the network. + same as the ethX's ip address or an address on the same subnet. Make + sure the ip address is unique in the network. 3. edit /etc/iscsi/iscsid.conf The default setting for MaxRecvDataSegmentLength (131072) is too big; - replace with a value no bigger than 15360 (for example 8192): + replace with a value no bigger than 15360 (for example 8192):: node.conn[0].iscsi.MaxRecvDataSegmentLength = 8192 * The login would fail for a normal session if MaxRecvDataSegmentLength is - too big. A error message in the format of - "cxgb3i: ERR! MaxRecvSegmentLength <X> too big. Need to be <= <Y>." - would be logged to dmesg. + too big. A error message in the format of + "cxgb3i: ERR! MaxRecvSegmentLength <X> too big. Need to be <= <Y>." + would be logged to dmesg. 4. To direct open-iscsi traffic to go through cxgb3i's accelerated path, "-I <iface file name>" option needs to be specified with most of the diff --git a/Documentation/scsi/dc395x.txt b/Documentation/scsi/dc395x.rst index 88219f96633d..d779e782b1cb 100644 --- a/Documentation/scsi/dc395x.txt +++ b/Documentation/scsi/dc395x.rst @@ -1,5 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================================== README file for the dc395x SCSI driver -========================================== +====================================== Status ------ @@ -18,14 +21,14 @@ http://lists.twibble.org/mailman/listinfo/dc395x/ Parameters ---------- -The driver uses the settings from the EEPROM set in the SCSI BIOS +The driver uses the settings from the EEPROM set in the SCSI BIOS setup. If there is no EEPROM, the driver uses default values. Both can be overridden by command line parameters (module or kernel parameters). The following parameters are available: - - safe +safe Default: 0, Acceptable values: 0 or 1 If safe is set to 1 then the adapter will use conservative @@ -33,52 +36,63 @@ The following parameters are available: shortcut for dc395x=7,4,9,15,2,10 - - adapter_id +adapter_id Default: 7, Acceptable values: 0 to 15 Sets the host adapter SCSI ID. - - max_speed +max_speed Default: 1, Acceptable value: 0 to 7 - 0 = 20 Mhz - 1 = 12.2 Mhz - 2 = 10 Mhz - 3 = 8 Mhz - 4 = 6.7 Mhz - 5 = 5.8 Hhz - 6 = 5 Mhz - 7 = 4 Mhz - - - dev_mode + + == ======== + 0 20 Mhz + 1 12.2 Mhz + 2 10 Mhz + 3 8 Mhz + 4 6.7 Mhz + 5 5.8 Hhz + 6 5 Mhz + 7 4 Mhz + == ======== + +dev_mode Bitmap for device configuration DevMode bit definition: + + === ======== ======== ========================================= 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 - *5 0x20 32 Wide Negotiation - - - adapter_mode + === ======== ======== ========================================= + 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 + 5 0x20 32 Wide Negotiation + === ======== ======== ========================================= + +adapter_mode Bitmap for adapter configuration AdaptMode bit definition + + ===== ======== ======== ==================================================== 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. + ===== ======== ======== ==================================================== + 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. + ===== ======== ======== ==================================================== - - tags +tags Default: 3, Acceptable values: 0-5 - + The number of tags is 1<<x, if x has been specified - - reset_delay +reset_delay Default: 1, Acceptable values: 0-180 The seconds to not accept commands after a SCSI Reset @@ -95,8 +109,9 @@ License (GPL). Please read it, before using this driver. It should be included in your kernel sources and with your distribution. It carries the filename COPYING. If you don't have it, please ask me to send you one by email. -Note: The GNU GPL says also something about warranty and liability. + +Note: The GNU GPL says also something about warranty and liability. Please be aware the following: While we do my best to provide a working and -reliable driver, there is a chance, that it will kill your valuable data. +reliable driver, there is a chance, that it will kill your valuable data. We refuse to take any responsibility for that. The driver is provided as-is and YOU USE IT AT YOUR OWN RESPONSIBILITY. diff --git a/Documentation/scsi/dpti.rst b/Documentation/scsi/dpti.rst new file mode 100644 index 000000000000..0496919d87d3 --- /dev/null +++ b/Documentation/scsi/dpti.rst @@ -0,0 +1,92 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================== +Adaptec dpti driver +=================== + +Redistribution and use in source form, with or without modification, are +permitted provided that redistributions of source code must retain the +above copyright notice, this list of conditions and the following disclaimer. + +This software is provided ``as is`` by Adaptec and +any express or implied warranties, including, but not limited to, the +implied warranties of merchantability and fitness for a particular purpose, +are disclaimed. In no event shall Adaptec be +liable for any direct, indirect, incidental, special, exemplary or +consequential damages (including, but not limited to, procurement of +substitute goods or services; loss of use, data, or profits; or business +interruptions) however caused and on any theory of liability, whether in +contract, strict liability, or tort (including negligence or otherwise) +arising in any way out of the use of this driver software, even if advised +of the possibility of such damage. + +This driver supports the Adaptec I2O RAID and DPT SmartRAID V I2O boards. + +Credits +======= + +The original linux driver was ported to Linux by Karen White while at +Dell Computer. It was ported from Bob Pasteur's (of DPT) original +non-Linux driver. Mark Salyzyn and Bob Pasteur consulted on the original +driver. + +2.0 version of the driver by Deanna Bonds and Mark Salyzyn. + +History +======= + +The driver was originally ported to linux version 2.0.34 + +==== ========================================================================== +V2.0 Rewrite of driver. Re-architectured based on i2o subsystem. + This was the first full GPL version since the last version used + i2osig headers which were not GPL. Developer Testing version. +V2.1 Internal testing +V2.2 First released version + +V2.3 Changes: + + - Added Raptor Support + - Fixed bug causing system to hang under extreme load with + - management utilities running (removed GFP_DMA from kmalloc flags) + +V2.4 First version ready to be submitted to be embedded in the kernel + + Changes: + + - Implemented suggestions from Alan Cox + - Added calculation of resid for sg layer + - Better error handling + - Added checking underflow conditions + - Added DATAPROTECT checking + - Changed error return codes + - Fixed pointer bug in bus reset routine + - Enabled hba reset from ioctls (allows a FW flash to reboot and use + the new FW without having to reboot) + - Changed proc output +==== ========================================================================== + +TODO +==== +- Add 64 bit Scatter Gather when compiled on 64 bit architectures +- Add sparse lun scanning +- Add code that checks if a device that had been taken offline is + now online (at the FW level) when test unit ready or inquiry + command from scsi-core +- Add proc read interface +- busrescan command +- rescan command +- Add code to rescan routine that notifies scsi-core about new devices +- Add support for C-PCI (hotplug stuff) +- Add ioctl passthru error recovery + +Notes +===== +The DPT card optimizes the order of processing commands. Consequently, +a command may take up to 6 minutes to complete after it has been sent +to the board. + +The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the +interface files for Adaptec's management routines. These define the structures used +in the ioctls. They are written to be portable. They are hard to read, but I need +to use them 'as is' or I can miss changes in the interface. diff --git a/Documentation/scsi/dpti.txt b/Documentation/scsi/dpti.txt deleted file mode 100644 index f36dc0e7c8da..000000000000 --- a/Documentation/scsi/dpti.txt +++ /dev/null @@ -1,83 +0,0 @@ - /* TERMS AND CONDITIONS OF USE - * - * Redistribution and use in source form, with or without modification, are - * permitted provided that redistributions of source code must retain the - * above copyright notice, this list of conditions and the following disclaimer. - * - * This software is provided `as is' by Adaptec and - * any express or implied warranties, including, but not limited to, the - * implied warranties of merchantability and fitness for a particular purpose, - * are disclaimed. In no event shall Adaptec be - * liable for any direct, indirect, incidental, special, exemplary or - * consequential damages (including, but not limited to, procurement of - * substitute goods or services; loss of use, data, or profits; or business - * interruptions) however caused and on any theory of liability, whether in - * contract, strict liability, or tort (including negligence or otherwise) - * arising in any way out of the use of this driver software, even if advised - * of the possibility of such damage. - * - **************************************************************** - * This driver supports the Adaptec I2O RAID and DPT SmartRAID V I2O boards. - * - * CREDITS: - * The original linux driver was ported to Linux by Karen White while at - * Dell Computer. It was ported from Bob Pasteur's (of DPT) original - * non-Linux driver. Mark Salyzyn and Bob Pasteur consulted on the original - * driver. - * - * 2.0 version of the driver by Deanna Bonds and Mark Salyzyn. - * - * HISTORY: - * The driver was originally ported to linux version 2.0.34 - * - * V2.0 Rewrite of driver. Re-architectured based on i2o subsystem. - * This was the first full GPL version since the last version used - * i2osig headers which were not GPL. Developer Testing version. - * V2.1 Internal testing - * V2.2 First released version - * - * V2.3 - * Changes: - * Added Raptor Support - * Fixed bug causing system to hang under extreme load with - * management utilities running (removed GFP_DMA from kmalloc flags) - * - * - * V2.4 First version ready to be submitted to be embedded in the kernel - * Changes: - * Implemented suggestions from Alan Cox - * Added calculation of resid for sg layer - * Better error handling - * Added checking underflow conditions - * Added DATAPROTECT checking - * Changed error return codes - * Fixed pointer bug in bus reset routine - * Enabled hba reset from ioctls (allows a FW flash to reboot and use the new - * FW without having to reboot) - * Changed proc output - * - * TODO: - * Add 64 bit Scatter Gather when compiled on 64 bit architectures - * Add sparse lun scanning - * Add code that checks if a device that had been taken offline is - * now online (at the FW level) when test unit ready or inquiry - * command from scsi-core - * Add proc read interface - * busrescan command - * rescan command - * Add code to rescan routine that notifies scsi-core about new devices - * Add support for C-PCI (hotplug stuff) - * Add ioctl passthru error recovery - * - * NOTES: - * The DPT card optimizes the order of processing commands. Consequently, - * a command may take up to 6 minutes to complete after it has been sent - * to the board. - * - * The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the - * interface files for Adaptec's management routines. These define the structures used - * in the ioctls. They are written to be portable. They are hard to read, but I need - * to use them 'as is' or I can miss changes in the interface. - * - */ - diff --git a/Documentation/scsi/g_NCR5380.rst b/Documentation/scsi/g_NCR5380.rst new file mode 100644 index 000000000000..a282059fec43 --- /dev/null +++ b/Documentation/scsi/g_NCR5380.rst @@ -0,0 +1,93 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. include:: <isonum.txt> + +========================================== +README file for the Linux g_NCR5380 driver +========================================== + +Copyright |copy| 1993 Drew Eckhard + +NCR53c400 extensions Copyright |copy| 1994,1995,1996 Kevin Lentin + +This file documents the NCR53c400 extensions by Kevin Lentin and some +enhancements to the NCR5380 core. + +This driver supports NCR5380 and NCR53c400 and compatible cards in port or +memory mapped modes. + +Use of an interrupt is recommended, if supported by the board, as this will +allow targets to disconnect and thereby improve SCSI bus utilization. + +If the irq parameter is 254 or is omitted entirely, the driver will probe +for the correct IRQ line automatically. If the irq parameter is 0 or 255 +then no IRQ will be used. + +The NCR53c400 does not support DMA but it does have Pseudo-DMA which is +supported by the driver. + +This driver provides some information on what it has detected in +/proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot +time. More info to come in the future. + +This driver works as a module. +When included as a module, parameters can be passed on the insmod/modprobe +command line: + + ============= =============================================================== + irq=xx[,...] the interrupt(s) + base=xx[,...] the port or base address(es) (for port or memory mapped, resp.) + card=xx[,...] card type(s): + + == ====================================== + 0 NCR5380, + 1 NCR53C400, + 2 NCR53C400A, + 3 Domex Technology Corp 3181E (DTC3181E) + 4 Hewlett Packard C2502 + == ====================================== + ============= =============================================================== + +These old-style parameters can support only one card: + + ============= ================================================= + ncr_irq=xx the interrupt + ncr_addr=xx the port or base address (for port or memory + mapped, resp.) + ncr_5380=1 to set up for a NCR5380 board + ncr_53c400=1 to set up for a NCR53C400 board + ncr_53c400a=1 to set up for a NCR53C400A board + dtc_3181e=1 to set up for a Domex Technology Corp 3181E board + hp_c2502=1 to set up for a Hewlett Packard C2502 board + ============= ================================================= + +E.g. Trantor T130B in its default configuration:: + + modprobe g_NCR5380 irq=5 base=0x350 card=1 + +or alternatively, using the old syntax:: + + modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_53c400=1 + +E.g. a port mapped NCR5380 board, driver to probe for IRQ:: + + modprobe g_NCR5380 base=0x350 card=0 + +or alternatively:: + + modprobe g_NCR5380 ncr_addr=0x350 ncr_5380=1 + +E.g. a memory mapped NCR53C400 board with no IRQ:: + + modprobe g_NCR5380 irq=255 base=0xc8000 card=1 + +or alternatively:: + + modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1 + +E.g. two cards, DTC3181 (in non-PnP mode) at 0x240 with no IRQ +and HP C2502 at 0x300 with IRQ 7:: + + modprobe g_NCR5380 irq=0,7 base=0x240,0x300 card=3,4 + +Kevin Lentin +K.Lentin@cs.monash.edu.au diff --git a/Documentation/scsi/g_NCR5380.txt b/Documentation/scsi/g_NCR5380.txt deleted file mode 100644 index 37b1967a00a9..000000000000 --- a/Documentation/scsi/g_NCR5380.txt +++ /dev/null @@ -1,68 +0,0 @@ -README file for the Linux g_NCR5380 driver. - -(c) 1993 Drew Eckhard -NCR53c400 extensions (c) 1994,1995,1996 Kevin Lentin - -This file documents the NCR53c400 extensions by Kevin Lentin and some -enhancements to the NCR5380 core. - -This driver supports NCR5380 and NCR53c400 and compatible cards in port or -memory mapped modes. - -Use of an interrupt is recommended, if supported by the board, as this will -allow targets to disconnect and thereby improve SCSI bus utilization. - -If the irq parameter is 254 or is omitted entirely, the driver will probe -for the correct IRQ line automatically. If the irq parameter is 0 or 255 -then no IRQ will be used. - -The NCR53c400 does not support DMA but it does have Pseudo-DMA which is -supported by the driver. - -This driver provides some information on what it has detected in -/proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot -time. More info to come in the future. - -This driver works as a module. -When included as a module, parameters can be passed on the insmod/modprobe -command line: - irq=xx[,...] the interrupt(s) - base=xx[,...] the port or base address(es) (for port or memory mapped, resp.) - card=xx[,...] card type(s): - 0 = NCR5380, - 1 = NCR53C400, - 2 = NCR53C400A, - 3 = Domex Technology Corp 3181E (DTC3181E) - 4 = Hewlett Packard C2502 - -These old-style parameters can support only one card: - ncr_irq=xx the interrupt - ncr_addr=xx the port or base address (for port or memory - mapped, resp.) - ncr_5380=1 to set up for a NCR5380 board - ncr_53c400=1 to set up for a NCR53C400 board - ncr_53c400a=1 to set up for a NCR53C400A board - dtc_3181e=1 to set up for a Domex Technology Corp 3181E board - hp_c2502=1 to set up for a Hewlett Packard C2502 board - -E.g. Trantor T130B in its default configuration: -modprobe g_NCR5380 irq=5 base=0x350 card=1 -or alternatively, using the old syntax, -modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_53c400=1 - -E.g. a port mapped NCR5380 board, driver to probe for IRQ: -modprobe g_NCR5380 base=0x350 card=0 -or alternatively, -modprobe g_NCR5380 ncr_addr=0x350 ncr_5380=1 - -E.g. a memory mapped NCR53C400 board with no IRQ: -modprobe g_NCR5380 irq=255 base=0xc8000 card=1 -or alternatively, -modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1 - -E.g. two cards, DTC3181 (in non-PnP mode) at 0x240 with no IRQ -and HP C2502 at 0x300 with IRQ 7: -modprobe g_NCR5380 irq=0,7 base=0x240,0x300 card=3,4 - -Kevin Lentin -K.Lentin@cs.monash.edu.au diff --git a/Documentation/scsi/hpsa.txt b/Documentation/scsi/hpsa.rst index 891435a72fce..340e10c6e35f 100644 --- a/Documentation/scsi/hpsa.txt +++ b/Documentation/scsi/hpsa.rst @@ -1,6 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 +========================================= HPSA - Hewlett Packard Smart Array driver ------------------------------------------ +========================================= This file describes the hpsa SCSI driver for HP Smart Array controllers. The hpsa driver is intended to supplant the cciss driver for newer @@ -11,17 +13,17 @@ driver (for logical drives) AND a SCSI driver (for tape drives). This complexity and eliminating that complexity is one of the reasons for hpsa to exist. -Supported devices: ------------------- +Supported devices +================= -Smart Array P212 -Smart Array P410 -Smart Array P410i -Smart Array P411 -Smart Array P812 -Smart Array P712m -Smart Array P711m -StorageWorks P1210m +- Smart Array P212 +- Smart Array P410 +- Smart Array P410i +- Smart Array P411 +- Smart Array P812 +- Smart Array P712m +- Smart Array P711m +- StorageWorks P1210m Additionally, older Smart Arrays may work with the hpsa driver if the kernel boot parameter "hpsa_allow_any=1" is specified, however these are not tested @@ -35,18 +37,20 @@ mode, each command completion requires an interrupt, while with "performant mode command completions indicated by a single interrupt. HPSA specific entries in /sys ------------------------------ +============================= In addition to the generic SCSI attributes available in /sys, hpsa supports the following attributes: - HPSA specific host attributes: - ------------------------------ +HPSA specific host attributes +============================= + + :: - /sys/class/scsi_host/host*/rescan - /sys/class/scsi_host/host*/firmware_revision - /sys/class/scsi_host/host*/resettable - /sys/class/scsi_host/host*/transport_mode + /sys/class/scsi_host/host*/rescan + /sys/class/scsi_host/host*/firmware_revision + /sys/class/scsi_host/host*/resettable + /sys/class/scsi_host/host*/transport_mode the host "rescan" attribute is a write only attribute. Writing to this attribute will cause the driver to scan for new, changed, or removed devices @@ -58,7 +62,7 @@ HPSA specific entries in /sys tape drives, or entire storage boxes containing pre-configured logical drives. The "firmware_revision" attribute contains the firmware version of the Smart Array. - For example: + For example:: root@host:/sys/class/scsi_host/host4# cat firmware_revision 7.14 @@ -78,16 +82,18 @@ HPSA specific entries in /sys kexec tools to warn the user if they attempt to designate a device which is unable to honor the reset_devices kernel parameter as a dump device. - HPSA specific disk attributes: - ------------------------------ +HPSA specific disk attributes +----------------------------- + + :: - /sys/class/scsi_disk/c:b:t:l/device/unique_id - /sys/class/scsi_disk/c:b:t:l/device/raid_level - /sys/class/scsi_disk/c:b:t:l/device/lunid + /sys/class/scsi_disk/c:b:t:l/device/unique_id + /sys/class/scsi_disk/c:b:t:l/device/raid_level + /sys/class/scsi_disk/c:b:t:l/device/lunid (where c:b:t:l are the controller, bus, target and lun of the device) - For example: + For example:: root@host:/sys/class/scsi_disk/4:0:0:0/device# cat unique_id 600508B1001044395355323037570F77 @@ -96,35 +102,28 @@ HPSA specific entries in /sys root@host:/sys/class/scsi_disk/4:0:0:0/device# cat raid_level RAID 0 -HPSA specific ioctls: ---------------------- +HPSA specific ioctls +==================== For compatibility with applications written for the cciss driver, many, but not all of the ioctls supported by the cciss driver are also supported by the hpsa driver. The data structures used by these are described in include/linux/cciss_ioctl.h - CCISS_DEREGDISK - CCISS_REGNEWDISK - CCISS_REGNEWD - - The above three ioctls all do exactly the same thing, which is to cause the driver - to rescan for new devices. This does exactly the same thing as writing to the - hpsa specific host "rescan" attribute. + CCISS_DEREGDISK, CCISS_REGNEWDISK, CCISS_REGNEWD + The above three ioctls all do exactly the same thing, which is to cause the driver + to rescan for new devices. This does exactly the same thing as writing to the + hpsa specific host "rescan" attribute. CCISS_GETPCIINFO - Returns PCI domain, bus, device and function and "board ID" (PCI subsystem ID). CCISS_GETDRIVVER + Returns driver version in three bytes encoded as:: - Returns driver version in three bytes encoded as: (major_version << 16) | (minor_version << 8) | (subminor_version) - CCISS_PASSTHRU - CCISS_BIG_PASSTHRU - + CCISS_PASSTHRU, CCISS_BIG_PASSTHRU Allows "BMIC" and "CISS" commands to be passed through to the Smart Array. These are used extensively by the HP Array Configuration Utility, SNMP storage agents, etc. See cciss_vol_status at http://cciss.sf.net for some examples. - diff --git a/Documentation/scsi/hptiop.txt b/Documentation/scsi/hptiop.rst index 12ecfd308e55..23ae7ae36971 100644 --- a/Documentation/scsi/hptiop.txt +++ b/Documentation/scsi/hptiop.rst @@ -1,15 +1,25 @@ -HIGHPOINT ROCKETRAID 3xxx/4xxx ADAPTER DRIVER (hptiop) +.. SPDX-License-Identifier: GPL-2.0 +.. include:: <isonum.txt> + +====================================================== +Highpoint RocketRAID 3xxx/4xxx Adapter Driver (hptiop) +====================================================== Controller Register Map -------------------------- +----------------------- -For RR44xx Intel IOP based adapters, the controller IOP is accessed via PCI BAR0 and BAR2: +For RR44xx Intel IOP based adapters, the controller IOP is accessed via PCI BAR0 and BAR2 + ============== ================================== BAR0 offset Register + ============== ================================== 0x11C5C Link Interface IRQ Set 0x11C60 Link Interface IRQ Clear + ============== ================================== + ============== ================================== BAR2 offset Register + ============== ================================== 0x10 Inbound Message Register 0 0x14 Inbound Message Register 1 0x18 Outbound Message Register 0 @@ -21,10 +31,13 @@ For RR44xx Intel IOP based adapters, the controller IOP is accessed via PCI BAR0 0x34 Outbound Interrupt Mask Register 0x40 Inbound Queue Port 0x44 Outbound Queue Port + ============== ================================== For Intel IOP based adapters, the controller IOP is accessed via PCI BAR0: + ============== ================================== BAR0 offset Register + ============== ================================== 0x10 Inbound Message Register 0 0x14 Inbound Message Register 1 0x18 Outbound Message Register 0 @@ -36,16 +49,22 @@ For Intel IOP based adapters, the controller IOP is accessed via PCI BAR0: 0x34 Outbound Interrupt Mask Register 0x40 Inbound Queue Port 0x44 Outbound Queue Port + ============== ================================== For Marvell not Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1: + ============== ================================== BAR0 offset Register + ============== ================================== 0x20400 Inbound Doorbell Register 0x20404 Inbound Interrupt Mask Register 0x20408 Outbound Doorbell Register 0x2040C Outbound Interrupt Mask Register + ============== ================================== + ============== ================================== BAR1 offset Register + ============== ================================== 0x0 Inbound Queue Head Pointer 0x4 Inbound Queue Tail Pointer 0x8 Outbound Queue Head Pointer @@ -53,14 +72,20 @@ For Marvell not Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BA 0x10 Inbound Message Register 0x14 Outbound Message Register 0x40-0x1040 Inbound Queue - 0x1040-0x2040 Outbound Queue + 0x1040-0x2040 Outbound Queue + ============== ================================== For Marvell Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1: + ============== ================================== BAR0 offset Register + ============== ================================== 0x0 IOP configuration information. + ============== ================================== + ============== =================================================== BAR1 offset Register + ============== =================================================== 0x4000 Inbound List Base Address Low 0x4004 Inbound List Base Address High 0x4018 Inbound List Write Pointer @@ -76,10 +101,11 @@ For Marvell Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1: 0x10420 CPU to PCIe Function 0 Message A 0x10480 CPU to PCIe Function 0 Doorbell 0x10484 CPU to PCIe Function 0 Doorbell Enable + ============== =================================================== I/O Request Workflow of Not Marvell Frey ------------------------------------------- +---------------------------------------- All queued requests are handled via inbound/outbound queue port. A request packet can be allocated in either IOP or host memory. @@ -124,7 +150,7 @@ of an inbound message. I/O Request Workflow of Marvell Frey --------------------------------------- +------------------------------------ All queued requests are handled via inbound/outbound list. @@ -167,13 +193,17 @@ User-level Interface The driver exposes following sysfs attributes: + ================== === ======================== NAME R/W Description + ================== === ======================== driver-version R driver version string firmware-version R firmware version string + ================== === ======================== ----------------------------------------------------------------------------- -Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved. + +Copyright |copy| 2006-2012 HighPoint Technologies, Inc. All Rights Reserved. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -181,4 +211,5 @@ Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved. GNU General Public License for more details. linux@highpoint-tech.com + http://www.highpoint-tech.com diff --git a/Documentation/scsi/index.rst b/Documentation/scsi/index.rst new file mode 100644 index 000000000000..7c5f5f8f614e --- /dev/null +++ b/Documentation/scsi/index.rst @@ -0,0 +1,51 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==================== +Linux SCSI Subsystem +==================== + +.. toctree:: + :maxdepth: 1 + + 53c700 + aacraid + advansys + aha152x + aic79xx + aic7xxx + arcmsr_spec + bfa + bnx2fc + BusLogic + cxgb3i + dc395x + dpti + FlashPoint + g_NCR5380 + hpsa + hptiop + libsas + link_power_management_policy + lpfc + megaraid + ncr53c8xx + NinjaSCSI + ppa + qlogicfas + scsi-changer + scsi_eh + scsi_fc_transport + scsi-generic + scsi_mid_low_api + scsi-parameters + scsi + sd-parameters + smartpqi + st + sym53c500_cs + sym53c8xx_2 + tcm_qla2xxx + ufs + wd719x + + scsi_transport_srp/figures diff --git a/Documentation/scsi/libsas.txt b/Documentation/scsi/libsas.rst index 8cac6492aade..7216b5d25800 100644 --- a/Documentation/scsi/libsas.txt +++ b/Documentation/scsi/libsas.rst @@ -1,5 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========= SAS Layer ---------- +========= The SAS Layer is a management infrastructure which manages SAS LLDDs. It sits between SCSI Core and SAS LLDDs. The @@ -37,16 +40,21 @@ It will then return. Then you enable your phys to actually start OOB (at which point your driver will start calling the notify_* event callbacks). -Structure descriptions: +Structure descriptions +====================== + +``struct sas_phy`` +------------------ -struct sas_phy -------------------- Normally this is statically embedded to your driver's -phy structure: - struct my_phy { - blah; - struct sas_phy sas_phy; - bleh; - }; +phy structure:: + + struct my_phy { + blah; + struct sas_phy sas_phy; + bleh; + }; + And then all the phys are an array of my_phy in your HA struct (shown below). @@ -63,94 +71,122 @@ There is a scheme where the LLDD can RW certain fields, and the SAS layer can only read such ones, and vice versa. The idea is to avoid unnecessary locking. -enabled -- must be set (0/1) -id -- must be set [0,MAX_PHYS) -class, proto, type, role, oob_mode, linkrate -- must be set -oob_mode -- you set this when OOB has finished and then notify -the SAS Layer. - -sas_addr -- this normally points to an array holding the sas -address of the phy, possibly somewhere in your my_phy -struct. - -attached_sas_addr -- set this when you (LLDD) receive an -IDENTIFY frame or a FIS frame, _before_ notifying the SAS -layer. The idea is that sometimes the LLDD may want to fake -or provide a different SAS address on that phy/port and this -allows it to do this. At best you should copy the sas -address from the IDENTIFY frame or maybe generate a SAS -address for SATA directly attached devices. The Discover -process may later change this. - -frame_rcvd -- this is where you copy the IDENTIFY/FIS frame -when you get it; you lock, copy, set frame_rcvd_size and -unlock the lock, and then call the event. It is a pointer -since there's no way to know your hw frame size _exactly_, -so you define the actual array in your phy struct and let -this pointer point to it. You copy the frame from your -DMAable memory to that area holding the lock. - -sas_prim -- this is where primitives go when they're -received. See sas.h. Grab the lock, set the primitive, -release the lock, notify. - -port -- this points to the sas_port if the phy belongs -to a port -- the LLDD only reads this. It points to the -sas_port this phy is part of. Set by the SAS Layer. - -ha -- may be set; the SAS layer sets it anyway. - -lldd_phy -- you should set this to point to your phy so you -can find your way around faster when the SAS layer calls one -of your callbacks and passes you a phy. If the sas_phy is -embedded you can also use container_of -- whatever you -prefer. - - -struct sas_port -------------------- +enabled + - must be set (0/1) + +id + - must be set [0,MAX_PHYS)] + +class, proto, type, role, oob_mode, linkrate + - must be set + +oob_mode + - you set this when OOB has finished and then notify + the SAS Layer. + +sas_addr + - this normally points to an array holding the sas + address of the phy, possibly somewhere in your my_phy + struct. + +attached_sas_addr + - set this when you (LLDD) receive an + IDENTIFY frame or a FIS frame, _before_ notifying the SAS + layer. The idea is that sometimes the LLDD may want to fake + or provide a different SAS address on that phy/port and this + allows it to do this. At best you should copy the sas + address from the IDENTIFY frame or maybe generate a SAS + address for SATA directly attached devices. The Discover + process may later change this. + +frame_rcvd + - this is where you copy the IDENTIFY/FIS frame + when you get it; you lock, copy, set frame_rcvd_size and + unlock the lock, and then call the event. It is a pointer + since there's no way to know your hw frame size _exactly_, + so you define the actual array in your phy struct and let + this pointer point to it. You copy the frame from your + DMAable memory to that area holding the lock. + +sas_prim + - this is where primitives go when they're + received. See sas.h. Grab the lock, set the primitive, + release the lock, notify. + +port + - this points to the sas_port if the phy belongs + to a port -- the LLDD only reads this. It points to the + sas_port this phy is part of. Set by the SAS Layer. + +ha + - may be set; the SAS layer sets it anyway. + +lldd_phy + - you should set this to point to your phy so you + can find your way around faster when the SAS layer calls one + of your callbacks and passes you a phy. If the sas_phy is + embedded you can also use container_of -- whatever you + prefer. + + +``struct sas_port`` +------------------- + The LLDD doesn't set any fields of this struct -- it only reads them. They should be self explanatory. phy_mask is 32 bit, this should be enough for now, as I haven't heard of a HA having more than 8 phys. -lldd_port -- I haven't found use for that -- maybe other -LLDD who wish to have internal port representation can make -use of this. +lldd_port + - I haven't found use for that -- maybe other + LLDD who wish to have internal port representation can make + use of this. +``struct sas_ha_struct`` +------------------------ -struct sas_ha_struct -------------------- It normally is statically declared in your own LLDD -structure describing your adapter: -struct my_sas_ha { - blah; - struct sas_ha_struct sas_ha; - struct my_phy phys[MAX_PHYS]; - struct sas_port sas_ports[MAX_PHYS]; /* (1) */ - bleh; -}; +structure describing your adapter:: + + struct my_sas_ha { + blah; + struct sas_ha_struct sas_ha; + struct my_phy phys[MAX_PHYS]; + struct sas_port sas_ports[MAX_PHYS]; /* (1) */ + bleh; + }; -(1) If your LLDD doesn't have its own port representation. + (1) If your LLDD doesn't have its own port representation. What needs to be initialized (sample function given below). pcidev -sas_addr -- since the SAS layer doesn't want to mess with +^^^^^^ + +sas_addr + - since the SAS layer doesn't want to mess with memory allocation, etc, this points to statically allocated array somewhere (say in your host adapter structure) and holds the SAS address of the host adapter as given by you or the manufacturer, etc. + sas_port -sas_phy -- an array of pointers to structures. (see +^^^^^^^^ + +sas_phy + - an array of pointers to structures. (see note above on sas_addr). These must be set. See more notes below. -num_phys -- the number of phys present in the sas_phy array, + +num_phys + - the number of phys present in the sas_phy array, and the number of ports present in the sas_port array. There can be a maximum num_phys ports (one per port) so we drop the num_ports, and only use num_phys. -The event interface: +The event interface:: /* LLDD calls these to notify the class of an event. */ void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event); @@ -161,7 +197,7 @@ When sas_register_ha() returns, those are set and can be called by the LLDD to notify the SAS layer of such events the SAS layer. -The port notification: +The port notification:: /* The class calls these to notify the LLDD of an event. */ void (*lldd_port_formed)(struct sas_phy *); @@ -171,7 +207,7 @@ If the LLDD wants notification when a port has been formed or deformed it sets those to a function satisfying the type. A SAS LLDD should also implement at least one of the Task -Management Functions (TMFs) described in SAM: +Management Functions (TMFs) described in SAM:: /* Task Management Functions. Must be called from process context. */ int (*lldd_abort_task)(struct sas_task *); @@ -184,7 +220,7 @@ Management Functions (TMFs) described in SAM: For more information please read SAM from T10.org. -Port and Adapter management: +Port and Adapter management:: /* Port and Adapter management */ int (*lldd_clear_nexus_port)(struct sas_port *); @@ -192,75 +228,78 @@ Port and Adapter management: A SAS LLDD should implement at least one of those. -Phy management: +Phy management:: /* Phy management */ int (*lldd_control_phy)(struct sas_phy *, enum phy_func); -lldd_ha -- set this to point to your HA struct. You can also -use container_of if you embedded it as shown above. +lldd_ha + - set this to point to your HA struct. You can also + use container_of if you embedded it as shown above. A sample initialization and registration function can look like this (called last thing from probe()) -*but* before you enable the phys to do OOB: +*but* before you enable the phys to do OOB:: -static int register_sas_ha(struct my_sas_ha *my_ha) -{ - int i; - static struct sas_phy *sas_phys[MAX_PHYS]; - static struct sas_port *sas_ports[MAX_PHYS]; + static int register_sas_ha(struct my_sas_ha *my_ha) + { + int i; + static struct sas_phy *sas_phys[MAX_PHYS]; + static struct sas_port *sas_ports[MAX_PHYS]; - my_ha->sas_ha.sas_addr = &my_ha->sas_addr[0]; + my_ha->sas_ha.sas_addr = &my_ha->sas_addr[0]; - for (i = 0; i < MAX_PHYS; i++) { - sas_phys[i] = &my_ha->phys[i].sas_phy; - sas_ports[i] = &my_ha->sas_ports[i]; - } + for (i = 0; i < MAX_PHYS; i++) { + sas_phys[i] = &my_ha->phys[i].sas_phy; + sas_ports[i] = &my_ha->sas_ports[i]; + } - my_ha->sas_ha.sas_phy = sas_phys; - my_ha->sas_ha.sas_port = sas_ports; - my_ha->sas_ha.num_phys = MAX_PHYS; + my_ha->sas_ha.sas_phy = sas_phys; + my_ha->sas_ha.sas_port = sas_ports; + my_ha->sas_ha.num_phys = MAX_PHYS; - my_ha->sas_ha.lldd_port_formed = my_port_formed; + my_ha->sas_ha.lldd_port_formed = my_port_formed; - my_ha->sas_ha.lldd_dev_found = my_dev_found; - my_ha->sas_ha.lldd_dev_gone = my_dev_gone; + my_ha->sas_ha.lldd_dev_found = my_dev_found; + my_ha->sas_ha.lldd_dev_gone = my_dev_gone; - my_ha->sas_ha.lldd_execute_task = my_execute_task; + my_ha->sas_ha.lldd_execute_task = my_execute_task; - my_ha->sas_ha.lldd_abort_task = my_abort_task; - my_ha->sas_ha.lldd_abort_task_set = my_abort_task_set; - my_ha->sas_ha.lldd_clear_aca = my_clear_aca; - my_ha->sas_ha.lldd_clear_task_set = my_clear_task_set; - my_ha->sas_ha.lldd_I_T_nexus_reset= NULL; (2) - my_ha->sas_ha.lldd_lu_reset = my_lu_reset; - my_ha->sas_ha.lldd_query_task = my_query_task; + my_ha->sas_ha.lldd_abort_task = my_abort_task; + my_ha->sas_ha.lldd_abort_task_set = my_abort_task_set; + my_ha->sas_ha.lldd_clear_aca = my_clear_aca; + my_ha->sas_ha.lldd_clear_task_set = my_clear_task_set; + my_ha->sas_ha.lldd_I_T_nexus_reset= NULL; (2) + my_ha->sas_ha.lldd_lu_reset = my_lu_reset; + my_ha->sas_ha.lldd_query_task = my_query_task; - my_ha->sas_ha.lldd_clear_nexus_port = my_clear_nexus_port; - my_ha->sas_ha.lldd_clear_nexus_ha = my_clear_nexus_ha; + my_ha->sas_ha.lldd_clear_nexus_port = my_clear_nexus_port; + my_ha->sas_ha.lldd_clear_nexus_ha = my_clear_nexus_ha; - my_ha->sas_ha.lldd_control_phy = my_control_phy; + my_ha->sas_ha.lldd_control_phy = my_control_phy; - return sas_register_ha(&my_ha->sas_ha); -} + return sas_register_ha(&my_ha->sas_ha); + } (2) SAS 1.1 does not define I_T Nexus Reset TMF. Events ------- +====== -Events are _the only way_ a SAS LLDD notifies the SAS layer +Events are **the only way** a SAS LLDD notifies the SAS layer of anything. There is no other method or way a LLDD to tell the SAS layer of anything happening internally or in the SAS domain. -Phy events: +Phy events:: + PHYE_LOSS_OF_SIGNAL, (C) PHYE_OOB_DONE, PHYE_OOB_ERROR, (C) PHYE_SPINUP_HOLD. -Port events, passed on a _phy_: +Port events, passed on a _phy_:: + PORTE_BYTES_DMAED, (M) PORTE_BROADCAST_RCVD, (E) PORTE_LINK_RESET_ERR, (C) @@ -271,6 +310,7 @@ Host Adapter event: HAE_RESET A SAS LLDD should be able to generate + - at least one event from group C (choice), - events marked M (mandatory) are mandatory (only one), - events marked E (expander) if it wants the SAS layer @@ -279,26 +319,42 @@ A SAS LLDD should be able to generate Meaning: -HAE_RESET -- when your HA got internal error and was reset. +HAE_RESET + - when your HA got internal error and was reset. + +PORTE_BYTES_DMAED + - on receiving an IDENTIFY/FIS frame + +PORTE_BROADCAST_RCVD + - on receiving a primitive + +PORTE_LINK_RESET_ERR + - timer expired, loss of signal, loss of DWS, etc. [1]_ -PORTE_BYTES_DMAED -- on receiving an IDENTIFY/FIS frame -PORTE_BROADCAST_RCVD -- on receiving a primitive -PORTE_LINK_RESET_ERR -- timer expired, loss of signal, loss -of DWS, etc. (*) -PORTE_TIMER_EVENT -- DWS reset timeout timer expired (*) -PORTE_HARD_RESET -- Hard Reset primitive received. +PORTE_TIMER_EVENT + - DWS reset timeout timer expired [1]_ -PHYE_LOSS_OF_SIGNAL -- the device is gone (*) -PHYE_OOB_DONE -- OOB went fine and oob_mode is valid -PHYE_OOB_ERROR -- Error while doing OOB, the device probably -got disconnected. (*) -PHYE_SPINUP_HOLD -- SATA is present, COMWAKE not sent. +PORTE_HARD_RESET + - Hard Reset primitive received. -(*) should set/clear the appropriate fields in the phy, - or alternatively call the inlined sas_phy_disconnected() - which is just a helper, from their tasklet. +PHYE_LOSS_OF_SIGNAL + - the device is gone [1]_ -The Execute Command SCSI RPC: +PHYE_OOB_DONE + - OOB went fine and oob_mode is valid + +PHYE_OOB_ERROR + - Error while doing OOB, the device probably + got disconnected. [1]_ + +PHYE_SPINUP_HOLD + - SATA is present, COMWAKE not sent. + +.. [1] should set/clear the appropriate fields in the phy, + or alternatively call the inlined sas_phy_disconnected() + which is just a helper, from their tasklet. + +The Execute Command SCSI RPC:: int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags); @@ -311,23 +367,28 @@ That is, when lldd_execute_task() is called, the command go out on the transport *immediately*. There is *no* queuing of any sort and at any level in a SAS LLDD. -Returns: -SAS_QUEUE_FULL, -ENOMEM, nothing was queued; - 0, the task(s) were queued. +Returns: -struct sas_task { - dev -- the device this task is destined to - task_proto -- _one_ of enum sas_proto - scatter -- pointer to scatter gather list array - num_scatter -- number of elements in scatter - total_xfer_len -- total number of bytes expected to be transferred - data_dir -- PCI_DMA_... - task_done -- callback when the task has finished execution -}; + * -SAS_QUEUE_FULL, -ENOMEM, nothing was queued; + * 0, the task(s) were queued. -DISCOVERY ---------- +:: + + struct sas_task { + dev -- the device this task is destined to + task_proto -- _one_ of enum sas_proto + scatter -- pointer to scatter gather list array + num_scatter -- number of elements in scatter + total_xfer_len -- total number of bytes expected to be transferred + data_dir -- PCI_DMA_... + task_done -- callback when the task has finished execution + }; + +Discovery +========= The sysfs tree has the following purposes: + a) It shows you the physical layout of the SAS domain at the current time, i.e. how the domain looks in the physical world right now. @@ -336,6 +397,7 @@ The sysfs tree has the following purposes: This is a link to the tree(1) program, very useful in viewing the SAS domain: ftp://mama.indstate.edu/linux/tree/ + I expect user space applications to actually create a graphical interface of this. @@ -359,7 +421,7 @@ contents of the domain_device structure, but it never creates or destroys one. Expander management from User Space ------------------------------------ +=================================== In each expander directory in sysfs, there is a file called "smp_portal". It is a binary sysfs attribute file, which @@ -371,15 +433,23 @@ Functionality is deceptively simple: 1. Build the SMP frame you want to send. The format and layout is described in the SAS spec. Leave the CRC field equal 0. + open(2) + 2. Open the expander's SMP portal sysfs file in RW mode. + write(2) + 3. Write the frame you built in 1. + read(2) + 4. Read the amount of data you expect to receive for the frame you built. If you receive different amount of data you expected to receive, then there was some kind of error. + close(2) + All this process is shown in detail in the function do_smp_func() and its callers, in the file "expander_conf.c". diff --git a/Documentation/scsi/link_power_management_policy.txt b/Documentation/scsi/link_power_management_policy.rst index d18993d01884..64288dcf10f6 100644 --- a/Documentation/scsi/link_power_management_policy.txt +++ b/Documentation/scsi/link_power_management_policy.rst @@ -1,8 +1,15 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================== +Link Power Managent Policy +========================== + This parameter allows the user to set the link (interface) power management. There are 3 possible options: +===================== ===================================================== Value Effect ----------------------------------------------------------------------------- +===================== ===================================================== min_power Tell the controller to try to make the link use the least possible power when possible. This may sacrifice some performance due to increased latency @@ -15,5 +22,4 @@ max_performance Generally, this means no power management. Tell medium_power Tell the controller to enter a lower power state when possible, but do not enter the lowest power state, thus improving latency over min_power setting. - - +===================== ===================================================== diff --git a/Documentation/scsi/lpfc.txt b/Documentation/scsi/lpfc.rst index 5741ea8aa88a..6e217e82b9b9 100644 --- a/Documentation/scsi/lpfc.txt +++ b/Documentation/scsi/lpfc.rst @@ -1,10 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 -LPFC Driver Release Notes: +========================= +LPFC Driver Release Notes +========================= -============================================================================= - - IMPORTANT: +.. important:: Starting in the 8.0.17 release, the driver began to be targeted strictly toward the upstream kernel. As such, we removed #ifdefs for older kernels @@ -22,9 +23,6 @@ LPFC Driver Release Notes: Please heed these dependencies.... - ******************************************************************** - - The following information is provided for additional background on the history of the driver as we push for upstream acceptance. @@ -64,6 +62,7 @@ Cable pull and temporary device Loss: Kernel Support +============== This source package is targeted for the upstream kernel only. (See notes at the top of this file). It relies on interfaces that are slowing @@ -77,7 +76,6 @@ Kernel Support Patches +======= Thankfully, at this time, patches are not needed. - - diff --git a/Documentation/scsi/megaraid.txt b/Documentation/scsi/megaraid.rst index 3c7cea51e687..22b75a86ba72 100644 --- a/Documentation/scsi/megaraid.txt +++ b/Documentation/scsi/megaraid.rst @@ -1,7 +1,10 @@ - Notes on Management Module - ~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. SPDX-License-Identifier: GPL-2.0 -Overview: +========================== +Notes on Management Module +========================== + +Overview -------- Different classes of controllers from LSI Logic accept and respond to the @@ -25,28 +28,32 @@ ioctl commands. But this module is envisioned to handle all user space level interactions. So any 'proc', 'sysfs' implementations will be localized in this common module. -Credits: +Credits ------- -"Shared code in a third module, a "library module", is an acceptable -solution. modprobe automatically loads dependent modules, so users -running "modprobe driver1" or "modprobe driver2" would automatically -load the shared library module." +:: + + "Shared code in a third module, a "library module", is an acceptable + solution. modprobe automatically loads dependent modules, so users + running "modprobe driver1" or "modprobe driver2" would automatically + load the shared library module." + +- Jeff Garzik (jgarzik@pobox.com), 02.25.2004 LKML - - Jeff Garzik (jgarzik@pobox.com), 02.25.2004 LKML +:: -"As Jeff hinted, if your userspace<->driver API is consistent between -your new MPT-based RAID controllers and your existing megaraid driver, -then perhaps you need a single small helper module (lsiioctl or some -better name), loaded by both mptraid and megaraid automatically, which -handles registering the /dev/megaraid node dynamically. In this case, -both mptraid and megaraid would register with lsiioctl for each -adapter discovered, and lsiioctl would essentially be a switch, -redirecting userspace tool ioctls to the appropriate driver." + "As Jeff hinted, if your userspace<->driver API is consistent between + your new MPT-based RAID controllers and your existing megaraid driver, + then perhaps you need a single small helper module (lsiioctl or some + better name), loaded by both mptraid and megaraid automatically, which + handles registering the /dev/megaraid node dynamically. In this case, + both mptraid and megaraid would register with lsiioctl for each + adapter discovered, and lsiioctl would essentially be a switch, + redirecting userspace tool ioctls to the appropriate driver." - - Matt Domsch, (Matt_Domsch@dell.com), 02.25.2004 LKML +- Matt Domsch, (Matt_Domsch@dell.com), 02.25.2004 LKML -Design: +Design ------ The Common Management Module is implemented in megaraid_mm.[ch] files. This @@ -61,7 +68,7 @@ uioc_t. The management module converts the older ioctl packets from the older applications into uioc_t. After driver handles the uioc_t, the common module will convert that back into the old format before returning to applications. -As new applications evolve and replace the old ones, the old packet format +As new applications evolve and replace the old ones, the old packet format will be retired. Common module dedicates one uioc_t packet to each controller registered. This diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.rst index 8586efff1e99..c41cec99f07c 100644 --- a/Documentation/scsi/ncr53c8xx.txt +++ b/Documentation/scsi/ncr53c8xx.rst @@ -1,106 +1,114 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================================================= The Linux NCR53C8XX/SYM53C8XX drivers README file +================================================= Written by Gerard Roudier <groudier@free.fr> + 21 Rue Carnot + 95170 DEUIL LA BARRE - FRANCE 29 May 1999 -=============================================================================== - -1. Introduction -2. Supported chips and SCSI features -3. Advantages of the enhanced 896 driver - 3.1 Optimized SCSI SCRIPTS - 3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller) -4. Memory mapped I/O versus normal I/O -5. Tagged command queueing -6. Parity checking -7. Profiling information -8. Control commands - 8.1 Set minimum synchronous period - 8.2 Set wide size - 8.3 Set maximum number of concurrent tagged commands - 8.4 Set order type for tagged command - 8.5 Set debug mode - 8.6 Clear profile counters - 8.7 Set flag (no_disc) - 8.8 Set verbose level - 8.9 Reset all logical units of a target - 8.10 Abort all tasks of all logical units of a target -9. Configuration parameters -10. Boot setup commands - 10.1 Syntax - 10.2 Available arguments - 10.2.1 Master parity checking - 10.2.2 Scsi parity checking - 10.2.3 Scsi disconnections - 10.2.4 Special features - 10.2.5 Ultra SCSI support - 10.2.6 Default number of tagged commands - 10.2.7 Default synchronous period factor - 10.2.8 Negotiate synchronous with all devices - 10.2.9 Verbosity level - 10.2.10 Debug mode - 10.2.11 Burst max - 10.2.12 LED support - 10.2.13 Max wide - 10.2.14 Differential mode - 10.2.15 IRQ mode - 10.2.16 Reverse probe - 10.2.17 Fix up PCI configuration space - 10.2.18 Serial NVRAM - 10.2.19 Check SCSI BUS - 10.2.20 Exclude a host from being attached - 10.2.21 Suggest a default SCSI id for hosts - 10.2.22 Enable use of IMMEDIATE ARBITRATION - 10.3 Advised boot setup commands - 10.4 PCI configuration fix-up boot option - 10.5 Serial NVRAM support boot option - 10.6 SCSI BUS checking boot option - 10.7 IMMEDIATE ARBITRATION boot option -11. Some constants and flags of the ncr53c8xx.h header file -12. Installation -13. Architecture dependent features -14. Known problems - 14.1 Tagged commands with Iomega Jaz device - 14.2 Device names change when another controller is added - 14.3 Using only 8 bit devices with a WIDE SCSI controller. - 14.4 Possible data corruption during a Memory Write and Invalidate - 14.5 IRQ sharing problems -15. SCSI problem troubleshooting - 15.1 Problem tracking - 15.2 Understanding hardware error reports -16. Synchronous transfer negotiation tables - 16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers - 16.2 Synchronous timings for fast SCSI-2 53C8XX controllers -17. Serial NVRAM support (by Richard Waltham) - 17.1 Features - 17.2 Symbios NVRAM layout - 17.3 Tekram NVRAM layout -18. Support for Big Endian - 18.1 Big Endian CPU - 18.2 NCR chip in Big Endian mode of operations -=============================================================================== +.. Contents: + + 1. Introduction + 2. Supported chips and SCSI features + 3. Advantages of the enhanced 896 driver + 3.1 Optimized SCSI SCRIPTS + 3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller) + 4. Memory mapped I/O versus normal I/O + 5. Tagged command queueing + 6. Parity checking + 7. Profiling information + 8. Control commands + 8.1 Set minimum synchronous period + 8.2 Set wide size + 8.3 Set maximum number of concurrent tagged commands + 8.4 Set order type for tagged command + 8.5 Set debug mode + 8.6 Clear profile counters + 8.7 Set flag (no_disc) + 8.8 Set verbose level + 8.9 Reset all logical units of a target + 8.10 Abort all tasks of all logical units of a target + 9. Configuration parameters + 10. Boot setup commands + 10.1 Syntax + 10.2 Available arguments + 10.2.1 Master parity checking + 10.2.2 Scsi parity checking + 10.2.3 Scsi disconnections + 10.2.4 Special features + 10.2.5 Ultra SCSI support + 10.2.6 Default number of tagged commands + 10.2.7 Default synchronous period factor + 10.2.8 Negotiate synchronous with all devices + 10.2.9 Verbosity level + 10.2.10 Debug mode + 10.2.11 Burst max + 10.2.12 LED support + 10.2.13 Max wide + 10.2.14 Differential mode + 10.2.15 IRQ mode + 10.2.16 Reverse probe + 10.2.17 Fix up PCI configuration space + 10.2.18 Serial NVRAM + 10.2.19 Check SCSI BUS + 10.2.20 Exclude a host from being attached + 10.2.21 Suggest a default SCSI id for hosts + 10.2.22 Enable use of IMMEDIATE ARBITRATION + 10.3 Advised boot setup commands + 10.4 PCI configuration fix-up boot option + 10.5 Serial NVRAM support boot option + 10.6 SCSI BUS checking boot option + 10.7 IMMEDIATE ARBITRATION boot option + 11. Some constants and flags of the ncr53c8xx.h header file + 12. Installation + 13. Architecture dependent features + 14. Known problems + 14.1 Tagged commands with Iomega Jaz device + 14.2 Device names change when another controller is added + 14.3 Using only 8 bit devices with a WIDE SCSI controller. + 14.4 Possible data corruption during a Memory Write and Invalidate + 14.5 IRQ sharing problems + 15. SCSI problem troubleshooting + 15.1 Problem tracking + 15.2 Understanding hardware error reports + 16. Synchronous transfer negotiation tables + 16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers + 16.2 Synchronous timings for fast SCSI-2 53C8XX controllers + 17. Serial NVRAM support (by Richard Waltham) + 17.1 Features + 17.2 Symbios NVRAM layout + 17.3 Tekram NVRAM layout + 18. Support for Big Endian + 18.1 Big Endian CPU + 18.2 NCR chip in Big Endian mode of operations 1. Introduction +=============== -The initial Linux ncr53c8xx driver has been a port of the ncr driver from +The initial Linux ncr53c8xx driver has been a port of the ncr driver from FreeBSD that has been achieved in November 1995 by: - Gerard Roudier <groudier@free.fr> + + - Gerard Roudier <groudier@free.fr> The original driver has been written for 386bsd and FreeBSD by: - Wolfgang Stanglmeier <wolf@cologne.de> - Stefan Esser <se@mi.Uni-Koeln.de> + + - Wolfgang Stanglmeier <wolf@cologne.de> + - Stefan Esser <se@mi.Uni-Koeln.de> It is now available as a bundle of 2 drivers: -- ncr53c8xx generic driver that supports all the SYM53C8XX family including +- ncr53c8xx generic driver that supports all the SYM53C8XX family including the earliest 810 rev. 1, the latest 896 (2 channel LVD SCSI controller) and the new 895A (1 channel LVD SCSI controller). -- sym53c8xx enhanced driver (a.k.a. 896 drivers) that drops support of oldest - chips in order to gain advantage of new features, as LOAD/STORE instructions - available since the 810A and hardware phase mismatch available with the +- sym53c8xx enhanced driver (a.k.a. 896 drivers) that drops support of oldest + chips in order to gain advantage of new features, as LOAD/STORE instructions + available since the 810A and hardware phase mismatch available with the 896 and the 895A. You can find technical information about the NCR 8xx family in the @@ -109,119 +117,145 @@ Drew Eckhardt. Information about new chips is available at LSILOGIC web server: - http://www.lsilogic.com/ + - http://www.lsilogic.com/ SCSI standard documentations are available at SYMBIOS ftp server: - ftp://ftp.symbios.com/ + - ftp://ftp.symbios.com/ Useful SCSI tools written by Eric Youngdale are available at tsx-11: - ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsiinfo-X.Y.tar.gz - ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsidev-X.Y.tar.gz + - ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsiinfo-X.Y.tar.gz + - ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/scsidev-X.Y.tar.gz These tools are not ALPHA but quite clean and work quite well. It is essential you have the 'scsiinfo' package. This short documentation describes the features of the generic and enhanced -drivers, configuration parameters and control commands available through +drivers, configuration parameters and control commands available through the proc SCSI file system read / write operations. This driver has been tested OK with linux/i386, Linux/Alpha and Linux/PPC. Latest driver version and patches are available at: - ftp://ftp.tux.org/pub/people/gerard-roudier + - ftp://ftp.tux.org/pub/people/gerard-roudier + or - ftp://ftp.symbios.com/mirror/ftp.tux.org/pub/tux/roudier/drivers + + - ftp://ftp.symbios.com/mirror/ftp.tux.org/pub/tux/roudier/drivers I am not a native speaker of English and there are probably lots of mistakes in this README file. Any help will be welcome. 2. Supported chips and SCSI features +==================================== The following features are supported for all chips: - Synchronous negotiation - Disconnection - Tagged command queuing - SCSI parity checking - Master parity checking + - Synchronous negotiation + - Disconnection + - Tagged command queuing + - SCSI parity checking + - Master parity checking "Wide negotiation" is supported for chips that allow it. The -following table shows some characteristics of NCR 8xx family chips +following table shows some characteristics of NCR 8xx family chips and what drivers support them. - Supported by Supported by - On board the generic the enhanced -Chip SDMS BIOS Wide SCSI std. Max. sync driver driver ----- --------- ---- --------- ---------- ------------ ------------- -810 N N FAST10 10 MB/s Y N -810A N N FAST10 10 MB/s Y Y -815 Y N FAST10 10 MB/s Y N -825 Y Y FAST10 20 MB/s Y N -825A Y Y FAST10 20 MB/s Y Y -860 N N FAST20 20 MB/s Y Y -875 Y Y FAST20 40 MB/s Y Y -876 Y Y FAST20 40 MB/s Y Y -895 Y Y FAST40 80 MB/s Y Y -895A Y Y FAST40 80 MB/s Y Y -896 Y Y FAST40 80 MB/s Y Y -897 Y Y FAST40 80 MB/s Y Y -1510D Y Y FAST40 80 MB/s Y Y -1010 Y Y FAST80 160 MB/s N Y -1010_66* Y Y FAST80 160 MB/s N Y - -* Chip supports 33MHz and 66MHz PCI buses. ++--------+-----------+-----+-----------+------------+------------+------------+ +| | | | | |Supported by|Supported by| +| |On board | | | |the generic |the enhanced| +|Chip |SDMS BIOS |Wide |SCSI std. | Max. sync |driver |driver | ++--------+-----------+-----+-----------+------------+------------+------------+ +|810 | N | N | FAST10 | 10 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+------------+ +|810A | N | N | FAST10 | 10 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|815 | Y | N | FAST10 | 10 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+------------+ +|825 | Y | Y | FAST10 | 20 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+------------+ +|825A | Y | Y | FAST10 | 20 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|860 | N | N | FAST20 | 20 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|875 | Y | Y | FAST20 | 40 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|876 | Y | Y | FAST20 | 40 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|895 | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|895A | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|896 | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|897 | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|1510D | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|1010 | Y | Y | FAST80 |160 MB/s | N | Y | ++--------+-----------+-----+-----------+------------+------------+------------+ +|1010_66 | Y | Y | FAST80 |160 MB/s | N | Y | +|[1]_ | | | | | | | ++--------+-----------+-----+-----------+------------+------------+------------+ + +.. [1] Chip supports 33MHz and 66MHz PCI buses. Summary of other supported features: -Module: allow to load the driver -Memory mapped I/O: increases performance -Profiling information: read operations from the proc SCSI file system -Control commands: write operations to the proc SCSI file system -Debugging information: written to syslog (expert only) -Scatter / gather -Shared interrupt -Boot setup commands -Serial NVRAM: Symbios and Tekram formats +:Module: allow to load the driver +:Memory mapped I/O: increases performance +:Profiling information: read operations from the proc SCSI file system +:Control commands: write operations to the proc SCSI file system +:Debugging information: written to syslog (expert only) +:Serial NVRAM: Symbios and Tekram formats + +- Scatter / gather +- Shared interrupt +- Boot setup commands 3. Advantages of the enhanced 896 driver +======================================== -3.1 Optimized SCSI SCRIPTS. +3.1 Optimized SCSI SCRIPTS +-------------------------- -The 810A, 825A, 875, 895, 896 and 895A support new SCSI SCRIPTS instructions -named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register -to/from memory much faster that the MOVE MEMORY instruction that is supported +The 810A, 825A, 875, 895, 896 and 895A support new SCSI SCRIPTS instructions +named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register +to/from memory much faster that the MOVE MEMORY instruction that is supported by the 53c7xx and 53c8xx family. -The LOAD/STORE instructions support absolute and DSA relative addressing -modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead +The LOAD/STORE instructions support absolute and DSA relative addressing +modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead of MOVE MEMORY instructions. 3.2 New features of the SYM53C896 (64 bit PCI dual LVD SCSI controller) +----------------------------------------------------------------------- -The 896 and the 895A allows handling of the phase mismatch context from -SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor +The 896 and the 895A allows handling of the phase mismatch context from +SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor until the C code has saved the context of the transfer). -Implementing this without using LOAD/STORE instructions would be painful +Implementing this without using LOAD/STORE instructions would be painful and I didn't even want to try it. -The 896 chip supports 64 bit PCI transactions and addressing, while the +The 896 chip supports 64 bit PCI transactions and addressing, while the 895A supports 32 bit PCI transactions and 64 bit addressing. -The SCRIPTS processor of these chips is not true 64 bit, but uses segment -registers for bit 32-63. Another interesting feature is that LOAD/STORE +The SCRIPTS processor of these chips is not true 64 bit, but uses segment +registers for bit 32-63. Another interesting feature is that LOAD/STORE instructions that address the on-chip RAM (8k) remain internal to the chip. -Due to the use of LOAD/STORE SCRIPTS instructions, this driver does not +Due to the use of LOAD/STORE SCRIPTS instructions, this driver does not support the following chips: + - SYM53C810 revision < 0x10 (16) - SYM53C815 all revisions - SYM53C825 revision < 0x10 (16) 4. Memory mapped I/O versus normal I/O +====================================== Memory mapped I/O has less latency than normal I/O. Since linux-1.3.x, memory mapped I/O is used rather than normal I/O. Memory @@ -233,17 +267,18 @@ driver to use normal I/O in all cases. 5. Tagged command queueing +========================== -Queuing more than 1 command at a time to a device allows it to perform -optimizations based on actual head positions and its mechanical +Queuing more than 1 command at a time to a device allows it to perform +optimizations based on actual head positions and its mechanical characteristics. This feature may also reduce average command latency. -In order to really gain advantage of this feature, devices must have -a reasonable cache size (No miracle is to be expected for a low-end +In order to really gain advantage of this feature, devices must have +a reasonable cache size (No miracle is to be expected for a low-end hard disk with 128 KB or less). Some known SCSI devices do not properly support tagged command queuing. -Generally, firmware revisions that fix this kind of problems are available +Generally, firmware revisions that fix this kind of problems are available at respective vendor web/ftp sites. -All I can say is that the hard disks I use on my machines behave well with +All I can say is that the hard disks I use on my machines behave well with this driver with tagged command queuing enabled: - IBM S12 0662 @@ -251,9 +286,9 @@ this driver with tagged command queuing enabled: - Quantum Atlas I - Quantum Atlas II -If your controller has NVRAM, you can configure this feature per target -from the user setup tool. The Tekram Setup program allows to tune the -maximum number of queued commands up to 32. The Symbios Setup only allows +If your controller has NVRAM, you can configure this feature per target +from the user setup tool. The Tekram Setup program allows to tune the +maximum number of queued commands up to 32. The Symbios Setup only allows to enable or disable this feature. The maximum number of simultaneous tagged commands queued to a device @@ -261,16 +296,16 @@ is currently set to 8 by default. This value is suitable for most SCSI disks. With large SCSI disks (>= 2GB, cache >= 512KB, average seek time <= 10 ms), using a larger value may give better performances. -The sym53c8xx driver supports up to 255 commands per device, and the -generic ncr53c8xx driver supports up to 64, but using more than 32 is -generally not worth-while, unless you are using a very large disk or disk -array. It is noticeable that most of recent hard disks seem not to accept -more than 64 simultaneous commands. So, using more than 64 queued commands +The sym53c8xx driver supports up to 255 commands per device, and the +generic ncr53c8xx driver supports up to 64, but using more than 32 is +generally not worth-while, unless you are using a very large disk or disk +array. It is noticeable that most of recent hard disks seem not to accept +more than 64 simultaneous commands. So, using more than 64 queued commands is probably just resource wasting. -If your controller does not have NVRAM or if it is managed by the SDMS -BIOS/SETUP, you can configure tagged queueing feature and device queue -depths from the boot command-line. For example: +If your controller does not have NVRAM or if it is managed by the SDMS +BIOS/SETUP, you can configure tagged queueing feature and device queue +depths from the boot command-line. For example:: ncr53c8xx=tags:4/t2t3q15-t4q7/t1u0q32 @@ -286,80 +321,85 @@ In some special conditions, some SCSI disk firmwares may return a QUEUE FULL status for a SCSI command. This behaviour is managed by the driver using the following heuristic: -- Each time a QUEUE FULL status is returned, tagged queue depth is reduced - to the actual number of disconnected commands. +- Each time a QUEUE FULL status is returned, tagged queue depth is reduced + to the actual number of disconnected commands. - Every 1000 successfully completed SCSI commands, if allowed by the current limit, the maximum number of queueable commands is incremented. -Since QUEUE FULL status reception and handling is resource wasting, the -driver notifies by default this problem to user by indicating the actual -number of commands used and their status, as well as its decision on the +Since QUEUE FULL status reception and handling is resource wasting, the +driver notifies by default this problem to user by indicating the actual +number of commands used and their status, as well as its decision on the device queue depth change. -The heuristic used by the driver in handling QUEUE FULL ensures that the -impact on performances is not too bad. You can get rid of the messages by +The heuristic used by the driver in handling QUEUE FULL ensures that the +impact on performances is not too bad. You can get rid of the messages by setting verbose level to zero, as follow: -1st method: boot your system using 'ncr53c8xx=verb:0' option. -2nd method: apply "setverbose 0" control command to the proc fs entry +1st method: + boot your system using 'ncr53c8xx=verb:0' option. + +2nd method: + apply "setverbose 0" control command to the proc fs entry corresponding to your controller after boot-up. 6. Parity checking +================== The driver supports SCSI parity checking and PCI bus master parity checking. These features must be enabled in order to ensure safe data transfers. However, some flawed devices or mother boards will have -problems with parity. You can disable either PCI parity or SCSI parity +problems with parity. You can disable either PCI parity or SCSI parity checking by entering appropriate options from the boot command line. (See 10: Boot setup commands). 7. Profiling information +======================== Profiling information is available through the proc SCSI file system. -Since gathering profiling information may impact performances, this -feature is disabled by default and requires a compilation configuration +Since gathering profiling information may impact performances, this +feature is disabled by default and requires a compilation configuration option to be set to Y. -The device associated with a host has the following pathname: +The device associated with a host has the following pathname:: /proc/scsi/ncr53c8xx/N (N=0,1,2 ....) -Generally, only 1 board is used on hardware configuration, and that device is: +Generally, only 1 board is used on hardware configuration, and that device is:: + /proc/scsi/ncr53c8xx/0 However, if the driver has been made as module, the number of the hosts is incremented each time the driver is loaded. -In order to display profiling information, just enter: +In order to display profiling information, just enter:: cat /proc/scsi/ncr53c8xx/0 -and you will get something like the following text: - -------------------------------------------------------- -General information: - Chip NCR53C810, device id 0x1, revision id 0x2 - IO port address 0x6000, IRQ number 10 - Using memory mapped IO at virtual address 0x282c000 - Synchronous transfer period 25, max commands per lun 4 -Profiling information: - num_trans = 18014 - num_kbytes = 671314 - num_disc = 25763 - num_break = 1673 - num_int = 1685 - num_fly = 18038 - ms_setup = 4940 - ms_data = 369940 - ms_disc = 183090 - ms_post = 1320 -------------------------------------------------------- +and you will get something like the following text:: + + General information: + Chip NCR53C810, device id 0x1, revision id 0x2 + IO port address 0x6000, IRQ number 10 + Using memory mapped IO at virtual address 0x282c000 + Synchronous transfer period 25, max commands per lun 4 + Profiling information: + num_trans = 18014 + num_kbytes = 671314 + num_disc = 25763 + num_break = 1673 + num_int = 1685 + num_fly = 18038 + ms_setup = 4940 + ms_data = 369940 + ms_disc = 183090 + ms_post = 1320 General information is easy to understand. The device ID and the revision ID identify the SCSI chip as follows: +======= ============= =========== Chip Device id Revision Id ----- --------- ----------- +======= ============= =========== 810 0x1 < 0x10 810A 0x1 >= 0x10 815 0x4 @@ -368,6 +408,7 @@ Chip Device id Revision Id 825A 0x3 >= 0x10 875 0xf 895 0xc +======= ============= =========== The profiling information is updated upon completion of SCSI commands. A data structure is allocated and zeroed when the host adapter is @@ -425,15 +466,16 @@ Due to the 1/100 second tick of the system clock, "ms_post" time may be wrong. In the example above, we got 18038 interrupts "on the fly" and only -1673 script breaks generally due to disconnections inside a segment +1673 script breaks generally due to disconnections inside a segment of the scatter list. 8. Control commands +=================== Control commands can be sent to the driver with write operations to the proc SCSI file system. The generic command syntax is the -following: +following:: echo "<verb> <parameters>" >/proc/scsi/ncr53c8xx/0 (assumes controller number is 0) @@ -444,66 +486,81 @@ apply to all targets of the SCSI chain (except the controller). Available commands: 8.1 Set minimum synchronous period factor +----------------------------------------- setsync <target> <period factor> - target: target number - period: minimum synchronous period. + :target: target number + :period: minimum synchronous period. Maximum speed = 1000/(4*period factor) except for special cases below. Specify a period of 255, to force asynchronous transfer mode. - 10 means 25 nano-seconds synchronous period - 11 means 30 nano-seconds synchronous period - 12 means 50 nano-seconds synchronous period + - 10 means 25 nano-seconds synchronous period + - 11 means 30 nano-seconds synchronous period + - 12 means 50 nano-seconds synchronous period 8.2 Set wide size +----------------- setwide <target> <size> - target: target number - size: 0=8 bits, 1=16bits + :target: target number + :size: 0=8 bits, 1=16bits 8.3 Set maximum number of concurrent tagged commands - +---------------------------------------------------- + settags <target> <tags> - target: target number - tags: number of concurrent tagged commands + :target: target number + :tags: number of concurrent tagged commands must not be greater than SCSI_NCR_MAX_TAGS (default: 8) 8.4 Set order type for tagged command +------------------------------------- setorder <order> - order: 3 possible values: - simple: use SIMPLE TAG for all operations (read and write) - ordered: use ORDERED TAG for all operations - default: use default tag type, + :order: 3 possible values: + + simple: + use SIMPLE TAG for all operations (read and write) + + ordered: + use ORDERED TAG for all operations + + default: + use default tag type, SIMPLE TAG for read operations ORDERED TAG for write operations 8.5 Set debug mode +------------------ setdebug <list of debug flags> Available debug flags: - alloc: print info about memory allocations (ccb, lcb) - queue: print info about insertions into the command start queue - result: print sense data on CHECK CONDITION status - scatter: print info about the scatter process - scripts: print info about the script binding process - tiny: print minimal debugging information - timing: print timing information of the NCR chip - nego: print information about SCSI negotiations - phase: print information on script interruptions + + ======== ======================================================== + alloc print info about memory allocations (ccb, lcb) + queue print info about insertions into the command start queue + result print sense data on CHECK CONDITION status + scatter print info about the scatter process + scripts print info about the script binding process + tiny print minimal debugging information + timing print timing information of the NCR chip + nego print information about SCSI negotiations + phase print information on script interruptions + ======== ======================================================== Use "setdebug" with no argument to reset debug flags. 8.6 Clear profile counters +-------------------------- clearprof @@ -513,7 +570,8 @@ Available commands: 8.7 Set flag (no_disc) - +---------------------- + setflag <target> <flag> target: target number @@ -523,38 +581,47 @@ Available commands: no_disc: not allow target to disconnect. Do not specify any flag in order to reset the flag. For example: - - setflag 4 + + setflag 4 will reset no_disc flag for target 4, so will allow it disconnections. - - setflag all + + setflag all will allow disconnection for all devices on the SCSI bus. 8.8 Set verbose level +--------------------- setverbose #level - The driver default verbose level is 1. This command allows to change + The driver default verbose level is 1. This command allows to change th driver verbose level after boot-up. 8.9 Reset all logical units of a target +--------------------------------------- resetdev <target> - target: target number + :target: target number + The driver will try to send a BUS DEVICE RESET message to the target. (Only supported by the SYM53C8XX driver and provided for test purpose) 8.10 Abort all tasks of all logical units of a target +----------------------------------------------------- cleardev <target> - target: target number - The driver will try to send a ABORT message to all the logical units + :target: target number + + The driver will try to send a ABORT message to all the logical units of the target. + (Only supported by the SYM53C8XX driver and provided for test purpose) 9. Configuration parameters +=========================== If the firmware of all your devices is perfect enough, all the features supported by the driver can be enabled at start-up. However, @@ -564,6 +631,7 @@ this feature after boot-up only for devices that support it safely. CONFIG_SCSI_NCR53C8XX_IOMAPPED (default answer: n) Answer "y" if you suspect your mother board to not allow memory mapped I/O. + May slow down performance a little. This option is required by Linux/PPC and is used no matter what you select here. Linux/PPC suffers no performance loss with this option since all IO is memory @@ -573,35 +641,37 @@ CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS (default answer: 8) Default tagged command queue depth. CONFIG_SCSI_NCR53C8XX_MAX_TAGS (default answer: 8) - This option allows you to specify the maximum number of tagged commands + This option allows you to specify the maximum number of tagged commands that can be queued to a device. The maximum supported value is 32. CONFIG_SCSI_NCR53C8XX_SYNC (default answer: 5) - This option allows you to specify the frequency in MHz the driver + This option allows you to specify the frequency in MHz the driver will use at boot time for synchronous data transfer negotiations. This frequency can be changed later with the "setsync" control command. 0 means "asynchronous data transfers". CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO (default answer: n) Force synchronous negotiation for all SCSI-2 devices. - Some SCSI-2 devices do not report this feature in byte 7 of inquiry + + Some SCSI-2 devices do not report this feature in byte 7 of inquiry response but do support it properly (TAMARACK scanners for example). CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT (default and only reasonable answer: n) If you suspect a device of yours does not properly support disconnections, - you can answer "y". Then, all SCSI devices will never disconnect the bus + you can answer "y". Then, all SCSI devices will never disconnect the bus even while performing long SCSI operations. CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT - Genuine SYMBIOS boards use GPIO0 in output for controller LED and GPIO3 + Genuine SYMBIOS boards use GPIO0 in output for controller LED and GPIO3 bit as a flag indicating singled-ended/differential interface. If all the boards of your system are genuine SYMBIOS boards or use BIOS and drivers from SYMBIOS, you would want to enable this option. - This option must NOT be enabled if your system has at least one 53C8XX + + This option must NOT be enabled if your system has at least one 53C8XX based scsi board with a vendor-specific BIOS. - For example, Tekram DC-390/U, DC-390/W and DC-390/F scsi controllers - use a vendor-specific BIOS and are known to not use SYMBIOS compatible - GPIO wiring. So, this option must not be enabled if your system has + For example, Tekram DC-390/U, DC-390/W and DC-390/F scsi controllers + use a vendor-specific BIOS and are known to not use SYMBIOS compatible + GPIO wiring. So, this option must not be enabled if your system has such a board installed. CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT @@ -610,7 +680,7 @@ CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT systems with more than one Symbios compatible controller where at least one has a serial NVRAM, or for a system with a mixture of Symbios and Tekram cards. Enables setting the boot order of host adaptors - to something other than the default order or "reverse probe" order. + to something other than the default order or "reverse probe" order. Also enables Symbios and Tekram cards to be distinguished so CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT may be set in a system with a mixture of Symbios and Tekram cards so the Symbios cards can make use of @@ -618,243 +688,364 @@ CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT causing problems for the Tekram card(s). 10. Boot setup commands +======================= 10.1 Syntax +----------- -Setup commands can be passed to the driver either at boot time or as a +Setup commands can be passed to the driver either at boot time or as a string variable using 'insmod'. -A boot setup command for the ncr53c8xx (sym53c8xx) driver begins with the -driver name "ncr53c8xx="(sym53c8xx). The kernel syntax parser then expects -an optional list of integers separated with comma followed by an optional -list of comma-separated strings. Example of boot setup command under lilo -prompt: +A boot setup command for the ncr53c8xx (sym53c8xx) driver begins with the +driver name "ncr53c8xx="(sym53c8xx). The kernel syntax parser then expects +an optional list of integers separated with comma followed by an optional +list of comma-separated strings. Example of boot setup command under lilo +prompt:: -lilo: linux root=/dev/hda2 ncr53c8xx=tags:4,sync:10,debug:0x200 + lilo: linux root=/dev/hda2 ncr53c8xx=tags:4,sync:10,debug:0x200 - enable tagged commands, up to 4 tagged commands queued. - set synchronous negotiation speed to 10 Mega-transfers / second. - set DEBUG_NEGO flag. -Since comma seems not to be allowed when defining a string variable using -'insmod', the driver also accepts <space> as option separator. -The following command will install driver module with the same options as -above. +Since comma seems not to be allowed when defining a string variable using +'insmod', the driver also accepts <space> as option separator. +The following command will install driver module with the same options as +above:: insmod ncr53c8xx.o ncr53c8xx="tags:4 sync:10 debug:0x200" -For the moment, the integer list of arguments is discarded by the driver. +For the moment, the integer list of arguments is discarded by the driver. It will be used in the future in order to allow a per controller setup. -Each string argument must be specified as "keyword:value". Only lower-case +Each string argument must be specified as "keyword:value". Only lower-case characters and digits are allowed. -In a system that contains multiple 53C8xx adapters insmod will install the +In a system that contains multiple 53C8xx adapters insmod will install the specified driver on each adapter. To exclude a chip use the 'excl' keyword. -The sequence of commands, +The sequence of commands:: insmod sym53c8xx sym53c8xx=excl:0x1400 insmod ncr53c8xx -installs the sym53c8xx driver on all adapters except the one at IO port -address 0x1400 and then installs the ncr53c8xx driver to the adapter at IO +installs the sym53c8xx driver on all adapters except the one at IO port +address 0x1400 and then installs the ncr53c8xx driver to the adapter at IO port address 0x1400. 10.2 Available arguments +------------------------ 10.2.1 Master parity checking +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ======== mpar:y enabled mpar:n disabled + ====== ======== 10.2.2 Scsi parity checking +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ======== spar:y enabled spar:n disabled + ====== ======== 10.2.3 Scsi disconnections +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ======== disc:y enabled disc:n disabled - + ====== ======== + 10.2.4 Special features +^^^^^^^^^^^^^^^^^^^^^^^^ + Only apply to 810A, 825A, 860, 875 and 895 controllers. Have no effect with other ones. + + ======= ================================================= specf:y (or 1) enabled specf:n (or 0) disabled specf:3 enabled except Memory Write And Invalidate - The default driver setup is 'specf:3'. As a consequence, option 'specf:y' - must be specified in the boot setup command to enable Memory Write And + ======= ================================================= + + The default driver setup is 'specf:3'. As a consequence, option 'specf:y' + must be specified in the boot setup command to enable Memory Write And Invalidate. 10.2.5 Ultra SCSI support +^^^^^^^^^^^^^^^^^^^^^^^^^^ + Only apply to 860, 875, 895, 895a, 896, 1010 and 1010_66 controllers. Have no effect with other ones. + + ======= ======================== ultra:n All ultra speeds enabled ultra:2 Ultra2 enabled ultra:1 Ultra enabled ultra:0 Ultra speeds disabled + ======= ======================== 10.2.6 Default number of tagged commands +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ======================= =============================== tags:0 (or tags:1 ) tagged command queuing disabled tags:#tags (#tags > 1) tagged command queuing enabled + ======================= =============================== + #tags will be truncated to the max queued commands configuration parameter. - This option also allows to specify a command queue depth for each device + This option also allows to specify a command queue depth for each device that support tagged command queueing. - Example: + + Example:: + ncr53c8xx=tags:10/t2t3q16-t5q24/t1u2q32 - will set devices queue depth as follow: + + will set devices queue depth as follow: + - controller #0 target #2 and target #3 -> 16 commands, - controller #0 target #5 -> 24 commands, - controller #1 target #1 logical unit #2 -> 32 commands, - all other logical units (all targets, all controllers) -> 10 commands. 10.2.7 Default synchronous period factor - sync:255 disabled (asynchronous transfer mode) - sync:#factor - #factor = 10 Ultra-2 SCSI 40 Mega-transfers / second - #factor = 11 Ultra-2 SCSI 33 Mega-transfers / second - #factor < 25 Ultra SCSI 20 Mega-transfers / second - #factor < 50 Fast SCSI-2 - - In all cases, the driver will use the minimum transfer period supported by +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +============ ======================================================== +sync:255 disabled (asynchronous transfer mode) +sync:#factor + ============ ======================================= + #factor = 10 Ultra-2 SCSI 40 Mega-transfers / second + #factor = 11 Ultra-2 SCSI 33 Mega-transfers / second + #factor < 25 Ultra SCSI 20 Mega-transfers / second + #factor < 50 Fast SCSI-2 + ============ ======================================= +============ ======================================================== + + In all cases, the driver will use the minimum transfer period supported by controllers according to NCR53C8XX chip type. 10.2.8 Negotiate synchronous with all devices +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (force sync nego) + + ===== ========= fsn:y enabled fsn:n disabled + ===== ========= 10.2.9 Verbosity level +^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ========= verb:0 minimal verb:1 normal verb:2 too much + ====== ========= 10.2.10 Debug mode - debug:0 clear debug flags - debug:#x set debug flags - #x is an integer value combining the following power-of-2 values: - DEBUG_ALLOC 0x1 - DEBUG_PHASE 0x2 - DEBUG_POLL 0x4 - DEBUG_QUEUE 0x8 - DEBUG_RESULT 0x10 - DEBUG_SCATTER 0x20 - DEBUG_SCRIPT 0x40 - DEBUG_TINY 0x80 - DEBUG_TIMING 0x100 - DEBUG_NEGO 0x200 - DEBUG_TAGS 0x400 - DEBUG_FREEZE 0x800 - DEBUG_RESTART 0x1000 - - You can play safely with DEBUG_NEGO. However, some of these flags may - generate bunches of syslog messages. +^^^^^^^^^^^^^^^^^^ + +======== ================================================================== +debug:0 clear debug flags +debug:#x set debug flags + + #x is an integer value combining the following power-of-2 values: + + ============= ====== + DEBUG_ALLOC 0x1 + DEBUG_PHASE 0x2 + DEBUG_POLL 0x4 + DEBUG_QUEUE 0x8 + DEBUG_RESULT 0x10 + DEBUG_SCATTER 0x20 + DEBUG_SCRIPT 0x40 + DEBUG_TINY 0x80 + DEBUG_TIMING 0x100 + DEBUG_NEGO 0x200 + DEBUG_TAGS 0x400 + DEBUG_FREEZE 0x800 + DEBUG_RESTART 0x1000 + ============= ====== +======== ================================================================== + + You can play safely with DEBUG_NEGO. However, some of these flags may + generate bunches of syslog messages. 10.2.11 Burst max - burst:0 burst disabled - burst:255 get burst length from initial IO register settings. - burst:#x burst enabled (1<<#x burst transfers max) - #x is an integer value which is log base 2 of the burst transfers max. - The NCR53C875 and NCR53C825A support up to 128 burst transfers (#x = 7). - Other chips only support up to 16 (#x = 4). - This is a maximum value. The driver set the burst length according to chip - and revision ids. By default the driver uses the maximum value supported - by the chip. +^^^^^^^^^^^^^^^^^ + +========= ================================================================== +burst:0 burst disabled +burst:255 get burst length from initial IO register settings. +burst:#x burst enabled (1<<#x burst transfers max) + + #x is an integer value which is log base 2 of the burst transfers + max. + + The NCR53C875 and NCR53C825A support up to 128 burst transfers + (#x = 7). + + Other chips only support up to 16 (#x = 4). + + This is a maximum value. The driver set the burst length according + to chip and revision ids. By default the driver uses the maximum + value supported by the chip. +========= ================================================================== 10.2.12 LED support +^^^^^^^^^^^^^^^^^^^ + + ===== =================== led:1 enable LED support led:0 disable LED support + ===== =================== + Donnot enable LED support if your scsi board does not use SDMS BIOS. (See 'Configuration parameters') 10.2.13 Max wide +^^^^^^^^^^^^^^^^ + + ====== =================== wide:1 wide scsi enabled wide:0 wide scsi disabled + ====== =================== + Some scsi boards use a 875 (ultra wide) and only supply narrow connectors. - If you have connected a wide device with a 50 pins to 68 pins cable + If you have connected a wide device with a 50 pins to 68 pins cable converter, any accepted wide negotiation will break further data transfers. - In such a case, using "wide:0" in the bootup command will be helpful. + In such a case, using "wide:0" in the bootup command will be helpful. 10.2.14 Differential mode +^^^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ================================= diff:0 never set up diff mode diff:1 set up diff mode if BIOS set it diff:2 always set up diff mode diff:3 set diff mode if GPIO3 is not set + ====== ================================= 10.2.15 IRQ mode +^^^^^^^^^^^^^^^^ + + ========= ======================================================== irqm:0 always open drain irqm:1 same as initial settings (assumed BIOS settings) irqm:2 always totem pole irqm:0x10 driver will not use IRQF_SHARED flag when requesting irq + ========= ======================================================== (Bits 0x10 and 0x20 can be combined with hardware irq mode option) 10.2.16 Reverse probe +^^^^^^^^^^^^^^^^^^^^^ + + ========= ======================================================== revprob:n probe chip ids from the PCI configuration in this order: 810, 815, 820, 860, 875, 885, 895, 896 revprob:y probe chip ids in the reverse order. + ========= ======================================================== 10.2.17 Fix up PCI configuration space +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pcifix:<option bits> Available option bits: - 0x0: No attempt to fix PCI configuration space registers values. - 0x1: Set PCI cache-line size register if not set. - 0x2: Set write and invalidate bit in PCI command register. - 0x4: Increase if necessary PCI latency timer according to burst max. + + === =============================================================== + 0x0 No attempt to fix PCI configuration space registers values. + 0x1 Set PCI cache-line size register if not set. + 0x2 Set write and invalidate bit in PCI command register. + 0x4 Increase if necessary PCI latency timer according to burst max. + === =============================================================== Use 'pcifix:7' in order to allow the driver to fix up all PCI features. 10.2.18 Serial NVRAM +^^^^^^^^^^^^^^^^^^^^ + + ======= ========================================= nvram:n do not look for serial NVRAM nvram:y test controllers for onboard serial NVRAM + ======= ========================================= + (alternate binary form) mvram=<bits options> + + ==== ================================================================= 0x01 look for NVRAM (equivalent to nvram=y) 0x02 ignore NVRAM "Synchronous negotiation" parameters for all devices 0x04 ignore NVRAM "Wide negotiation" parameter for all devices 0x08 ignore NVRAM "Scan at boot time" parameter for all devices 0x80 also attach controllers set to OFF in the NVRAM (sym53c8xx only) + ==== ================================================================= + +10.2.19 Check SCSI BUS +^^^^^^^^^^^^^^^^^^^^^^ -10.2.19 Check SCSI BUS buschk:<option bits> Available option bits: + + ==== ================================================ 0x0: No check. - 0x1: Check and do not attach the controller on error. + 0x1: Check and do not attach the controller on error. 0x2: Check and just warn on error. 0x4: Disable SCSI bus integrity checking. + ==== ================================================ 10.2.20 Exclude a host from being attached +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + excl=<io_address> Prevent host at a given io address from being attached. - For example 'ncr53c8xx=excl:0xb400,excl:0xc000' indicate to the + For example 'ncr53c8xx=excl:0xb400,excl:0xc000' indicate to the ncr53c8xx driver not to attach hosts at address 0xb400 and 0xc000. 10.2.21 Suggest a default SCSI id for hosts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ========== ========================================== hostid:255 no id suggested. - hostid:#x (0 < x < 7) x suggested for hosts SCSI id. + hostid:#x (0 < x < 7) x suggested for hosts SCSI id. + ========== ========================================== - If a host SCSI id is available from the NVRAM, the driver will ignore - any value suggested as boot option. Otherwise, if a suggested value - different from 255 has been supplied, it will use it. Otherwise, it will - try to deduce the value previously set in the hardware and use value + If a host SCSI id is available from the NVRAM, the driver will ignore + any value suggested as boot option. Otherwise, if a suggested value + different from 255 has been supplied, it will use it. Otherwise, it will + try to deduce the value previously set in the hardware and use value 7 if the hardware value is zero. 10.2.22 Enable use of IMMEDIATE ARBITRATION +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + (only supported by the sym53c8xx driver. See 10.7 for more details) - iarb:0 do not use this feature. - iarb:#x use this feature according to bit fields as follow: - bit 0 (1) : enable IARB each time the initiator has been reselected - when it arbitrated for the SCSI BUS. - (#x >> 4) : maximum number of successive settings of IARB if the initiator - win arbitration and it has other commands to send to a device. +======= ================================================================= +iarb:0 do not use this feature. +iarb:#x use this feature according to bit fields as follow: + + ========= ======================================================= + bit 0 (1) enable IARB each time the initiator has been reselected + when it arbitrated for the SCSI BUS. + (#x >> 4) maximum number of successive settings of IARB if the + initiator win arbitration and it has other commands + to send to a device. + ========= ======================================================= +======= ================================================================= Boot fail safe safe:y load the following assumed fail safe initial setup + ======================== ====================== ========== master parity disabled mpar:n scsi parity enabled spar:y disconnections not allowed disc:n @@ -876,189 +1067,222 @@ Boot fail safe irq mode from BIOS settings irqm:1 SCSI BUS check do not attach on error buschk:1 immediate arbitration disabled iarb:0 + ======================== ====================== ========== 10.3 Advised boot setup commands +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If the driver has been configured with default options, the equivalent -boot setup is: +If the driver has been configured with default options, the equivalent +boot setup is:: ncr53c8xx=mpar:y,spar:y,disc:y,specf:3,fsn:n,ultra:2,fsn:n,revprob:n,verb:1\ tags:0,sync:50,debug:0,burst:7,led:0,wide:1,settle:2,diff:0,irqm:0 For an installation diskette or a safe but not fast system, -boot setup can be: +boot setup can be:: ncr53c8xx=safe:y,mpar:y,disc:y ncr53c8xx=safe:y,disc:y ncr53c8xx=safe:y,mpar:y ncr53c8xx=safe:y -My personal system works flawlessly with the following equivalent setup: +My personal system works flawlessly with the following equivalent setup:: ncr53c8xx=mpar:y,spar:y,disc:y,specf:1,fsn:n,ultra:2,fsn:n,revprob:n,verb:1\ tags:32,sync:12,debug:0,burst:7,led:1,wide:1,settle:2,diff:0,irqm:0 -The driver prints its actual setup when verbosity level is 2. You can try -"ncr53c8xx=verb:2" to get the "static" setup of the driver, or add "verb:2" -to your boot setup command in order to check the actual setup the driver is +The driver prints its actual setup when verbosity level is 2. You can try +"ncr53c8xx=verb:2" to get the "static" setup of the driver, or add "verb:2" +to your boot setup command in order to check the actual setup the driver is using. 10.4 PCI configuration fix-up boot option +----------------------------------------- pcifix:<option bits> Available option bits: - 0x1: Set PCI cache-line size register if not set. - 0x2: Set write and invalidate bit in PCI command register. + + === ===================================================== + 0x1 Set PCI cache-line size register if not set. + 0x2 Set write and invalidate bit in PCI command register. + === ===================================================== Use 'pcifix:3' in order to allow the driver to fix both PCI features. -These options only apply to new SYMBIOS chips 810A, 825A, 860, 875 +These options only apply to new SYMBIOS chips 810A, 825A, 860, 875 and 895 and are only supported for Pentium and 486 class processors. -Recent SYMBIOS 53C8XX scsi processors are able to use PCI read multiple -and PCI write and invalidate commands. These features require the -cache line size register to be properly set in the PCI configuration -space of the chips. On the other hand, chips will use PCI write and -invalidate commands only if the corresponding bit is set to 1 in the +Recent SYMBIOS 53C8XX scsi processors are able to use PCI read multiple +and PCI write and invalidate commands. These features require the +cache line size register to be properly set in the PCI configuration +space of the chips. On the other hand, chips will use PCI write and +invalidate commands only if the corresponding bit is set to 1 in the PCI command register. -Not all PCI bioses set the PCI cache line register and the PCI write and +Not all PCI bioses set the PCI cache line register and the PCI write and invalidate bit in the PCI configuration space of 53C8XX chips. -Optimized PCI accesses may be broken for some PCI/memory controllers or +Optimized PCI accesses may be broken for some PCI/memory controllers or make problems with some PCI boards. This fix-up worked flawlessly on my previous system. (MB Triton HX / 53C875 / 53C810A) -I use these options at my own risks as you will do if you decide to +I use these options at my own risks as you will do if you decide to use them too. 10.5 Serial NVRAM support boot option +------------------------------------- +======= ========================================= nvram:n do not look for serial NVRAM nvram:y test controllers for onboard serial NVRAM +======= ========================================= -This option can also been entered as an hexadecimal value that allows -to control what information the driver will get from the NVRAM and what +This option can also been entered as an hexadecimal value that allows +to control what information the driver will get from the NVRAM and what information it will ignore. For details see '17. Serial NVRAM support'. -When this option is enabled, the driver tries to detect all boards using +When this option is enabled, the driver tries to detect all boards using a Serial NVRAM. This memory is used to hold user set up parameters. -The parameters the driver is able to get from the NVRAM depend on the +The parameters the driver is able to get from the NVRAM depend on the data format used, as follow: - Tekram format Symbios format -General and host parameters - Boot order N Y - Host SCSI ID Y Y - SCSI parity checking Y Y - Verbose boot messages N Y -SCSI devices parameters - Synchronous transfer speed Y Y - Wide 16 / Narrow Y Y - Tagged Command Queuing enabled Y Y - Disconnections enabled Y Y - Scan at boot time N Y - -In order to speed up the system boot, for each device configured without -the "scan at boot time" option, the driver forces an error on the ++-------------------------------+------------------+--------------+ +| |Tekram format |Symbios format| ++-------------------------------+------------------+--------------+ +|General and host parameters | | | ++-------------------------------+------------------+--------------+ +| * Boot order | N | Y | ++-------------------------------+------------------+--------------+ +| * Host SCSI ID | Y | Y | ++-------------------------------+------------------+--------------+ +| * SCSI parity checking | Y | Y | ++-------------------------------+------------------+--------------+ +| * Verbose boot messages | N | Y | ++-------------------------------+------------------+--------------+ +|SCSI devices parameters | ++-------------------------------+------------------+--------------+ +| * Synchronous transfer speed | Y | Y | ++-------------------------------+------------------+--------------+ +| * Wide 16 / Narrow | Y | Y | ++-------------------------------+------------------+--------------+ +| * Tagged Command Queuing | Y | Y | +| enabled | | | ++-------------------------------+------------------+--------------+ +| * Disconnections enabled | Y | Y | ++-------------------------------+------------------+--------------+ +| * Scan at boot time | N | Y | ++-------------------------------+------------------+--------------+ + +In order to speed up the system boot, for each device configured without +the "scan at boot time" option, the driver forces an error on the first TEST UNIT READY command received for this device. -Some SDMS BIOS revisions seem to be unable to boot cleanly with very fast -hard disks. In such a situation you cannot configure the NVRAM with +Some SDMS BIOS revisions seem to be unable to boot cleanly with very fast +hard disks. In such a situation you cannot configure the NVRAM with optimized parameters value. -The 'nvram' boot option can be entered in hexadecimal form in order +The 'nvram' boot option can be entered in hexadecimal form in order to ignore some options configured in the NVRAM, as follow: mvram=<bits options> + + ==== ================================================================= 0x01 look for NVRAM (equivalent to nvram=y) 0x02 ignore NVRAM "Synchronous negotiation" parameters for all devices 0x04 ignore NVRAM "Wide negotiation" parameter for all devices 0x08 ignore NVRAM "Scan at boot time" parameter for all devices 0x80 also attach controllers set to OFF in the NVRAM (sym53c8xx only) + ==== ================================================================= -Option 0x80 is only supported by the sym53c8xx driver and is disabled by -default. Result is that, by default (option not set), the sym53c8xx driver +Option 0x80 is only supported by the sym53c8xx driver and is disabled by +default. Result is that, by default (option not set), the sym53c8xx driver will not attach controllers set to OFF in the NVRAM. -The ncr53c8xx always tries to attach all the controllers. Option 0x80 has -not been added to the ncr53c8xx driver, since it has been reported to -confuse users who use this driver since a long time. If you desire a -controller not to be attached by the ncr53c8xx driver at Linux boot, you +The ncr53c8xx always tries to attach all the controllers. Option 0x80 has +not been added to the ncr53c8xx driver, since it has been reported to +confuse users who use this driver since a long time. If you desire a +controller not to be attached by the ncr53c8xx driver at Linux boot, you must use the 'excl' driver boot option. 10.6 SCSI BUS checking boot option. +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When this option is set to a non-zero value, the driver checks SCSI lines +When this option is set to a non-zero value, the driver checks SCSI lines logic state, 100 micro-seconds after having asserted the SCSI RESET line. The driver just reads SCSI lines and checks all lines read FALSE except RESET. -Since SCSI devices shall release the BUS at most 800 nano-seconds after SCSI +Since SCSI devices shall release the BUS at most 800 nano-seconds after SCSI RESET has been asserted, any signal to TRUE may indicate a SCSI BUS problem. Unfortunately, the following common SCSI BUS problems are not detected: + - Only 1 terminator installed. - Misplaced terminators. - Bad quality terminators. -On the other hand, either bad cabling, broken devices, not conformant + +On the other hand, either bad cabling, broken devices, not conformant devices, ... may cause a SCSI signal to be wrong when te driver reads it. 10.7 IMMEDIATE ARBITRATION boot option +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This option is only supported by the SYM53C8XX driver (not by the NCR53C8XX). -SYMBIOS 53C8XX chips are able to arbitrate for the SCSI BUS as soon as they -have detected an expected disconnection (BUS FREE PHASE). For this process -to be started, bit 1 of SCNTL1 IO register must be set when the chip is +SYMBIOS 53C8XX chips are able to arbitrate for the SCSI BUS as soon as they +have detected an expected disconnection (BUS FREE PHASE). For this process +to be started, bit 1 of SCNTL1 IO register must be set when the chip is connected to the SCSI BUS. -When this feature has been enabled for the current connection, the chip has -every chance to win arbitration if only devices with lower priority are -competing for the SCSI BUS. By the way, when the chip is using SCSI id 7, +When this feature has been enabled for the current connection, the chip has +every chance to win arbitration if only devices with lower priority are +competing for the SCSI BUS. By the way, when the chip is using SCSI id 7, then it will for sure win the next SCSI BUS arbitration. -Since, there is no way to know what devices are trying to arbitrate for the +Since, there is no way to know what devices are trying to arbitrate for the BUS, using this feature can be extremely unfair. So, you are not advised -to enable it, or at most enable this feature for the case the chip lost +to enable it, or at most enable this feature for the case the chip lost the previous arbitration (boot option 'iarb:1'). This feature has the following advantages: a) Allow the initiator with ID 7 to win arbitration when it wants so. -b) Overlap at least 4 micro-seconds of arbitration time with the execution - of SCRIPTS that deal with the end of the current connection and that +b) Overlap at least 4 micro-seconds of arbitration time with the execution + of SCRIPTS that deal with the end of the current connection and that starts the next job. -Hmmm... But (a) may just prevent other devices from reselecting the initiator, -and delay data transfers or status/completions, and (b) may just waste +Hmmm... But (a) may just prevent other devices from reselecting the initiator, +and delay data transfers or status/completions, and (b) may just waste SCSI BUS bandwidth if the SCRIPTS execution lasts more than 4 micro-seconds. -The use of IARB needs the SCSI_NCR_IARB_SUPPORT option to have been defined -at compile time and the 'iarb' boot option to have been set to a non zero -value at boot time. It is not that useful for real work, but can be used -to stress SCSI devices or for some applications that can gain advantage of -it. By the way, if you experience badnesses like 'unexpected disconnections', -'bad reselections', etc... when using IARB on heavy IO load, you should not -be surprised, because force-feeding anything and blocking its arse at the +The use of IARB needs the SCSI_NCR_IARB_SUPPORT option to have been defined +at compile time and the 'iarb' boot option to have been set to a non zero +value at boot time. It is not that useful for real work, but can be used +to stress SCSI devices or for some applications that can gain advantage of +it. By the way, if you experience badnesses like 'unexpected disconnections', +'bad reselections', etc... when using IARB on heavy IO load, you should not +be surprised, because force-feeding anything and blocking its arse at the same time cannot work for a long time. :-)) 11. Some constants and flags of the ncr53c8xx.h header file +=========================================================== Some of these are defined from the configuration parameters. To change other "defines", you must edit the header file. Do that only if you know what you are doing. SCSI_NCR_SETUP_SPECIAL_FEATURES (default: defined) - If defined, the driver will enable some special features according + If defined, the driver will enable some special features according to chip and revision id. - For 810A, 860, 825A, 875 and 895 scsi chips, this option enables - support of features that reduce load of PCI bus and memory accesses - during scsi transfer processing: burst op-code fetch, read multiple, - read line, prefetch, cache line, write and invalidate, + + For 810A, 860, 825A, 875 and 895 scsi chips, this option enables + support of features that reduce load of PCI bus and memory accesses + during scsi transfer processing: burst op-code fetch, read multiple, + read line, prefetch, cache line, write and invalidate, burst 128 (875 only), large dma fifo (875 only), offset 16 (875 only). - Can be changed by the following boot setup command: + Can be changed by the following boot setup command:: + ncr53c8xx=specf:n SCSI_NCR_IOMAPPED (default: not defined) @@ -1066,22 +1290,26 @@ SCSI_NCR_IOMAPPED (default: not defined) SCSI_NCR_SHARE_IRQ (default: defined) If defined, request shared IRQ. - + SCSI_NCR_MAX_TAGS (default: 8) Maximum number of simultaneous tagged commands to a device. + Can be changed by "settags <target> <maxtags>" SCSI_NCR_SETUP_DEFAULT_SYNC (default: 50) - Transfer period factor the driver will use at boot time for synchronous + Transfer period factor the driver will use at boot time for synchronous negotiation. 0 means asynchronous. + Can be changed by "setsync <target> <period factor>" SCSI_NCR_SETUP_DEFAULT_TAGS (default: 8) Default number of simultaneous tagged commands to a device. + < 1 means tagged command queuing disabled at start-up. SCSI_NCR_ALWAYS_SIMPLE_TAG (default: defined) Use SIMPLE TAG for read and write commands. + Can be changed by "setorder <ordered|simple|default>" SCSI_NCR_SETUP_DISCONNECTION (default: defined) @@ -1089,6 +1317,7 @@ SCSI_NCR_SETUP_DISCONNECTION (default: defined) SCSI_NCR_SETUP_FORCE_SYNC_NEGO (default: not defined) If defined, synchronous negotiation is tried for all SCSI-2 devices. + Can be changed by "setsync <target> <period>" SCSI_NCR_SETUP_MASTER_PARITY (default: defined) @@ -1115,6 +1344,7 @@ SCSI_NCR_SETTLE_TIME (default: 2) SCSI_NCR_TIMEOUT_ALERT (default: 3) If a pending command will time out after this amount of seconds, an ordered tag is used for the next command. + Avoids timeouts for unordered tagged commands. SCSI_NCR_CAN_QUEUE (default: 7*SCSI_NCR_MAX_TAGS) @@ -1131,34 +1361,38 @@ SCSI_NCR_MAX_LUN (default: 8) 12. Installation +================ This driver is part of the linux kernel distribution. -Driver files are located in the sub-directory "drivers/scsi" of the +Driver files are located in the sub-directory "drivers/scsi" of the kernel source tree. -Driver files: +Driver files:: README.ncr53c8xx : this file ChangeLog.ncr53c8xx : change log ncr53c8xx.h : definitions ncr53c8xx.c : the driver code -New driver versions are made available separately in order to allow testing -changes and new features prior to including them into the linux kernel -distribution. The following URL provides information on latest available -patches: +New driver versions are made available separately in order to allow testing +changes and new features prior to including them into the linux kernel +distribution. The following URL provides information on latest available +patches: ftp://ftp.tux.org/pub/people/gerard-roudier/README -13. Architecture dependent features. +13. Architecture dependent features +=================================== <Not yet written> 14. Known problems +================== 14.1 Tagged commands with Iomega Jaz device +------------------------------------------- I have not tried this device, however it has been reported to me the following: This device is capable of Tagged command queuing. However @@ -1170,14 +1404,15 @@ other problem that may appear is timeouts. The only way to avoid timeouts seems to edit linux/drivers/scsi/sd.c and to increase the current timeout values. -14.2 Device names change when another controller is added. +14.2 Device names change when another controller is added +--------------------------------------------------------- -When you add a new NCR53C8XX chip based controller to a system that already -has one or more controllers of this family, it may happen that the order -the driver registers them to the kernel causes problems due to device +When you add a new NCR53C8XX chip based controller to a system that already +has one or more controllers of this family, it may happen that the order +the driver registers them to the kernel causes problems due to device name changes. -When at least one controller uses NvRAM, SDMS BIOS version 4 allows you to -define the order the BIOS will scan the scsi boards. The driver attaches +When at least one controller uses NvRAM, SDMS BIOS version 4 allows you to +define the order the BIOS will scan the scsi boards. The driver attaches controllers according to BIOS information if NvRAM detect option is set. If your controllers do not have NvRAM, you can: @@ -1187,52 +1422,58 @@ If your controllers do not have NvRAM, you can: - Make appropriate changes in the fstab. - Use the 'scsidev' tool from Eric Youngdale. -14.3 Using only 8 bit devices with a WIDE SCSI controller. +14.3 Using only 8 bit devices with a WIDE SCSI controller +--------------------------------------------------------- -When only 8 bit NARROW devices are connected to a 16 bit WIDE SCSI controller, +When only 8 bit NARROW devices are connected to a 16 bit WIDE SCSI controller, you must ensure that lines of the wide part of the SCSI BUS are pulled-up. -This can be achieved by ENABLING the WIDE TERMINATOR portion of the SCSI +This can be achieved by ENABLING the WIDE TERMINATOR portion of the SCSI controller card. + The TYAN 1365 documentation revision 1.2 is not correct about such settings. (page 10, figure 3.3). 14.4 Possible data corruption during a Memory Write and Invalidate +------------------------------------------------------------------ This problem is described in SYMBIOS DEL 397, Part Number 69-039241, ITEM 4. -In some complex situations, 53C875 chips revision <= 3 may start a PCI +In some complex situations, 53C875 chips revision <= 3 may start a PCI Write and Invalidate Command at a not cache-line-aligned 4 DWORDS boundary. This is only possible when Cache Line Size is 8 DWORDS or greater. -Pentium systems use a 8 DWORDS cache line size and so are concerned by +Pentium systems use a 8 DWORDS cache line size and so are concerned by this chip bug, unlike i486 systems that use a 4 DWORDS cache line size. -When this situation occurs, the chip may complete the Write and Invalidate -command after having only filled part of the last cache line involved in +When this situation occurs, the chip may complete the Write and Invalidate +command after having only filled part of the last cache line involved in the transfer, leaving to data corruption the remainder of this cache line. -Not using Write And Invalidate obviously gets rid of this chip bug, and so +Not using Write And Invalidate obviously gets rid of this chip bug, and so it is now the default setting of the driver. -However, for people like me who want to enable this feature, I have added -part of a work-around suggested by SYMBIOS. This work-around resets the -addressing logic when the DATA IN phase is entered and so prevents the bug -from being triggered for the first SCSI MOVE of the phase. This work-around +However, for people like me who want to enable this feature, I have added +part of a work-around suggested by SYMBIOS. This work-around resets the +addressing logic when the DATA IN phase is entered and so prevents the bug +from being triggered for the first SCSI MOVE of the phase. This work-around should be enough according to the following: -The only driver internal data structure that is greater than 8 DWORDS and -that is moved by the SCRIPTS processor is the 'CCB header' that contains -the context of the SCSI transfer. This data structure is aligned on 8 DWORDS -boundary (Pentium Cache Line Size), and so is immune to this chip bug, at +The only driver internal data structure that is greater than 8 DWORDS and +that is moved by the SCRIPTS processor is the 'CCB header' that contains +the context of the SCSI transfer. This data structure is aligned on 8 DWORDS +boundary (Pentium Cache Line Size), and so is immune to this chip bug, at least on Pentium systems. -But the conditions of this bug can be met when a SCSI read command is + +But the conditions of this bug can be met when a SCSI read command is performed using a buffer that is 4 DWORDS but not cache-line aligned. -This cannot happen under Linux when scatter/gather lists are used since -they only refer to system buffers that are well aligned. So, a work around -may only be needed under Linux when a scatter/gather list is not used and +This cannot happen under Linux when scatter/gather lists are used since +they only refer to system buffers that are well aligned. So, a work around +may only be needed under Linux when a scatter/gather list is not used and when the SCSI DATA IN phase is reentered after a phase mismatch. 15. SCSI problem troubleshooting +================================ 15.1 Problem tracking +--------------------- Most SCSI problems are due to a non conformant SCSI bus or to buggy devices. If unfortunately you have SCSI problems, you can check the @@ -1267,193 +1508,286 @@ tagged commands queuing. Try to enable one feature at a time with control commands. For example: -- echo "setsync all 25" >/proc/scsi/ncr53c8xx/0 - Will enable fast synchronous data transfer negotiation for all targets. +:: + + echo "setsync all 25" >/proc/scsi/ncr53c8xx/0 + +Will enable fast synchronous data transfer negotiation for all targets. + +:: -- echo "setflag 3" >/proc/scsi/ncr53c8xx/0 - Will reset flags (no_disc) for target 3, and so will allow it to disconnect - the SCSI Bus. + echo "setflag 3" >/proc/scsi/ncr53c8xx/0 -- echo "settags 3 8" >/proc/scsi/ncr53c8xx/0 - Will enable tagged command queuing for target 3 if that device supports it. +Will reset flags (no_disc) for target 3, and so will allow it to disconnect +the SCSI Bus. -Once you have found the device and the feature that cause problems, just +:: + + echo "settags 3 8" >/proc/scsi/ncr53c8xx/0 + +Will enable tagged command queuing for target 3 if that device supports it. + +Once you have found the device and the feature that cause problems, just disable that feature for that device. 15.2 Understanding hardware error reports +----------------------------------------- -When the driver detects an unexpected error condition, it may display a -message of the following pattern. +When the driver detects an unexpected error condition, it may display a +message of the following pattern:: -sym53c876-0:1: ERROR (0:48) (1-21-65) (f/95) @ (script 7c0:19000000). -sym53c876-0: script cmd = 19000000 -sym53c876-0: regdump: da 10 80 95 47 0f 01 07 75 01 81 21 80 01 09 00. + sym53c876-0:1: ERROR (0:48) (1-21-65) (f/95) @ (script 7c0:19000000). + sym53c876-0: script cmd = 19000000 + sym53c876-0: regdump: da 10 80 95 47 0f 01 07 75 01 81 21 80 01 09 00. -Some fields in such a message may help you understand the cause of the -problem, as follows: +Some fields in such a message may help you understand the cause of the +problem, as follows:: -sym53c876-0:1: ERROR (0:48) (1-21-65) (f/95) @ (script 7c0:19000000). -............A.........B.C....D.E..F....G.H.......I.....J...K....... + sym53c876-0:1: ERROR (0:48) (1-21-65) (f/95) @ (script 7c0:19000000). + ............A.........B.C....D.E..F....G.H.......I.....J...K....... Field A : target number. - SCSI ID of the device the controller was talking with at the moment the + SCSI ID of the device the controller was talking with at the moment the error occurs. Field B : DSTAT io register (DMA STATUS) - Bit 0x40 : MDPE Master Data Parity Error + ======== ============================================================= + Bit 0x40 MDPE Master Data Parity Error Data parity error detected on the PCI BUS. - Bit 0x20 : BF Bus Fault + Bit 0x20 BF Bus Fault PCI bus fault condition detected - Bit 0x01 : IID Illegal Instruction Detected - Set by the chip when it detects an Illegal Instruction format + Bit 0x01 IID Illegal Instruction Detected + Set by the chip when it detects an Illegal Instruction format on some condition that makes an instruction illegal. - Bit 0x80 : DFE Dma Fifo Empty + Bit 0x80 DFE Dma Fifo Empty Pure status bit that does not indicate an error. - If the reported DSTAT value contains a combination of MDPE (0x40), + ======== ============================================================= + + If the reported DSTAT value contains a combination of MDPE (0x40), BF (0x20), then the cause may be likely due to a PCI BUS problem. Field C : SIST io register (SCSI Interrupt Status) - Bit 0x08 : SGE SCSI GROSS ERROR - Indicates that the chip detected a severe error condition + ======== ================================================================== + Bit 0x08 SGE SCSI GROSS ERROR + Indicates that the chip detected a severe error condition on the SCSI BUS that prevents the SCSI protocol from functioning properly. - Bit 0x04 : UDC Unexpected Disconnection - Indicates that the device released the SCSI BUS when the chip - was not expecting this to happen. A device may behave so to - indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occurred. - Bit 0x02 : RST SCSI BUS Reset - Generally SCSI targets do not reset the SCSI BUS, although any + Bit 0x04 UDC Unexpected Disconnection + Indicates that the device released the SCSI BUS when the chip + was not expecting this to happen. A device may behave so to + indicate the SCSI initiator that an error condition not reportable + using the SCSI protocol has occurred. + Bit 0x02 RST SCSI BUS Reset + Generally SCSI targets do not reset the SCSI BUS, although any device on the BUS can reset it at any time. - Bit 0x01 : PAR Parity + Bit 0x01 PAR Parity SCSI parity error detected. - On a faulty SCSI BUS, any error condition among SGE (0x08), UDC (0x04) and - PAR (0x01) may be detected by the chip. If your SCSI system sometimes - encounters such error conditions, especially SCSI GROSS ERROR, then a SCSI + ======== ================================================================== + + On a faulty SCSI BUS, any error condition among SGE (0x08), UDC (0x04) and + PAR (0x01) may be detected by the chip. If your SCSI system sometimes + encounters such error conditions, especially SCSI GROSS ERROR, then a SCSI BUS problem is likely the cause of these errors. -For fields D,E,F,G and H, you may look into the sym53c8xx_defs.h file +For fields D,E,F,G and H, you may look into the sym53c8xx_defs.h file that contains some minimal comments on IO register bits. + Field D : SOCL Scsi Output Control Latch - This register reflects the state of the SCSI control lines the + This register reflects the state of the SCSI control lines the chip want to drive or compare against. + Field E : SBCL Scsi Bus Control Lines Actual value of control lines on the SCSI BUS. + Field F : SBDL Scsi Bus Data Lines Actual value of data lines on the SCSI BUS. + Field G : SXFER SCSI Transfer - Contains the setting of the Synchronous Period for output and + Contains the setting of the Synchronous Period for output and the current Synchronous offset (offset 0 means asynchronous). + Field H : SCNTL3 Scsi Control Register 3 - Contains the setting of timing values for both asynchronous and - synchronous data transfers. + Contains the setting of timing values for both asynchronous and + synchronous data transfers. -Understanding Fields I, J, K and dumps requires to have good knowledge of +Understanding Fields I, J, K and dumps requires to have good knowledge of SCSI standards, chip cores functionnals and internal driver data structures. -You are not required to decode and understand them, unless you want to help +You are not required to decode and understand them, unless you want to help maintain the driver code. 16. Synchronous transfer negotiation tables +=========================================== Tables below have been created by calling the routine the driver uses for synchronisation negotiation timing calculation and chip setting. -The first table corresponds to Ultra chips 53875 and 53C860 with 80 MHz +The first table corresponds to Ultra chips 53875 and 53C860 with 80 MHz clock and 5 clock divisors. -The second one has been calculated by setting the scsi clock to 40 Mhz -and using 4 clock divisors and so applies to all NCR53C8XX chips in fast +The second one has been calculated by setting the scsi clock to 40 Mhz +and using 4 clock divisors and so applies to all NCR53C8XX chips in fast SCSI-2 mode. Periods are in nano-seconds and speeds are in Mega-transfers per second. -1 Mega-transfers/second means 1 MB/s with 8 bits SCSI and 2 MB/s with +1 Mega-transfers/second means 1 MB/s with 8 bits SCSI and 2 MB/s with Wide16 SCSI. 16.1 Synchronous timings for 53C895, 53C875 and 53C860 SCSI controllers - ---------------------------------------------- - Negotiated NCR settings - Factor Period Speed Period Speed - ------ ------ ------ ------ ------ - 10 25 40.000 25 40.000 (53C895 only) - 11 30.2 33.112 31.25 32.000 (53C895 only) - 12 50 20.000 50 20.000 - 13 52 19.230 62 16.000 - 14 56 17.857 62 16.000 - 15 60 16.666 62 16.000 - 16 64 15.625 75 13.333 - 17 68 14.705 75 13.333 - 18 72 13.888 75 13.333 - 19 76 13.157 87 11.428 - 20 80 12.500 87 11.428 - 21 84 11.904 87 11.428 - 22 88 11.363 93 10.666 - 23 92 10.869 93 10.666 - 24 96 10.416 100 10.000 - 25 100 10.000 100 10.000 - 26 104 9.615 112 8.888 - 27 108 9.259 112 8.888 - 28 112 8.928 112 8.888 - 29 116 8.620 125 8.000 - 30 120 8.333 125 8.000 - 31 124 8.064 125 8.000 - 32 128 7.812 131 7.619 - 33 132 7.575 150 6.666 - 34 136 7.352 150 6.666 - 35 140 7.142 150 6.666 - 36 144 6.944 150 6.666 - 37 148 6.756 150 6.666 - 38 152 6.578 175 5.714 - 39 156 6.410 175 5.714 - 40 160 6.250 175 5.714 - 41 164 6.097 175 5.714 - 42 168 5.952 175 5.714 - 43 172 5.813 175 5.714 - 44 176 5.681 187 5.333 - 45 180 5.555 187 5.333 - 46 184 5.434 187 5.333 - 47 188 5.319 200 5.000 - 48 192 5.208 200 5.000 - 49 196 5.102 200 5.000 - ++-----------------------------+--------+-------+--------------+ +|Negotiated |NCR settings | | ++-------+--------+------------+--------+-------+ | +|Factor |Period |Speed |Period |Speed | | ++-------+--------+------------+--------+-------+--------------+ +|10 | 25 |40.000 | 25 |40.000 | (53C895 only)| ++-------+--------+------------+--------+-------+--------------+ +|11 | 30.2 |33.112 | 31.25 |32.000 | (53C895 only)| ++-------+--------+------------+--------+-------+--------------+ +|12 | 50 |20.000 | 50 |20.000 | | ++-------+--------+------------+--------+-------+--------------+ +|13 | 52 |19.230 | 62 |16.000 | | ++-------+--------+------------+--------+-------+--------------+ +|14 | 56 |17.857 | 62 |16.000 | | ++-------+--------+------------+--------+-------+--------------+ +|15 | 60 |16.666 | 62 |16.000 | | ++-------+--------+------------+--------+-------+--------------+ +|16 | 64 |15.625 | 75 |13.333 | | ++-------+--------+------------+--------+-------+--------------+ +|17 | 68 |14.705 | 75 |13.333 | | ++-------+--------+------------+--------+-------+--------------+ +|18 | 72 |13.888 | 75 |13.333 | | ++-------+--------+------------+--------+-------+--------------+ +|19 | 76 |13.157 | 87 |11.428 | | ++-------+--------+------------+--------+-------+--------------+ +|20 | 80 |12.500 | 87 |11.428 | | ++-------+--------+------------+--------+-------+--------------+ +|21 | 84 |11.904 | 87 |11.428 | | ++-------+--------+------------+--------+-------+--------------+ +|22 | 88 |11.363 | 93 |10.666 | | ++-------+--------+------------+--------+-------+--------------+ +|23 | 92 |10.869 | 93 |10.666 | | ++-------+--------+------------+--------+-------+--------------+ +|24 | 96 |10.416 |100 |10.000 | | ++-------+--------+------------+--------+-------+--------------+ +|25 |100 |10.000 |100 |10.000 | | ++-------+--------+------------+--------+-------+--------------+ +|26 |104 | 9.615 |112 | 8.888 | | ++-------+--------+------------+--------+-------+--------------+ +|27 |108 | 9.259 |112 | 8.888 | | ++-------+--------+------------+--------+-------+--------------+ +|28 |112 | 8.928 |112 | 8.888 | | ++-------+--------+------------+--------+-------+--------------+ +|29 |116 | 8.620 |125 | 8.000 | | ++-------+--------+------------+--------+-------+--------------+ +|30 |120 | 8.333 |125 | 8.000 | | ++-------+--------+------------+--------+-------+--------------+ +|31 |124 | 8.064 |125 | 8.000 | | ++-------+--------+------------+--------+-------+--------------+ +|32 |128 | 7.812 |131 | 7.619 | | ++-------+--------+------------+--------+-------+--------------+ +|33 |132 | 7.575 |150 | 6.666 | | ++-------+--------+------------+--------+-------+--------------+ +|34 |136 | 7.352 |150 | 6.666 | | ++-------+--------+------------+--------+-------+--------------+ +|35 |140 | 7.142 |150 | 6.666 | | ++-------+--------+------------+--------+-------+--------------+ +|36 |144 | 6.944 |150 | 6.666 | | ++-------+--------+------------+--------+-------+--------------+ +|37 |148 | 6.756 |150 | 6.666 | | ++-------+--------+------------+--------+-------+--------------+ +|38 |152 | 6.578 |175 | 5.714 | | ++-------+--------+------------+--------+-------+--------------+ +|39 |156 | 6.410 |175 | 5.714 | | ++-------+--------+------------+--------+-------+--------------+ +|40 |160 | 6.250 |175 | 5.714 | | ++-------+--------+------------+--------+-------+--------------+ +|41 |164 | 6.097 |175 | 5.714 | | ++-------+--------+------------+--------+-------+--------------+ +|42 |168 | 5.952 |175 | 5.714 | | ++-------+--------+------------+--------+-------+--------------+ +|43 |172 | 5.813 |175 | 5.714 | | ++-------+--------+------------+--------+-------+--------------+ +|44 |176 | 5.681 |187 | 5.333 | | ++-------+--------+------------+--------+-------+--------------+ +|45 |180 | 5.555 |187 | 5.333 | | ++-------+--------+------------+--------+-------+--------------+ +|46 |184 | 5.434 |187 | 5.333 | | ++-------+--------+------------+--------+-------+--------------+ +|47 |188 | 5.319 |200 | 5.000 | | ++-------+--------+------------+--------+-------+--------------+ +|48 |192 | 5.208 |200 | 5.000 | | ++-------+--------+------------+--------+-------+--------------+ +|49 |196 | 5.102 |200 | 5.000 | | ++-------+--------+------------+--------+-------+--------------+ 16.2 Synchronous timings for fast SCSI-2 53C8XX controllers - ---------------------------------------------- - Negotiated NCR settings - Factor Period Speed Period Speed - ------ ------ ------ ------ ------ - 25 100 10.000 100 10.000 - 26 104 9.615 125 8.000 - 27 108 9.259 125 8.000 - 28 112 8.928 125 8.000 - 29 116 8.620 125 8.000 - 30 120 8.333 125 8.000 - 31 124 8.064 125 8.000 - 32 128 7.812 131 7.619 - 33 132 7.575 150 6.666 - 34 136 7.352 150 6.666 - 35 140 7.142 150 6.666 - 36 144 6.944 150 6.666 - 37 148 6.756 150 6.666 - 38 152 6.578 175 5.714 - 39 156 6.410 175 5.714 - 40 160 6.250 175 5.714 - 41 164 6.097 175 5.714 - 42 168 5.952 175 5.714 - 43 172 5.813 175 5.714 - 44 176 5.681 187 5.333 - 45 180 5.555 187 5.333 - 46 184 5.434 187 5.333 - 47 188 5.319 200 5.000 - 48 192 5.208 200 5.000 - 49 196 5.102 200 5.000 - - -17. Serial NVRAM (added by Richard Waltham: dormouse@farsrobt.demon.co.uk) ++-----------------------------+----------------+ +|Negotiated |NCR settings | ++-------+--------+------------+--------+-------+ +|Factor |Period |Speed |Period |Speed | ++-------+--------+------------+--------+-------+ +|25 |100 |10.000 |100 |10.000 | ++-------+--------+------------+--------+-------+ +|26 |104 |9.615 |125 | 8.000 | ++-------+--------+------------+--------+-------+ +|27 |108 |9.259 |125 | 8.000 | ++-------+--------+------------+--------+-------+ +|28 |112 |8.928 |125 | 8.000 | ++-------+--------+------------+--------+-------+ +|29 |116 |8.620 |125 | 8.000 | ++-------+--------+------------+--------+-------+ +|30 |120 |8.333 |125 | 8.000 | ++-------+--------+------------+--------+-------+ +|31 |124 |8.064 |125 | 8.000 | ++-------+--------+------------+--------+-------+ +|32 |128 |7.812 |131 | 7.619 | ++-------+--------+------------+--------+-------+ +|33 |132 |7.575 |150 | 6.666 | ++-------+--------+------------+--------+-------+ +|34 |136 |7.352 |150 | 6.666 | ++-------+--------+------------+--------+-------+ +|35 |140 |7.142 |150 | 6.666 | ++-------+--------+------------+--------+-------+ +|36 |144 |6.944 |150 | 6.666 | ++-------+--------+------------+--------+-------+ +|37 |148 |6.756 |150 | 6.666 | ++-------+--------+------------+--------+-------+ +|38 |152 |6.578 |175 | 5.714 | ++-------+--------+------------+--------+-------+ +|39 |156 |6.410 |175 | 5.714 | ++-------+--------+------------+--------+-------+ +|40 |160 |6.250 |175 | 5.714 | ++-------+--------+------------+--------+-------+ +|41 |164 |6.097 |175 | 5.714 | ++-------+--------+------------+--------+-------+ +|42 |168 |5.952 |175 | 5.714 | ++-------+--------+------------+--------+-------+ +|43 |172 |5.813 |175 | 5.714 | ++-------+--------+------------+--------+-------+ +|44 |176 |5.681 |187 | 5.333 | ++-------+--------+------------+--------+-------+ +|45 |180 |5.555 |187 | 5.333 | ++-------+--------+------------+--------+-------+ +|46 |184 |5.434 |187 | 5.333 | ++-------+--------+------------+--------+-------+ +|47 |188 |5.319 |200 | 5.000 | ++-------+--------+------------+--------+-------+ +|48 |192 |5.208 |200 | 5.000 | ++-------+--------+------------+--------+-------+ +|49 |196 |5.102 |200 | 5.000 | ++-------+--------+------------+--------+-------+ + + +17. Serial NVRAM +================ + +(added by Richard Waltham: dormouse@farsrobt.demon.co.uk) 17.1 Features +------------- Enabling serial NVRAM support enables detection of the serial NVRAM included -on Symbios and some Symbios compatible host adaptors, and Tekram boards. The -serial NVRAM is used by Symbios and Tekram to hold set up parameters for the +on Symbios and some Symbios compatible host adaptors, and Tekram boards. The +serial NVRAM is used by Symbios and Tekram to hold set up parameters for the host adaptor and its attached drives. The Symbios NVRAM also holds data on the boot order of host adaptors in a @@ -1467,10 +1801,10 @@ NVRAM boot order settings can do this as well as change the order the same types of cards are scanned in, something "reverse probe" cannot do. Tekram boards using Symbios chips, DC390W/F/U, which have NVRAM are detected -and this is used to distinguish between Symbios compatible and Tekram host +and this is used to distinguish between Symbios compatible and Tekram host adaptors. This is used to disable the Symbios compatible "diff" setting -incorrectly set on Tekram boards if the CONFIG_SCSI_53C8XX_SYMBIOS_COMPAT -configuration parameter is set enabling both Symbios and Tekram boards to be +incorrectly set on Tekram boards if the CONFIG_SCSI_53C8XX_SYMBIOS_COMPAT +configuration parameter is set enabling both Symbios and Tekram boards to be used together with the Symbios cards using all their features, including "diff" support. ("led pin" support for Symbios compatible cards can remain enabled when using Tekram cards. It does nothing useful for Tekram host @@ -1478,71 +1812,76 @@ adaptors but does not cause problems either.) 17.2 Symbios NVRAM layout +------------------------- + +typical data at NVRAM address 0x100 (53c810a NVRAM):: + + 00 00 + 64 01 + 8e 0b + + 00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 + + 04 00 0f 00 00 10 00 50 00 00 01 00 00 62 + 04 00 03 00 00 10 00 58 00 00 01 00 00 63 + 04 00 01 00 00 10 00 48 00 00 01 00 00 61 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + + fe fe + 00 00 + 00 00 -typical data at NVRAM address 0x100 (53c810a NVRAM) ------------------------------------------------------------ -00 00 -64 01 -8e 0b - -00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 - -04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -04 00 03 00 00 10 00 58 00 00 01 00 00 63 -04 00 01 00 00 10 00 48 00 00 01 00 00 61 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 - -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 - -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 - -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 - -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 - -fe fe -00 00 -00 00 ------------------------------------------------------------ NVRAM layout details -NVRAM Address 0x000-0x0ff not used - 0x100-0x26f initialised data - 0x270-0x7ff not used +============= ================ +NVRAM Address +============= ================ +0x000-0x0ff not used +0x100-0x26f initialised data +0x270-0x7ff not used +============= ================ -general layout +general layout:: header - 6 bytes, data - 356 bytes (checksum is byte sum of this data) @@ -1550,7 +1889,7 @@ general layout --- total 368 bytes -data area layout +data area layout:: controller set up - 20 bytes boot configuration - 56 bytes (4x14 bytes) @@ -1559,121 +1898,126 @@ data area layout --- total 356 bytes ------------------------------------------------------------ -header - -00 00 - ?? start marker -64 01 - byte count (lsb/msb excludes header/trailer) -8e 0b - checksum (lsb/msb excludes header/trailer) ------------------------------------------------------------ -controller set up - -00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 - | | | | - | | | -- host ID - | | | - | | --Removable Media Support - | | 0x00 = none - | | 0x01 = Bootable Device - | | 0x02 = All with Media - | | - | --flag bits 2 - | 0x00000001= scan order hi->low - | (default 0x00 - scan low->hi) - --flag bits 1 - 0x00000001 scam enable - 0x00000010 parity enable - 0x00000100 verbose boot msgs +header:: + + 00 00 - ?? start marker + 64 01 - byte count (lsb/msb excludes header/trailer) + 8e 0b - checksum (lsb/msb excludes header/trailer) + +controller set up:: + + 00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 + | | | | + | | | -- host ID + | | | + | | --Removable Media Support + | | 0x00 = none + | | 0x01 = Bootable Device + | | 0x02 = All with Media + | | + | --flag bits 2 + | 0x00000001= scan order hi->low + | (default 0x00 - scan low->hi) + --flag bits 1 + 0x00000001 scam enable + 0x00000010 parity enable + 0x00000100 verbose boot msgs remaining bytes unknown - they do not appear to change in my current set up for any of the controllers. default set up is identical for 53c810a and 53c875 NVRAM (Removable Media added Symbios BIOS version 4.09) ------------------------------------------------------------ + boot configuration -boot order set by order of the devices in this table +boot order set by order of the devices in this table:: -04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -- 1st controller -04 00 03 00 00 10 00 58 00 00 01 00 00 63 2nd controller -04 00 01 00 00 10 00 48 00 00 01 00 00 61 3rd controller -00 00 00 00 00 00 00 00 00 00 00 00 00 00 4th controller - | | | | | | | | - | | | | | | ---- PCI io port adr - | | | | | --0x01 init/scan at boot time - | | | | --PCI device/function number (0xdddddfff) - | | ----- ?? PCI vendor ID (lsb/msb) - ----PCI device ID (lsb/msb) + 04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -- 1st controller + 04 00 03 00 00 10 00 58 00 00 01 00 00 63 2nd controller + 04 00 01 00 00 10 00 48 00 00 01 00 00 61 3rd controller + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4th controller + | | | | | | | | + | | | | | | ---- PCI io port adr + | | | | | --0x01 init/scan at boot time + | | | | --PCI device/function number (0xdddddfff) + | | ----- ?? PCI vendor ID (lsb/msb) + ----PCI device ID (lsb/msb) -?? use of this data is a guess but seems reasonable + ?? use of this data is a guess but seems reasonable remaining bytes unknown - they do not appear to change in my current set up default set up is identical for 53c810a and 53c875 NVRAM ------------------------------------------------------------ -device set up (up to 16 devices - includes controller) - -0f 00 08 08 64 00 0a 00 - id 0 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 - -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 - id 15 - | | | | | | - | | | | ----timeout (lsb/msb) - | | | --synch period (0x?? 40 Mtrans/sec- fast 40) (probably 0x28) - | | | (0x30 20 Mtrans/sec- fast 20) - | | | (0x64 10 Mtrans/sec- fast ) - | | | (0xc8 5 Mtrans/sec) - | | | (0x00 asynchronous) - | | -- ?? max sync offset (0x08 in NVRAM on 53c810a) - | | (0x10 in NVRAM on 53c875) - | --device bus width (0x08 narrow) - | (0x10 16 bit wide) - --flag bits - 0x00000001 - disconnect enabled - 0x00000010 - scan at boot time - 0x00000100 - scan luns - 0x00001000 - queue tags enabled +-------------------------------------------------------- + +device set up (up to 16 devices - includes controller):: + + 0f 00 08 08 64 00 0a 00 - id 0 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 - id 15 + | | | | | | + | | | | ----timeout (lsb/msb) + | | | --synch period (0x?? 40 Mtrans/sec- fast 40) (probably 0x28) + | | | (0x30 20 Mtrans/sec- fast 20) + | | | (0x64 10 Mtrans/sec- fast ) + | | | (0xc8 5 Mtrans/sec) + | | | (0x00 asynchronous) + | | -- ?? max sync offset (0x08 in NVRAM on 53c810a) + | | (0x10 in NVRAM on 53c875) + | --device bus width (0x08 narrow) + | (0x10 16 bit wide) + --flag bits + 0x00000001 - disconnect enabled + 0x00000010 - scan at boot time + 0x00000100 - scan luns + 0x00001000 - queue tags enabled remaining bytes unknown - they do not appear to change in my current set up -?? use of this data is a guess but seems reasonable +?? use of this data is a guess but seems reasonable (but it could be max bus width) default set up for 53c810a NVRAM -default set up for 53c875 NVRAM - bus width - 0x10 +default set up for 53c875 NVRAM + + - bus width - 0x10 - sync offset ? - 0x10 - sync period - 0x30 ------------------------------------------------------------ + ?? spare device space (32 bit bus ??) -00 00 00 00 00 00 00 00 (19x8bytes) -. -. -00 00 00 00 00 00 00 00 +:: + + 00 00 00 00 00 00 00 00 (19x8bytes) + . + . + 00 00 00 00 00 00 00 00 default set up is identical for 53c810a and 53c875 NVRAM ------------------------------------------------------------ -trailer +-------------------------------------------------------- -fe fe - ? end marker ? -00 00 -00 00 +trailer:: + + fe fe - ? end marker ? + 00 00 + 00 00 default set up is identical for 53c810a and 53c875 NVRAM ----------------------------------------------------------- @@ -1681,51 +2025,52 @@ default set up is identical for 53c810a and 53c875 NVRAM 17.3 Tekram NVRAM layout +------------------------ nvram 64x16 (1024 bit) -Drive settings - -Drive ID 0-15 (addr 0x0yyyy0 = device setup, yyyy = ID) - (addr 0x0yyyy1 = 0x0000) - - x x x x x x x x x x x x x x x x - | | | | | | | | | - | | | | | | | | ----- parity check 0 - off - | | | | | | | | 1 - on - | | | | | | | | - | | | | | | | ------- sync neg 0 - off - | | | | | | | 1 - on - | | | | | | | - | | | | | | --------- disconnect 0 - off - | | | | | | 1 - on - | | | | | | - | | | | | ----------- start cmd 0 - off - | | | | | 1 - on - | | | | | - | | | | -------------- tagged cmds 0 - off - | | | | 1 - on - | | | | - | | | ---------------- wide neg 0 - off - | | | 1 - on - | | | - --------------------------- sync rate 0 - 10.0 Mtrans/sec - 1 - 8.0 - 2 - 6.6 - 3 - 5.7 - 4 - 5.0 - 5 - 4.0 - 6 - 3.0 - 7 - 2.0 - 7 - 2.0 - 8 - 20.0 - 9 - 16.7 - a - 13.9 - b - 11.9 +Drive settings:: + + Drive ID 0-15 (addr 0x0yyyy0 = device setup, yyyy = ID) + (addr 0x0yyyy1 = 0x0000) + + x x x x x x x x x x x x x x x x + | | | | | | | | | + | | | | | | | | ----- parity check 0 - off + | | | | | | | | 1 - on + | | | | | | | | + | | | | | | | ------- sync neg 0 - off + | | | | | | | 1 - on + | | | | | | | + | | | | | | --------- disconnect 0 - off + | | | | | | 1 - on + | | | | | | + | | | | | ----------- start cmd 0 - off + | | | | | 1 - on + | | | | | + | | | | -------------- tagged cmds 0 - off + | | | | 1 - on + | | | | + | | | ---------------- wide neg 0 - off + | | | 1 - on + | | | + --------------------------- sync rate 0 - 10.0 Mtrans/sec + 1 - 8.0 + 2 - 6.6 + 3 - 5.7 + 4 - 5.0 + 5 - 4.0 + 6 - 3.0 + 7 - 2.0 + 7 - 2.0 + 8 - 20.0 + 9 - 16.7 + a - 13.9 + b - 11.9 Global settings -Host flags 0 (addr 0x100000, 32) +Host flags 0 (addr 0x100000, 32):: x x x x x x x x x x x x x x x x | | | | | | | | | | | | @@ -1733,7 +2078,7 @@ Host flags 0 (addr 0x100000, 32) | | | | | | | | | | | | | | | ----------------------- support for 0 - off | | | | | | | > 2 drives 1 - on - | | | | | | | + | | | | | | | | | | | | | ------------------------- support drives 0 - off | | | | | | > 1Gbytes 1 - on | | | | | | @@ -1753,10 +2098,10 @@ Host flags 0 (addr 0x100000, 32) as BIOS dev 1 - boot device 2 - all -Host flags 1 (addr 0x100001, 33) +Host flags 1 (addr 0x100001, 33):: x x x x x x x x x x x x x x x x - | | | | | | + | | | | | | | | | --------- boot delay 0 - 3 sec | | | 1 - 5 | | | 2 - 10 @@ -1771,7 +2116,7 @@ Host flags 1 (addr 0x100001, 33) 3 - 16 4 - 32 -Host flags 2 (addr 0x100010, 34) +Host flags 2 (addr 0x100010, 34):: x x x x x x x x x x x x x x x x | @@ -1784,41 +2129,41 @@ checksum = 0x1234 - (sum addr 0-63) ---------------------------------------------------------------------------- -default nvram data: +default nvram data:: -0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 -0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 -0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 -0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 + 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 + 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 + 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 + 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 -0x0f07 0x0400 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000 -0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 -0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 -0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc + 0x0f07 0x0400 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000 + 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 + 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 + 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc 18. Support for Big Endian +========================== The PCI local bus has been primarily designed for x86 architecture. -As a consequence, PCI devices generally expect DWORDS using little endian +As a consequence, PCI devices generally expect DWORDS using little endian byte ordering. 18.1 Big Endian CPU +------------------- -In order to support NCR chips on a Big Endian architecture the driver has to -perform byte reordering each time it is needed. This feature has been -added to the driver by Cort <cort@cs.nmt.edu> and is available in driver -version 2.5 and later ones. For the moment Big Endian support has only +In order to support NCR chips on a Big Endian architecture the driver has to +perform byte reordering each time it is needed. This feature has been +added to the driver by Cort <cort@cs.nmt.edu> and is available in driver +version 2.5 and later ones. For the moment Big Endian support has only been tested on Linux/PPC (PowerPC). 18.2 NCR chip in Big Endian mode of operations +---------------------------------------------- -It can be read in SYMBIOS documentation that some chips support a special +It can be read in SYMBIOS documentation that some chips support a special Big Endian mode, on paper: 53C815, 53C825A, 53C875, 53C875N, 53C895. -This mode of operations is not software-selectable, but needs pin named -BigLit to be pulled-up. Using this mode, most of byte reorderings should +This mode of operations is not software-selectable, but needs pin named +BigLit to be pulled-up. Using this mode, most of byte reorderings should be avoided when the driver is running on a Big Endian CPU. Driver version 2.5 is also, in theory, ready for this feature. - -=============================================================================== -End of NCR53C8XX driver README file diff --git a/Documentation/scsi/ppa.rst b/Documentation/scsi/ppa.rst new file mode 100644 index 000000000000..5fe3859a6892 --- /dev/null +++ b/Documentation/scsi/ppa.rst @@ -0,0 +1,18 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================================== +Terse where to get ZIP Drive help info +====================================== + +General Iomega ZIP drive page for Linux: +http://web.archive.org/web/%2E/http://www.torque.net/~campbell/ + +Driver archive for old drivers: +http://web.archive.org/web/%2E/http://www.torque.net/~campbell/ppa + +Linux Parport page (parallel port) +http://web.archive.org/web/%2E/http://www.torque.net/parport/ + +Email list for Linux Parport +linux-parport@torque.net + diff --git a/Documentation/scsi/ppa.txt b/Documentation/scsi/ppa.txt deleted file mode 100644 index 05ff47dbe8d1..000000000000 --- a/Documentation/scsi/ppa.txt +++ /dev/null @@ -1,14 +0,0 @@ --------- Terse where to get ZIP Drive help info -------- - -General Iomega ZIP drive page for Linux: -http://web.archive.org/web/*/http://www.torque.net/~campbell/ - -Driver archive for old drivers: -http://web.archive.org/web/*/http://www.torque.net/~campbell/ppa - -Linux Parport page (parallel port) -http://web.archive.org/web/*/http://www.torque.net/parport/ - -Email list for Linux Parport -linux-parport@torque.net - diff --git a/Documentation/scsi/qlogicfas.txt b/Documentation/scsi/qlogicfas.rst index c211d827fef2..b17f1b3676c3 100644 --- a/Documentation/scsi/qlogicfas.txt +++ b/Documentation/scsi/qlogicfas.rst @@ -1,3 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================================= +Qlogic FASXXX Family Driver Notes +================================= This driver supports the Qlogic FASXXX family of chips. This driver only works with the ISA, VLB, and PCMCIA versions of the Qlogic @@ -16,7 +21,8 @@ is provided by the qla1280 driver. Nor does it support the PCI-Basic, which is supported by the 'am53c974' driver. -PCMCIA SUPPORT +PCMCIA Support +============== This currently only works if the card is enabled first from DOS. This means you will have to load your socket and card services, and @@ -31,7 +37,8 @@ it from configuring the card. I am working with the PCMCIA group to make it more flexible, but that may take a while. -ALL CARDS +All Cards +========= The top of the qlogic.c file has a number of defines that controls configuration. As shipped, it provides a balance between speed and @@ -46,7 +53,8 @@ command or something. It comes up faster if this is set to zero, and if you have reliable hardware and connections it may be more useful to not reset things. -SOME TROUBLESHOOTING TIPS +Some Troubleshooting Tips +========================= Make sure it works properly under DOS. You should also do an initial FDISK on a new drive if you want partitions. @@ -54,7 +62,8 @@ on a new drive if you want partitions. Don't enable all the speedups first. If anything is wrong, they will make any problem worse. -IMPORTANT +Important +========= The best way to test if your cables, termination, etc. are good is to copy a very big file (e.g. a doublespace container file, or a very diff --git a/Documentation/scsi/scsi-changer.txt b/Documentation/scsi/scsi-changer.rst index ade046ea7c17..ab60e7e61a6c 100644 --- a/Documentation/scsi/scsi-changer.txt +++ b/Documentation/scsi/scsi-changer.rst @@ -1,4 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 +======================================== README for the SCSI media changer driver ======================================== @@ -28,15 +30,17 @@ The SCSI changer model is complex, compared to - for example - IDE-CD changers. But it allows to handle nearly all possible cases. It knows 4 different types of changer elements: - media transport - this one shuffles around the media, i.e. the + =============== ================================================== + media transport this one shuffles around the media, i.e. the transport arm. Also known as "picker". - storage - a slot which can hold a media. - import/export - the same as above, but is accessible from outside, + storage a slot which can hold a media. + import/export the same as above, but is accessible from outside, i.e. there the operator (you !) can use this to fill in and remove media from the changer. Sometimes named "mailslot". - data transfer - this is the device which reads/writes, i.e. the + data transfer this is the device which reads/writes, i.e. the CD-ROM / Tape / whatever drive. + =============== ================================================== None of these is limited to one: A huge Jukebox could have slots for 123 CD-ROM's, 5 CD-ROM readers (and therefore 6 SCSI ID's: the changer @@ -131,24 +135,23 @@ timeout_init=<seconds> timeout_move=<seconds> timeout for all other commands (default: 120). -dt_id=<id1>,<id2>,... -dt_lun=<lun1>,<lun2>,... +dt_id=<id1>,<id2>,... / dt_lun=<lun1>,<lun2>,... These two allow to specify the SCSI ID and LUN for the data transfer elements. You likely don't need this as the jukebox should provide this information. But some devices don't ... -vendor_firsts= -vendor_counts= -vendor_labels= +vendor_firsts=, vendor_counts=, vendor_labels= These insmod options can be used to tell the driver that there are some vendor-specific element types. Grundig for example does this. Some jukeboxes have a printer to label fresh burned CDs, which is addressed as element 0xc000 (type 5). To tell the - driver about this vendor-specific element, use this: + driver about this vendor-specific element, use this:: + $ insmod ch \ vendor_firsts=0xc000 \ vendor_counts=1 \ vendor_labels=printer + All three insmod options accept up to four comma-separated values, this way you can configure the element types 5-8. You likely need the SCSI specs for the device in question to @@ -162,13 +165,15 @@ Credits I wrote this driver using the famous mailing-patches-around-the-world method. With (more or less) help from: - Daniel Moehwald <moehwald@hdg.de> - Dane Jasper <dane@sonic.net> - R. Scott Bailey <sbailey@dsddi.eds.com> - Jonathan Corbet <corbet@lwn.net> + - Daniel Moehwald <moehwald@hdg.de> + - Dane Jasper <dane@sonic.net> + - R. Scott Bailey <sbailey@dsddi.eds.com> + - Jonathan Corbet <corbet@lwn.net> Special thanks go to - Martin Kuehne <martin.kuehne@bnbt.de> + + - Martin Kuehne <martin.kuehne@bnbt.de> + for a old, second-hand (but full functional) cdrom jukebox which I use to develop/test driver and tools now. @@ -176,5 +181,4 @@ Have fun, Gerd --- Gerd Knorr <kraxel@bytesex.org> diff --git a/Documentation/scsi/scsi-generic.txt b/Documentation/scsi/scsi-generic.rst index 51be20a6a14d..258505e557a6 100644 --- a/Documentation/scsi/scsi-generic.txt +++ b/Documentation/scsi/scsi-generic.rst @@ -1,6 +1,11 @@ - Notes on Linux SCSI Generic (sg) driver - --------------------------------------- +.. SPDX-License-Identifier: GPL-2.0 + +======================================= +Notes on Linux SCSI Generic (sg) driver +======================================= + 20020126 + Introduction ============ The SCSI Generic driver (sg) is one of the four "high level" SCSI device @@ -18,7 +23,7 @@ and examples. Major versions of the sg driver =============================== There are three major versions of sg found in the linux kernel (lk): - - sg version 1 (original) from 1992 to early 1999 (lk 2.2.5) . + - sg version 1 (original) from 1992 to early 1999 (lk 2.2.5) . It is based in the sg_header interface structure. - sg version 2 from lk 2.2.6 in the 2.2 series. It is based on an extended version of the sg_header interface structure. @@ -29,12 +34,16 @@ There are three major versions of sg found in the linux kernel (lk): Sg driver documentation ======================= The most recent documentation of the sg driver is kept at the Linux -Documentation Project's (LDP) site: -http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO +Documentation Project's (LDP) site: + +- http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO + This describes the sg version 3 driver found in the lk 2.4 series. + The LDP renders documents in single and multiple page HTML, postscript and pdf. This document can also be found at: -http://sg.danny.cz/sg/p/sg_v3_ho.html + +- http://sg.danny.cz/sg/p/sg_v3_ho.html Documentation for the version 2 sg driver found in the lk 2.2 series can be found at http://sg.danny.cz/sg/. A larger version @@ -45,23 +54,27 @@ found at http://www.torque.net/sg/p/original/SCSI-Programming-HOWTO.txt and in the LDP archives. A changelog with brief notes can be found in the -/usr/src/linux/include/scsi/sg.h file. Note that the glibc maintainers copy -and edit this file (removing its changelog for example) before placing it -in /usr/include/scsi/sg.h . Driver debugging information and other notes +/usr/src/linux/include/scsi/sg.h file. Note that the glibc maintainers copy +and edit this file (removing its changelog for example) before placing it +in /usr/include/scsi/sg.h . Driver debugging information and other notes can be found at the top of the /usr/src/linux/drivers/scsi/sg.c file. -A more general description of the Linux SCSI subsystem of which sg is a +A more general description of the Linux SCSI subsystem of which sg is a part can be found at http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO . Example code and utilities ========================== There are two packages of sg utilities: - - sg3_utils for the sg version 3 driver found in lk 2.4 - - sg_utils for the sg version 2 (and original) driver found in lk 2.2 + + ========= ========================================================== + sg3_utils for the sg version 3 driver found in lk 2.4 + sg_utils for the sg version 2 (and original) driver found in lk 2.2 and earlier + ========= ========================================================== + Both packages will work in the lk 2.4 series however sg3_utils offers more -capabilities. They can be found at: http://sg.danny.cz/sg/sg3_utils.html and +capabilities. They can be found at: http://sg.danny.cz/sg/sg3_utils.html and freecode.com Another approach is to look at the applications that use the sg driver. @@ -72,30 +85,34 @@ Mapping of Linux kernel versions to sg driver versions ====================================================== Here is a list of linux kernels in the 2.4 series that had new version of the sg driver: - lk 2.4.0 : sg version 3.1.17 - lk 2.4.7 : sg version 3.1.19 - lk 2.4.10 : sg version 3.1.20 ** - lk 2.4.17 : sg version 3.1.22 -** There were 3 changes to sg version 3.1.20 by third parties in the - next six linux kernel versions. + - lk 2.4.0 : sg version 3.1.17 + - lk 2.4.7 : sg version 3.1.19 + - lk 2.4.10 : sg version 3.1.20 [#]_ + - lk 2.4.17 : sg version 3.1.22 + +.. [#] There were 3 changes to sg version 3.1.20 by third parties in the + next six linux kernel versions. -For reference here is a list of linux kernels in the 2.2 series that had +For reference here is a list of linux kernels in the 2.2 series that had new version of the sg driver: - lk 2.2.0 : original sg version [with no version number] - lk 2.2.6 : sg version 2.1.31 - lk 2.2.8 : sg version 2.1.32 - lk 2.2.10 : sg version 2.1.34 [SG_GET_VERSION_NUM ioctl first appeared] - lk 2.2.14 : sg version 2.1.36 - lk 2.2.16 : sg version 2.1.38 - lk 2.2.17 : sg version 2.1.39 - lk 2.2.20 : sg version 2.1.40 + + - lk 2.2.0 : original sg version [with no version number] + - lk 2.2.6 : sg version 2.1.31 + - lk 2.2.8 : sg version 2.1.32 + - lk 2.2.10 : sg version 2.1.34 [SG_GET_VERSION_NUM ioctl first appeared] + - lk 2.2.14 : sg version 2.1.36 + - lk 2.2.16 : sg version 2.1.38 + - lk 2.2.17 : sg version 2.1.39 + - lk 2.2.20 : sg version 2.1.40 The lk 2.5 development series has recently commenced and it currently contains sg version 3.5.23 which is functionally equivalent to sg -version 3.1.22 found in lk 2.4.17 . +version 3.1.22 found in lk 2.4.17. Douglas Gilbert + 26th January 2002 + dgilbert@interlog.com diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.rst index 25a4b4cf04a6..9aba897c97ac 100644 --- a/Documentation/scsi/scsi-parameters.txt +++ b/Documentation/scsi/scsi-parameters.rst @@ -1,31 +1,35 @@ - SCSI Kernel Parameters - ~~~~~~~~~~~~~~~~~~~~~~ +.. SPDX-License-Identifier: GPL-2.0 + +====================== +SCSI Kernel Parameters +====================== See Documentation/admin-guide/kernel-parameters.rst for general information on specifying module parameters. This document may not be entirely up to date and comprehensive. The command -"modinfo -p ${modulename}" shows a current list of all parameters of a loadable +``modinfo -p ${modulename}`` shows a current list of all parameters of a loadable module. Loadable modules, after being loaded into the running kernel, also reveal their parameters in /sys/module/${modulename}/parameters/. Some of these parameters may be changed at runtime by the command -"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}". +``echo -n ${value} > /sys/module/${modulename}/parameters/${parm}``. +:: advansys= [HW,SCSI] See header of drivers/scsi/advansys.c. aha152x= [HW,SCSI] - See Documentation/scsi/aha152x.txt. + See Documentation/scsi/aha152x.rst. aha1542= [HW,SCSI] Format: <portbase>[,<buson>,<busoff>[,<dmaspeed>]] aic7xxx= [HW,SCSI] - See Documentation/scsi/aic7xxx.txt. + See Documentation/scsi/aic7xxx.rst. aic79xx= [HW,SCSI] - See Documentation/scsi/aic79xx.txt. + See Documentation/scsi/aic79xx.rst. atascsi= [HW,SCSI] See drivers/scsi/atari_scsi.c. @@ -57,19 +61,19 @@ parameters may be changed at runtime by the command See header of drivers/scsi/NCR_D700.c. ncr5380= [HW,SCSI] - See Documentation/scsi/g_NCR5380.txt. + See Documentation/scsi/g_NCR5380.rst. ncr53c400= [HW,SCSI] - See Documentation/scsi/g_NCR5380.txt. + See Documentation/scsi/g_NCR5380.rst. ncr53c400a= [HW,SCSI] - See Documentation/scsi/g_NCR5380.txt. + See Documentation/scsi/g_NCR5380.rst. ncr53c8xx= [HW,SCSI] osst= [HW,SCSI] SCSI Tape Driver Format: <buffer_size>,<write_threshold> - See also Documentation/scsi/st.txt. + See also Documentation/scsi/st.rst. scsi_debug_*= [SCSI] See drivers/scsi/scsi_debug.c. @@ -101,7 +105,7 @@ parameters may be changed at runtime by the command See header of drivers/scsi/sim710.c. st= [HW,SCSI] SCSI tape parameters (buffers, etc.) - See Documentation/scsi/st.txt. + See Documentation/scsi/st.rst. wd33c93= [HW,SCSI] See header of drivers/scsi/wd33c93.c. diff --git a/Documentation/scsi/scsi.txt b/Documentation/scsi/scsi.rst index 3d99d38cb62a..276918eb4d74 100644 --- a/Documentation/scsi/scsi.txt +++ b/Documentation/scsi/scsi.rst @@ -1,44 +1,47 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============================ SCSI subsystem documentation ============================ + The Linux Documentation Project (LDP) maintains a document describing the SCSI subsystem in the Linux kernel (lk) 2.4 series. See: http://www.tldp.org/HOWTO/SCSI-2.4-HOWTO . The LDP has single and multiple page HTML renderings as well as postscript and pdf. It can also be found at: -http://web.archive.org/web/*/http://www.torque.net/scsi/SCSI-2.4-HOWTO +http://web.archive.org/web/%2E/http://www.torque.net/scsi/SCSI-2.4-HOWTO Notes on using modules in the SCSI subsystem ============================================ -The scsi support in the linux kernel can be modularized in a number of +The scsi support in the linux kernel can be modularized in a number of different ways depending upon the needs of the end user. To understand your options, we should first define a few terms. -The scsi-core (also known as the "mid level") contains the core of scsi +The scsi-core (also known as the "mid level") contains the core of scsi support. Without it you can do nothing with any of the other scsi drivers. The scsi core support can be a module (scsi_mod.o), or it can be built into -the kernel. If the core is a module, it must be the first scsi module -loaded, and if you unload the modules, it will have to be the last one +the kernel. If the core is a module, it must be the first scsi module +loaded, and if you unload the modules, it will have to be the last one unloaded. In practice the modprobe and rmmod commands (and "autoclean") will enforce the correct ordering of loading and unloading modules in the SCSI subsystem. -The individual upper and lower level drivers can be loaded in any order +The individual upper and lower level drivers can be loaded in any order once the scsi core is present in the kernel (either compiled in or loaded as a module). The disk driver (sd_mod.o), cdrom driver (sr_mod.o), -tape driver ** (st.o) and scsi generics driver (sg.o) represent the upper -level drivers to support the various assorted devices which can be -controlled. You can for example load the tape driver to use the tape drive, +tape driver [1]_ (st.o) and scsi generics driver (sg.o) represent the upper +level drivers to support the various assorted devices which can be +controlled. You can for example load the tape driver to use the tape drive, and then unload it once you have no further need for the driver (and release the associated memory). The lower level drivers are the ones that support the individual cards that are supported for the hardware platform that you are running under. Those individual cards are often called Host Bus Adapters (HBAs). For example the -aic7xxx.o driver is used to control all recent SCSI controller cards from -Adaptec. Almost all lower level drivers can be built either as modules or +aic7xxx.o driver is used to control all recent SCSI controller cards from +Adaptec. Almost all lower level drivers can be built either as modules or built into the kernel. - -** There is a variant of the st driver for controlling OnStream tape - devices. Its module name is osst.o . +.. [1] There is a variant of the st driver for controlling OnStream tape + devices. Its module name is osst.o . diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.rst index 1b7436932a2b..7d78c2475615 100644 --- a/Documentation/scsi/scsi_eh.txt +++ b/Documentation/scsi/scsi_eh.rst @@ -1,35 +1,39 @@ +.. SPDX-License-Identifier: GPL-2.0 +======= SCSI EH -====================================== +======= - This document describes SCSI midlayer error handling infrastructure. -Please refer to Documentation/scsi/scsi_mid_low_api.txt for more +This document describes SCSI midlayer error handling infrastructure. +Please refer to Documentation/scsi/scsi_mid_low_api.rst for more information regarding SCSI midlayer. -TABLE OF CONTENTS +.. TABLE OF CONTENTS -[1] How SCSI commands travel through the midlayer and to EH - [1-1] struct scsi_cmnd - [1-2] How do scmd's get completed? - [1-2-1] Completing a scmd w/ scsi_done - [1-2-2] Completing a scmd w/ timeout - [1-3] How EH takes over -[2] How SCSI EH works - [2-1] EH through fine-grained callbacks - [2-1-1] Overview - [2-1-2] Flow of scmds through EH - [2-1-3] Flow of control - [2-2] EH through transportt->eh_strategy_handler() - [2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions - [2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions - [2-2-3] Things to consider + [1] How SCSI commands travel through the midlayer and to EH + [1-1] struct scsi_cmnd + [1-2] How do scmd's get completed? + [1-2-1] Completing a scmd w/ scsi_done + [1-2-2] Completing a scmd w/ timeout + [1-3] How EH takes over + [2] How SCSI EH works + [2-1] EH through fine-grained callbacks + [2-1-1] Overview + [2-1-2] Flow of scmds through EH + [2-1-3] Flow of control + [2-2] EH through transportt->eh_strategy_handler() + [2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions + [2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions + [2-2-3] Things to consider -[1] How SCSI commands travel through the midlayer and to EH +1. How SCSI commands travel through the midlayer and to EH +========================================================== -[1-1] struct scsi_cmnd +1.1 struct scsi_cmnd +-------------------- - Each SCSI command is represented with struct scsi_cmnd (== scmd). A +Each SCSI command is represented with struct scsi_cmnd (== scmd). A scmd has two list_head's to link itself into lists. The two are scmd->list and scmd->eh_entry. The former is used for free list or per-device allocated scmd list and not of much interest to this EH @@ -38,25 +42,28 @@ otherwise stated scmds are always linked using scmd->eh_entry in this discussion. -[1-2] How do scmd's get completed? +1.2 How do scmd's get completed? +-------------------------------- - Once LLDD gets hold of a scmd, either the LLDD will complete the +Once LLDD gets hold of a scmd, either the LLDD will complete the command by calling scsi_done callback passed from midlayer when invoking hostt->queuecommand() or the block layer will time it out. -[1-2-1] Completing a scmd w/ scsi_done +1.2.1 Completing a scmd w/ scsi_done +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - For all non-EH commands, scsi_done() is the completion callback. It +For all non-EH commands, scsi_done() is the completion callback. It just calls blk_complete_request() to delete the block layer timer and raise SCSI_SOFTIRQ - SCSI_SOFTIRQ handler scsi_softirq calls scsi_decide_disposition() to +SCSI_SOFTIRQ handler scsi_softirq calls scsi_decide_disposition() to determine what to do with the command. scsi_decide_disposition() looks at the scmd->result value and sense data to determine what to do with the command. - SUCCESS + scsi_finish_command() is invoked for the command. The function does some maintenance chores and then calls scsi_io_completion() to finish the I/O. @@ -66,17 +73,21 @@ with the command. of the data in case of an error. - NEEDS_RETRY + - ADD_TO_MLQUEUE + scmd is requeued to blk queue. - otherwise + scsi_eh_scmd_add(scmd) is invoked for the command. See [1-3] for details of this function. -[1-2-2] Completing a scmd w/ timeout +1.2.2 Completing a scmd w/ timeout +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - The timeout handler is scsi_times_out(). When a timeout occurs, this +The timeout handler is scsi_times_out(). When a timeout occurs, this function 1. invokes optional hostt->eh_timed_out() callback. Return value can @@ -101,18 +112,21 @@ function 3. scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD) is invoked for the command. See [1-4] for more information. -[1-3] Asynchronous command aborts +1.3 Asynchronous command aborts +------------------------------- After a timeout occurs a command abort is scheduled from scsi_abort_command(). If the abort is successful the command will either be retried (if the number of retries is not exhausted) or terminated with DID_TIME_OUT. + Otherwise scsi_eh_scmd_add() is invoked for the command. See [1-4] for more information. -[1-4] How EH takes over +1.4 How EH takes over +--------------------- - scmds enter EH via scsi_eh_scmd_add(), which does the following. +scmds enter EH via scsi_eh_scmd_add(), which does the following. 1. Links scmd->eh_entry to shost->eh_cmd_q @@ -122,19 +136,19 @@ function 4. Wakes up SCSI EH thread if shost->host_busy == shost->host_failed - As can be seen above, once any scmd is added to shost->eh_cmd_q, +As can be seen above, once any scmd is added to shost->eh_cmd_q, SHOST_RECOVERY shost_state bit is turned on. This prevents any new scmd to be issued from blk queue to the host; eventually, all scmds on the host either complete normally, fail and get added to eh_cmd_q, or time out and get added to shost->eh_cmd_q. - If all scmds either complete or fail, the number of in-flight scmds +If all scmds either complete or fail, the number of in-flight scmds becomes equal to the number of failed scmds - i.e. shost->host_busy == shost->host_failed. This wakes up SCSI EH thread. So, once woken up, SCSI EH thread can expect that all in-flight commands have failed and are linked on shost->eh_cmd_q. - Note that this does not mean lower layers are quiescent. If a LLDD +Note that this does not mean lower layers are quiescent. If a LLDD completed a scmd with error status, the LLDD and lower layers are assumed to forget about the scmd at that point. However, if a scmd has timed out, unless hostt->eh_timed_out() made lower layers forget @@ -143,13 +157,14 @@ active as long as lower layers are concerned and completion could occur at any time. Of course, all such completions are ignored as the timer has already expired. - We'll talk about how SCSI EH takes actions to abort - make LLDD +We'll talk about how SCSI EH takes actions to abort - make LLDD forget about - timed out scmds later. -[2] How SCSI EH works +2. How SCSI EH works +==================== - LLDD's can implement SCSI EH actions in one of the following two +LLDD's can implement SCSI EH actions in one of the following two ways. - Fine-grained EH callbacks @@ -162,7 +177,7 @@ ways. handling. As such, it should do all chores the SCSI midlayer performs during recovery. This will be discussed in [2-2]. - Once recovery is complete, SCSI EH resumes normal operation by +Once recovery is complete, SCSI EH resumes normal operation by calling scsi_restart_operations(), which 1. Checks if door locking is needed and locks door. @@ -177,34 +192,38 @@ calling scsi_restart_operations(), which 4. Kicks queues in all devices on the host in the asses -[2-1] EH through fine-grained callbacks +2.1 EH through fine-grained callbacks +------------------------------------- -[2-1-1] Overview +2.1.1 Overview +^^^^^^^^^^^^^^ - If eh_strategy_handler() is not present, SCSI midlayer takes charge +If eh_strategy_handler() is not present, SCSI midlayer takes charge of driving error handling. EH's goals are two - make LLDD, host and device forget about timed out scmds and make them ready for new commands. A scmd is said to be recovered if the scmd is forgotten by lower layers and lower layers are ready to process or fail the scmd again. - To achieve these goals, EH performs recovery actions with increasing +To achieve these goals, EH performs recovery actions with increasing severity. Some actions are performed by issuing SCSI commands and others are performed by invoking one of the following fine-grained hostt EH callbacks. Callbacks may be omitted and omitted ones are considered to fail always. -int (* eh_abort_handler)(struct scsi_cmnd *); -int (* eh_device_reset_handler)(struct scsi_cmnd *); -int (* eh_bus_reset_handler)(struct scsi_cmnd *); -int (* eh_host_reset_handler)(struct scsi_cmnd *); +:: - Higher-severity actions are taken only when lower-severity actions + int (* eh_abort_handler)(struct scsi_cmnd *); + int (* eh_device_reset_handler)(struct scsi_cmnd *); + int (* eh_bus_reset_handler)(struct scsi_cmnd *); + int (* eh_host_reset_handler)(struct scsi_cmnd *); + +Higher-severity actions are taken only when lower-severity actions cannot recover some of failed scmds. Also, note that failure of the highest-severity action means EH failure and results in offlining of all unrecovered devices. - During recovery, the following rules are followed +During recovery, the following rules are followed - Recovery actions are performed on failed scmds on the to do list, eh_work_q. If a recovery action succeeds for a scmd, recovered @@ -221,58 +240,72 @@ all unrecovered devices. timed-out scmds, SCSI EH ensures that LLDD forgets about a scmd before reusing it for EH commands. - When a scmd is recovered, the scmd is moved from eh_work_q to EH +When a scmd is recovered, the scmd is moved from eh_work_q to EH local eh_done_q using scsi_eh_finish_cmd(). After all scmds are recovered (eh_work_q is empty), scsi_eh_flush_done_q() is invoked to either retry or error-finish (notify upper layer of failure) recovered scmds. - scmds are retried iff its sdev is still online (not offlined during +scmds are retried iff its sdev is still online (not offlined during EH), REQ_FAILFAST is not set and ++scmd->retries is less than scmd->allowed. -[2-1-2] Flow of scmds through EH +2.1.2 Flow of scmds through EH +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1. Error completion / time out - ACTION: scsi_eh_scmd_add() is invoked for scmd + + :ACTION: scsi_eh_scmd_add() is invoked for scmd + - add scmd to shost->eh_cmd_q - set SHOST_RECOVERY - shost->host_failed++ - LOCKING: shost->host_lock + + :LOCKING: shost->host_lock 2. EH starts - ACTION: move all scmds to EH's local eh_work_q. shost->eh_cmd_q - is cleared. - LOCKING: shost->host_lock (not strictly necessary, just for + + :ACTION: move all scmds to EH's local eh_work_q. shost->eh_cmd_q + is cleared. + + :LOCKING: shost->host_lock (not strictly necessary, just for consistency) 3. scmd recovered - ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd + + :ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd + - scsi_setup_cmd_retry() - move from local eh_work_q to local eh_done_q - LOCKING: none - CONCURRENCY: at most one thread per separate eh_work_q to - keep queue manipulation lockless + + :LOCKING: none + + :CONCURRENCY: at most one thread per separate eh_work_q to + keep queue manipulation lockless 4. EH completes - ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper - layer of failure. May be called concurrently but must have - a no more than one thread per separate eh_work_q to - manipulate the queue locklessly - - scmd is removed from eh_done_q and scmd->eh_entry is cleared - - if retry is necessary, scmd is requeued using - scsi_queue_insert() - - otherwise, scsi_finish_command() is invoked for scmd - - zero shost->host_failed - LOCKING: queue or finish function performs appropriate locking + :ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper + layer of failure. May be called concurrently but must have + a no more than one thread per separate eh_work_q to + manipulate the queue locklessly -[2-1-3] Flow of control + - scmd is removed from eh_done_q and scmd->eh_entry is cleared + - if retry is necessary, scmd is requeued using + scsi_queue_insert() + - otherwise, scsi_finish_command() is invoked for scmd + - zero shost->host_failed + + :LOCKING: queue or finish function performs appropriate locking + + +2.1.3 Flow of control +^^^^^^^^^^^^^^^^^^^^^^ EH through fine-grained callbacks start from scsi_unjam_host(). -<<scsi_unjam_host>> +``scsi_unjam_host`` 1. Lock shost->host_lock, splice_init shost->eh_cmd_q into local eh_work_q and unlock host_lock. Note that shost->eh_cmd_q is @@ -280,7 +313,7 @@ scmd->allowed. 2. Invoke scsi_eh_get_sense. - <<scsi_eh_get_sense>> + ``scsi_eh_get_sense`` This action is taken for each error-completed (!SCSI_EH_CANCEL_CMD) commands without valid sense data. Most @@ -315,7 +348,7 @@ scmd->allowed. 3. If !list_empty(&eh_work_q), invoke scsi_eh_abort_cmds(). - <<scsi_eh_abort_cmds>> + ``scsi_eh_abort_cmds`` This action is taken for each timed out command when no_async_abort is enabled in the host template. @@ -339,14 +372,14 @@ scmd->allowed. 4. If !list_empty(&eh_work_q), invoke scsi_eh_ready_devs() - <<scsi_eh_ready_devs>> + ``scsi_eh_ready_devs`` This function takes four increasingly more severe measures to make failed sdevs ready for new commands. 1. Invoke scsi_eh_stu() - <<scsi_eh_stu>> + ``scsi_eh_stu`` For each sdev which has failed scmds with valid sense data of which scsi_check_sense()'s verdict is FAILED, @@ -369,7 +402,7 @@ scmd->allowed. 2. If !list_empty(&eh_work_q), invoke scsi_eh_bus_device_reset(). - <<scsi_eh_bus_device_reset>> + ``scsi_eh_bus_device_reset`` This action is very similar to scsi_eh_stu() except that, instead of issuing STU, hostt->eh_device_reset_handler() @@ -379,7 +412,7 @@ scmd->allowed. 3. If !list_empty(&eh_work_q), invoke scsi_eh_bus_reset() - <<scsi_eh_bus_reset>> + ``scsi_eh_bus_reset`` hostt->eh_bus_reset_handler() is invoked for each channel with failed scmds. If bus reset succeeds, all failed @@ -388,7 +421,7 @@ scmd->allowed. 4. If !list_empty(&eh_work_q), invoke scsi_eh_host_reset() - <<scsi_eh_host_reset>> + ``scsi_eh_host_reset`` This is the last resort. hostt->eh_host_reset_handler() is invoked. If host reset succeeds, all failed scmds on @@ -396,14 +429,14 @@ scmd->allowed. 5. If !list_empty(&eh_work_q), invoke scsi_eh_offline_sdevs() - <<scsi_eh_offline_sdevs>> + ``scsi_eh_offline_sdevs`` Take all sdevs which still have unrecovered scmds offline and EH-finish the scmds. 5. Invoke scsi_eh_flush_done_q(). - <<scsi_eh_flush_done_q>> + ``scsi_eh_flush_done_q`` At this point all scmds are recovered (or given up) and put on eh_done_q by scsi_eh_finish_cmd(). This function @@ -411,9 +444,10 @@ scmd->allowed. layer of failure of the scmds. -[2-2] EH through transportt->eh_strategy_handler() +2.2 EH through transportt->eh_strategy_handler() +------------------------------------------------ - transportt->eh_strategy_handler() is invoked in the place of +transportt->eh_strategy_handler() is invoked in the place of scsi_unjam_host() and it is responsible for whole recovery process. On completion, the handler should have made lower layers forget about all failed scmds and either ready for new commands or offline. Also, @@ -422,7 +456,8 @@ SCSI midlayer. IOW, of the steps described in [2-1-2], all steps except for #1 must be implemented by eh_strategy_handler(). -[2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions +2.2.1 Pre transportt->eh_strategy_handler() SCSI midlayer conditions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following conditions are true on entry to the handler. @@ -435,7 +470,8 @@ except for #1 must be implemented by eh_strategy_handler(). - shost->host_failed == shost->host_busy -[2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions +2.2.2 Post transportt->eh_strategy_handler() SCSI midlayer conditions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following conditions must be true on exit from the handler. @@ -453,7 +489,8 @@ except for #1 must be implemented by eh_strategy_handler(). ->allowed to limit the number of retries. -[2-2-3] Things to consider +2.2.3 Things to consider +^^^^^^^^^^^^^^^^^^^^^^^^ - Know that timed out scmds are still active on lower layers. Make lower layers forget about them before doing anything else with @@ -469,7 +506,7 @@ except for #1 must be implemented by eh_strategy_handler(). offline. --- Tejun Heo htejun@gmail.com + 11th September 2005 diff --git a/Documentation/scsi/scsi_fc_transport.txt b/Documentation/scsi/scsi_fc_transport.rst index f79282fc48d7..176c1862cb9b 100644 --- a/Documentation/scsi/scsi_fc_transport.txt +++ b/Documentation/scsi/scsi_fc_transport.rst @@ -1,8 +1,13 @@ - SCSI FC Tansport - ============================================= +.. SPDX-License-Identifier: GPL-2.0 + +================ +SCSI FC Tansport +================ Date: 11/18/2008 -Kernel Revisions for features: + +Kernel Revisions for features:: + rports : <<TBS>> vports : 2.6.22 bsg support : 2.6.30 (?TBD?) @@ -12,25 +17,27 @@ Introduction ============ This file documents the features and components of the SCSI FC Transport. It also provides documents the API between the transport and FC LLDDs. -The FC transport can be found at: + +The FC transport can be found at:: + drivers/scsi/scsi_transport_fc.c include/scsi/scsi_transport_fc.h include/scsi/scsi_netlink_fc.h include/scsi/scsi_bsg_fc.h -This file is found at Documentation/scsi/scsi_fc_transport.txt +This file is found at Documentation/scsi/scsi_fc_transport.rst FC Remote Ports (rports) -======================================================================== +======================== << To Be Supplied >> FC Virtual Ports (vports) -======================================================================== +========================= -Overview: -------------------------------- +Overview +-------- New FC standards have defined mechanisms which allows for a single physical port to appear on as multiple communication ports. Using the N_Port Id @@ -61,12 +68,14 @@ Overview: Thus, whether a FC port is based on a physical port or on a virtual port, each will appear as a unique scsi_host with its own target and lun space. - Note: At this time, the transport is written to create only NPIV-based + .. Note:: + At this time, the transport is written to create only NPIV-based vports. However, consideration was given to VF-based vports and it should be a minor change to add support if needed. The remaining discussion will concentrate on NPIV. - Note: World Wide Name assignment (and uniqueness guarantees) are left + .. Note:: + World Wide Name assignment (and uniqueness guarantees) are left up to an administrative entity controlling the vport. For example, if vports are to be associated with virtual machines, a XEN mgmt utility would be responsible for creating wwpn/wwnn's for the vport, @@ -91,18 +100,29 @@ Device Trees and Vport Objects: port's scsi_host. Here's what to expect in the device tree : - The typical Physical Port's Scsi_Host: + + The typical Physical Port's Scsi_Host:: + /sys/devices/.../host17/ - and it has the typical descendant tree: + + and it has the typical descendant tree:: + /sys/devices/.../host17/rport-17:0-0/target17:0:0/17:0:0:0: - and then the vport is created on the Physical Port: + + and then the vport is created on the Physical Port:: + /sys/devices/.../host17/vport-17:0-0 - and the vport's Scsi_Host is then created: + + and the vport's Scsi_Host is then created:: + /sys/devices/.../host17/vport-17:0-0/host18 - and then the rest of the tree progresses, such as: + + and then the rest of the tree progresses, such as:: + /sys/devices/.../host17/vport-17:0-0/host18/rport-18:0-0/target18:0:0/18:0:0:0: - Here's what to expect in the sysfs tree : + Here's what to expect in the sysfs tree:: + scsi_hosts: /sys/class/scsi_host/host17 physical port's scsi_host /sys/class/scsi_host/host18 vport's scsi_host @@ -116,8 +136,8 @@ Device Trees and Vport Objects: /sys/class/fc_remote_ports/rport-18:0-0 rport on the vport -Vport Attributes: -------------------------------- +Vport Attributes +---------------- The new fc_vport class object has the following attributes @@ -184,16 +204,18 @@ Vport Attributes: (e.g. 0x, x, etc). -Vport States: -------------------------------- +Vport States +------------ Vport instantiation consists of two parts: + - Creation with the kernel and LLDD. This means all transport and driver data structures are built up, and device objects created. This is equivalent to a driver "attach" on an adapter, which is independent of the adapter's link state. - Instantiation of the vport on the FC link via ELS traffic, etc. This is equivalent to a "link up" and successful link initialization. + Further information can be found in the interfaces section below for Vport Creation. @@ -227,6 +249,7 @@ Vport States: FC_VPORT_NO_FABRIC_SUPP - No Fabric Support The vport is not operational. One of the following conditions were encountered: + - The FC topology is not Point-to-Point - The FC port is not connected to an F_Port - The F_Port has indicated that NPIV is not supported. @@ -251,32 +274,53 @@ Vport States: The following state table indicates the different state transitions: - State Event New State - -------------------------------------------------------------------- - n/a Initialization Unknown - Unknown: Link Down Linkdown - Link Up & Loop No Fabric Support - Link Up & no Fabric No Fabric Support - Link Up & FLOGI response No Fabric Support - indicates no NPIV support - Link Up & FDISC being sent Initializing - Disable request Disable - Linkdown: Link Up Unknown - Initializing: FDISC ACC Active - FDISC LS_RJT w/ no resources No Fabric Resources - FDISC LS_RJT w/ invalid Fabric Rejected WWN - pname or invalid nport_id - FDISC LS_RJT failed for Vport Failed - other reasons - Link Down Linkdown - Disable request Disable - Disable: Enable request Unknown - Active: LOGO received from fabric Fabric Logout - Link Down Linkdown - Disable request Disable - Fabric Logout: Link still up Unknown + +------------------+--------------------------------+---------------------+ + | State | Event | New State | + +==================+================================+=====================+ + | n/a | Initialization | Unknown | + +------------------+--------------------------------+---------------------+ + | Unknown: | Link Down | Linkdown | + | +--------------------------------+---------------------+ + | | Link Up & Loop | No Fabric Support | + | +--------------------------------+---------------------+ + | | Link Up & no Fabric | No Fabric Support | + | +--------------------------------+---------------------+ + | | Link Up & FLOGI response | No Fabric Support | + | | indicates no NPIV support | | + | +--------------------------------+---------------------+ + | | Link Up & FDISC being sent | Initializing | + | +--------------------------------+---------------------+ + | | Disable request | Disable | + +------------------+--------------------------------+---------------------+ + | Linkdown: | Link Up | Unknown | + +------------------+--------------------------------+---------------------+ + | Initializing: | FDISC ACC | Active | + | +--------------------------------+---------------------+ + | | FDISC LS_RJT w/ no resources | No Fabric Resources | + | +--------------------------------+---------------------+ + | | FDISC LS_RJT w/ invalid | Fabric Rejected WWN | + | | pname or invalid nport_id | | + | +--------------------------------+---------------------+ + | | FDISC LS_RJT failed for | Vport Failed | + | | other reasons | | + | +--------------------------------+---------------------+ + | | Link Down | Linkdown | + | +--------------------------------+---------------------+ + | | Disable request | Disable | + +------------------+--------------------------------+---------------------+ + | Disable: | Enable request | Unknown | + +------------------+--------------------------------+---------------------+ + | Active: | LOGO received from fabric | Fabric Logout | + | +--------------------------------+---------------------+ + | | Link Down | Linkdown | + | +--------------------------------+---------------------+ + | | Disable request | Disable | + +------------------+--------------------------------+---------------------+ + | Fabric Logout: | Link still up | Unknown | + +------------------+--------------------------------+---------------------+ + +The following 4 error states all have the same transitions:: - The following 4 error states all have the same transitions: No Fabric Support: No Fabric Resources: Fabric Rejected WWN: @@ -285,8 +329,8 @@ Vport States: Link goes down Linkdown -Transport <-> LLDD Interfaces : -------------------------------- +Transport <-> LLDD Interfaces +----------------------------- Vport support by LLDD: @@ -300,14 +344,17 @@ Vport support by LLDD: Vport Creation: - The LLDD vport_create() syntax is: + The LLDD vport_create() syntax is:: int vport_create(struct fc_vport *vport, bool disable) - where: - vport: Is the newly allocated vport object - disable: If "true", the vport is to be created in a disabled stated. + where: + + ======= =========================================================== + vport Is the newly allocated vport object + disable If "true", the vport is to be created in a disabled stated. If "false", the vport is to be enabled upon creation. + ======= =========================================================== When a request is made to create a new vport (via sgio/netlink, or the vport_create fc_host attribute), the transport will validate that the LLDD @@ -317,6 +364,7 @@ Vport Creation: LLDD's vport_create() function with the newly allocated vport object. As mentioned above, vport creation is divided into two parts: + - Creation with the kernel and LLDD. This means all transport and driver data structures are built up, and device objects created. This is equivalent to a driver "attach" on an adapter, which is @@ -329,6 +377,7 @@ Vport Creation: infrastructure exists to support NPIV, and complete the first part of vport creation (data structure build up) before returning. We do not hinge vport_create() on the link-side operation mainly because: + - The link may be down. It is not a failure if it is. It simply means the vport is in an inoperable state until the link comes up. This is consistent with the link bouncing post vport creation. @@ -337,11 +386,15 @@ Vport Creation: FC adapter. The vport_create is synonymous with driver attachment to the adapter, which is independent of link state. - Note: special error codes have been defined to delineate infrastructure + .. Note:: + + special error codes have been defined to delineate infrastructure failure cases for quicker resolution. The expected behavior for the LLDD's vport_create() function is: + - Validate Infrastructure: + - If the driver or adapter cannot support another vport, whether due to improper firmware, (a lie about) max_npiv, or a lack of some other resource - return VPCERR_UNSUPPORTED. @@ -349,17 +402,21 @@ Vport Creation: the adapter and detects an overlap - return VPCERR_BAD_WWN. - If the driver detects the topology is loop, non-fabric, or the FLOGI did not support NPIV - return VPCERR_NO_FABRIC_SUPP. + - Allocate data structures. If errors are encountered, such as out of memory conditions, return the respective negative Exxx error code. - If the role is FCP Initiator, the LLDD is to : + - Call scsi_host_alloc() to allocate a scsi_host for the vport. - Call scsi_add_host(new_shost, &vport->dev) to start the scsi_host and bind it as a child of the vport device. - Initializes the fc_host attribute values. + - Kick of further vport state transitions based on the disable flag and link state - and return success (zero). LLDD Implementers Notes: + - It is suggested that there be a different fc_function_templates for the physical port and the virtual port. The physical port's template would have the vport_create, vport_delete, and vport_disable functions, @@ -373,14 +430,17 @@ Vport Creation: Vport Disable/Enable: - The LLDD vport_disable() syntax is: + The LLDD vport_disable() syntax is:: int vport_disable(struct fc_vport *vport, bool disable) - where: - vport: Is vport to be enabled or disabled - disable: If "true", the vport is to be disabled. + where: + + ======= ======================================= + vport Is vport to be enabled or disabled + disable If "true", the vport is to be disabled. If "false", the vport is to be enabled. + ======= ======================================= When a request is made to change the disabled state on a vport, the transport will validate the request against the existing vport state. @@ -401,11 +461,12 @@ Vport Disable/Enable: Vport Deletion: - The LLDD vport_delete() syntax is: + The LLDD vport_delete() syntax is:: int vport_delete(struct fc_vport *vport) - where: + where: + vport: Is vport to delete When a request is made to delete a vport (via sgio/netlink, or via the @@ -443,39 +504,42 @@ Transport supplied functions The following functions are supplied by the FC-transport for use by LLDs. - fc_vport_create - create a vport - fc_vport_terminate - detach and remove a vport - -Details: - -/** - * fc_vport_create - Admin App or LLDD requests creation of a vport - * @shost: scsi host the virtual port is connected to. - * @ids: The world wide names, FC4 port roles, etc for - * the virtual port. - * - * Notes: - * This routine assumes no locks are held on entry. - */ -struct fc_vport * -fc_vport_create(struct Scsi_Host *shost, struct fc_vport_identifiers *ids) - -/** - * fc_vport_terminate - Admin App or LLDD requests termination of a vport - * @vport: fc_vport to be terminated - * - * Calls the LLDD vport_delete() function, then deallocates and removes - * the vport from the shost and object tree. - * - * Notes: - * This routine assumes no locks are held on entry. - */ -int -fc_vport_terminate(struct fc_vport *vport) + ================== ========================= + fc_vport_create create a vport + fc_vport_terminate detach and remove a vport + ================== ========================= + +Details:: + + /** + * fc_vport_create - Admin App or LLDD requests creation of a vport + * @shost: scsi host the virtual port is connected to. + * @ids: The world wide names, FC4 port roles, etc for + * the virtual port. + * + * Notes: + * This routine assumes no locks are held on entry. + */ + struct fc_vport * + fc_vport_create(struct Scsi_Host *shost, struct fc_vport_identifiers *ids) + + /** + * fc_vport_terminate - Admin App or LLDD requests termination of a vport + * @vport: fc_vport to be terminated + * + * Calls the LLDD vport_delete() function, then deallocates and removes + * the vport from the shost and object tree. + * + * Notes: + * This routine assumes no locks are held on entry. + */ + int + fc_vport_terminate(struct fc_vport *vport) FC BSG support (CT & ELS passthru, and more) -======================================================================== +============================================ + << To Be Supplied >> diff --git a/Documentation/scsi/scsi_mid_low_api.rst b/Documentation/scsi/scsi_mid_low_api.rst new file mode 100644 index 000000000000..5358bc10689e --- /dev/null +++ b/Documentation/scsi/scsi_mid_low_api.rst @@ -0,0 +1,1313 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============================================= +SCSI mid_level - lower_level driver interface +============================================= + +Introduction +============ +This document outlines the interface between the Linux SCSI mid level and +SCSI lower level drivers. Lower level drivers (LLDs) are variously called +host bus adapter (HBA) drivers and host drivers (HD). A "host" in this +context is a bridge between a computer IO bus (e.g. PCI or ISA) and a +single SCSI initiator port on a SCSI transport. An "initiator" port +(SCSI terminology, see SAM-3 at http://www.t10.org) sends SCSI commands +to "target" SCSI ports (e.g. disks). There can be many LLDs in a running +system, but only one per hardware type. Most LLDs can control one or more +SCSI HBAs. Some HBAs contain multiple hosts. + +In some cases the SCSI transport is an external bus that already has +its own subsystem in Linux (e.g. USB and ieee1394). In such cases the +SCSI subsystem LLD is a software bridge to the other driver subsystem. +Examples are the usb-storage driver (found in the drivers/usb/storage +directory) and the ieee1394/sbp2 driver (found in the drivers/ieee1394 +directory). + +For example, the aic7xxx LLD controls Adaptec SCSI parallel interface +(SPI) controllers based on that company's 7xxx chip series. The aic7xxx +LLD can be built into the kernel or loaded as a module. There can only be +one aic7xxx LLD running in a Linux system but it may be controlling many +HBAs. These HBAs might be either on PCI daughter-boards or built into +the motherboard (or both). Some aic7xxx based HBAs are dual controllers +and thus represent two hosts. Like most modern HBAs, each aic7xxx host +has its own PCI device address. [The one-to-one correspondence between +a SCSI host and a PCI device is common but not required (e.g. with +ISA adapters).] + +The SCSI mid level isolates an LLD from other layers such as the SCSI +upper layer drivers and the block layer. + +This version of the document roughly matches linux kernel version 2.6.8 . + +Documentation +============= +There is a SCSI documentation directory within the kernel source tree, +typically Documentation/scsi . Most documents are in plain +(i.e. ASCII) text. This file is named scsi_mid_low_api.txt and can be +found in that directory. A more recent copy of this document may be found +at http://web.archive.org/web/20070107183357rn_1/sg.torque.net/scsi/. +Many LLDs are documented there (e.g. aic7xxx.txt). The SCSI mid-level is +briefly described in scsi.txt which contains a url to a document +describing the SCSI subsystem in the lk 2.4 series. Two upper level +drivers have documents in that directory: st.txt (SCSI tape driver) and +scsi-generic.txt (for the sg driver). + +Some documentation (or urls) for LLDs may be found in the C source code +or in the same directory as the C source code. For example to find a url +about the USB mass storage driver see the +/usr/src/linux/drivers/usb/storage directory. + +Driver structure +================ +Traditionally an LLD for the SCSI subsystem has been at least two files in +the drivers/scsi directory. For example, a driver called "xyz" has a header +file "xyz.h" and a source file "xyz.c". [Actually there is no good reason +why this couldn't all be in one file; the header file is superfluous.] Some +drivers that have been ported to several operating systems have more than +two files. For example the aic7xxx driver has separate files for generic +and OS-specific code (e.g. FreeBSD and Linux). Such drivers tend to have +their own directory under the drivers/scsi directory. + +When a new LLD is being added to Linux, the following files (found in the +drivers/scsi directory) will need some attention: Makefile and Kconfig . +It is probably best to study how existing LLDs are organized. + +As the 2.5 series development kernels evolve into the 2.6 series +production series, changes are being introduced into this interface. An +example of this is driver initialization code where there are now 2 models +available. The older one, similar to what was found in the lk 2.4 series, +is based on hosts that are detected at HBA driver load time. This will be +referred to the "passive" initialization model. The newer model allows HBAs +to be hot plugged (and unplugged) during the lifetime of the LLD and will +be referred to as the "hotplug" initialization model. The newer model is +preferred as it can handle both traditional SCSI equipment that is +permanently connected as well as modern "SCSI" devices (e.g. USB or +IEEE 1394 connected digital cameras) that are hotplugged. Both +initialization models are discussed in the following sections. + +An LLD interfaces to the SCSI subsystem several ways: + + a) directly invoking functions supplied by the mid level + b) passing a set of function pointers to a registration function + supplied by the mid level. The mid level will then invoke these + functions at some point in the future. The LLD will supply + implementations of these functions. + c) direct access to instances of well known data structures maintained + by the mid level + +Those functions in group a) are listed in a section entitled "Mid level +supplied functions" below. + +Those functions in group b) are listed in a section entitled "Interface +functions" below. Their function pointers are placed in the members of +"struct scsi_host_template", an instance of which is passed to +scsi_host_alloc() [#]_. Those interface functions that the LLD does not +wish to supply should have NULL placed in the corresponding member of +struct scsi_host_template. Defining an instance of struct +scsi_host_template at file scope will cause NULL to be placed in function +pointer members not explicitly initialized. + +Those usages in group c) should be handled with care, especially in a +"hotplug" environment. LLDs should be aware of the lifetime of instances +that are shared with the mid level and other layers. + +All functions defined within an LLD and all data defined at file scope +should be static. For example the slave_alloc() function in an LLD +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. + + +Hotplug initialization model +============================ +In this model an LLD controls when SCSI hosts are introduced and removed +from the SCSI subsystem. Hosts can be introduced as early as driver +initialization and removed as late as driver shutdown. Typically a driver +will respond to a sysfs probe() callback that indicates an HBA has been +detected. After confirming that the new device is one that the LLD wants +to control, the LLD will initialize the HBA and then register a new host +with the SCSI mid level. + +During LLD initialization the driver should register itself with the +appropriate IO bus on which it expects to find HBA(s) (e.g. the PCI bus). +This can probably be done via sysfs. Any driver parameters (especially +those that are writable after the driver is loaded) could also be +registered with sysfs at this point. The SCSI mid level first becomes +aware of an LLD when that LLD registers its first HBA. + +At some later time, the LLD becomes aware of an HBA and what follows +is a typical sequence of calls between the LLD and the mid level. +This example shows the mid level scanning the newly introduced HBA for 3 +scsi devices of which only the first 2 respond:: + + HBA PROBE: assume 2 SCSI devices found in scan + LLD mid level LLD + ===-------------------=========--------------------===------ + scsi_host_alloc() --> + scsi_add_host() ----> + scsi_scan_host() -------+ + | + slave_alloc() + slave_configure() --> scsi_change_queue_depth() + | + slave_alloc() + slave_configure() + | + slave_alloc() *** + slave_destroy() *** + + + *** For scsi devices that the mid level tries to scan but do not + respond, a slave_alloc(), slave_destroy() pair is called. + +If the LLD wants to adjust the default queue settings, it can invoke +scsi_change_queue_depth() in its slave_configure() routine. + +When an HBA is being removed it could be as part of an orderly shutdown +associated with the LLD module being unloaded (e.g. with the "rmmod" +command) or in response to a "hot unplug" indicated by sysfs()'s +remove() callback being invoked. In either case, the sequence is the +same:: + + HBA REMOVE: assume 2 SCSI devices attached + LLD mid level LLD + ===----------------------=========-----------------===------ + scsi_remove_host() ---------+ + | + slave_destroy() + slave_destroy() + scsi_host_put() + +It may be useful for a LLD to keep track of struct Scsi_Host instances +(a pointer is returned by scsi_host_alloc()). Such instances are "owned" +by the mid-level. struct Scsi_Host instances are freed from +scsi_host_put() when the reference count hits zero. + +Hot unplugging an HBA that controls a disk which is processing SCSI +commands on a mounted file system is an interesting situation. Reference +counting logic is being introduced into the mid level to cope with many +of the issues involved. See the section on reference counting below. + + +The hotplug concept may be extended to SCSI devices. Currently, when an +HBA is added, the scsi_scan_host() function causes a scan for SCSI devices +attached to the HBA's SCSI transport. On newer SCSI transports the HBA +may become aware of a new SCSI device _after_ the scan has completed. +An LLD can use this sequence to make the mid level aware of a SCSI device:: + + SCSI DEVICE hotplug + LLD mid level LLD + ===-------------------=========--------------------===------ + scsi_add_device() ------+ + | + slave_alloc() + slave_configure() [--> scsi_change_queue_depth()] + +In a similar fashion, an LLD may become aware that a SCSI device has been +removed (unplugged) or the connection to it has been interrupted. Some +existing SCSI transports (e.g. SPI) may not become aware that a SCSI +device has been removed until a subsequent SCSI command fails which will +probably cause that device to be set offline by the mid level. An LLD that +detects the removal of a SCSI device can instigate its removal from +upper layers with this sequence:: + + SCSI DEVICE hot unplug + LLD mid level LLD + ===----------------------=========-----------------===------ + scsi_remove_device() -------+ + | + slave_destroy() + +It may be useful for an LLD to keep track of struct scsi_device instances +(a pointer is passed as the parameter to slave_alloc() and +slave_configure() callbacks). Such instances are "owned" by the mid-level. +struct scsi_device instances are freed after slave_destroy(). + + +Reference Counting +================== +The Scsi_Host structure has had reference counting infrastructure added. +This effectively spreads the ownership of struct Scsi_Host instances +across the various SCSI layers which use them. Previously such instances +were exclusively owned by the mid level. LLDs would not usually need to +directly manipulate these reference counts but there may be some cases +where they do. + +There are 3 reference counting functions of interest associated with +struct Scsi_Host: + + - scsi_host_alloc(): + returns a pointer to new instance of struct + Scsi_Host which has its reference count ^^ set to 1 + + - scsi_host_get(): + adds 1 to the reference count of the given instance + + - scsi_host_put(): + decrements 1 from the reference count of the given + instance. If the reference count reaches 0 then the given instance + is freed + +The scsi_device structure has had reference counting infrastructure added. +This effectively spreads the ownership of struct scsi_device instances +across the various SCSI layers which use them. Previously such instances +were exclusively owned by the mid level. See the access functions declared +towards the end of include/scsi/scsi_device.h . If an LLD wants to keep +a copy of a pointer to a scsi_device instance it should use scsi_device_get() +to bump its reference count. When it is finished with the pointer it can +use scsi_device_put() to decrement its reference count (and potentially +delete it). + +.. Note:: + + struct Scsi_Host actually has 2 reference counts which are manipulated + in parallel by these functions. + + +Conventions +=========== +First, Linus Torvalds's thoughts on C coding style can be found in the +Documentation/process/coding-style.rst file. + +Next, there is a movement to "outlaw" typedefs introducing synonyms for +struct tags. Both can be still found in the SCSI subsystem, but +the typedefs have been moved to a single file, scsi_typedefs.h to +make their future removal easier, for example: +"typedef struct scsi_cmnd Scsi_Cmnd;" + +Also, most C99 enhancements are encouraged to the extent they are supported +by the relevant gcc compilers. So C99 style structure and array +initializers are encouraged where appropriate. Don't go too far, +VLAs are not properly supported yet. An exception to this is the use of +``//`` style comments; ``/*...*/`` comments are still preferred in Linux. + +Well written, tested and documented code, need not be re-formatted to +comply with the above conventions. For example, the aic7xxx driver +comes to Linux from FreeBSD and Adaptec's own labs. No doubt FreeBSD +and Adaptec have their own coding conventions. + + +Mid level supplied functions +============================ +These functions are supplied by the SCSI mid level for use by LLDs. +The names (i.e. entry points) of these functions are exported +so an LLD that is a module can access them. The kernel will +arrange for the SCSI mid level to be loaded and initialized before any LLD +is initialized. The functions below are listed alphabetically and their +names all start with ``scsi_``. + +Summary: + + - scsi_add_device - creates new scsi device (lu) instance + - scsi_add_host - perform sysfs registration and set up transport class + - scsi_change_queue_depth - change the queue depth on a SCSI device + - scsi_bios_ptable - return copy of block device's partition table + - scsi_block_requests - prevent further commands being queued to given host + - scsi_host_alloc - return a new scsi_host instance whose refcount==1 + - scsi_host_get - increments Scsi_Host instance's refcount + - scsi_host_put - decrements Scsi_Host instance's refcount (free if 0) + - scsi_register - create and register a scsi host adapter instance. + - scsi_remove_device - detach and remove a SCSI device + - scsi_remove_host - detach and remove all SCSI devices owned by host + - scsi_report_bus_reset - report scsi _bus_ reset observed + - scsi_scan_host - scan SCSI bus + - scsi_track_queue_full - track successive QUEUE_FULL events + - scsi_unblock_requests - allow further commands to be queued to given host + - scsi_unregister - [calls scsi_host_put()] + + +Details:: + + /** + * scsi_add_device - creates new scsi device (lu) instance + * @shost: pointer to scsi host instance + * @channel: channel number (rarely other than 0) + * @id: target id number + * @lun: logical unit number + * + * Returns pointer to new struct scsi_device instance or + * ERR_PTR(-ENODEV) (or some other bent pointer) if something is + * wrong (e.g. no lu responds at given address) + * + * Might block: yes + * + * Notes: This call is usually performed internally during a scsi + * bus scan when an HBA is added (i.e. scsi_scan_host()). So it + * should only be called if the HBA becomes aware of a new scsi + * device (lu) after scsi_scan_host() has completed. If successful + * this call can lead to slave_alloc() and slave_configure() callbacks + * into the LLD. + * + * Defined in: drivers/scsi/scsi_scan.c + **/ + struct scsi_device * scsi_add_device(struct Scsi_Host *shost, + unsigned int channel, + unsigned int id, unsigned int lun) + + + /** + * scsi_add_host - perform sysfs registration and set up transport class + * @shost: pointer to scsi host instance + * @dev: pointer to struct device of type scsi class + * + * Returns 0 on success, negative errno of failure (e.g. -ENOMEM) + * + * Might block: no + * + * Notes: Only required in "hotplug initialization model" after a + * successful call to scsi_host_alloc(). This function does not + * scan the bus; this can be done by calling scsi_scan_host() or + * in some other transport-specific way. The LLD must set up + * the transport template before calling this function and may only + * access the transport class data after this function has been called. + * + * Defined in: drivers/scsi/hosts.c + **/ + int scsi_add_host(struct Scsi_Host *shost, struct device * dev) + + + /** + * scsi_change_queue_depth - allow LLD to change queue depth on a SCSI device + * @sdev: pointer to SCSI device to change queue depth on + * @tags Number of tags allowed if tagged queuing enabled, + * or number of commands the LLD can queue up + * in non-tagged mode (as per cmd_per_lun). + * + * Returns nothing + * + * Might block: no + * + * Notes: Can be invoked any time on a SCSI device controlled by this + * LLD. [Specifically during and after slave_configure() and prior to + * slave_destroy().] Can safely be invoked from interrupt code. + * + * Defined in: drivers/scsi/scsi.c [see source code for more notes] + * + **/ + int scsi_change_queue_depth(struct scsi_device *sdev, int tags) + + + /** + * scsi_bios_ptable - return copy of block device's partition table + * @dev: pointer to block device + * + * Returns pointer to partition table, or NULL for failure + * + * Might block: yes + * + * Notes: Caller owns memory returned (free with kfree() ) + * + * Defined in: drivers/scsi/scsicam.c + **/ + unsigned char *scsi_bios_ptable(struct block_device *dev) + + + /** + * scsi_block_requests - prevent further commands being queued to given host + * + * @shost: pointer to host to block commands on + * + * Returns nothing + * + * Might block: no + * + * Notes: There is no timer nor any other means by which the requests + * get unblocked other than the LLD calling scsi_unblock_requests(). + * + * Defined in: drivers/scsi/scsi_lib.c + **/ + void scsi_block_requests(struct Scsi_Host * shost) + + + /** + * scsi_host_alloc - create a scsi host adapter instance and perform basic + * initialization. + * @sht: pointer to scsi host template + * @privsize: extra bytes to allocate in hostdata array (which is the + * last member of the returned Scsi_Host instance) + * + * Returns pointer to new Scsi_Host instance or NULL on failure + * + * Might block: yes + * + * Notes: When this call returns to the LLD, the SCSI bus scan on + * this host has _not_ yet been done. + * The hostdata array (by default zero length) is a per host scratch + * area for the LLD's exclusive use. + * Both associated refcounting objects have their refcount set to 1. + * Full registration (in sysfs) and a bus scan are performed later when + * scsi_add_host() and scsi_scan_host() are called. + * + * Defined in: drivers/scsi/hosts.c . + **/ + struct Scsi_Host * scsi_host_alloc(struct scsi_host_template * sht, + int privsize) + + + /** + * scsi_host_get - increment Scsi_Host instance refcount + * @shost: pointer to struct Scsi_Host instance + * + * Returns nothing + * + * Might block: currently may block but may be changed to not block + * + * Notes: Actually increments the counts in two sub-objects + * + * Defined in: drivers/scsi/hosts.c + **/ + void scsi_host_get(struct Scsi_Host *shost) + + + /** + * scsi_host_put - decrement Scsi_Host instance refcount, free if 0 + * @shost: pointer to struct Scsi_Host instance + * + * Returns nothing + * + * Might block: currently may block but may be changed to not block + * + * Notes: Actually decrements the counts in two sub-objects. If the + * latter refcount reaches 0, the Scsi_Host instance is freed. + * The LLD need not worry exactly when the Scsi_Host instance is + * freed, it just shouldn't access the instance after it has balanced + * out its refcount usage. + * + * Defined in: drivers/scsi/hosts.c + **/ + void scsi_host_put(struct Scsi_Host *shost) + + + /** + * scsi_register - create and register a scsi host adapter instance. + * @sht: pointer to scsi host template + * @privsize: extra bytes to allocate in hostdata array (which is the + * last member of the returned Scsi_Host instance) + * + * Returns pointer to new Scsi_Host instance or NULL on failure + * + * Might block: yes + * + * Notes: When this call returns to the LLD, the SCSI bus scan on + * this host has _not_ yet been done. + * The hostdata array (by default zero length) is a per host scratch + * area for the LLD. + * + * Defined in: drivers/scsi/hosts.c . + **/ + struct Scsi_Host * scsi_register(struct scsi_host_template * sht, + int privsize) + + + /** + * scsi_remove_device - detach and remove a SCSI device + * @sdev: a pointer to a scsi device instance + * + * Returns value: 0 on success, -EINVAL if device not attached + * + * Might block: yes + * + * Notes: If an LLD becomes aware that a scsi device (lu) has + * been removed but its host is still present then it can request + * the removal of that scsi device. If successful this call will + * lead to the slave_destroy() callback being invoked. sdev is an + * invalid pointer after this call. + * + * Defined in: drivers/scsi/scsi_sysfs.c . + **/ + int scsi_remove_device(struct scsi_device *sdev) + + + /** + * scsi_remove_host - detach and remove all SCSI devices owned by host + * @shost: a pointer to a scsi host instance + * + * Returns value: 0 on success, 1 on failure (e.g. LLD busy ??) + * + * Might block: yes + * + * Notes: Should only be invoked if the "hotplug initialization + * model" is being used. It should be called _prior_ to + * scsi_unregister(). + * + * Defined in: drivers/scsi/hosts.c . + **/ + int scsi_remove_host(struct Scsi_Host *shost) + + + /** + * scsi_report_bus_reset - report scsi _bus_ reset observed + * @shost: a pointer to a scsi host involved + * @channel: channel (within) host on which scsi bus reset occurred + * + * Returns nothing + * + * Might block: no + * + * Notes: This only needs to be called if the reset is one which + * originates from an unknown location. Resets originated by the + * mid level itself don't need to call this, but there should be + * no harm. The main purpose of this is to make sure that a + * CHECK_CONDITION is properly treated. + * + * Defined in: drivers/scsi/scsi_error.c . + **/ + void scsi_report_bus_reset(struct Scsi_Host * shost, int channel) + + + /** + * scsi_scan_host - scan SCSI bus + * @shost: a pointer to a scsi host instance + * + * Might block: yes + * + * Notes: Should be called after scsi_add_host() + * + * Defined in: drivers/scsi/scsi_scan.c + **/ + void scsi_scan_host(struct Scsi_Host *shost) + + + /** + * scsi_track_queue_full - track successive QUEUE_FULL events on given + * device to determine if and when there is a need + * to adjust the queue depth on the device. + * @sdev: pointer to SCSI device instance + * @depth: Current number of outstanding SCSI commands on this device, + * not counting the one returned as QUEUE_FULL. + * + * Returns 0 - no change needed + * >0 - adjust queue depth to this new depth + * -1 - drop back to untagged operation using host->cmd_per_lun + * as the untagged command depth + * + * Might block: no + * + * Notes: LLDs may call this at any time and we will do "The Right + * Thing"; interrupt context safe. + * + * Defined in: drivers/scsi/scsi.c . + **/ + int scsi_track_queue_full(struct scsi_device *sdev, int depth) + + + /** + * scsi_unblock_requests - allow further commands to be queued to given host + * + * @shost: pointer to host to unblock commands on + * + * Returns nothing + * + * Might block: no + * + * Defined in: drivers/scsi/scsi_lib.c . + **/ + void scsi_unblock_requests(struct Scsi_Host * shost) + + + /** + * scsi_unregister - unregister and free memory used by host instance + * @shp: pointer to scsi host instance to unregister. + * + * Returns nothing + * + * Might block: no + * + * Notes: Should not be invoked if the "hotplug initialization + * model" is being used. Called internally by exit_this_scsi_driver() + * in the "passive initialization model". Hence a LLD has no need to + * call this function directly. + * + * Defined in: drivers/scsi/hosts.c . + **/ + void scsi_unregister(struct Scsi_Host * shp) + + + + +Interface Functions +=================== +Interface functions are supplied (defined) by LLDs and their function +pointers are placed in an instance of struct scsi_host_template which +is passed to scsi_host_alloc() [or scsi_register() / init_this_scsi_driver()]. +Some are mandatory. Interface functions should be declared static. The +accepted convention is that driver "xyz" will declare its slave_configure() +function as:: + + static int xyz_slave_configure(struct scsi_device * sdev); + +and so forth for all interface functions listed below. + +A pointer to this function should be placed in the 'slave_configure' member +of a "struct scsi_host_template" instance. A pointer to such an instance +should be passed to the mid level's scsi_host_alloc() [or scsi_register() / +init_this_scsi_driver()]. + +The interface functions are also described in the include/scsi/scsi_host.h +file immediately above their definition point in "struct scsi_host_template". +In some cases more detail is given in scsi_host.h than below. + +The interface functions are listed below in alphabetical order. + +Summary: + + - bios_param - fetch head, sector, cylinder info for a disk + - 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 + - eh_device_reset_handler - issue SCSI device reset + - eh_host_reset_handler - reset host (host bus adapter) + - info - supply information about given host + - ioctl - driver can respond to ioctls + - proc_info - supports /proc/scsi/{driver_name}/{host_no} + - queuecommand - queue scsi command, invoke 'done' on completion + - 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 + + +Details:: + + /** + * bios_param - fetch head, sector, cylinder info for a disk + * @sdev: pointer to scsi device context (defined in + * include/scsi/scsi_device.h) + * @bdev: pointer to block device context (defined in fs.h) + * @capacity: device size (in 512 byte sectors) + * @params: three element array to place output: + * params[0] number of heads (max 255) + * params[1] number of sectors (max 63) + * params[2] number of cylinders + * + * Return value is ignored + * + * Locks: none + * + * Calling context: process (sd) + * + * Notes: an arbitrary geometry (based on READ CAPACITY) is used + * if this function is not provided. The params array is + * pre-initialized with made up values just in case this function + * doesn't output anything. + * + * Optionally defined in: LLD + **/ + int bios_param(struct scsi_device * sdev, struct block_device *bdev, + sector_t capacity, int params[3]) + + + /** + * eh_timed_out - The timer for the command has just fired + * @scp: identifies command timing out + * + * Returns: + * + * EH_HANDLED: I fixed the error, please complete the command + * EH_RESET_TIMER: I need more time, reset the timer and + * begin counting again + * EH_NOT_HANDLED Begin normal error recovery + * + * + * Locks: None held + * + * Calling context: interrupt + * + * Notes: This is to give the LLD an opportunity to do local recovery. + * This recovery is limited to determining if the outstanding command + * will ever complete. You may not abort and restart the command from + * this callback. + * + * Optionally defined in: LLD + **/ + int eh_timed_out(struct scsi_cmnd * scp) + + + /** + * eh_abort_handler - abort command associated with scp + * @scp: identifies command to be aborted + * + * Returns SUCCESS if command aborted else FAILED + * + * Locks: None held + * + * Calling context: kernel thread + * + * Notes: If 'no_async_abort' is defined this callback + * will be invoked from scsi_eh thread. No other commands + * will then be queued on current host during eh. + * Otherwise it will be called whenever scsi_times_out() + * is called due to a command timeout. + * + * Optionally defined in: LLD + **/ + int eh_abort_handler(struct scsi_cmnd * scp) + + + /** + * eh_bus_reset_handler - issue SCSI bus reset + * @scp: SCSI bus that contains this device should be reset + * + * Returns SUCCESS if command aborted else FAILED + * + * Locks: None held + * + * Calling context: kernel thread + * + * Notes: Invoked from scsi_eh thread. No other commands will be + * queued on current host during eh. + * + * Optionally defined in: LLD + **/ + int eh_bus_reset_handler(struct scsi_cmnd * scp) + + + /** + * eh_device_reset_handler - issue SCSI device reset + * @scp: identifies SCSI device to be reset + * + * Returns SUCCESS if command aborted else FAILED + * + * Locks: None held + * + * Calling context: kernel thread + * + * Notes: Invoked from scsi_eh thread. No other commands will be + * queued on current host during eh. + * + * Optionally defined in: LLD + **/ + int eh_device_reset_handler(struct scsi_cmnd * scp) + + + /** + * eh_host_reset_handler - reset host (host bus adapter) + * @scp: SCSI host that contains this device should be reset + * + * Returns SUCCESS if command aborted else FAILED + * + * Locks: None held + * + * Calling context: kernel thread + * + * Notes: Invoked from scsi_eh thread. No other commands will be + * queued on current host during eh. + * With the default eh_strategy in place, if none of the _abort_, + * _device_reset_, _bus_reset_ or this eh handler function are + * defined (or they all return FAILED) then the device in question + * will be set offline whenever eh is invoked. + * + * Optionally defined in: LLD + **/ + int eh_host_reset_handler(struct scsi_cmnd * scp) + + + /** + * info - supply information about given host: driver name plus data + * to distinguish given host + * @shp: host to supply information about + * + * Return ASCII null terminated string. [This driver is assumed to + * manage the memory pointed to and maintain it, typically for the + * lifetime of this host.] + * + * Locks: none + * + * Calling context: process + * + * Notes: Often supplies PCI or ISA information such as IO addresses + * and interrupt numbers. If not supplied struct Scsi_Host::name used + * instead. It is assumed the returned information fits on one line + * (i.e. does not included embedded newlines). + * The SCSI_IOCTL_PROBE_HOST ioctl yields the string returned by this + * function (or struct Scsi_Host::name if this function is not + * available). + * In a similar manner, init_this_scsi_driver() outputs to the console + * each host's "info" (or name) for the driver it is registering. + * Also if proc_info() is not supplied, the output of this function + * is used instead. + * + * Optionally defined in: LLD + **/ + const char * info(struct Scsi_Host * shp) + + + /** + * ioctl - driver can respond to ioctls + * @sdp: device that ioctl was issued for + * @cmd: ioctl number + * @arg: pointer to read or write data from. Since it points to + * user space, should use appropriate kernel functions + * (e.g. copy_from_user() ). In the Unix style this argument + * can also be viewed as an unsigned long. + * + * Returns negative "errno" value when there is a problem. 0 or a + * positive value indicates success and is returned to the user space. + * + * Locks: none + * + * Calling context: process + * + * Notes: The SCSI subsystem uses a "trickle down" ioctl model. + * The user issues an ioctl() against an upper level driver + * (e.g. /dev/sdc) and if the upper level driver doesn't recognize + * the 'cmd' then it is passed to the SCSI mid level. If the SCSI + * mid level does not recognize it, then the LLD that controls + * the device receives the ioctl. According to recent Unix standards + * unsupported ioctl() 'cmd' numbers should return -ENOTTY. + * + * Optionally defined in: LLD + **/ + int ioctl(struct scsi_device *sdp, int cmd, void *arg) + + + /** + * proc_info - supports /proc/scsi/{driver_name}/{host_no} + * @buffer: anchor point to output to (0==writeto1_read0) or fetch from + * (1==writeto1_read0). + * @start: where "interesting" data is written to. Ignored when + * 1==writeto1_read0. + * @offset: offset within buffer 0==writeto1_read0 is actually + * interested in. Ignored when 1==writeto1_read0 . + * @length: maximum (or actual) extent of buffer + * @host_no: host number of interest (struct Scsi_Host::host_no) + * @writeto1_read0: 1 -> data coming from user space towards driver + * (e.g. "echo some_string > /proc/scsi/xyz/2") + * 0 -> user what data from this driver + * (e.g. "cat /proc/scsi/xyz/2") + * + * Returns length when 1==writeto1_read0. Otherwise number of chars + * output to buffer past offset. + * + * Locks: none held + * + * Calling context: process + * + * Notes: Driven from scsi_proc.c which interfaces to proc_fs. proc_fs + * support can now be configured out of the scsi subsystem. + * + * Optionally defined in: LLD + **/ + int proc_info(char * buffer, char ** start, off_t offset, + int length, int host_no, int writeto1_read0) + + + /** + * queuecommand - queue scsi command, invoke scp->scsi_done on completion + * @shost: pointer to the scsi host object + * @scp: pointer to scsi command object + * + * Returns 0 on success. + * + * If there's a failure, return either: + * + * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or + * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full + * + * On both of these returns, the mid-layer will requeue the I/O + * + * - if the return is SCSI_MLQUEUE_DEVICE_BUSY, only that particular + * device will be paused, and it will be unpaused when a command to + * the device returns (or after a brief delay if there are no more + * outstanding commands to it). Commands to other devices continue + * to be processed normally. + * + * - if the return is SCSI_MLQUEUE_HOST_BUSY, all I/O to the host + * is paused and will be unpaused when any command returns from + * the host (or after a brief delay if there are no outstanding + * commands to the host). + * + * For compatibility with earlier versions of queuecommand, any + * other return value is treated the same as + * SCSI_MLQUEUE_HOST_BUSY. + * + * Other types of errors that are detected immediately may be + * flagged by setting scp->result to an appropriate value, + * invoking the scp->scsi_done callback, and then returning 0 + * from this function. If the command is not performed + * immediately (and the LLD is starting (or will start) the given + * command) then this function should place 0 in scp->result and + * return 0. + * + * Command ownership. If the driver returns zero, it owns the + * command and must take responsibility for ensuring the + * scp->scsi_done callback is executed. Note: the driver may + * call scp->scsi_done before returning zero, but after it has + * called scp->scsi_done, it may not return any value other than + * zero. If the driver makes a non-zero return, it must not + * execute the command's scsi_done callback at any time. + * + * Locks: up to and including 2.6.36, struct Scsi_Host::host_lock + * held on entry (with "irqsave") and is expected to be + * held on return. From 2.6.37 onwards, queuecommand is + * called without any locks held. + * + * Calling context: in interrupt (soft irq) or process context + * + * Notes: This function should be relatively fast. Normally it + * will not wait for IO to complete. Hence the scp->scsi_done + * callback is invoked (often directly from an interrupt service + * routine) some time after this function has returned. In some + * cases (e.g. pseudo adapter drivers that manufacture the + * response to a SCSI INQUIRY) the scp->scsi_done callback may be + * invoked before this function returns. If the scp->scsi_done + * callback is not invoked within a certain period the SCSI mid + * level will commence error processing. If a status of CHECK + * CONDITION is placed in "result" when the scp->scsi_done + * callback is invoked, then the LLD driver should perform + * autosense and fill in the struct scsi_cmnd::sense_buffer + * array. The scsi_cmnd::sense_buffer array is zeroed prior to + * the mid level queuing a command to an LLD. + * + * Defined in: LLD + **/ + int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp) + + + /** + * slave_alloc - prior to any commands being sent to a new device + * (i.e. just prior to scan) this call is made + * @sdp: pointer to new device (about to be scanned) + * + * Returns 0 if ok. Any other return is assumed to be an error and + * the device is ignored. + * + * Locks: none + * + * Calling context: process + * + * Notes: Allows the driver to allocate any resources for a device + * prior to its initial scan. The corresponding scsi device may not + * exist but the mid level is just about to scan for it (i.e. send + * and INQUIRY command plus ...). If a device is found then + * slave_configure() will be called while if a device is not found + * slave_destroy() is called. + * For more details see the include/scsi/scsi_host.h file. + * + * Optionally defined in: LLD + **/ + int slave_alloc(struct scsi_device *sdp) + + + /** + * slave_configure - driver fine tuning for given device just after it + * has been first scanned (i.e. it responded to an + * INQUIRY) + * @sdp: device that has just been attached + * + * Returns 0 if ok. Any other return is assumed to be an error and + * the device is taken offline. [offline devices will _not_ have + * slave_destroy() called on them so clean up resources.] + * + * Locks: none + * + * Calling context: process + * + * Notes: Allows the driver to inspect the response to the initial + * INQUIRY done by the scanning code and take appropriate action. + * For more details see the include/scsi/scsi_host.h file. + * + * Optionally defined in: LLD + **/ + int slave_configure(struct scsi_device *sdp) + + + /** + * slave_destroy - given device is about to be shut down. All + * activity has ceased on this device. + * @sdp: device that is about to be shut down + * + * Returns nothing + * + * Locks: none + * + * Calling context: process + * + * Notes: Mid level structures for given device are still in place + * but are about to be torn down. Any per device resources allocated + * by this driver for given device should be freed now. No further + * commands will be sent for this sdp instance. [However the device + * could be re-attached in the future in which case a new instance + * of struct scsi_device would be supplied by future slave_alloc() + * and slave_configure() calls.] + * + * Optionally defined in: LLD + **/ + void slave_destroy(struct scsi_device *sdp) + + + +Data Structures +=============== +struct scsi_host_template +------------------------- +There is one "struct scsi_host_template" instance per LLD [#]_. It is +typically initialized as a file scope static in a driver's header file. That +way members that are not explicitly initialized will be set to 0 or NULL. +Member of interest: + + name + - name of driver (may contain spaces, please limit to + less than 80 characters) + + proc_name + - name used in "/proc/scsi/<proc_name>/<host_no>" and + by sysfs in one of its "drivers" directories. Hence + "proc_name" should only contain characters acceptable + to a Unix file name. + + ``(*queuecommand)()`` + - primary callback that the mid level uses to inject + SCSI commands into an LLD. + +The structure is defined and commented in include/scsi/scsi_host.h + +.. [#] In extreme situations a single driver may have several instances + if it controls several different classes of hardware (e.g. an LLD + that handles both ISA and PCI cards and has a separate instance of + struct scsi_host_template for each class). + +struct Scsi_Host +---------------- +There is one struct Scsi_Host instance per host (HBA) that an LLD +controls. The struct Scsi_Host structure has many members in common +with "struct scsi_host_template". When a new struct Scsi_Host instance +is created (in scsi_host_alloc() in hosts.c) those common members are +initialized from the driver's struct scsi_host_template instance. Members +of interest: + + host_no + - system wide unique number that is used for identifying + this host. Issued in ascending order from 0. + can_queue + - must be greater than 0; do not send more than can_queue + commands to the adapter. + this_id + - scsi id of host (scsi initiator) or -1 if not known + sg_tablesize + - maximum scatter gather elements allowed by host. + Set this to SG_ALL or less to avoid chained SG lists. + Must be at least 1. + max_sectors + - maximum number of sectors (usually 512 bytes) allowed + in a single SCSI command. The default value of 0 leads + to a setting of SCSI_DEFAULT_MAX_SECTORS (defined in + scsi_host.h) which is currently set to 1024. So for a + disk the maximum transfer size is 512 KB when max_sectors + is not defined. Note that this size may not be sufficient + for disk firmware uploads. + cmd_per_lun + - maximum number of commands that can be queued on devices + controlled by the host. Overridden by LLD calls to + scsi_change_queue_depth(). + unchecked_isa_dma + - 1=>only use bottom 16 MB of ram (ISA DMA addressing + restriction), 0=>can use full 32 bit (or better) DMA + address space + no_async_abort + - 1=>Asynchronous aborts are not supported + - 0=>Timed-out commands will be aborted asynchronously + hostt + - pointer to driver's struct scsi_host_template from which + this struct Scsi_Host instance was spawned + hostt->proc_name + - name of LLD. This is the driver name that sysfs uses + transportt + - pointer to driver's struct scsi_transport_template instance + (if any). FC and SPI transports currently supported. + sh_list + - a double linked list of pointers to all struct Scsi_Host + instances (currently ordered by ascending host_no) + my_devices + - a double linked list of pointers to struct scsi_device + instances that belong to this host. + hostdata[0] + - area reserved for LLD at end of struct Scsi_Host. Size + is set by the second argument (named 'xtr_bytes') to + scsi_host_alloc() or scsi_register(). + vendor_id + - a unique value that identifies the vendor supplying + the LLD for the Scsi_Host. Used most often in validating + vendor-specific message requests. Value consists of an + identifier type and a vendor-specific value. + See scsi_netlink.h for a description of valid formats. + +The scsi_host structure is defined in include/scsi/scsi_host.h + +struct scsi_device +------------------ +Generally, there is one instance of this structure for each SCSI logical unit +on a host. Scsi devices connected to a host are uniquely identified by a +channel number, target id and logical unit number (lun). +The structure is defined in include/scsi/scsi_device.h + +struct scsi_cmnd +---------------- +Instances of this structure convey SCSI commands to the LLD and responses +back to the mid level. The SCSI mid level will ensure that no more SCSI +commands become queued against the LLD than are indicated by +scsi_change_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will +be at least one instance of struct scsi_cmnd available for each SCSI device. +Members of interest: + + cmnd + - array containing SCSI command + cmnd_len + - length (in bytes) of SCSI command + sc_data_direction + - direction of data transfer in data phase. See + "enum dma_data_direction" in include/linux/dma-mapping.h + request_bufflen + - number of data bytes to transfer (0 if no data phase) + use_sg + - ==0 -> no scatter gather list, hence transfer data + to/from request_buffer + - >0 -> scatter gather list (actually an array) in + request_buffer with use_sg elements + request_buffer + - either contains data buffer or scatter gather list + depending on the setting of use_sg. Scatter gather + elements are defined by 'struct scatterlist' found + in include/linux/scatterlist.h . + done + - function pointer that should be invoked by LLD when the + SCSI command is completed (successfully or otherwise). + Should only be called by an LLD if the LLD has accepted + the command (i.e. queuecommand() returned or will return + 0). The LLD may invoke 'done' prior to queuecommand() + finishing. + result + - should be set by LLD prior to calling 'done'. A value + of 0 implies a successfully completed command (and all + data (if any) has been transferred to or from the SCSI + target device). 'result' is a 32 bit unsigned integer that + can be viewed as 4 related bytes. The SCSI status value is + in the LSB. See include/scsi/scsi.h status_byte(), + msg_byte(), host_byte() and driver_byte() macros and + related constants. + sense_buffer + - an array (maximum size: SCSI_SENSE_BUFFERSIZE bytes) that + should be written when the SCSI status (LSB of 'result') + is set to CHECK_CONDITION (2). When CHECK_CONDITION is + set, if the top nibble of sense_buffer[0] has the value 7 + then the mid level will assume the sense_buffer array + contains a valid SCSI sense buffer; otherwise the mid + level will issue a REQUEST_SENSE SCSI command to + retrieve the sense buffer. The latter strategy is error + prone in the presence of command queuing so the LLD should + always "auto-sense". + device + - pointer to scsi_device object that this command is + associated with. + resid + - an LLD should set this signed integer to the requested + transfer length (i.e. 'request_bufflen') less the number + of bytes that are actually transferred. 'resid' is + preset to 0 so an LLD can ignore it if it cannot detect + underruns (overruns should be rare). If possible an LLD + should set 'resid' prior to invoking 'done'. The most + interesting case is data transfers from a SCSI target + device (e.g. READs) that underrun. + underflow + - LLD should place (DID_ERROR << 16) in 'result' if + actual number of bytes transferred is less than this + figure. Not many LLDs implement this check and some that + do just output an error message to the log rather than + report a DID_ERROR. Better for an LLD to implement + 'resid'. + +It is recommended that a LLD set 'resid' on data transfers from a SCSI +target device (e.g. READs). It is especially important that 'resid' is set +when such data transfers have sense keys of MEDIUM ERROR and HARDWARE ERROR +(and possibly RECOVERED ERROR). In these cases if a LLD is in doubt how much +data has been received then the safest approach is to indicate no bytes have +been received. For example: to indicate that no valid data has been received +a LLD might use these helpers:: + + scsi_set_resid(SCpnt, scsi_bufflen(SCpnt)); + +where 'SCpnt' is a pointer to a scsi_cmnd object. To indicate only three 512 +bytes blocks has been received 'resid' could be set like this:: + + scsi_set_resid(SCpnt, scsi_bufflen(SCpnt) - (3 * 512)); + +The scsi_cmnd structure is defined in include/scsi/scsi_cmnd.h + + +Locks +===== +Each struct Scsi_Host instance has a spin_lock called struct +Scsi_Host::default_lock which is initialized in scsi_host_alloc() [found in +hosts.c]. Within the same function the struct Scsi_Host::host_lock pointer +is initialized to point at default_lock. Thereafter lock and unlock +operations performed by the mid level use the struct Scsi_Host::host_lock +pointer. Previously drivers could override the host_lock pointer but +this is not allowed anymore. + + +Autosense +========= +Autosense (or auto-sense) is defined in the SAM-2 document as "the +automatic return of sense data to the application client coincident +with the completion of a SCSI command" when a status of CHECK CONDITION +occurs. LLDs should perform autosense. This should be done when the LLD +detects a CHECK CONDITION status by either: + + a) instructing the SCSI protocol (e.g. SCSI Parallel Interface (SPI)) + to perform an extra data in phase on such responses + b) or, the LLD issuing a REQUEST SENSE command itself + +Either way, when a status of CHECK CONDITION is detected, the mid level +decides whether the LLD has performed autosense by checking struct +scsi_cmnd::sense_buffer[0] . If this byte has an upper nibble of 7 (or 0xf) +then autosense is assumed to have taken place. If it has another value (and +this byte is initialized to 0 before each command) then the mid level will +issue a REQUEST SENSE command. + +In the presence of queued commands the "nexus" that maintains sense +buffer data from the command that failed until a following REQUEST SENSE +may get out of synchronization. This is why it is best for the LLD +to perform autosense. + + +Changes since lk 2.4 series +=========================== +io_request_lock has been replaced by several finer grained locks. The lock +relevant to LLDs is struct Scsi_Host::host_lock and there is +one per SCSI host. + +The older error handling mechanism has been removed. This means the +LLD interface functions abort() and reset() have been removed. +The struct scsi_host_template::use_new_eh_code flag has been removed. + +In the 2.4 series the SCSI subsystem configuration descriptions were +aggregated with the configuration descriptions from all other Linux +subsystems in the Documentation/Configure.help file. In the 2.6 series, +the SCSI subsystem now has its own (much smaller) drivers/scsi/Kconfig +file that contains both configuration and help information. + +struct SHT has been renamed to struct scsi_host_template. + +Addition of the "hotplug initialization model" and many extra functions +to support it. + + +Credits +======= +The following people have contributed to this document: + + - Mike Anderson <andmike at us dot ibm dot com> + - James Bottomley <James dot Bottomley at hansenpartnership dot com> + - Patrick Mansfield <patmans at us dot ibm dot com> + - Christoph Hellwig <hch at infradead dot org> + - Doug Ledford <dledford at redhat dot com> + - Andries Brouwer <Andries dot Brouwer at cwi dot nl> + - Randy Dunlap <rdunlap at xenotime dot net> + - Alan Stern <stern at rowland dot harvard dot edu> + + +Douglas Gilbert +dgilbert at interlog dot com + +21st September 2004 diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt deleted file mode 100644 index 537f04728487..000000000000 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ /dev/null @@ -1,1259 +0,0 @@ - Linux Kernel 2.6 series - SCSI mid_level - lower_level driver interface - ============================================= - -Introduction -============ -This document outlines the interface between the Linux SCSI mid level and -SCSI lower level drivers. Lower level drivers (LLDs) are variously called -host bus adapter (HBA) drivers and host drivers (HD). A "host" in this -context is a bridge between a computer IO bus (e.g. PCI or ISA) and a -single SCSI initiator port on a SCSI transport. An "initiator" port -(SCSI terminology, see SAM-3 at http://www.t10.org) sends SCSI commands -to "target" SCSI ports (e.g. disks). There can be many LLDs in a running -system, but only one per hardware type. Most LLDs can control one or more -SCSI HBAs. Some HBAs contain multiple hosts. - -In some cases the SCSI transport is an external bus that already has -its own subsystem in Linux (e.g. USB and ieee1394). In such cases the -SCSI subsystem LLD is a software bridge to the other driver subsystem. -Examples are the usb-storage driver (found in the drivers/usb/storage -directory) and the ieee1394/sbp2 driver (found in the drivers/ieee1394 -directory). - -For example, the aic7xxx LLD controls Adaptec SCSI parallel interface -(SPI) controllers based on that company's 7xxx chip series. The aic7xxx -LLD can be built into the kernel or loaded as a module. There can only be -one aic7xxx LLD running in a Linux system but it may be controlling many -HBAs. These HBAs might be either on PCI daughter-boards or built into -the motherboard (or both). Some aic7xxx based HBAs are dual controllers -and thus represent two hosts. Like most modern HBAs, each aic7xxx host -has its own PCI device address. [The one-to-one correspondence between -a SCSI host and a PCI device is common but not required (e.g. with -ISA adapters).] - -The SCSI mid level isolates an LLD from other layers such as the SCSI -upper layer drivers and the block layer. - -This version of the document roughly matches linux kernel version 2.6.8 . - -Documentation -============= -There is a SCSI documentation directory within the kernel source tree, -typically Documentation/scsi . Most documents are in plain -(i.e. ASCII) text. This file is named scsi_mid_low_api.txt and can be -found in that directory. A more recent copy of this document may be found -at http://web.archive.org/web/20070107183357rn_1/sg.torque.net/scsi/. -Many LLDs are documented there (e.g. aic7xxx.txt). The SCSI mid-level is -briefly described in scsi.txt which contains a url to a document -describing the SCSI subsystem in the lk 2.4 series. Two upper level -drivers have documents in that directory: st.txt (SCSI tape driver) and -scsi-generic.txt (for the sg driver). - -Some documentation (or urls) for LLDs may be found in the C source code -or in the same directory as the C source code. For example to find a url -about the USB mass storage driver see the -/usr/src/linux/drivers/usb/storage directory. - -Driver structure -================ -Traditionally an LLD for the SCSI subsystem has been at least two files in -the drivers/scsi directory. For example, a driver called "xyz" has a header -file "xyz.h" and a source file "xyz.c". [Actually there is no good reason -why this couldn't all be in one file; the header file is superfluous.] Some -drivers that have been ported to several operating systems have more than -two files. For example the aic7xxx driver has separate files for generic -and OS-specific code (e.g. FreeBSD and Linux). Such drivers tend to have -their own directory under the drivers/scsi directory. - -When a new LLD is being added to Linux, the following files (found in the -drivers/scsi directory) will need some attention: Makefile and Kconfig . -It is probably best to study how existing LLDs are organized. - -As the 2.5 series development kernels evolve into the 2.6 series -production series, changes are being introduced into this interface. An -example of this is driver initialization code where there are now 2 models -available. The older one, similar to what was found in the lk 2.4 series, -is based on hosts that are detected at HBA driver load time. This will be -referred to the "passive" initialization model. The newer model allows HBAs -to be hot plugged (and unplugged) during the lifetime of the LLD and will -be referred to as the "hotplug" initialization model. The newer model is -preferred as it can handle both traditional SCSI equipment that is -permanently connected as well as modern "SCSI" devices (e.g. USB or -IEEE 1394 connected digital cameras) that are hotplugged. Both -initialization models are discussed in the following sections. - -An LLD interfaces to the SCSI subsystem several ways: - a) directly invoking functions supplied by the mid level - b) passing a set of function pointers to a registration function - supplied by the mid level. The mid level will then invoke these - functions at some point in the future. The LLD will supply - implementations of these functions. - c) direct access to instances of well known data structures maintained - by the mid level - -Those functions in group a) are listed in a section entitled "Mid level -supplied functions" below. - -Those functions in group b) are listed in a section entitled "Interface -functions" below. Their function pointers are placed in the members of -"struct scsi_host_template", an instance of which is passed to -scsi_host_alloc() ** . Those interface functions that the LLD does not -wish to supply should have NULL placed in the corresponding member of -struct scsi_host_template. Defining an instance of struct -scsi_host_template at file scope will cause NULL to be placed in function - pointer members not explicitly initialized. - -Those usages in group c) should be handled with care, especially in a -"hotplug" environment. LLDs should be aware of the lifetime of instances -that are shared with the mid level and other layers. - -All functions defined within an LLD and all data defined at file scope -should be static. For example the slave_alloc() function in an LLD -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. - - -Hotplug initialization model -============================ -In this model an LLD controls when SCSI hosts are introduced and removed -from the SCSI subsystem. Hosts can be introduced as early as driver -initialization and removed as late as driver shutdown. Typically a driver -will respond to a sysfs probe() callback that indicates an HBA has been -detected. After confirming that the new device is one that the LLD wants -to control, the LLD will initialize the HBA and then register a new host -with the SCSI mid level. - -During LLD initialization the driver should register itself with the -appropriate IO bus on which it expects to find HBA(s) (e.g. the PCI bus). -This can probably be done via sysfs. Any driver parameters (especially -those that are writable after the driver is loaded) could also be -registered with sysfs at this point. The SCSI mid level first becomes -aware of an LLD when that LLD registers its first HBA. - -At some later time, the LLD becomes aware of an HBA and what follows -is a typical sequence of calls between the LLD and the mid level. -This example shows the mid level scanning the newly introduced HBA for 3 -scsi devices of which only the first 2 respond: - - HBA PROBE: assume 2 SCSI devices found in scan -LLD mid level LLD -===-------------------=========--------------------===------ -scsi_host_alloc() --> -scsi_add_host() ----> -scsi_scan_host() -------+ - | - slave_alloc() - slave_configure() --> scsi_change_queue_depth() - | - slave_alloc() - slave_configure() - | - slave_alloc() *** - slave_destroy() *** ------------------------------------------------------------- - -If the LLD wants to adjust the default queue settings, it can invoke -scsi_change_queue_depth() in its slave_configure() routine. - -*** For scsi devices that the mid level tries to scan but do not - respond, a slave_alloc(), slave_destroy() pair is called. - -When an HBA is being removed it could be as part of an orderly shutdown -associated with the LLD module being unloaded (e.g. with the "rmmod" -command) or in response to a "hot unplug" indicated by sysfs()'s -remove() callback being invoked. In either case, the sequence is the -same: - - HBA REMOVE: assume 2 SCSI devices attached -LLD mid level LLD -===----------------------=========-----------------===------ -scsi_remove_host() ---------+ - | - slave_destroy() - slave_destroy() -scsi_host_put() ------------------------------------------------------------- - -It may be useful for a LLD to keep track of struct Scsi_Host instances -(a pointer is returned by scsi_host_alloc()). Such instances are "owned" -by the mid-level. struct Scsi_Host instances are freed from -scsi_host_put() when the reference count hits zero. - -Hot unplugging an HBA that controls a disk which is processing SCSI -commands on a mounted file system is an interesting situation. Reference -counting logic is being introduced into the mid level to cope with many -of the issues involved. See the section on reference counting below. - - -The hotplug concept may be extended to SCSI devices. Currently, when an -HBA is added, the scsi_scan_host() function causes a scan for SCSI devices -attached to the HBA's SCSI transport. On newer SCSI transports the HBA -may become aware of a new SCSI device _after_ the scan has completed. -An LLD can use this sequence to make the mid level aware of a SCSI device: - - SCSI DEVICE hotplug -LLD mid level LLD -===-------------------=========--------------------===------ -scsi_add_device() ------+ - | - slave_alloc() - slave_configure() [--> scsi_change_queue_depth()] ------------------------------------------------------------- - -In a similar fashion, an LLD may become aware that a SCSI device has been -removed (unplugged) or the connection to it has been interrupted. Some -existing SCSI transports (e.g. SPI) may not become aware that a SCSI -device has been removed until a subsequent SCSI command fails which will -probably cause that device to be set offline by the mid level. An LLD that -detects the removal of a SCSI device can instigate its removal from -upper layers with this sequence: - - SCSI DEVICE hot unplug -LLD mid level LLD -===----------------------=========-----------------===------ -scsi_remove_device() -------+ - | - slave_destroy() ------------------------------------------------------------- - -It may be useful for an LLD to keep track of struct scsi_device instances -(a pointer is passed as the parameter to slave_alloc() and -slave_configure() callbacks). Such instances are "owned" by the mid-level. -struct scsi_device instances are freed after slave_destroy(). - - -Reference Counting -================== -The Scsi_Host structure has had reference counting infrastructure added. -This effectively spreads the ownership of struct Scsi_Host instances -across the various SCSI layers which use them. Previously such instances -were exclusively owned by the mid level. LLDs would not usually need to -directly manipulate these reference counts but there may be some cases -where they do. - -There are 3 reference counting functions of interest associated with -struct Scsi_Host: - - scsi_host_alloc(): returns a pointer to new instance of struct - Scsi_Host which has its reference count ^^ set to 1 - - scsi_host_get(): adds 1 to the reference count of the given instance - - scsi_host_put(): decrements 1 from the reference count of the given - instance. If the reference count reaches 0 then the given instance - is freed - -The scsi_device structure has had reference counting infrastructure added. -This effectively spreads the ownership of struct scsi_device instances -across the various SCSI layers which use them. Previously such instances -were exclusively owned by the mid level. See the access functions declared -towards the end of include/scsi/scsi_device.h . If an LLD wants to keep -a copy of a pointer to a scsi_device instance it should use scsi_device_get() -to bump its reference count. When it is finished with the pointer it can -use scsi_device_put() to decrement its reference count (and potentially -delete it). - -^^ struct Scsi_Host actually has 2 reference counts which are manipulated -in parallel by these functions. - - -Conventions -=========== -First, Linus Torvalds's thoughts on C coding style can be found in the -Documentation/process/coding-style.rst file. - -Next, there is a movement to "outlaw" typedefs introducing synonyms for -struct tags. Both can be still found in the SCSI subsystem, but -the typedefs have been moved to a single file, scsi_typedefs.h to -make their future removal easier, for example: -"typedef struct scsi_cmnd Scsi_Cmnd;" - -Also, most C99 enhancements are encouraged to the extent they are supported -by the relevant gcc compilers. So C99 style structure and array -initializers are encouraged where appropriate. Don't go too far, -VLAs are not properly supported yet. An exception to this is the use of -"//" style comments; /*...*/ comments are still preferred in Linux. - -Well written, tested and documented code, need not be re-formatted to -comply with the above conventions. For example, the aic7xxx driver -comes to Linux from FreeBSD and Adaptec's own labs. No doubt FreeBSD -and Adaptec have their own coding conventions. - - -Mid level supplied functions -============================ -These functions are supplied by the SCSI mid level for use by LLDs. -The names (i.e. entry points) of these functions are exported -so an LLD that is a module can access them. The kernel will -arrange for the SCSI mid level to be loaded and initialized before any LLD -is initialized. The functions below are listed alphabetically and their -names all start with "scsi_". - -Summary: - scsi_add_device - creates new scsi device (lu) instance - scsi_add_host - perform sysfs registration and set up transport class - scsi_change_queue_depth - change the queue depth on a SCSI device - scsi_bios_ptable - return copy of block device's partition table - scsi_block_requests - prevent further commands being queued to given host - scsi_host_alloc - return a new scsi_host instance whose refcount==1 - scsi_host_get - increments Scsi_Host instance's refcount - scsi_host_put - decrements Scsi_Host instance's refcount (free if 0) - scsi_register - create and register a scsi host adapter instance. - scsi_remove_device - detach and remove a SCSI device - scsi_remove_host - detach and remove all SCSI devices owned by host - scsi_report_bus_reset - report scsi _bus_ reset observed - scsi_scan_host - scan SCSI bus - scsi_track_queue_full - track successive QUEUE_FULL events - scsi_unblock_requests - allow further commands to be queued to given host - scsi_unregister - [calls scsi_host_put()] - - -Details: - -/** - * scsi_add_device - creates new scsi device (lu) instance - * @shost: pointer to scsi host instance - * @channel: channel number (rarely other than 0) - * @id: target id number - * @lun: logical unit number - * - * Returns pointer to new struct scsi_device instance or - * ERR_PTR(-ENODEV) (or some other bent pointer) if something is - * wrong (e.g. no lu responds at given address) - * - * Might block: yes - * - * Notes: This call is usually performed internally during a scsi - * bus scan when an HBA is added (i.e. scsi_scan_host()). So it - * should only be called if the HBA becomes aware of a new scsi - * device (lu) after scsi_scan_host() has completed. If successful - * this call can lead to slave_alloc() and slave_configure() callbacks - * into the LLD. - * - * Defined in: drivers/scsi/scsi_scan.c - **/ -struct scsi_device * scsi_add_device(struct Scsi_Host *shost, - unsigned int channel, - unsigned int id, unsigned int lun) - - -/** - * scsi_add_host - perform sysfs registration and set up transport class - * @shost: pointer to scsi host instance - * @dev: pointer to struct device of type scsi class - * - * Returns 0 on success, negative errno of failure (e.g. -ENOMEM) - * - * Might block: no - * - * Notes: Only required in "hotplug initialization model" after a - * successful call to scsi_host_alloc(). This function does not - * scan the bus; this can be done by calling scsi_scan_host() or - * in some other transport-specific way. The LLD must set up - * the transport template before calling this function and may only - * access the transport class data after this function has been called. - * - * Defined in: drivers/scsi/hosts.c - **/ -int scsi_add_host(struct Scsi_Host *shost, struct device * dev) - - -/** - * scsi_change_queue_depth - allow LLD to change queue depth on a SCSI device - * @sdev: pointer to SCSI device to change queue depth on - * @tags Number of tags allowed if tagged queuing enabled, - * or number of commands the LLD can queue up - * in non-tagged mode (as per cmd_per_lun). - * - * Returns nothing - * - * Might block: no - * - * Notes: Can be invoked any time on a SCSI device controlled by this - * LLD. [Specifically during and after slave_configure() and prior to - * slave_destroy().] Can safely be invoked from interrupt code. - * - * Defined in: drivers/scsi/scsi.c [see source code for more notes] - * - **/ -int scsi_change_queue_depth(struct scsi_device *sdev, int tags) - - -/** - * scsi_bios_ptable - return copy of block device's partition table - * @dev: pointer to block device - * - * Returns pointer to partition table, or NULL for failure - * - * Might block: yes - * - * Notes: Caller owns memory returned (free with kfree() ) - * - * Defined in: drivers/scsi/scsicam.c - **/ -unsigned char *scsi_bios_ptable(struct block_device *dev) - - -/** - * scsi_block_requests - prevent further commands being queued to given host - * - * @shost: pointer to host to block commands on - * - * Returns nothing - * - * Might block: no - * - * Notes: There is no timer nor any other means by which the requests - * get unblocked other than the LLD calling scsi_unblock_requests(). - * - * Defined in: drivers/scsi/scsi_lib.c -**/ -void scsi_block_requests(struct Scsi_Host * shost) - - -/** - * scsi_host_alloc - create a scsi host adapter instance and perform basic - * initialization. - * @sht: pointer to scsi host template - * @privsize: extra bytes to allocate in hostdata array (which is the - * last member of the returned Scsi_Host instance) - * - * Returns pointer to new Scsi_Host instance or NULL on failure - * - * Might block: yes - * - * Notes: When this call returns to the LLD, the SCSI bus scan on - * this host has _not_ yet been done. - * The hostdata array (by default zero length) is a per host scratch - * area for the LLD's exclusive use. - * Both associated refcounting objects have their refcount set to 1. - * Full registration (in sysfs) and a bus scan are performed later when - * scsi_add_host() and scsi_scan_host() are called. - * - * Defined in: drivers/scsi/hosts.c . - **/ -struct Scsi_Host * scsi_host_alloc(struct scsi_host_template * sht, - int privsize) - - -/** - * scsi_host_get - increment Scsi_Host instance refcount - * @shost: pointer to struct Scsi_Host instance - * - * Returns nothing - * - * Might block: currently may block but may be changed to not block - * - * Notes: Actually increments the counts in two sub-objects - * - * Defined in: drivers/scsi/hosts.c - **/ -void scsi_host_get(struct Scsi_Host *shost) - - -/** - * scsi_host_put - decrement Scsi_Host instance refcount, free if 0 - * @shost: pointer to struct Scsi_Host instance - * - * Returns nothing - * - * Might block: currently may block but may be changed to not block - * - * Notes: Actually decrements the counts in two sub-objects. If the - * latter refcount reaches 0, the Scsi_Host instance is freed. - * The LLD need not worry exactly when the Scsi_Host instance is - * freed, it just shouldn't access the instance after it has balanced - * out its refcount usage. - * - * Defined in: drivers/scsi/hosts.c - **/ -void scsi_host_put(struct Scsi_Host *shost) - - -/** - * scsi_register - create and register a scsi host adapter instance. - * @sht: pointer to scsi host template - * @privsize: extra bytes to allocate in hostdata array (which is the - * last member of the returned Scsi_Host instance) - * - * Returns pointer to new Scsi_Host instance or NULL on failure - * - * Might block: yes - * - * Notes: When this call returns to the LLD, the SCSI bus scan on - * this host has _not_ yet been done. - * The hostdata array (by default zero length) is a per host scratch - * area for the LLD. - * - * Defined in: drivers/scsi/hosts.c . - **/ -struct Scsi_Host * scsi_register(struct scsi_host_template * sht, - int privsize) - - -/** - * scsi_remove_device - detach and remove a SCSI device - * @sdev: a pointer to a scsi device instance - * - * Returns value: 0 on success, -EINVAL if device not attached - * - * Might block: yes - * - * Notes: If an LLD becomes aware that a scsi device (lu) has - * been removed but its host is still present then it can request - * the removal of that scsi device. If successful this call will - * lead to the slave_destroy() callback being invoked. sdev is an - * invalid pointer after this call. - * - * Defined in: drivers/scsi/scsi_sysfs.c . - **/ -int scsi_remove_device(struct scsi_device *sdev) - - -/** - * scsi_remove_host - detach and remove all SCSI devices owned by host - * @shost: a pointer to a scsi host instance - * - * Returns value: 0 on success, 1 on failure (e.g. LLD busy ??) - * - * Might block: yes - * - * Notes: Should only be invoked if the "hotplug initialization - * model" is being used. It should be called _prior_ to - * scsi_unregister(). - * - * Defined in: drivers/scsi/hosts.c . - **/ -int scsi_remove_host(struct Scsi_Host *shost) - - -/** - * scsi_report_bus_reset - report scsi _bus_ reset observed - * @shost: a pointer to a scsi host involved - * @channel: channel (within) host on which scsi bus reset occurred - * - * Returns nothing - * - * Might block: no - * - * Notes: This only needs to be called if the reset is one which - * originates from an unknown location. Resets originated by the - * mid level itself don't need to call this, but there should be - * no harm. The main purpose of this is to make sure that a - * CHECK_CONDITION is properly treated. - * - * Defined in: drivers/scsi/scsi_error.c . - **/ -void scsi_report_bus_reset(struct Scsi_Host * shost, int channel) - - -/** - * scsi_scan_host - scan SCSI bus - * @shost: a pointer to a scsi host instance - * - * Might block: yes - * - * Notes: Should be called after scsi_add_host() - * - * Defined in: drivers/scsi/scsi_scan.c - **/ -void scsi_scan_host(struct Scsi_Host *shost) - - -/** - * scsi_track_queue_full - track successive QUEUE_FULL events on given - * device to determine if and when there is a need - * to adjust the queue depth on the device. - * @sdev: pointer to SCSI device instance - * @depth: Current number of outstanding SCSI commands on this device, - * not counting the one returned as QUEUE_FULL. - * - * Returns 0 - no change needed - * >0 - adjust queue depth to this new depth - * -1 - drop back to untagged operation using host->cmd_per_lun - * as the untagged command depth - * - * Might block: no - * - * Notes: LLDs may call this at any time and we will do "The Right - * Thing"; interrupt context safe. - * - * Defined in: drivers/scsi/scsi.c . - **/ -int scsi_track_queue_full(struct scsi_device *sdev, int depth) - - -/** - * scsi_unblock_requests - allow further commands to be queued to given host - * - * @shost: pointer to host to unblock commands on - * - * Returns nothing - * - * Might block: no - * - * Defined in: drivers/scsi/scsi_lib.c . -**/ -void scsi_unblock_requests(struct Scsi_Host * shost) - - -/** - * scsi_unregister - unregister and free memory used by host instance - * @shp: pointer to scsi host instance to unregister. - * - * Returns nothing - * - * Might block: no - * - * Notes: Should not be invoked if the "hotplug initialization - * model" is being used. Called internally by exit_this_scsi_driver() - * in the "passive initialization model". Hence a LLD has no need to - * call this function directly. - * - * Defined in: drivers/scsi/hosts.c . - **/ -void scsi_unregister(struct Scsi_Host * shp) - - - - -Interface Functions -=================== -Interface functions are supplied (defined) by LLDs and their function -pointers are placed in an instance of struct scsi_host_template which -is passed to scsi_host_alloc() [or scsi_register() / init_this_scsi_driver()]. -Some are mandatory. Interface functions should be declared static. The -accepted convention is that driver "xyz" will declare its slave_configure() -function as: - static int xyz_slave_configure(struct scsi_device * sdev); -and so forth for all interface functions listed below. - -A pointer to this function should be placed in the 'slave_configure' member -of a "struct scsi_host_template" instance. A pointer to such an instance -should be passed to the mid level's scsi_host_alloc() [or scsi_register() / -init_this_scsi_driver()]. - -The interface functions are also described in the include/scsi/scsi_host.h -file immediately above their definition point in "struct scsi_host_template". -In some cases more detail is given in scsi_host.h than below. - -The interface functions are listed below in alphabetical order. - -Summary: - bios_param - fetch head, sector, cylinder info for a disk - 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 - eh_device_reset_handler - issue SCSI device reset - eh_host_reset_handler - reset host (host bus adapter) - info - supply information about given host - ioctl - driver can respond to ioctls - proc_info - supports /proc/scsi/{driver_name}/{host_no} - queuecommand - queue scsi command, invoke 'done' on completion - 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 - - -Details: - -/** - * bios_param - fetch head, sector, cylinder info for a disk - * @sdev: pointer to scsi device context (defined in - * include/scsi/scsi_device.h) - * @bdev: pointer to block device context (defined in fs.h) - * @capacity: device size (in 512 byte sectors) - * @params: three element array to place output: - * params[0] number of heads (max 255) - * params[1] number of sectors (max 63) - * params[2] number of cylinders - * - * Return value is ignored - * - * Locks: none - * - * Calling context: process (sd) - * - * Notes: an arbitrary geometry (based on READ CAPACITY) is used - * if this function is not provided. The params array is - * pre-initialized with made up values just in case this function - * doesn't output anything. - * - * Optionally defined in: LLD - **/ - int bios_param(struct scsi_device * sdev, struct block_device *bdev, - sector_t capacity, int params[3]) - - -/** - * eh_timed_out - The timer for the command has just fired - * @scp: identifies command timing out - * - * Returns: - * - * EH_HANDLED: I fixed the error, please complete the command - * EH_RESET_TIMER: I need more time, reset the timer and - * begin counting again - * EH_NOT_HANDLED Begin normal error recovery - * - * - * Locks: None held - * - * Calling context: interrupt - * - * Notes: This is to give the LLD an opportunity to do local recovery. - * This recovery is limited to determining if the outstanding command - * will ever complete. You may not abort and restart the command from - * this callback. - * - * Optionally defined in: LLD - **/ - int eh_timed_out(struct scsi_cmnd * scp) - - -/** - * eh_abort_handler - abort command associated with scp - * @scp: identifies command to be aborted - * - * Returns SUCCESS if command aborted else FAILED - * - * Locks: None held - * - * Calling context: kernel thread - * - * Notes: If 'no_async_abort' is defined this callback - * will be invoked from scsi_eh thread. No other commands - * will then be queued on current host during eh. - * Otherwise it will be called whenever scsi_times_out() - * is called due to a command timeout. - * - * Optionally defined in: LLD - **/ - int eh_abort_handler(struct scsi_cmnd * scp) - - -/** - * eh_bus_reset_handler - issue SCSI bus reset - * @scp: SCSI bus that contains this device should be reset - * - * Returns SUCCESS if command aborted else FAILED - * - * Locks: None held - * - * Calling context: kernel thread - * - * Notes: Invoked from scsi_eh thread. No other commands will be - * queued on current host during eh. - * - * Optionally defined in: LLD - **/ - int eh_bus_reset_handler(struct scsi_cmnd * scp) - - -/** - * eh_device_reset_handler - issue SCSI device reset - * @scp: identifies SCSI device to be reset - * - * Returns SUCCESS if command aborted else FAILED - * - * Locks: None held - * - * Calling context: kernel thread - * - * Notes: Invoked from scsi_eh thread. No other commands will be - * queued on current host during eh. - * - * Optionally defined in: LLD - **/ - int eh_device_reset_handler(struct scsi_cmnd * scp) - - -/** - * eh_host_reset_handler - reset host (host bus adapter) - * @scp: SCSI host that contains this device should be reset - * - * Returns SUCCESS if command aborted else FAILED - * - * Locks: None held - * - * Calling context: kernel thread - * - * Notes: Invoked from scsi_eh thread. No other commands will be - * queued on current host during eh. - * With the default eh_strategy in place, if none of the _abort_, - * _device_reset_, _bus_reset_ or this eh handler function are - * defined (or they all return FAILED) then the device in question - * will be set offline whenever eh is invoked. - * - * Optionally defined in: LLD - **/ - int eh_host_reset_handler(struct scsi_cmnd * scp) - - -/** - * info - supply information about given host: driver name plus data - * to distinguish given host - * @shp: host to supply information about - * - * Return ASCII null terminated string. [This driver is assumed to - * manage the memory pointed to and maintain it, typically for the - * lifetime of this host.] - * - * Locks: none - * - * Calling context: process - * - * Notes: Often supplies PCI or ISA information such as IO addresses - * and interrupt numbers. If not supplied struct Scsi_Host::name used - * instead. It is assumed the returned information fits on one line - * (i.e. does not included embedded newlines). - * The SCSI_IOCTL_PROBE_HOST ioctl yields the string returned by this - * function (or struct Scsi_Host::name if this function is not - * available). - * In a similar manner, init_this_scsi_driver() outputs to the console - * each host's "info" (or name) for the driver it is registering. - * Also if proc_info() is not supplied, the output of this function - * is used instead. - * - * Optionally defined in: LLD - **/ - const char * info(struct Scsi_Host * shp) - - -/** - * ioctl - driver can respond to ioctls - * @sdp: device that ioctl was issued for - * @cmd: ioctl number - * @arg: pointer to read or write data from. Since it points to - * user space, should use appropriate kernel functions - * (e.g. copy_from_user() ). In the Unix style this argument - * can also be viewed as an unsigned long. - * - * Returns negative "errno" value when there is a problem. 0 or a - * positive value indicates success and is returned to the user space. - * - * Locks: none - * - * Calling context: process - * - * Notes: The SCSI subsystem uses a "trickle down" ioctl model. - * The user issues an ioctl() against an upper level driver - * (e.g. /dev/sdc) and if the upper level driver doesn't recognize - * the 'cmd' then it is passed to the SCSI mid level. If the SCSI - * mid level does not recognize it, then the LLD that controls - * the device receives the ioctl. According to recent Unix standards - * unsupported ioctl() 'cmd' numbers should return -ENOTTY. - * - * Optionally defined in: LLD - **/ - int ioctl(struct scsi_device *sdp, int cmd, void *arg) - - -/** - * proc_info - supports /proc/scsi/{driver_name}/{host_no} - * @buffer: anchor point to output to (0==writeto1_read0) or fetch from - * (1==writeto1_read0). - * @start: where "interesting" data is written to. Ignored when - * 1==writeto1_read0. - * @offset: offset within buffer 0==writeto1_read0 is actually - * interested in. Ignored when 1==writeto1_read0 . - * @length: maximum (or actual) extent of buffer - * @host_no: host number of interest (struct Scsi_Host::host_no) - * @writeto1_read0: 1 -> data coming from user space towards driver - * (e.g. "echo some_string > /proc/scsi/xyz/2") - * 0 -> user what data from this driver - * (e.g. "cat /proc/scsi/xyz/2") - * - * Returns length when 1==writeto1_read0. Otherwise number of chars - * output to buffer past offset. - * - * Locks: none held - * - * Calling context: process - * - * Notes: Driven from scsi_proc.c which interfaces to proc_fs. proc_fs - * support can now be configured out of the scsi subsystem. - * - * Optionally defined in: LLD - **/ - int proc_info(char * buffer, char ** start, off_t offset, - int length, int host_no, int writeto1_read0) - - -/** - * queuecommand - queue scsi command, invoke scp->scsi_done on completion - * @shost: pointer to the scsi host object - * @scp: pointer to scsi command object - * - * Returns 0 on success. - * - * If there's a failure, return either: - * - * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or - * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full - * - * On both of these returns, the mid-layer will requeue the I/O - * - * - if the return is SCSI_MLQUEUE_DEVICE_BUSY, only that particular - * device will be paused, and it will be unpaused when a command to - * the device returns (or after a brief delay if there are no more - * outstanding commands to it). Commands to other devices continue - * to be processed normally. - * - * - if the return is SCSI_MLQUEUE_HOST_BUSY, all I/O to the host - * is paused and will be unpaused when any command returns from - * the host (or after a brief delay if there are no outstanding - * commands to the host). - * - * For compatibility with earlier versions of queuecommand, any - * other return value is treated the same as - * SCSI_MLQUEUE_HOST_BUSY. - * - * Other types of errors that are detected immediately may be - * flagged by setting scp->result to an appropriate value, - * invoking the scp->scsi_done callback, and then returning 0 - * from this function. If the command is not performed - * immediately (and the LLD is starting (or will start) the given - * command) then this function should place 0 in scp->result and - * return 0. - * - * Command ownership. If the driver returns zero, it owns the - * command and must take responsibility for ensuring the - * scp->scsi_done callback is executed. Note: the driver may - * call scp->scsi_done before returning zero, but after it has - * called scp->scsi_done, it may not return any value other than - * zero. If the driver makes a non-zero return, it must not - * execute the command's scsi_done callback at any time. - * - * Locks: up to and including 2.6.36, struct Scsi_Host::host_lock - * held on entry (with "irqsave") and is expected to be - * held on return. From 2.6.37 onwards, queuecommand is - * called without any locks held. - * - * Calling context: in interrupt (soft irq) or process context - * - * Notes: This function should be relatively fast. Normally it - * will not wait for IO to complete. Hence the scp->scsi_done - * callback is invoked (often directly from an interrupt service - * routine) some time after this function has returned. In some - * cases (e.g. pseudo adapter drivers that manufacture the - * response to a SCSI INQUIRY) the scp->scsi_done callback may be - * invoked before this function returns. If the scp->scsi_done - * callback is not invoked within a certain period the SCSI mid - * level will commence error processing. If a status of CHECK - * CONDITION is placed in "result" when the scp->scsi_done - * callback is invoked, then the LLD driver should perform - * autosense and fill in the struct scsi_cmnd::sense_buffer - * array. The scsi_cmnd::sense_buffer array is zeroed prior to - * the mid level queuing a command to an LLD. - * - * Defined in: LLD - **/ - int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp) - - -/** - * slave_alloc - prior to any commands being sent to a new device - * (i.e. just prior to scan) this call is made - * @sdp: pointer to new device (about to be scanned) - * - * Returns 0 if ok. Any other return is assumed to be an error and - * the device is ignored. - * - * Locks: none - * - * Calling context: process - * - * Notes: Allows the driver to allocate any resources for a device - * prior to its initial scan. The corresponding scsi device may not - * exist but the mid level is just about to scan for it (i.e. send - * and INQUIRY command plus ...). If a device is found then - * slave_configure() will be called while if a device is not found - * slave_destroy() is called. - * For more details see the include/scsi/scsi_host.h file. - * - * Optionally defined in: LLD - **/ - int slave_alloc(struct scsi_device *sdp) - - -/** - * slave_configure - driver fine tuning for given device just after it - * has been first scanned (i.e. it responded to an - * INQUIRY) - * @sdp: device that has just been attached - * - * Returns 0 if ok. Any other return is assumed to be an error and - * the device is taken offline. [offline devices will _not_ have - * slave_destroy() called on them so clean up resources.] - * - * Locks: none - * - * Calling context: process - * - * Notes: Allows the driver to inspect the response to the initial - * INQUIRY done by the scanning code and take appropriate action. - * For more details see the include/scsi/scsi_host.h file. - * - * Optionally defined in: LLD - **/ - int slave_configure(struct scsi_device *sdp) - - -/** - * slave_destroy - given device is about to be shut down. All - * activity has ceased on this device. - * @sdp: device that is about to be shut down - * - * Returns nothing - * - * Locks: none - * - * Calling context: process - * - * Notes: Mid level structures for given device are still in place - * but are about to be torn down. Any per device resources allocated - * by this driver for given device should be freed now. No further - * commands will be sent for this sdp instance. [However the device - * could be re-attached in the future in which case a new instance - * of struct scsi_device would be supplied by future slave_alloc() - * and slave_configure() calls.] - * - * Optionally defined in: LLD - **/ - void slave_destroy(struct scsi_device *sdp) - - - -Data Structures -=============== -struct scsi_host_template -------------------------- -There is one "struct scsi_host_template" instance per LLD ***. It is -typically initialized as a file scope static in a driver's header file. That -way members that are not explicitly initialized will be set to 0 or NULL. -Member of interest: - name - name of driver (may contain spaces, please limit to - less than 80 characters) - proc_name - name used in "/proc/scsi/<proc_name>/<host_no>" and - by sysfs in one of its "drivers" directories. Hence - "proc_name" should only contain characters acceptable - to a Unix file name. - (*queuecommand)() - primary callback that the mid level uses to inject - SCSI commands into an LLD. -The structure is defined and commented in include/scsi/scsi_host.h - -*** In extreme situations a single driver may have several instances - if it controls several different classes of hardware (e.g. an LLD - that handles both ISA and PCI cards and has a separate instance of - struct scsi_host_template for each class). - -struct Scsi_Host ----------------- -There is one struct Scsi_Host instance per host (HBA) that an LLD -controls. The struct Scsi_Host structure has many members in common -with "struct scsi_host_template". When a new struct Scsi_Host instance -is created (in scsi_host_alloc() in hosts.c) those common members are -initialized from the driver's struct scsi_host_template instance. Members -of interest: - host_no - system wide unique number that is used for identifying - this host. Issued in ascending order from 0. - can_queue - must be greater than 0; do not send more than can_queue - commands to the adapter. - this_id - scsi id of host (scsi initiator) or -1 if not known - sg_tablesize - maximum scatter gather elements allowed by host. - Set this to SG_ALL or less to avoid chained SG lists. - Must be at least 1. - max_sectors - maximum number of sectors (usually 512 bytes) allowed - in a single SCSI command. The default value of 0 leads - to a setting of SCSI_DEFAULT_MAX_SECTORS (defined in - scsi_host.h) which is currently set to 1024. So for a - disk the maximum transfer size is 512 KB when max_sectors - is not defined. Note that this size may not be sufficient - for disk firmware uploads. - cmd_per_lun - maximum number of commands that can be queued on devices - controlled by the host. Overridden by LLD calls to - scsi_change_queue_depth(). - unchecked_isa_dma - 1=>only use bottom 16 MB of ram (ISA DMA addressing - restriction), 0=>can use full 32 bit (or better) DMA - address space - no_async_abort - 1=>Asynchronous aborts are not supported - 0=>Timed-out commands will be aborted asynchronously - hostt - pointer to driver's struct scsi_host_template from which - this struct Scsi_Host instance was spawned - hostt->proc_name - name of LLD. This is the driver name that sysfs uses - transportt - pointer to driver's struct scsi_transport_template instance - (if any). FC and SPI transports currently supported. - sh_list - a double linked list of pointers to all struct Scsi_Host - instances (currently ordered by ascending host_no) - my_devices - a double linked list of pointers to struct scsi_device - instances that belong to this host. - hostdata[0] - area reserved for LLD at end of struct Scsi_Host. Size - is set by the second argument (named 'xtr_bytes') to - scsi_host_alloc() or scsi_register(). - vendor_id - a unique value that identifies the vendor supplying - the LLD for the Scsi_Host. Used most often in validating - vendor-specific message requests. Value consists of an - identifier type and a vendor-specific value. - See scsi_netlink.h for a description of valid formats. - -The scsi_host structure is defined in include/scsi/scsi_host.h - -struct scsi_device ------------------- -Generally, there is one instance of this structure for each SCSI logical unit -on a host. Scsi devices connected to a host are uniquely identified by a -channel number, target id and logical unit number (lun). -The structure is defined in include/scsi/scsi_device.h - -struct scsi_cmnd ----------------- -Instances of this structure convey SCSI commands to the LLD and responses -back to the mid level. The SCSI mid level will ensure that no more SCSI -commands become queued against the LLD than are indicated by -scsi_change_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will -be at least one instance of struct scsi_cmnd available for each SCSI device. -Members of interest: - cmnd - array containing SCSI command - cmnd_len - length (in bytes) of SCSI command - sc_data_direction - direction of data transfer in data phase. See - "enum dma_data_direction" in include/linux/dma-mapping.h - request_bufflen - number of data bytes to transfer (0 if no data phase) - use_sg - ==0 -> no scatter gather list, hence transfer data - to/from request_buffer - - >0 -> scatter gather list (actually an array) in - request_buffer with use_sg elements - request_buffer - either contains data buffer or scatter gather list - depending on the setting of use_sg. Scatter gather - elements are defined by 'struct scatterlist' found - in include/linux/scatterlist.h . - done - function pointer that should be invoked by LLD when the - SCSI command is completed (successfully or otherwise). - Should only be called by an LLD if the LLD has accepted - the command (i.e. queuecommand() returned or will return - 0). The LLD may invoke 'done' prior to queuecommand() - finishing. - result - should be set by LLD prior to calling 'done'. A value - of 0 implies a successfully completed command (and all - data (if any) has been transferred to or from the SCSI - target device). 'result' is a 32 bit unsigned integer that - can be viewed as 4 related bytes. The SCSI status value is - in the LSB. See include/scsi/scsi.h status_byte(), - msg_byte(), host_byte() and driver_byte() macros and - related constants. - sense_buffer - an array (maximum size: SCSI_SENSE_BUFFERSIZE bytes) that - should be written when the SCSI status (LSB of 'result') - is set to CHECK_CONDITION (2). When CHECK_CONDITION is - set, if the top nibble of sense_buffer[0] has the value 7 - then the mid level will assume the sense_buffer array - contains a valid SCSI sense buffer; otherwise the mid - level will issue a REQUEST_SENSE SCSI command to - retrieve the sense buffer. The latter strategy is error - prone in the presence of command queuing so the LLD should - always "auto-sense". - device - pointer to scsi_device object that this command is - associated with. - resid - an LLD should set this signed integer to the requested - transfer length (i.e. 'request_bufflen') less the number - of bytes that are actually transferred. 'resid' is - preset to 0 so an LLD can ignore it if it cannot detect - underruns (overruns should be rare). If possible an LLD - should set 'resid' prior to invoking 'done'. The most - interesting case is data transfers from a SCSI target - device (e.g. READs) that underrun. - underflow - LLD should place (DID_ERROR << 16) in 'result' if - actual number of bytes transferred is less than this - figure. Not many LLDs implement this check and some that - do just output an error message to the log rather than - report a DID_ERROR. Better for an LLD to implement - 'resid'. - -It is recommended that a LLD set 'resid' on data transfers from a SCSI -target device (e.g. READs). It is especially important that 'resid' is set -when such data transfers have sense keys of MEDIUM ERROR and HARDWARE ERROR -(and possibly RECOVERED ERROR). In these cases if a LLD is in doubt how much -data has been received then the safest approach is to indicate no bytes have -been received. For example: to indicate that no valid data has been received -a LLD might use these helpers: - scsi_set_resid(SCpnt, scsi_bufflen(SCpnt)); -where 'SCpnt' is a pointer to a scsi_cmnd object. To indicate only three 512 -bytes blocks has been received 'resid' could be set like this: - scsi_set_resid(SCpnt, scsi_bufflen(SCpnt) - (3 * 512)); - -The scsi_cmnd structure is defined in include/scsi/scsi_cmnd.h - - -Locks -===== -Each struct Scsi_Host instance has a spin_lock called struct -Scsi_Host::default_lock which is initialized in scsi_host_alloc() [found in -hosts.c]. Within the same function the struct Scsi_Host::host_lock pointer -is initialized to point at default_lock. Thereafter lock and unlock -operations performed by the mid level use the struct Scsi_Host::host_lock -pointer. Previously drivers could override the host_lock pointer but -this is not allowed anymore. - - -Autosense -========= -Autosense (or auto-sense) is defined in the SAM-2 document as "the -automatic return of sense data to the application client coincident -with the completion of a SCSI command" when a status of CHECK CONDITION -occurs. LLDs should perform autosense. This should be done when the LLD -detects a CHECK CONDITION status by either: - a) instructing the SCSI protocol (e.g. SCSI Parallel Interface (SPI)) - to perform an extra data in phase on such responses - b) or, the LLD issuing a REQUEST SENSE command itself - -Either way, when a status of CHECK CONDITION is detected, the mid level -decides whether the LLD has performed autosense by checking struct -scsi_cmnd::sense_buffer[0] . If this byte has an upper nibble of 7 (or 0xf) -then autosense is assumed to have taken place. If it has another value (and -this byte is initialized to 0 before each command) then the mid level will -issue a REQUEST SENSE command. - -In the presence of queued commands the "nexus" that maintains sense -buffer data from the command that failed until a following REQUEST SENSE -may get out of synchronization. This is why it is best for the LLD -to perform autosense. - - -Changes since lk 2.4 series -=========================== -io_request_lock has been replaced by several finer grained locks. The lock -relevant to LLDs is struct Scsi_Host::host_lock and there is -one per SCSI host. - -The older error handling mechanism has been removed. This means the -LLD interface functions abort() and reset() have been removed. -The struct scsi_host_template::use_new_eh_code flag has been removed. - -In the 2.4 series the SCSI subsystem configuration descriptions were -aggregated with the configuration descriptions from all other Linux -subsystems in the Documentation/Configure.help file. In the 2.6 series, -the SCSI subsystem now has its own (much smaller) drivers/scsi/Kconfig -file that contains both configuration and help information. - -struct SHT has been renamed to struct scsi_host_template. - -Addition of the "hotplug initialization model" and many extra functions -to support it. - - -Credits -======= -The following people have contributed to this document: - Mike Anderson <andmike at us dot ibm dot com> - James Bottomley <James dot Bottomley at hansenpartnership dot com> - Patrick Mansfield <patmans at us dot ibm dot com> - Christoph Hellwig <hch at infradead dot org> - Doug Ledford <dledford at redhat dot com> - Andries Brouwer <Andries dot Brouwer at cwi dot nl> - Randy Dunlap <rdunlap at xenotime dot net> - Alan Stern <stern at rowland dot harvard dot edu> - - -Douglas Gilbert -dgilbert at interlog dot com -21st September 2004 diff --git a/Documentation/scsi/scsi_transport_srp/Makefile b/Documentation/scsi/scsi_transport_srp/Makefile deleted file mode 100644 index 5f6b567e955c..000000000000 --- a/Documentation/scsi/scsi_transport_srp/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: rport_state_diagram.svg rport_state_diagram.png - -rport_state_diagram.svg: rport_state_diagram.dot - dot -Tsvg -o $@ $< - -rport_state_diagram.png: rport_state_diagram.dot - dot -Tpng -o $@ $< diff --git a/Documentation/scsi/scsi_transport_srp/figures.rst b/Documentation/scsi/scsi_transport_srp/figures.rst new file mode 100644 index 000000000000..6c8f8dd6301b --- /dev/null +++ b/Documentation/scsi/scsi_transport_srp/figures.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +SCSI RDMA (SRP) transport class diagram +======================================= + +.. kernel-figure:: rport_state_diagram.dot diff --git a/Documentation/scsi/sd-parameters.rst b/Documentation/scsi/sd-parameters.rst new file mode 100644 index 000000000000..87d554008bfb --- /dev/null +++ b/Documentation/scsi/sd-parameters.rst @@ -0,0 +1,27 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================================== +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 diff --git a/Documentation/scsi/sd-parameters.txt b/Documentation/scsi/sd-parameters.txt deleted file mode 100644 index 8e5af00d88e7..000000000000 --- a/Documentation/scsi/sd-parameters.txt +++ /dev/null @@ -1,22 +0,0 @@ -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 diff --git a/Documentation/scsi/smartpqi.txt b/Documentation/scsi/smartpqi.rst index df129f55ace5..a7de27352c6f 100644 --- a/Documentation/scsi/smartpqi.txt +++ b/Documentation/scsi/smartpqi.rst @@ -1,6 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 +===================================== SMARTPQI - Microsemi Smart PQI Driver ------------------------------------------ +===================================== This file describes the smartpqi SCSI driver for Microsemi (http://www.microsemi.com) PQI controllers. The smartpqi driver @@ -16,20 +18,21 @@ For Microsemi smartpqi controller support, enable the smartpqi driver when configuring the kernel. For more information on the PQI Queuing Interface, please see: -http://www.t10.org/drafts.htm -http://www.t10.org/members/w_pqi2.htm -Supported devices: ------------------- +- http://www.t10.org/drafts.htm +- http://www.t10.org/members/w_pqi2.htm + +Supported devices +================= <Controller names to be added as they become publicly available.> smartpqi specific entries in /sys ------------------------------ +================================= - smartpqi host attributes: - ------------------------- - /sys/class/scsi_host/host*/rescan - /sys/class/scsi_host/host*/driver_version +smartpqi host attributes +------------------------ + - /sys/class/scsi_host/host*/rescan + - /sys/class/scsi_host/host*/driver_version The host rescan attribute is a write only attribute. Writing to this attribute will trigger the driver to scan for new, changed, or removed @@ -37,12 +40,13 @@ smartpqi specific entries in /sys The version attribute is read-only and will return the driver version and the controller firmware version. - For example: + For example:: + driver: 0.9.13-370 firmware: 0.01-522 - smartpqi sas device attributes - ------------------------------ +smartpqi sas device attributes +------------------------------ HBA devices are added to the SAS transport layer. These attributes are automatically added by the SAS transport layer. @@ -50,31 +54,25 @@ smartpqi specific entries in /sys /sys/class/sas_device/end_device-X:X/enclosure_identifier /sys/class/sas_device/end_device-X:X/scsi_target_id -smartpqi specific ioctls: -------------------------- +smartpqi specific ioctls +======================== For compatibility with applications written for the cciss protocol. - CCISS_DEREGDISK - CCISS_REGNEWDISK - CCISS_REGNEWD - - The above three ioctls all do exactly the same thing, which is to cause the driver - to rescan for new devices. This does exactly the same thing as writing to the - smartpqi specific host "rescan" attribute. + CCISS_DEREGDISK, CCISS_REGNEWDISK, CCISS_REGNEWD + The above three ioctls all do exactly the same thing, which is to cause the driver + to rescan for new devices. This does exactly the same thing as writing to the + smartpqi specific host "rescan" attribute. CCISS_GETPCIINFO - Returns PCI domain, bus, device and function and "board ID" (PCI subsystem ID). CCISS_GETDRIVVER + Returns driver version in three bytes encoded as:: - Returns driver version in three bytes encoded as: - (DRIVER_MAJOR << 28) | (DRIVER_MINOR << 24) | (DRIVER_RELEASE << 16) | DRIVER_REVISION; + (DRIVER_MAJOR << 28) | (DRIVER_MINOR << 24) | (DRIVER_RELEASE << 16) | DRIVER_REVISION; CCISS_PASSTHRU - Allows "BMIC" and "CISS" commands to be passed through to the Smart Storage Array. These are used extensively by the SSA Array Configuration Utility, SNMP storage agents, etc. - diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.rst index ec0acf6acccd..d3b28c28d74c 100644 --- a/Documentation/scsi/st.txt +++ b/Documentation/scsi/st.rst @@ -1,3 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==================== +The SCSI Tape Driver +==================== + This file contains brief information about the SCSI tape driver. The driver is currently maintained by Kai Mäkisara (email Kai.Makisara@kolumbus.fi) @@ -5,7 +11,8 @@ Kai.Makisara@kolumbus.fi) Last modified: Tue Feb 9 21:54:16 2016 by kai.makisara -BASICS +Basics +====== The driver is generic, i.e., it does not contain any code tailored to any specific tape drive. The tape parameters can be specified with @@ -110,15 +117,17 @@ tape in the drive (commands trying to write something return error if attempted). -MINOR NUMBERS +Minor Numbers +============= The tape driver currently supports up to 2^17 drives if 4 modes for each drive are used. -The minor numbers consist of the following bit fields: +The minor numbers consist of the following bit fields:: + + dev_upper non-rew mode dev-lower + 20 - 8 7 6 5 4 0 -dev_upper non-rew mode dev-lower - 20 - 8 7 6 5 4 0 The non-rewind bit is always bit 7 (the uppermost bit in the lowermost byte). The bits defining the mode are below the non-rewind bit. The remaining bits define the tape device number. This numbering is @@ -126,7 +135,8 @@ backward compatible with the numbering used when the minor number was only 8 bits wide. -SYSFS SUPPORT +Sysfs Support +============= The driver creates the directory /sys/class/scsi_tape and populates it with directories corresponding to the existing tape devices. There are autorewind @@ -148,10 +158,11 @@ bit definitions are the same as those used with MTSETDRVBUFFER in setting the options. A link named 'tape' is made from the SCSI device directory to the class -directory corresponding to the mode 0 auto-rewind device (e.g., st0). +directory corresponding to the mode 0 auto-rewind device (e.g., st0). -SYSFS AND STATISTICS FOR TAPE DEVICES +Sysfs and Statistics for Tape Devices +===================================== The st driver maintains statistics for tape drives inside the sysfs filesystem. The following method can be used to locate the statistics that are @@ -160,10 +171,10 @@ available (assuming that sysfs is mounted at /sys): 1. Use opendir(3) on the directory /sys/class/scsi_tape 2. Use readdir(3) to read the directory contents 3. Use regcomp(3)/regexec(3) to match directory entries to the extended - regular expression "^st[0-9]+$" + regular expression "^st[0-9]+$" 4. Access the statistics from the /sys/class/scsi_tape/<match>/stats - directory (where <match> is a directory entry from /sys/class/scsi_tape - that matched the extended regular expression) + directory (where <match> is a directory entry from /sys/class/scsi_tape + that matched the extended regular expression) The reason for using this approach is that all the character devices pointing to the same tape drive use the same statistics. That means @@ -171,29 +182,41 @@ that st0 would have the same statistics as nst0. The directory contains the following statistics files: -1. in_flight - The number of I/Os currently outstanding to this device. -2. io_ns - The amount of time spent waiting (in nanoseconds) for all I/O +1. in_flight + - The number of I/Os currently outstanding to this device. +2. io_ns + - The amount of time spent waiting (in nanoseconds) for all I/O to complete (including read and write). This includes tape movement commands such as seeking between file or set marks and implicit tape movement such as when rewind on close tape devices are used. -3. other_cnt - The number of I/Os issued to the tape drive other than read or +3. other_cnt + - The number of I/Os issued to the tape drive other than read or write commands. The time taken to complete these commands uses the following calculation io_ms-read_ms-write_ms. -4. read_byte_cnt - The number of bytes read from the tape drive. -5. read_cnt - The number of read requests issued to the tape drive. -6. read_ns - The amount of time (in nanoseconds) spent waiting for read +4. read_byte_cnt + - The number of bytes read from the tape drive. +5. read_cnt + - The number of read requests issued to the tape drive. +6. read_ns + - The amount of time (in nanoseconds) spent waiting for read requests to complete. -7. write_byte_cnt - The number of bytes written to the tape drive. -8. write_cnt - The number of write requests issued to the tape drive. -9. write_ns - The amount of time (in nanoseconds) spent waiting for write +7. write_byte_cnt + - The number of bytes written to the tape drive. +8. write_cnt + - The number of write requests issued to the tape drive. +9. write_ns + - The amount of time (in nanoseconds) spent waiting for write requests to complete. -10. resid_cnt - The number of times during a read or write we found +10. resid_cnt + - The number of times during a read or write we found the residual amount to be non-zero. This should mean that a program is issuing a read larger thean the block size on tape. For write not all data made it to tape. -Note: The in_flight value is incremented when an I/O starts the I/O -itself is not added to the statistics until it completes. +.. Note:: + + The in_flight value is incremented when an I/O starts the I/O + itself is not added to the statistics until it completes. The total of read_cnt, write_cnt, and other_cnt may not total to the same value as iodone_cnt at the device level. The tape statistics only count @@ -210,7 +233,8 @@ The value of in_flight is 0 when there are no I/Os outstanding that are issued by the st driver. Tape statistics do not take into account any I/O performed via the sg device. -BSD AND SYS V SEMANTICS +BSD and Sys V Semantics +======================= The user can choose between these two behaviours of the tape driver by defining the value of the symbol ST_SYSV. The semantics differ when a @@ -221,13 +245,15 @@ filemark unless the filemark has just been crossed. The default is BSD semantics. -BUFFERING +Buffering +========= The driver tries to do transfers directly to/from user space. If this is not possible, a driver buffer allocated at run-time is used. If direct i/o is not possible for the whole transfer, the driver buffer is used (i.e., bounce buffers for individual pages are not used). Direct i/o can be impossible because of several reasons, e.g.: + - one or more pages are at addresses not reachable by the HBA - the number of pages in the transfer exceeds the number of scatter/gather segments permitted by the HBA @@ -269,28 +295,30 @@ in the physical memory) are used if contiguous buffers can't be allocated. To support all SCSI adapters (including those not supporting scatter/gather), buffer allocation is using the following three kinds of chunks: + 1. The initial segment that is used for all SCSI adapters including -those not supporting scatter/gather. The size of this buffer will be -(PAGE_SIZE << ST_FIRST_ORDER) bytes if the system can give a chunk of -this size (and it is not larger than the buffer size specified by -ST_BUFFER_BLOCKS). If this size is not available, the driver halves -the size and tries again until the size of one page. The default -settings in st_options.h make the driver to try to allocate all of the -buffer as one chunk. + those not supporting scatter/gather. The size of this buffer will be + (PAGE_SIZE << ST_FIRST_ORDER) bytes if the system can give a chunk of + this size (and it is not larger than the buffer size specified by + ST_BUFFER_BLOCKS). If this size is not available, the driver halves + the size and tries again until the size of one page. The default + settings in st_options.h make the driver to try to allocate all of the + buffer as one chunk. 2. The scatter/gather segments to fill the specified buffer size are -allocated so that as many segments as possible are used but the number -of segments does not exceed ST_FIRST_SG. + allocated so that as many segments as possible are used but the number + of segments does not exceed ST_FIRST_SG. 3. The remaining segments between ST_MAX_SG (or the module parameter -max_sg_segs) and the number of segments used in phases 1 and 2 -are used to extend the buffer at run-time if this is necessary. The -number of scatter/gather segments allowed for the SCSI adapter is not -exceeded if it is smaller than the maximum number of scatter/gather -segments specified. If the maximum number allowed for the SCSI adapter -is smaller than the number of segments used in phases 1 and 2, -extending the buffer will always fail. + max_sg_segs) and the number of segments used in phases 1 and 2 + are used to extend the buffer at run-time if this is necessary. The + number of scatter/gather segments allowed for the SCSI adapter is not + exceeded if it is smaller than the maximum number of scatter/gather + segments specified. If the maximum number allowed for the SCSI adapter + is smaller than the number of segments used in phases 1 and 2, + extending the buffer will always fail. -EOM BEHAVIOUR WHEN WRITING +EOM Behaviour When Writing +========================== When the end of medium early warning is encountered, the current write is finished and the number of bytes is returned. The next write @@ -300,12 +328,13 @@ bytes is returned. After this, -1 and the number of bytes are alternately returned until the physical end of medium (or some other error) is encountered. - -MODULE PARAMETERS +Module Parameters +================= The buffer size, write threshold, and the maximum number of allocated buffers are configurable when the driver is loaded as a module. The keywords are: +========================== =========================================== buffer_kbs=xxx the buffer size for fixed block mode is set to xxx kilobytes write_threshold_kbs=xxx the write threshold in kilobytes set to xxx @@ -313,12 +342,14 @@ max_sg_segs=xxx the maximum number of scatter/gather segments try_direct_io=x try direct transfer between user buffer and tape drive if this is non-zero +========================== =========================================== Note that if the buffer size is changed but the write threshold is not set, the write threshold is set to the new buffer size - 2 kB. -BOOT TIME CONFIGURATION +Boot Time Configuration +======================= If the driver is compiled into the kernel, the same parameters can be also set using, e.g., the LILO command line. The preferred syntax is @@ -332,21 +363,23 @@ versions is supported. The same keywords can be used as when loading the driver as module. If several parameters are set, the keyword-value pairs are separated with a comma (no spaces allowed). A colon can be used instead of the equal mark. The definition is prepended by the -string st=. Here is an example: +string st=. Here is an example:: st=buffer_kbs:64,write_threshold_kbs:60 -The following syntax used by the old kernel versions is also supported: +The following syntax used by the old kernel versions is also supported:: st=aa[,bb[,dd]] -where - aa is the buffer size for fixed block mode in 1024 byte units - bb is the write threshold in 1024 byte units - dd is the maximum number of scatter/gather segments +where: + - aa is the buffer size for fixed block mode in 1024 byte units + - bb is the write threshold in 1024 byte units + - dd is the maximum number of scatter/gather segments -IOCTLS + +IOCTLs +====== The tape is positioned and the drive parameters are set with ioctls defined in mtio.h The tape control program 'mt' uses these ioctls. Try @@ -359,55 +392,80 @@ The supported ioctls are: The following use the structure mtop: -MTFSF Space forward over count filemarks. Tape positioned after filemark. -MTFSFM As above but tape positioned before filemark. -MTBSF Space backward over count filemarks. Tape positioned before +MTFSF + Space forward over count filemarks. Tape positioned after filemark. +MTFSFM + As above but tape positioned before filemark. +MTBSF + Space backward over count filemarks. Tape positioned before filemark. -MTBSFM As above but ape positioned after filemark. -MTFSR Space forward over count records. -MTBSR Space backward over count records. -MTFSS Space forward over count setmarks. -MTBSS Space backward over count setmarks. -MTWEOF Write count filemarks. -MTWEOFI Write count filemarks with immediate bit set (i.e., does not +MTBSFM + As above but ape positioned after filemark. +MTFSR + Space forward over count records. +MTBSR + Space backward over count records. +MTFSS + Space forward over count setmarks. +MTBSS + Space backward over count setmarks. +MTWEOF + Write count filemarks. +MTWEOFI + Write count filemarks with immediate bit set (i.e., does not wait until data is on tape) -MTWSM Write count setmarks. -MTREW Rewind tape. -MTOFFL Set device off line (often rewind plus eject). -MTNOP Do nothing except flush the buffers. -MTRETEN Re-tension tape. -MTEOM Space to end of recorded data. -MTERASE Erase tape. If the argument is zero, the short erase command +MTWSM + Write count setmarks. +MTREW + Rewind tape. +MTOFFL + Set device off line (often rewind plus eject). +MTNOP + Do nothing except flush the buffers. +MTRETEN + Re-tension tape. +MTEOM + Space to end of recorded data. +MTERASE + Erase tape. If the argument is zero, the short erase command is used. The long erase command is used with all other values of the argument. -MTSEEK Seek to tape block count. Uses Tandberg-compatible seek (QFA) +MTSEEK + Seek to tape block count. Uses Tandberg-compatible seek (QFA) for SCSI-1 drives and SCSI-2 seek for SCSI-2 drives. The file and block numbers in the status are not valid after a seek. -MTSETBLK Set the drive block size. Setting to zero sets the drive into +MTSETBLK + Set the drive block size. Setting to zero sets the drive into variable block mode (if applicable). -MTSETDENSITY Sets the drive density code to arg. See drive +MTSETDENSITY + Sets the drive density code to arg. See drive documentation for available codes. -MTLOCK and MTUNLOCK Explicitly lock/unlock the tape drive door. -MTLOAD and MTUNLOAD Explicitly load and unload the tape. If the +MTLOCK and MTUNLOCK + Explicitly lock/unlock the tape drive door. +MTLOAD and MTUNLOAD + Explicitly load and unload the tape. If the command argument x is between MT_ST_HPLOADER_OFFSET + 1 and MT_ST_HPLOADER_OFFSET + 6, the number x is used sent to the drive with the command and it selects the tape slot to use of HP C1553A changer. -MTCOMPRESSION Sets compressing or uncompressing drive mode using the +MTCOMPRESSION + Sets compressing or uncompressing drive mode using the SCSI mode page 15. Note that some drives other methods for control of compression. Some drives (like the Exabytes) use density codes for compression control. Some drives use another mode page but this page has not been implemented in the driver. Some drives without compression capability will accept any compression mode without error. -MTSETPART Moves the tape to the partition given by the argument at the +MTSETPART + Moves the tape to the partition given by the argument at the next tape operation. The block at which the tape is positioned is the block where the tape was previously positioned in the new active partition unless the next tape operation is MTSEEK. In this case the tape is moved directly to the block specified by MTSEEK. MTSETPART is inactive unless MT_ST_CAN_PARTITIONS set. -MTMKPART Formats the tape with one partition (argument zero) or two +MTMKPART + Formats the tape with one partition (argument zero) or two partitions (argument non-zero). If the argument is positive, it specifies the size of partition 1 in megabytes. For DDS drives and several early drives this is the physically first @@ -422,64 +480,81 @@ MTSETDRVBUFFER with mask MT_SET_OPTIONS, the low order bits are used as argument. This command is only allowed for the superuser (root). The subcommands are: - 0 + + * 0 The drive buffer option is set to the argument. Zero means no buffering. - MT_ST_BOOLEANS + * MT_ST_BOOLEANS Sets the buffering options. The bits are the new states (enabled/disabled) the following options (in the parenthesis is specified whether the option is global or can be specified differently for each mode): - MT_ST_BUFFER_WRITES write buffering (mode) - MT_ST_ASYNC_WRITES asynchronous writes (mode) - MT_ST_READ_AHEAD read ahead (mode) - MT_ST_TWO_FM writing of two filemarks (global) - MT_ST_FAST_EOM using the SCSI spacing to EOD (global) - MT_ST_AUTO_LOCK automatic locking of the drive door (global) - MT_ST_DEF_WRITES the defaults are meant only for writes (mode) - MT_ST_CAN_BSR backspacing over more than one records can + + MT_ST_BUFFER_WRITES + write buffering (mode) + MT_ST_ASYNC_WRITES + asynchronous writes (mode) + MT_ST_READ_AHEAD + read ahead (mode) + MT_ST_TWO_FM + writing of two filemarks (global) + MT_ST_FAST_EOM + using the SCSI spacing to EOD (global) + MT_ST_AUTO_LOCK + automatic locking of the drive door (global) + MT_ST_DEF_WRITES + the defaults are meant only for writes (mode) + MT_ST_CAN_BSR + backspacing over more than one records can be used for repositioning the tape (global) - MT_ST_NO_BLKLIMS the driver does not ask the block limits + MT_ST_NO_BLKLIMS + the driver does not ask the block limits from the drive (block size can be changed only to variable) (global) - MT_ST_CAN_PARTITIONS enables support for partitioned + MT_ST_CAN_PARTITIONS + enables support for partitioned tapes (global) - MT_ST_SCSI2LOGICAL the logical block number is used in + MT_ST_SCSI2LOGICAL + the logical block number is used in the MTSEEK and MTIOCPOS for SCSI-2 drives instead of the device dependent address. It is recommended to set this flag unless there are tapes using the device dependent (from the old times) (global) - MT_ST_SYSV sets the SYSV semantics (mode) - MT_ST_NOWAIT enables immediate mode (i.e., don't wait for + MT_ST_SYSV + sets the SYSV semantics (mode) + MT_ST_NOWAIT + enables immediate mode (i.e., don't wait for the command to finish) for some commands (e.g., rewind) - MT_ST_NOWAIT_EOF enables immediate filemark mode (i.e. when + MT_ST_NOWAIT_EOF + enables immediate filemark mode (i.e. when writing a filemark, don't wait for it to complete). Please see the BASICS note about MTWEOFI with respect to the possible dangers of writing immediate filemarks. - MT_ST_SILI enables setting the SILI bit in SCSI commands when + MT_ST_SILI + enables setting the SILI bit in SCSI commands when reading in variable block mode to enhance performance when reading blocks shorter than the byte count; set this only if you are sure that the drive supports SILI and the HBA correctly returns transfer residuals - MT_ST_DEBUGGING debugging (global; debugging must be + MT_ST_DEBUGGING + debugging (global; debugging must be compiled into the driver) - MT_ST_SETBOOLEANS - MT_ST_CLEARBOOLEANS + + * MT_ST_SETBOOLEANS, MT_ST_CLEARBOOLEANS Sets or clears the option bits. - MT_ST_WRITE_THRESHOLD + * MT_ST_WRITE_THRESHOLD Sets the write threshold for this device to kilobytes specified by the lowest bits. - MT_ST_DEF_BLKSIZE + * MT_ST_DEF_BLKSIZE Defines the default block size set automatically. Value 0xffffff means that the default is not used any more. - MT_ST_DEF_DENSITY - MT_ST_DEF_DRVBUFFER + * MT_ST_DEF_DENSITY, MT_ST_DEF_DRVBUFFER Used to set or clear the density (8 bits), and drive buffer state (3 bits). If the value is MT_ST_CLEAR_DEFAULT (0xfffff) the default will not be used any more. Otherwise the lowermost bits of the value contain the new value of the parameter. - MT_ST_DEF_COMPRESSION + * MT_ST_DEF_COMPRESSION The compression default will not be used if the value of the lowermost byte is 0xff. Otherwise the lowermost bit contains the new default. If the bits 8-15 are set to a @@ -487,17 +562,17 @@ MTSETDRVBUFFER used as the compression algorithm. The value MT_ST_CLEAR_DEFAULT can be used to clear the compression default. - MT_ST_SET_TIMEOUT + * MT_ST_SET_TIMEOUT Set the normal timeout in seconds for this device. The default is 900 seconds (15 minutes). The timeout should be long enough for the retries done by the device while reading/writing. - MT_ST_SET_LONG_TIMEOUT + * MT_ST_SET_LONG_TIMEOUT Set the long timeout that is used for operations that are known to take a long time. The default is 14000 seconds (3.9 hours). For erase this value is further multiplied by eight. - MT_ST_SET_CLN + * MT_ST_SET_CLN Set the cleaning request interpretation parameters using the lowest 24 bits of the argument. The driver can set the generic status bit GMT_CLN if a cleaning request bit pattern @@ -506,7 +581,7 @@ MTSETDRVBUFFER cleaning. The bits are device-dependent. The driver is given the number of the sense data byte (the lowest eight bits of the argument; must be >= 18 (values 1 - 17 - reserved) and <= the maximum requested sense data sixe), + reserved) and <= the maximum requested sense data sixe), a mask to select the relevant bits (the bits 9-16), and the bit pattern (bits 17-23). If the bit pattern is zero, one or more bits under the mask indicate cleaning request. If @@ -518,12 +593,16 @@ MTSETDRVBUFFER MT_ST_SET_CLN.) The following ioctl uses the structure mtpos: -MTIOCPOS Reads the current position from the drive. Uses + +MTIOCPOS + Reads the current position from the drive. Uses Tandberg-compatible QFA for SCSI-1 drives and the SCSI-2 command for the SCSI-2 drives. The following ioctl uses the structure mtget to return the status: -MTIOCGET Returns some status information. + +MTIOCGET + Returns some status information. The file number and block number within file are returned. The block is -1 when it can't be determined (e.g., after MTBSF). The drive type is either MTISSCSI1 or MTISSCSI2. @@ -537,7 +616,8 @@ MTIOCGET Returns some status information. end of recorded data or end of tape. GMT_EOT means end of tape. -MISCELLANEOUS COMPILE OPTIONS +Miscellaneous Compile Options +============================= The recovered write errors are considered fatal if ST_RECOVERED_WRITE_FATAL is defined. @@ -568,7 +648,8 @@ time or the MT_ST_CAN_BSR bit is set for the drive with an ioctl. user does not request data that far.) -DEBUGGING HINTS +Debugging Hints +=============== Debugging code is now compiled in by default but debugging is turned off with the kernel module parameter debug_flag defaulting to 0. Debugging diff --git a/Documentation/scsi/sym53c500_cs.txt b/Documentation/scsi/sym53c500_cs.rst index 75febcf9298c..55464861bbd5 100644 --- a/Documentation/scsi/sym53c500_cs.txt +++ b/Documentation/scsi/sym53c500_cs.rst @@ -1,3 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======================= +The sym53c500_cs Driver +======================= + The sym53c500_cs driver originated as an add-on to David Hinds' pcmcia-cs package, and was written by Tom Corner (tcorner@via.at). A rewrite was long overdue, and the current version addresses the following concerns: @@ -20,4 +26,4 @@ Through the years, there have been a number of downloads of the pcmcia-cs version of this driver, and I guess it worked for those users. It worked for Tom Corner, and it works for me. Your mileage will probably vary. ---Bob Tracy (rct@frus.com) +Bob Tracy (rct@frus.com) diff --git a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.rst index d28186553fb0..8de44a7baa9b 100644 --- a/Documentation/scsi/sym53c8xx_2.txt +++ b/Documentation/scsi/sym53c8xx_2.rst @@ -1,99 +1,111 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================================= The Linux SYM-2 driver documentation file +========================================= Written by Gerard Roudier <groudier@free.fr> + 21 Rue Carnot + 95170 DEUIL LA BARRE - FRANCE Updated by Matthew Wilcox <matthew@wil.cx> 2004-10-09 -=============================================================================== - -1. Introduction -2. Supported chips and SCSI features -3. Advantages of this driver for newer chips. - 3.1 Optimized SCSI SCRIPTS - 3.2 New features appeared with the SYM53C896 -4. Memory mapped I/O versus normal I/O -5. Tagged command queueing -6. Parity checking -7. Profiling information -8. Control commands - 8.1 Set minimum synchronous period - 8.2 Set wide size - 8.3 Set maximum number of concurrent tagged commands - 8.4 Set debug mode - 8.5 Set flag (no_disc) - 8.6 Set verbose level - 8.7 Reset all logical units of a target - 8.8 Abort all tasks of all logical units of a target -9. Configuration parameters -10. Boot setup commands - 10.1 Syntax - 10.2 Available arguments - 10.2.1 Default number of tagged commands - 10.2.2 Burst max - 10.2.3 LED support - 10.2.4 Differential mode - 10.2.5 IRQ mode - 10.2.6 Check SCSI BUS - 10.2.7 Suggest a default SCSI id for hosts - 10.2.8 Verbosity level - 10.2.9 Debug mode - 10.2.10 Settle delay - 10.2.11 Serial NVRAM - 10.2.12 Exclude a host from being attached - 10.3 Converting from old options - 10.4 SCSI BUS checking boot option -11. SCSI problem troubleshooting - 15.1 Problem tracking - 15.2 Understanding hardware error reports -12. Serial NVRAM support (by Richard Waltham) - 17.1 Features - 17.2 Symbios NVRAM layout - 17.3 Tekram NVRAM layout - -=============================================================================== + +.. Contents + + 1. Introduction + 2. Supported chips and SCSI features + 3. Advantages of this driver for newer chips. + 3.1 Optimized SCSI SCRIPTS + 3.2 New features appeared with the SYM53C896 + 4. Memory mapped I/O versus normal I/O + 5. Tagged command queueing + 6. Parity checking + 7. Profiling information + 8. Control commands + 8.1 Set minimum synchronous period + 8.2 Set wide size + 8.3 Set maximum number of concurrent tagged commands + 8.4 Set debug mode + 8.5 Set flag (no_disc) + 8.6 Set verbose level + 8.7 Reset all logical units of a target + 8.8 Abort all tasks of all logical units of a target + 9. Configuration parameters + 10. Boot setup commands + 10.1 Syntax + 10.2 Available arguments + 10.2.1 Default number of tagged commands + 10.2.2 Burst max + 10.2.3 LED support + 10.2.4 Differential mode + 10.2.5 IRQ mode + 10.2.6 Check SCSI BUS + 10.2.7 Suggest a default SCSI id for hosts + 10.2.8 Verbosity level + 10.2.9 Debug mode + 10.2.10 Settle delay + 10.2.11 Serial NVRAM + 10.2.12 Exclude a host from being attached + 10.3 Converting from old options + 10.4 SCSI BUS checking boot option + 11. SCSI problem troubleshooting + 15.1 Problem tracking + 15.2 Understanding hardware error reports + 12. Serial NVRAM support (by Richard Waltham) + 17.1 Features + 17.2 Symbios NVRAM layout + 17.3 Tekram NVRAM layout + 1. Introduction +=============== This driver supports the whole SYM53C8XX family of PCI-SCSI controllers. -It also support the subset of LSI53C10XX PCI-SCSI controllers that are based +It also support the subset of LSI53C10XX PCI-SCSI controllers that are based on the SYM53C8XX SCRIPTS language. -It replaces the sym53c8xx+ncr53c8xx driver bundle and shares its core code -with the FreeBSD SYM-2 driver. The `glue' that allows this driver to work +It replaces the sym53c8xx+ncr53c8xx driver bundle and shares its core code +with the FreeBSD SYM-2 driver. The 'glue' that allows this driver to work under Linux is contained in 2 files named sym_glue.h and sym_glue.c. -Other drivers files are intended not to depend on the Operating System +Other drivers files are intended not to depend on the Operating System on which the driver is used. The history of this driver can be summarized as follows: 1993: ncr driver written for 386bsd and FreeBSD by: - Wolfgang Stanglmeier <wolf@cologne.de> - Stefan Esser <se@mi.Uni-Koeln.de> + + - Wolfgang Stanglmeier <wolf@cologne.de> + - Stefan Esser <se@mi.Uni-Koeln.de> 1996: port of the ncr driver to Linux-1.2.13 and rename it ncr53c8xx. - Gerard Roudier -1998: new sym53c8xx driver for Linux based on LOAD/STORE instruction and that + - Gerard Roudier + +1998: new sym53c8xx driver for Linux based on LOAD/STORE instruction and that adds full support for the 896 but drops support for early NCR devices. - Gerard Roudier -1999: port of the sym53c8xx driver to FreeBSD and support for the LSI53C1010 - 33 MHz and 66MHz Ultra-3 controllers. The new driver is named `sym'. - Gerard Roudier + - Gerard Roudier -2000: Add support for early NCR devices to FreeBSD `sym' driver. - Break the driver into several sources and separate the OS glue +1999: port of the sym53c8xx driver to FreeBSD and support for the LSI53C1010 + 33 MHz and 66MHz Ultra-3 controllers. The new driver is named 'sym'. + + - Gerard Roudier + +2000: Add support for early NCR devices to FreeBSD 'sym' driver. + Break the driver into several sources and separate the OS glue code from the core code that can be shared among different O/Ses. Write a glue code for Linux. - Gerard Roudier + + - Gerard Roudier 2004: Remove FreeBSD compatibility code. Remove support for versions of Linux before 2.6. Start using Linux facilities. -This README file addresses the Linux version of the driver. Under FreeBSD, +This README file addresses the Linux version of the driver. Under FreeBSD, the driver documentation is the sym.8 man page. Information about new chips is available at LSILOGIC web server: @@ -104,113 +116,145 @@ SCSI standard documentations are available at T10 site: http://www.t10.org/ -Useful SCSI tools written by Eric Youngdale are part of most Linux +Useful SCSI tools written by Eric Youngdale are part of most Linux distributions: - scsiinfo: command line tool - scsi-config: TCL/Tk tool using scsiinfo + + ============ ========================== + scsiinfo command line tool + scsi-config TCL/Tk tool using scsiinfo + ============ ========================== 2. Supported chips and SCSI features +==================================== The following features are supported for all chips: - Synchronous negotiation - Disconnection - Tagged command queuing - SCSI parity checking - PCI Master parity checking + - Synchronous negotiation + - Disconnection + - Tagged command queuing + - SCSI parity checking + - PCI Master parity checking Other features depends on chip capabilities. -The driver notably uses optimized SCRIPTS for devices that support -LOAD/STORE and handles PHASE MISMATCH from SCRIPTS for devices that + +The driver notably uses optimized SCRIPTS for devices that support +LOAD/STORE and handles PHASE MISMATCH from SCRIPTS for devices that support the corresponding feature. The following table shows some characteristics of the chip family. - On board LOAD/STORE HARDWARE -Chip SDMS BIOS Wide SCSI std. Max. sync SCRIPTS PHASE MISMATCH ----- --------- ---- --------- ---------- ---------- -------------- -810 N N FAST10 10 MB/s N N -810A N N FAST10 10 MB/s Y N -815 Y N FAST10 10 MB/s N N -825 Y Y FAST10 20 MB/s N N -825A Y Y FAST10 20 MB/s Y N -860 N N FAST20 20 MB/s Y N -875 Y Y FAST20 40 MB/s Y N -875A Y Y FAST20 40 MB/s Y Y -876 Y Y FAST20 40 MB/s Y N -895 Y Y FAST40 80 MB/s Y N -895A Y Y FAST40 80 MB/s Y Y -896 Y Y FAST40 80 MB/s Y Y -897 Y Y FAST40 80 MB/s Y Y -1510D Y Y FAST40 80 MB/s Y Y -1010 Y Y FAST80 160 MB/s Y Y -1010_66* Y Y FAST80 160 MB/s Y Y - -* Chip supports 33MHz and 66MHz PCI bus clock. ++--------+-----------+-----+-----------+------------+------------+---------+ +| | | | | |Load/store |Hardware | +| |On board | | | |scripts |phase | +|Chip |SDMS BIOS |Wide |SCSI std. | Max. sync | |mismatch | ++--------+-----------+-----+-----------+------------+------------+---------+ +|810 | N | N | FAST10 | 10 MB/s | N | N | ++--------+-----------+-----+-----------+------------+------------+---------+ +|810A | N | N | FAST10 | 10 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+---------+ +|815 | Y | N | FAST10 | 10 MB/s | N | N | ++--------+-----------+-----+-----------+------------+------------+---------+ +|825 | Y | Y | FAST10 | 20 MB/s | N | N | ++--------+-----------+-----+-----------+------------+------------+---------+ +|825A | Y | Y | FAST10 | 20 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+---------+ +|860 | N | N | FAST20 | 20 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+---------+ +|875 | Y | Y | FAST20 | 40 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+---------+ +|875A | Y | Y | FAST20 | 40 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+---------+ +|876 | Y | Y | FAST20 | 40 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+---------+ +|895 | Y | Y | FAST40 | 80 MB/s | Y | N | ++--------+-----------+-----+-----------+------------+------------+---------+ +|895A | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+---------+ +|896 | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+---------+ +|897 | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+---------+ +|1510D | Y | Y | FAST40 | 80 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+---------+ +|1010 | Y | Y | FAST80 |160 MB/s | Y | Y | ++--------+-----------+-----+-----------+------------+------------+---------+ +|1010_66 | Y | Y | FAST80 |160 MB/s | Y | Y | +|[1]_ | | | | | | | ++--------+-----------+-----+-----------+------------+------------+---------+ + +.. [1] Chip supports 33MHz and 66MHz PCI bus clock. Summary of other supported features: -Module: allow to load the driver -Memory mapped I/O: increases performance -Control commands: write operations to the proc SCSI file system -Debugging information: written to syslog (expert only) -Scatter / gather -Shared interrupt -Boot setup commands -Serial NVRAM: Symbios and Tekram formats +:Module: allow to load the driver +:Memory mapped I/O: increases performance +:Control commands: write operations to the proc SCSI file system +:Debugging information: written to syslog (expert only) +:Serial NVRAM: Symbios and Tekram formats + +- Scatter / gather +- Shared interrupt +- Boot setup commands 3. Advantages of this driver for newer chips. +============================================= -3.1 Optimized SCSI SCRIPTS. +3.1 Optimized SCSI SCRIPTS +-------------------------- -All chips except the 810, 815 and 825, support new SCSI SCRIPTS instructions -named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register -to/from memory much faster that the MOVE MEMORY instruction that is supported +All chips except the 810, 815 and 825, support new SCSI SCRIPTS instructions +named LOAD and STORE that allow to move up to 1 DWORD from/to an IO register +to/from memory much faster that the MOVE MEMORY instruction that is supported by the 53c7xx and 53c8xx family. -The LOAD/STORE instructions support absolute and DSA relative addressing -modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead +The LOAD/STORE instructions support absolute and DSA relative addressing +modes. The SCSI SCRIPTS had been entirely rewritten using LOAD/STORE instead of MOVE MEMORY instructions. -Due to the lack of LOAD/STORE SCRIPTS instructions by earlier chips, this -driver also incorporates a different SCRIPTS set based on MEMORY MOVE, in +Due to the lack of LOAD/STORE SCRIPTS instructions by earlier chips, this +driver also incorporates a different SCRIPTS set based on MEMORY MOVE, in order to provide support for the entire SYM53C8XX chips family. 3.2 New features appeared with the SYM53C896 +-------------------------------------------- -Newer chips (see above) allows handling of the phase mismatch context from -SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor +Newer chips (see above) allows handling of the phase mismatch context from +SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor until the C code has saved the context of the transfer). -The 896 and 1010 chips support 64 bit PCI transactions and addressing, +The 896 and 1010 chips support 64 bit PCI transactions and addressing, while the 895A supports 32 bit PCI transactions and 64 bit addressing. -The SCRIPTS processor of these chips is not true 64 bit, but uses segment -registers for bit 32-63. Another interesting feature is that LOAD/STORE +The SCRIPTS processor of these chips is not true 64 bit, but uses segment +registers for bit 32-63. Another interesting feature is that LOAD/STORE instructions that address the on-chip RAM (8k) remain internal to the chip. 4. Memory mapped I/O versus normal I/O +====================================== -Memory mapped I/O has less latency than normal I/O and is the recommended -way for doing IO with PCI devices. Memory mapped I/O seems to work fine on -most hardware configurations, but some poorly designed chipsets may break -this feature. A configuration option is provided for normal I/O to be +Memory mapped I/O has less latency than normal I/O and is the recommended +way for doing IO with PCI devices. Memory mapped I/O seems to work fine on +most hardware configurations, but some poorly designed chipsets may break +this feature. A configuration option is provided for normal I/O to be used but the driver defaults to MMIO. 5. Tagged command queueing +========================== -Queuing more than 1 command at a time to a device allows it to perform -optimizations based on actual head positions and its mechanical +Queuing more than 1 command at a time to a device allows it to perform +optimizations based on actual head positions and its mechanical characteristics. This feature may also reduce average command latency. -In order to really gain advantage of this feature, devices must have -a reasonable cache size (No miracle is to be expected for a low-end +In order to really gain advantage of this feature, devices must have +a reasonable cache size (No miracle is to be expected for a low-end hard disk with 128 KB or less). + Some known old SCSI devices do not properly support tagged command queuing. -Generally, firmware revisions that fix this kind of problems are available +Generally, firmware revisions that fix this kind of problems are available at respective vendor web/ftp sites. -All I can say is that I never have had problem with tagged queuing using -this driver and its predecessors. Hard disks that behaved correctly for + +All I can say is that I never have had problem with tagged queuing using +this driver and its predecessors. Hard disks that behaved correctly for me using tagged commands are the following: - IBM S12 0662 @@ -223,9 +267,9 @@ me using tagged commands are the following: - Quantum Atlas IV - Seagate Cheetah II -If your controller has NVRAM, you can configure this feature per target -from the user setup tool. The Tekram Setup program allows to tune the -maximum number of queued commands up to 32. The Symbios Setup only allows +If your controller has NVRAM, you can configure this feature per target +from the user setup tool. The Tekram Setup program allows to tune the +maximum number of queued commands up to 32. The Symbios Setup only allows to enable or disable this feature. The maximum number of simultaneous tagged commands queued to a device @@ -233,15 +277,15 @@ is currently set to 16 by default. This value is suitable for most SCSI disks. With large SCSI disks (>= 2GB, cache >= 512KB, average seek time <= 10 ms), using a larger value may give better performances. -This driver supports up to 255 commands per device, and but using more than -64 is generally not worth-while, unless you are using a very large disk or -disk arrays. It is noticeable that most of recent hard disks seem not to -accept more than 64 simultaneous commands. So, using more than 64 queued +This driver supports up to 255 commands per device, and but using more than +64 is generally not worth-while, unless you are using a very large disk or +disk arrays. It is noticeable that most of recent hard disks seem not to +accept more than 64 simultaneous commands. So, using more than 64 queued commands is probably just resource wasting. -If your controller does not have NVRAM or if it is managed by the SDMS -BIOS/SETUP, you can configure tagged queueing feature and device queue -depths from the boot command-line. For example: +If your controller does not have NVRAM or if it is managed by the SDMS +BIOS/SETUP, you can configure tagged queueing feature and device queue +depths from the boot command-line. For example:: sym53c8xx=tags:4/t2t3q15-t4q7/t1u0q32 @@ -257,25 +301,28 @@ In some special conditions, some SCSI disk firmwares may return a QUEUE FULL status for a SCSI command. This behaviour is managed by the driver using the following heuristic: -- Each time a QUEUE FULL status is returned, tagged queue depth is reduced - to the actual number of disconnected commands. +- Each time a QUEUE FULL status is returned, tagged queue depth is reduced + to the actual number of disconnected commands. - Every 200 successfully completed SCSI commands, if allowed by the current limit, the maximum number of queueable commands is incremented. -Since QUEUE FULL status reception and handling is resource wasting, the -driver notifies by default this problem to user by indicating the actual -number of commands used and their status, as well as its decision on the +Since QUEUE FULL status reception and handling is resource wasting, the +driver notifies by default this problem to user by indicating the actual +number of commands used and their status, as well as its decision on the device queue depth change. -The heuristic used by the driver in handling QUEUE FULL ensures that the -impact on performances is not too bad. You can get rid of the messages by +The heuristic used by the driver in handling QUEUE FULL ensures that the +impact on performances is not too bad. You can get rid of the messages by setting verbose level to zero, as follow: -1st method: boot your system using 'sym53c8xx=verb:0' option. -2nd method: apply "setverbose 0" control command to the proc fs entry +1st method: + boot your system using 'sym53c8xx=verb:0' option. +2nd method: + apply "setverbose 0" control command to the proc fs entry corresponding to your controller after boot-up. 6. Parity checking +================== The driver supports SCSI parity checking and PCI bus master parity checking. These features must be enabled in order to ensure safe @@ -284,17 +331,19 @@ with parity. The options to defeat parity checking have been removed from the driver. 7. Profiling information +======================== This driver does not provide profiling information as did its predecessors. -This feature was not this useful and added complexity to the code. -As the driver code got more complex, I have decided to remove everything +This feature was not this useful and added complexity to the code. +As the driver code got more complex, I have decided to remove everything that didn't seem actually useful. 8. Control commands +=================== Control commands can be sent to the driver with write operations to the proc SCSI file system. The generic command syntax is the -following: +following:: echo "<verb> <parameters>" >/proc/scsi/sym53c8xx/0 (assumes controller number is 0) @@ -305,97 +354,112 @@ apply to all targets of the SCSI chain (except the controller). Available commands: 8.1 Set minimum synchronous period factor +----------------------------------------- setsync <target> <period factor> - target: target number - period: minimum synchronous period. + :target: target number + :period: minimum synchronous period. Maximum speed = 1000/(4*period factor) except for special cases below. Specify a period of 0, to force asynchronous transfer mode. - 9 means 12.5 nano-seconds synchronous period - 10 means 25 nano-seconds synchronous period - 11 means 30 nano-seconds synchronous period - 12 means 50 nano-seconds synchronous period + - 9 means 12.5 nano-seconds synchronous period + - 10 means 25 nano-seconds synchronous period + - 11 means 30 nano-seconds synchronous period + - 12 means 50 nano-seconds synchronous period 8.2 Set wide size +----------------- setwide <target> <size> - target: target number - size: 0=8 bits, 1=16bits + :target: target number + :size: 0=8 bits, 1=16bits 8.3 Set maximum number of concurrent tagged commands - +---------------------------------------------------- + settags <target> <tags> - target: target number - tags: number of concurrent tagged commands + :target: target number + :tags: number of concurrent tagged commands must not be greater than configured (default: 16) 8.4 Set debug mode +------------------ setdebug <list of debug flags> Available debug flags: - alloc: print info about memory allocations (ccb, lcb) - queue: print info about insertions into the command start queue - result: print sense data on CHECK CONDITION status - scatter: print info about the scatter process - scripts: print info about the script binding process - tiny: print minimal debugging information - timing: print timing information of the NCR chip - nego: print information about SCSI negotiations - phase: print information on script interruptions + + ======== ======================================================== + alloc print info about memory allocations (ccb, lcb) + queue print info about insertions into the command start queue + result print sense data on CHECK CONDITION status + scatter print info about the scatter process + scripts print info about the script binding process + tiny print minimal debugging information + timing print timing information of the NCR chip + nego print information about SCSI negotiations + phase print information on script interruptions + ======== ======================================================== Use "setdebug" with no argument to reset debug flags. 8.5 Set flag (no_disc) - +---------------------- + setflag <target> <flag> - target: target number + :target: target number For the moment, only one flag is available: no_disc: not allow target to disconnect. Do not specify any flag in order to reset the flag. For example: - - setflag 4 + + setflag 4 will reset no_disc flag for target 4, so will allow it disconnections. - - setflag all + setflag all will allow disconnection for all devices on the SCSI bus. 8.6 Set verbose level +--------------------- setverbose #level - The driver default verbose level is 1. This command allows to change + The driver default verbose level is 1. This command allows to change th driver verbose level after boot-up. 8.7 Reset all logical units of a target +--------------------------------------- resetdev <target> - target: target number + :target: target number + The driver will try to send a BUS DEVICE RESET message to the target. 8.8 Abort all tasks of all logical units of a target +---------------------------------------------------- cleardev <target> - target: target number - The driver will try to send a ABORT message to all the logical units + :target: target number + + The driver will try to send a ABORT message to all the logical units of the target. 9. Configuration parameters +=========================== -Under kernel configuration tools (make menuconfig, for example), it is +Under kernel configuration tools (make menuconfig, for example), it is possible to change some default driver configuration parameters. If the firmware of all your devices is perfect enough, all the features supported by the driver can be enabled at start-up. However, @@ -414,166 +478,238 @@ Default tagged command queue depth (default answer: 16) This parameter can be specified from the boot command line. Maximum number of queued commands (default answer: 32) - This option allows you to specify the maximum number of tagged commands + This option allows you to specify the maximum number of tagged commands that can be queued to a device. The maximum supported value is 255. Synchronous transfers frequency (default answer: 80) - This option allows you to specify the frequency in MHz the driver + This option allows you to specify the frequency in MHz the driver will use at boot time for synchronous data transfer negotiations. 0 means "asynchronous data transfers". 10. Boot setup commands +======================= 10.1 Syntax +----------- Setup commands can be passed to the driver either at boot time or as parameters to modprobe, as described in Documentation/admin-guide/kernel-parameters.rst -Example of boot setup command under lilo prompt: +Example of boot setup command under lilo prompt:: -lilo: linux root=/dev/sda2 sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.debug=0x200 + lilo: linux root=/dev/sda2 sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.debug=0x200 - enable tagged commands, up to 4 tagged commands queued. - set synchronous negotiation speed to 10 Mega-transfers / second. - set DEBUG_NEGO flag. The following command will install the driver module with the same -options as above. +options as above:: modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200 10.2 Available arguments +------------------------ 10.2.1 Default number of tagged commands - cmd_per_lun=0 (or cmd_per_lun=1) tagged command queuing disabled - cmd_per_lun=#tags (#tags > 1) tagged command queuing enabled +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + - cmd_per_lun=0 (or cmd_per_lun=1) tagged command queuing disabled + - cmd_per_lun=#tags (#tags > 1) tagged command queuing enabled + #tags will be truncated to the max queued commands configuration parameter. 10.2.2 Burst max +^^^^^^^^^^^^^^^^ + + ========== ====================================================== burst=0 burst disabled burst=255 get burst length from initial IO register settings. burst=#x burst enabled (1<<#x burst transfers max) - #x is an integer value which is log base 2 of the burst transfers max. + + #x is an integer value which is log base 2 of the burst + transfers max. + ========== ====================================================== + By default the driver uses the maximum value supported by the chip. 10.2.3 LED support +^^^^^^^^^^^^^^^^^^ + + ===== =================== led=1 enable LED support led=0 disable LED support + ===== =================== + Do not enable LED support if your scsi board does not use SDMS BIOS. (See 'Configuration parameters') 10.2.4 Differential mode - diff=0 never set up diff mode +^^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ================================= + diff=0 never set up diff mode diff=1 set up diff mode if BIOS set it diff=2 always set up diff mode diff=3 set diff mode if GPIO3 is not set + ====== ================================= 10.2.5 IRQ mode +^^^^^^^^^^^^^^^ + + ====== ================================================ irqm=0 always open drain irqm=1 same as initial settings (assumed BIOS settings) irqm=2 always totem pole + ====== ================================================ + +10.2.6 Check SCSI BUS +^^^^^^^^^^^^^^^^^^^^^ -10.2.6 Check SCSI BUS buschk=<option bits> Available option bits: - 0x0: No check. - 0x1: Check and do not attach the controller on error. - 0x2: Check and just warn on error. + + === ================================================ + 0x0 No check. + 0x1 Check and do not attach the controller on error. + 0x2 Check and just warn on error. + === ================================================ 10.2.7 Suggest a default SCSI id for hosts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ========== ========================================== hostid=255 no id suggested. - hostid=#x (0 < x < 7) x suggested for hosts SCSI id. + hostid=#x (0 < x < 7) x suggested for hosts SCSI id. + ========== ========================================== - If a host SCSI id is available from the NVRAM, the driver will ignore - any value suggested as boot option. Otherwise, if a suggested value - different from 255 has been supplied, it will use it. Otherwise, it will - try to deduce the value previously set in the hardware and use value + If a host SCSI id is available from the NVRAM, the driver will ignore + any value suggested as boot option. Otherwise, if a suggested value + different from 255 has been supplied, it will use it. Otherwise, it will + try to deduce the value previously set in the hardware and use value 7 if the hardware value is zero. 10.2.8 Verbosity level +^^^^^^^^^^^^^^^^^^^^^^^ + + ====== ======== verb=0 minimal verb=1 normal verb=2 too much + ====== ======== 10.2.9 Debug mode - debug=0 clear debug flags - debug=#x set debug flags - #x is an integer value combining the following power-of-2 values: - DEBUG_ALLOC 0x1 - DEBUG_PHASE 0x2 - DEBUG_POLL 0x4 - DEBUG_QUEUE 0x8 - DEBUG_RESULT 0x10 - DEBUG_SCATTER 0x20 - DEBUG_SCRIPT 0x40 - DEBUG_TINY 0x80 - DEBUG_TIMING 0x100 - DEBUG_NEGO 0x200 - DEBUG_TAGS 0x400 - DEBUG_FREEZE 0x800 - DEBUG_RESTART 0x1000 - - You can play safely with DEBUG_NEGO. However, some of these flags may - generate bunches of syslog messages. +^^^^^^^^^^^^^^^^^ + + ========= ==================================== + debug=0 clear debug flags + debug=#x set debug flags + + #x is an integer value combining the + following power-of-2 values: + + ============= ====== + DEBUG_ALLOC 0x1 + DEBUG_PHASE 0x2 + DEBUG_POLL 0x4 + DEBUG_QUEUE 0x8 + DEBUG_RESULT 0x10 + DEBUG_SCATTER 0x20 + DEBUG_SCRIPT 0x40 + DEBUG_TINY 0x80 + DEBUG_TIMING 0x100 + DEBUG_NEGO 0x200 + DEBUG_TAGS 0x400 + DEBUG_FREEZE 0x800 + DEBUG_RESTART 0x1000 + ============= ====== + ========= ==================================== + + You can play safely with DEBUG_NEGO. However, some of these flags may + generate bunches of syslog messages. 10.2.10 Settle delay +^^^^^^^^^^^^^^^^^^^^ + + ======== =================== settle=n delay for n seconds + ======== =================== After a bus reset, the driver will delay for n seconds before talking to any device on the bus. The default is 3 seconds and safe mode will default it to 10. 10.2.11 Serial NVRAM - NB: option not currently implemented. +^^^^^^^^^^^^^^^^^^^^ + + .. Note:: option not currently implemented. + + ======= ========================================= nvram=n do not look for serial NVRAM nvram=y test controllers for onboard serial NVRAM + ======= ========================================= + (alternate binary form) + nvram=<bits options> + + ==== ================================================================= 0x01 look for NVRAM (equivalent to nvram=y) 0x02 ignore NVRAM "Synchronous negotiation" parameters for all devices 0x04 ignore NVRAM "Wide negotiation" parameter for all devices 0x08 ignore NVRAM "Scan at boot time" parameter for all devices 0x80 also attach controllers set to OFF in the NVRAM (sym53c8xx only) + ==== ================================================================= 10.2.12 Exclude a host from being attached +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + excl=<io_address>,... Prevent host at a given io address from being attached. - For example 'excl=0xb400,0xc000' indicate to the + For example 'excl=0xb400,0xc000' indicate to the driver not to attach hosts at address 0xb400 and 0xc000. 10.3 Converting from old style options +-------------------------------------- + +Previously, the sym2 driver accepted arguments of the form:: -Previously, the sym2 driver accepted arguments of the form sym53c8xx=tags:4,sync:10,debug:0x200 As a result of the new module parameters, this is no longer available. Most of the options have remained the same, but tags has become cmd_per_lun to reflect its different purposes. The sample above would -be specified as: +be specified as:: + modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200 -or on the kernel boot line as: +or on the kernel boot line as:: + sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.debug=0x200 -10.4 SCSI BUS checking boot option. +10.4 SCSI BUS checking boot option +---------------------------------- -When this option is set to a non-zero value, the driver checks SCSI lines +When this option is set to a non-zero value, the driver checks SCSI lines logic state, 100 micro-seconds after having asserted the SCSI RESET line. The driver just reads SCSI lines and checks all lines read FALSE except RESET. -Since SCSI devices shall release the BUS at most 800 nano-seconds after SCSI +Since SCSI devices shall release the BUS at most 800 nano-seconds after SCSI RESET has been asserted, any signal to TRUE may indicate a SCSI BUS problem. Unfortunately, the following common SCSI BUS problems are not detected: + - Only 1 terminator installed. - Misplaced terminators. - Bad quality terminators. -On the other hand, either bad cabling, broken devices, not conformant + +On the other hand, either bad cabling, broken devices, not conformant devices, ... may cause a SCSI signal to be wrong when te driver reads it. 15. SCSI problem troubleshooting +================================ 15.1 Problem tracking +--------------------- Most SCSI problems are due to a non conformant SCSI bus or too buggy devices. If unfortunately you have SCSI problems, you can check the @@ -607,86 +743,96 @@ hard disks. Good SCSI hard disks with a large cache gain advantage of tagged commands queuing. 15.2 Understanding hardware error reports +----------------------------------------- -When the driver detects an unexpected error condition, it may display a -message of the following pattern. +When the driver detects an unexpected error condition, it may display a +message of the following pattern:: -sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000). -sym0: script cmd = 19000000 -sym0: regdump: da 10 80 95 47 0f 01 07 75 01 81 21 80 01 09 00. + sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000). + sym0: script cmd = 19000000 + sym0: regdump: da 10 80 95 47 0f 01 07 75 01 81 21 80 01 09 00. -Some fields in such a message may help you understand the cause of the -problem, as follows: +Some fields in such a message may help you understand the cause of the +problem, as follows:: -sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000). -.....A.........B.C....D.E..F....G.H..I.......J.....K...L....... + sym0:1: ERROR (0:48) (1-21-65) (f/95/0) @ (script 7c0:19000000). + .....A.........B.C....D.E..F....G.H..I.......J.....K...L....... Field A : target number. - SCSI ID of the device the controller was talking with at the moment the + SCSI ID of the device the controller was talking with at the moment the error occurs. Field B : DSTAT io register (DMA STATUS) - Bit 0x40 : MDPE Master Data Parity Error + ======== ============================================================= + Bit 0x40 MDPE Master Data Parity Error Data parity error detected on the PCI BUS. - Bit 0x20 : BF Bus Fault + Bit 0x20 BF Bus Fault PCI bus fault condition detected - Bit 0x01 : IID Illegal Instruction Detected - Set by the chip when it detects an Illegal Instruction format + Bit 0x01 IID Illegal Instruction Detected + Set by the chip when it detects an Illegal Instruction format on some condition that makes an instruction illegal. - Bit 0x80 : DFE Dma Fifo Empty + Bit 0x80 DFE Dma Fifo Empty Pure status bit that does not indicate an error. - If the reported DSTAT value contains a combination of MDPE (0x40), + ======== ============================================================= + + If the reported DSTAT value contains a combination of MDPE (0x40), BF (0x20), then the cause may be likely due to a PCI BUS problem. Field C : SIST io register (SCSI Interrupt Status) - Bit 0x08 : SGE SCSI GROSS ERROR - Indicates that the chip detected a severe error condition + ======== ================================================================== + Bit 0x08 SGE SCSI GROSS ERROR + Indicates that the chip detected a severe error condition on the SCSI BUS that prevents the SCSI protocol from functioning properly. - Bit 0x04 : UDC Unexpected Disconnection - Indicates that the device released the SCSI BUS when the chip - was not expecting this to happen. A device may behave so to + Bit 0x04 UDC Unexpected Disconnection + Indicates that the device released the SCSI BUS when the chip + was not expecting this to happen. A device may behave so to indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occurred. - Bit 0x02 : RST SCSI BUS Reset - Generally SCSI targets do not reset the SCSI BUS, although any + Bit 0x02 RST SCSI BUS Reset + Generally SCSI targets do not reset the SCSI BUS, although any device on the BUS can reset it at any time. - Bit 0x01 : PAR Parity + Bit 0x01 PAR Parity SCSI parity error detected. - On a faulty SCSI BUS, any error condition among SGE (0x08), UDC (0x04) and - PAR (0x01) may be detected by the chip. If your SCSI system sometimes - encounters such error conditions, especially SCSI GROSS ERROR, then a SCSI + ======== ================================================================== + + On a faulty SCSI BUS, any error condition among SGE (0x08), UDC (0x04) and + PAR (0x01) may be detected by the chip. If your SCSI system sometimes + encounters such error conditions, especially SCSI GROSS ERROR, then a SCSI BUS problem is likely the cause of these errors. -For fields D,E,F,G and H, you may look into the sym53c8xx_defs.h file +For fields D,E,F,G and H, you may look into the sym53c8xx_defs.h file that contains some minimal comments on IO register bits. + Field D : SOCL Scsi Output Control Latch - This register reflects the state of the SCSI control lines the + This register reflects the state of the SCSI control lines the chip want to drive or compare against. Field E : SBCL Scsi Bus Control Lines Actual value of control lines on the SCSI BUS. Field F : SBDL Scsi Bus Data Lines Actual value of data lines on the SCSI BUS. Field G : SXFER SCSI Transfer - Contains the setting of the Synchronous Period for output and + Contains the setting of the Synchronous Period for output and the current Synchronous offset (offset 0 means asynchronous). Field H : SCNTL3 Scsi Control Register 3 - Contains the setting of timing values for both asynchronous and - synchronous data transfers. + Contains the setting of timing values for both asynchronous and + synchronous data transfers. Field I : SCNTL4 Scsi Control Register 4 Only meaningful for 53C1010 Ultra3 controllers. -Understanding Fields J, K, L and dumps requires to have good knowledge of +Understanding Fields J, K, L and dumps requires to have good knowledge of SCSI standards, chip cores functionnals and internal driver data structures. -You are not required to decode and understand them, unless you want to help +You are not required to decode and understand them, unless you want to help maintain the driver code. 17. Serial NVRAM (added by Richard Waltham: dormouse@farsrobt.demon.co.uk) +========================================================================== 17.1 Features +------------- Enabling serial NVRAM support enables detection of the serial NVRAM included -on Symbios and some Symbios compatible host adaptors, and Tekram boards. The -serial NVRAM is used by Symbios and Tekram to hold set up parameters for the +on Symbios and some Symbios compatible host adaptors, and Tekram boards. The +serial NVRAM is used by Symbios and Tekram to hold set up parameters for the host adaptor and its attached drives. The Symbios NVRAM also holds data on the boot order of host adaptors in a @@ -694,102 +840,122 @@ system with more than one host adaptor. This information is no longer used as it's fundamentally incompatible with the hotplug PCI model. Tekram boards using Symbios chips, DC390W/F/U, which have NVRAM are detected -and this is used to distinguish between Symbios compatible and Tekram host +and this is used to distinguish between Symbios compatible and Tekram host adaptors. This is used to disable the Symbios compatible "diff" setting -incorrectly set on Tekram boards if the CONFIG_SCSI_53C8XX_SYMBIOS_COMPAT -configuration parameter is set enabling both Symbios and Tekram boards to be +incorrectly set on Tekram boards if the CONFIG_SCSI_53C8XX_SYMBIOS_COMPAT +configuration parameter is set enabling both Symbios and Tekram boards to be used together with the Symbios cards using all their features, including "diff" support. ("led pin" support for Symbios compatible cards can remain enabled when using Tekram cards. It does nothing useful for Tekram host adaptors but does not cause problems either.) -The parameters the driver is able to get from the NVRAM depend on the +The parameters the driver is able to get from the NVRAM depend on the data format used, as follow: - Tekram format Symbios format -General and host parameters - Boot order N Y - Host SCSI ID Y Y - SCSI parity checking Y Y - Verbose boot messages N Y -SCSI devices parameters - Synchronous transfer speed Y Y - Wide 16 / Narrow Y Y - Tagged Command Queuing enabled Y Y - Disconnections enabled Y Y - Scan at boot time N Y - -In order to speed up the system boot, for each device configured without -the "scan at boot time" option, the driver forces an error on the ++-------------------------------+------------------+--------------+ +| |Tekram format |Symbios format| ++-------------------------------+------------------+--------------+ +|General and host parameters | | | ++-------------------------------+------------------+--------------+ +| * Boot order | N | Y | ++-------------------------------+------------------+--------------+ +| * Host SCSI ID | Y | Y | ++-------------------------------+------------------+--------------+ +| * SCSI parity checking | Y | Y | ++-------------------------------+------------------+--------------+ +| * Verbose boot messages | N | Y | ++-------------------------------+------------------+--------------+ +|SCSI devices parameters | ++-------------------------------+------------------+--------------+ +| * Synchronous transfer speed | Y | Y | ++-------------------------------+------------------+--------------+ +| * Wide 16 / Narrow | Y | Y | ++-------------------------------+------------------+--------------+ +| * Tagged Command Queuing | Y | Y | +| enabled | | | ++-------------------------------+------------------+--------------+ +| * Disconnections enabled | Y | Y | ++-------------------------------+------------------+--------------+ +| * Scan at boot time | N | Y | ++-------------------------------+------------------+--------------+ + + +In order to speed up the system boot, for each device configured without +the "scan at boot time" option, the driver forces an error on the first TEST UNIT READY command received for this device. 17.2 Symbios NVRAM layout +------------------------- + +typical data at NVRAM address 0x100 (53c810a NVRAM):: + + 00 00 + 64 01 + 8e 0b + + 00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 + + 04 00 0f 00 00 10 00 50 00 00 01 00 00 62 + 04 00 03 00 00 10 00 58 00 00 01 00 00 63 + 04 00 01 00 00 10 00 48 00 00 01 00 00 61 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + + fe fe + 00 00 + 00 00 -typical data at NVRAM address 0x100 (53c810a NVRAM) ------------------------------------------------------------ -00 00 -64 01 -8e 0b - -00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 - -04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -04 00 03 00 00 10 00 58 00 00 01 00 00 63 -04 00 01 00 00 10 00 48 00 00 01 00 00 61 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 - -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 - -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 - -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 - -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 - -fe fe -00 00 -00 00 ------------------------------------------------------------ NVRAM layout details -NVRAM Address 0x000-0x0ff not used - 0x100-0x26f initialised data - 0x270-0x7ff not used +============= ================= +NVRAM Address +============= ================= +0x000-0x0ff not used +0x100-0x26f initialised data +0x270-0x7ff not used +============= ================= -general layout +general layout:: header - 6 bytes, data - 356 bytes (checksum is byte sum of this data) @@ -797,7 +963,7 @@ general layout --- total 368 bytes -data area layout +data area layout:: controller set up - 20 bytes boot configuration - 56 bytes (4x14 bytes) @@ -806,52 +972,51 @@ data area layout --- total 356 bytes ------------------------------------------------------------ -header - -00 00 - ?? start marker -64 01 - byte count (lsb/msb excludes header/trailer) -8e 0b - checksum (lsb/msb excludes header/trailer) ------------------------------------------------------------ -controller set up - -00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 - | | | | - | | | -- host ID - | | | - | | --Removable Media Support - | | 0x00 = none - | | 0x01 = Bootable Device - | | 0x02 = All with Media - | | - | --flag bits 2 - | 0x00000001= scan order hi->low - | (default 0x00 - scan low->hi) - --flag bits 1 - 0x00000001 scam enable - 0x00000010 parity enable - 0x00000100 verbose boot msgs +header:: + + 00 00 - ?? start marker + 64 01 - byte count (lsb/msb excludes header/trailer) + 8e 0b - checksum (lsb/msb excludes header/trailer) + +controller set up:: + + 00 30 00 00 00 00 07 00 00 00 00 00 00 00 07 04 10 04 00 00 + | | | | + | | | -- host ID + | | | + | | --Removable Media Support + | | 0x00 = none + | | 0x01 = Bootable Device + | | 0x02 = All with Media + | | + | --flag bits 2 + | 0x00000001= scan order hi->low + | (default 0x00 - scan low->hi) + --flag bits 1 + 0x00000001 scam enable + 0x00000010 parity enable + 0x00000100 verbose boot msgs remaining bytes unknown - they do not appear to change in my current set up for any of the controllers. default set up is identical for 53c810a and 53c875 NVRAM (Removable Media added Symbios BIOS version 4.09) ------------------------------------------------------------ + boot configuration -boot order set by order of the devices in this table +boot order set by order of the devices in this table:: -04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -- 1st controller -04 00 03 00 00 10 00 58 00 00 01 00 00 63 2nd controller -04 00 01 00 00 10 00 48 00 00 01 00 00 61 3rd controller -00 00 00 00 00 00 00 00 00 00 00 00 00 00 4th controller - | | | | | | | | - | | | | | | ---- PCI io port adr - | | | | | --0x01 init/scan at boot time - | | | | --PCI device/function number (0xdddddfff) - | | ----- ?? PCI vendor ID (lsb/msb) - ----PCI device ID (lsb/msb) + 04 00 0f 00 00 10 00 50 00 00 01 00 00 62 -- 1st controller + 04 00 03 00 00 10 00 58 00 00 01 00 00 63 2nd controller + 04 00 01 00 00 10 00 48 00 00 01 00 00 61 3rd controller + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4th controller + | | | | | | | | + | | | | | | ---- PCI io port adr + | | | | | --0x01 init/scan at boot time + | | | | --PCI device/function number (0xdddddfff) + | | ----- ?? PCI vendor ID (lsb/msb) + ----PCI device ID (lsb/msb) ?? use of this data is a guess but seems reasonable @@ -859,120 +1024,120 @@ remaining bytes unknown - they do not appear to change in my current set up default set up is identical for 53c810a and 53c875 NVRAM ------------------------------------------------------------ -device set up (up to 16 devices - includes controller) - -0f 00 08 08 64 00 0a 00 - id 0 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 - -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 -0f 00 08 08 64 00 0a 00 - id 15 - | | | | | | - | | | | ----timeout (lsb/msb) - | | | --synch period (0x?? 40 Mtrans/sec- fast 40) (probably 0x28) - | | | (0x30 20 Mtrans/sec- fast 20) - | | | (0x64 10 Mtrans/sec- fast ) - | | | (0xc8 5 Mtrans/sec) - | | | (0x00 asynchronous) - | | -- ?? max sync offset (0x08 in NVRAM on 53c810a) - | | (0x10 in NVRAM on 53c875) - | --device bus width (0x08 narrow) - | (0x10 16 bit wide) - --flag bits - 0x00000001 - disconnect enabled - 0x00000010 - scan at boot time - 0x00000100 - scan luns - 0x00001000 - queue tags enabled + +device set up (up to 16 devices - includes controller):: + + 0f 00 08 08 64 00 0a 00 - id 0 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 + 0f 00 08 08 64 00 0a 00 - id 15 + | | | | | | + | | | | ----timeout (lsb/msb) + | | | --synch period (0x?? 40 Mtrans/sec- fast 40) (probably 0x28) + | | | (0x30 20 Mtrans/sec- fast 20) + | | | (0x64 10 Mtrans/sec- fast ) + | | | (0xc8 5 Mtrans/sec) + | | | (0x00 asynchronous) + | | -- ?? max sync offset (0x08 in NVRAM on 53c810a) + | | (0x10 in NVRAM on 53c875) + | --device bus width (0x08 narrow) + | (0x10 16 bit wide) + --flag bits + 0x00000001 - disconnect enabled + 0x00000010 - scan at boot time + 0x00000100 - scan luns + 0x00001000 - queue tags enabled remaining bytes unknown - they do not appear to change in my current set up -?? use of this data is a guess but seems reasonable +?? use of this data is a guess but seems reasonable (but it could be max bus width) default set up for 53c810a NVRAM -default set up for 53c875 NVRAM - bus width - 0x10 +default set up for 53c875 NVRAM + + - bus width - 0x10 - sync offset ? - 0x10 - sync period - 0x30 ------------------------------------------------------------ -?? spare device space (32 bit bus ??) - -00 00 00 00 00 00 00 00 (19x8bytes) -. -. -00 00 00 00 00 00 00 00 -default set up is identical for 53c810a and 53c875 NVRAM ------------------------------------------------------------ -trailer +?? spare device space (32 bit bus ??):: -fe fe - ? end marker ? -00 00 -00 00 + 00 00 00 00 00 00 00 00 (19x8bytes) + . + . + 00 00 00 00 00 00 00 00 default set up is identical for 53c810a and 53c875 NVRAM ------------------------------------------------------------ +trailer:: + fe fe - ? end marker ? + 00 00 + 00 00 + +default set up is identical for 53c810a and 53c875 NVRAM 17.3 Tekram NVRAM layout +------------------------ nvram 64x16 (1024 bit) -Drive settings - -Drive ID 0-15 (addr 0x0yyyy0 = device setup, yyyy = ID) - (addr 0x0yyyy1 = 0x0000) - - x x x x x x x x x x x x x x x x - | | | | | | | | | - | | | | | | | | ----- parity check 0 - off - | | | | | | | | 1 - on - | | | | | | | | - | | | | | | | ------- sync neg 0 - off - | | | | | | | 1 - on - | | | | | | | - | | | | | | --------- disconnect 0 - off - | | | | | | 1 - on - | | | | | | - | | | | | ----------- start cmd 0 - off - | | | | | 1 - on - | | | | | - | | | | -------------- tagged cmds 0 - off - | | | | 1 - on - | | | | - | | | ---------------- wide neg 0 - off - | | | 1 - on - | | | - --------------------------- sync rate 0 - 10.0 Mtrans/sec - 1 - 8.0 - 2 - 6.6 - 3 - 5.7 - 4 - 5.0 - 5 - 4.0 - 6 - 3.0 - 7 - 2.0 - 7 - 2.0 - 8 - 20.0 - 9 - 16.7 - a - 13.9 - b - 11.9 +Drive settings:: + + Drive ID 0-15 (addr 0x0yyyy0 = device setup, yyyy = ID) + (addr 0x0yyyy1 = 0x0000) + + x x x x x x x x x x x x x x x x + | | | | | | | | | + | | | | | | | | ----- parity check 0 - off + | | | | | | | | 1 - on + | | | | | | | | + | | | | | | | ------- sync neg 0 - off + | | | | | | | 1 - on + | | | | | | | + | | | | | | --------- disconnect 0 - off + | | | | | | 1 - on + | | | | | | + | | | | | ----------- start cmd 0 - off + | | | | | 1 - on + | | | | | + | | | | -------------- tagged cmds 0 - off + | | | | 1 - on + | | | | + | | | ---------------- wide neg 0 - off + | | | 1 - on + | | | + --------------------------- sync rate 0 - 10.0 Mtrans/sec + 1 - 8.0 + 2 - 6.6 + 3 - 5.7 + 4 - 5.0 + 5 - 4.0 + 6 - 3.0 + 7 - 2.0 + 7 - 2.0 + 8 - 20.0 + 9 - 16.7 + a - 13.9 + b - 11.9 Global settings -Host flags 0 (addr 0x100000, 32) +Host flags 0 (addr 0x100000, 32):: x x x x x x x x x x x x x x x x | | | | | | | | | | | | @@ -980,7 +1145,7 @@ Host flags 0 (addr 0x100000, 32) | | | | | | | | | | | | | | | ----------------------- support for 0 - off | | | | | | | > 2 drives 1 - on - | | | | | | | + | | | | | | | | | | | | | ------------------------- support drives 0 - off | | | | | | > 1Gbytes 1 - on | | | | | | @@ -1000,10 +1165,10 @@ Host flags 0 (addr 0x100000, 32) as BIOS dev 1 - boot device 2 - all -Host flags 1 (addr 0x100001, 33) +Host flags 1 (addr 0x100001, 33):: x x x x x x x x x x x x x x x x - | | | | | | + | | | | | | | | | --------- boot delay 0 - 3 sec | | | 1 - 5 | | | 2 - 10 @@ -1018,7 +1183,7 @@ Host flags 1 (addr 0x100001, 33) 3 - 16 4 - 32 -Host flags 2 (addr 0x100010, 34) +Host flags 2 (addr 0x100010, 34):: x x x x x x x x x x x x x x x x | @@ -1031,18 +1196,14 @@ checksum = 0x1234 - (sum addr 0-63) ---------------------------------------------------------------------------- -default nvram data: - -0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 -0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 -0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 -0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 - -0x0f07 0x0400 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000 -0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 -0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 -0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc +default nvram data:: + 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 + 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 + 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 + 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 0x0037 0x0000 -=============================================================================== -End of Linux SYM-2 driver documentation file + 0x0f07 0x0400 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000 + 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 + 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 + 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0xfbbc diff --git a/Documentation/scsi/tcm_qla2xxx.txt b/Documentation/scsi/tcm_qla2xxx.rst index c3a670a25e2b..91bc1fcd369e 100644 --- a/Documentation/scsi/tcm_qla2xxx.txt +++ b/Documentation/scsi/tcm_qla2xxx.rst @@ -1,22 +1,36 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======================== +tcm_qla2xxx Driver Notes +======================== + tcm_qla2xxx jam_host attribute ------------------------------ There is now a new module endpoint atribute called jam_host -attribute: jam_host: boolean=0/1 +attribute:: + + jam_host: boolean=0/1 + This attribute and accompanying code is only included if the Kconfig parameter TCM_QLA2XXX_DEBUG is set to Y + By default this jammer code and functionality is disabled Use this attribute to control the discarding of SCSI commands to a selected host. + This may be useful for testing error handling and simulating slow drain and other fabric issues. Setting a boolean of 1 for the jam_host attribute for a particular host - will discard the commands for that host. +will discard the commands for that host. + Reset back to 0 to stop the jamming. -Enable host 4 to be jammed -echo 1 > /sys/kernel/config/target/qla2xxx/21:00:00:24:ff:27:8f:ae/tpgt_1/attrib/jam_host +Enable host 4 to be jammed:: + + echo 1 > /sys/kernel/config/target/qla2xxx/21:00:00:24:ff:27:8f:ae/tpgt_1/attrib/jam_host + +Disable jamming on host 4:: -Disable jamming on host 4 -echo 0 > /sys/kernel/config/target/qla2xxx/21:00:00:24:ff:27:8f:ae/tpgt_1/attrib/jam_host + echo 0 > /sys/kernel/config/target/qla2xxx/21:00:00:24:ff:27:8f:ae/tpgt_1/attrib/jam_host diff --git a/Documentation/scsi/ufs.txt b/Documentation/scsi/ufs.rst index 81842ec3e116..a920c0a5a1f6 100644 --- a/Documentation/scsi/ufs.txt +++ b/Documentation/scsi/ufs.rst @@ -1,24 +1,26 @@ - Universal Flash Storage - ======================= +.. SPDX-License-Identifier: GPL-2.0 +======================= +Universal Flash Storage +======================= -Contents --------- -1. Overview -2. UFS Architecture Overview - 2.1 Application Layer - 2.2 UFS Transport Protocol(UTP) layer - 2.3 UFS Interconnect(UIC) Layer -3. UFSHCD Overview - 3.1 UFS controller initialization - 3.2 UTP Transfer requests - 3.3 UFS error handling - 3.4 SCSI Error handling +.. Contents + + 1. Overview + 2. UFS Architecture Overview + 2.1 Application Layer + 2.2 UFS Transport Protocol(UTP) layer + 2.3 UFS Interconnect(UIC) Layer + 3. UFSHCD Overview + 3.1 UFS controller initialization + 3.2 UTP Transfer requests + 3.3 UFS error handling + 3.4 SCSI Error handling 1. Overview ------------ +=========== Universal Flash Storage(UFS) is a storage specification for flash devices. It is aimed to provide a universal storage interface for both @@ -28,19 +30,25 @@ is defined by JEDEC Solid State Technology Association. UFS is based on MIPI M-PHY physical layer standard. UFS uses MIPI M-PHY as the physical layer and MIPI Unipro as the link layer. -The main goals of UFS is to provide, +The main goals of UFS is to provide: + * Optimized performance: - For UFS version 1.0 and 1.1 the target performance is as follows, - Support for Gear1 is mandatory (rate A: 1248Mbps, rate B: 1457.6Mbps) - Support for Gear2 is optional (rate A: 2496Mbps, rate B: 2915.2Mbps) + + For UFS version 1.0 and 1.1 the target performance is as follows: + + - Support for Gear1 is mandatory (rate A: 1248Mbps, rate B: 1457.6Mbps) + - Support for Gear2 is optional (rate A: 2496Mbps, rate B: 2915.2Mbps) + Future version of the standard, - Gear3 (rate A: 4992Mbps, rate B: 5830.4Mbps) + + - Gear3 (rate A: 4992Mbps, rate B: 5830.4Mbps) + * Low power consumption * High random IOPs and low latency 2. UFS Architecture Overview ----------------------------- +============================ UFS has a layered communication architecture which is based on SCSI SAM-5 architectural model. @@ -48,16 +56,22 @@ SAM-5 architectural model. UFS communication architecture consists of following layers, 2.1 Application Layer +--------------------- The Application layer is composed of UFS command set layer(UCS), Task Manager and Device manager. The UFS interface is designed to be protocol agnostic, however SCSI has been selected as a baseline protocol for versions 1.0 and 1.1 of UFS protocol layer. + UFS supports subset of SCSI commands defined by SPC-4 and SBC-3. - * UCS: It handles SCSI commands supported by UFS specification. - * Task manager: It handles task management functions defined by the + + * UCS: + It handles SCSI commands supported by UFS specification. + * Task manager: + It handles task management functions defined by the UFS which are meant for command queue control. - * Device manager: It handles device level operations and device + * Device manager: + It handles device level operations and device configuration operations. Device level operations mainly involve device power management operations and commands to Interconnect layers. Device level configurations involve handling of query @@ -65,10 +79,12 @@ UFS communication architecture consists of following layers, information of the device. 2.2 UFS Transport Protocol(UTP) layer +------------------------------------- UTP layer provides services for the higher layers through Service Access Points. UTP defines 3 service access points for higher layers. + * UDM_SAP: Device manager service access point is exposed to device manager for device level operations. These device level operations are done through query requests. @@ -76,20 +92,23 @@ UFS communication architecture consists of following layers, set layer(UCS) to transport commands. * UTP_TM_SAP: Task management service access point is exposed to task manager to transport task management functions. + UTP transports messages through UFS protocol information unit(UPIU). 2.3 UFS Interconnect(UIC) Layer +------------------------------- UIC is the lowest layer of UFS layered architecture. It handles connection between UFS host and UFS device. UIC consists of MIPI UniPro and MIPI M-PHY. UIC provides 2 service access points to upper layer, + * UIC_SAP: To transport UPIU between UFS host and UFS device. * UIO_SAP: To issue commands to Unipro layers. 3. UFSHCD Overview ------------------- +================== The UFS host controller driver is based on Linux SCSI Framework. UFSHCD is a low level device driver which acts as an interface between @@ -98,12 +117,14 @@ SCSI Midlayer and PCIe based UFS host controllers. The current UFSHCD implementation supports following functionality, 3.1 UFS controller initialization +--------------------------------- The initialization module brings UFS host controller to active state and prepares the controller to transfer commands/response between UFSHCD and UFS device. 3.2 UTP Transfer requests +------------------------- Transfer request handling module of UFSHCD receives SCSI commands from SCSI Midlayer, forms UPIUs and issues the UPIUs to UFS Host @@ -112,11 +133,13 @@ The current UFSHCD implementation supports following functionality, of the status of the command. 3.3 UFS error handling +---------------------- Error handling module handles Host controller fatal errors, Device fatal errors and UIC interconnect layer related errors. 3.4 SCSI Error handling +----------------------- This is done through UFSHCD SCSI error handling routines registered with SCSI Midlayer. Examples of some of the error handling commands @@ -129,7 +152,7 @@ In this version of UFSHCD Query requests and power management functionality are not implemented. 4. BSG Support ------------------- +============== This transport driver supports exchanging UFS protocol information units (UPIUs) with a UFS device. Typically, user space will allocate @@ -138,7 +161,7 @@ request_upiu and reply_upiu respectively. Filling those UPIUs should be done in accordance with JEDEC spec UFS2.1 paragraph 10.7. *Caveat emptor*: The driver makes no further input validations and sends the UPIU to the device as it is. Open the bsg device in /dev/ufs-bsg and -send SG_IO with the applicable sg_io_v4: +send SG_IO with the applicable sg_io_v4:: io_hdr_v4.guard = 'Q'; io_hdr_v4.protocol = BSG_PROTOCOL_SCSI; @@ -166,6 +189,7 @@ upiu-based protocol is available at: For more detailed information about the tool and its supported features, please see the tool's README. -UFS Specifications can be found at, -UFS - http://www.jedec.org/sites/default/files/docs/JESD220.pdf -UFSHCI - http://www.jedec.org/sites/default/files/docs/JESD223.pdf +UFS Specifications can be found at: + +- UFS - http://www.jedec.org/sites/default/files/docs/JESD220.pdf +- UFSHCI - http://www.jedec.org/sites/default/files/docs/JESD223.pdf diff --git a/Documentation/scsi/wd719x.rst b/Documentation/scsi/wd719x.rst new file mode 100644 index 000000000000..a35015dfedd9 --- /dev/null +++ b/Documentation/scsi/wd719x.rst @@ -0,0 +1,24 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============================================================== +Driver for Western Digital WD7193, WD7197 and WD7296 SCSI cards +=============================================================== + +The card requires firmware that can be cut out of the Windows NT driver that +can be downloaded from WD at: +http://support.wdc.com/product/download.asp?groupid=801&sid=27&lang=en + +There is no license anywhere in the file or on the page - so the firmware +probably cannot be added to linux-firmware. + +This script downloads and extracts the firmware, creating wd719x-risc.bin and +d719x-wcs.bin files. Put them in /lib/firmware/:: + + #!/bin/sh + wget http://support.wdc.com/download/archive/pciscsi.exe + lha xi pciscsi.exe pci-scsi.exe + lha xi pci-scsi.exe nt/wd7296a.sys + rm pci-scsi.exe + dd if=wd7296a.sys of=wd719x-risc.bin bs=1 skip=5760 count=14336 + dd if=wd7296a.sys of=wd719x-wcs.bin bs=1 skip=20096 count=514 + rm wd7296a.sys diff --git a/Documentation/scsi/wd719x.txt b/Documentation/scsi/wd719x.txt deleted file mode 100644 index 0816b0220238..000000000000 --- a/Documentation/scsi/wd719x.txt +++ /dev/null @@ -1,21 +0,0 @@ -Driver for Western Digital WD7193, WD7197 and WD7296 SCSI cards ---------------------------------------------------------------- - -The card requires firmware that can be cut out of the Windows NT driver that -can be downloaded from WD at: -http://support.wdc.com/product/download.asp?groupid=801&sid=27&lang=en - -There is no license anywhere in the file or on the page - so the firmware -probably cannot be added to linux-firmware. - -This script downloads and extracts the firmware, creating wd719x-risc.bin and -d719x-wcs.bin files. Put them in /lib/firmware/. - -#!/bin/sh -wget http://support.wdc.com/download/archive/pciscsi.exe -lha xi pciscsi.exe pci-scsi.exe -lha xi pci-scsi.exe nt/wd7296a.sys -rm pci-scsi.exe -dd if=wd7296a.sys of=wd719x-risc.bin bs=1 skip=5760 count=14336 -dd if=wd7296a.sys of=wd719x-wcs.bin bs=1 skip=20096 count=514 -rm wd7296a.sys diff --git a/MAINTAINERS b/MAINTAINERS index 863011649869..c3e43514f174 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -236,7 +236,7 @@ M: Adaptec OEM Raid Solutions <aacraid@microsemi.com> L: linux-scsi@vger.kernel.org W: http://www.adaptec.com/ S: Supported -F: Documentation/scsi/aacraid.txt +F: Documentation/scsi/aacraid.rst F: drivers/scsi/aacraid/ ABI/API @@ -540,7 +540,7 @@ M: Matthew Wilcox <willy@infradead.org> M: Hannes Reinecke <hare@suse.com> L: linux-scsi@vger.kernel.org S: Maintained -F: Documentation/scsi/advansys.txt +F: Documentation/scsi/advansys.rst F: drivers/scsi/advansys.c ADXL34X THREE-AXIS DIGITAL ACCELEROMETER DRIVER (ADXL345/ADXL346) @@ -4718,7 +4718,7 @@ L: dc395x@twibble.org W: http://twibble.org/dist/dc395x/ W: http://lists.twibble.org/mailman/listinfo/dc395x/ S: Maintained -F: Documentation/scsi/dc395x.txt +F: Documentation/scsi/dc395x.rst F: drivers/scsi/dc395x.* DCCP PROTOCOL @@ -7491,7 +7491,7 @@ M: Don Brace <don.brace@microsemi.com> L: esc.storagedev@microsemi.com L: linux-scsi@vger.kernel.org S: Supported -F: Documentation/scsi/hpsa.txt +F: Documentation/scsi/hpsa.rst F: drivers/scsi/hpsa*.[ch] F: include/linux/cciss*.h F: include/uapi/linux/cciss*.h @@ -7580,7 +7580,7 @@ HIGHPOINT ROCKETRAID 3xxx RAID DRIVER M: HighPoint Linux Team <linux@highpoint-tech.com> W: http://www.highpoint-tech.com S: Supported -F: Documentation/scsi/hptiop.txt +F: Documentation/scsi/hptiop.rst F: drivers/scsi/hptiop.c HIPPI @@ -9473,7 +9473,7 @@ LASI 53c700 driver for PARISC M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com> L: linux-scsi@vger.kernel.org S: Maintained -F: Documentation/scsi/53c700.txt +F: Documentation/scsi/53c700.rst F: drivers/scsi/53c700* LEAKING_ADDRESSES @@ -10741,7 +10741,7 @@ L: megaraidlinux.pdl@broadcom.com L: linux-scsi@vger.kernel.org W: http://www.avagotech.com/support/ S: Maintained -F: Documentation/scsi/megaraid.txt +F: Documentation/scsi/megaraid.rst F: drivers/scsi/megaraid.* F: drivers/scsi/megaraid/ @@ -11195,7 +11195,7 @@ F: drivers/scsi/smartpqi/Kconfig F: drivers/scsi/smartpqi/Makefile F: include/linux/cciss*.h F: include/uapi/linux/cciss*.h -F: Documentation/scsi/smartpqi.txt +F: Documentation/scsi/smartpqi.rst MICROSEMI ETHERNET SWITCH DRIVER M: Alexandre Belloni <alexandre.belloni@bootlin.com> @@ -11577,7 +11577,7 @@ M: Finn Thain <fthain@telegraphics.com.au> M: Michael Schmitz <schmitzmic@gmail.com> L: linux-scsi@vger.kernel.org S: Maintained -F: Documentation/scsi/g_NCR5380.txt +F: Documentation/scsi/g_NCR5380.rst F: drivers/scsi/NCR5380.* F: drivers/scsi/arm/cumana_1.c F: drivers/scsi/arm/oak.c @@ -11906,7 +11906,7 @@ NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER M: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp> W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/ S: Maintained -F: Documentation/scsi/NinjaSCSI.txt +F: Documentation/scsi/NinjaSCSI.rst F: drivers/scsi/pcmcia/nsp_* NINJA SCSI-32Bi/UDE PCI/CARDBUS SCSI HOST ADAPTER DRIVER @@ -11914,7 +11914,7 @@ M: GOTO Masanori <gotom@debian.or.jp> M: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp> W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/ S: Maintained -F: Documentation/scsi/NinjaSCSI.txt +F: Documentation/scsi/NinjaSCSI.rst F: drivers/scsi/nsp32* NIOS2 ARCHITECTURE @@ -14929,7 +14929,7 @@ M: Doug Gilbert <dgilbert@interlog.com> L: linux-scsi@vger.kernel.org W: http://sg.danny.cz/sg S: Maintained -F: Documentation/scsi/scsi-generic.txt +F: Documentation/scsi/scsi-generic.rst F: drivers/scsi/sg.c F: include/scsi/sg.h @@ -14949,7 +14949,7 @@ SCSI TAPE DRIVER M: Kai Mäkisara <Kai.Makisara@kolumbus.fi> L: linux-scsi@vger.kernel.org S: Maintained -F: Documentation/scsi/st.txt +F: Documentation/scsi/st.rst F: drivers/scsi/st.* F: drivers/scsi/st_*.h @@ -17306,7 +17306,7 @@ R: Alim Akhtar <alim.akhtar@samsung.com> R: Avri Altman <avri.altman@wdc.com> L: linux-scsi@vger.kernel.org S: Supported -F: Documentation/scsi/ufs.txt +F: Documentation/scsi/ufs.rst F: drivers/scsi/ufs/ UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER DWC HOOKS diff --git a/arch/alpha/configs/defconfig b/arch/alpha/configs/defconfig index f4ec420d7f2d..3a132c91d45b 100644 --- a/arch/alpha/configs/defconfig +++ b/arch/alpha/configs/defconfig @@ -36,7 +36,6 @@ CONFIG_BLK_DEV_CY82C693=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SCSI_AIC7XXX=m CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set diff --git a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig index 3b82b64950d9..c090643b1ecb 100644 --- a/arch/arm/configs/rpc_defconfig +++ b/arch/arm/configs/rpc_defconfig @@ -32,7 +32,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 73ed73a8785a..153009130dab 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -202,7 +202,6 @@ CONFIG_EEPROM_AT24=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=m CONFIG_SCSI_CONSTANTS=y diff --git a/arch/c6x/include/asm/unaligned.h b/arch/c6x/include/asm/unaligned.h index b56ba7110f5a..d628cc170564 100644 --- a/arch/c6x/include/asm/unaligned.h +++ b/arch/c6x/include/asm/unaligned.h @@ -10,6 +10,7 @@ #define _ASM_C6X_UNALIGNED_H #include <linux/swab.h> +#include <linux/unaligned/generic.h> /* * The C64x+ can do unaligned word and dword accesses in hardware @@ -100,68 +101,4 @@ static inline void put_unaligned64(u64 val, const void *p) #endif -/* - * Cause a link-time error if we try an unaligned access other than - * 1,2,4 or 8 bytes long - */ -extern int __bad_unaligned_access_size(void); - -#define __get_unaligned_le(ptr) (typeof(*(ptr)))({ \ - sizeof(*(ptr)) == 1 ? *(ptr) : \ - (sizeof(*(ptr)) == 2 ? get_unaligned_le16((ptr)) : \ - (sizeof(*(ptr)) == 4 ? get_unaligned_le32((ptr)) : \ - (sizeof(*(ptr)) == 8 ? get_unaligned_le64((ptr)) : \ - __bad_unaligned_access_size()))); \ - }) - -#define __get_unaligned_be(ptr) (__force typeof(*(ptr)))({ \ - sizeof(*(ptr)) == 1 ? *(ptr) : \ - (sizeof(*(ptr)) == 2 ? get_unaligned_be16((ptr)) : \ - (sizeof(*(ptr)) == 4 ? get_unaligned_be32((ptr)) : \ - (sizeof(*(ptr)) == 8 ? get_unaligned_be64((ptr)) : \ - __bad_unaligned_access_size()))); \ - }) - -#define __put_unaligned_le(val, ptr) ({ \ - void *__gu_p = (ptr); \ - switch (sizeof(*(ptr))) { \ - case 1: \ - *(u8 *)__gu_p = (__force u8)(val); \ - break; \ - case 2: \ - put_unaligned_le16((__force u16)(val), __gu_p); \ - break; \ - case 4: \ - put_unaligned_le32((__force u32)(val), __gu_p); \ - break; \ - case 8: \ - put_unaligned_le64((__force u64)(val), __gu_p); \ - break; \ - default: \ - __bad_unaligned_access_size(); \ - break; \ - } \ - (void)0; }) - -#define __put_unaligned_be(val, ptr) ({ \ - void *__gu_p = (ptr); \ - switch (sizeof(*(ptr))) { \ - case 1: \ - *(u8 *)__gu_p = (__force u8)(val); \ - break; \ - case 2: \ - put_unaligned_be16((__force u16)(val), __gu_p); \ - break; \ - case 4: \ - put_unaligned_be32((__force u32)(val), __gu_p); \ - break; \ - case 8: \ - put_unaligned_be64((__force u64)(val), __gu_p); \ - break; \ - default: \ - __bad_unaligned_access_size(); \ - break; \ - } \ - (void)0; }) - #endif /* _ASM_C6X_UNALIGNED_H */ diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig index 8c92e095f8bb..d42f79a33e91 100644 --- a/arch/ia64/configs/zx1_defconfig +++ b/arch/ia64/configs/zx1_defconfig @@ -35,7 +35,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_CHR_DEV_OSST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index 9818d0ed143e..5b3a273ae3da 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -333,7 +333,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index db2402c75300..0bf0907a7c80 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -318,7 +318,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 07a28b48eb43..876e69292294 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -333,7 +333,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index 033589367cb1..aa59c242e715 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -315,7 +315,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index ee4d02a90214..308cd93929a9 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -317,7 +317,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index 442eed608ebc..0bc210ace870 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -324,7 +324,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 1de7da7c1041..3b3b832dee80 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -357,7 +357,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index ced341e047db..e3633c66926f 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -314,7 +314,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 006188f1f063..88b3f7f9f146 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -315,7 +315,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index c65d985ee642..3dd5b536921e 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -323,7 +323,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 32905fe56cd7..715e015ed270 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -312,7 +312,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 32b0969668fe..f9ff129ac7c2 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -312,7 +312,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SAS_ATTRS=m diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index f14ad0538f4e..eea9b613bb74 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig @@ -112,7 +112,6 @@ CONFIG_BLK_DEV_TC86C001=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_CHR_DEV_SCH=m CONFIG_ATA=y diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig index 1788ae23bff9..6466e83067b4 100644 --- a/arch/mips/configs/fuloong2e_defconfig +++ b/arch/mips/configs/fuloong2e_defconfig @@ -99,7 +99,6 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_ATA_OVER_ETH=m CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOWLEVEL is not set diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 82d942a6026e..638d7cf5ef01 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -99,7 +99,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_CHR_DEV_SCH=m CONFIG_SCSI_CONSTANTS=y diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 370884018aad..7b1fab518317 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -50,7 +50,6 @@ CONFIG_RAID_ATTRS=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig index 92085df3e367..8c223035921f 100644 --- a/arch/mips/configs/jazz_defconfig +++ b/arch/mips/configs/jazz_defconfig @@ -42,7 +42,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_ISCSI_TCP=m diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig index 59eedf55419d..211bd3d6e6cb 100644 --- a/arch/mips/configs/malta_defconfig +++ b/arch/mips/configs/malta_defconfig @@ -239,7 +239,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig index 8ef612552a19..62b1969b4f55 100644 --- a/arch/mips/configs/malta_kvm_defconfig +++ b/arch/mips/configs/malta_kvm_defconfig @@ -247,7 +247,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/mips/configs/malta_kvm_guest_defconfig b/arch/mips/configs/malta_kvm_guest_defconfig index d2a008c9907c..9185e0a0aa45 100644 --- a/arch/mips/configs/malta_kvm_guest_defconfig +++ b/arch/mips/configs/malta_kvm_guest_defconfig @@ -245,7 +245,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/mips/configs/maltaup_xpa_defconfig b/arch/mips/configs/maltaup_xpa_defconfig index 970df6d42728..636311d67a53 100644 --- a/arch/mips/configs/maltaup_xpa_defconfig +++ b/arch/mips/configs/maltaup_xpa_defconfig @@ -245,7 +245,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index 2c7adea7638f..30d7c3db884e 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -203,7 +203,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/powerpc/configs/85xx-hw.config b/arch/powerpc/configs/85xx-hw.config index 9575a38c9155..b507df6ac69f 100644 --- a/arch/powerpc/configs/85xx-hw.config +++ b/arch/powerpc/configs/85xx-hw.config @@ -2,7 +2,6 @@ CONFIG_AQUANTIA_PHY=y CONFIG_AT803X_PHY=y CONFIG_ATA=y CONFIG_BLK_DEV_SD=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_BLK_DEV_SR=y CONFIG_BROADCOM_PHY=y CONFIG_C293_PCIE=y diff --git a/arch/powerpc/configs/amigaone_defconfig b/arch/powerpc/configs/amigaone_defconfig index f6d140f2d922..200bb1ecb560 100644 --- a/arch/powerpc/configs/amigaone_defconfig +++ b/arch/powerpc/configs/amigaone_defconfig @@ -44,7 +44,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SYM53C8XX_2=y diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig index 502a75d49789..a4a805b87469 100644 --- a/arch/powerpc/configs/chrp32_defconfig +++ b/arch/powerpc/configs/chrp32_defconfig @@ -42,7 +42,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SYM53C8XX_2=y diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index fbfcc85e4dc0..a68c7f3af10e 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -62,7 +62,6 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index 2975e64629aa..161351a18517 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig @@ -41,7 +41,6 @@ CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_IPR=y CONFIG_ATA=y diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig index 4b6d31d4474e..08b7f4cef243 100644 --- a/arch/powerpc/configs/pasemi_defconfig +++ b/arch/powerpc/configs/pasemi_defconfig @@ -60,7 +60,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_CHR_DEV_OSST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=y CONFIG_SCSI_CONSTANTS=y diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index f492e7d35925..05e325ca3fbd 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig @@ -117,7 +117,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig index 71749377d164..df8bdbaa5d8f 100644 --- a/arch/powerpc/configs/powernv_defconfig +++ b/arch/powerpc/configs/powernv_defconfig @@ -108,7 +108,6 @@ CONFIG_BLK_DEV_NVME=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 7e68cb222c7b..bae8170d7401 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -110,7 +110,6 @@ CONFIG_VIRTIO_BLK=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 0d746774c2bd..33a01a9e86be 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig @@ -60,7 +60,6 @@ CONFIG_BLK_DEV_RAM_SIZE=65536 CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig index 3e2f44f38ac5..feb5d47d8d1e 100644 --- a/arch/powerpc/configs/ppc6xx_defconfig +++ b/arch/powerpc/configs/ppc6xx_defconfig @@ -368,7 +368,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=m CONFIG_SCSI_ENCLOSURE=m diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 6b68109e248f..0bea4d3ffb85 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -97,7 +97,6 @@ CONFIG_VIRTIO_BLK=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_FC_ATTRS=y diff --git a/arch/powerpc/configs/skiroot_defconfig b/arch/powerpc/configs/skiroot_defconfig index 1b6bdad36b13..ad6739ac63dc 100644 --- a/arch/powerpc/configs/skiroot_defconfig +++ b/arch/powerpc/configs/skiroot_defconfig @@ -84,7 +84,6 @@ CONFIG_EEPROM_AT24=m # CONFIG_OCXL is not set CONFIG_BLK_DEV_SD=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y diff --git a/arch/sh/configs/sh03_defconfig b/arch/sh/configs/sh03_defconfig index e5beb625ab88..87db9a84b5ec 100644 --- a/arch/sh/configs/sh03_defconfig +++ b/arch/sh/configs/sh03_defconfig @@ -46,7 +46,6 @@ CONFIG_BLK_DEV_IDETAPE=m CONFIG_SCSI=m CONFIG_BLK_DEV_SD=m CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig index 6c325d53a20a..bde4d21a8ac8 100644 --- a/arch/sparc/configs/sparc64_defconfig +++ b/arch/sparc/configs/sparc64_defconfig @@ -73,7 +73,6 @@ CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=m CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index 5b602beb0b72..ab8b30cb978e 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig @@ -136,7 +136,6 @@ CONFIG_CONNECTOR=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index f3d1f36103b1..2d196cb49084 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -134,7 +134,6 @@ CONFIG_CONNECTOR=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index b4e73d5dd5c2..ef722f04f88a 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -193,6 +193,10 @@ static void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter) __set_bit(GPCMD_LOAD_UNLOAD, filter->write_ok); __set_bit(GPCMD_SET_STREAMING, filter->write_ok); __set_bit(GPCMD_SET_READ_AHEAD, filter->write_ok); + + /* ZBC Commands */ + __set_bit(ZBC_OUT, filter->write_ok); + __set_bit(ZBC_IN, filter->read_ok); } int blk_verify_command(unsigned char *cmd, fmode_t mode) diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index 8a24494f8c4d..a1ec7e84d6fe 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -64,6 +64,7 @@ #include <linux/if_arp.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/printk.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/workqueue.h> @@ -111,13 +112,13 @@ MODULE_DESCRIPTION(LANAME); #ifdef MPT_LAN_IO_DEBUG #define dioprintk(x) printk x #else -#define dioprintk(x) +#define dioprintk(x) no_printk x #endif #ifdef MPT_LAN_DEBUG #define dlprintk(x) printk x #else -#define dlprintk(x) +#define dlprintk(x) no_printk x #endif #define NETDEV_TO_LANPRIV_PTR(d) ((struct mpt_lan_priv *)netdev_priv(d)) diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h index c396483d3624..e35b13891fe4 100644 --- a/drivers/message/fusion/mptsas.h +++ b/drivers/message/fusion/mptsas.h @@ -110,7 +110,7 @@ struct fw_event_work { MPT_ADAPTER *ioc; u32 event; u8 retries; - char event_data[0] __aligned(4); + char event_data[] __aligned(4); }; struct mptsas_discovery_event { diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 86603d9b0cef..76dbb55625ac 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -142,14 +142,6 @@ static void nvme_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc); static const struct blk_mq_ops nvme_rdma_mq_ops; static const struct blk_mq_ops nvme_rdma_admin_mq_ops; -/* XXX: really should move to a generic header sooner or later.. */ -static inline void put_unaligned_le24(u32 val, u8 *p) -{ - *p++ = val; - *p++ = val >> 8; - *p++ = val >> 16; -} - static inline int nvme_rdma_queue_idx(struct nvme_rdma_queue *queue) { return queue - queue->ctrl->queues; diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c index 9e1b8c61f54e..c90c06839d64 100644 --- a/drivers/nvme/target/rdma.c +++ b/drivers/nvme/target/rdma.c @@ -146,12 +146,6 @@ static int num_pages(int len) return 1 + (((len - 1) & PAGE_MASK) >> PAGE_SHIFT); } -/* XXX: really should move to a generic header sooner or later.. */ -static inline u32 get_unaligned_le24(const u8 *p) -{ - return (u32)p[0] | (u32)p[1] << 8 | (u32)p[2] << 16; -} - static inline bool nvmet_rdma_need_data_in(struct nvmet_rdma_rsp *rsp) { return nvme_is_write(rsp->req.cmd) && diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 1234294700c4..673e42defb91 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -4,7 +4,7 @@ * * Debug traces for zfcp. * - * Copyright IBM Corp. 2002, 2018 + * Copyright IBM Corp. 2002, 2020 */ #define KMSG_COMPONENT "zfcp" @@ -104,6 +104,48 @@ void zfcp_dbf_hba_fsf_res(char *tag, int level, struct zfcp_fsf_req *req) } /** + * zfcp_dbf_hba_fsf_fces - trace event for fsf responses related to + * FC Endpoint Security (FCES) + * @tag: tag indicating which kind of FC Endpoint Security event has occurred + * @req: request for which a response was received + * @wwpn: remote port or ZFCP_DBF_INVALID_WWPN + * @fc_security_old: old FC Endpoint Security of FCP device or connection + * @fc_security_new: new FC Endpoint Security of FCP device or connection + */ +void zfcp_dbf_hba_fsf_fces(char *tag, const struct zfcp_fsf_req *req, u64 wwpn, + u32 fc_security_old, u32 fc_security_new) +{ + struct zfcp_dbf *dbf = req->adapter->dbf; + struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix; + struct fsf_qtcb_header *q_head = &req->qtcb->header; + struct zfcp_dbf_hba *rec = &dbf->hba_buf; + static int const level = 3; + unsigned long flags; + + if (unlikely(!debug_level_enabled(dbf->hba, level))) + return; + + spin_lock_irqsave(&dbf->hba_lock, flags); + memset(rec, 0, sizeof(*rec)); + + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_HBA_FCES; + rec->fsf_req_id = req->req_id; + rec->fsf_req_status = req->status; + rec->fsf_cmd = q_head->fsf_command; + rec->fsf_seq_no = q_pref->req_seq_no; + rec->u.fces.req_issued = req->issued; + rec->u.fces.fsf_status = q_head->fsf_status; + rec->u.fces.port_handle = q_head->port_handle; + rec->u.fces.wwpn = wwpn; + rec->u.fces.fc_security_old = fc_security_old; + rec->u.fces.fc_security_new = fc_security_new; + + debug_event(dbf->hba, level, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->hba_lock, flags); +} + +/** * zfcp_dbf_hba_fsf_uss - trace event for an unsolicited status buffer * @tag: tag indicating which kind of unsolicited status has been received * @req: request providing the unsolicited status diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 900c779cc39b..4d1435c573bc 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -3,7 +3,7 @@ * zfcp device driver * debug feature declarations * - * Copyright IBM Corp. 2008, 2017 + * Copyright IBM Corp. 2008, 2020 */ #ifndef ZFCP_DBF_H @@ -16,6 +16,7 @@ #define ZFCP_DBF_TAG_LEN 7 +#define ZFCP_DBF_INVALID_WWPN 0x0000000000000000ull #define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull enum zfcp_dbf_pseudo_erp_act_type { @@ -158,17 +159,38 @@ struct zfcp_dbf_hba_uss { } __packed; /** + * struct zfcp_dbf_hba_fces - trace record for FC Endpoint Security + * @req_issued: timestamp when request was issued + * @fsf_status: fsf status + * @port_handle: handle for port + * @wwpn: remote FC port WWPN + * @fc_security_old: old FC Endpoint Security + * @fc_security_new: new FC Endpoint Security + * + */ +struct zfcp_dbf_hba_fces { + u64 req_issued; + u32 fsf_status; + u32 port_handle; + u64 wwpn; + u32 fc_security_old; + u32 fc_security_new; +} __packed; + +/** * enum zfcp_dbf_hba_id - HBA trace record identifier * @ZFCP_DBF_HBA_RES: response trace record * @ZFCP_DBF_HBA_USS: unsolicited status trace record * @ZFCP_DBF_HBA_BIT: bit error trace record * @ZFCP_DBF_HBA_BASIC: basic adapter event, only trace tag, no other data + * @ZFCP_DBF_HBA_FCES: FC Endpoint Security trace record */ enum zfcp_dbf_hba_id { ZFCP_DBF_HBA_RES = 1, ZFCP_DBF_HBA_USS = 2, ZFCP_DBF_HBA_BIT = 3, ZFCP_DBF_HBA_BASIC = 4, + ZFCP_DBF_HBA_FCES = 5, }; /** @@ -181,9 +203,10 @@ enum zfcp_dbf_hba_id { * @fsf_seq_no: fsf sequence number * @pl_len: length of payload stored as zfcp_dbf_pay * @u: record type specific data - * @u.res: data for fsf responses - * @u.uss: data for unsolicited status buffer - * @u.be: data for bit error unsolicited status buffer + * @u.res: data for fsf responses + * @u.uss: data for unsolicited status buffer + * @u.be: data for bit error unsolicited status buffer + * @u.fces: data for FC Endpoint Security */ struct zfcp_dbf_hba { u8 id; @@ -197,6 +220,7 @@ struct zfcp_dbf_hba { struct zfcp_dbf_hba_res res; struct zfcp_dbf_hba_uss uss; struct fsf_bit_error_payload be; + struct zfcp_dbf_hba_fces fces; } u; } __packed; diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 8cc0eefe4ccc..da8a5ceb615c 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -4,7 +4,7 @@ * * Global definitions for the zfcp device driver. * - * Copyright IBM Corp. 2002, 2018 + * Copyright IBM Corp. 2002, 2020 */ #ifndef ZFCP_DEF_H @@ -158,6 +158,8 @@ struct zfcp_adapter { u32 adapter_features; /* FCP channel features */ u32 connection_features; /* host connection features */ u32 hardware_version; /* of FCP channel */ + u32 fc_security_algorithms; /* of FCP channel */ + u32 fc_security_algorithms_old; /* of FCP channel */ u16 timer_ticks; /* time int for a tick */ struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ struct list_head port_list; /* remote port list */ @@ -218,6 +220,8 @@ struct zfcp_port { atomic_t erp_counter; u32 maxframe_size; u32 supported_classes; + u32 connection_info; + u32 connection_info_old; struct work_struct gid_pn_work; struct work_struct test_link_work; struct work_struct rport_work; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 93655b85b73f..18a6751299f9 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -725,7 +725,7 @@ static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) adapter->peer_d_id); if (IS_ERR(port)) /* error or port already attached */ return; - _zfcp_erp_port_reopen(port, 0, "ereptp1"); + zfcp_erp_port_reopen(port, 0, "ereptp1"); } static enum zfcp_erp_act_result zfcp_erp_adapter_strat_fsf_xconf( diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index c8556787cfdc..88294ca0e2ea 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -4,7 +4,7 @@ * * External function declarations. * - * Copyright IBM Corp. 2002, 2018 + * Copyright IBM Corp. 2002, 2020 */ #ifndef ZFCP_EXT_H @@ -44,6 +44,9 @@ extern void zfcp_dbf_rec_run_lvl(int level, char *tag, extern void zfcp_dbf_rec_run_wka(char *, struct zfcp_fc_wka_port *, u64); extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_fsf_res(char *, int, struct zfcp_fsf_req *); +extern void zfcp_dbf_hba_fsf_fces(char *tag, const struct zfcp_fsf_req *req, + u64 wwpn, u32 fc_security_old, + u32 fc_security_new); extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *); @@ -135,6 +138,13 @@ extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_device *sdev, u8 tm_flags); extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *); extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int); +enum zfcp_fsf_print_fmt { + ZFCP_FSF_PRINT_FMT_LIST, + ZFCP_FSF_PRINT_FMT_SINGLEITEM, +}; +extern ssize_t zfcp_fsf_scnprint_fc_security(char *buf, size_t size, + u32 fc_security, + enum zfcp_fsf_print_fmt fmt); /* zfcp_qdio.c */ extern int zfcp_qdio_setup(struct zfcp_adapter *); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index cae9b7ff79b0..7c603e5b5b19 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4,7 +4,7 @@ * * Implementation of FSF commands. * - * Copyright IBM Corp. 2002, 2018 + * Copyright IBM Corp. 2002, 2020 */ #define KMSG_COMPONENT "zfcp" @@ -120,6 +120,23 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) read_unlock_irqrestore(&adapter->port_list_lock, flags); } +static void zfcp_fsf_fc_host_link_down(struct zfcp_adapter *adapter) +{ + struct Scsi_Host *shost = adapter->scsi_host; + + fc_host_port_id(shost) = 0; + fc_host_fabric_name(shost) = 0; + fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; + fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; + adapter->hydra_version = 0; + snprintf(fc_host_model(shost), FC_SYMBOLIC_NAME_SIZE, "0x%04x", 0); + memset(fc_host_active_fc4s(shost), 0, FC_FC4_LIST_SIZE); + + adapter->peer_wwpn = 0; + adapter->peer_wwnn = 0; + adapter->peer_d_id = 0; +} + static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, struct fsf_link_down_info *link_down) { @@ -132,6 +149,8 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, zfcp_scsi_schedule_rports_block(adapter); + zfcp_fsf_fc_host_link_down(adapter); + if (!link_down) goto out; @@ -502,6 +521,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) if (req->data) memcpy(req->data, bottom, sizeof(*bottom)); + snprintf(fc_host_manufacturer(shost), FC_SERIAL_NUMBER_SIZE, "%s", + "IBM"); fc_host_port_name(shost) = be64_to_cpu(nsp->fl_wwpn); fc_host_node_name(shost) = be64_to_cpu(nsp->fl_wwnn); fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; @@ -510,9 +531,6 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) adapter->stat_read_buf_num = max(bottom->status_read_buf_num, (u16)FSF_STATUS_READS_RECOM); - if (fc_host_permanent_port_name(shost) == -1) - fc_host_permanent_port_name(shost) = fc_host_port_name(shost); - zfcp_scsi_set_prot(adapter); /* no error return above here, otherwise must fix call chains */ @@ -525,6 +543,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) zfcp_fsf_convert_portspeed(bottom->fc_link_speed); adapter->hydra_version = bottom->adapter_type; + snprintf(fc_host_model(shost), FC_SYMBOLIC_NAME_SIZE, "0x%04x", + bottom->adapter_type); switch (bottom->fc_topology) { case FSF_TOPO_P2P: @@ -532,8 +552,10 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) adapter->peer_wwpn = be64_to_cpu(plogi->fl_wwpn); adapter->peer_wwnn = be64_to_cpu(plogi->fl_wwnn); fc_host_port_type(shost) = FC_PORTTYPE_PTP; + fc_host_fabric_name(shost) = 0; break; case FSF_TOPO_FABRIC: + fc_host_fabric_name(shost) = be64_to_cpu(plogi->fl_wwnn); if (bottom->connection_features & FSF_FEATURE_NPIV_MODE) fc_host_port_type(shost) = FC_PORTTYPE_NPIV; else @@ -541,8 +563,10 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) break; case FSF_TOPO_AL: fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; + fc_host_fabric_name(shost) = 0; /* fall through */ default: + fc_host_fabric_name(shost) = 0; dev_err(&adapter->ccw_device->dev, "Unknown or unsupported arbitrated loop " "fibre channel topology detected\n"); @@ -565,6 +589,8 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; + snprintf(fc_host_firmware_version(shost), FC_VERSION_STRING_SIZE, + "0x%08x", bottom->lic_version); adapter->fsf_lic_version = bottom->lic_version; adapter->adapter_features = bottom->adapter_features; adapter->connection_features = bottom->connection_features; @@ -598,13 +624,6 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) zfcp_diag_update_xdata(diag_hdr, bottom, true); req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE; - fc_host_node_name(shost) = 0; - fc_host_port_name(shost) = 0; - fc_host_port_id(shost) = 0; - fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; - fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; - adapter->hydra_version = 0; - /* avoids adapter shutdown to be able to recognize * events such as LINK UP */ atomic_or(ZFCP_STATUS_ADAPTER_XCONFIG_OK, @@ -621,6 +640,9 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { adapter->hardware_version = bottom->hardware_version; + snprintf(fc_host_hardware_version(shost), + FC_VERSION_STRING_SIZE, + "0x%08x", bottom->hardware_version); memcpy(fc_host_serial_number(shost), bottom->serial_number, min(FC_SERIAL_NUMBER_SIZE, 17)); EBCASC(fc_host_serial_number(shost), @@ -642,6 +664,99 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) } } +/* + * Mapping of FC Endpoint Security flag masks to mnemonics + * + * NOTE: Update macro ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH when making any + * changes. + */ +static const struct { + u32 mask; + char *name; +} zfcp_fsf_fc_security_mnemonics[] = { + { FSF_FC_SECURITY_AUTH, "Authentication" }, + { FSF_FC_SECURITY_ENC_FCSP2 | + FSF_FC_SECURITY_ENC_ERAS, "Encryption" }, +}; + +/* maximum strlen(zfcp_fsf_fc_security_mnemonics[...].name) + 1 */ +#define ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH 15 + +/** + * zfcp_fsf_scnprint_fc_security() - translate FC Endpoint Security flags into + * mnemonics and place in a buffer + * @buf : the buffer to place the translated FC Endpoint Security flag(s) + * into + * @size : the size of the buffer, including the trailing null space + * @fc_security: one or more FC Endpoint Security flags, or zero + * @fmt : specifies whether a list or a single item is to be put into the + * buffer + * + * The Fibre Channel (FC) Endpoint Security flags are translated into mnemonics. + * If the FC Endpoint Security flags are zero "none" is placed into the buffer. + * + * With ZFCP_FSF_PRINT_FMT_LIST the mnemonics are placed as a list separated by + * a comma followed by a space into the buffer. If one or more FC Endpoint + * Security flags cannot be translated into a mnemonic, as they are undefined + * in zfcp_fsf_fc_security_mnemonics, their bitwise ORed value in hexadecimal + * representation is placed into the buffer. + * + * With ZFCP_FSF_PRINT_FMT_SINGLEITEM only one single mnemonic is placed into + * the buffer. If the FC Endpoint Security flag cannot be translated, as it is + * undefined in zfcp_fsf_fc_security_mnemonics, its value in hexadecimal + * representation is placed into the buffer. If more than one FC Endpoint + * Security flag was specified, their value in hexadecimal representation is + * placed into the buffer. The macro ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH + * can be used to define a buffer that is large enough to hold one mnemonic. + * + * Return: The number of characters written into buf not including the trailing + * '\0'. If size is == 0 the function returns 0. + */ +ssize_t zfcp_fsf_scnprint_fc_security(char *buf, size_t size, u32 fc_security, + enum zfcp_fsf_print_fmt fmt) +{ + const char *prefix = ""; + ssize_t len = 0; + int i; + + if (fc_security == 0) + return scnprintf(buf, size, "none"); + if (fmt == ZFCP_FSF_PRINT_FMT_SINGLEITEM && hweight32(fc_security) != 1) + return scnprintf(buf, size, "0x%08x", fc_security); + + for (i = 0; i < ARRAY_SIZE(zfcp_fsf_fc_security_mnemonics); i++) { + if (!(fc_security & zfcp_fsf_fc_security_mnemonics[i].mask)) + continue; + + len += scnprintf(buf + len, size - len, "%s%s", prefix, + zfcp_fsf_fc_security_mnemonics[i].name); + prefix = ", "; + fc_security &= ~zfcp_fsf_fc_security_mnemonics[i].mask; + } + + if (fc_security != 0) + len += scnprintf(buf + len, size - len, "%s0x%08x", + prefix, fc_security); + + return len; +} + +static void zfcp_fsf_dbf_adapter_fc_security(struct zfcp_adapter *adapter, + struct zfcp_fsf_req *req) +{ + if (adapter->fc_security_algorithms == + adapter->fc_security_algorithms_old) { + /* no change, no trace */ + return; + } + + zfcp_dbf_hba_fsf_fces("fsfcesa", req, ZFCP_DBF_INVALID_WWPN, + adapter->fc_security_algorithms_old, + adapter->fc_security_algorithms); + + adapter->fc_security_algorithms_old = adapter->fc_security_algorithms; +} + static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; @@ -651,10 +766,7 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) if (req->data) memcpy(req->data, bottom, sizeof(*bottom)); - if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { - fc_host_permanent_port_name(shost) = bottom->wwpn; - } else - fc_host_permanent_port_name(shost) = fc_host_port_name(shost); + fc_host_permanent_port_name(shost) = bottom->wwpn; fc_host_maxframe_size(shost) = bottom->maximum_frame_size; fc_host_supported_speeds(shost) = zfcp_fsf_convert_portspeed(bottom->supported_speed); @@ -662,6 +774,12 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) FC_FC4_LIST_SIZE); memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, FC_FC4_LIST_SIZE); + if (adapter->adapter_features & FSF_FEATURE_FC_SECURITY) + adapter->fc_security_algorithms = + bottom->fc_security_algorithms; + else + adapter->fc_security_algorithms = 0; + zfcp_fsf_dbf_adapter_fc_security(adapter, req); } static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) @@ -688,9 +806,9 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) zfcp_diag_update_xdata(diag_hdr, bottom, true); req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE; - zfcp_fsf_exchange_port_evaluate(req); zfcp_fsf_link_down_info_eval(req, &qtcb->header.fsf_status_qual.link_down_info); + zfcp_fsf_exchange_port_evaluate(req); break; } } @@ -1287,7 +1405,8 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) req->qtcb->bottom.config.feature_selection = FSF_FEATURE_NOTIFICATION_LOST | FSF_FEATURE_UPDATE_ALERT | - FSF_FEATURE_REQUEST_SFP_DATA; + FSF_FEATURE_REQUEST_SFP_DATA | + FSF_FEATURE_FC_SECURITY; req->erp_action = erp_action; req->handler = zfcp_fsf_exchange_config_data_handler; erp_action->fsf_req_id = req->req_id; @@ -1341,7 +1460,8 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, req->qtcb->bottom.config.feature_selection = FSF_FEATURE_NOTIFICATION_LOST | FSF_FEATURE_UPDATE_ALERT | - FSF_FEATURE_REQUEST_SFP_DATA; + FSF_FEATURE_REQUEST_SFP_DATA | + FSF_FEATURE_FC_SECURITY; if (data) req->data = data; @@ -1478,10 +1598,117 @@ out_unlock: return retval; } +static void zfcp_fsf_log_port_fc_security(struct zfcp_port *port, + struct zfcp_fsf_req *req) +{ + char mnemonic_old[ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH]; + char mnemonic_new[ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH]; + + if (port->connection_info == port->connection_info_old) { + /* no change, no log nor trace */ + return; + } + + zfcp_dbf_hba_fsf_fces("fsfcesp", req, port->wwpn, + port->connection_info_old, + port->connection_info); + + zfcp_fsf_scnprint_fc_security(mnemonic_old, sizeof(mnemonic_old), + port->connection_info_old, + ZFCP_FSF_PRINT_FMT_SINGLEITEM); + zfcp_fsf_scnprint_fc_security(mnemonic_new, sizeof(mnemonic_new), + port->connection_info, + ZFCP_FSF_PRINT_FMT_SINGLEITEM); + + if (strncmp(mnemonic_old, mnemonic_new, + ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH) == 0) { + /* no change in string representation, no log */ + goto out; + } + + if (port->connection_info_old == 0) { + /* activation */ + dev_info(&port->adapter->ccw_device->dev, + "FC Endpoint Security of connection to remote port 0x%16llx enabled: %s\n", + port->wwpn, mnemonic_new); + } else if (port->connection_info == 0) { + /* deactivation */ + dev_warn(&port->adapter->ccw_device->dev, + "FC Endpoint Security of connection to remote port 0x%16llx disabled: was %s\n", + port->wwpn, mnemonic_old); + } else { + /* change */ + dev_warn(&port->adapter->ccw_device->dev, + "FC Endpoint Security of connection to remote port 0x%16llx changed: from %s to %s\n", + port->wwpn, mnemonic_old, mnemonic_new); + } + +out: + port->connection_info_old = port->connection_info; +} + +static void zfcp_fsf_log_security_error(const struct device *dev, u32 fsf_sqw0, + u64 wwpn) +{ + switch (fsf_sqw0) { + + /* + * Open Port command error codes + */ + + case FSF_SQ_SECURITY_REQUIRED: + dev_warn_ratelimited(dev, + "FC Endpoint Security error: FC security is required but not supported or configured on remote port 0x%016llx\n", + wwpn); + break; + case FSF_SQ_SECURITY_TIMEOUT: + dev_warn_ratelimited(dev, + "FC Endpoint Security error: a timeout prevented opening remote port 0x%016llx\n", + wwpn); + break; + case FSF_SQ_SECURITY_KM_UNAVAILABLE: + dev_warn_ratelimited(dev, + "FC Endpoint Security error: opening remote port 0x%016llx failed because local and external key manager cannot communicate\n", + wwpn); + break; + case FSF_SQ_SECURITY_RKM_UNAVAILABLE: + dev_warn_ratelimited(dev, + "FC Endpoint Security error: opening remote port 0x%016llx failed because it cannot communicate with the external key manager\n", + wwpn); + break; + case FSF_SQ_SECURITY_AUTH_FAILURE: + dev_warn_ratelimited(dev, + "FC Endpoint Security error: the device could not verify the identity of remote port 0x%016llx\n", + wwpn); + break; + + /* + * Send FCP command error codes + */ + + case FSF_SQ_SECURITY_ENC_FAILURE: + dev_warn_ratelimited(dev, + "FC Endpoint Security error: FC connection to remote port 0x%016llx closed because encryption broke down\n", + wwpn); + break; + + /* + * Unknown error codes + */ + + default: + dev_warn_ratelimited(dev, + "FC Endpoint Security error: the device issued an unknown error code 0x%08x related to the FC connection to remote port 0x%016llx\n", + fsf_sqw0, wwpn); + } +} + static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) { + struct zfcp_adapter *adapter = req->adapter; struct zfcp_port *port = req->data; struct fsf_qtcb_header *header = &req->qtcb->header; + struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support; struct fc_els_flogi *plogi; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) @@ -1491,7 +1718,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) case FSF_PORT_ALREADY_OPEN: break; case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: - dev_warn(&req->adapter->ccw_device->dev, + dev_warn(&adapter->ccw_device->dev, "Not enough FCP adapter resources to open " "remote port 0x%016Lx\n", (unsigned long long)port->wwpn); @@ -1499,6 +1726,12 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) ZFCP_STATUS_COMMON_ERP_FAILED); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; + case FSF_SECURITY_ERROR: + zfcp_fsf_log_security_error(&req->adapter->ccw_device->dev, + header->fsf_status_qual.word[0], + port->wwpn); + req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; case FSF_ADAPTER_STATUS_AVAILABLE: switch (header->fsf_status_qual.word[0]) { case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: @@ -1512,6 +1745,11 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) break; case FSF_GOOD: port->handle = header->port_handle; + if (adapter->adapter_features & FSF_FEATURE_FC_SECURITY) + port->connection_info = bottom->connection_info; + else + port->connection_info = 0; + zfcp_fsf_log_port_fc_security(port, req); atomic_or(ZFCP_STATUS_COMMON_OPEN | ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_BOXED, @@ -1531,10 +1769,9 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) * another GID_PN straight after a port has been opened. * Alternately, an ADISC/PDISC ELS should suffice, as well. */ - plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els; - if (req->qtcb->bottom.support.els1_length >= - FSF_PLOGI_MIN_LEN) - zfcp_fc_plogi_evaluate(port, plogi); + plogi = (struct fc_els_flogi *) bottom->els; + if (bottom->els1_length >= FSF_PLOGI_MIN_LEN) + zfcp_fc_plogi_evaluate(port, plogi); break; case FSF_UNKNOWN_OP_SUBTYPE: req->status |= ZFCP_STATUS_FSFREQ_ERROR; @@ -2225,6 +2462,13 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req, zfcp_fc_test_link(zfcp_sdev->port); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; + case FSF_SECURITY_ERROR: + zfcp_fsf_log_security_error(&req->adapter->ccw_device->dev, + header->fsf_status_qual.word[0], + zfcp_sdev->port->wwpn); + zfcp_erp_port_forced_reopen(zfcp_sdev->port, 0, "fssfch7"); + req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; } } diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 4bfb79f20588..09d73d0061ef 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -4,7 +4,7 @@ * * Interface to the FSF support functions. * - * Copyright IBM Corp. 2002, 2018 + * Copyright IBM Corp. 2002, 2020 */ #ifndef FSF_H @@ -78,6 +78,7 @@ #define FSF_BLOCK_GUARD_CHECK_FAILURE 0x00000081 #define FSF_APP_TAG_CHECK_FAILURE 0x00000082 #define FSF_REF_TAG_CHECK_FAILURE 0x00000083 +#define FSF_SECURITY_ERROR 0x00000090 #define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD #define FSF_FCP_RSP_AVAILABLE 0x000000AF #define FSF_UNKNOWN_COMMAND 0x000000E2 @@ -110,6 +111,14 @@ #define FSF_PSQ_LINK_MODE_TABLE_CURRUPTED 0x00004000 #define FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT 0x00008000 +/* FSF status qualifier, security error */ +#define FSF_SQ_SECURITY_REQUIRED 0x00000001 +#define FSF_SQ_SECURITY_TIMEOUT 0x00000002 +#define FSF_SQ_SECURITY_KM_UNAVAILABLE 0x00000003 +#define FSF_SQ_SECURITY_RKM_UNAVAILABLE 0x00000004 +#define FSF_SQ_SECURITY_AUTH_FAILURE 0x00000005 +#define FSF_SQ_SECURITY_ENC_FAILURE 0x00000010 + /* payload size in status read buffer */ #define FSF_STATUS_READ_PAYLOAD_SIZE 4032 @@ -165,6 +174,7 @@ #define FSF_FEATURE_MEASUREMENT_DATA 0x00000200 #define FSF_FEATURE_REQUEST_SFP_DATA 0x00000200 #define FSF_FEATURE_REPORT_SFP_DATA 0x00000800 +#define FSF_FEATURE_FC_SECURITY 0x00001000 #define FSF_FEATURE_DIF_PROT_TYPE1 0x00010000 #define FSF_FEATURE_DIX_PROT_TCPIP 0x00020000 @@ -174,6 +184,11 @@ /* option */ #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 +/* FC security algorithms */ +#define FSF_FC_SECURITY_AUTH 0x00000001 +#define FSF_FC_SECURITY_ENC_FCSP2 0x00000002 +#define FSF_FC_SECURITY_ENC_ERAS 0x00000004 + struct fsf_queue_designator { u8 cssid; u8 chpid; @@ -338,7 +353,8 @@ struct fsf_qtcb_bottom_support { u8 res3[3]; u8 timeout; u32 lun_access_info; - u8 res4[180]; + u32 connection_info; + u8 res4[176]; u32 els1_length; u32 els2_length; u32 req_buf_length; @@ -426,7 +442,8 @@ struct fsf_qtcb_bottom_port { u16 port_tx_type :4; }; } sfp_flags; - u8 res3[240]; + u32 fc_security_algorithms; + u8 res3[236]; } __attribute__ ((packed)); union fsf_qtcb_bottom { diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 3910d529c15a..13d873f806e4 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -856,6 +856,10 @@ struct fc_function_template zfcp_transport_functions = { .show_host_supported_speeds = 1, .show_host_maxframe_size = 1, .show_host_serial_number = 1, + .show_host_manufacturer = 1, + .show_host_model = 1, + .show_host_hardware_version = 1, + .show_host_firmware_version = 1, .get_fc_host_stats = zfcp_scsi_get_fc_host_stats, .reset_fc_host_stats = zfcp_scsi_reset_fc_host_stats, .set_rport_dev_loss_tmo = zfcp_scsi_set_rport_dev_loss_tmo, @@ -871,5 +875,6 @@ struct fc_function_template zfcp_transport_functions = { .show_host_symbolic_name = 1, .show_host_speed = 1, .show_host_port_id = 1, + .show_host_fabric_name = 1, .dd_bsg_size = sizeof(struct zfcp_fsf_ct_els), }; diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index a711a0d15100..7ec30ded0169 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -4,7 +4,7 @@ * * sysfs attributes. * - * Copyright IBM Corp. 2008, 2010 + * Copyright IBM Corp. 2008, 2020 */ #define KMSG_COMPONENT "zfcp" @@ -370,6 +370,42 @@ static ZFCP_DEV_ATTR(adapter, diag_max_age, 0644, zfcp_sysfs_adapter_diag_max_age_show, zfcp_sysfs_adapter_diag_max_age_store); +static ssize_t zfcp_sysfs_adapter_fc_security_show( + struct device *dev, struct device_attribute *attr, char *buf) +{ + struct ccw_device *cdev = to_ccwdev(dev); + struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); + unsigned int status; + int i; + + if (!adapter) + return -ENODEV; + + /* + * Adapter status COMMON_OPEN implies xconf data and xport data + * was done. Adapter FC Endpoint Security capability remains + * unchanged in case of COMMON_ERP_FAILED (e.g. due to local link + * down). + */ + status = atomic_read(&adapter->status); + if (0 == (status & ZFCP_STATUS_COMMON_OPEN)) + i = sprintf(buf, "unknown\n"); + else if (!(adapter->adapter_features & FSF_FEATURE_FC_SECURITY)) + i = sprintf(buf, "unsupported\n"); + else { + i = zfcp_fsf_scnprint_fc_security( + buf, PAGE_SIZE - 1, adapter->fc_security_algorithms, + ZFCP_FSF_PRINT_FMT_LIST); + i += scnprintf(buf + i, PAGE_SIZE - i, "\n"); + } + + zfcp_ccw_adapter_put(adapter); + return i; +} +static ZFCP_DEV_ATTR(adapter, fc_security, S_IRUGO, + zfcp_sysfs_adapter_fc_security_show, + NULL); + static struct attribute *zfcp_adapter_attrs[] = { &dev_attr_adapter_failed.attr, &dev_attr_adapter_in_recovery.attr, @@ -383,6 +419,7 @@ static struct attribute *zfcp_adapter_attrs[] = { &dev_attr_adapter_status.attr, &dev_attr_adapter_hardware_version.attr, &dev_attr_adapter_diag_max_age.attr, + &dev_attr_adapter_fc_security.attr, NULL }; @@ -426,6 +463,36 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, } static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); +static ssize_t zfcp_sysfs_port_fc_security_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); + struct zfcp_adapter *adapter = port->adapter; + unsigned int status = atomic_read(&port->status); + int i; + + if (0 == (status & ZFCP_STATUS_COMMON_OPEN) || + 0 == (status & ZFCP_STATUS_COMMON_UNBLOCKED) || + 0 == (status & ZFCP_STATUS_PORT_PHYS_OPEN) || + 0 != (status & ZFCP_STATUS_COMMON_ERP_FAILED) || + 0 != (status & ZFCP_STATUS_COMMON_ACCESS_BOXED)) + i = sprintf(buf, "unknown\n"); + else if (!(adapter->adapter_features & FSF_FEATURE_FC_SECURITY)) + i = sprintf(buf, "unsupported\n"); + else { + i = zfcp_fsf_scnprint_fc_security( + buf, PAGE_SIZE - 1, port->connection_info, + ZFCP_FSF_PRINT_FMT_SINGLEITEM); + i += scnprintf(buf + i, PAGE_SIZE - i, "\n"); + } + + return i; +} +static ZFCP_DEV_ATTR(port, fc_security, S_IRUGO, + zfcp_sysfs_port_fc_security_show, + NULL); + static struct attribute *zfcp_port_attrs[] = { &dev_attr_unit_add.attr, &dev_attr_unit_remove.attr, @@ -433,6 +500,7 @@ static struct attribute *zfcp_port_attrs[] = { &dev_attr_port_in_recovery.attr, &dev_attr_port_status.attr, &dev_attr_port_access_denied.attr, + &dev_attr_port_fc_security.attr, NULL }; static struct attribute_group zfcp_port_attr_group = { diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 186259417449..b5b3154e2c28 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -3654,7 +3654,7 @@ static bool __init blogic_parse(char **str, char *keyword) selected host adapter. The BusLogic Driver Probing Options are described in - <file:Documentation/scsi/BusLogic.txt>. + <file:Documentation/scsi/BusLogic.rst>. */ static int __init blogic_parseopts(char *options) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 1b6eaf8da5fa..17feff174f57 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -33,7 +33,7 @@ config SCSI Channel, and FireWire storage. To compile this driver as a module, choose M here and read - <file:Documentation/scsi/scsi.txt>. + <file:Documentation/scsi/scsi.rst>. The module will be called scsi_mod. However, do not compile this as a module if your root file system @@ -79,7 +79,7 @@ config BLK_DEV_SD CD-ROMs. To compile this driver as a module, choose M here and read - <file:Documentation/scsi/scsi.txt>. + <file:Documentation/scsi/scsi.rst>. The module will be called sd_mod. Do not compile this driver as a module if your root file system @@ -94,11 +94,11 @@ config CHR_DEV_ST If you want to use a SCSI tape drive under Linux, say Y and read the SCSI-HOWTO, available from <http://www.tldp.org/docs.html#howto>, and - <file:Documentation/scsi/st.txt> in the kernel source. This is NOT + <file:Documentation/scsi/st.rst> in the kernel source. This is NOT for SCSI CD-ROMs. To compile this driver as a module, choose M here and read - <file:Documentation/scsi/scsi.txt>. The module will be called st. + <file:Documentation/scsi/scsi.rst>. The module will be called st. config BLK_DEV_SR tristate "SCSI CDROM support" @@ -112,18 +112,9 @@ config BLK_DEV_SR Make sure to say Y or M to "ISO 9660 CD-ROM file system support". To compile this driver as a module, choose M here and read - <file:Documentation/scsi/scsi.txt>. + <file:Documentation/scsi/scsi.rst>. The module will be called sr_mod. -config BLK_DEV_SR_VENDOR - bool "Enable vendor-specific extensions (for SCSI CDROM)" - depends on BLK_DEV_SR - help - This enables the usage of vendor specific SCSI commands. This is - required to support multisession CDs with old NEC/TOSHIBA cdrom - drives (and HP Writers). If you have such a drive and get the first - session only, try saying Y here; everybody else says N. - config CHR_DEV_SG tristate "SCSI generic support" depends on SCSI @@ -142,10 +133,10 @@ config CHR_DEV_SG quality digital reader of audio CDs (<http://www.xiph.org/paranoia/>). For other devices, it's possible that you'll have to write the driver software yourself. Please read the file - <file:Documentation/scsi/scsi-generic.txt> for more information. + <file:Documentation/scsi/scsi-generic.rst> for more information. To compile this driver as a module, choose M here and read - <file:Documentation/scsi/scsi.txt>. The module will be called sg. + <file:Documentation/scsi/scsi.rst>. The module will be called sg. If unsure, say N. @@ -158,12 +149,12 @@ config CHR_DEV_SCH don't need this for those tiny 6-slot cdrom changers. Media changers are listed as "Type: Medium Changer" in /proc/scsi/scsi. If you have such hardware and want to use it with linux, say Y - here. Check <file:Documentation/scsi/scsi-changer.txt> for details. + here. Check <file:Documentation/scsi/scsi-changer.rst> for details. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read <file:Documentation/kbuild/modules.rst> and - <file:Documentation/scsi/scsi.txt>. The module will be called ch.o. + <file:Documentation/scsi/scsi.rst>. The module will be called ch.o. If unsure, say N. config SCSI_ENCLOSURE @@ -392,7 +383,7 @@ config SCSI_AHA152X It is explained in section 3.3 of the SCSI-HOWTO, available from <http://www.tldp.org/docs.html#howto>. You might also want to - read the file <file:Documentation/scsi/aha152x.txt>. + read the file <file:Documentation/scsi/aha152x.rst>. To compile this driver as a module, choose M here: the module will be called aha152x. @@ -430,7 +421,7 @@ config SCSI_AACRAID help This driver supports a variety of Dell, HP, Adaptec, IBM and ICP storage products. For a list of supported products, refer - to <file:Documentation/scsi/aacraid.txt>. + to <file:Documentation/scsi/aacraid.rst>. To compile this driver as a module, choose M here: the module will be called aacraid. @@ -457,7 +448,7 @@ config SCSI_DPT_I2O help This driver supports all of Adaptec's I2O based RAID controllers as well as the DPT SmartRaid V cards. This is an Adaptec maintained - driver by Deanna Bonds. See <file:Documentation/scsi/dpti.txt>. + driver by Deanna Bonds. See <file:Documentation/scsi/dpti.rst>. To compile this driver as a module, choose M here: the module will be called dpt_i2o. @@ -511,8 +502,8 @@ config SCSI_BUSLOGIC This is support for BusLogic MultiMaster and FlashPoint SCSI Host Adapters. Consult the SCSI-HOWTO, available from <http://www.tldp.org/docs.html#howto>, and the files - <file:Documentation/scsi/BusLogic.txt> and - <file:Documentation/scsi/FlashPoint.txt> for more information. + <file:Documentation/scsi/BusLogic.rst> and + <file:Documentation/scsi/FlashPoint.rst> for more information. Note that support for FlashPoint is only available for 32-bit x86 configurations. @@ -613,7 +604,7 @@ config FCOE_FNIC This is support for the Cisco PCI-Express FCoE HBA. To compile this driver as a module, choose M here and read - <file:Documentation/scsi/scsi.txt>. + <file:Documentation/scsi/scsi.rst>. The module will be called fnic. config SCSI_SNIC @@ -623,7 +614,7 @@ config SCSI_SNIC This is support for the Cisco PCI-Express SCSI HBA. To compile this driver as a module, choose M here and read - <file:Documentation/scsi/scsi.txt>. + <file:Documentation/scsi/scsi.rst>. The module will be called snic. config SCSI_SNIC_DEBUG_FS @@ -813,7 +804,7 @@ config SCSI_PPA newer drives)", below. For more information about this driver and how to use it you should - read the file <file:Documentation/scsi/ppa.txt>. You should also read + read the file <file:Documentation/scsi/ppa.rst>. You should also read the SCSI-HOWTO, which is available from <http://www.tldp.org/docs.html#howto>. If you use this driver, you will still be able to use the parallel port for other tasks, @@ -840,7 +831,7 @@ config SCSI_IMM here and Y to "IOMEGA Parallel Port (ppa - older drives)", above. For more information about this driver and how to use it you should - read the file <file:Documentation/scsi/ppa.txt>. You should also read + read the file <file:Documentation/scsi/ppa.rst>. You should also read the SCSI-HOWTO, which is available from <http://www.tldp.org/docs.html#howto>. If you use this driver, you will still be able to use the parallel port for other tasks, @@ -930,7 +921,7 @@ config SCSI_SYM53C8XX_2 language. It does not support LSI53C10XX Ultra-320 PCI-X SCSI controllers; you need to use the Fusion MPT driver for that. - Please read <file:Documentation/scsi/sym53c8xx_2.txt> for more + Please read <file:Documentation/scsi/sym53c8xx_2.rst> for more information. config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE @@ -1127,7 +1118,7 @@ config SCSI_QLOGIC_FAS SCSI support"), below. Information about this driver is contained in - <file:Documentation/scsi/qlogicfas.txt>. You should also read the + <file:Documentation/scsi/qlogicfas.rst>. You should also read the SCSI-HOWTO, available from <http://www.tldp.org/docs.html#howto>. @@ -1197,7 +1188,7 @@ config SCSI_DC395x This driver works, but is still in experimental status. So better have a bootable disk and a backup in case of emergency. - Documentation can be found in <file:Documentation/scsi/dc395x.txt>. + Documentation can be found in <file:Documentation/scsi/dc395x.rst>. To compile this driver as a module, choose M here: the module will be called dc395x. diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 33dbc051bff9..eb72ac8136c3 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -798,6 +798,11 @@ static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd) return 0; } +static void aac_probe_container_scsi_done(struct scsi_cmnd *scsi_cmnd) +{ + aac_probe_container_callback1(scsi_cmnd); +} + int aac_probe_container(struct aac_dev *dev, int cid) { struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL); @@ -810,7 +815,7 @@ int aac_probe_container(struct aac_dev *dev, int cid) return -ENOMEM; } scsicmd->list.next = NULL; - scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))aac_probe_container_callback1; + scsicmd->scsi_done = aac_probe_container_scsi_done; scsicmd->device = scsidev; scsidev->sdev_state = 0; @@ -2601,9 +2606,7 @@ static int aac_write(struct scsi_cmnd * scsicmd) static void synchronize_callback(void *context, struct fib *fibptr) { struct aac_synchronize_reply *synchronizereply; - struct scsi_cmnd *cmd; - - cmd = context; + struct scsi_cmnd *cmd = context; if (!aac_valid_context(cmd, fibptr)) return; @@ -2644,77 +2647,8 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) int status; struct fib *cmd_fibcontext; struct aac_synchronize *synchronizecmd; - struct scsi_cmnd *cmd; struct scsi_device *sdev = scsicmd->device; - int active = 0; struct aac_dev *aac; - u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | - (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; - u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; - unsigned long flags; - - /* - * Wait for all outstanding queued commands to complete to this - * specific target (block). - */ - spin_lock_irqsave(&sdev->list_lock, flags); - list_for_each_entry(cmd, &sdev->cmd_list, list) - if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) { - u64 cmnd_lba; - u32 cmnd_count; - - if (cmd->cmnd[0] == WRITE_6) { - cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) | - (cmd->cmnd[2] << 8) | - cmd->cmnd[3]; - cmnd_count = cmd->cmnd[4]; - if (cmnd_count == 0) - cmnd_count = 256; - } else if (cmd->cmnd[0] == WRITE_16) { - cmnd_lba = ((u64)cmd->cmnd[2] << 56) | - ((u64)cmd->cmnd[3] << 48) | - ((u64)cmd->cmnd[4] << 40) | - ((u64)cmd->cmnd[5] << 32) | - ((u64)cmd->cmnd[6] << 24) | - (cmd->cmnd[7] << 16) | - (cmd->cmnd[8] << 8) | - cmd->cmnd[9]; - cmnd_count = (cmd->cmnd[10] << 24) | - (cmd->cmnd[11] << 16) | - (cmd->cmnd[12] << 8) | - cmd->cmnd[13]; - } else if (cmd->cmnd[0] == WRITE_12) { - cmnd_lba = ((u64)cmd->cmnd[2] << 24) | - (cmd->cmnd[3] << 16) | - (cmd->cmnd[4] << 8) | - cmd->cmnd[5]; - cmnd_count = (cmd->cmnd[6] << 24) | - (cmd->cmnd[7] << 16) | - (cmd->cmnd[8] << 8) | - cmd->cmnd[9]; - } else if (cmd->cmnd[0] == WRITE_10) { - cmnd_lba = ((u64)cmd->cmnd[2] << 24) | - (cmd->cmnd[3] << 16) | - (cmd->cmnd[4] << 8) | - cmd->cmnd[5]; - cmnd_count = (cmd->cmnd[7] << 8) | - cmd->cmnd[8]; - } else - continue; - if (((cmnd_lba + cmnd_count) < lba) || - (count && ((lba + count) < cmnd_lba))) - continue; - ++active; - break; - } - - spin_unlock_irqrestore(&sdev->list_lock, flags); - - /* - * Yield the processor (requeue for later) - */ - if (active) - return SCSI_MLQUEUE_DEVICE_BUSY; aac = (struct aac_dev *)sdev->host->hostdata; if (aac->in_reset) @@ -2723,8 +2657,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) /* * Allocate and initialize a Fib */ - if (!(cmd_fibcontext = aac_fib_alloc(aac))) - return SCSI_MLQUEUE_HOST_BUSY; + cmd_fibcontext = aac_fib_alloc_tag(aac, scsicmd); aac_fib_init(cmd_fibcontext); diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index f75878d773cf..355b16f0b145 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -272,36 +272,35 @@ static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, q->entries = qsize; } +static bool wait_for_io_iter(struct scsi_cmnd *cmd, void *data, bool rsvd) +{ + int *active = data; + + if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) + *active = *active + 1; + return true; +} static void aac_wait_for_io_completion(struct aac_dev *aac) { - unsigned long flagv = 0; - int i = 0; + int i = 0, active; for (i = 60; i; --i) { - struct scsi_device *dev; - struct scsi_cmnd *command; - int active = 0; - - __shost_for_each_device(dev, aac->scsi_host_ptr) { - spin_lock_irqsave(&dev->list_lock, flagv); - list_for_each_entry(command, &dev->cmd_list, list) { - if (command->SCp.phase == AAC_OWNER_FIRMWARE) { - active++; - break; - } - } - spin_unlock_irqrestore(&dev->list_lock, flagv); - if (active) - break; - } + active = 0; + scsi_host_busy_iter(aac->scsi_host_ptr, + wait_for_io_iter, &active); /* * We can exit If all the commands are complete */ if (active == 0) break; + dev_info(&aac->pdev->dev, + "Wait for %d commands to complete\n", active); ssleep(1); } + if (active) + dev_err(&aac->pdev->dev, + "%d outstanding commands during shutdown\n", active); } /** diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 5a8a999606ea..4725e4c763cf 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -729,7 +729,7 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback, hbacmd->request_id = cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1); fibptr->flags |= FIB_CONTEXT_FLAG_SCSI_CMD; - } else if (command != HBA_IU_TYPE_SCSI_TM_REQ) + } else return -EINVAL; @@ -1476,10 +1476,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) { int index, quirks; int retval; - struct Scsi_Host *host; - struct scsi_device *dev; - struct scsi_cmnd *command; - struct scsi_cmnd *command_list; + struct Scsi_Host *host = aac->scsi_host_ptr; int jafo = 0; int bled; u64 dmamask; @@ -1495,8 +1492,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) * - The card is dead, or will be very shortly ;-/ so no new * commands are completing in the interrupt service. */ - host = aac->scsi_host_ptr; - scsi_block_requests(host); aac_adapter_disable_int(aac); if (aac->thread && aac->thread->pid != current->pid) { spin_unlock_irq(host->host_lock); @@ -1607,39 +1602,11 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) * This is where the assumption that the Adapter is quiesced * is important. */ - command_list = NULL; - __shost_for_each_device(dev, host) { - unsigned long flags; - spin_lock_irqsave(&dev->list_lock, flags); - list_for_each_entry(command, &dev->cmd_list, list) - if (command->SCp.phase == AAC_OWNER_FIRMWARE) { - command->SCp.buffer = (struct scatterlist *)command_list; - command_list = command; - } - spin_unlock_irqrestore(&dev->list_lock, flags); - } - while ((command = command_list)) { - command_list = (struct scsi_cmnd *)command->SCp.buffer; - command->SCp.buffer = NULL; - command->result = DID_OK << 16 - | COMMAND_COMPLETE << 8 - | SAM_STAT_TASK_SET_FULL; - command->SCp.phase = AAC_OWNER_ERROR_HANDLER; - command->scsi_done(command); - } - /* - * Any Device that was already marked offline needs to be marked - * running - */ - __shost_for_each_device(dev, host) { - if (!scsi_device_online(dev)) - scsi_device_set_state(dev, SDEV_RUNNING); - } - retval = 0; + scsi_host_complete_all_commands(host, DID_RESET); + retval = 0; out: aac->in_reset = 0; - scsi_unblock_requests(host); /* * Issue bus rescan to catch any configuration that might have @@ -1660,7 +1627,7 @@ int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) { unsigned long flagv = 0; int retval; - struct Scsi_Host * host; + struct Scsi_Host *host = aac->scsi_host_ptr; int bled; if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0) @@ -1678,8 +1645,7 @@ int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) * target (block maximum 60 seconds). Although not necessary, * it does make us a good storage citizen. */ - host = aac->scsi_host_ptr; - scsi_block_requests(host); + scsi_host_block(host); /* Quiesce build, flush cache, write through mode */ if (forced < 2) @@ -1690,6 +1656,8 @@ int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type) retval = _aac_reset_adapter(aac, bled, reset_type); spin_unlock_irqrestore(host->host_lock, flagv); + retval = scsi_host_unblock(host, SDEV_RUNNING); + if ((forced < 2) && (retval == -ENODEV)) { /* Unwind aac_send_shutdown() IOP_RESET unsupported/disabled */ struct fib * fibctx = aac_fib_alloc(aac); diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 0443b74390cf..83a60b0a8cd8 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -623,54 +623,56 @@ static int aac_ioctl(struct scsi_device *sdev, unsigned int cmd, return aac_do_ioctl(dev, cmd, arg); } -static int get_num_of_incomplete_fibs(struct aac_dev *aac) +struct fib_count_data { + int mlcnt; + int llcnt; + int ehcnt; + int fwcnt; + int krlcnt; +}; + +static bool fib_count_iter(struct scsi_cmnd *scmnd, void *data, bool reserved) { + struct fib_count_data *fib_count = data; - unsigned long flags; - struct scsi_device *sdev = NULL; + switch (scmnd->SCp.phase) { + case AAC_OWNER_FIRMWARE: + fib_count->fwcnt++; + break; + case AAC_OWNER_ERROR_HANDLER: + fib_count->ehcnt++; + break; + case AAC_OWNER_LOWLEVEL: + fib_count->llcnt++; + break; + case AAC_OWNER_MIDLEVEL: + fib_count->mlcnt++; + break; + default: + fib_count->krlcnt++; + break; + } + return true; +} + +/* Called during SCSI EH, so we don't need to block requests */ +static int get_num_of_incomplete_fibs(struct aac_dev *aac) +{ struct Scsi_Host *shost = aac->scsi_host_ptr; - struct scsi_cmnd *scmnd = NULL; struct device *ctrl_dev; + struct fib_count_data fcnt = { }; - int mlcnt = 0; - int llcnt = 0; - int ehcnt = 0; - int fwcnt = 0; - int krlcnt = 0; - - __shost_for_each_device(sdev, shost) { - spin_lock_irqsave(&sdev->list_lock, flags); - list_for_each_entry(scmnd, &sdev->cmd_list, list) { - switch (scmnd->SCp.phase) { - case AAC_OWNER_FIRMWARE: - fwcnt++; - break; - case AAC_OWNER_ERROR_HANDLER: - ehcnt++; - break; - case AAC_OWNER_LOWLEVEL: - llcnt++; - break; - case AAC_OWNER_MIDLEVEL: - mlcnt++; - break; - default: - krlcnt++; - break; - } - } - spin_unlock_irqrestore(&sdev->list_lock, flags); - } + scsi_host_busy_iter(shost, fib_count_iter, &fcnt); ctrl_dev = &aac->pdev->dev; - dev_info(ctrl_dev, "outstanding cmd: midlevel-%d\n", mlcnt); - dev_info(ctrl_dev, "outstanding cmd: lowlevel-%d\n", llcnt); - dev_info(ctrl_dev, "outstanding cmd: error handler-%d\n", ehcnt); - dev_info(ctrl_dev, "outstanding cmd: firmware-%d\n", fwcnt); - dev_info(ctrl_dev, "outstanding cmd: kernel-%d\n", krlcnt); + dev_info(ctrl_dev, "outstanding cmd: midlevel-%d\n", fcnt.mlcnt); + dev_info(ctrl_dev, "outstanding cmd: lowlevel-%d\n", fcnt.llcnt); + dev_info(ctrl_dev, "outstanding cmd: error handler-%d\n", fcnt.ehcnt); + dev_info(ctrl_dev, "outstanding cmd: firmware-%d\n", fcnt.fwcnt); + dev_info(ctrl_dev, "outstanding cmd: kernel-%d\n", fcnt.krlcnt); - return mlcnt + llcnt + ehcnt + fwcnt; + return fcnt.mlcnt + fcnt.llcnt + fcnt.ehcnt + fcnt.fwcnt; } static int aac_eh_abort(struct scsi_cmnd* cmd) @@ -732,7 +734,11 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) status = aac_hba_send(HBA_IU_TYPE_SCSI_TM_REQ, fib, (fib_callback) aac_hba_callback, (void *) cmd); - + if (status != -EINPROGRESS) { + aac_fib_complete(fib); + aac_fib_free(fib); + return ret; + } /* Wait up to 15 secs for completion */ for (count = 0; count < 15; ++count) { if (cmd->SCp.sent_command) { @@ -911,11 +917,11 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) info = &aac->hba_map[bus][cid]; - if (info->devtype != AAC_DEVTYPE_NATIVE_RAW && - info->reset_state > 0) + if (!(info->devtype == AAC_DEVTYPE_NATIVE_RAW && + !(info->reset_state > 0))) return FAILED; - pr_err("%s: Host adapter reset request. SCSI hang ?\n", + pr_err("%s: Host device reset request. SCSI hang ?\n", AAC_DRIVERNAME); fib = aac_fib_alloc(aac); @@ -930,7 +936,12 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) status = aac_hba_send(command, fib, (fib_callback) aac_tmf_callback, (void *) info); - + if (status != -EINPROGRESS) { + info->reset_state = 0; + aac_fib_complete(fib); + aac_fib_free(fib); + return ret; + } /* Wait up to 15 seconds for completion */ for (count = 0; count < 15; ++count) { if (info->reset_state == 0) { @@ -969,11 +980,11 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) info = &aac->hba_map[bus][cid]; - if (info->devtype != AAC_DEVTYPE_NATIVE_RAW && - info->reset_state > 0) + if (!(info->devtype == AAC_DEVTYPE_NATIVE_RAW && + !(info->reset_state > 0))) return FAILED; - pr_err("%s: Host adapter reset request. SCSI hang ?\n", + pr_err("%s: Host target reset request. SCSI hang ?\n", AAC_DRIVERNAME); fib = aac_fib_alloc(aac); @@ -990,6 +1001,13 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) (fib_callback) aac_tmf_callback, (void *) info); + if (status != -EINPROGRESS) { + info->reset_state = 0; + aac_fib_complete(fib); + aac_fib_free(fib); + return ret; + } + /* Wait up to 15 seconds for completion */ for (count = 0; count < 15; ++count) { if (info->reset_state <= 0) { @@ -1042,7 +1060,7 @@ static int aac_eh_bus_reset(struct scsi_cmnd* cmd) } } - pr_err("%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVERNAME); + pr_err("%s: Host bus reset request. SCSI hang ?\n", AAC_DRIVERNAME); /* * Check the health of the controller @@ -1270,20 +1288,21 @@ static ssize_t aac_show_flags(struct device *cdev, if (nblank(dprintk(x))) len = snprintf(buf, PAGE_SIZE, "dprintk\n"); #ifdef AAC_DETAILED_STATUS_INFO - len += snprintf(buf + len, PAGE_SIZE - len, - "AAC_DETAILED_STATUS_INFO\n"); + len += scnprintf(buf + len, PAGE_SIZE - len, + "AAC_DETAILED_STATUS_INFO\n"); #endif if (dev->raw_io_interface && dev->raw_io_64) - len += snprintf(buf + len, PAGE_SIZE - len, - "SAI_READ_CAPACITY_16\n"); + len += scnprintf(buf + len, PAGE_SIZE - len, + "SAI_READ_CAPACITY_16\n"); if (dev->jbod) - len += snprintf(buf + len, PAGE_SIZE - len, "SUPPORTED_JBOD\n"); + len += scnprintf(buf + len, PAGE_SIZE - len, + "SUPPORTED_JBOD\n"); if (dev->supplement_adapter_info.supported_options2 & AAC_OPTION_POWER_MANAGEMENT) - len += snprintf(buf + len, PAGE_SIZE - len, - "SUPPORTED_POWER_MANAGEMENT\n"); + len += scnprintf(buf + len, PAGE_SIZE - len, + "SUPPORTED_POWER_MANAGEMENT\n"); if (dev->msi) - len += snprintf(buf + len, PAGE_SIZE - len, "PCI_HAS_MSI\n"); + len += scnprintf(buf + len, PAGE_SIZE - len, "PCI_HAS_MSI\n"); return len; } @@ -1676,7 +1695,6 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) shost->irq = pdev->irq; shost->unique_id = unique_id; shost->max_cmd_len = 16; - shost->use_cmd_list = 1; if (aac_cfg_major == AAC_CHARDEV_NEEDS_REINIT) aac_init_char(); @@ -1895,7 +1913,7 @@ static int aac_suspend(struct pci_dev *pdev, pm_message_t state) struct Scsi_Host *shost = pci_get_drvdata(pdev); struct aac_dev *aac = (struct aac_dev *)shost->hostdata; - scsi_block_requests(shost); + scsi_host_block(shost); aac_cancel_rescan_worker(aac); aac_send_shutdown(aac); @@ -1931,7 +1949,7 @@ static int aac_resume(struct pci_dev *pdev) * aac_send_shutdown() to block ioctls from upperlayer */ aac->adapter_shutdown = 0; - scsi_unblock_requests(shost); + scsi_host_unblock(shost, SDEV_RUNNING); return 0; @@ -1946,7 +1964,8 @@ fail_device: static void aac_shutdown(struct pci_dev *dev) { struct Scsi_Host *shost = pci_get_drvdata(dev); - scsi_block_requests(shost); + + scsi_host_block(shost); __aac_shutdown((struct aac_dev *)shost->hostdata); } @@ -1978,26 +1997,6 @@ static void aac_remove_one(struct pci_dev *pdev) } } -static void aac_flush_ios(struct aac_dev *aac) -{ - int i; - struct scsi_cmnd *cmd; - - for (i = 0; i < aac->scsi_host_ptr->can_queue; i++) { - cmd = (struct scsi_cmnd *)aac->fibs[i].callback_data; - if (cmd && (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) { - scsi_dma_unmap(cmd); - - if (aac->handle_pci_error) - cmd->result = DID_NO_CONNECT << 16; - else - cmd->result = DID_RESET << 16; - - cmd->scsi_done(cmd); - } - } -} - static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev, enum pci_channel_state error) { @@ -2012,9 +2011,9 @@ static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev, case pci_channel_io_frozen: aac->handle_pci_error = 1; - scsi_block_requests(aac->scsi_host_ptr); + scsi_host_block(shost); aac_cancel_rescan_worker(aac); - aac_flush_ios(aac); + scsi_host_complete_all_commands(shost, DID_NO_CONNECT); aac_release_resources(aac); pci_disable_pcie_error_reporting(pdev); @@ -2024,7 +2023,7 @@ static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev, case pci_channel_io_perm_failure: aac->handle_pci_error = 1; - aac_flush_ios(aac); + scsi_host_complete_all_commands(shost, DID_NO_CONNECT); return PCI_ERS_RESULT_DISCONNECT; } @@ -2065,7 +2064,6 @@ fail_device: static void aac_pci_resume(struct pci_dev *pdev) { struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct scsi_device *sdev = NULL; struct aac_dev *aac = (struct aac_dev *)shost_priv(shost); if (aac_adapter_ioremap(aac, aac->base_size)) { @@ -2092,10 +2090,7 @@ static void aac_pci_resume(struct pci_dev *pdev) aac->adapter_shutdown = 0; aac->handle_pci_error = 0; - shost_for_each_device(sdev, shost) - if (sdev->sdev_state == SDEV_OFFLINE) - sdev->sdev_state = SDEV_RUNNING; - scsi_unblock_requests(aac->scsi_host_ptr); + scsi_host_unblock(shost, SDEV_RUNNING); aac_scan_host(aac); pci_save_state(pdev); diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index a242a62caaa1..c2c7850ff7b4 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -316,7 +316,7 @@ typedef struct asc_sg_head { ushort queue_cnt; ushort entry_to_copy; ushort res; - ASC_SG_LIST sg_list[0]; + ASC_SG_LIST sg_list[]; } ASC_SG_HEAD; typedef struct asc_scsi_q { diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index eb466c2e1839..90f97df1c42a 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -220,7 +220,7 @@ * ************************************************************************** - see Documentation/scsi/aha152x.txt for configuration details + see Documentation/scsi/aha152x.rst for configuration details **************************************************************************/ @@ -1249,7 +1249,7 @@ static int aha152x_biosparam(struct scsi_device *sdev, struct block_device *bdev "aha152x: unable to verify geometry for disk with >1GB.\n" " Using default translation. Please verify yourself.\n" " Perhaps you need to enable extended translation in the driver.\n" - " See Documentation/scsi/aha152x.txt for details.\n"); + " See Documentation/scsi/aha152x.rst for details.\n"); } } else { info_array[0] = info[0]; diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index da4150c17781..5a227c03895f 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c @@ -592,7 +592,6 @@ 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_host_put (shpnt); goto err_host_put; } diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx index 16743fb9eead..d4c50b8fce29 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic79xx +++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx @@ -32,7 +32,7 @@ config AIC79XX_CMDS_PER_DEVICE on some devices. The upper bound is 253. 0 disables tagged queueing. Per device tag depth can be controlled via the kernel command line - "tag_info" option. See Documentation/scsi/aic79xx.txt for details. + "tag_info" option. See Documentation/scsi/aic79xx.rst for details. config AIC79XX_RESET_DELAY_MS int "Initial bus reset delay in milli-seconds" diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index 3546b8cc401f..9d027549d698 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx @@ -37,7 +37,7 @@ config AIC7XXX_CMDS_PER_DEVICE on some devices. The upper bound is 253. 0 disables tagged queueing. Per device tag depth can be controlled via the kernel command line - "tag_info" option. See Documentation/scsi/aic7xxx.txt for details. + "tag_info" option. See Documentation/scsi/aic7xxx.rst for details. config AIC7XXX_RESET_DELAY_MS int "Initial bus reset delay in milli-seconds" diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 7e5044bf05c0..a336a458c978 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -3107,19 +3107,6 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) printerror = 0; } else if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_BUS_DEV_RESET, TRUE)) { -#ifdef __FreeBSD__ - /* - * Don't mark the user's request for this BDR - * as completing with CAM_BDR_SENT. CAM3 - * specifies CAM_REQ_CMP. - */ - if (scb != NULL - && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV - && ahd_match_scb(ahd, scb, target, 'A', - CAM_LUN_WILDCARD, SCB_LIST_NULL, - ROLE_INITIATOR)) - ahd_set_transaction_status(scb, CAM_REQ_CMP); -#endif ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD, CAM_BDR_SENT, "Bus Device Reset", /*verbose_level*/0); @@ -6067,22 +6054,17 @@ ahd_alloc(void *platform_arg, char *name) { struct ahd_softc *ahd; -#ifndef __FreeBSD__ ahd = kmalloc(sizeof(*ahd), GFP_ATOMIC); if (!ahd) { printk("aic7xxx: cannot malloc softc!\n"); kfree(name); return NULL; } -#else - ahd = device_get_softc((device_t)platform_arg); -#endif + memset(ahd, 0, sizeof(*ahd)); ahd->seep_config = kmalloc(sizeof(*ahd->seep_config), GFP_ATOMIC); if (ahd->seep_config == NULL) { -#ifndef __FreeBSD__ kfree(ahd); -#endif kfree(name); return (NULL); } @@ -6206,9 +6188,7 @@ ahd_free(struct ahd_softc *ahd) kfree(ahd->seep_config); if (ahd->saved_stack != NULL) kfree(ahd->saved_stack); -#ifndef __FreeBSD__ kfree(ahd); -#endif return; } diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 259d9c20bf25..57be9609d504 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -41,7 +41,7 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr -** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt +** Firmware Specification, see Documentation/scsi/arcmsr_spec.rst ******************************************************************************* */ #include <linux/module.h> diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index c2c79a37a9ef..30914c8f29cc 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -41,7 +41,7 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* ** For history of changes, see Documentation/scsi/ChangeLog.arcmsr -** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt +** Firmware Specification, see Documentation/scsi/arcmsr_spec.rst ******************************************************************************* */ #include <linux/module.h> diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index d4febaadfaa3..a2d69b287c7b 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -1178,12 +1178,12 @@ beiscsi_active_session_disp(struct device *dev, struct device_attribute *attr, if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { avlbl_cids = BEISCSI_ULP_AVLBL_CID(phba, ulp_num); total_cids = BEISCSI_GET_CID_COUNT(phba, ulp_num); - len += snprintf(buf+len, PAGE_SIZE - len, - "ULP%d : %d\n", ulp_num, - (total_cids - avlbl_cids)); + len += scnprintf(buf+len, PAGE_SIZE - len, + "ULP%d : %d\n", ulp_num, + (total_cids - avlbl_cids)); } else - len += snprintf(buf+len, PAGE_SIZE - len, - "ULP%d : %d\n", ulp_num, 0); + len += scnprintf(buf+len, PAGE_SIZE - len, + "ULP%d : %d\n", ulp_num, 0); } return len; @@ -1208,12 +1208,12 @@ beiscsi_free_session_disp(struct device *dev, struct device_attribute *attr, for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) - len += snprintf(buf+len, PAGE_SIZE - len, - "ULP%d : %d\n", ulp_num, - BEISCSI_ULP_AVLBL_CID(phba, ulp_num)); + len += scnprintf(buf+len, PAGE_SIZE - len, + "ULP%d : %d\n", ulp_num, + BEISCSI_ULP_AVLBL_CID(phba, ulp_num)); else - len += snprintf(buf+len, PAGE_SIZE - len, - "ULP%d : %d\n", ulp_num, 0); + len += scnprintf(buf+len, PAGE_SIZE - len, + "ULP%d : %d\n", ulp_num, 0); } return len; diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index ed5f4a6ae270..cb74ab1ae5a4 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -44,7 +44,6 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR); MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER); -static DEFINE_MUTEX(ch_mutex); static int init = 1; module_param(init, int, 0444); MODULE_PARM_DESC(init, \ @@ -569,6 +568,7 @@ static void ch_destroy(struct kref *ref) { scsi_changer *ch = container_of(ref, scsi_changer, ref); + ch->device = NULL; kfree(ch->dt); kfree(ch); } @@ -590,20 +590,22 @@ ch_open(struct inode *inode, struct file *file) scsi_changer *ch; int minor = iminor(inode); - mutex_lock(&ch_mutex); spin_lock(&ch_index_lock); ch = idr_find(&ch_index_idr, minor); - if (NULL == ch || scsi_device_get(ch->device)) { + if (ch == NULL || !kref_get_unless_zero(&ch->ref)) { spin_unlock(&ch_index_lock); - mutex_unlock(&ch_mutex); return -ENXIO; } - kref_get(&ch->ref); spin_unlock(&ch_index_lock); - + if (scsi_device_get(ch->device)) { + kref_put(&ch->ref, ch_destroy); + return -ENXIO; + } + /* Synchronize with ch_probe() */ + mutex_lock(&ch->lock); file->private_data = ch; - mutex_unlock(&ch_mutex); + mutex_unlock(&ch->lock); return 0; } @@ -938,7 +940,16 @@ static int ch_probe(struct device *dev) ch->minor = ret; sprintf(ch->name,"ch%d",ch->minor); + ret = scsi_device_get(sd); + if (ret) { + sdev_printk(KERN_WARNING, sd, "ch%d: failed to get device\n", + ch->minor); + goto remove_idr; + } + mutex_init(&ch->lock); + kref_init(&ch->ref); + ch->device = sd; class_dev = device_create(ch_sysfs_class, dev, MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch, "s%s", ch->name); @@ -946,24 +957,27 @@ static int ch_probe(struct device *dev) sdev_printk(KERN_WARNING, sd, "ch%d: device_create failed\n", ch->minor); ret = PTR_ERR(class_dev); - goto remove_idr; + goto put_device; } - mutex_init(&ch->lock); - kref_init(&ch->ref); - ch->device = sd; + mutex_lock(&ch->lock); ret = ch_readconfig(ch); - if (ret) + if (ret) { + mutex_unlock(&ch->lock); goto destroy_dev; + } if (init) ch_init_elem(ch); + mutex_unlock(&ch->lock); dev_set_drvdata(dev, ch); sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name); return 0; destroy_dev: device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR, ch->minor)); +put_device: + scsi_device_put(sd); remove_idr: idr_remove(&ch_index_idr, ch->minor); free_ch: @@ -977,9 +991,11 @@ static int ch_remove(struct device *dev) spin_lock(&ch_index_lock); idr_remove(&ch_index_idr, ch->minor); + dev_set_drvdata(dev, NULL); spin_unlock(&ch_index_lock); device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR,ch->minor)); + scsi_device_put(ch->device); kref_put(&ch->ref, ch_destroy); return 0; } diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 13fbb2eab842..e95f5b3bef4d 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -61,7 +61,6 @@ #include <asm/io.h> #include <scsi/scsi.h> -#include <scsi/scsicam.h> /* needed for scsicam_bios_param */ #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> @@ -1053,38 +1052,6 @@ complete: static DEF_SCSI_QCMD(dc395x_queue_command) -/* - * Return the disk geometry for the given SCSI device. - */ -static int dc395x_bios_param(struct scsi_device *sdev, - struct block_device *bdev, sector_t capacity, int *info) -{ -#ifdef CONFIG_SCSI_DC395x_TRMS1040_TRADMAP - int heads, sectors, cylinders; - struct AdapterCtlBlk *acb; - int size = capacity; - - dprintkdbg(DBG_0, "dc395x_bios_param..............\n"); - acb = (struct AdapterCtlBlk *)sdev->host->hostdata; - heads = 64; - sectors = 32; - cylinders = size / (heads * sectors); - - if ((acb->gmode2 & NAC_GREATER_1G) && (cylinders > 1024)) { - heads = 255; - sectors = 63; - cylinders = size / (heads * sectors); - } - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - return 0; -#else - return scsicam_bios_param(bdev, capacity, info); -#endif -} - - static void dump_register_info(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { @@ -4622,7 +4589,6 @@ static struct scsi_host_template dc395x_driver_template = { .show_info = dc395x_show_info, .name = DC395X_BANNER " " DC395X_VERSION, .queuecommand = dc395x_queue_command, - .bios_param = dc395x_bios_param, .slave_alloc = dc395x_slave_alloc, .slave_destroy = dc395x_slave_destroy, .can_queue = DC395x_MAX_CAN_QUEUE, diff --git a/drivers/scsi/dpt/dpti_ioctl.h b/drivers/scsi/dpt/dpti_ioctl.h index 6bc33f4f020d..25e9251f8c78 100644 --- a/drivers/scsi/dpt/dpti_ioctl.h +++ b/drivers/scsi/dpt/dpti_ioctl.h @@ -5,7 +5,7 @@ begin : Thu Sep 7 2000 copyright : (C) 2001 by Adaptec - See Documentation/scsi/dpti.txt for history, notes, license info + See Documentation/scsi/dpti.rst for history, notes, license info and credits ***************************************************************************/ diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index abc74fd474dc..02dff3a684e0 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -8,7 +8,7 @@ July 30, 2001 First version being submitted for inclusion in the kernel. V2.4 - See Documentation/scsi/dpti.txt for history, notes, license info + See Documentation/scsi/dpti.rst for history, notes, license info and credits ***************************************************************************/ @@ -817,7 +817,7 @@ static int adpt_hba_reset(adpt_hba* pHba) } pHba->state &= ~DPTI_STATE_RESET; - adpt_fail_posted_scbs(pHba); + scsi_host_complete_all_commands(pHba->host, DID_RESET); return 0; /* return success */ } @@ -2173,7 +2173,7 @@ static irqreturn_t adpt_isr(int irq, void *dev_id) readl(reply + 12) - 1); if(cmd != NULL){ scsi_dma_unmap(cmd); - adpt_i2o_to_scsi(reply, cmd); + adpt_i2o_scsi_complete(reply, cmd); } } writel(m, pHba->reply_port); @@ -2335,13 +2335,12 @@ static s32 adpt_scsi_host_alloc(adpt_hba* pHba, struct scsi_host_template *sht) host->unique_id = (u32)sys_tbl_pa + pHba->unit; host->sg_tablesize = pHba->sg_tablesize; host->can_queue = pHba->post_fifo_size; - host->use_cmd_list = 1; return 0; } -static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) +static void adpt_i2o_scsi_complete(void __iomem *reply, struct scsi_cmnd *cmd) { adpt_hba* pHba; u32 hba_status; @@ -2459,7 +2458,6 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) if(cmd->scsi_done != NULL){ cmd->scsi_done(cmd); } - return cmd->result; } @@ -2647,23 +2645,6 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) return 0; } -static void adpt_fail_posted_scbs(adpt_hba* pHba) -{ - struct scsi_cmnd* cmd = NULL; - struct scsi_device* d = NULL; - - shost_for_each_device(d, pHba->host) { - unsigned long flags; - spin_lock_irqsave(&d->list_lock, flags); - list_for_each_entry(cmd, &d->cmd_list, list) { - cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1); - cmd->scsi_done(cmd); - } - spin_unlock_irqrestore(&d->list_lock, flags); - } -} - - /*============================================================================ * Routines from i2o subsystem *============================================================================ diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index 42b1e28b5884..8a079e8d7f65 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -5,7 +5,7 @@ begin : Thu Sep 7 2000 copyright : (C) 2001 by Adaptec - See Documentation/scsi/dpti.txt for history, notes, license info + See Documentation/scsi/dpti.rst for history, notes, license info and credits ***************************************************************************/ @@ -286,7 +286,7 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba); static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba); static s32 adpt_i2o_hrt_get(adpt_hba* pHba); static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice); -static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd); +static void adpt_i2o_scsi_complete(void __iomem *reply, struct scsi_cmnd *cmd); static s32 adpt_scsi_host_alloc(adpt_hba* pHba,struct scsi_host_template * sht); static s32 adpt_hba_reset(adpt_hba* pHba); static s32 adpt_i2o_reset_hba(adpt_hba* pHba); @@ -295,7 +295,6 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba); static s32 adpt_send_nop(adpt_hba*pHba,u32 m); static void adpt_i2o_delete_hba(adpt_hba* pHba); static void adpt_inquiry(adpt_hba* pHba); -static void adpt_fail_posted_scbs(adpt_hba* pHba); static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun); static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ; static int adpt_i2o_online_hba(adpt_hba* pHba); diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c index a0d01aea28f7..9d52d83161ed 100644 --- a/drivers/scsi/fnic/fnic_trace.c +++ b/drivers/scsi/fnic/fnic_trace.c @@ -138,7 +138,7 @@ int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt) * Dump trace buffer entry to memory file * and increment read index @rd_idx */ - len += snprintf(fnic_dbgfs_prt->buffer + len, + len += scnprintf(fnic_dbgfs_prt->buffer + len, (trace_max_pages * PAGE_SIZE * 3) - len, "%16llu.%09lu %-50s %8x %8x %16llx %16llx " "%16llx %16llx %16llx\n", (u64)val.tv_sec, @@ -180,7 +180,7 @@ int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt) * Dump trace buffer entry to memory file * and increment read index @rd_idx */ - len += snprintf(fnic_dbgfs_prt->buffer + len, + len += scnprintf(fnic_dbgfs_prt->buffer + len, (trace_max_pages * PAGE_SIZE * 3) - len, "%16llu.%09lu %-50s %8x %8x %16llx %16llx " "%16llx %16llx %16llx\n", (u64)val.tv_sec, @@ -220,12 +220,12 @@ int fnic_get_stats_data(struct stats_debug_info *debug, struct timespec64 val1, val2; ktime_get_real_ts64(&val1); - len = snprintf(debug->debug_buffer + len, buf_size - len, + len = scnprintf(debug->debug_buffer + len, buf_size - len, "------------------------------------------\n" "\t\tTime\n" "------------------------------------------\n"); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "Current time : [%lld:%ld]\n" "Last stats reset time: [%lld:%09ld]\n" "Last stats read time: [%lld:%ld]\n" @@ -243,11 +243,11 @@ int fnic_get_stats_data(struct stats_debug_info *debug, stats->stats_timestamps.last_read_time = val1; - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "------------------------------------------\n" "\t\tIO Statistics\n" "------------------------------------------\n"); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "Number of Active IOs: %lld\nMaximum Active IOs: %lld\n" "Number of IOs: %lld\nNumber of IO Completions: %lld\n" "Number of IO Failures: %lld\nNumber of IO NOT Found: %lld\n" @@ -280,16 +280,16 @@ int fnic_get_stats_data(struct stats_debug_info *debug, (u64)atomic64_read(&stats->io_stats.io_btw_10000_to_30000_msec), (u64)atomic64_read(&stats->io_stats.io_greater_than_30000_msec)); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "\nCurrent Max IO time : %lld\n", (u64)atomic64_read(&stats->io_stats.current_max_io_time)); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "\n------------------------------------------\n" "\t\tAbort Statistics\n" "------------------------------------------\n"); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "Number of Aborts: %lld\n" "Number of Abort Failures: %lld\n" "Number of Abort Driver Timeouts: %lld\n" @@ -318,12 +318,12 @@ int fnic_get_stats_data(struct stats_debug_info *debug, (u64)atomic64_read(&stats->abts_stats.abort_issued_btw_50_to_60_sec), (u64)atomic64_read(&stats->abts_stats.abort_issued_greater_than_60_sec)); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "\n------------------------------------------\n" "\t\tTerminate Statistics\n" "------------------------------------------\n"); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "Number of Terminates: %lld\n" "Maximum Terminates: %lld\n" "Number of Terminate Driver Timeouts: %lld\n" @@ -337,12 +337,12 @@ int fnic_get_stats_data(struct stats_debug_info *debug, (u64)atomic64_read(&stats->term_stats.terminate_io_not_found), (u64)atomic64_read(&stats->term_stats.terminate_failures)); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "\n------------------------------------------\n" "\t\tReset Statistics\n" "------------------------------------------\n"); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "Number of Device Resets: %lld\n" "Number of Device Reset Failures: %lld\n" "Number of Device Reset Aborts: %lld\n" @@ -368,12 +368,12 @@ int fnic_get_stats_data(struct stats_debug_info *debug, &stats->reset_stats.fnic_reset_completions), (u64)atomic64_read(&stats->reset_stats.fnic_reset_failures)); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "\n------------------------------------------\n" "\t\tFirmware Statistics\n" "------------------------------------------\n"); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "Number of Active FW Requests %lld\n" "Maximum FW Requests: %lld\n" "Number of FW out of resources: %lld\n" @@ -383,12 +383,12 @@ int fnic_get_stats_data(struct stats_debug_info *debug, (u64)atomic64_read(&stats->fw_stats.fw_out_of_resources), (u64)atomic64_read(&stats->fw_stats.io_fw_errs)); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "\n------------------------------------------\n" "\t\tVlan Discovery Statistics\n" "------------------------------------------\n"); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "Number of Vlan Discovery Requests Sent %lld\n" "Vlan Response Received with no FCF VLAN ID: %lld\n" "No solicitations recvd after vlan set, expiry count: %lld\n" @@ -398,7 +398,7 @@ int fnic_get_stats_data(struct stats_debug_info *debug, (u64)atomic64_read(&stats->vlan_stats.sol_expiry_count), (u64)atomic64_read(&stats->vlan_stats.flogi_rejects)); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "\n------------------------------------------\n" "\t\tOther Important Statistics\n" "------------------------------------------\n"); @@ -406,7 +406,7 @@ int fnic_get_stats_data(struct stats_debug_info *debug, jiffies_to_timespec64(stats->misc_stats.last_isr_time, &val1); jiffies_to_timespec64(stats->misc_stats.last_ack_time, &val2); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "Last ISR time: %llu (%8llu.%09lu)\n" "Last ACK time: %llu (%8llu.%09lu)\n" "Max ISR jiffies: %llu\n" @@ -452,7 +452,7 @@ int fnic_get_stats_data(struct stats_debug_info *debug, (u64)atomic64_read(&stats->misc_stats.rport_not_ready), (u64)atomic64_read(&stats->misc_stats.frame_errors)); - len += snprintf(debug->debug_buffer + len, buf_size - len, + len += scnprintf(debug->debug_buffer + len, buf_size - len, "Firmware reported port speed: %llu\n", (u64)atomic64_read( &stats->misc_stats.current_port_speed)); @@ -742,7 +742,7 @@ int fnic_fc_trace_get_data(fnic_dbgfs_t *fnic_dbgfs_prt, u8 rdata_flag) rd_idx = fc_trace_entries.rd_idx; wr_idx = fc_trace_entries.wr_idx; if (rdata_flag == 0) { - len += snprintf(fnic_dbgfs_prt->buffer + len, + len += scnprintf(fnic_dbgfs_prt->buffer + len, (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len, "Time Stamp (UTC)\t\t" "Host No: F Type: len: FCoE_FRAME:\n"); @@ -762,11 +762,11 @@ int fnic_fc_trace_get_data(fnic_dbgfs_t *fnic_dbgfs_prt, u8 rdata_flag) } else { fc_trace = (char *)tdata; for (j = 0; j < FC_TRC_SIZE_BYTES; j++) { - len += snprintf(fnic_dbgfs_prt->buffer + len, + len += scnprintf(fnic_dbgfs_prt->buffer + len, (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len, "%02x", fc_trace[j] & 0xff); } /* for loop */ - len += snprintf(fnic_dbgfs_prt->buffer + len, + len += scnprintf(fnic_dbgfs_prt->buffer + len, (fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len, "\n"); } @@ -810,7 +810,7 @@ void copy_and_format_trace_data(struct fc_trace_hdr *tdata, time64_to_tm(tdata->time_stamp.tv_sec, 0, &tm); fmt = "%02d:%02d:%04ld %02d:%02d:%02d.%09lu ns%8x %c%8x\t"; - len += snprintf(fnic_dbgfs_prt->buffer + len, + len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len, fmt, tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, @@ -823,25 +823,25 @@ void copy_and_format_trace_data(struct fc_trace_hdr *tdata, for (j = 0; j < min_t(u8, tdata->frame_len, (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)); j++) { if (tdata->frame_type == FNIC_FC_LE) { - len += snprintf(fnic_dbgfs_prt->buffer + len, + len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len, "%c", fc_trace[j]); } else { - len += snprintf(fnic_dbgfs_prt->buffer + len, + len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len, "%02x", fc_trace[j] & 0xff); - len += snprintf(fnic_dbgfs_prt->buffer + len, + len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len, " "); if (j == ethhdr_len || j == ethhdr_len + fcoehdr_len || j == ethhdr_len + fcoehdr_len + fchdr_len || (i > 3 && j%fchdr_len == 0)) { - len += snprintf(fnic_dbgfs_prt->buffer + len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len, "\n\t\t\t\t\t\t\t\t"); i++; } } /* end of else*/ } /* End of for loop*/ - len += snprintf(fnic_dbgfs_prt->buffer + len, + len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len, "\n"); *orig_len = len; } diff --git a/drivers/scsi/fnic/vnic_devcmd.h b/drivers/scsi/fnic/vnic_devcmd.h index c5dde556dc7c..c20d30e36dfc 100644 --- a/drivers/scsi/fnic/vnic_devcmd.h +++ b/drivers/scsi/fnic/vnic_devcmd.h @@ -442,7 +442,7 @@ struct vnic_devcmd_notify { struct vnic_devcmd_provinfo { u8 oui[3]; u8 type; - u8 data[0]; + u8 data[]; }; /* diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 2ab774e62e40..2cc676e3df6a 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -20,7 +20,7 @@ * Added ISAPNP support for DTC436 adapters, * Thomas Sailer, sailer@ife.ee.ethz.ch * - * See Documentation/scsi/g_NCR5380.txt for more info. + * See Documentation/scsi/g_NCR5380.rst for more info. */ #include <asm/io.h> diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index 381d849726ac..c764312f9ba0 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -193,7 +193,7 @@ int gdth_show_info(struct seq_file *m, struct Scsi_Host *host) for (i = 1; i < MAX_RES_ARGS; i++) { if (reserve_list[i] == 0xff) break; - hlen += snprintf(hrec + hlen , 161 - hlen, ",%d", reserve_list[i]); + hlen += scnprintf(hrec + hlen, 161 - hlen, ",%d", reserve_list[i]); } } seq_printf(m, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index a2debe0c8185..374885aa8d77 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2938,6 +2938,7 @@ static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, { u32 cache_dw_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * HISI_SAS_IOST_ITCT_CACHE_NUM; + struct device *dev = hisi_hba->dev; u32 *buf = cache; u32 i, val; @@ -2950,7 +2951,7 @@ static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, } if (val != 0xffffffff) { - pr_err("Issue occur when reading IOST/ITCT cache!\n"); + dev_err(dev, "Issue occurred in reading IOST/ITCT cache!\n"); return; } diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 1d669e47b692..7ec91c3a66ca 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -650,3 +650,68 @@ void scsi_flush_work(struct Scsi_Host *shost) flush_workqueue(shost->work_q); } EXPORT_SYMBOL_GPL(scsi_flush_work); + +static bool complete_all_cmds_iter(struct request *rq, void *data, bool rsvd) +{ + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq); + int status = *(int *)data; + + scsi_dma_unmap(scmd); + scmd->result = status << 16; + scmd->scsi_done(scmd); + return true; +} + +/** + * scsi_host_complete_all_commands - Terminate all running commands + * @shost: Scsi Host on which commands should be terminated + * @status: Status to be set for the terminated commands + * + * There is no protection against modification of the number + * of outstanding commands. It is the responsibility of the + * caller to ensure that concurrent I/O submission and/or + * completion is stopped when calling this function. + */ +void scsi_host_complete_all_commands(struct Scsi_Host *shost, int status) +{ + blk_mq_tagset_busy_iter(&shost->tag_set, complete_all_cmds_iter, + &status); +} +EXPORT_SYMBOL_GPL(scsi_host_complete_all_commands); + +struct scsi_host_busy_iter_data { + bool (*fn)(struct scsi_cmnd *, void *, bool); + void *priv; +}; + +static bool __scsi_host_busy_iter_fn(struct request *req, void *priv, + bool reserved) +{ + struct scsi_host_busy_iter_data *iter_data = priv; + struct scsi_cmnd *sc = blk_mq_rq_to_pdu(req); + + return iter_data->fn(sc, iter_data->priv, reserved); +} + +/** + * scsi_host_busy_iter - Iterate over all busy commands + * @shost: Pointer to Scsi_Host. + * @fn: Function to call on each busy command + * @priv: Data pointer passed to @fn + * + * If locking against concurrent command completions is required + * ithas to be provided by the caller + **/ +void scsi_host_busy_iter(struct Scsi_Host *shost, + bool (*fn)(struct scsi_cmnd *, void *, bool), + void *priv) +{ + struct scsi_host_busy_iter_data iter_data = { + .fn = fn, + .priv = priv, + }; + + blk_mq_tagset_busy_iter(&shost->tag_set, __scsi_host_busy_iter_fn, + &iter_data); +} +EXPORT_SYMBOL_GPL(scsi_host_busy_iter); diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 1a4ddfacb458..1e9302e99d05 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -504,6 +504,12 @@ static ssize_t host_store_rescan(struct device *dev, return count; } +static void hpsa_turn_off_ioaccel_for_device(struct hpsa_scsi_dev_t *device) +{ + device->offload_enabled = 0; + device->offload_to_be_enabled = 0; +} + static ssize_t host_show_firmware_revision(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1738,8 +1744,7 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, __func__, h->scsi_host->host_no, logical_drive->bus, logical_drive->target, logical_drive->lun); - logical_drive->offload_enabled = 0; - logical_drive->offload_to_be_enabled = 0; + hpsa_turn_off_ioaccel_for_device(logical_drive); logical_drive->queue_depth = 8; } } @@ -2499,8 +2504,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h, IOACCEL2_SERV_RESPONSE_FAILURE) { if (c2->error_data.status == IOACCEL2_STATUS_SR_IOACCEL_DISABLED) { - dev->offload_enabled = 0; - dev->offload_to_be_enabled = 0; + hpsa_turn_off_ioaccel_for_device(dev); } if (dev->in_reset) { @@ -3670,10 +3674,17 @@ static void hpsa_get_ioaccel_status(struct ctlr_info *h, this_device->offload_config = !!(ioaccel_status & OFFLOAD_CONFIGURED_BIT); if (this_device->offload_config) { - this_device->offload_to_be_enabled = + bool offload_enabled = !!(ioaccel_status & OFFLOAD_ENABLED_BIT); - if (hpsa_get_raid_map(h, scsi3addr, this_device)) - this_device->offload_to_be_enabled = 0; + /* + * Check to see if offload can be enabled. + */ + if (offload_enabled) { + rc = hpsa_get_raid_map(h, scsi3addr, this_device); + if (rc) /* could not load raid_map */ + goto out; + this_device->offload_to_be_enabled = 1; + } } out: @@ -3996,8 +4007,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, } else { this_device->raid_level = RAID_UNKNOWN; this_device->offload_config = 0; - this_device->offload_enabled = 0; - this_device->offload_to_be_enabled = 0; + hpsa_turn_off_ioaccel_for_device(this_device); this_device->hba_ioaccel_enabled = 0; this_device->volume_offline = 0; this_device->queue_depth = h->nr_cmds; @@ -5230,8 +5240,12 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, /* Handles load balance across RAID 1 members. * (2-drive R1 and R10 with even # of drives.) * Appropriate for SSDs, not optimal for HDDs + * Ensure we have the correct raid_map. */ - BUG_ON(le16_to_cpu(map->layout_map_count) != 2); + if (le16_to_cpu(map->layout_map_count) != 2) { + hpsa_turn_off_ioaccel_for_device(dev); + return IO_ACCEL_INELIGIBLE; + } if (dev->offload_to_mirror) map_index += le16_to_cpu(map->data_disks_per_row); dev->offload_to_mirror = !dev->offload_to_mirror; @@ -5239,8 +5253,12 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, case HPSA_RAID_ADM: /* Handles N-way mirrors (R1-ADM) * and R10 with # of drives divisible by 3.) + * Ensure we have the correct raid_map. */ - BUG_ON(le16_to_cpu(map->layout_map_count) != 3); + if (le16_to_cpu(map->layout_map_count) != 3) { + hpsa_turn_off_ioaccel_for_device(dev); + return IO_ACCEL_INELIGIBLE; + } offload_to_mirror = dev->offload_to_mirror; raid_map_helper(map, offload_to_mirror, @@ -5265,7 +5283,10 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, r5or6_blocks_per_row = le16_to_cpu(map->strip_size) * le16_to_cpu(map->data_disks_per_row); - BUG_ON(r5or6_blocks_per_row == 0); + if (r5or6_blocks_per_row == 0) { + hpsa_turn_off_ioaccel_for_device(dev); + return IO_ACCEL_INELIGIBLE; + } stripesize = r5or6_blocks_per_row * le16_to_cpu(map->layout_map_count); #if BITS_PER_LONG == 32 @@ -8285,7 +8306,7 @@ static int detect_controller_lockup(struct ctlr_info *h) * * Called from monitor controller worker (hpsa_event_monitor_worker) * - * A Volume (or Volumes that comprise an Array set may be undergoing a + * A Volume (or Volumes that comprise an Array set) may be undergoing a * transformation, so we will be turning off ioaccel for all volumes that * make up the Array. */ @@ -8308,6 +8329,9 @@ static void hpsa_set_ioaccel_status(struct ctlr_info *h) * Run through current device list used during I/O requests. */ for (i = 0; i < h->ndevices; i++) { + int offload_to_be_enabled = 0; + int offload_config = 0; + device = h->dev[i]; if (!device) @@ -8325,25 +8349,35 @@ static void hpsa_set_ioaccel_status(struct ctlr_info *h) continue; ioaccel_status = buf[IOACCEL_STATUS_BYTE]; - device->offload_config = + + /* + * Check if offload is still configured on + */ + offload_config = !!(ioaccel_status & OFFLOAD_CONFIGURED_BIT); - if (device->offload_config) - device->offload_to_be_enabled = + /* + * If offload is configured on, check to see if ioaccel + * needs to be enabled. + */ + if (offload_config) + offload_to_be_enabled = !!(ioaccel_status & OFFLOAD_ENABLED_BIT); /* + * If ioaccel is to be re-enabled, re-enable later during the + * scan operation so the driver can get a fresh raidmap + * before turning ioaccel back on. + */ + if (offload_to_be_enabled) + continue; + + /* * Immediately turn off ioaccel for any volume the * controller tells us to. Some of the reasons could be: * transformation - change to the LVs of an Array. * degraded volume - component failure - * - * If ioaccel is to be re-enabled, re-enable later during the - * scan operation so the driver can get a fresh raidmap - * before turning ioaccel back on. - * */ - if (!device->offload_to_be_enabled) - device->offload_enabled = 0; + hpsa_turn_off_ioaccel_for_device(device); } kfree(buf); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index df897df5cafe..7da9e060b270 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -133,6 +133,7 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *); static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *); static void ibmvfc_tgt_query_target(struct ibmvfc_target *); static void ibmvfc_npiv_logout(struct ibmvfc_host *); +static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *); static const char *unknown_error = "unknown error"; @@ -413,22 +414,44 @@ static const char *ibmvfc_get_fc_type(u16 status) * @tgt: ibmvfc target struct * @action: action to perform * + * Returns: + * 0 if action changed / non-zero if not changed **/ -static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, +static int ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, enum ibmvfc_target_action action) { + int rc = -EINVAL; + switch (tgt->action) { + case IBMVFC_TGT_ACTION_LOGOUT_RPORT: + if (action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT || + action == IBMVFC_TGT_ACTION_DEL_RPORT) { + tgt->action = action; + rc = 0; + } + break; + case IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT: + if (action == IBMVFC_TGT_ACTION_DEL_RPORT) { + tgt->action = action; + rc = 0; + } + break; case IBMVFC_TGT_ACTION_DEL_RPORT: - if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) + if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) { tgt->action = action; + rc = 0; + } case IBMVFC_TGT_ACTION_DELETED_RPORT: break; default: - if (action == IBMVFC_TGT_ACTION_DEL_RPORT) + if (action >= IBMVFC_TGT_ACTION_LOGOUT_RPORT) tgt->add_rport = 0; tgt->action = action; + rc = 0; break; } + + return rc; } /** @@ -537,6 +560,19 @@ static void ibmvfc_reinit_host(struct ibmvfc_host *vhost) } /** + * ibmvfc_del_tgt - Schedule cleanup and removal of the target + * @tgt: ibmvfc target struct + * @job_step: job step to perform + * + **/ +static void ibmvfc_del_tgt(struct ibmvfc_target *tgt) +{ + if (!ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_RPORT)) + tgt->job_step = ibmvfc_tgt_implicit_logout_and_del; + wake_up(&tgt->vhost->work_wait_q); +} + +/** * ibmvfc_link_down - Handle a link down event from the adapter * @vhost: ibmvfc host struct * @state: ibmvfc host state to enter @@ -550,7 +586,7 @@ static void ibmvfc_link_down(struct ibmvfc_host *vhost, ENTER; scsi_block_requests(vhost->host); list_for_each_entry(tgt, &vhost->targets, queue) - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); ibmvfc_set_host_state(vhost, state); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL); vhost->events_to_log |= IBMVFC_AE_LINKDOWN; @@ -583,7 +619,7 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost) vhost->async_crq.cur = 0; list_for_each_entry(tgt, &vhost->targets, queue) - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); scsi_block_requests(vhost->host); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT); vhost->job_step = ibmvfc_npiv_login; @@ -1500,7 +1536,7 @@ static void ibmvfc_relogin(struct scsi_device *sdev) list_for_each_entry(tgt, &vhost->targets, queue) { if (rport == tgt->rport) { - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); break; } } @@ -2686,7 +2722,7 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, if (tgt->need_login && be64_to_cpu(crq->event) == IBMVFC_AE_ELS_LOGO) tgt->logo_rcvd = 1; if (!tgt->need_login || be64_to_cpu(crq->event) == IBMVFC_AE_ELS_PLOGI) { - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); ibmvfc_reinit_host(vhost); } } @@ -3220,8 +3256,8 @@ static void ibmvfc_tasklet(void *data) static void ibmvfc_init_tgt(struct ibmvfc_target *tgt, void (*job_step) (struct ibmvfc_target *)) { - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT); - tgt->job_step = job_step; + if (!ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT)) + tgt->job_step = job_step; wake_up(&tgt->vhost->work_wait_q); } @@ -3237,7 +3273,7 @@ static int ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt, void (*job_step) (struct ibmvfc_target *)) { if (++tgt->init_retries > IBMVFC_MAX_TGT_INIT_RETRIES) { - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); wake_up(&tgt->vhost->work_wait_q); return 0; } else @@ -3312,13 +3348,13 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; tgt->add_rport = 1; } else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); } else if (prli_rsp[index].retry) ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); } else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); break; case IBMVFC_MAD_DRIVER_FAILED: break; @@ -3335,7 +3371,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n", ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), @@ -3434,7 +3470,7 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), @@ -3515,33 +3551,28 @@ static void ibmvfc_tgt_implicit_logout_done(struct ibmvfc_event *evt) break; } - if (vhost->action == IBMVFC_HOST_ACTION_TGT_INIT) - ibmvfc_init_tgt(tgt, ibmvfc_tgt_send_plogi); - else if (vhost->action == IBMVFC_HOST_ACTION_QUERY_TGTS && - tgt->scsi_id != tgt->new_scsi_id) - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_init_tgt(tgt, ibmvfc_tgt_send_plogi); kref_put(&tgt->kref, ibmvfc_release_tgt); wake_up(&vhost->work_wait_q); } /** - * ibmvfc_tgt_implicit_logout - Initiate an Implicit Logout for specified target + * __ibmvfc_tgt_get_implicit_logout_evt - Allocate and init an event for implicit logout * @tgt: ibmvfc target struct * + * Returns: + * Allocated and initialized ibmvfc_event struct **/ -static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) +static struct ibmvfc_event *__ibmvfc_tgt_get_implicit_logout_evt(struct ibmvfc_target *tgt, + void (*done) (struct ibmvfc_event *)) { struct ibmvfc_implicit_logout *mad; struct ibmvfc_host *vhost = tgt->vhost; struct ibmvfc_event *evt; - if (vhost->discovery_threads >= disc_threads) - return; - kref_get(&tgt->kref); evt = ibmvfc_get_event(vhost); - vhost->discovery_threads++; - ibmvfc_init_event(evt, ibmvfc_tgt_implicit_logout_done, IBMVFC_MAD_FORMAT); + ibmvfc_init_event(evt, done, IBMVFC_MAD_FORMAT); evt->tgt = tgt; mad = &evt->iu.implicit_logout; memset(mad, 0, sizeof(*mad)); @@ -3549,6 +3580,25 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT); mad->common.length = cpu_to_be16(sizeof(*mad)); mad->old_scsi_id = cpu_to_be64(tgt->scsi_id); + return evt; +} + +/** + * ibmvfc_tgt_implicit_logout - Initiate an Implicit Logout for specified target + * @tgt: ibmvfc target struct + * + **/ +static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) +{ + struct ibmvfc_host *vhost = tgt->vhost; + struct ibmvfc_event *evt; + + if (vhost->discovery_threads >= disc_threads) + return; + + vhost->discovery_threads++; + evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt, + ibmvfc_tgt_implicit_logout_done); ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); if (ibmvfc_send_event(evt, vhost, default_timeout)) { @@ -3560,6 +3610,53 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) } /** + * ibmvfc_tgt_implicit_logout_and_del_done - Completion handler for Implicit Logout MAD + * @evt: ibmvfc event struct + * + **/ +static void ibmvfc_tgt_implicit_logout_and_del_done(struct ibmvfc_event *evt) +{ + struct ibmvfc_target *tgt = evt->tgt; + struct ibmvfc_host *vhost = evt->vhost; + struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru; + u32 status = be16_to_cpu(mad->common.status); + + vhost->discovery_threads--; + ibmvfc_free_event(evt); + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + + tgt_dbg(tgt, "Implicit Logout %s\n", (status == IBMVFC_MAD_SUCCESS) ? "succeeded" : "failed"); + kref_put(&tgt->kref, ibmvfc_release_tgt); + wake_up(&vhost->work_wait_q); +} + +/** + * ibmvfc_tgt_implicit_logout_and_del - Initiate an Implicit Logout for specified target + * @tgt: ibmvfc target struct + * + **/ +static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *tgt) +{ + struct ibmvfc_host *vhost = tgt->vhost; + struct ibmvfc_event *evt; + + if (vhost->discovery_threads >= disc_threads) + return; + + vhost->discovery_threads++; + evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt, + ibmvfc_tgt_implicit_logout_and_del_done); + + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT); + if (ibmvfc_send_event(evt, vhost, default_timeout)) { + vhost->discovery_threads--; + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + kref_put(&tgt->kref, ibmvfc_release_tgt); + } else + tgt_dbg(tgt, "Sent Implicit Logout\n"); +} + +/** * ibmvfc_adisc_needs_plogi - Does device need PLOGI? * @mad: ibmvfc passthru mad struct * @tgt: ibmvfc target struct @@ -3600,13 +3697,13 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt) case IBMVFC_MAD_SUCCESS: tgt_dbg(tgt, "ADISC succeeded\n"); if (ibmvfc_adisc_needs_plogi(mad, tgt)) - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); break; case IBMVFC_MAD_DRIVER_FAILED: break; case IBMVFC_MAD_FAILED: default: - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); fc_reason = (be32_to_cpu(mad->fc_iu.response[1]) & 0x00ff0000) >> 16; fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8; tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", @@ -3799,9 +3896,8 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) switch (status) { case IBMVFC_MAD_SUCCESS: tgt_dbg(tgt, "Query Target succeeded\n"); - tgt->new_scsi_id = be64_to_cpu(rsp->scsi_id); if (be64_to_cpu(rsp->scsi_id) != tgt->scsi_id) - ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout); + ibmvfc_del_tgt(tgt); else ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc); break; @@ -3815,11 +3911,11 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) if ((be16_to_cpu(rsp->status) & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED && be16_to_cpu(rsp->error) == IBMVFC_UNABLE_TO_PERFORM_REQ && be16_to_cpu(rsp->fc_explain) == IBMVFC_PORT_NAME_NOT_REG) - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target); else - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_del_tgt(tgt); tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), @@ -3896,7 +3992,6 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id) tgt = mempool_alloc(vhost->tgt_pool, GFP_NOIO); memset(tgt, 0, sizeof(*tgt)); tgt->scsi_id = scsi_id; - tgt->new_scsi_id = scsi_id; tgt->vhost = vhost; tgt->need_login = 1; tgt->cancel_key = vhost->task_set++; @@ -4189,6 +4284,25 @@ static int ibmvfc_dev_init_to_do(struct ibmvfc_host *vhost) } /** + * ibmvfc_dev_logo_to_do - Is there target logout work to do? + * @vhost: ibmvfc host struct + * + * Returns: + * 1 if work to do / 0 if not + **/ +static int ibmvfc_dev_logo_to_do(struct ibmvfc_host *vhost) +{ + struct ibmvfc_target *tgt; + + list_for_each_entry(tgt, &vhost->targets, queue) { + if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT || + tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT) + return 1; + } + return 0; +} + +/** * __ibmvfc_work_to_do - Is there task level work to do? (no locking) * @vhost: ibmvfc host struct * @@ -4217,11 +4331,20 @@ static int __ibmvfc_work_to_do(struct ibmvfc_host *vhost) if (tgt->action == IBMVFC_TGT_ACTION_INIT_WAIT) return 0; return 1; + case IBMVFC_HOST_ACTION_TGT_DEL: + case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: + if (vhost->discovery_threads == disc_threads) + return 0; + list_for_each_entry(tgt, &vhost->targets, queue) + if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) + return 1; + list_for_each_entry(tgt, &vhost->targets, queue) + if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT) + return 0; + return 1; case IBMVFC_HOST_ACTION_LOGO: case IBMVFC_HOST_ACTION_INIT: case IBMVFC_HOST_ACTION_ALLOC_TGTS: - case IBMVFC_HOST_ACTION_TGT_DEL: - case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: case IBMVFC_HOST_ACTION_QUERY: case IBMVFC_HOST_ACTION_RESET: case IBMVFC_HOST_ACTION_REENABLE: @@ -4391,6 +4514,18 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) case IBMVFC_HOST_ACTION_TGT_DEL: case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: list_for_each_entry(tgt, &vhost->targets, queue) { + if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) { + tgt->job_step(tgt); + break; + } + } + + if (ibmvfc_dev_logo_to_do(vhost)) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + return; + } + + list_for_each_entry(tgt, &vhost->targets, queue) { if (tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { tgt_dbg(tgt, "Deleting rport\n"); rport = tgt->rport; diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 7da89f4d26b2..907889f1fa9d 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -596,6 +596,8 @@ enum ibmvfc_target_action { IBMVFC_TGT_ACTION_NONE = 0, IBMVFC_TGT_ACTION_INIT, IBMVFC_TGT_ACTION_INIT_WAIT, + IBMVFC_TGT_ACTION_LOGOUT_RPORT, + IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT, IBMVFC_TGT_ACTION_DEL_RPORT, IBMVFC_TGT_ACTION_DELETED_RPORT, }; @@ -604,7 +606,6 @@ struct ibmvfc_target { struct list_head queue; struct ibmvfc_host *vhost; u64 scsi_id; - u64 new_scsi_id; struct fc_rport *rport; int target_id; enum ibmvfc_target_action action; diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index cd8db1349871..d48a8fa997b9 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -1299,9 +1299,9 @@ static char *__ipr_format_res_path(u8 *res_path, char *buffer, int len) char *p = buffer; *p = '\0'; - p += snprintf(p, buffer + len - p, "%02X", res_path[0]); + p += scnprintf(p, buffer + len - p, "%02X", res_path[0]); for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++) - p += snprintf(p, buffer + len - p, "-%02X", res_path[i]); + p += scnprintf(p, buffer + len - p, "-%02X", res_path[i]); return buffer; } @@ -1322,7 +1322,7 @@ static char *ipr_format_res_path(struct ipr_ioa_cfg *ioa_cfg, char *p = buffer; *p = '\0'; - p += snprintf(p, buffer + len - p, "%d/", ioa_cfg->host->host_no); + p += scnprintf(p, buffer + len - p, "%d/", ioa_cfg->host->host_no); __ipr_format_res_path(res_path, p, len - (buffer - p)); return buffer; } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index b97aa9ac2ffe..9a0d3d729320 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -451,12 +451,12 @@ struct ipr_config_table_hdr64 { struct ipr_config_table { struct ipr_config_table_hdr hdr; - struct ipr_config_table_entry dev[0]; + struct ipr_config_table_entry dev[]; }__attribute__((packed, aligned (4))); struct ipr_config_table64 { struct ipr_config_table_hdr64 hdr64; - struct ipr_config_table_entry64 dev[0]; + struct ipr_config_table_entry64 dev[]; }__attribute__((packed, aligned (8))); struct ipr_config_table_entry_wrapper { @@ -792,7 +792,7 @@ struct ipr_mode_page28 { struct ipr_mode_page_hdr hdr; u8 num_entries; u8 entry_length; - struct ipr_dev_bus_entry bus[0]; + struct ipr_dev_bus_entry bus[]; }__attribute__((packed)); struct ipr_mode_page24 { diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h index dc26b4aea99e..15d8f3631ab7 100644 --- a/drivers/scsi/isci/sas.h +++ b/drivers/scsi/isci/sas.h @@ -201,7 +201,7 @@ struct smp_req { u8 func; /* byte 1 */ u8 alloc_resp_len; /* byte 2 */ u8 req_len; /* byte 3 */ - u8 req_data[0]; + u8 req_data[]; } __packed; /* diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 70b99c0e2e67..874dd4beed10 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2771,7 +2771,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, "must be a power of 2.\n", total_cmds); total_cmds = rounddown_pow_of_two(total_cmds); if (total_cmds < ISCSI_TOTAL_CMDS_MIN) - return NULL; + goto dec_session_count; printk(KERN_INFO "iscsi: Rounding can_queue to %d.\n", total_cmds); } @@ -3153,13 +3153,18 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) switch (flag) { case STOP_CONN_RECOVER: + cls_conn->state = ISCSI_CONN_FAILED; + break; case STOP_CONN_TERM: - iscsi_start_session_recovery(session, conn, flag); + cls_conn->state = ISCSI_CONN_DOWN; break; default: iscsi_conn_printk(KERN_ERR, conn, "invalid stop flag %d\n", flag); + return; } + + iscsi_start_session_recovery(session, conn, flag); } EXPORT_SYMBOL_GPL(iscsi_conn_stop); diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 04d73e2be373..357fdec06bae 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -262,7 +262,6 @@ struct lpfc_stats { uint32_t elsRcvPRLI; uint32_t elsRcvLIRR; uint32_t elsRcvRLS; - uint32_t elsRcvRPS; uint32_t elsRcvRPL; uint32_t elsRcvRRQ; uint32_t elsRcvRTV; @@ -749,6 +748,7 @@ struct lpfc_hba { * capability */ #define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */ +#define HBA_DEFER_FLOGI 0x800000 /* Defer FLOGI till read_sparm cmpl */ uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ struct lpfc_dmabuf slim2p; @@ -1353,3 +1353,32 @@ lpfc_sli4_mod_hba_eq_delay(struct lpfc_hba *phba, struct lpfc_queue *eq, writel(reg_data.word0, phba->sli4_hba.u.if_type2.EQDregaddr); eq->q_mode = delay; } + + +/* + * Macro that declares tables and a routine to perform enum type to + * ascii string lookup. + * + * Defines a <key,value> table for an enum. Uses xxx_INIT defines for + * the enum to populate the table. Macro defines a routine (named + * by caller) that will search all elements of the table for the key + * and return the name string if found or "Unrecognized" if not found. + */ +#define DECLARE_ENUM2STR_LOOKUP(routine, enum_name, enum_init) \ +static struct { \ + enum enum_name value; \ + char *name; \ +} fc_##enum_name##_e2str_names[] = enum_init; \ +static const char *routine(enum enum_name table_key) \ +{ \ + int i; \ + char *name = "Unrecognized"; \ + \ + for (i = 0; i < ARRAY_SIZE(fc_##enum_name##_e2str_names); i++) {\ + if (fc_##enum_name##_e2str_names[i].value == table_key) {\ + name = fc_##enum_name##_e2str_names[i].name; \ + break; \ + } \ + } \ + return name; \ +} diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 46f56f30f77e..4317c9ce7eca 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -3869,9 +3869,6 @@ LPFC_VPORT_ATTR_R(enable_da_id, 1, 0, 1, /* # lun_queue_depth: This parameter is used to limit the number of outstanding # commands per FCP LUN. Value range is [1,512]. Default value is 30. -# If this parameter value is greater than 1/8th the maximum number of exchanges -# supported by the HBA port, then the lun queue depth will be reduced to -# 1/8th the maximum number of exchanges. */ LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 512, "Max number of FCP commands we can queue to a specific LUN"); diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 25d3dd39bc05..a450477a7e00 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -140,9 +140,10 @@ int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *); -int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t); +int lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry); int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry); int lpfc_issue_fabric_reglogin(struct lpfc_vport *); +int lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry); int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 58b35a1442c1..2aa578d20f8c 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -2073,8 +2073,8 @@ lpfc_fdmi_hba_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, sizeof(struct lpfc_name)); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName, sizeof(struct lpfc_name)); @@ -2090,8 +2090,8 @@ lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); /* This string MUST be consistent with other FC platforms * supported by Broadcom. @@ -2115,8 +2115,8 @@ lpfc_fdmi_hba_attr_sn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, phba->SerialNumber, sizeof(ae->un.AttrString)); @@ -2137,8 +2137,8 @@ lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, phba->ModelName, sizeof(ae->un.AttrString)); @@ -2158,8 +2158,8 @@ lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, phba->ModelDesc, sizeof(ae->un.AttrString)); @@ -2181,8 +2181,8 @@ lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t i, j, incr, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); /* Convert JEDEC ID to ascii for hardware version */ incr = vp->rev.biuRev; @@ -2211,8 +2211,8 @@ lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, lpfc_release_version, sizeof(ae->un.AttrString)); @@ -2233,8 +2233,8 @@ lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); if (phba->sli_rev == LPFC_SLI_REV4) lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1); @@ -2258,8 +2258,8 @@ lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1); len = strnlen(ae->un.AttrString, @@ -2278,8 +2278,8 @@ lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s %s %s", init_utsname()->sysname, @@ -2301,7 +2301,7 @@ lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = cpu_to_be32(LPFC_MAX_CT_SIZE); size = FOURBYTES + sizeof(uint32_t); @@ -2317,8 +2317,8 @@ lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); len = lpfc_vport_symbolic_node_name(vport, ae->un.AttrString, 256); @@ -2336,7 +2336,7 @@ lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; /* Nothing is defined for this currently */ ae->un.AttrInt = cpu_to_be32(0); @@ -2353,7 +2353,7 @@ lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; /* Each driver instance corresponds to a single port */ ae->un.AttrInt = cpu_to_be32(1); @@ -2370,8 +2370,8 @@ lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, sizeof(struct lpfc_name)); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrWWN, &vport->fabric_nodename, sizeof(struct lpfc_name)); @@ -2389,8 +2389,8 @@ lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strlcat(ae->un.AttrString, phba->BIOSVersion, sizeof(ae->un.AttrString)); @@ -2410,7 +2410,7 @@ lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; /* Driver doesn't have access to this information */ ae->un.AttrInt = cpu_to_be32(0); @@ -2427,8 +2427,8 @@ lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, "EMULEX", sizeof(ae->un.AttrString)); @@ -2450,10 +2450,9 @@ lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 32); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); - ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */ ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */ ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */ @@ -2476,7 +2475,7 @@ lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = 0; if (!(phba->hba_flag & HBA_FCOE_MODE)) { @@ -2530,7 +2529,7 @@ lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; if (!(phba->hba_flag & HBA_FCOE_MODE)) { switch (phba->fc_linkspeed) { @@ -2600,7 +2599,7 @@ lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; hsp = (struct serv_parm *)&vport->fc_sparam; ae->un.AttrInt = (((uint32_t) hsp->cmn.bbRcvSizeMsb & 0x0F) << 8) | @@ -2620,8 +2619,8 @@ lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "/sys/class/scsi_host/host%d", shost->host_no); @@ -2641,8 +2640,8 @@ lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); scnprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s", vport->phba->os_host_name); @@ -2662,8 +2661,8 @@ lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, sizeof(struct lpfc_name)); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName, sizeof(struct lpfc_name)); @@ -2680,8 +2679,8 @@ lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, sizeof(struct lpfc_name)); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrWWN, &vport->fc_sparam.portName, sizeof(struct lpfc_name)); @@ -2698,8 +2697,8 @@ lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); len = lpfc_vport_symbolic_port_name(vport, ae->un.AttrString, 256); len += (len & 3) ? (4 - (len & 3)) : 4; @@ -2717,7 +2716,7 @@ lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTTYPE_NLPORT); else @@ -2735,7 +2734,7 @@ lpfc_fdmi_port_attr_class(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = cpu_to_be32(FC_COS_CLASS2 | FC_COS_CLASS3); size = FOURBYTES + sizeof(uint32_t); ad->AttrLen = cpu_to_be16(size); @@ -2750,8 +2749,8 @@ lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, sizeof(struct lpfc_name)); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrWWN, &vport->fabric_portname, sizeof(struct lpfc_name)); @@ -2768,10 +2767,9 @@ lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 32); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); - ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */ ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */ ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */ @@ -2792,7 +2790,7 @@ lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; /* Link Up - operational */ ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTSTATE_ONLINE); size = FOURBYTES + sizeof(uint32_t); @@ -2808,7 +2806,7 @@ lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; vport->fdmi_num_disc = lpfc_find_map_node(vport); ae->un.AttrInt = cpu_to_be32(vport->fdmi_num_disc); size = FOURBYTES + sizeof(uint32_t); @@ -2824,7 +2822,7 @@ lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = cpu_to_be32(vport->fc_myDID); size = FOURBYTES + sizeof(uint32_t); ad->AttrLen = cpu_to_be16(size); @@ -2839,8 +2837,8 @@ lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, "Smart SAN Initiator", sizeof(ae->un.AttrString)); @@ -2860,8 +2858,8 @@ lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); memcpy(&ae->un.AttrString, &vport->fc_sparam.nodeName, sizeof(struct lpfc_name)); @@ -2881,8 +2879,8 @@ lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, "Smart SAN Version 2.0", sizeof(ae->un.AttrString)); @@ -2903,8 +2901,8 @@ lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t len, size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; - memset(ae, 0, 256); + ae = &ad->AttrValue; + memset(ae, 0, sizeof(*ae)); strncpy(ae->un.AttrString, phba->ModelName, sizeof(ae->un.AttrString)); @@ -2923,7 +2921,7 @@ lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; /* SRIOV (type 3) is not supported */ if (vport->vpi) @@ -2943,7 +2941,7 @@ lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = cpu_to_be32(0); size = FOURBYTES + sizeof(uint32_t); ad->AttrLen = cpu_to_be16(size); @@ -2958,7 +2956,7 @@ lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport, struct lpfc_fdmi_attr_entry *ae; uint32_t size; - ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + ae = &ad->AttrValue; ae->un.AttrInt = cpu_to_be32(1); size = FOURBYTES + sizeof(uint32_t); ad->AttrLen = cpu_to_be16(size); @@ -3106,7 +3104,8 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* Registered Port List */ /* One entry (port) per adapter */ rh->rpl.EntryCnt = cpu_to_be32(1); - memcpy(&rh->rpl.pe, &phba->pport->fc_sparam.portName, + memcpy(&rh->rpl.pe.PortName, + &phba->pport->fc_sparam.portName, sizeof(struct lpfc_name)); /* point to the HBA attribute block */ diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 42a2bf38eaea..80d1e661b0d4 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -3008,10 +3008,9 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, * This routine is a generic completion callback function for ELS commands. * Specifically, it is the callback function which does not need to perform * any command specific operations. It is currently used by the ELS command - * issuing routines for the ELS State Change Request (SCR), - * lpfc_issue_els_scr(), and the ELS Fibre Channel Address Resolution - * Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). Other than - * certain debug loggings, this callback function simply invokes the + * issuing routines for RSCN, lpfc_issue_els_rscn, and the ELS Fibre Channel + * Address Resolution Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). + * Other than certain debug loggings, this callback function simply invokes the * lpfc_els_chk_latt() routine to check whether link went down during the * discovery process. **/ @@ -3025,14 +3024,117 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp = &rspiocb->iocb; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "ELS cmd cmpl: status:x%x/x%x did:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->un.elsreq64.remoteID); + + /* ELS cmd tag <ulpIoTag> completes */ + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n", + irsp->ulpIoTag, irsp->ulpStatus, + irsp->un.ulpWord[4], irsp->ulpTimeout); + + /* Check to see if link went down during discovery */ + lpfc_els_chk_latt(vport); + lpfc_els_free_iocb(phba, cmdiocb); +} + +/** + * lpfc_cmpl_els_disc_cmd - Completion callback function for Discovery ELS cmd + * @phba: pointer to lpfc hba data structure. + * @cmdiocb: pointer to lpfc command iocb data structure. + * @rspiocb: pointer to lpfc response iocb data structure. + * + * This routine is a generic completion callback function for Discovery ELS cmd. + * Currently used by the ELS command issuing routines for the ELS State Change + * Request (SCR), lpfc_issue_els_scr() and the ELS RDF, lpfc_issue_els_rdf(). + * These commands will be retried once only for ELS timeout errors. + **/ +static void +lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + struct lpfc_iocbq *rspiocb) +{ + struct lpfc_vport *vport = cmdiocb->vport; + IOCB_t *irsp; + struct lpfc_els_rdf_rsp *prdf; + struct lpfc_dmabuf *pcmd, *prsp; + u32 *pdata; + u32 cmd; + + irsp = &rspiocb->iocb; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "ELS cmd cmpl: status:x%x/x%x did:x%x", irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.elsreq64.remoteID); /* ELS cmd tag <ulpIoTag> completes */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, - "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n", + "0217 ELS cmd tag x%x completes Data: x%x x%x x%x " + "x%x\n", irsp->ulpIoTag, irsp->ulpStatus, - irsp->un.ulpWord[4], irsp->ulpTimeout); + irsp->un.ulpWord[4], irsp->ulpTimeout, + cmdiocb->retry); + + pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; + if (!pcmd) + goto out; + + pdata = (u32 *)pcmd->virt; + if (!pdata) + goto out; + cmd = *pdata; + + /* Only 1 retry for ELS Timeout only */ + if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT && + ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == + IOERR_SEQUENCE_TIMEOUT)) { + cmdiocb->retry++; + if (cmdiocb->retry <= 1) { + switch (cmd) { + case ELS_CMD_SCR: + lpfc_issue_els_scr(vport, cmdiocb->retry); + break; + case ELS_CMD_RDF: + cmdiocb->context1 = NULL; /* save ndlp refcnt */ + lpfc_issue_els_rdf(vport, cmdiocb->retry); + break; + } + goto out; + } + phba->fc_stat.elsRetryExceeded++; + } + if (irsp->ulpStatus) { + /* ELS discovery cmd completes with error */ + lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, + "4203 ELS cmd x%x error: x%x x%X\n", cmd, + irsp->ulpStatus, irsp->un.ulpWord[4]); + goto out; + } + + /* The RDF response doesn't have any impact on the running driver + * but the notification descriptors are dumped here for support. + */ + if (cmd == ELS_CMD_RDF) { + int i; + + prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); + if (!prsp) + goto out; + + prdf = (struct lpfc_els_rdf_rsp *)prsp->virt; + if (!prdf) + goto out; + + for (i = 0; i < ELS_RDF_REG_TAG_CNT && + i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++) + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "4677 Fabric RDF Notification Grant Data: " + "0x%08x\n", + be32_to_cpu( + prdf->reg_d1.desc_tags[i])); + } + +out: /* Check to see if link went down during discovery */ lpfc_els_chk_latt(vport); lpfc_els_free_iocb(phba, cmdiocb); @@ -3042,11 +3144,10 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /** * lpfc_issue_els_scr - Issue a scr to an node on a vport * @vport: pointer to a host virtual N_Port data structure. - * @nportid: N_Port identifier to the remote node. - * @retry: number of retries to the command IOCB. + * @retry: retry counter for the command IOCB. * * This routine issues a State Change Request (SCR) to a fabric node - * on a @vport. The remote node @nportid is passed into the function. It + * on a @vport. The remote node is Fabric Controller (0xfffffd). It * first search the @vport node list to find the matching ndlp. If no such * ndlp is found, a new ndlp shall be created for this (SCR) purpose. An * IOCB is allocated, payload prepared, and the lpfc_sli_issue_iocb() @@ -3062,7 +3163,7 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * 1 - Failed to issue scr command **/ int -lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) +lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) { struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *elsiocb; @@ -3072,9 +3173,9 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) cmdsize = (sizeof(uint32_t) + sizeof(SCR)); - ndlp = lpfc_findnode_did(vport, nportid); + ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID); if (!ndlp) { - ndlp = lpfc_nlp_init(vport, nportid); + ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID); if (!ndlp) return 1; lpfc_enqueue_node(vport, ndlp); @@ -3109,7 +3210,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) ndlp->nlp_DID, 0, 0); phba->fc_stat.elsXmitSCR++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; + elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) { /* The additional lpfc_nlp_put will cause the following @@ -3339,6 +3440,102 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) /* This will cause the callback-function lpfc_cmpl_els_cmd to * trigger the release of the node. */ + /* Don't release reference count as RDF is likely outstanding */ + return 0; +} + +/** + * lpfc_issue_els_rdf - Register for diagnostic functions from the fabric. + * @vport: pointer to a host virtual N_Port data structure. + * @retry: retry counter for the command IOCB. + * + * This routine issues an ELS RDF to the Fabric Controller to register + * for diagnostic functions. + * + * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp + * will be incremented by 1 for holding the ndlp and the reference to ndlp + * will be stored into the context1 field of the IOCB for the completion + * callback function to the RDF ELS command. + * + * Return code + * 0 - Successfully issued rdf command + * 1 - Failed to issue rdf command + **/ +int +lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry) +{ + struct lpfc_hba *phba = vport->phba; + struct lpfc_iocbq *elsiocb; + struct lpfc_els_rdf_req *prdf; + struct lpfc_nodelist *ndlp; + uint16_t cmdsize; + + cmdsize = sizeof(*prdf); + + ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID); + if (!ndlp) { + ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID); + if (!ndlp) + return -ENODEV; + lpfc_enqueue_node(vport, ndlp); + } else if (!NLP_CHK_NODE_ACT(ndlp)) { + ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); + if (!ndlp) + return -ENODEV; + } + + /* RDF ELS is not required on an NPIV VN_Port. */ + if (vport->port_type == LPFC_NPIV_PORT) { + lpfc_nlp_put(ndlp); + return -EACCES; + } + + elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, + ndlp->nlp_DID, ELS_CMD_RDF); + if (!elsiocb) { + /* This will trigger the release of the node just + * allocated + */ + lpfc_nlp_put(ndlp); + return -ENOMEM; + } + + /* Configure the payload for the supported FPIN events. */ + prdf = (struct lpfc_els_rdf_req *) + (((struct lpfc_dmabuf *)elsiocb->context2)->virt); + memset(prdf, 0, cmdsize); + prdf->rdf.fpin_cmd = ELS_RDF; + prdf->rdf.desc_len = cpu_to_be32(sizeof(struct lpfc_els_rdf_req) - + sizeof(struct fc_els_rdf)); + prdf->reg_d1.reg_desc.desc_tag = cpu_to_be32(ELS_DTAG_FPIN_REGISTER); + prdf->reg_d1.reg_desc.desc_len = cpu_to_be32( + FC_TLV_DESC_LENGTH_FROM_SZ(prdf->reg_d1)); + prdf->reg_d1.reg_desc.count = cpu_to_be32(ELS_RDF_REG_TAG_CNT); + prdf->reg_d1.desc_tags[0] = cpu_to_be32(ELS_DTAG_LNK_INTEGRITY); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue RDF: did:x%x", + ndlp->nlp_DID, 0, 0); + + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "6444 Xmit RDF to remote NPORT x%x\n", + ndlp->nlp_DID); + + elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; + if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == + IOCB_ERROR) { + /* The additional lpfc_nlp_put will cause the following + * lpfc_els_free_iocb routine to trigger the rlease of + * the node. + */ + lpfc_nlp_put(ndlp); + lpfc_els_free_iocb(phba, elsiocb); + return -EIO; + } + + /* An RDF was issued - this put ensures the ndlp is cleaned up + * when the RDF completes. + */ lpfc_nlp_put(ndlp); return 0; } @@ -7135,108 +7332,12 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /** - * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd - * @phba: pointer to lpfc hba data structure. - * @pmb: pointer to the driver internal queue element for mailbox command. - * - * This routine is the completion callback function for the MBX_READ_LNK_STAT - * mailbox command. This callback function is to actually send the Accept - * (ACC) response to a Read Port Status (RPS) unsolicited IOCB event. It - * collects the link statistics from the completion of the MBX_READ_LNK_STAT - * mailbox command, constructs the RPS response with the link statistics - * collected, and then invokes the lpfc_sli_issue_iocb() routine to send ACC - * response to the RPS. - * - * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp - * will be incremented by 1 for holding the ndlp and the reference to ndlp - * will be stored into the context1 field of the IOCB for the completion - * callback function to the RPS Accept Response ELS IOCB command. - * - **/ -static void -lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) -{ - MAILBOX_t *mb; - IOCB_t *icmd; - RPS_RSP *rps_rsp; - uint8_t *pcmd; - struct lpfc_iocbq *elsiocb; - struct lpfc_nodelist *ndlp; - uint16_t status; - uint16_t oxid; - uint16_t rxid; - uint32_t cmdsize; - - mb = &pmb->u.mb; - - ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; - rxid = (uint16_t)((unsigned long)(pmb->ctx_buf) & 0xffff); - oxid = (uint16_t)(((unsigned long)(pmb->ctx_buf) >> 16) & 0xffff); - pmb->ctx_ndlp = NULL; - pmb->ctx_buf = NULL; - - if (mb->mbxStatus) { - mempool_free(pmb, phba->mbox_mem_pool); - return; - } - - cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); - mempool_free(pmb, phba->mbox_mem_pool); - elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize, - lpfc_max_els_tries, ndlp, - ndlp->nlp_DID, ELS_CMD_ACC); - - /* Decrement the ndlp reference count from previous mbox command */ - lpfc_nlp_put(ndlp); - - if (!elsiocb) - return; - - icmd = &elsiocb->iocb; - icmd->ulpContext = rxid; - icmd->unsli3.rcvsli3.ox_id = oxid; - - pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); - *((uint32_t *) (pcmd)) = ELS_CMD_ACC; - pcmd += sizeof(uint32_t); /* Skip past command */ - rps_rsp = (RPS_RSP *)pcmd; - - if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) - status = 0x10; - else - status = 0x8; - if (phba->pport->fc_flag & FC_FABRIC) - status |= 0x4; - - rps_rsp->rsvd1 = 0; - rps_rsp->portStatus = cpu_to_be16(status); - rps_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt); - rps_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt); - rps_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt); - rps_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt); - rps_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord); - rps_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt); - /* Xmit ELS RPS ACC response tag <ulpIoTag> */ - lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS, - "0118 Xmit ELS RPS ACC response tag x%x xri x%x, " - "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", - elsiocb->iotag, elsiocb->iocb.ulpContext, - ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, - ndlp->nlp_rpi); - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; - phba->fc_stat.elsXmitACC++; - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) - lpfc_els_free_iocb(phba, elsiocb); - return; -} - -/** * lpfc_els_rcv_rls - Process an unsolicited rls iocb * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. * - * This routine processes Read Port Status (RPL) IOCB received as an + * This routine processes Read Link Status (RLS) IOCB received as an * ELS unsolicited event. It first checks the remote port state. If the * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE * state, it invokes the lpfc_els_rsl_reject() routine to send the reject @@ -7258,7 +7359,7 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) - /* reject the unsolicited RPS request and done with it */ + /* reject the unsolicited RLS request and done with it */ goto reject_out; mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC); @@ -7306,7 +7407,7 @@ reject_out: * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp * will be incremented by 1 for holding the ndlp and the reference to ndlp * will be stored into the context1 field of the IOCB for the completion - * callback function to the RPS Accept Response ELS IOCB command. + * callback function to the RTV Accept Response ELS IOCB command. * * Return codes * 0 - Successfully processed rtv iocb (currently always return 0) @@ -7325,7 +7426,7 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) - /* reject the unsolicited RPS request and done with it */ + /* reject the unsolicited RTV request and done with it */ goto reject_out; cmdsize = sizeof(struct RTV_RSP) + sizeof(uint32_t); @@ -7378,84 +7479,7 @@ reject_out: return 0; } -/* lpfc_els_rcv_rps - Process an unsolicited rps iocb - * @vport: pointer to a host virtual N_Port data structure. - * @cmdiocb: pointer to lpfc command iocb data structure. - * @ndlp: pointer to a node-list data structure. - * - * This routine processes Read Port Status (RPS) IOCB received as an - * ELS unsolicited event. It first checks the remote port state. If the - * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE - * state, it invokes the lpfc_els_rsp_reject() routine to send the reject - * response. Otherwise, it issue the MBX_READ_LNK_STAT mailbox command - * for reading the HBA link statistics. It is for the callback function, - * lpfc_els_rsp_rps_acc(), set to the MBX_READ_LNK_STAT mailbox command - * to actually sending out RPS Accept (ACC) response. - * - * Return codes - * 0 - Successfully processed rps iocb (currently always return 0) - **/ -static int -lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, - struct lpfc_nodelist *ndlp) -{ - struct lpfc_hba *phba = vport->phba; - uint32_t *lp; - uint8_t flag; - LPFC_MBOXQ_t *mbox; - struct lpfc_dmabuf *pcmd; - RPS *rps; - struct ls_rjt stat; - - if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && - (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) - /* reject the unsolicited RPS request and done with it */ - goto reject_out; - - pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; - lp = (uint32_t *) pcmd->virt; - flag = (be32_to_cpu(*lp++) & 0xf); - rps = (RPS *) lp; - - if ((flag == 0) || - ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) || - ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname, - sizeof(struct lpfc_name)) == 0))) { - - printk("Fix me....\n"); - dump_stack(); - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC); - if (mbox) { - lpfc_read_lnk_stat(phba, mbox); - mbox->ctx_buf = (void *)((unsigned long) - ((cmdiocb->iocb.unsli3.rcvsli3.ox_id << 16) | - cmdiocb->iocb.ulpContext)); /* rx_id */ - mbox->ctx_ndlp = lpfc_nlp_get(ndlp); - mbox->vport = vport; - mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; - if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) - != MBX_NOT_FINISHED) - /* Mbox completion will send ELS Response */ - return 0; - /* Decrement reference count used for the failed mbox - * command. - */ - lpfc_nlp_put(ndlp); - mempool_free(mbox, phba->mbox_mem_pool); - } - } - -reject_out: - /* issue rejection response */ - stat.un.b.lsRjtRsvd0 = 0; - stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; - stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; - stat.un.b.vendorUnique = 0; - lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); - return 0; -} - -/* lpfc_issue_els_rrq - Process an unsolicited rps iocb +/* lpfc_issue_els_rrq - Process an unsolicited rrq iocb * @vport: pointer to a host virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @did: DID of the target. @@ -8310,6 +8334,90 @@ lpfc_send_els_event(struct lpfc_vport *vport, } +DECLARE_ENUM2STR_LOOKUP(lpfc_get_tlv_dtag_nm, fc_ls_tlv_dtag, + FC_LS_TLV_DTAG_INIT); + +DECLARE_ENUM2STR_LOOKUP(lpfc_get_fpin_li_event_nm, fc_fpin_li_event_types, + FC_FPIN_LI_EVT_TYPES_INIT); + +/** + * lpfc_els_rcv_fpin_li - Process an FPIN Link Integrity Event. + * @vport: Pointer to vport object. + * @lnk_not: Pointer to the Link Integrity Notification Descriptor. + * + * This function processes a link integrity FPIN event by + * logging a message + **/ +static void +lpfc_els_rcv_fpin_li(struct lpfc_vport *vport, struct fc_tlv_desc *tlv) +{ + struct fc_fn_li_desc *li = (struct fc_fn_li_desc *)tlv; + const char *li_evt_str; + u32 li_evt; + + li_evt = be16_to_cpu(li->event_type); + li_evt_str = lpfc_get_fpin_li_event_nm(li_evt); + + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "4680 FPIN Link Integrity %s (x%x) " + "Detecting PN x%016llx Attached PN x%016llx " + "Duration %d mSecs Count %d Port Cnt %d\n", + li_evt_str, li_evt, + be64_to_cpu(li->detecting_wwpn), + be64_to_cpu(li->attached_wwpn), + be32_to_cpu(li->event_threshold), + be32_to_cpu(li->event_count), + be32_to_cpu(li->pname_count)); +} + +static void +lpfc_els_rcv_fpin(struct lpfc_vport *vport, struct fc_els_fpin *fpin, + u32 fpin_length) +{ + struct fc_tlv_desc *tlv; + const char *dtag_nm; + uint32_t desc_cnt = 0, bytes_remain; + u32 dtag; + + /* FPINs handled only if we are in the right discovery state */ + if (vport->port_state < LPFC_DISC_AUTH) + return; + + /* make sure there is the full fpin header */ + if (fpin_length < sizeof(struct fc_els_fpin)) + return; + + tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0]; + bytes_remain = fpin_length - offsetof(struct fc_els_fpin, fpin_desc); + bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len)); + + /* process each descriptor */ + while (bytes_remain >= FC_TLV_DESC_HDR_SZ && + bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) { + + dtag = be32_to_cpu(tlv->desc_tag); + switch (dtag) { + case ELS_DTAG_LNK_INTEGRITY: + lpfc_els_rcv_fpin_li(vport, tlv); + break; + default: + dtag_nm = lpfc_get_tlv_dtag_nm(dtag); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "4678 skipped FPIN descriptor[%d]: " + "tag x%x (%s)\n", + desc_cnt, dtag, dtag_nm); + break; + } + + desc_cnt++; + bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv); + tlv = fc_tlv_next_desc(tlv); + } + + fc_host_fpin_rcv(lpfc_shost_from_vport(vport), fpin_length, + (char *)fpin); +} + /** * lpfc_els_unsol_buffer - Process an unsolicited event data buffer * @phba: pointer to lpfc hba data structure. @@ -8331,7 +8439,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct Scsi_Host *shost; struct lpfc_nodelist *ndlp; struct ls_rjt stat; - uint32_t *payload; + uint32_t *payload, payload_len; uint32_t cmd, did, newnode; uint8_t rjt_exp, rjt_err = 0, init_link = 0; IOCB_t *icmd = &elsiocb->iocb; @@ -8342,6 +8450,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, newnode = 0; payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt; + payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len; cmd = *payload; if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) lpfc_post_buffer(phba, pring, 1); @@ -8632,16 +8741,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (newnode) lpfc_nlp_put(ndlp); break; - case ELS_CMD_RPS: - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, - "RCV RPS: did:x%x/ste:x%x flg:x%x", - did, vport->port_state, ndlp->nlp_flag); - - phba->fc_stat.elsRcvRPS++; - lpfc_els_rcv_rps(vport, elsiocb, ndlp); - if (newnode) - lpfc_nlp_put(ndlp); - break; case ELS_CMD_RPL: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, "RCV RPL: did:x%x/ste:x%x flg:x%x", @@ -8697,12 +8796,14 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, rjt_exp = LSEXP_INVALID_OX_RX; break; case ELS_CMD_FPIN: - /* - * Received FPIN from fabric - pass it to the - * transport FPIN handler. - */ - fc_host_fpin_rcv(shost, elsiocb->iocb.unsli3.rcvsli3.acc_len, - (char *)payload); + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, + "RCV FPIN: did:x%x/ste:x%x flg:x%x", + did, vport->port_state, ndlp->nlp_flag); + + lpfc_els_rcv_fpin(vport, (struct fc_els_fpin *)payload, + payload_len); + + /* There are no replies, so no rjt codes */ break; default: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index dcc8999c6a68..789eecbf32eb 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -1163,13 +1163,16 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /* Start discovery by sending a FLOGI. port_state is identically - * LPFC_FLOGI while waiting for FLOGI cmpl + * LPFC_FLOGI while waiting for FLOGI cmpl. Check if sending + * the FLOGI is being deferred till after MBX_READ_SPARAM completes. */ - if (vport->port_state != LPFC_FLOGI) - lpfc_initial_flogi(vport); - else if (vport->fc_flag & FC_PT2PT) - lpfc_disc_start(vport); - + if (vport->port_state != LPFC_FLOGI) { + if (!(phba->hba_flag & HBA_DEFER_FLOGI)) + lpfc_initial_flogi(vport); + } else { + if (vport->fc_flag & FC_PT2PT) + lpfc_disc_start(vport); + } return; out: @@ -3094,6 +3097,14 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free(pmb, phba->mbox_mem_pool); + + /* Check if sending the FLOGI is being deferred to after we get + * up to date CSPs from MBX_READ_SPARAM. + */ + if (phba->hba_flag & HBA_DEFER_FLOGI) { + lpfc_initial_flogi(vport); + phba->hba_flag &= ~HBA_DEFER_FLOGI; + } return; out: @@ -3224,6 +3235,23 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) } lpfc_linkup(phba); + sparam_mbox = NULL; + + if (!(phba->hba_flag & HBA_FCOE_MODE)) { + cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!cfglink_mbox) + goto out; + vport->port_state = LPFC_LOCAL_CFG_LINK; + lpfc_config_link(phba, cfglink_mbox); + cfglink_mbox->vport = vport; + cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; + rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { + mempool_free(cfglink_mbox, phba->mbox_mem_pool); + goto out; + } + } + sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!sparam_mbox) goto out; @@ -3244,20 +3272,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) goto out; } - if (!(phba->hba_flag & HBA_FCOE_MODE)) { - cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!cfglink_mbox) - goto out; - vport->port_state = LPFC_LOCAL_CFG_LINK; - lpfc_config_link(phba, cfglink_mbox); - cfglink_mbox->vport = vport; - cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; - rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) { - mempool_free(cfglink_mbox, phba->mbox_mem_pool); - goto out; - } - } else { + if (phba->hba_flag & HBA_FCOE_MODE) { vport->port_state = LPFC_VPORT_UNKNOWN; /* * Add the driver's default FCF record at FCF index 0 now. This @@ -3314,6 +3329,10 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) } /* Reset FCF roundrobin bmask for new discovery */ lpfc_sli4_clear_fcf_rr_bmask(phba); + } else { + if (phba->bbcredit_support && phba->cfg_enable_bbcr && + !(phba->link_flag & LS_LOOPBACK_MODE)) + phba->hba_flag |= HBA_DEFER_FLOGI; } /* Prepare for LINK up registrations */ @@ -4070,7 +4089,9 @@ out: FC_TYPE_NVME); /* Issue SCR just before NameServer GID_FT Query */ - lpfc_issue_els_scr(vport, SCR_DID, 0); + lpfc_issue_els_scr(vport, 0); + + lpfc_issue_els_rdf(vport, 0); } vport->fc_ns_retry = 0; diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 436cdc8c5ef4..ae51c0dbba0a 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -22,7 +22,7 @@ #define FDMI_DID 0xfffffaU #define NameServer_DID 0xfffffcU -#define SCR_DID 0xfffffdU +#define Fabric_Cntl_DID 0xfffffdU #define Fabric_DID 0xfffffeU #define Bcast_DID 0xffffffU #define Mask_DID 0xffffffU @@ -588,6 +588,7 @@ struct fc_vft_header { #define ELS_CMD_RRQ 0x12000000 #define ELS_CMD_REC 0x13000000 #define ELS_CMD_RDP 0x18000000 +#define ELS_CMD_RDF 0x19000000 #define ELS_CMD_PRLI 0x20100014 #define ELS_CMD_NVMEPRLI 0x20140018 #define ELS_CMD_PRLO 0x21100014 @@ -597,7 +598,6 @@ struct fc_vft_header { #define ELS_CMD_ADISC 0x52000000 #define ELS_CMD_FARP 0x54000000 #define ELS_CMD_FARPR 0x55000000 -#define ELS_CMD_RPS 0x56000000 #define ELS_CMD_RPL 0x57000000 #define ELS_CMD_FAN 0x60000000 #define ELS_CMD_RSCN 0x61040000 @@ -630,6 +630,7 @@ struct fc_vft_header { #define ELS_CMD_RRQ 0x12 #define ELS_CMD_REC 0x13 #define ELS_CMD_RDP 0x18 +#define ELS_CMD_RDF 0x19 #define ELS_CMD_PRLI 0x14001020 #define ELS_CMD_NVMEPRLI 0x18001420 #define ELS_CMD_PRLO 0x14001021 @@ -639,7 +640,6 @@ struct fc_vft_header { #define ELS_CMD_ADISC 0x52 #define ELS_CMD_FARP 0x54 #define ELS_CMD_FARPR 0x55 -#define ELS_CMD_RPS 0x56 #define ELS_CMD_RPL 0x57 #define ELS_CMD_FAN 0x60 #define ELS_CMD_RSCN 0x0461 @@ -919,24 +919,6 @@ typedef struct _RNID { /* Structure is in Big Endian format */ } un; } __packed RNID; -typedef struct _RPS { /* Structure is in Big Endian format */ - union { - uint32_t portNum; - struct lpfc_name portName; - } un; -} RPS; - -typedef struct _RPS_RSP { /* Structure is in Big Endian format */ - uint16_t rsvd1; - uint16_t portStatus; - uint32_t linkFailureCnt; - uint32_t lossSyncCnt; - uint32_t lossSignalCnt; - uint32_t primSeqErrCnt; - uint32_t invalidXmitWord; - uint32_t crcCnt; -} RPS_RSP; - struct RLS { /* Structure is in Big Endian format */ uint32_t rls; #define rls_rsvd_SHIFT 24 @@ -1340,25 +1322,8 @@ struct fc_rdp_res_frame { /* lpfc_sli_ct_request defines the CT_IU preamble for FDMI commands */ #define SLI_CT_FDMI_Subtypes 0x10 /* Management Service Subtype */ -/* - * Registered Port List Format - */ -struct lpfc_fdmi_reg_port_list { - uint32_t EntryCnt; - uint32_t pe; /* Variable-length array */ -}; - - /* Definitions for HBA / Port attribute entries */ -struct lpfc_fdmi_attr_def { /* Defined in TLV format */ - /* Structure is in Big Endian format */ - uint32_t AttrType:16; - uint32_t AttrLen:16; - uint32_t AttrValue; /* Marks start of Value (ATTRIBUTE_ENTRY) */ -}; - - /* Attribute Entry */ struct lpfc_fdmi_attr_entry { union { @@ -1369,7 +1334,13 @@ struct lpfc_fdmi_attr_entry { } un; }; -#define LPFC_FDMI_MAX_AE_SIZE sizeof(struct lpfc_fdmi_attr_entry) +struct lpfc_fdmi_attr_def { /* Defined in TLV format */ + /* Structure is in Big Endian format */ + uint32_t AttrType:16; + uint32_t AttrLen:16; + /* Marks start of Value (ATTRIBUTE_ENTRY) */ + struct lpfc_fdmi_attr_entry AttrValue; +} __packed; /* * HBA Attribute Block @@ -1394,12 +1365,19 @@ struct lpfc_fdmi_hba_ident { }; /* + * Registered Port List Format + */ +struct lpfc_fdmi_reg_port_list { + uint32_t EntryCnt; + struct lpfc_fdmi_port_entry pe; +} __packed; + +/* * Register HBA(RHBA) */ struct lpfc_fdmi_reg_hba { struct lpfc_fdmi_hba_ident hi; - struct lpfc_fdmi_reg_port_list rpl; /* variable-length array */ -/* struct lpfc_fdmi_attr_block ab; */ + struct lpfc_fdmi_reg_port_list rpl; }; /* diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 9a064b96e570..10c5d1c3122e 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -20,6 +20,8 @@ * included with this package. * *******************************************************************/ +#include <uapi/scsi/fc/fc_els.h> + /* Macros to deal with bit fields. Each bit field must have 3 #defines * associated with it (_SHIFT, _MASK, and _WORD). * EG. For a bit field that is in the 7th bit of the "field4" field of a @@ -4795,6 +4797,23 @@ struct send_frame_wqe { uint32_t fc_hdr_wd5; /* word 15 */ }; +#define ELS_RDF_REG_TAG_CNT 1 +struct lpfc_els_rdf_reg_desc { + struct fc_df_desc_fpin_reg reg_desc; /* descriptor header */ + __be32 desc_tags[ELS_RDF_REG_TAG_CNT]; + /* tags in reg_desc */ +}; + +struct lpfc_els_rdf_req { + struct fc_els_rdf rdf; /* hdr up to descriptors */ + struct lpfc_els_rdf_reg_desc reg_d1; /* 1st descriptor */ +}; + +struct lpfc_els_rdf_rsp { + struct fc_els_rdf_resp rdf_resp; /* hdr up to descriptors */ + struct lpfc_els_rdf_reg_desc reg_d1; /* 1st descriptor */ +}; + union lpfc_wqe { uint32_t words[16]; struct lpfc_wqe_generic generic; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 5a605773dd0a..9d03e9b71efb 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -512,21 +512,12 @@ lpfc_config_port_post(struct lpfc_hba *phba) lpfc_sli_read_link_ste(phba); /* Reset the DFT_HBA_Q_DEPTH to the max xri */ - i = (mb->un.varRdConfig.max_xri + 1); - if (phba->cfg_hba_queue_depth > i) { + if (phba->cfg_hba_queue_depth > mb->un.varRdConfig.max_xri) { lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, "3359 HBA queue depth changed from %d to %d\n", - phba->cfg_hba_queue_depth, i); - phba->cfg_hba_queue_depth = i; - } - - /* Reset the DFT_LUN_Q_DEPTH to (max xri >> 3) */ - i = (mb->un.varRdConfig.max_xri >> 3); - if (phba->pport->cfg_lun_queue_depth > i) { - lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, - "3360 LUN queue depth changed from %d to %d\n", - phba->pport->cfg_lun_queue_depth, i); - phba->pport->cfg_lun_queue_depth = i; + phba->cfg_hba_queue_depth, + mb->un.varRdConfig.max_xri); + phba->cfg_hba_queue_depth = mb->un.varRdConfig.max_xri; } phba->lmt = mb->un.varRdConfig.lmt; @@ -9235,6 +9226,7 @@ lpfc_sli4_release_hdwq(struct lpfc_hba *phba) /* Free the CQ/WQ corresponding to the Hardware Queue */ lpfc_sli4_queue_free(hdwq[idx].io_cq); lpfc_sli4_queue_free(hdwq[idx].io_wq); + hdwq[idx].hba_eq = NULL; hdwq[idx].io_cq = NULL; hdwq[idx].io_wq = NULL; if (phba->cfg_xpsgl && !phba->nvmet_support) @@ -11105,15 +11097,19 @@ found_any: * @cpu: cpu going offline * @eqlist: */ -static void +static int lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu, struct list_head *eqlist) { const struct cpumask *maskp; struct lpfc_queue *eq; - cpumask_t tmp; + struct cpumask *tmp; u16 idx; + tmp = kzalloc(cpumask_size(), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + for (idx = 0; idx < phba->cfg_irq_chann; idx++) { maskp = pci_irq_get_affinity(phba->pcidev, idx); if (!maskp) @@ -11123,7 +11119,7 @@ lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu, * then we don't need to poll the eq attached * to it. */ - if (!cpumask_and(&tmp, maskp, cpumask_of(cpu))) + if (!cpumask_and(tmp, maskp, cpumask_of(cpu))) continue; /* get the cpus that are online and are affini- * tized to this irq vector. If the count is @@ -11131,8 +11127,8 @@ lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu, * down this vector. Since this cpu has not * gone offline yet, we need >1. */ - cpumask_and(&tmp, maskp, cpu_online_mask); - if (cpumask_weight(&tmp) > 1) + cpumask_and(tmp, maskp, cpu_online_mask); + if (cpumask_weight(tmp) > 1) continue; /* Now that we have an irq to shutdown, get the eq @@ -11143,6 +11139,8 @@ lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu, eq = phba->sli4_hba.hba_eq_hdl[idx].eq; list_add(&eq->_poll_list, eqlist); } + kfree(tmp); + return 0; } static void __lpfc_cpuhp_remove(struct lpfc_hba *phba) @@ -11313,7 +11311,9 @@ static int lpfc_cpu_offline(unsigned int cpu, struct hlist_node *node) lpfc_irq_rebalance(phba, cpu, true); - lpfc_cpuhp_get_eq(phba, cpu, &eqlist); + retval = lpfc_cpuhp_get_eq(phba, cpu, &eqlist); + if (retval) + return retval; /* start polling on these eq's */ list_for_each_entry_safe(eq, next, &eqlist, _poll_list) { diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 2c7e0b22db2f..0fc9a242bc65 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -671,8 +671,10 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, lpfc_cmd->prot_data_type = 0; #endif tmp = lpfc_get_cmd_rsp_buf_per_hdwq(phba, lpfc_cmd); - if (!tmp) + if (!tmp) { + lpfc_release_io_buf(phba, lpfc_cmd, lpfc_cmd->hdwq); return NULL; + } lpfc_cmd->fcp_cmnd = tmp->fcp_cmnd; lpfc_cmd->fcp_rsp = tmp->fcp_rsp; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 64002b0cb02d..0b26b5c0527e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * @@ -7371,15 +7371,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) phba->vpd.rev.fcphHigh, phba->vpd.rev.fcphLow, phba->vpd.rev.feaLevelHigh, phba->vpd.rev.feaLevelLow); - /* Reset the DFT_LUN_Q_DEPTH to (max xri >> 3) */ - rc = (phba->sli4_hba.max_cfg_param.max_xri >> 3); - if (phba->pport->cfg_lun_queue_depth > rc) { - lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, - "3362 LUN queue depth changed from %d to %d\n", - phba->pport->cfg_lun_queue_depth, rc); - phba->pport->cfg_lun_queue_depth = rc; - } - if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == LPFC_SLI_INTF_IF_TYPE_0) { lpfc_set_features(phba, mboxq, LPFC_SET_UE_RECOVERY); @@ -9468,6 +9459,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { if (pcmd && (*pcmd == ELS_CMD_FLOGI || *pcmd == ELS_CMD_SCR || + *pcmd == ELS_CMD_RDF || *pcmd == ELS_CMD_RSCN_XMT || *pcmd == ELS_CMD_FDISC || *pcmd == ELS_CMD_LOGO || @@ -17950,6 +17942,10 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) list_add_tail(&iocbq->list, &first_iocbq->list); } } + /* Free the sequence's header buffer */ + if (!first_iocbq) + lpfc_in_buf_free(vport->phba, &seq_dmabuf->dbuf); + return first_iocbq; } diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 9563c49f36ab..c4ab006e6ecc 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. 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 "12.6.0.3" +#define LPFC_DRIVER_VERSION "12.6.0.4" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index fd4b5ac6ac5b..babe85d7b537 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -2987,9 +2987,10 @@ megasas_dump_sys_regs(void __iomem *reg_set, char *buf) u32 __iomem *reg = (u32 __iomem *)reg_set; for (i = 0; i < sz / sizeof(u32); i++) { - bytes_wrote += snprintf(loc + bytes_wrote, PAGE_SIZE, - "%08x: %08x\n", (i * 4), - readl(®[i])); + bytes_wrote += scnprintf(loc + bytes_wrote, + PAGE_SIZE - bytes_wrote, + "%08x: %08x\n", (i * 4), + readl(®[i])); } return bytes_wrote; } @@ -8224,8 +8225,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, "return -EBUSY from %s %d cmd 0x%x opcode 0x%x cmd->cmd_status_drv 0x%x\n", __func__, __LINE__, cmd->frame->hdr.cmd, opcode, cmd->cmd_status_drv); - error = -EBUSY; - goto out; + error = -EBUSY; + goto out; } cmd->sync_cmd = 0; diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index c597d544eb39..778d5e6ce385 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -207,7 +207,7 @@ struct fw_event_work { u8 ignore; u16 event; struct kref refcount; - char event_data[0] __aligned(4); + char event_data[] __aligned(4); }; static void fw_event_work_free(struct kref *r) diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 519edc796691..327fdd5ee962 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -394,7 +394,7 @@ struct mvs_info { dma_addr_t bulk_buffer_dma1; #define TRASH_BUCKET_SIZE 0x20000 void *dma_pool; - struct mvs_slot_info slot_info[0]; + struct mvs_slot_info slot_info[]; }; struct mvs_prv_info{ diff --git a/drivers/scsi/mvumi.h b/drivers/scsi/mvumi.h index ec8cc2207536..60d5691fc4ab 100644 --- a/drivers/scsi/mvumi.h +++ b/drivers/scsi/mvumi.h @@ -130,7 +130,7 @@ enum { struct mvumi_hotplug_event { u16 size; u8 dummy[2]; - u8 bitmap[0]; + u8 bitmap[]; }; struct mvumi_driver_event { @@ -290,7 +290,7 @@ struct mvumi_rsp_frame { struct mvumi_ob_data { struct list_head list; - unsigned char data[0]; + unsigned char data[]; }; struct version_info { diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 11a2cb844ecb..f88adab3f913 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -2203,7 +2203,7 @@ static struct script script0 __initdata = { ** Possible data corruption during Memory Write and Invalidate. ** This work-around resets the addressing logic prior to the ** start of the first MOVE of a DATA IN phase. - ** (See Documentation/scsi/ncr53c8xx.txt for more information) + ** (See Documentation/scsi/ncr53c8xx.rst for more information) */ SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)), 20, diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index dc9b74c9348a..9696b6b5591f 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig @@ -36,7 +36,7 @@ config PCMCIA_NINJA_SCSI help If you intend to attach this type of PCMCIA SCSI host adapter to your computer, say Y here and read - <file:Documentation/scsi/NinjaSCSI.txt>. + <file:Documentation/scsi/NinjaSCSI.rst>. Supported cards: diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index 7c6be2ec110d..3c9f42779dd0 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -463,7 +463,7 @@ static ssize_t pm8001_ctl_bios_version_show(struct device *cdev, pm8001_ha->nvmd_completion = &completion; payload.minor_function = 7; payload.offset = 0; - payload.length = 4096; + payload.rd_length = 4096; payload.func_specific = kzalloc(4096, GFP_KERNEL); if (!payload.func_specific) return -ENOMEM; @@ -554,6 +554,49 @@ static ssize_t pm8001_ctl_fatal_log_show(struct device *cdev, static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL); +/** + ** non_fatal_log_show - non fatal error logging + ** @cdev:pointer to embedded class device + ** @buf: the buffer returned + ** + ** A sysfs 'read-only' shost attribute. + **/ +static ssize_t non_fatal_log_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + u32 count; + + count = pm80xx_get_non_fatal_dump(cdev, attr, buf); + return count; +} +static DEVICE_ATTR_RO(non_fatal_log); + +static ssize_t non_fatal_count_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); + struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; + + return snprintf(buf, PAGE_SIZE, "%08x", + pm8001_ha->non_fatal_count); +} + +static ssize_t non_fatal_count_store(struct device *cdev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); + struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; + int val = 0; + + if (kstrtoint(buf, 16, &val) != 0) + return -EINVAL; + + pm8001_ha->non_fatal_count = val; + return strlen(buf); +} +static DEVICE_ATTR_RW(non_fatal_count); /** ** pm8001_ctl_gsm_log_show - gsm dump collection @@ -631,7 +674,7 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) payload = (struct pm8001_ioctl_payload *)ioctlbuffer; memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data, pm8001_ha->fw_image->size); - payload->length = pm8001_ha->fw_image->size; + payload->wr_length = pm8001_ha->fw_image->size; payload->id = 0; payload->minor_function = 0x1; pm8001_ha->nvmd_completion = &completion; @@ -677,7 +720,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) IOCTL_BUF_SIZE); for (loopNumber = 0; loopNumber < loopcount; loopNumber++) { payload = (struct pm8001_ioctl_payload *)ioctlbuffer; - payload->length = 1024*16; + payload->wr_length = 1024*16; payload->id = 0; fwControl = (struct fw_control_info *)&payload->func_specific; @@ -829,6 +872,8 @@ struct device_attribute *pm8001_host_attrs[] = { &dev_attr_aap_log, &dev_attr_iop_log, &dev_attr_fatal_log, + &dev_attr_non_fatal_log, + &dev_attr_non_fatal_count, &dev_attr_gsm_log, &dev_attr_max_out_io, &dev_attr_max_devices, diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index 48e0624ecc68..1c7f15fd69ce 100644 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h @@ -75,7 +75,7 @@ enum port_type { }; /* driver compile-time configuration */ -#define PM8001_MAX_CCB 512 /* max ccbs supported */ +#define PM8001_MAX_CCB 256 /* max ccbs supported */ #define PM8001_MPI_QUEUE 1024 /* maximum mpi queue entries */ #define PM8001_MAX_INB_NUM 1 #define PM8001_MAX_OUTB_NUM 1 @@ -99,7 +99,8 @@ enum port_type { #define OB (CI + PM8001_MAX_SPCV_INB_NUM) #define PI (OB + PM8001_MAX_SPCV_OUTB_NUM) #define USI_MAX_MEMCNT (PI + PM8001_MAX_SPCV_OUTB_NUM) -#define PM8001_MAX_DMA_SG SG_ALL +#define CONFIG_SCSI_PM8001_MAX_DMA_SG 528 +#define PM8001_MAX_DMA_SG CONFIG_SCSI_PM8001_MAX_DMA_SG enum memory_region_num { AAP1 = 0x0, /* application acceleration processor */ IOP, /* IO processor */ diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 2328ff1349ac..fb9848e1d481 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -4793,7 +4793,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, if (!fw_control_context) return -ENOMEM; fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific; - fw_control_context->len = ioctl_payload->length; + fw_control_context->len = ioctl_payload->rd_length; circularQ = &pm8001_ha->inbnd_q_tbl[0]; memset(&nvmd_req, 0, sizeof(nvmd_req)); rc = pm8001_tag_alloc(pm8001_ha, &tag); @@ -4814,7 +4814,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | twi_addr << 16 | twi_page_size << 8 | TWI_DEVICE); - nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); + nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length); nvmd_req.resp_addr_hi = cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); nvmd_req.resp_addr_lo = @@ -4823,7 +4823,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, } case C_SEEPROM: { nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | C_SEEPROM); - nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); + nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length); nvmd_req.resp_addr_hi = cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); nvmd_req.resp_addr_lo = @@ -4832,7 +4832,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, } case VPD_FLASH: { nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | VPD_FLASH); - nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); + nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length); nvmd_req.resp_addr_hi = cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); nvmd_req.resp_addr_lo = @@ -4841,7 +4841,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, } case EXPAN_ROM: { nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | EXPAN_ROM); - nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); + nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length); nvmd_req.resp_addr_hi = cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); nvmd_req.resp_addr_lo = @@ -4850,7 +4850,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, } case IOP_RDUMP: { nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | IOP_RDUMP); - nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); + nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length); nvmd_req.vpd_offset = cpu_to_le32(ioctl_payload->offset); nvmd_req.resp_addr_hi = cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); @@ -4890,7 +4890,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, circularQ = &pm8001_ha->inbnd_q_tbl[0]; memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr, &ioctl_payload->func_specific, - ioctl_payload->length); + ioctl_payload->wr_length); memset(&nvmd_req, 0, sizeof(nvmd_req)); rc = pm8001_tag_alloc(pm8001_ha, &tag); if (rc) { @@ -4909,7 +4909,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98); nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | twi_addr << 16 | twi_page_size << 8 | TWI_DEVICE); - nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); + nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length); nvmd_req.resp_addr_hi = cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); nvmd_req.resp_addr_lo = @@ -4918,7 +4918,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, } case C_SEEPROM: nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | C_SEEPROM); - nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); + nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length); nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98); nvmd_req.resp_addr_hi = cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); @@ -4927,7 +4927,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, break; case VPD_FLASH: nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | VPD_FLASH); - nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); + nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length); nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98); nvmd_req.resp_addr_hi = cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); @@ -4936,7 +4936,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, break; case EXPAN_ROM: nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | EXPAN_ROM); - nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); + nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length); nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98); nvmd_req.resp_addr_hi = cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 3c6076e4c6d2..a8f5344fdfda 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -95,7 +95,7 @@ static struct scsi_host_template pm8001_sht = { .bios_param = sas_bios_param, .can_queue = 1, .this_id = -1, - .sg_tablesize = SG_ALL, + .sg_tablesize = PM8001_MAX_DMA_SG, .max_sectors = SCSI_DEFAULT_MAX_SECTORS, .eh_device_reset_handler = sas_eh_device_reset_handler, .eh_target_reset_handler = sas_eh_target_reset_handler, @@ -251,6 +251,9 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id) return ret; } +static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha); +static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha); + /** * pm8001_alloc - initiate our hba structure and 6 DMAs area. * @pm8001_ha:our hba structure. @@ -483,6 +486,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, pm8001_ha->shost = shost; pm8001_ha->id = pm8001_id++; pm8001_ha->logging_level = logging_level; + pm8001_ha->non_fatal_count = 0; if (link_rate >= 1 && link_rate <= 15) pm8001_ha->link_rate = (link_rate << 8); else { @@ -635,22 +639,22 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) if (pm8001_ha->chip_id == chip_8001) { if (deviceid == 0x8081 || deviceid == 0x0042) { payload.minor_function = 4; - payload.length = 4096; + payload.rd_length = 4096; } else { payload.minor_function = 0; - payload.length = 128; + payload.rd_length = 128; } } else if ((pm8001_ha->chip_id == chip_8070 || pm8001_ha->chip_id == chip_8072) && pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) { payload.minor_function = 4; - payload.length = 4096; + payload.rd_length = 4096; } else { payload.minor_function = 1; - payload.length = 4096; + payload.rd_length = 4096; } payload.offset = 0; - payload.func_specific = kzalloc(payload.length, GFP_KERNEL); + payload.func_specific = kzalloc(payload.rd_length, GFP_KERNEL); if (!payload.func_specific) { PM8001_INIT_DBG(pm8001_ha, pm8001_printk("mem alloc fail\n")); return; @@ -720,7 +724,7 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) /* SAS ADDRESS read from flash / EEPROM */ payload.minor_function = 6; payload.offset = 0; - payload.length = 4096; + payload.rd_length = 4096; payload.func_specific = kzalloc(4096, GFP_KERNEL); if (!payload.func_specific) return -ENOMEM; @@ -893,9 +897,7 @@ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha) */ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) { - u32 i = 0, j = 0; u32 number_of_intr; - int flag = 0; int rc; /* SPCv controllers supports 64 msi-x */ @@ -903,11 +905,11 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) number_of_intr = 1; } else { number_of_intr = PM8001_MAX_MSIX_VEC; - flag &= ~IRQF_SHARED; } rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr, number_of_intr, PCI_IRQ_MSIX); + number_of_intr = rc; if (rc < 0) return rc; pm8001_ha->number_of_intr = number_of_intr; @@ -915,8 +917,22 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) PM8001_INIT_DBG(pm8001_ha, pm8001_printk( "pci_alloc_irq_vectors request ret:%d no of intr %d\n", rc, pm8001_ha->number_of_intr)); + return 0; +} - for (i = 0; i < number_of_intr; i++) { +static u32 pm8001_request_msix(struct pm8001_hba_info *pm8001_ha) +{ + u32 i = 0, j = 0; + int flag = 0, rc = 0; + + if (pm8001_ha->chip_id != chip_8001) + flag &= ~IRQF_SHARED; + + PM8001_INIT_DBG(pm8001_ha, + pm8001_printk("pci_enable_msix request number of intr %d\n", + pm8001_ha->number_of_intr)); + + for (i = 0; i < pm8001_ha->number_of_intr; i++) { snprintf(pm8001_ha->intr_drvname[i], sizeof(pm8001_ha->intr_drvname[0]), "%s-%d", pm8001_ha->name, i); @@ -941,6 +957,21 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) } #endif +static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha) +{ + struct pci_dev *pdev; + + pdev = pm8001_ha->pdev; + +#ifdef PM8001_USE_MSIX + if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) + return pm8001_setup_msix(pm8001_ha); + PM8001_INIT_DBG(pm8001_ha, + pm8001_printk("MSIX not supported!!!\n")); +#endif + return 0; +} + /** * pm8001_request_irq - register interrupt * @chip_info: our ha struct. @@ -954,7 +985,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) #ifdef PM8001_USE_MSIX if (pdev->msix_cap && pci_msi_enabled()) - return pm8001_setup_msix(pm8001_ha); + return pm8001_request_msix(pm8001_ha); else { PM8001_INIT_DBG(pm8001_ha, pm8001_printk("MSIX not supported!!!\n")); @@ -989,6 +1020,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev, struct pm8001_hba_info *pm8001_ha; struct Scsi_Host *shost = NULL; const struct pm8001_chip_info *chip; + struct sas_ha_struct *sha; dev_printk(KERN_INFO, &pdev->dev, "pm80xx: driver version %s\n", DRV_VERSION); @@ -1017,12 +1049,12 @@ static int pm8001_pci_probe(struct pci_dev *pdev, goto err_out_regions; } chip = &pm8001_chips[ent->driver_data]; - SHOST_TO_SAS_HA(shost) = - kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL); - if (!SHOST_TO_SAS_HA(shost)) { + sha = kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL); + if (!sha) { rc = -ENOMEM; goto err_out_free_host; } + SHOST_TO_SAS_HA(shost) = sha; rc = pm8001_prep_sas_ha_init(shost, chip); if (rc) { @@ -1036,7 +1068,14 @@ static int pm8001_pci_probe(struct pci_dev *pdev, rc = -ENOMEM; goto err_out_free; } - list_add_tail(&pm8001_ha->list, &hba_list); + /* Setup Interrupt */ + rc = pm8001_setup_irq(pm8001_ha); + if (rc) { + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( + "pm8001_setup_irq failed [ret: %d]\n", rc)); + goto err_out_shost; + } + PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); if (rc) { @@ -1048,6 +1087,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev, rc = scsi_add_host(shost, &pdev->dev); if (rc) goto err_out_ha_free; + /* Request Interrupt */ rc = pm8001_request_irq(pm8001_ha); if (rc) { PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( @@ -1070,8 +1110,12 @@ static int pm8001_pci_probe(struct pci_dev *pdev, pm8001_post_sas_ha_init(shost, chip); rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); - if (rc) + if (rc) { + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( + "sas_register_ha failed [ret: %d]\n", rc)); goto err_out_shost; + } + list_add_tail(&pm8001_ha->list, &hba_list); scsi_scan_host(pm8001_ha->shost); pm8001_ha->flags = PM8001F_RUN_TIME; return 0; @@ -1081,7 +1125,7 @@ err_out_shost: err_out_ha_free: pm8001_free(pm8001_ha); err_out_free: - kfree(SHOST_TO_SAS_HA(shost)); + kfree(sha); err_out_free_host: scsi_host_put(shost); err_out_regions: diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 93438c8f67da..ae7ba9b3c4bc 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -137,10 +137,11 @@ struct pm8001_ioctl_payload { u32 signature; u16 major_function; u16 minor_function; - u16 length; u16 status; u16 offset; u16 id; + u32 wr_length; + u32 rd_length; u8 *func_specific; }; @@ -558,6 +559,8 @@ struct pm8001_hba_info { const struct firmware *fw_image; struct isr_param irq_vector[PM8001_MAX_MSIX_VEC]; u32 reset_in_progress; + u32 non_fatal_count; + u32 non_fatal_read_length; }; struct pm8001_work { @@ -741,6 +744,8 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); ssize_t pm80xx_get_fatal_dump(struct device *cdev, struct device_attribute *attr, char *buf); +ssize_t pm80xx_get_non_fatal_dump(struct device *cdev, + struct device_attribute *attr, char *buf); ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf); /* ctl shared API */ extern struct device_attribute *pm8001_host_attrs[]; diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index d1d95f1a2c6a..4d205ebaee87 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -393,6 +393,136 @@ moreData: (char *)buf; } +/* pm80xx_get_non_fatal_dump - dump the nonfatal data from the dma + * location by the firmware. + */ +ssize_t pm80xx_get_non_fatal_dump(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); + struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; + void __iomem *nonfatal_table_address = pm8001_ha->fatal_tbl_addr; + u32 accum_len = 0; + u32 total_len = 0; + u32 reg_val = 0; + u32 *temp = NULL; + u32 index = 0; + u32 output_length; + unsigned long start = 0; + char *buf_copy = buf; + + temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr; + if (++pm8001_ha->non_fatal_count == 1) { + if (pm8001_ha->chip_id == chip_8001) { + snprintf(pm8001_ha->forensic_info.data_buf.direct_data, + PAGE_SIZE, "Not supported for SPC controller"); + return 0; + } + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("forensic_info TYPE_NON_FATAL...\n")); + /* + * Step 1: Write the host buffer parameters in the MPI Fatal and + * Non-Fatal Error Dump Capture Table.This is the buffer + * where debug data will be DMAed to. + */ + pm8001_mw32(nonfatal_table_address, + MPI_FATAL_EDUMP_TABLE_LO_OFFSET, + pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_lo); + + pm8001_mw32(nonfatal_table_address, + MPI_FATAL_EDUMP_TABLE_HI_OFFSET, + pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_hi); + + pm8001_mw32(nonfatal_table_address, + MPI_FATAL_EDUMP_TABLE_LENGTH, SYSFS_OFFSET); + + /* Optionally, set the DUMPCTRL bit to 1 if the host + * keeps sending active I/Os while capturing the non-fatal + * debug data. Otherwise, leave this bit set to zero + */ + pm8001_mw32(nonfatal_table_address, + MPI_FATAL_EDUMP_TABLE_HANDSHAKE, MPI_FATAL_EDUMP_HANDSHAKE_RDY); + + /* + * Step 2: Clear Accumulative Length of Debug Data Transferred + * [ACCDDLEN] field in the MPI Fatal and Non-Fatal Error Dump + * Capture Table to zero. + */ + pm8001_mw32(nonfatal_table_address, + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN, 0); + + /* initiallize previous accumulated length to 0 */ + pm8001_ha->forensic_preserved_accumulated_transfer = 0; + pm8001_ha->non_fatal_read_length = 0; + } + + total_len = pm8001_mr32(nonfatal_table_address, + MPI_FATAL_EDUMP_TABLE_TOTAL_LEN); + /* + * Step 3:Clear Fatal/Non-Fatal Debug Data Transfer Status [FDDTSTAT] + * field and then request that the SPCv controller transfer the debug + * data by setting bit 7 of the Inbound Doorbell Set Register. + */ + pm8001_mw32(nonfatal_table_address, MPI_FATAL_EDUMP_TABLE_STATUS, 0); + pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, + SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP); + + /* + * Step 4.1: Read back the Inbound Doorbell Set Register (by polling for + * 2 seconds) until register bit 7 is cleared. + * This step only indicates the request is accepted by the controller. + */ + start = jiffies + (2 * HZ); /* 2 sec */ + do { + reg_val = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET) & + SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP; + } while ((reg_val != 0) && time_before(jiffies, start)); + + /* Step 4.2: To check the completion of the transfer, poll the Fatal/Non + * Fatal Debug Data Transfer Status [FDDTSTAT] field for 2 seconds in + * the MPI Fatal and Non-Fatal Error Dump Capture Table. + */ + start = jiffies + (2 * HZ); /* 2 sec */ + do { + reg_val = pm8001_mr32(nonfatal_table_address, + MPI_FATAL_EDUMP_TABLE_STATUS); + } while ((!reg_val) && time_before(jiffies, start)); + + if ((reg_val == 0x00) || + (reg_val == MPI_FATAL_EDUMP_TABLE_STAT_DMA_FAILED) || + (reg_val > MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE)) { + pm8001_ha->non_fatal_read_length = 0; + buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 0xFFFFFFFF); + pm8001_ha->non_fatal_count = 0; + return (buf_copy - buf); + } else if (reg_val == + MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_MORE_DATA) { + buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 2); + } else if ((reg_val == MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) || + (pm8001_ha->non_fatal_read_length >= total_len)) { + pm8001_ha->non_fatal_read_length = 0; + buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 4); + pm8001_ha->non_fatal_count = 0; + } + accum_len = pm8001_mr32(nonfatal_table_address, + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN); + output_length = accum_len - + pm8001_ha->forensic_preserved_accumulated_transfer; + + for (index = 0; index < output_length/4; index++) + buf_copy += snprintf(buf_copy, PAGE_SIZE, + "%08x ", *(temp+index)); + + pm8001_ha->non_fatal_read_length += output_length; + + /* store current accumulated length to use in next iteration as + * the previous accumulated length + */ + pm8001_ha->forensic_preserved_accumulated_transfer = accum_len; + return (buf_copy - buf); +} + /** * read_main_config_table - read the configure table and save it. * @pm8001_ha: our hba card information @@ -1438,11 +1568,18 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) if (!pm8001_ha->controller_fatal_error) { /* Check if MPI is in ready state to reset */ if (mpi_uninit_check(pm8001_ha) != 0) { - regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); + u32 r0 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0); + u32 r1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); + u32 r2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2); + u32 r3 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "MPI state is not ready scratch1 :0x%x\n", - regval)); - return -1; + "MPI state is not ready scratch: %x:%x:%x:%x\n", + r0, r1, r2, r3)); + /* if things aren't ready but the bootloader is ok then + * try the reset anyway. + */ + if (r1 & SCRATCH_PAD1_BOOTSTATE_MASK) + return -1; } } /* checked for reset register normal state; 0x0 */ @@ -3708,28 +3845,32 @@ static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) { + u32 tag; u8 page_code; + int rc = 0; struct set_phy_profile_resp *pPayload = (struct set_phy_profile_resp *)(piomb + 4); u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid); u32 status = le32_to_cpu(pPayload->status); + tag = le32_to_cpu(pPayload->tag); page_code = (u8)((ppc_phyid & 0xFF00) >> 8); if (status) { /* status is FAILED */ PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("PhyProfile command failed with status " "0x%08X \n", status)); - return -1; + rc = -1; } else { if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) { PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Invalid page code 0x%X\n", page_code)); - return -1; + rc = -1; } } - return 0; + pm8001_tag_free(pm8001_ha, tag); + return rc; } /** diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index a4f7eb8f50a3..15c962108075 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h @@ -623,7 +623,7 @@ struct pmcraid_aen_msg { u32 hostno; u32 length; u8 reserved[8]; - u8 data[0]; + u8 data[]; }; /* Controller state event message type */ diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h index 9513fd320ffd..9498279ae80d 100644 --- a/drivers/scsi/qedi/qedi.h +++ b/drivers/scsi/qedi/qedi.h @@ -36,6 +36,7 @@ struct qedi_endpoint; */ #define QEDI_MODE_NORMAL 0 #define QEDI_MODE_RECOVERY 1 +#define QEDI_MODE_SHUTDOWN 2 #define ISCSI_WQE_SET_PTU_INVALIDATE 1 #define QEDI_MAX_ISCSI_TASK 4096 @@ -278,6 +279,7 @@ struct qedi_ctx { #define QEDI_IOTHREAD_WAKE 2 #define QEDI_IN_RECOVERY 5 #define QEDI_IN_OFFLINE 6 +#define QEDI_IN_SHUTDOWN 7 u8 mac[ETH_ALEN]; u32 src_ip[4]; @@ -331,6 +333,7 @@ struct qedi_ctx { u16 ll2_mtu; struct workqueue_struct *dpc_wq; + struct delayed_work recovery_work; spinlock_t task_idx_lock; /* To protect gbl context */ s32 last_tidx_alloc; diff --git a/drivers/scsi/qedi/qedi_gbl.h b/drivers/scsi/qedi/qedi_gbl.h index 8ba7c771ce4d..116645c08c71 100644 --- a/drivers/scsi/qedi/qedi_gbl.h +++ b/drivers/scsi/qedi/qedi_gbl.h @@ -73,5 +73,6 @@ void qedi_remove_sysfs_ctx_attr(struct qedi_ctx *qedi); void qedi_clearsq(struct qedi_ctx *qedi, struct qedi_conn *qedi_conn, struct iscsi_task *task); +void qedi_clear_session_ctx(struct iscsi_cls_session *cls_sess); #endif diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 8829880a54c3..1f4a5fb00a05 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -392,6 +392,7 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session, qedi_ep->conn = qedi_conn; qedi_conn->ep = qedi_ep; + qedi_conn->iscsi_ep = ep; qedi_conn->iscsi_conn_id = qedi_ep->iscsi_cid; qedi_conn->fw_cid = qedi_ep->fw_cid; qedi_conn->cmd_cleanup_req = 0; @@ -782,6 +783,9 @@ static int qedi_task_xmit(struct iscsi_task *task) struct qedi_cmd *cmd = task->dd_data; struct scsi_cmnd *sc = task->sc; + if (test_bit(QEDI_IN_SHUTDOWN, &qedi_conn->qedi->flags)) + return -ENODEV; + cmd->state = 0; cmd->task = NULL; cmd->use_slowpath = false; @@ -1596,6 +1600,20 @@ void qedi_process_iscsi_error(struct qedi_endpoint *ep, qedi_start_conn_recovery(qedi_conn->qedi, qedi_conn); } +void qedi_clear_session_ctx(struct iscsi_cls_session *cls_sess) +{ + struct iscsi_session *session = cls_sess->dd_data; + struct iscsi_conn *conn = session->leadconn; + struct qedi_conn *qedi_conn = conn->dd_data; + + if (iscsi_is_session_online(cls_sess)) + qedi_ep_disconnect(qedi_conn->iscsi_ep); + + qedi_conn_destroy(qedi_conn->cls_conn); + + qedi_session_destroy(cls_sess); +} + void qedi_process_tcp_error(struct qedi_endpoint *ep, struct iscsi_eqe_data *data) { diff --git a/drivers/scsi/qedi/qedi_iscsi.h b/drivers/scsi/qedi/qedi_iscsi.h index 67c3b7349271..39dc27c85e3c 100644 --- a/drivers/scsi/qedi/qedi_iscsi.h +++ b/drivers/scsi/qedi/qedi_iscsi.h @@ -149,6 +149,7 @@ struct qedi_conn { struct iscsi_cls_conn *cls_conn; struct qedi_ctx *qedi; struct qedi_endpoint *ep; + struct iscsi_endpoint *iscsi_ep; struct list_head active_cmd_list; spinlock_t list_lock; /* internal conn lock */ u32 active_cmd_count; diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index acb930b8c6a6..b995b19865ca 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -58,6 +58,7 @@ static struct qedi_cmd *qedi_get_cmd_from_tid(struct qedi_ctx *qedi, u32 tid); static void qedi_reset_uio_rings(struct qedi_uio_dev *udev); static void qedi_ll2_free_skbs(struct qedi_ctx *qedi); static struct nvm_iscsi_block *qedi_get_nvram_block(struct qedi_ctx *qedi); +static void qedi_recovery_handler(struct work_struct *work); static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle) { @@ -1113,6 +1114,20 @@ exit_get_data: return; } +static void qedi_schedule_recovery_handler(void *dev) +{ + struct qedi_ctx *qedi = dev; + + QEDI_ERR(&qedi->dbg_ctx, "Recovery handler scheduled.\n"); + + if (test_and_set_bit(QEDI_IN_RECOVERY, &qedi->flags)) + return; + + atomic_set(&qedi->link_state, QEDI_LINK_DOWN); + + schedule_delayed_work(&qedi->recovery_work, 0); +} + static void qedi_link_update(void *dev, struct qed_link_output *link) { struct qedi_ctx *qedi = (struct qedi_ctx *)dev; @@ -1130,6 +1145,7 @@ static void qedi_link_update(void *dev, struct qed_link_output *link) static struct qed_iscsi_cb_ops qedi_cb_ops = { { .link_update = qedi_link_update, + .schedule_recovery_handler = qedi_schedule_recovery_handler, .get_protocol_tlv_data = qedi_get_protocol_tlv_data, .get_generic_tlv_data = qedi_get_generic_tlv_data, } @@ -2328,16 +2344,22 @@ static void __qedi_remove(struct pci_dev *pdev, int mode) struct qedi_ctx *qedi = pci_get_drvdata(pdev); int rval; - if (qedi->tmf_thread) { - flush_workqueue(qedi->tmf_thread); - destroy_workqueue(qedi->tmf_thread); - qedi->tmf_thread = NULL; - } + if (mode == QEDI_MODE_SHUTDOWN) + iscsi_host_for_each_session(qedi->shost, + qedi_clear_session_ctx); + + if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) { + if (qedi->tmf_thread) { + flush_workqueue(qedi->tmf_thread); + destroy_workqueue(qedi->tmf_thread); + qedi->tmf_thread = NULL; + } - if (qedi->offload_thread) { - flush_workqueue(qedi->offload_thread); - destroy_workqueue(qedi->offload_thread); - qedi->offload_thread = NULL; + if (qedi->offload_thread) { + flush_workqueue(qedi->offload_thread); + destroy_workqueue(qedi->offload_thread); + qedi->offload_thread = NULL; + } } #ifdef CONFIG_DEBUG_FS @@ -2353,8 +2375,7 @@ static void __qedi_remove(struct pci_dev *pdev, int mode) qedi_ops->ll2->stop(qedi->cdev); } - if (mode == QEDI_MODE_NORMAL) - qedi_free_iscsi_pf_param(qedi); + qedi_free_iscsi_pf_param(qedi); rval = qedi_ops->common->update_drv_state(qedi->cdev, false); if (rval) @@ -2367,15 +2388,12 @@ static void __qedi_remove(struct pci_dev *pdev, int mode) qedi_destroy_fp(qedi); - if (mode == QEDI_MODE_NORMAL) { + if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) { qedi_release_cid_que(qedi); qedi_cm_free_mem(qedi); qedi_free_uio(qedi->udev); qedi_free_itt(qedi); - iscsi_host_remove(qedi->shost); - iscsi_host_free(qedi->shost); - if (qedi->ll2_recv_thread) { kthread_stop(qedi->ll2_recv_thread); qedi->ll2_recv_thread = NULL; @@ -2384,9 +2402,22 @@ static void __qedi_remove(struct pci_dev *pdev, int mode) if (qedi->boot_kset) iscsi_boot_destroy_kset(qedi->boot_kset); + + iscsi_host_remove(qedi->shost); + iscsi_host_free(qedi->shost); } } +static void qedi_shutdown(struct pci_dev *pdev) +{ + struct qedi_ctx *qedi = pci_get_drvdata(pdev); + + QEDI_ERR(&qedi->dbg_ctx, "%s: Shutdown qedi\n", __func__); + if (test_and_set_bit(QEDI_IN_SHUTDOWN, &qedi->flags)) + return; + __qedi_remove(pdev, QEDI_MODE_SHUTDOWN); +} + static int __qedi_probe(struct pci_dev *pdev, int mode) { struct qedi_ctx *qedi; @@ -2435,14 +2466,12 @@ static int __qedi_probe(struct pci_dev *pdev, int mode) qedi->dev_info.common.num_hwfns, qedi_ops->common->get_affin_hwfn_idx(qedi->cdev)); - if (mode != QEDI_MODE_RECOVERY) { - rc = qedi_set_iscsi_pf_param(qedi); - if (rc) { - rc = -ENOMEM; - QEDI_ERR(&qedi->dbg_ctx, - "Set iSCSI pf param fail\n"); - goto free_host; - } + rc = qedi_set_iscsi_pf_param(qedi); + if (rc) { + rc = -ENOMEM; + QEDI_ERR(&qedi->dbg_ctx, + "Set iSCSI pf param fail\n"); + goto free_host; } qedi_ops->common->update_pf_params(qedi->cdev, &qedi->pf_params); @@ -2633,6 +2662,8 @@ static int __qedi_probe(struct pci_dev *pdev, int mode) goto free_cid_que; } + INIT_DELAYED_WORK(&qedi->recovery_work, qedi_recovery_handler); + /* F/w needs 1st task context memory entry for performance */ set_bit(QEDI_RESERVE_TASK_ID, qedi->task_idx_map); atomic_set(&qedi->num_offloads, 0); @@ -2673,6 +2704,32 @@ exit_probe: return rc; } +static void qedi_mark_conn_recovery(struct iscsi_cls_session *cls_session) +{ + struct iscsi_session *session = cls_session->dd_data; + struct iscsi_conn *conn = session->leadconn; + struct qedi_conn *qedi_conn = conn->dd_data; + + iscsi_conn_failure(qedi_conn->cls_conn->dd_data, ISCSI_ERR_CONN_FAILED); +} + +static void qedi_recovery_handler(struct work_struct *work) +{ + struct qedi_ctx *qedi = + container_of(work, struct qedi_ctx, recovery_work.work); + + iscsi_host_for_each_session(qedi->shost, qedi_mark_conn_recovery); + + /* Call common_ops->recovery_prolog to allow the MFW to quiesce + * any PCI transactions. + */ + qedi_ops->common->recovery_prolog(qedi->cdev); + + __qedi_remove(qedi->pdev, QEDI_MODE_RECOVERY); + __qedi_probe(qedi->pdev, QEDI_MODE_RECOVERY); + clear_bit(QEDI_IN_RECOVERY, &qedi->flags); +} + static int qedi_probe(struct pci_dev *pdev, const struct pci_device_id *id) { return __qedi_probe(pdev, QEDI_MODE_NORMAL); @@ -2697,6 +2754,7 @@ static struct pci_driver qedi_pci_driver = { .id_table = qedi_pci_tbl, .probe = qedi_probe, .remove = qedi_remove, + .shutdown = qedi_shutdown, }; static int __init qedi_init(void) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index d7e7043f9eab..97cabd7e0014 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1324,6 +1324,79 @@ qla2x00_beacon_store(struct device *dev, struct device_attribute *attr, } static ssize_t +qla2x00_beacon_config_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + uint16_t led[3] = { 0 }; + + if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return -EPERM; + + if (ql26xx_led_config(vha, 0, led)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%#04hx %#04hx %#04hx\n", + led[0], led[1], led[2]); +} + +static ssize_t +qla2x00_beacon_config_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + uint16_t options = BIT_0; + uint16_t led[3] = { 0 }; + uint16_t word[4]; + int n; + + if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return -EPERM; + + n = sscanf(buf, "%hx %hx %hx %hx", word+0, word+1, word+2, word+3); + if (n == 4) { + if (word[0] == 3) { + options |= BIT_3|BIT_2|BIT_1; + led[0] = word[1]; + led[1] = word[2]; + led[2] = word[3]; + goto write; + } + return -EINVAL; + } + + if (n == 2) { + /* check led index */ + if (word[0] == 0) { + options |= BIT_2; + led[0] = word[1]; + goto write; + } + if (word[0] == 1) { + options |= BIT_3; + led[1] = word[1]; + goto write; + } + if (word[0] == 2) { + options |= BIT_1; + led[2] = word[1]; + goto write; + } + return -EINVAL; + } + + return -EINVAL; + +write: + if (ql26xx_led_config(vha, options, led)) + return -EFAULT; + + return count; +} + +static ssize_t qla2x00_optrom_bios_version_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -2250,6 +2323,26 @@ qla2x00_port_no_show(struct device *dev, struct device_attribute *attr, return scnprintf(buf, PAGE_SIZE, "%u\n", vha->hw->port_no); } +static ssize_t +qla2x00_dport_diagnostics_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + + if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && + !IS_QLA28XX(vha->hw)) + return scnprintf(buf, PAGE_SIZE, "\n"); + + if (!*vha->dport_data) + return scnprintf(buf, PAGE_SIZE, "\n"); + + return scnprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", + vha->dport_data[0], vha->dport_data[1], + vha->dport_data[2], vha->dport_data[3]); +} +static DEVICE_ATTR(dport_diagnostics, 0444, + qla2x00_dport_diagnostics_show, NULL); + static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_version_show, NULL); static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); @@ -2264,6 +2357,8 @@ static DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, qla2x00_zio_timer_store); static DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, qla2x00_beacon_store); +static DEVICE_ATTR(beacon_config, 0644, qla2x00_beacon_config_show, + qla2x00_beacon_config_store); static DEVICE_ATTR(optrom_bios_version, S_IRUGO, qla2x00_optrom_bios_version_show, NULL); static DEVICE_ATTR(optrom_efi_version, S_IRUGO, @@ -2327,6 +2422,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_zio, &dev_attr_zio_timer, &dev_attr_beacon, + &dev_attr_beacon_config, &dev_attr_optrom_bios_version, &dev_attr_optrom_efi_version, &dev_attr_optrom_fcode_version, @@ -2355,6 +2451,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_port_speed, &dev_attr_port_no, &dev_attr_fw_attr, + &dev_attr_dport_diagnostics, NULL, /* reserve for qlini_mode */ NULL, /* reserve for ql2xiniexchg */ NULL, /* reserve for ql2xexchoffld */ @@ -2648,22 +2745,28 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) if (rval != QLA_SUCCESS) goto done_free; - p->link_failure_count = stats->link_fail_cnt; - p->loss_of_sync_count = stats->loss_sync_cnt; - p->loss_of_signal_count = stats->loss_sig_cnt; - p->prim_seq_protocol_err_count = stats->prim_seq_err_cnt; - p->invalid_tx_word_count = stats->inval_xmit_word_cnt; - p->invalid_crc_count = stats->inval_crc_cnt; + p->link_failure_count = le32_to_cpu(stats->link_fail_cnt); + p->loss_of_sync_count = le32_to_cpu(stats->loss_sync_cnt); + p->loss_of_signal_count = le32_to_cpu(stats->loss_sig_cnt); + p->prim_seq_protocol_err_count = le32_to_cpu(stats->prim_seq_err_cnt); + p->invalid_tx_word_count = le32_to_cpu(stats->inval_xmit_word_cnt); + p->invalid_crc_count = le32_to_cpu(stats->inval_crc_cnt); if (IS_FWI2_CAPABLE(ha)) { - p->lip_count = stats->lip_cnt; - p->tx_frames = stats->tx_frames; - p->rx_frames = stats->rx_frames; - p->dumped_frames = stats->discarded_frames; - p->nos_count = stats->nos_rcvd; + p->lip_count = le32_to_cpu(stats->lip_cnt); + p->tx_frames = le32_to_cpu(stats->tx_frames); + p->rx_frames = le32_to_cpu(stats->rx_frames); + p->dumped_frames = le32_to_cpu(stats->discarded_frames); + p->nos_count = le32_to_cpu(stats->nos_rcvd); p->error_frames = - stats->dropped_frames + stats->discarded_frames; - p->rx_words = vha->qla_stats.input_bytes; - p->tx_words = vha->qla_stats.output_bytes; + le32_to_cpu(stats->dropped_frames) + + le32_to_cpu(stats->discarded_frames); + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + p->rx_words = le64_to_cpu(stats->fpm_recv_word_cnt); + p->tx_words = le64_to_cpu(stats->fpm_xmit_word_cnt); + } else { + p->rx_words = vha->qla_stats.input_bytes; + p->tx_words = vha->qla_stats.output_bytes; + } } p->fcp_control_requests = vha->qla_stats.control_requests; p->fcp_input_requests = vha->qla_stats.input_requests; @@ -2671,7 +2774,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) p->fcp_input_megabytes = vha->qla_stats.input_bytes >> 20; p->fcp_output_megabytes = vha->qla_stats.output_bytes >> 20; p->seconds_since_last_reset = - get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset; + get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset; do_div(p->seconds_since_last_reset, HZ); done_free: diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index d7169e43f5e1..97b51c477972 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -11,6 +11,14 @@ #include <linux/delay.h> #include <linux/bsg-lib.h> +static void qla2xxx_free_fcport_work(struct work_struct *work) +{ + struct fc_port *fcport = container_of(work, typeof(*fcport), + free_work); + + qla2x00_free_fcport(fcport); +} + /* BSG support for ELS/CT pass through */ void qla2x00_bsg_job_done(srb_t *sp, int res) { @@ -53,8 +61,10 @@ void qla2x00_bsg_sp_free(srb_t *sp) if (sp->type == SRB_CT_CMD || sp->type == SRB_FXIOCB_BCMD || - sp->type == SRB_ELS_CMD_HST) - qla2x00_free_fcport(sp->fcport); + sp->type == SRB_ELS_CMD_HST) { + INIT_WORK(&sp->fcport->free_work, qla2xxx_free_fcport_work); + queue_work(ha->wq, &sp->fcport->free_work); + } qla2x00_rel_sp(sp); } @@ -718,7 +728,7 @@ qla2x00_process_loopback(struct bsg_job *bsg_job) uint16_t response[MAILBOX_REGISTER_COUNT]; uint16_t config[4], new_config[4]; uint8_t *fw_sts_ptr; - uint8_t *req_data = NULL; + void *req_data = NULL; dma_addr_t req_data_dma; uint32_t req_data_len; uint8_t *rsp_data = NULL; @@ -796,10 +806,11 @@ qla2x00_process_loopback(struct bsg_job *bsg_job) bsg_request->rqst_data.h_vendor.vendor_cmd[2]; if (atomic_read(&vha->loop_state) == LOOP_READY && - (ha->current_topology == ISP_CFG_F || - (get_unaligned_le32(req_data) == ELS_OPCODE_BYTE && - req_data_len == MAX_ELS_FRAME_PAYLOAD)) && - elreq.options == EXTERNAL_LOOPBACK) { + ((ha->current_topology == ISP_CFG_F && (elreq.options & 7) >= 2) || + ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) && + get_unaligned_le32(req_data) == ELS_OPCODE_BYTE && + req_data_len == MAX_ELS_FRAME_PAYLOAD && + elreq.options == EXTERNAL_LOOPBACK))) { type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; ql_dbg(ql_dbg_user, vha, 0x701e, "BSG request type: %s.\n", type); @@ -1506,10 +1517,15 @@ qla2x00_update_optrom(struct bsg_job *bsg_job) bsg_job->request_payload.sg_cnt, ha->optrom_buffer, ha->optrom_region_size); - ha->isp_ops->write_optrom(vha, ha->optrom_buffer, + rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); - bsg_reply->result = DID_OK; + if (rval) { + bsg_reply->result = -EINVAL; + rval = -EINVAL; + } else { + bsg_reply->result = DID_OK; + } vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; @@ -2404,7 +2420,7 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job) regions.global_image = active_regions.global; if (IS_QLA28XX(ha)) { - qla27xx_get_active_image(vha, &active_regions); + qla28xx_get_aux_images(vha, &active_regions); regions.board_config = active_regions.aux.board_config; regions.vpd_nvram = active_regions.aux.vpd_nvram; regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1; diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 88a56e8480f7..f301a8048b2f 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -73,6 +73,8 @@ #include "qla_def.h" #include <linux/delay.h> +#define CREATE_TRACE_POINTS +#include <trace/events/qla.h> static uint32_t ql_dbg_offset = 0x800; @@ -2537,15 +2539,30 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) { va_list va; struct va_format vaf; - - if (!ql_mask_match(level)) - return; + char pbuf[64]; va_start(va, fmt); vaf.fmt = fmt; vaf.va = &va; + if (!ql_mask_match(level)) { + if (vha != NULL) { + const struct pci_dev *pdev = vha->hw->pdev; + /* <module-name> <msg-id>:<host> Message */ + snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x:%ld: ", + QL_MSGHDR, dev_name(&(pdev->dev)), id, + vha->host_no); + } else { + snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ", + QL_MSGHDR, "0000:00:00.0", id); + } + pbuf[sizeof(pbuf) - 1] = 0; + trace_ql_dbg_log(pbuf, &vaf); + va_end(va); + return; + } + if (vha != NULL) { const struct pci_dev *pdev = vha->hw->pdev; /* <module-name> <pci-name> <msg-id>:<host> Message */ diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index ed32e9715794..47c7a56438b5 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -119,7 +119,10 @@ typedef struct { #define LSD(x) ((uint32_t)((uint64_t)(x))) #define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16)) -#define MAKE_HANDLE(x, y) ((uint32_t)((((uint32_t)(x)) << 16) | (uint32_t)(y))) +static inline uint32_t make_handle(uint16_t x, uint16_t y) +{ + return ((uint32_t)x << 16) | y; +} /* * I/O register @@ -414,7 +417,7 @@ struct els_logo_payload { struct els_plogi_payload { uint8_t opcode; uint8_t rsvd[3]; - uint8_t data[112]; + __be32 data[112 / 4]; }; struct ct_arg { @@ -597,9 +600,6 @@ typedef struct srb { struct fc_port *fcport; struct scsi_qla_host *vha; unsigned int start_timer:1; - unsigned int abort:1; - unsigned int aborted:1; - unsigned int completed:1; uint32_t handle; uint16_t flags; @@ -1049,6 +1049,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define MBA_TEMPERATURE_ALERT 0x8070 /* Temperature Alert */ #define MBA_DPORT_DIAGNOSTICS 0x8080 /* D-port Diagnostics */ #define MBA_TRANS_INSERT 0x8130 /* Transceiver Insertion */ +#define MBA_TRANS_REMOVE 0x8131 /* Transceiver Removal */ #define MBA_FW_INIT_FAILURE 0x8401 /* Firmware initialization failure */ #define MBA_MIRROR_LUN_CHANGE 0x8402 /* Mirror LUN State Change Notification */ @@ -1134,6 +1135,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define MBC_GET_FIRMWARE_OPTION 0x28 /* Get Firmware Options. */ #define MBC_GET_MEM_OFFLOAD_CNTRL_STAT 0x34 /* Memory Offload ctrl/Stat*/ #define MBC_SET_FIRMWARE_OPTION 0x38 /* Set Firmware Options. */ +#define MBC_SET_GET_FC_LED_CONFIG 0x3b /* Set/Get FC LED config */ #define MBC_LOOP_PORT_BYPASS 0x40 /* Loop Port Bypass. */ #define MBC_LOOP_PORT_ENABLE 0x41 /* Loop Port Enable. */ #define MBC_GET_RESOURCE_COUNTS 0x42 /* Get Resource Counts. */ @@ -1260,10 +1262,15 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs) #define MBX_1 BIT_1 #define MBX_0 BIT_0 +#define RNID_TYPE_ELS_CMD 0x5 #define RNID_TYPE_PORT_LOGIN 0x7 +#define RNID_BUFFER_CREDITS 0x8 #define RNID_TYPE_SET_VERSION 0x9 #define RNID_TYPE_ASIC_TEMP 0xC +#define ELS_CMD_MAP_SIZE 32 +#define ELS_COMMAND_RDP 0x18 + /* * Firmware state codes from get firmware state mailbox command */ @@ -1474,47 +1481,44 @@ typedef struct { #define GLSO_USE_DID BIT_3 struct link_statistics { - uint32_t link_fail_cnt; - uint32_t loss_sync_cnt; - uint32_t loss_sig_cnt; - uint32_t prim_seq_err_cnt; - uint32_t inval_xmit_word_cnt; - uint32_t inval_crc_cnt; - uint32_t lip_cnt; - uint32_t link_up_cnt; - uint32_t link_down_loop_init_tmo; - uint32_t link_down_los; - uint32_t link_down_loss_rcv_clk; + __le32 link_fail_cnt; + __le32 loss_sync_cnt; + __le32 loss_sig_cnt; + __le32 prim_seq_err_cnt; + __le32 inval_xmit_word_cnt; + __le32 inval_crc_cnt; + __le32 lip_cnt; + __le32 link_up_cnt; + __le32 link_down_loop_init_tmo; + __le32 link_down_los; + __le32 link_down_loss_rcv_clk; uint32_t reserved0[5]; - uint32_t port_cfg_chg; + __le32 port_cfg_chg; uint32_t reserved1[11]; - uint32_t rsp_q_full; - uint32_t atio_q_full; - uint32_t drop_ae; - uint32_t els_proto_err; - uint32_t reserved2; - uint32_t tx_frames; - uint32_t rx_frames; - uint32_t discarded_frames; - uint32_t dropped_frames; + __le32 rsp_q_full; + __le32 atio_q_full; + __le32 drop_ae; + __le32 els_proto_err; + __le32 reserved2; + __le32 tx_frames; + __le32 rx_frames; + __le32 discarded_frames; + __le32 dropped_frames; uint32_t reserved3; - uint32_t nos_rcvd; + __le32 nos_rcvd; uint32_t reserved4[4]; - uint32_t tx_prjt; - uint32_t rcv_exfail; - uint32_t rcv_abts; - uint32_t seq_frm_miss; - uint32_t corr_err; - uint32_t mb_rqst; - uint32_t nport_full; - uint32_t eofa; + __le32 tx_prjt; + __le32 rcv_exfail; + __le32 rcv_abts; + __le32 seq_frm_miss; + __le32 corr_err; + __le32 mb_rqst; + __le32 nport_full; + __le32 eofa; uint32_t reserved5; - uint32_t fpm_recv_word_cnt_lo; - uint32_t fpm_recv_word_cnt_hi; - uint32_t fpm_disc_word_cnt_lo; - uint32_t fpm_disc_word_cnt_hi; - uint32_t fpm_xmit_word_cnt_lo; - uint32_t fpm_xmit_word_cnt_hi; + __le64 fpm_recv_word_cnt; + __le64 fpm_disc_word_cnt; + __le64 fpm_xmit_word_cnt; uint32_t reserved6[70]; }; @@ -2624,10 +2628,11 @@ static const char * const port_dstate_str[] = { #define GFF_ID_RSP_SIZE (16 + 128) /* - * HBA attribute types. + * FDMI HBA attribute types. */ -#define FDMI_HBA_ATTR_COUNT 9 -#define FDMIV2_HBA_ATTR_COUNT 17 +#define FDMI1_HBA_ATTR_COUNT 9 +#define FDMI2_HBA_ATTR_COUNT 17 + #define FDMI_HBA_NODE_NAME 0x1 #define FDMI_HBA_MANUFACTURER 0x2 #define FDMI_HBA_SERIAL_NUMBER 0x3 @@ -2639,12 +2644,13 @@ static const char * const port_dstate_str[] = { #define FDMI_HBA_FIRMWARE_VERSION 0x9 #define FDMI_HBA_OS_NAME_AND_VERSION 0xa #define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH 0xb + #define FDMI_HBA_NODE_SYMBOLIC_NAME 0xc -#define FDMI_HBA_VENDOR_ID 0xd +#define FDMI_HBA_VENDOR_SPECIFIC_INFO 0xd #define FDMI_HBA_NUM_PORTS 0xe #define FDMI_HBA_FABRIC_NAME 0xf #define FDMI_HBA_BOOT_BIOS_NAME 0x10 -#define FDMI_HBA_TYPE_VENDOR_IDENTIFIER 0xe0 +#define FDMI_HBA_VENDOR_IDENTIFIER 0xe0 struct ct_fdmi_hba_attr { uint16_t type; @@ -2661,31 +2667,9 @@ struct ct_fdmi_hba_attr { uint8_t fw_version[32]; uint8_t os_version[128]; uint32_t max_ct_len; - } a; -}; - -struct ct_fdmi_hba_attributes { - uint32_t count; - struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT]; -}; -struct ct_fdmiv2_hba_attr { - uint16_t type; - uint16_t len; - union { - uint8_t node_name[WWN_SIZE]; - uint8_t manufacturer[64]; - uint8_t serial_num[32]; - uint8_t model[16+1]; - uint8_t model_desc[80]; - uint8_t hw_version[16]; - uint8_t driver_version[32]; - uint8_t orom_version[16]; - uint8_t fw_version[32]; - uint8_t os_version[128]; - uint32_t max_ct_len; uint8_t sym_name[256]; - uint32_t vendor_id; + uint32_t vendor_specific_info; uint32_t num_ports; uint8_t fabric_name[WWN_SIZE]; uint8_t bios_name[32]; @@ -2693,22 +2677,30 @@ struct ct_fdmiv2_hba_attr { } a; }; -struct ct_fdmiv2_hba_attributes { +struct ct_fdmi1_hba_attributes { uint32_t count; - struct ct_fdmiv2_hba_attr entry[FDMIV2_HBA_ATTR_COUNT]; + struct ct_fdmi_hba_attr entry[FDMI1_HBA_ATTR_COUNT]; +}; + +struct ct_fdmi2_hba_attributes { + uint32_t count; + struct ct_fdmi_hba_attr entry[FDMI2_HBA_ATTR_COUNT]; }; /* - * Port attribute types. + * FDMI Port attribute types. */ -#define FDMI_PORT_ATTR_COUNT 6 -#define FDMIV2_PORT_ATTR_COUNT 16 +#define FDMI1_PORT_ATTR_COUNT 6 +#define FDMI2_PORT_ATTR_COUNT 16 +#define FDMI2_SMARTSAN_PORT_ATTR_COUNT 23 + #define FDMI_PORT_FC4_TYPES 0x1 #define FDMI_PORT_SUPPORT_SPEED 0x2 #define FDMI_PORT_CURRENT_SPEED 0x3 #define FDMI_PORT_MAX_FRAME_SIZE 0x4 #define FDMI_PORT_OS_DEVICE_NAME 0x5 #define FDMI_PORT_HOST_NAME 0x6 + #define FDMI_PORT_NODE_NAME 0x7 #define FDMI_PORT_NAME 0x8 #define FDMI_PORT_SYM_NAME 0x9 @@ -2718,7 +2710,15 @@ struct ct_fdmiv2_hba_attributes { #define FDMI_PORT_FC4_TYPE 0xd #define FDMI_PORT_STATE 0x101 #define FDMI_PORT_COUNT 0x102 -#define FDMI_PORT_ID 0x103 +#define FDMI_PORT_IDENTIFIER 0x103 + +#define FDMI_SMARTSAN_SERVICE 0xF100 +#define FDMI_SMARTSAN_GUID 0xF101 +#define FDMI_SMARTSAN_VERSION 0xF102 +#define FDMI_SMARTSAN_PROD_NAME 0xF103 +#define FDMI_SMARTSAN_PORT_INFO 0xF104 +#define FDMI_SMARTSAN_QOS_SUPPORT 0xF105 +#define FDMI_SMARTSAN_SECURITY_SUPPORT 0xF106 #define FDMI_PORT_SPEED_1GB 0x1 #define FDMI_PORT_SPEED_2GB 0x2 @@ -2734,7 +2734,7 @@ struct ct_fdmiv2_hba_attributes { #define FC_CLASS_3 0x08 #define FC_CLASS_2_3 0x0C -struct ct_fdmiv2_port_attr { +struct ct_fdmi_port_attr { uint16_t type; uint16_t len; union { @@ -2744,6 +2744,7 @@ struct ct_fdmiv2_port_attr { uint32_t max_frame_size; uint8_t os_dev_name[32]; uint8_t host_name[256]; + uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; uint8_t port_sym_name[128]; @@ -2754,35 +2755,38 @@ struct ct_fdmiv2_port_attr { uint32_t port_state; uint32_t num_ports; uint32_t port_id; + + uint8_t smartsan_service[24]; + uint8_t smartsan_guid[16]; + uint8_t smartsan_version[24]; + uint8_t smartsan_prod_name[16]; + uint32_t smartsan_port_info; + uint32_t smartsan_qos_support; + uint32_t smartsan_security_support; } a; }; -/* - * Port Attribute Block. - */ -struct ct_fdmiv2_port_attributes { +struct ct_fdmi1_port_attributes { uint32_t count; - struct ct_fdmiv2_port_attr entry[FDMIV2_PORT_ATTR_COUNT]; -}; - -struct ct_fdmi_port_attr { - uint16_t type; - uint16_t len; - union { - uint8_t fc4_types[32]; - uint32_t sup_speed; - uint32_t cur_speed; - uint32_t max_frame_size; - uint8_t os_dev_name[32]; - uint8_t host_name[256]; - } a; + struct ct_fdmi_port_attr entry[FDMI1_PORT_ATTR_COUNT]; }; -struct ct_fdmi_port_attributes { +struct ct_fdmi2_port_attributes { uint32_t count; - struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT]; + struct ct_fdmi_port_attr entry[FDMI2_PORT_ATTR_COUNT]; }; +#define FDMI_ATTR_TYPELEN(obj) \ + (sizeof((obj)->type) + sizeof((obj)->len)) + +#define FDMI_ATTR_ALIGNMENT(len) \ + (4 - ((len) & 3)) + +/* FDMI register call options */ +#define CALLOPT_FDMI1 0 +#define CALLOPT_FDMI2 1 +#define CALLOPT_FDMI2_SMARTSAN 2 + /* FDMI definitions. */ #define GRHL_CMD 0x100 #define GHAT_CMD 0x101 @@ -2793,10 +2797,13 @@ struct ct_fdmi_port_attributes { #define RHBA_RSP_SIZE 16 #define RHAT_CMD 0x201 + #define RPRT_CMD 0x210 +#define RPRT_RSP_SIZE 24 #define RPA_CMD 0x211 #define RPA_RSP_SIZE 16 +#define SMARTSAN_RPA_RSP_SIZE 24 #define DHBA_CMD 0x300 #define DHBA_REQ_SIZE (16 + 8) @@ -2879,30 +2886,24 @@ struct ct_sns_req { uint8_t hba_identifier[8]; uint32_t entry_count; uint8_t port_name[8]; - struct ct_fdmi_hba_attributes attrs; + struct ct_fdmi2_hba_attributes attrs; } rhba; struct { uint8_t hba_identifier[8]; - uint32_t entry_count; - uint8_t port_name[8]; - struct ct_fdmiv2_hba_attributes attrs; - } rhba2; - - struct { - uint8_t hba_identifier[8]; - struct ct_fdmi_hba_attributes attrs; + struct ct_fdmi1_hba_attributes attrs; } rhat; struct { uint8_t port_name[8]; - struct ct_fdmi_port_attributes attrs; + struct ct_fdmi2_port_attributes attrs; } rpa; struct { + uint8_t hba_identifier[8]; uint8_t port_name[8]; - struct ct_fdmiv2_port_attributes attrs; - } rpa2; + struct ct_fdmi2_port_attributes attrs; + } rprt; struct { uint8_t port_name[8]; @@ -3016,7 +3017,7 @@ struct ct_sns_rsp { struct { uint32_t entry_count; uint8_t port_name[8]; - struct ct_fdmi_hba_attributes attrs; + struct ct_fdmi1_hba_attributes attrs; } ghat; struct { @@ -3250,6 +3251,7 @@ struct isp_operations { #define QLA_MSIX_RSP_Q 0x01 #define QLA_ATIO_VECTOR 0x02 #define QLA_MSIX_QPAIR_MULTIQ_RSP_Q 0x03 +#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS 0x04 #define QLA_MIDX_DEFAULT 0 #define QLA_MIDX_RSP_Q 1 @@ -3562,6 +3564,134 @@ struct qlfc_fw { uint32_t len; }; +struct rdp_req_payload { + uint32_t els_request; + uint32_t desc_list_len; + + /* NPIV descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t reserved; + uint8_t nport_id[3]; + } npiv_desc; +}; + +struct rdp_rsp_payload { + struct { + uint32_t cmd; + uint32_t len; + } hdr; + + /* LS Request Info descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t req_payload_word_0; + } ls_req_info_desc; + + /* LS Request Info descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t req_payload_word_0; + } ls_req_info_desc2; + + /* SFP diagnostic param descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint16_t temperature; + uint16_t vcc; + uint16_t tx_bias; + uint16_t tx_power; + uint16_t rx_power; + uint16_t sfp_flags; + } sfp_diag_desc; + + /* Port Speed Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint16_t speed_capab; + uint16_t operating_speed; + } port_speed_desc; + + /* Link Error Status Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t link_fail_cnt; + uint32_t loss_sync_cnt; + uint32_t loss_sig_cnt; + uint32_t prim_seq_err_cnt; + uint32_t inval_xmit_word_cnt; + uint32_t inval_crc_cnt; + uint8_t pn_port_phy_type; + uint8_t reserved[3]; + } ls_err_desc; + + /* Port name description with diag param */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t WWNN[WWN_SIZE]; + uint8_t WWPN[WWN_SIZE]; + } port_name_diag_desc; + + /* Port Name desc for Direct attached Fx_Port or Nx_Port */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t WWNN[WWN_SIZE]; + uint8_t WWPN[WWN_SIZE]; + } port_name_direct_desc; + + /* Buffer Credit descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint32_t fcport_b2b; + uint32_t attached_fcport_b2b; + uint32_t fcport_rtt; + } buffer_credit_desc; + + /* Optical Element Data Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint16_t high_alarm; + uint16_t low_alarm; + uint16_t high_warn; + uint16_t low_warn; + uint32_t element_flags; + } optical_elmt_desc[5]; + + /* Optical Product Data Descriptor */ + struct { + uint32_t desc_tag; + uint32_t desc_len; + uint8_t vendor_name[16]; + uint8_t part_number[16]; + uint8_t serial_number[16]; + uint8_t revision[4]; + uint8_t date[8]; + } optical_prod_desc; +}; + +#define RDP_DESC_LEN(obj) \ + (sizeof(obj) - sizeof((obj).desc_tag) - sizeof((obj).desc_len)) + +#define RDP_PORT_SPEED_1GB BIT_15 +#define RDP_PORT_SPEED_2GB BIT_14 +#define RDP_PORT_SPEED_4GB BIT_13 +#define RDP_PORT_SPEED_10GB BIT_12 +#define RDP_PORT_SPEED_8GB BIT_11 +#define RDP_PORT_SPEED_16GB BIT_10 +#define RDP_PORT_SPEED_32GB BIT_9 +#define RDP_PORT_SPEED_64GB BIT_8 +#define RDP_PORT_SPEED_UNKNOWN BIT_0 + struct scsi_qlt_host { void *target_lport_ptr; struct mutex tgt_mutex; @@ -3673,8 +3803,8 @@ struct qla_hw_data { uint32_t fw_started:1; uint32_t fw_init_done:1; - uint32_t detected_lr_sfp:1; - uint32_t using_lr_setting:1; + uint32_t lr_detected:1; + uint32_t rida_fmt2:1; uint32_t purge_mbox:1; uint32_t n2n_bigger:1; @@ -3683,7 +3813,7 @@ struct qla_hw_data { } flags; uint16_t max_exchg; - uint16_t long_range_distance; /* 32G & above */ + uint16_t lr_distance; /* 32G & above */ #define LR_DISTANCE_5K 1 #define LR_DISTANCE_10K 0 @@ -3965,6 +4095,8 @@ struct qla_hw_data { #define SFP_DEV_SIZE 512 #define SFP_BLOCK_SIZE 64 +#define SFP_RTDI_LEN SFP_BLOCK_SIZE + void *sfp_data; dma_addr_t sfp_data_dma; @@ -4344,6 +4476,15 @@ struct active_regions { #define QLA_SET_DATA_RATE_NOLR 1 #define QLA_SET_DATA_RATE_LR 2 /* Set speed and initiate LR */ +struct purex_item { + struct list_head list; + struct scsi_qla_host *vha; + void (*process_item)(struct scsi_qla_host *vha, void *pkt); + struct { + uint8_t iocb[64]; + } iocb; +}; + /* * Qlogic scsi host structure */ @@ -4424,6 +4565,8 @@ typedef struct scsi_qla_host { #define ISP_ABORT_TO_ROM 33 #define VPORT_DELETE 34 +#define PROCESS_PUREX_IOCB 63 + unsigned long pci_flags; #define PFLG_DISCONNECTED 0 /* PCI device removed */ #define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */ @@ -4461,6 +4604,7 @@ typedef struct scsi_qla_host { uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; uint8_t fabric_node_name[WWN_SIZE]; + uint8_t fabric_port_name[WWN_SIZE]; struct nvme_fc_local_port *nvme_local_port; struct completion nvme_del_done; @@ -4531,6 +4675,11 @@ typedef struct scsi_qla_host { uint16_t ql2xexchoffld; uint16_t ql2xiniexchg; + struct purex_list { + struct list_head head; + spinlock_t lock; + } purex_list; + struct name_list_extended gnl; /* Count of active session/fcport */ int fcport_count; @@ -4540,6 +4689,7 @@ typedef struct scsi_qla_host { uint8_t n2n_node_name[WWN_SIZE]; uint8_t n2n_port_name[WWN_SIZE]; uint16_t n2n_id; + __le16 dport_data[4]; struct list_head gpnid_list; struct fab_scan scan; @@ -4822,11 +4972,14 @@ struct sff_8247_a0 { u8 resv2[128]; }; -#define AUTO_DETECT_SFP_SUPPORT(_vha)\ - (ql2xautodetectsfp && !_vha->vp_idx && \ - (IS_QLA25XX(_vha->hw) || IS_QLA81XX(_vha->hw) ||\ - IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw) || \ - IS_QLA28XX(_vha->hw))) +/* BPM -- Buffer Plus Management support. */ +#define IS_BPM_CAPABLE(ha) \ + (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ + IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_BPM_RANGE_CAPABLE(ha) \ + (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_BPM_ENABLED(vha) \ + (ql2xautodetectsfp && !vha->vp_idx && IS_BPM_CAPABLE(vha->hw)) #define FLASH_SEMAPHORE_REGISTER_ADDR 0x00101016 diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index 0a6fb359f4d5..e62b2115235e 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -134,11 +134,11 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) } else { seq_puts(s, "FW Resource count\n\n"); seq_printf(s, "Original TGT exchg count[%d]\n", mb[1]); - seq_printf(s, "current TGT exchg count[%d]\n", mb[2]); - seq_printf(s, "original Initiator Exchange count[%d]\n", mb[3]); - seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[6]); - seq_printf(s, "Original IOCB count[%d]\n", mb[7]); - seq_printf(s, "Current IOCB count[%d]\n", mb[10]); + seq_printf(s, "Current TGT exchg count[%d]\n", mb[2]); + seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[3]); + seq_printf(s, "Original Initiator Exchange count[%d]\n", mb[6]); + seq_printf(s, "Current IOCB count[%d]\n", mb[7]); + seq_printf(s, "Original IOCB count[%d]\n", mb[10]); seq_printf(s, "MAX VP count[%d]\n", mb[11]); seq_printf(s, "MAX FCF count[%d]\n", mb[12]); seq_printf(s, "Current free pageable XCB buffer cnt[%d]\n", @@ -149,7 +149,6 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) mb[22]); seq_printf(s, "Original Target fast XCB buffer cnt[%d]\n", mb[23]); - } return 0; diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index d641918cdd46..f9bad5bd7198 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -31,6 +31,9 @@ #define PDO_FORCE_ADISC BIT_1 #define PDO_FORCE_PLOGI BIT_0 +struct buffer_credit_24xx { + u32 parameter[28]; +}; #define PORT_DATABASE_24XX_SIZE 64 struct port_database_24xx { @@ -721,6 +724,48 @@ struct ct_entry_24xx { }; /* + * ISP queue - PUREX IOCB entry structure definition + */ +#define PUREX_IOCB_TYPE 0x51 /* CT Pass Through IOCB entry */ +struct purex_entry_24xx { + uint8_t entry_type; /* Entry type. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ + uint8_t entry_status; /* Entry Status. */ + + uint16_t reserved1; + uint8_t vp_idx; + uint8_t reserved2; + + uint16_t status_flags; + uint16_t nport_handle; + + uint16_t frame_size; + uint16_t trunc_frame_size; + + uint32_t rx_xchg_addr; + + uint8_t d_id[3]; + uint8_t r_ctl; + + uint8_t s_id[3]; + uint8_t cs_ctl; + + uint8_t f_ctl[3]; + uint8_t type; + + uint16_t seq_cnt; + uint8_t df_ctl; + uint8_t seq_id; + + uint16_t rx_id; + uint16_t ox_id; + uint32_t param; + + uint8_t els_frame_payload[20]; +}; + +/* * ISP queue - ELS Pass-Through entry structure definition. */ #define ELS_IOCB_TYPE 0x53 /* ELS Pass-Through IOCB entry */ @@ -732,9 +777,8 @@ struct els_entry_24xx { uint32_t handle; /* System handle. */ - uint16_t reserved_1; - - uint16_t nport_handle; /* N_PORT handle. */ + uint16_t comp_status; /* response only */ + uint16_t nport_handle; uint16_t tx_dsd_count; @@ -749,7 +793,7 @@ struct els_entry_24xx { uint8_t opcode; uint8_t reserved_2; - uint8_t port_id[3]; + uint8_t d_id[3]; uint8_t s_id[3]; uint16_t control_flags; /* Control flags. */ @@ -761,13 +805,24 @@ struct els_entry_24xx { #define ECF_CLR_PASSTHRU_PEND BIT_12 #define ECF_INCL_FRAME_HDR BIT_11 - __le32 rx_byte_count; - __le32 tx_byte_count; + union { + struct { + __le32 rx_byte_count; + __le32 tx_byte_count; - __le64 tx_address __packed; /* Data segment 0 address. */ - __le32 tx_len; /* Data segment 0 length. */ - __le64 rx_address __packed; /* Data segment 1 address. */ - __le32 rx_len; /* Data segment 1 length. */ + __le64 tx_address __packed; /* DSD 0 address. */ + __le32 tx_len; /* DSD 0 length. */ + + __le64 rx_address __packed; /* DSD 1 address. */ + __le32 rx_len; /* DSD 1 length. */ + }; + struct { + uint32_t total_byte_count; + uint32_t error_subcode_1; + uint32_t error_subcode_2; + uint32_t error_subcode_3; + }; + }; }; struct els_sts_entry_24xx { @@ -793,15 +848,16 @@ struct els_sts_entry_24xx { uint8_t opcode; uint8_t reserved_3; - uint8_t port_id[3]; - uint8_t reserved_4; - - uint16_t reserved_5; + uint8_t d_id[3]; + uint8_t s_id[3]; uint16_t control_flags; /* Control flags. */ uint32_t total_byte_count; uint32_t error_subcode_1; uint32_t error_subcode_2; + uint32_t error_subcode_3; + + uint32_t reserved_4[4]; }; /* * ISP queue - Mailbox Command entry structure definition. @@ -942,6 +998,91 @@ struct abort_entry_24xx { uint8_t reserved_2[12]; }; +#define ABTS_RCV_TYPE 0x54 +#define ABTS_RSP_TYPE 0x55 +struct abts_entry_24xx { + uint8_t entry_type; + uint8_t entry_count; + uint8_t handle_count; + uint8_t entry_status; + + uint32_t handle; /* type 0x55 only */ + + uint16_t comp_status; /* type 0x55 only */ + uint16_t nport_handle; /* type 0x54 only */ + + uint16_t control_flags; /* type 0x55 only */ + uint8_t vp_idx; + uint8_t sof_type; /* sof_type is upper nibble */ + + uint32_t rx_xch_addr; + + uint8_t d_id[3]; + uint8_t r_ctl; + + uint8_t s_id[3]; + uint8_t cs_ctl; + + uint8_t f_ctl[3]; + uint8_t type; + + uint16_t seq_cnt; + uint8_t df_ctl; + uint8_t seq_id; + + uint16_t rx_id; + uint16_t ox_id; + + uint32_t param; + + union { + struct { + uint32_t subcode3; + uint32_t rsvd; + uint32_t subcode1; + uint32_t subcode2; + } error; + struct { + uint16_t rsrvd1; + uint8_t last_seq_id; + uint8_t seq_id_valid; + uint16_t aborted_rx_id; + uint16_t aborted_ox_id; + uint16_t high_seq_cnt; + uint16_t low_seq_cnt; + } ba_acc; + struct { + uint8_t vendor_unique; + uint8_t explanation; + uint8_t reason; + } ba_rjt; + } payload; + + uint32_t rx_xch_addr_to_abort; +} __packed; + +/* ABTS payload explanation values */ +#define BA_RJT_EXP_NO_ADDITIONAL 0 +#define BA_RJT_EXP_INV_OX_RX_ID 3 +#define BA_RJT_EXP_SEQ_ABORTED 5 + +/* ABTS payload reason values */ +#define BA_RJT_RSN_INV_CMD_CODE 1 +#define BA_RJT_RSN_LOGICAL_ERROR 3 +#define BA_RJT_RSN_LOGICAL_BUSY 5 +#define BA_RJT_RSN_PROTOCOL_ERROR 7 +#define BA_RJT_RSN_UNABLE_TO_PERFORM 9 +#define BA_RJT_RSN_VENDOR_SPECIFIC 0xff + +/* FC_F values */ +#define FC_TYPE_BLD 0x000 /* Basic link data */ +#define FC_F_CTL_RSP_CNTXT 0x800000 /* Responder of exchange */ +#define FC_F_CTL_LAST_SEQ 0x100000 /* Last sequence */ +#define FC_F_CTL_END_SEQ 0x80000 /* Last sequence */ +#define FC_F_CTL_SEQ_INIT 0x010000 /* Sequence initiative */ +#define FC_ROUTING_BLD 0x80 /* Basic link data frame */ +#define FC_R_CTL_BLD_BA_ACC 0x04 /* BA_ACC (basic accept) */ + /* * ISP I/O Register Set structure definitions. */ @@ -1726,9 +1867,8 @@ struct access_chip_rsp_84xx { /* LR Distance bit positions */ #define LR_DIST_NV_POS 2 +#define LR_DIST_NV_MASK 0xf #define LR_DIST_FW_POS 12 -#define LR_DIST_FW_SHIFT (LR_DIST_FW_POS - LR_DIST_NV_POS) -#define LR_DIST_FW_FIELD(x) ((x) << LR_DIST_FW_SHIFT & 0xf000) /* FAC semaphore defines */ #define FAC_SEMAPHORE_UNLOCK 0 @@ -1883,6 +2023,7 @@ struct nvram_81xx { * BIT 6-15 = Unused */ uint16_t enhanced_features; + uint16_t reserved_24[4]; /* Offset 416. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 2a64729a2bc5..1b93f5b4d77d 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -31,7 +31,7 @@ extern int qla24xx_nvram_config(struct scsi_qla_host *); extern int qla81xx_nvram_config(struct scsi_qla_host *); extern void qla2x00_update_fw_options(struct scsi_qla_host *); extern void qla24xx_update_fw_options(scsi_qla_host_t *); -extern void qla81xx_update_fw_options(scsi_qla_host_t *); + extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *); extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *); extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *); @@ -109,7 +109,7 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *, int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, u8*, void *, u8); int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *); -int qla24xx_detect_sfp(scsi_qla_host_t *vha); +int qla24xx_detect_sfp(scsi_qla_host_t *); int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); extern void qla28xx_get_aux_images(struct scsi_qla_host *, @@ -142,6 +142,8 @@ extern int qlport_down_retry; extern int ql2xplogiabsentdevice; extern int ql2xloginretrycount; extern int ql2xfdmienable; +extern int ql2xrdpenable; +extern int ql2xsmartsan; extern int ql2xallocfwdump; extern int ql2xextended_error_logging; extern int ql2xiidmaenable; @@ -226,6 +228,7 @@ void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *, int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_post_relogin_work(struct scsi_qla_host *vha); void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *); +void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt); /* * Global Functions in qla_mid.c source file. @@ -354,6 +357,9 @@ extern int qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t); extern int +qla24xx_get_port_database(scsi_qla_host_t *, u16, struct port_database_24xx *); + +extern int qla2x00_get_firmware_state(scsi_qla_host_t *, uint16_t *); extern int @@ -452,6 +458,13 @@ extern int qla25xx_set_driver_version(scsi_qla_host_t *, char *); extern int +qla25xx_set_els_cmds_supported(scsi_qla_host_t *); + +extern int +qla24xx_get_buffer_credits(scsi_qla_host_t *, struct buffer_credit_24xx *, + dma_addr_t); + +extern int qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint8_t *, uint16_t, uint16_t, uint16_t, uint16_t); @@ -552,6 +565,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *, struct req_que *, uint32_t); extern irqreturn_t qla2xxx_msix_rsp_q(int irq, void *dev_id); +extern irqreturn_t +qla2xxx_msix_rsp_q_hs(int irq, void *dev_id); fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t); fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8); fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8); @@ -656,7 +671,7 @@ extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); extern int qla2x00_fdmi_register(scsi_qla_host_t *); extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *); extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *); -extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t); +extern size_t qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t); extern int qla2x00_chk_ms_status(scsi_qla_host_t *, ms_iocb_entry_t *, struct ct_sns_rsp *, const char *); extern void qla2x00_async_iocb_timeout(void *data); @@ -844,6 +859,7 @@ extern void qla82xx_clear_pending_mbx(scsi_qla_host_t *); extern int qla82xx_read_temperature(scsi_qla_host_t *); extern int qla8044_read_temperature(scsi_qla_host_t *); extern int qla2x00_read_sfp_dev(struct scsi_qla_host *, char *, int); +extern int ql26xx_led_config(scsi_qla_host_t *, uint16_t, uint16_t *); /* BSG related functions */ extern int qla24xx_bsg_request(struct bsg_job *); @@ -913,6 +929,7 @@ void qlt_remove_target_resources(struct qla_hw_data *); void qlt_clr_qp_table(struct scsi_qla_host *vha); void qlt_set_mode(struct scsi_qla_host *); int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode); +extern void qla24xx_process_purex_list(struct purex_list *); /* nvme.c */ void qla_nvme_unregister_remote_port(struct fc_port *fcport); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index aaa4a5bbf2ff..42c3ad27f1cb 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -19,6 +19,8 @@ static int qla_async_rffid(scsi_qla_host_t *, port_id_t *, u8, u8); static int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*); static int qla_async_rsnn_nn(scsi_qla_host_t *); + + /** * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query. * @vha: HA context @@ -844,19 +846,18 @@ done: return rval; } -void +size_t qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size) { struct qla_hw_data *ha = vha->hw; if (IS_QLAFX00(ha)) - snprintf(snn, size, "%s FW:v%s DVR:v%s", ha->model_number, - ha->mr.fw_version, qla2x00_version_str); - else - snprintf(snn, size, - "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number, - ha->fw_major_version, ha->fw_minor_version, - ha->fw_subminor_version, qla2x00_version_str); + return scnprintf(snn, size, "%s FW:v%s DVR:v%s", + ha->model_number, ha->mr.fw_version, qla2x00_version_str); + + return scnprintf(snn, size, "%s FW:v%d.%02d.%02d DVR:v%s", + ha->model_number, ha->fw_major_version, ha->fw_minor_version, + ha->fw_subminor_version, qla2x00_version_str); } /** @@ -1501,747 +1502,732 @@ qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd, return &p->p.req; } +static uint +qla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha) +{ + if (IS_CNA_CAPABLE(ha)) + return FDMI_PORT_SPEED_10GB; + if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) { + uint speeds = 0; + + if (ha->max_supported_speed == 2) { + if (ha->min_supported_speed <= 6) + speeds |= FDMI_PORT_SPEED_64GB; + } + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1) { + if (ha->min_supported_speed <= 5) + speeds |= FDMI_PORT_SPEED_32GB; + } + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 4) + speeds |= FDMI_PORT_SPEED_16GB; + } + if (ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 3) + speeds |= FDMI_PORT_SPEED_8GB; + } + if (ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 2) + speeds |= FDMI_PORT_SPEED_4GB; + } + return speeds; + } + if (IS_QLA2031(ha)) + return FDMI_PORT_SPEED_16GB|FDMI_PORT_SPEED_8GB| + FDMI_PORT_SPEED_4GB; + if (IS_QLA25XX(ha)) + return FDMI_PORT_SPEED_8GB|FDMI_PORT_SPEED_4GB| + FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB; + if (IS_QLA24XX_TYPE(ha)) + return FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_2GB| + FDMI_PORT_SPEED_1GB; + if (IS_QLA23XX(ha)) + return FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB; + return FDMI_PORT_SPEED_1GB; +} +static uint +qla25xx_fdmi_port_speed_currently(struct qla_hw_data *ha) +{ + switch (ha->link_data_rate) { + case PORT_SPEED_1GB: + return FDMI_PORT_SPEED_1GB; + case PORT_SPEED_2GB: + return FDMI_PORT_SPEED_2GB; + case PORT_SPEED_4GB: + return FDMI_PORT_SPEED_4GB; + case PORT_SPEED_8GB: + return FDMI_PORT_SPEED_8GB; + case PORT_SPEED_10GB: + return FDMI_PORT_SPEED_10GB; + case PORT_SPEED_16GB: + return FDMI_PORT_SPEED_16GB; + case PORT_SPEED_32GB: + return FDMI_PORT_SPEED_32GB; + case PORT_SPEED_64GB: + return FDMI_PORT_SPEED_64GB; + default: + return FDMI_PORT_SPEED_UNKNOWN; + } +} + /** - * qla2x00_fdmi_rhba() - perform RHBA FDMI registration + * qla2x00_hba_attributes() perform HBA attributes registration * @vha: HA context + * @entries: number of entries to use + * @callopt: Option to issue extended or standard FDMI + * command parameter * * Returns 0 on success. */ -static int -qla2x00_fdmi_rhba(scsi_qla_host_t *vha) +static unsigned long +qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries, + unsigned int callopt) { - int rval, alen; - uint32_t size, sn; - - ms_iocb_entry_t *ms_pkt; - struct ct_sns_req *ct_req; - struct ct_sns_rsp *ct_rsp; - void *entries; - struct ct_fdmi_hba_attr *eiter; struct qla_hw_data *ha = vha->hw; - - /* Issue RHBA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE); - - /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE); - ct_rsp = &ha->ct_sns->p.rsp; - - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE); - ct_req->req.rhba.entry_count = cpu_to_be32(1); - memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE); - size = 2 * WWN_SIZE + 4 + 4; - - /* Attributes */ - ct_req->req.rhba.attrs.count = - cpu_to_be32(FDMI_HBA_ATTR_COUNT); - entries = &ct_req->req; + struct init_cb_24xx *icb24 = (void *)ha->init_cb; + struct new_utsname *p_sysid = utsname(); + struct ct_fdmi_hba_attr *eiter; + uint16_t alen; + unsigned long size = 0; /* Nodename. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x2025, - "NodeName = %8phN.\n", eiter->a.node_name); - + memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name)); + alen = sizeof(eiter->a.node_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a0, + "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name)); /* Manufacturer. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER); - alen = strlen(QLA2XXX_MANUFACTURER); - snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer), - "%s", "QLogic Corporation"); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2026, - "Manufacturer = %s.\n", eiter->a.manufacturer); - + alen = scnprintf( + eiter->a.manufacturer, sizeof(eiter->a.manufacturer), + "%s", "QLogic Corporation"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a1, + "MANUFACTURER = %s.\n", eiter->a.manufacturer); /* Serial number. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); - if (IS_FWI2_CAPABLE(ha)) - qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num, - sizeof(eiter->a.serial_num)); - else { - sn = ((ha->serial0 & 0x1f) << 16) | + alen = 0; + if (IS_FWI2_CAPABLE(ha)) { + alen = qla2xxx_get_vpd_field(vha, "SN", + eiter->a.serial_num, sizeof(eiter->a.serial_num)); + } + if (!alen) { + uint32_t sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; - snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num), - "%c%05d", 'A' + sn / 100000, sn % 100000); + alen = scnprintf( + eiter->a.serial_num, sizeof(eiter->a.serial_num), + "%c%05d", 'A' + sn / 100000, sn % 100000); } - alen = strlen(eiter->a.serial_num); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2027, - "Serial no. = %s.\n", eiter->a.serial_num); - + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a2, + "SERIAL NUMBER = %s.\n", eiter->a.serial_num); /* Model name. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MODEL); - snprintf(eiter->a.model, sizeof(eiter->a.model), - "%s", ha->model_number); - alen = strlen(eiter->a.model); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2028, - "Model Name = %s.\n", eiter->a.model); - + alen = scnprintf( + eiter->a.model, sizeof(eiter->a.model), + "%s", ha->model_number); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a3, + "MODEL NAME = %s.\n", eiter->a.model); /* Model description. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); - snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc), - "%s", ha->model_desc); - alen = strlen(eiter->a.model_desc); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x2029, - "Model Desc = %s.\n", eiter->a.model_desc); - + alen = scnprintf( + eiter->a.model_desc, sizeof(eiter->a.model_desc), + "%s", ha->model_desc); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a4, + "MODEL DESCRIPTION = %s.\n", eiter->a.model_desc); /* Hardware version. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); - if (!IS_FWI2_CAPABLE(ha)) { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); - } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); + alen = 0; + if (IS_FWI2_CAPABLE(ha)) { + if (!alen) { + alen = qla2xxx_get_vpd_field(vha, "MN", + eiter->a.hw_version, sizeof(eiter->a.hw_version)); + } + if (!alen) { + alen = qla2xxx_get_vpd_field(vha, "EC", + eiter->a.hw_version, sizeof(eiter->a.hw_version)); + } } - alen = strlen(eiter->a.hw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x202a, - "Hardware ver = %s.\n", eiter->a.hw_version); - + if (!alen) { + alen = scnprintf( + eiter->a.hw_version, sizeof(eiter->a.hw_version), + "HW:%s", ha->adapter_id); + } + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a5, + "HARDWARE VERSION = %s.\n", eiter->a.hw_version); /* Driver version. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION); - snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version), - "%s", qla2x00_version_str); - alen = strlen(eiter->a.driver_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x202b, - "Driver ver = %s.\n", eiter->a.driver_version); - + alen = scnprintf( + eiter->a.driver_version, sizeof(eiter->a.driver_version), + "%s", qla2x00_version_str); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a6, + "DRIVER VERSION = %s.\n", eiter->a.driver_version); /* Option ROM version. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); - snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version), - "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); - alen = strlen(eiter->a.orom_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha , 0x202c, - "Optrom vers = %s.\n", eiter->a.orom_version); + alen = scnprintf( + eiter->a.orom_version, sizeof(eiter->a.orom_version), + "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a7, + "OPTROM VERSION = %d.%02d.\n", + eiter->a.orom_version[1], eiter->a.orom_version[0]); /* Firmware version */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); ha->isp_ops->fw_version_str(vha, eiter->a.fw_version, sizeof(eiter->a.fw_version)); - alen = strlen(eiter->a.fw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x202d, - "Firmware vers = %s.\n", eiter->a.fw_version); - - /* Update MS request size. */ - qla2x00_update_ms_fdmi_iocb(vha, size + 16); - - ql_dbg(ql_dbg_disc, vha, 0x202e, - "RHBA identifier = %8phN size=%d.\n", - ct_req->req.rhba.hba_identifier, size); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076, - entries, size); - - /* Execute MS IOCB */ - rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x2030, - "RHBA issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; - if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && - ct_rsp->header.explanation_code == - CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x2034, - "HBA already registered.\n"); - rval = QLA_ALREADY_REGISTERED; - } else { - ql_dbg(ql_dbg_disc, vha, 0x20ad, - "RHBA FDMI registration failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", - ct_rsp->header.reason_code, - ct_rsp->header.explanation_code); - } - } else { - ql_dbg(ql_dbg_disc, vha, 0x2035, - "RHBA exiting normally.\n"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a8, + "FIRMWARE VERSION = %s.\n", eiter->a.fw_version); + if (callopt == CALLOPT_FDMI1) + goto done; + /* OS Name and Version */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION); + alen = 0; + if (p_sysid) { + alen = scnprintf( + eiter->a.os_version, sizeof(eiter->a.os_version), + "%s %s %s", + p_sysid->sysname, p_sysid->release, p_sysid->machine); } - - return rval; + if (!alen) { + alen = scnprintf( + eiter->a.os_version, sizeof(eiter->a.os_version), + "%s %s", + "Linux", fc_host_system_hostname(vha->host)); + } + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20a9, + "OS VERSION = %s.\n", eiter->a.os_version); + /* MAX CT Payload Length */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH); + eiter->a.max_ct_len = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ? + icb24->frame_payload_size : ha->init_cb->frame_payload_size)); + alen = sizeof(eiter->a.max_ct_len); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20aa, + "CT PAYLOAD LENGTH = 0x%x.\n", be32_to_cpu(eiter->a.max_ct_len)); + /* Node Sybolic Name */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME); + alen = qla2x00_get_sym_node_name(vha, eiter->a.sym_name, + sizeof(eiter->a.sym_name)); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ab, + "SYMBOLIC NAME = %s.\n", eiter->a.sym_name); + /* Vendor Specific information */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_SPECIFIC_INFO); + eiter->a.vendor_specific_info = cpu_to_be32(PCI_VENDOR_ID_QLOGIC); + alen = sizeof(eiter->a.vendor_specific_info); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ac, + "VENDOR SPECIFIC INFO = 0x%x.\n", + be32_to_cpu(eiter->a.vendor_specific_info)); + /* Num Ports */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS); + eiter->a.num_ports = cpu_to_be32(1); + alen = sizeof(eiter->a.num_ports); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ad, + "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports)); + /* Fabric Name */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME); + memcpy(eiter->a.fabric_name, vha->fabric_node_name, + sizeof(eiter->a.fabric_name)); + alen = sizeof(eiter->a.fabric_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ae, + "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); + /* BIOS Version */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME); + alen = scnprintf( + eiter->a.bios_name, sizeof(eiter->a.bios_name), + "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20af, + "BIOS NAME = %s\n", eiter->a.bios_name); + /* Vendor Identifier */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_IDENTIFIER); + alen = scnprintf( + eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier), + "%s", "QLGC"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20b0, + "VENDOR IDENTIFIER = %s.\n", eiter->a.vendor_identifier); +done: + return size; } /** - * qla2x00_fdmi_rpa() - perform RPA registration + * qla2x00_port_attributes() perform Port attributes registration * @vha: HA context + * @entries: number of entries to use + * @callopt: Option to issue extended or standard FDMI + * command parameter * * Returns 0 on success. */ -static int -qla2x00_fdmi_rpa(scsi_qla_host_t *vha) +static unsigned long +qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries, + unsigned int callopt) { - int rval, alen; - uint32_t size; struct qla_hw_data *ha = vha->hw; - ms_iocb_entry_t *ms_pkt; - struct ct_sns_req *ct_req; - struct ct_sns_rsp *ct_rsp; - void *entries; + struct init_cb_24xx *icb24 = (void *)ha->init_cb; + struct new_utsname *p_sysid = utsname(); + char *hostname = p_sysid ? + p_sysid->nodename : fc_host_system_hostname(vha->host); struct ct_fdmi_port_attr *eiter; - struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb; - struct new_utsname *p_sysid = NULL; - - /* Issue RPA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE); - - /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, - RPA_RSP_SIZE); - ct_rsp = &ha->ct_sns->p.rsp; - - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE); - size = WWN_SIZE + 4; - - /* Attributes */ - ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT); - entries = &ct_req->req; + uint16_t alen; + unsigned long size = 0; /* FC4 types. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES); - eiter->len = cpu_to_be16(4 + 32); + eiter->a.fc4_types[0] = 0x00; + eiter->a.fc4_types[1] = 0x00; eiter->a.fc4_types[2] = 0x01; - size += 4 + 32; - - ql_dbg(ql_dbg_disc, vha, 0x2039, - "FC4_TYPES=%02x %02x.\n", - eiter->a.fc4_types[2], - eiter->a.fc4_types[1]); - + eiter->a.fc4_types[3] = 0x00; + alen = sizeof(eiter->a.fc4_types); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c0, + "FC4 TYPES = %016llx.\n", *(uint64_t *)eiter->a.fc4_types); + if (vha->flags.nvme_enabled) { + eiter->a.fc4_types[6] = 1; /* NVMe type 28h */ + ql_dbg(ql_dbg_disc, vha, 0x211f, + "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", + eiter->a.fc4_types[6]); + } /* Supported speed. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); - eiter->len = cpu_to_be16(4 + 4); - if (IS_CNA_CAPABLE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_10GB); - else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_32GB| - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB); - else if (IS_QLA2031(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB); - else if (IS_QLA25XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA24XX_TYPE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA23XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_1GB); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x203a, - "Supported_Speed=%x.\n", eiter->a.sup_speed); - + eiter->a.sup_speed = cpu_to_be32( + qla25xx_fdmi_port_speed_capability(ha)); + alen = sizeof(eiter->a.sup_speed); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c1, + "SUPPORTED SPEED = %x.\n", be32_to_cpu(eiter->a.sup_speed)); /* Current speed. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED); - eiter->len = cpu_to_be16(4 + 4); - switch (ha->link_data_rate) { - case PORT_SPEED_1GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_1GB); - break; - case PORT_SPEED_2GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_2GB); - break; - case PORT_SPEED_4GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_4GB); - break; - case PORT_SPEED_8GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_8GB); - break; - case PORT_SPEED_10GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_10GB); - break; - case PORT_SPEED_16GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_16GB); - break; - case PORT_SPEED_32GB: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_32GB); - break; - default: - eiter->a.cur_speed = - cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN); - break; - } - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x203b, - "Current_Speed=%x.\n", eiter->a.cur_speed); - + eiter->a.cur_speed = cpu_to_be32( + qla25xx_fdmi_port_speed_currently(ha)); + alen = sizeof(eiter->a.cur_speed); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c2, + "CURRENT SPEED = %x.\n", be32_to_cpu(eiter->a.cur_speed)); /* Max frame size. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); - eiter->len = cpu_to_be16(4 + 4); - eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ? - le16_to_cpu(icb24->frame_payload_size) : - le16_to_cpu(ha->init_cb->frame_payload_size); - eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x203c, - "Max_Frame_Size=%x.\n", eiter->a.max_frame_size); - + eiter->a.max_frame_size = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ? + icb24->frame_payload_size : ha->init_cb->frame_payload_size)); + alen = sizeof(eiter->a.max_frame_size); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c3, + "MAX FRAME SIZE = %x.\n", be32_to_cpu(eiter->a.max_frame_size)); /* OS device name. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); - snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), - "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); - alen = strlen(eiter->a.os_dev_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x204b, - "OS_Device_Name=%s.\n", eiter->a.os_dev_name); - + alen = scnprintf( + eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), + "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c4, + "OS DEVICE NAME = %s.\n", eiter->a.os_dev_name); /* Hostname. */ eiter = entries + size; eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); - p_sysid = utsname(); - if (p_sysid) { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", p_sysid->nodename); - } else { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", fc_host_system_hostname(vha->host)); - } - alen = strlen(eiter->a.host_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x203d, "HostName=%s.\n", eiter->a.host_name); - - /* Update MS request size. */ - qla2x00_update_ms_fdmi_iocb(vha, size + 16); - - ql_dbg(ql_dbg_disc, vha, 0x203e, - "RPA portname %016llx, size = %d.\n", - wwn_to_u64(ct_req->req.rpa.port_name), size); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079, - entries, size); - - /* Execute MS IOCB */ - rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x2040, - "RPA issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; - if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && - ct_rsp->header.explanation_code == - CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x20cd, - "RPA already registered.\n"); - rval = QLA_ALREADY_REGISTERED; - } - - } else { - ql_dbg(ql_dbg_disc, vha, 0x2041, - "RPA exiting normally.\n"); - } - - return rval; -} - -/** - * qla2x00_fdmiv2_rhba() - perform RHBA FDMI v2 registration - * @vha: HA context - * - * Returns 0 on success. - */ -static int -qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha) -{ - int rval, alen; - uint32_t size, sn; - ms_iocb_entry_t *ms_pkt; - struct ct_sns_req *ct_req; - struct ct_sns_rsp *ct_rsp; - void *entries; - struct ct_fdmiv2_hba_attr *eiter; - struct qla_hw_data *ha = vha->hw; - struct new_utsname *p_sysid = NULL; - - /* Issue RHBA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE); - - /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, - RHBA_RSP_SIZE); - ct_rsp = &ha->ct_sns->p.rsp; - - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rhba2.hba_identifier, vha->port_name, WWN_SIZE); - ct_req->req.rhba2.entry_count = cpu_to_be32(1); - memcpy(ct_req->req.rhba2.port_name, vha->port_name, WWN_SIZE); - size = 2 * WWN_SIZE + 4 + 4; + if (!*hostname || !strncmp(hostname, "(none)", 6)) + hostname = "Linux-default"; + alen = scnprintf( + eiter->a.host_name, sizeof(eiter->a.host_name), + "%s", hostname); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c5, + "HOSTNAME = %s.\n", eiter->a.host_name); - /* Attributes */ - ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT); - entries = &ct_req->req; + if (callopt == CALLOPT_FDMI1) + goto done; - /* Nodename. */ + /* Node Name */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x207d, - "NodeName = %016llx.\n", wwn_to_u64(eiter->a.node_name)); + eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME); + memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name)); + alen = sizeof(eiter->a.node_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c6, + "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name)); - /* Manufacturer. */ + /* Port Name */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER); - snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer), - "%s", "QLogic Corporation"); - eiter->a.manufacturer[strlen("QLogic Corporation")] = '\0'; - alen = strlen(eiter->a.manufacturer); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a5, - "Manufacturer = %s.\n", eiter->a.manufacturer); + eiter->type = cpu_to_be16(FDMI_PORT_NAME); + memcpy(eiter->a.port_name, vha->port_name, sizeof(eiter->a.port_name)); + alen = sizeof(eiter->a.port_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c7, + "PORTNAME = %016llx.\n", wwn_to_u64(eiter->a.port_name)); - /* Serial number. */ + /* Port Symbolic Name */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); - if (IS_FWI2_CAPABLE(ha)) - qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num, - sizeof(eiter->a.serial_num)); - else { - sn = ((ha->serial0 & 0x1f) << 16) | - (ha->serial2 << 8) | ha->serial1; - snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num), - "%c%05d", 'A' + sn / 100000, sn % 100000); - } - alen = strlen(eiter->a.serial_num); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a6, - "Serial no. = %s.\n", eiter->a.serial_num); + eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME); + alen = qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name, + sizeof(eiter->a.port_sym_name)); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c8, + "PORT SYMBOLIC NAME = %s\n", eiter->a.port_sym_name); - /* Model name. */ + /* Port Type */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_MODEL); - snprintf(eiter->a.model, sizeof(eiter->a.model), - "%s", ha->model_number); - alen = strlen(eiter->a.model); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a7, - "Model Name = %s.\n", eiter->a.model); - - /* Model description. */ + eiter->type = cpu_to_be16(FDMI_PORT_TYPE); + eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE); + alen = sizeof(eiter->a.port_type); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20c9, + "PORT TYPE = %x.\n", be32_to_cpu(eiter->a.port_type)); + + /* Supported Class of Service */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); - snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc), - "%s", ha->model_desc); - alen = strlen(eiter->a.model_desc); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a8, - "Model Desc = %s.\n", eiter->a.model_desc); + eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS); + eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3); + alen = sizeof(eiter->a.port_supported_cos); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ca, + "SUPPORTED COS = %08x\n", be32_to_cpu(eiter->a.port_supported_cos)); - /* Hardware version. */ + /* Port Fabric Name */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); - if (!IS_FWI2_CAPABLE(ha)) { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); - } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version, - sizeof(eiter->a.hw_version))) { - ; - } else { - snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), - "HW:%s", ha->adapter_id); - } - alen = strlen(eiter->a.hw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20a9, - "Hardware ver = %s.\n", eiter->a.hw_version); + eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME); + memcpy(eiter->a.fabric_name, vha->fabric_node_name, + sizeof(eiter->a.fabric_name)); + alen = sizeof(eiter->a.fabric_name); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cb, + "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); - /* Driver version. */ + /* FC4_type */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION); - snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version), - "%s", qla2x00_version_str); - alen = strlen(eiter->a.driver_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20aa, - "Driver ver = %s.\n", eiter->a.driver_version); + eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE); + eiter->a.port_fc4_type[0] = 0x00; + eiter->a.port_fc4_type[1] = 0x00; + eiter->a.port_fc4_type[2] = 0x01; + eiter->a.port_fc4_type[3] = 0x00; + alen = sizeof(eiter->a.port_fc4_type); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cc, + "PORT ACTIVE FC4 TYPE = %016llx.\n", + *(uint64_t *)eiter->a.port_fc4_type); - /* Option ROM version. */ + /* Port State */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); - snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version), - "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); - alen = strlen(eiter->a.orom_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha , 0x20ab, - "Optrom version = %d.%02d.\n", eiter->a.orom_version[1], - eiter->a.orom_version[0]); + eiter->type = cpu_to_be16(FDMI_PORT_STATE); + eiter->a.port_state = cpu_to_be32(2); + alen = sizeof(eiter->a.port_state); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cd, + "PORT_STATE = %x.\n", be32_to_cpu(eiter->a.port_state)); - /* Firmware version */ + /* Number of Ports */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); - ha->isp_ops->fw_version_str(vha, eiter->a.fw_version, - sizeof(eiter->a.fw_version)); - alen = strlen(eiter->a.fw_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20ac, - "Firmware vers = %s.\n", eiter->a.fw_version); - - /* OS Name and Version */ + eiter->type = cpu_to_be16(FDMI_PORT_COUNT); + eiter->a.num_ports = cpu_to_be32(1); + alen = sizeof(eiter->a.num_ports); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20ce, + "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports)); + + /* Port Identifier */ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION); - p_sysid = utsname(); - if (p_sysid) { - snprintf(eiter->a.os_version, sizeof(eiter->a.os_version), - "%s %s %s", - p_sysid->sysname, p_sysid->release, p_sysid->version); - } else { - snprintf(eiter->a.os_version, sizeof(eiter->a.os_version), - "%s %s", "Linux", fc_host_system_hostname(vha->host)); - } - alen = strlen(eiter->a.os_version); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20ae, - "OS Name and Version = %s.\n", eiter->a.os_version); + eiter->type = cpu_to_be16(FDMI_PORT_IDENTIFIER); + eiter->a.port_id = cpu_to_be32(vha->d_id.b24); + alen = sizeof(eiter->a.port_id); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20cf, + "PORT ID = %x.\n", be32_to_cpu(eiter->a.port_id)); + + if (callopt == CALLOPT_FDMI2 || !ql2xsmartsan) + goto done; - /* MAX CT Payload Length */ + /* Smart SAN Service Category (Populate Smart SAN Initiator)*/ eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH); - eiter->a.max_ct_len = cpu_to_be32(ha->frame_payload_size); - eiter->a.max_ct_len = cpu_to_be32(eiter->a.max_ct_len); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_SERVICE); + alen = scnprintf( + eiter->a.smartsan_service, sizeof(eiter->a.smartsan_service), + "%s", "Smart SAN Initiator"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d0, + "SMARTSAN SERVICE CATEGORY = %s.\n", eiter->a.smartsan_service); + + /* Smart SAN GUID (NWWN+PWWN) */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_GUID); + memcpy(eiter->a.smartsan_guid, vha->node_name, WWN_SIZE); + memcpy(eiter->a.smartsan_guid + WWN_SIZE, vha->port_name, WWN_SIZE); + alen = sizeof(eiter->a.smartsan_guid); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d1, + "Smart SAN GUID = %016llx-%016llx\n", + wwn_to_u64(eiter->a.smartsan_guid), + wwn_to_u64(eiter->a.smartsan_guid + WWN_SIZE)); + + /* Smart SAN Version (populate "Smart SAN Version 1.0") */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_VERSION); + alen = scnprintf( + eiter->a.smartsan_version, sizeof(eiter->a.smartsan_version), + "%s", "Smart SAN Version 2.0"); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d2, + "SMARTSAN VERSION = %s\n", eiter->a.smartsan_version); + + /* Smart SAN Product Name (Specify Adapter Model No) */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_PROD_NAME); + alen = scnprintf(eiter->a.smartsan_prod_name, + sizeof(eiter->a.smartsan_prod_name), + "ISP%04x", ha->pdev->device); + alen += FDMI_ATTR_ALIGNMENT(alen); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d3, + "SMARTSAN PRODUCT NAME = %s\n", eiter->a.smartsan_prod_name); + + /* Smart SAN Port Info (specify: 1=Physical, 2=NPIV, 3=SRIOV) */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_PORT_INFO); + eiter->a.smartsan_port_info = cpu_to_be32(vha->vp_idx ? 2 : 1); + alen = sizeof(eiter->a.smartsan_port_info); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d4, + "SMARTSAN PORT INFO = %x\n", eiter->a.smartsan_port_info); + + /* Smart SAN Security Support */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_SMARTSAN_SECURITY_SUPPORT); + eiter->a.smartsan_security_support = cpu_to_be32(1); + alen = sizeof(eiter->a.smartsan_security_support); + alen += FDMI_ATTR_TYPELEN(eiter); + eiter->len = cpu_to_be16(alen); + size += alen; + ql_dbg(ql_dbg_disc, vha, 0x20d6, + "SMARTSAN SECURITY SUPPORT = %d\n", + be32_to_cpu(eiter->a.smartsan_security_support)); - ql_dbg(ql_dbg_disc, vha, 0x20af, - "CT Payload Length = 0x%x.\n", eiter->a.max_ct_len); +done: + return size; +} - /* Node Sybolic Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME); - qla2x00_get_sym_node_name(vha, eiter->a.sym_name, - sizeof(eiter->a.sym_name)); - alen = strlen(eiter->a.sym_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; +/** + * qla2x00_fdmi_rhba() - perform RHBA FDMI registration + * @vha: HA context + * @callopt: Option to issue FDMI registration + * + * Returns 0 on success. + */ +static int +qla2x00_fdmi_rhba(scsi_qla_host_t *vha, unsigned int callopt) +{ + struct qla_hw_data *ha = vha->hw; + unsigned long size = 0; + unsigned int rval, count; + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + void *entries; - ql_dbg(ql_dbg_disc, vha, 0x20b0, - "Symbolic Name = %s.\n", eiter->a.sym_name); + count = callopt != CALLOPT_FDMI1 ? + FDMI2_HBA_ATTR_COUNT : FDMI1_HBA_ATTR_COUNT; - /* Vendor Id */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_ID); - eiter->a.vendor_id = cpu_to_be32(0x1077); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; + size = RHBA_RSP_SIZE; - ql_dbg(ql_dbg_disc, vha, 0x20b1, - "Vendor Id = %x.\n", eiter->a.vendor_id); + ql_dbg(ql_dbg_disc, vha, 0x20e0, + "RHBA (callopt=%x count=%u size=%lu).\n", callopt, count, size); - /* Num Ports */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS); - eiter->a.num_ports = cpu_to_be32(1); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; + /* Request size adjusted after CT preparation */ + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); - ql_dbg(ql_dbg_disc, vha, 0x20b2, - "Port Num = %x.\n", eiter->a.num_ports); + /* Prepare CT request */ + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, size); + ct_rsp = &ha->ct_sns->p.rsp; - /* Fabric Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME); - memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; + /* Prepare FDMI command entries */ + memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, + sizeof(ct_req->req.rhba.hba_identifier)); + size += sizeof(ct_req->req.rhba.hba_identifier); - ql_dbg(ql_dbg_disc, vha, 0x20b3, - "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); + ct_req->req.rhba.entry_count = cpu_to_be32(1); + size += sizeof(ct_req->req.rhba.entry_count); - /* BIOS Version */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME); - snprintf(eiter->a.bios_name, sizeof(eiter->a.bios_name), - "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]); - alen = strlen(eiter->a.bios_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; + memcpy(ct_req->req.rhba.port_name, vha->port_name, + sizeof(ct_req->req.rhba.port_name)); + size += sizeof(ct_req->req.rhba.port_name); - ql_dbg(ql_dbg_disc, vha, 0x20b4, - "BIOS Name = %s\n", eiter->a.bios_name); + /* Attribute count */ + ct_req->req.rhba.attrs.count = cpu_to_be32(count); + size += sizeof(ct_req->req.rhba.attrs.count); - /* Vendor Identifier */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER); - snprintf(eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier), - "%s", "QLGC"); - alen = strlen(eiter->a.vendor_identifier); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; + /* Attribute block */ + entries = &ct_req->req.rhba.attrs.entry; - ql_dbg(ql_dbg_disc, vha, 0x201b, - "Vendor Identifier = %s.\n", eiter->a.vendor_identifier); + size += qla2x00_hba_attributes(vha, entries, callopt); /* Update MS request size. */ qla2x00_update_ms_fdmi_iocb(vha, size + 16); - ql_dbg(ql_dbg_disc, vha, 0x20b5, - "RHBA identifier = %016llx.\n", - wwn_to_u64(ct_req->req.rhba2.hba_identifier)); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20b6, + ql_dbg(ql_dbg_disc, vha, 0x20e1, + "RHBA %016llx %016llx.\n", + wwn_to_u64(ct_req->req.rhba.hba_identifier), + wwn_to_u64(ct_req->req.rhba.port_name)); + + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20e2, entries, size); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x20b7, - "RHBA issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; + sizeof(*ha->ms_iocb)); + if (rval) { + ql_dbg(ql_dbg_disc, vha, 0x20e3, + "RHBA iocb failed (%d).\n", rval); + return rval; + } + rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA"); + if (rval) { if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && ct_rsp->header.explanation_code == CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x20b8, - "HBA already registered.\n"); - rval = QLA_ALREADY_REGISTERED; - } else { - ql_dbg(ql_dbg_disc, vha, 0x2016, - "RHBA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", - ct_rsp->header.reason_code, - ct_rsp->header.explanation_code); + ql_dbg(ql_dbg_disc, vha, 0x20e4, + "RHBA already registered.\n"); + return QLA_ALREADY_REGISTERED; } - } else { - ql_dbg(ql_dbg_disc, vha, 0x20b9, - "RHBA FDMI V2 exiting normally.\n"); + + ql_dbg(ql_dbg_disc, vha, 0x20e5, + "RHBA failed, CT Reason %#x, CT Explanation %#x\n", + ct_rsp->header.reason_code, + ct_rsp->header.explanation_code); + return rval; } + ql_dbg(ql_dbg_disc, vha, 0x20e6, "RHBA exiting normally.\n"); return rval; } -/** - * qla2x00_fdmi_dhba() - - * @vha: HA context - * - * Returns 0 on success. - */ + static int qla2x00_fdmi_dhba(scsi_qla_host_t *vha) { @@ -2250,22 +2236,17 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha) ms_iocb_entry_t *ms_pkt; struct ct_sns_req *ct_req; struct ct_sns_rsp *ct_rsp; - /* Issue RPA */ /* Prepare common MS IOCB */ ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE, DHBA_RSP_SIZE); - /* Prepare CT request */ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; - /* Prepare FDMI command arguments -- portname. */ memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE); - ql_dbg(ql_dbg_disc, vha, 0x2036, "DHBA portname = %8phN.\n", ct_req->req.dhba.port_name); - /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, sizeof(ms_iocb_entry_t)); @@ -2280,337 +2261,178 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha) ql_dbg(ql_dbg_disc, vha, 0x2038, "DHBA exiting normally.\n"); } - return rval; } /** - * qla2x00_fdmiv2_rpa() - + * qla2x00_fdmi_rprt() perform RPRT registration * @vha: HA context + * @callopt: Option to issue extended or standard FDMI + * command parameter * * Returns 0 on success. */ static int -qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) +qla2x00_fdmi_rprt(scsi_qla_host_t *vha, int callopt) { - int rval, alen; - uint32_t size; + struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev); struct qla_hw_data *ha = vha->hw; + ulong size = 0; + uint rval, count; ms_iocb_entry_t *ms_pkt; struct ct_sns_req *ct_req; struct ct_sns_rsp *ct_rsp; void *entries; - struct ct_fdmiv2_port_attr *eiter; - struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb; - struct new_utsname *p_sysid = NULL; - - /* Issue RPA */ - /* Prepare common MS IOCB */ - /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE); - + count = callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ? + FDMI2_SMARTSAN_PORT_ATTR_COUNT : + callopt != CALLOPT_FDMI1 ? + FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT; + + size = RPRT_RSP_SIZE; + ql_dbg(ql_dbg_disc, vha, 0x20e8, + "RPRT (callopt=%x count=%u size=%lu).\n", callopt, count, size); + /* Request size adjusted after CT preparation */ + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE); + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPRT_CMD, size); ct_rsp = &ha->ct_sns->p.rsp; - - /* Prepare FDMI command arguments -- attribute block, attributes. */ - memcpy(ct_req->req.rpa2.port_name, vha->port_name, WWN_SIZE); - size = WWN_SIZE + 4; - - /* Attributes */ - ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT); - entries = &ct_req->req; - - /* FC4 types. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES); - eiter->len = cpu_to_be16(4 + 32); - eiter->a.fc4_types[2] = 0x01; - size += 4 + 32; - - ql_dbg(ql_dbg_disc, vha, 0x20ba, - "FC4_TYPES=%02x %02x.\n", - eiter->a.fc4_types[2], - eiter->a.fc4_types[1]); - - if (vha->flags.nvme_enabled) { - eiter->a.fc4_types[6] = 1; /* NVMe type 28h */ - ql_dbg(ql_dbg_disc, vha, 0x211f, - "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", - eiter->a.fc4_types[6]); - } - - /* Supported speed. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); - eiter->len = cpu_to_be16(4 + 4); - if (IS_CNA_CAPABLE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_10GB); - else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_32GB| - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB); - else if (IS_QLA2031(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_16GB| - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB); - else if (IS_QLA25XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_8GB| - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA24XX_TYPE(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_4GB| - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else if (IS_QLA23XX(ha)) - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_2GB| - FDMI_PORT_SPEED_1GB); - else - eiter->a.sup_speed = cpu_to_be32( - FDMI_PORT_SPEED_1GB); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20bb, - "Supported Port Speed = %x.\n", eiter->a.sup_speed); - - /* Current speed. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED); - eiter->len = cpu_to_be16(4 + 4); - switch (ha->link_data_rate) { - case PORT_SPEED_1GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_1GB); - break; - case PORT_SPEED_2GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_2GB); - break; - case PORT_SPEED_4GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_4GB); - break; - case PORT_SPEED_8GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_8GB); - break; - case PORT_SPEED_10GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_10GB); - break; - case PORT_SPEED_16GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_16GB); - break; - case PORT_SPEED_32GB: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_32GB); - break; - default: - eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN); - break; + /* Prepare FDMI command entries */ + memcpy(ct_req->req.rprt.hba_identifier, base_vha->port_name, + sizeof(ct_req->req.rprt.hba_identifier)); + size += sizeof(ct_req->req.rprt.hba_identifier); + memcpy(ct_req->req.rprt.port_name, vha->port_name, + sizeof(ct_req->req.rprt.port_name)); + size += sizeof(ct_req->req.rprt.port_name); + /* Attribute count */ + ct_req->req.rprt.attrs.count = cpu_to_be32(count); + size += sizeof(ct_req->req.rprt.attrs.count); + /* Attribute block */ + entries = ct_req->req.rprt.attrs.entry; + size += qla2x00_port_attributes(vha, entries, callopt); + /* Update MS request size. */ + qla2x00_update_ms_fdmi_iocb(vha, size + 16); + ql_dbg(ql_dbg_disc, vha, 0x20e9, + "RPRT %016llx %016llx.\n", + wwn_to_u64(ct_req->req.rprt.port_name), + wwn_to_u64(ct_req->req.rprt.port_name)); + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ea, + entries, size); + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, + sizeof(*ha->ms_iocb)); + if (rval) { + ql_dbg(ql_dbg_disc, vha, 0x20eb, + "RPRT iocb failed (%d).\n", rval); + return rval; } - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x2017, - "Current_Speed = %x.\n", eiter->a.cur_speed); - - /* Max frame size. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); - eiter->len = cpu_to_be16(4 + 4); - eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ? - le16_to_cpu(icb24->frame_payload_size) : - le16_to_cpu(ha->init_cb->frame_payload_size); - eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20bc, - "Max_Frame_Size = %x.\n", eiter->a.max_frame_size); - - /* OS device name. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); - alen = strlen(QLA2XXX_DRIVER_NAME); - snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), - "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20be, - "OS_Device_Name = %s.\n", eiter->a.os_dev_name); + rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPRT"); + if (rval) { + if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && + ct_rsp->header.explanation_code == + CT_EXPL_ALREADY_REGISTERED) { + ql_dbg(ql_dbg_disc, vha, 0x20ec, + "RPRT already registered.\n"); + return QLA_ALREADY_REGISTERED; + } - /* Hostname. */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); - p_sysid = utsname(); - if (p_sysid) { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", p_sysid->nodename); - } else { - snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), - "%s", fc_host_system_hostname(vha->host)); + ql_dbg(ql_dbg_disc, vha, 0x20ed, + "RPRT failed, CT Reason code: %#x, CT Explanation %#x\n", + ct_rsp->header.reason_code, + ct_rsp->header.explanation_code); + return rval; } - alen = strlen(eiter->a.host_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x201a, - "HostName=%s.\n", eiter->a.host_name); - - /* Node Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME); - memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x20c0, - "Node Name = %016llx.\n", wwn_to_u64(eiter->a.node_name)); - - /* Port Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_NAME); - memcpy(eiter->a.port_name, vha->port_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; - - ql_dbg(ql_dbg_disc, vha, 0x20c1, - "Port Name = %016llx.\n", wwn_to_u64(eiter->a.port_name)); - - /* Port Symbolic Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME); - qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name, - sizeof(eiter->a.port_sym_name)); - alen = strlen(eiter->a.port_sym_name); - alen += 4 - (alen & 3); - eiter->len = cpu_to_be16(4 + alen); - size += 4 + alen; - - ql_dbg(ql_dbg_disc, vha, 0x20c2, - "port symbolic name = %s\n", eiter->a.port_sym_name); - - /* Port Type */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_TYPE); - eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c3, - "Port Type = %x.\n", eiter->a.port_type); - - /* Class of Service */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS); - eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c4, - "Supported COS = %08x\n", eiter->a.port_supported_cos); + ql_dbg(ql_dbg_disc, vha, 0x20ee, "RPRT exiting normally.\n"); + return rval; +} - /* Port Fabric Name */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME); - memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE); - eiter->len = cpu_to_be16(4 + WWN_SIZE); - size += 4 + WWN_SIZE; +/** + * qla2x00_fdmi_rpa() - perform RPA registration + * @vha: HA context + * @callopt: Option to issue FDMI registration + * + * Returns 0 on success. + */ +static int +qla2x00_fdmi_rpa(scsi_qla_host_t *vha, uint callopt) +{ + struct qla_hw_data *ha = vha->hw; + ulong size = 0; + uint rval, count; + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + void *entries; - ql_dbg(ql_dbg_disc, vha, 0x20c5, - "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); + count = + callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ? + FDMI2_SMARTSAN_PORT_ATTR_COUNT : + callopt != CALLOPT_FDMI1 ? + FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT; - /* FC4_type */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE); - eiter->a.port_fc4_type[0] = 0; - eiter->a.port_fc4_type[1] = 0; - eiter->a.port_fc4_type[2] = 1; - eiter->a.port_fc4_type[3] = 0; - eiter->len = cpu_to_be16(4 + 32); - size += 4 + 32; + size = + callopt != CALLOPT_FDMI1 ? + SMARTSAN_RPA_RSP_SIZE : RPA_RSP_SIZE; - ql_dbg(ql_dbg_disc, vha, 0x20c6, - "Port Active FC4 Type = %02x %02x.\n", - eiter->a.port_fc4_type[2], eiter->a.port_fc4_type[1]); + ql_dbg(ql_dbg_disc, vha, 0x20f0, + "RPA (callopt=%x count=%u size=%lu).\n", callopt, count, size); - if (vha->flags.nvme_enabled) { - eiter->a.port_fc4_type[4] = 0; - eiter->a.port_fc4_type[5] = 0; - eiter->a.port_fc4_type[6] = 1; /* NVMe type 28h */ - ql_dbg(ql_dbg_disc, vha, 0x2120, - "NVME Port Active FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", - eiter->a.port_fc4_type[6]); - } + /* Request size adjusted after CT preparation */ + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); - /* Port State */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_STATE); - eiter->a.port_state = cpu_to_be32(1); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; + /* Prepare CT request */ + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, size); + ct_rsp = &ha->ct_sns->p.rsp; - ql_dbg(ql_dbg_disc, vha, 0x20c7, - "Port State = %x.\n", eiter->a.port_state); + /* Prepare FDMI command entries. */ + memcpy(ct_req->req.rpa.port_name, vha->port_name, + sizeof(ct_req->req.rpa.port_name)); + size += sizeof(ct_req->req.rpa.port_name); - /* Number of Ports */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_COUNT); - eiter->a.num_ports = cpu_to_be32(1); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; - - ql_dbg(ql_dbg_disc, vha, 0x20c8, - "Number of ports = %x.\n", eiter->a.num_ports); + /* Attribute count */ + ct_req->req.rpa.attrs.count = cpu_to_be32(count); + size += sizeof(ct_req->req.rpa.attrs.count); - /* Port Id */ - eiter = entries + size; - eiter->type = cpu_to_be16(FDMI_PORT_ID); - eiter->a.port_id = cpu_to_be32(vha->d_id.b24); - eiter->len = cpu_to_be16(4 + 4); - size += 4 + 4; + /* Attribute block */ + entries = ct_req->req.rpa.attrs.entry; - ql_dbg(ql_dbg_disc, vha, 0x201c, - "Port Id = %x.\n", eiter->a.port_id); + size += qla2x00_port_attributes(vha, entries, callopt); /* Update MS request size. */ qla2x00_update_ms_fdmi_iocb(vha, size + 16); - ql_dbg(ql_dbg_disc, vha, 0x2018, - "RPA portname= %8phN size=%d.\n", ct_req->req.rpa.port_name, size); - ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ca, + ql_dbg(ql_dbg_disc, vha, 0x20f1, + "RPA %016llx.\n", wwn_to_u64(ct_req->req.rpa.port_name)); + + ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20f2, entries, size); /* Execute MS IOCB */ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, - sizeof(ms_iocb_entry_t)); - if (rval != QLA_SUCCESS) { - /*EMPTY*/ - ql_dbg(ql_dbg_disc, vha, 0x20cb, - "RPA FDMI v2 issue IOCB failed (%d).\n", rval); - } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") != - QLA_SUCCESS) { - rval = QLA_FUNCTION_FAILED; + sizeof(*ha->ms_iocb)); + if (rval) { + ql_dbg(ql_dbg_disc, vha, 0x20f3, + "RPA iocb failed (%d).\n", rval); + return rval; + } + + rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA"); + if (rval) { if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && ct_rsp->header.explanation_code == CT_EXPL_ALREADY_REGISTERED) { - ql_dbg(ql_dbg_disc, vha, 0x20ce, - "RPA FDMI v2 already registered\n"); - rval = QLA_ALREADY_REGISTERED; - } else { - ql_dbg(ql_dbg_disc, vha, 0x2020, - "RPA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", - ct_rsp->header.reason_code, - ct_rsp->header.explanation_code); + ql_dbg(ql_dbg_disc, vha, 0x20f4, + "RPA already registered.\n"); + return QLA_ALREADY_REGISTERED; } - } else { - ql_dbg(ql_dbg_disc, vha, 0x20cc, - "RPA FDMI V2 exiting normally.\n"); + + ql_dbg(ql_dbg_disc, vha, 0x20f5, + "RPA failed, CT Reason code: %#x, CT Explanation %#x\n", + ct_rsp->header.reason_code, + ct_rsp->header.explanation_code); + return rval; } + ql_dbg(ql_dbg_disc, vha, 0x20f6, "RPA exiting normally.\n"); return rval; } @@ -2623,18 +2445,31 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) int qla2x00_fdmi_register(scsi_qla_host_t *vha) { - int rval = QLA_FUNCTION_FAILED; + int rval = QLA_SUCCESS; struct qla_hw_data *ha = vha->hw; if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLAFX00(ha)) - return QLA_FUNCTION_FAILED; + return rval; rval = qla2x00_mgmt_svr_login(vha); if (rval) return rval; - rval = qla2x00_fdmiv2_rhba(vha); + /* For npiv/vport send rprt only */ + if (vha->vp_idx) { + if (ql2xsmartsan) + rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2_SMARTSAN); + if (rval || !ql2xsmartsan) + rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2); + if (rval) + rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI1); + + return rval; + } + + /* Try fdmi2 first, if fails then try fdmi1 */ + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2); if (rval) { if (rval != QLA_ALREADY_REGISTERED) goto try_fdmi; @@ -2643,18 +2478,22 @@ qla2x00_fdmi_register(scsi_qla_host_t *vha) if (rval) goto try_fdmi; - rval = qla2x00_fdmiv2_rhba(vha); + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2); if (rval) goto try_fdmi; } - rval = qla2x00_fdmiv2_rpa(vha); + + if (ql2xsmartsan) + rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2_SMARTSAN); + if (rval || !ql2xsmartsan) + rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2); if (rval) goto try_fdmi; - goto out; + return rval; try_fdmi: - rval = qla2x00_fdmi_rhba(vha); + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1); if (rval) { if (rval != QLA_ALREADY_REGISTERED) return rval; @@ -2663,12 +2502,13 @@ try_fdmi: if (rval) return rval; - rval = qla2x00_fdmi_rhba(vha); + rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1); if (rval) return rval; } - rval = qla2x00_fdmi_rpa(vha); -out: + + rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI1); + return rval; } @@ -2893,7 +2733,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list) for (i = 0; i < ha->max_fibre_devices; i++) { /* Set default FC4 Type as UNKNOWN so the default is to * Process this port */ - list[i].fc4_type = FC4_TYPE_UNKNOWN; + list[i].fc4_type = 0; /* Do not attempt GFF_ID if we are not FWI_2 capable */ if (!IS_FWI2_CAPABLE(ha)) @@ -3243,7 +3083,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) "%s %d %8phC post new sess\n", __func__, __LINE__, ea->port_name); qla24xx_post_newsess_work(vha, &ea->id, - ea->port_name, NULL, NULL, FC4_TYPE_UNKNOWN); + ea->port_name, NULL, NULL, 0); } } } @@ -3647,6 +3487,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE)) continue; fcport->scan_state = QLA_FCPORT_FOUND; + fcport->last_rscn_gen = fcport->rscn_gen; found = true; /* * If device was not a fabric device before. diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 9e6b56527b25..5b2deaa730bf 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1043,7 +1043,7 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) __func__, __LINE__, (u8 *)&wwn, id.b24); wwnn = wwn_to_u64(e->node_name); qla24xx_post_newsess_work(vha, &id, (u8 *)&wwn, - (u8 *)&wwnn, NULL, FC4_TYPE_UNKNOWN); + (u8 *)&wwnn, NULL, 0); } } @@ -2219,10 +2219,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) /* Check for secure flash support */ if (IS_QLA28XX(ha)) { - if (RD_REG_DWORD(®->mailbox12) & BIT_0) { - ql_log(ql_log_info, vha, 0xffff, "Adapter is Secure\n"); + if (RD_REG_DWORD(®->mailbox12) & BIT_0) ha->flags.secure_adapter = 1; - } + ql_log(ql_log_info, vha, 0xffff, "Secure Adapter: %s\n", + (ha->flags.secure_adapter) ? "Yes" : "No"); } @@ -2270,6 +2270,12 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) ql_dbg(ql_dbg_init, vha, 0x0078, "Verifying loaded RISC code...\n"); + /* If smartsan enabled then require fdmi and rdp enabled */ + if (ql2xsmartsan) { + ql2xfdmienable = 1; + ql2xrdpenable = 1; + } + if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) { rval = ha->isp_ops->chip_diag(vha); if (rval) @@ -3544,53 +3550,77 @@ static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha) } -/* - * Return Code: - * QLA_SUCCESS: no action - * QLA_INTERFACE_ERROR: SFP is not there. - * QLA_FUNCTION_FAILED: detected New SFP +/** + * qla24xx_detect_sfp() + * + * @vha: adapter state pointer. + * + * @return + * 0 -- Configure firmware to use short-range settings -- normal + * buffer-to-buffer credits. + * + * 1 -- Configure firmware to use long-range settings -- extra + * buffer-to-buffer credits should be allocated with + * ha->lr_distance containing distance settings from NVRAM or SFP + * (if supported). */ int qla24xx_detect_sfp(scsi_qla_host_t *vha) { - int rc = QLA_SUCCESS; + int rc, used_nvram; struct sff_8247_a0 *a; struct qla_hw_data *ha = vha->hw; - - if (!AUTO_DETECT_SFP_SUPPORT(vha)) + struct nvram_81xx *nv = ha->nvram; +#define LR_DISTANCE_UNKNOWN 2 + static const char * const types[] = { "Short", "Long" }; + static const char * const lengths[] = { "(10km)", "(5km)", "" }; + u8 ll = 0; + + /* Seed with NVRAM settings. */ + used_nvram = 0; + ha->flags.lr_detected = 0; + if (IS_BPM_RANGE_CAPABLE(ha) && + (nv->enhanced_features & NEF_LR_DIST_ENABLE)) { + used_nvram = 1; + ha->flags.lr_detected = 1; + ha->lr_distance = + (nv->enhanced_features >> LR_DIST_NV_POS) + & LR_DIST_NV_MASK; + } + + if (!IS_BPM_ENABLED(vha)) goto out; - + /* Determine SR/LR capabilities of SFP/Transceiver. */ rc = qla2x00_read_sfp_dev(vha, NULL, 0); if (rc) goto out; + used_nvram = 0; a = (struct sff_8247_a0 *)vha->hw->sfp_data; qla2xxx_print_sfp_info(vha); - if (a->fc_ll_cc7 & FC_LL_VL || a->fc_ll_cc7 & FC_LL_L) { - /* long range */ - ha->flags.detected_lr_sfp = 1; + ha->flags.lr_detected = 0; + ll = a->fc_ll_cc7; + if (ll & FC_LL_VL || ll & FC_LL_L) { + /* Long range, track length. */ + ha->flags.lr_detected = 1; if (a->length_km > 5 || a->length_100m > 50) - ha->long_range_distance = LR_DISTANCE_10K; + ha->lr_distance = LR_DISTANCE_10K; else - ha->long_range_distance = LR_DISTANCE_5K; - - if (ha->flags.detected_lr_sfp != ha->flags.using_lr_setting) - ql_dbg(ql_dbg_async, vha, 0x507b, - "Detected Long Range SFP.\n"); - } else { - /* short range */ - ha->flags.detected_lr_sfp = 0; - if (ha->flags.using_lr_setting) - ql_dbg(ql_dbg_async, vha, 0x5084, - "Detected Short Range SFP.\n"); + ha->lr_distance = LR_DISTANCE_5K; } if (!vha->flags.init_done) rc = QLA_SUCCESS; out: - return rc; + ql_dbg(ql_dbg_async, vha, 0x507b, + "SFP detect: %s-Range SFP %s (nvr=%x ll=%x lr=%x lrd=%x).\n", + types[ha->flags.lr_detected], + ha->flags.lr_detected ? lengths[ha->lr_distance] : + lengths[LR_DISTANCE_UNKNOWN], + used_nvram, ll, ha->flags.lr_detected, ha->lr_distance); + return ha->flags.lr_detected; } /** @@ -3608,6 +3638,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; unsigned long flags; uint16_t fw_major_version; + int done_once = 0; if (IS_P3P_TYPE(ha)) { rval = ha->isp_ops->load_risc(vha, &srisc_address); @@ -3628,6 +3659,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) qla81xx_mpi_sync(vha); +execute_fw_with_lr: /* Load firmware sequences */ rval = ha->isp_ops->load_risc(vha, &srisc_address); if (rval == QLA_SUCCESS) { @@ -3649,7 +3681,15 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) rval = qla2x00_execute_fw(vha, srisc_address); /* Retrieve firmware information. */ if (rval == QLA_SUCCESS) { - qla24xx_detect_sfp(vha); + /* Enable BPM support? */ + if (!done_once++ && qla24xx_detect_sfp(vha)) { + ql_dbg(ql_dbg_init, vha, 0x00ca, + "Re-starting firmware -- BPM.\n"); + /* Best-effort - re-init. */ + ha->isp_ops->reset_chip(vha); + ha->isp_ops->chip_diag(vha); + goto execute_fw_with_lr; + } if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) && @@ -3708,6 +3748,10 @@ enable_82xx_npiv: "ISP Firmware failed checksum.\n"); goto failed; } + + /* Enable PUREX PASSTHRU */ + if (ql2xrdpenable) + qla25xx_set_els_cmds_supported(vha); } else goto failed; @@ -3919,6 +3963,13 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ha->fw_options[2] &= ~BIT_8; } + if (ql2xrdpenable) + ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + + /* Enable Async 8130/8131 events -- transceiver insertion/removal */ + if (IS_BPM_RANGE_CAPABLE(ha)) + ha->fw_options[3] |= BIT_10; + ql_dbg(ql_dbg_init, vha, 0x00e8, "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", __func__, ha->fw_options[1], ha->fw_options[2], @@ -5060,7 +5111,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) if (N2N_TOPO(ha)) { if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) { /* borrowing */ - u32 *bp, i, sz; + u32 *bp, sz; memset(ha->init_cb, 0, ha->init_cb_size); sz = min_t(int, sizeof(struct els_plogi_payload), @@ -5068,13 +5119,12 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, (void *)ha->init_cb, sz); if (rval == QLA_SUCCESS) { + __be32 *q = &ha->plogi_els_payld.data[0]; + bp = (uint32_t *)ha->init_cb; - for (i = 0; i < sz/4 ; i++, bp++) - *bp = cpu_to_be32(*bp); + cpu_to_be32_array(q, bp, sz / 4); - memcpy(&ha->plogi_els_payld.data, - (void *)ha->init_cb, - sizeof(ha->plogi_els_payld.data)); + memcpy(bp, q, sizeof(ha->plogi_els_payld.data)); } else { ql_dbg(ql_dbg_init, vha, 0x00d1, "PLOGI ELS param read fail.\n"); @@ -5097,6 +5147,7 @@ skip_login: set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); } + return QLA_FUNCTION_FAILED; } found_devs = 0; @@ -5541,24 +5592,22 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) } vha->device_flags |= SWITCH_FOUND; + rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_port_name, 0); + if (rval != QLA_SUCCESS) + ql_dbg(ql_dbg_disc, vha, 0x20ff, + "Failed to get Fabric Port Name\n"); if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) { rval = qla2x00_send_change_request(vha, 0x3, 0); if (rval != QLA_SUCCESS) ql_log(ql_log_warn, vha, 0x121, - "Failed to enable receiving of RSCN requests: 0x%x.\n", - rval); + "Failed to enable receiving of RSCN requests: 0x%x.\n", + rval); } - do { qla2x00_mgmt_svr_login(vha); - /* FDMI support. */ - if (ql2xfdmienable && - test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags)) - qla2x00_fdmi_register(vha); - /* Ensure we are logged into the SNS. */ loop_id = NPH_SNS_LID(ha); rval = ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff, @@ -5570,6 +5619,12 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); return rval; } + + /* FDMI support. */ + if (ql2xfdmienable && + test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags)) + qla2x00_fdmi_register(vha); + if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) { if (qla2x00_rft_id(vha)) { /* EMPTY */ @@ -5812,7 +5867,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha) /* Bypass ports whose FCP-4 type is not FCP_SCSI */ if (ql2xgffidenable && (!(new_fcport->fc4_type & FS_FC4TYPE_FCP) && - new_fcport->fc4_type != FC4_TYPE_UNKNOWN)) + new_fcport->fc4_type != 0)) continue; spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); @@ -6656,7 +6711,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) ha->flags.n2n_ae = 0; ha->flags.lip_ae = 0; ha->current_topology = 0; - ha->flags.fw_started = 0; + QLA_FW_STOPPED(ha); ha->flags.fw_init_done = 0; ha->chip_reset++; ha->base_qpair->chip_reset = ha->chip_reset; @@ -8663,61 +8718,6 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) return status; } -void -qla81xx_update_fw_options(scsi_qla_host_t *vha) -{ - struct qla_hw_data *ha = vha->hw; - - /* Hold status IOCBs until ABTS response received. */ - if (ql2xfwholdabts) - ha->fw_options[3] |= BIT_12; - - /* Set Retry FLOGI in case of P2P connection */ - if (ha->operating_mode == P2P) { - ha->fw_options[2] |= BIT_3; - ql_dbg(ql_dbg_disc, vha, 0x2103, - "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n", - __func__, ha->fw_options[2]); - } - - /* Move PUREX, ABTS RX & RIDA to ATIOQ */ - if (ql2xmvasynctoatio) { - if (qla_tgt_mode_enabled(vha) || - qla_dual_mode_enabled(vha)) - ha->fw_options[2] |= BIT_11; - else - ha->fw_options[2] &= ~BIT_11; - } - - if (qla_tgt_mode_enabled(vha) || - qla_dual_mode_enabled(vha)) { - /* FW auto send SCSI status during */ - ha->fw_options[1] |= BIT_8; - ha->fw_options[10] |= (u16)SAM_STAT_BUSY << 8; - - /* FW perform Exchange validation */ - ha->fw_options[2] |= BIT_4; - } else { - ha->fw_options[1] &= ~BIT_8; - ha->fw_options[10] &= 0x00ff; - - ha->fw_options[2] &= ~BIT_4; - } - - if (ql2xetsenable) { - /* Enable ETS Burst. */ - memset(ha->fw_options, 0, sizeof(ha->fw_options)); - ha->fw_options[2] |= BIT_9; - } - - ql_dbg(ql_dbg_init, vha, 0x00e9, - "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", - __func__, ha->fw_options[1], ha->fw_options[2], - ha->fw_options[3], vha->host->active_mode); - - qla2x00_set_fw_options(vha, ha->fw_options); -} - /* * qla24xx_get_fcp_prio * Gets the fcp cmd priority value for the logged in port. diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 47bf60a9490a..182bd68c79ac 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -530,7 +530,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair, int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); mrk24->vp_index = vha->vp_idx; - mrk24->handle = MAKE_HANDLE(req->id, mrk24->handle); + mrk24->handle = make_handle(req->id, mrk24->handle); } else { SET_TARGET_ID(ha, mrk->target, loop_id); mrk->lun = cpu_to_le16((uint16_t)lun); @@ -1655,7 +1655,7 @@ qla24xx_start_scsi(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -1843,7 +1843,7 @@ qla24xx_dif_start_scsi(srb_t *sp) /* Fill-in common area */ cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); clr_ptr = (uint32_t *)cmd_pkt + 2; memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); @@ -1975,7 +1975,7 @@ qla2xxx_start_scsi_mq(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -2178,7 +2178,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) /* Fill-in common area */ cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); clr_ptr = (uint32_t *)cmd_pkt + 2; memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); @@ -2362,6 +2362,8 @@ qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) struct srb_iocb *lio = &sp->u.iocb_cmd; logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; + logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); + if (lio->u.logio.flags & SRB_LOGIN_PRLI_ONLY) { logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI); } else { @@ -2489,7 +2491,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) tsk->entry_type = TSK_MGMT_IOCB_TYPE; tsk->entry_count = 1; - tsk->handle = MAKE_HANDLE(req->id, tsk->handle); + tsk->handle = make_handle(req->id, tsk->handle); tsk->nport_handle = cpu_to_le16(fcport->loop_id); tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); tsk->control_flags = cpu_to_le32(flags); @@ -2684,9 +2686,9 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->rx_dsd_count = 0; els_iocb->opcode = elsio->u.els_logo.els_cmd; - els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; - els_iocb->port_id[1] = sp->fcport->d_id.b.area; - els_iocb->port_id[2] = sp->fcport->d_id.b.domain; + els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa; + els_iocb->d_id[1] = sp->fcport->d_id.b.area; + els_iocb->d_id[2] = sp->fcport->d_id.b.domain; /* For SID the byte order is different than DID */ els_iocb->s_id[1] = vha->d_id.b.al_pa; els_iocb->s_id[2] = vha->d_id.b.area; @@ -2939,7 +2941,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, sp->fcport = fcport; elsio->timeout = qla2x00_els_dcmd2_iocb_timeout; - init_completion(&elsio->u.els_plogi.comp); if (wait) sp->flags = SRB_WAKEUP_ON_COMP; @@ -2949,7 +2950,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE; ptr = elsio->u.els_plogi.els_plogi_pyld = - dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.tx_size, &elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL); if (!elsio->u.els_plogi.els_plogi_pyld) { @@ -2958,7 +2959,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, } resp_ptr = elsio->u.els_plogi.els_resp_pyld = - dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.rx_size, &elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL); if (!elsio->u.els_plogi.els_resp_pyld) { @@ -2982,6 +2983,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, sizeof(*elsio->u.els_plogi.els_plogi_pyld)); + init_completion(&elsio->u.els_plogi.comp); rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { rval = QLA_FUNCTION_FAILED; @@ -3030,9 +3032,9 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) sp->type == SRB_ELS_CMD_RPT ? bsg_request->rqst_data.r_els.els_code : bsg_request->rqst_data.h_els.command_code; - els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; - els_iocb->port_id[1] = sp->fcport->d_id.b.area; - els_iocb->port_id[2] = sp->fcport->d_id.b.domain; + els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa; + els_iocb->d_id[1] = sp->fcport->d_id.b.area; + els_iocb->d_id[2] = sp->fcport->d_id.b.domain; els_iocb->control_flags = 0; els_iocb->rx_byte_count = cpu_to_le32(bsg_job->reply_payload.payload_len); @@ -3358,7 +3360,7 @@ sufficient_dsds: } cmd_pkt = (struct cmd_type_6 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -3429,7 +3431,7 @@ sufficient_dsds: goto queuing_error; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ @@ -3534,7 +3536,7 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb) memset(abt_iocb, 0, sizeof(struct abort_entry_24xx)); abt_iocb->entry_type = ABORT_IOCB_TYPE; abt_iocb->entry_count = 1; - abt_iocb->handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); + abt_iocb->handle = cpu_to_le32(make_handle(req->id, sp->handle)); if (sp->fcport) { abt_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); abt_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; @@ -3542,7 +3544,7 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb) abt_iocb->port_id[2] = sp->fcport->d_id.b.domain; } abt_iocb->handle_to_abort = - cpu_to_le32(MAKE_HANDLE(aio->u.abt.req_que_no, + cpu_to_le32(make_handle(aio->u.abt.req_que_no, aio->u.abt.cmd_hndl)); abt_iocb->vp_index = vha->vp_idx; abt_iocb->req_que_no = cpu_to_le16(aio->u.abt.req_que_no); @@ -3905,7 +3907,7 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) } cmd_pkt = (struct cmd_bidir *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index e40705d38cea..8d7a905f6247 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -31,6 +31,144 @@ const char *const port_state_str[] = { "ONLINE" }; +static void qla24xx_purex_iocb(scsi_qla_host_t *vha, void *pkt, + void (*process_item)(struct scsi_qla_host *vha, void *pkt)) +{ + struct purex_list *list = &vha->purex_list; + struct purex_item *item; + ulong flags; + + item = kzalloc(sizeof(*item), GFP_KERNEL); + if (!item) { + ql_log(ql_log_warn, vha, 0x5092, + ">> Failed allocate purex list item.\n"); + return; + } + + item->vha = vha; + item->process_item = process_item; + memcpy(&item->iocb, pkt, sizeof(item->iocb)); + + spin_lock_irqsave(&list->lock, flags); + list_add_tail(&item->list, &list->head); + spin_unlock_irqrestore(&list->lock, flags); + + set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); +} + +static void +qla24xx_process_abts(struct scsi_qla_host *vha, void *pkt) +{ + struct abts_entry_24xx *abts = pkt; + struct qla_hw_data *ha = vha->hw; + struct els_entry_24xx *rsp_els; + struct abts_entry_24xx *abts_rsp; + dma_addr_t dma; + uint32_t fctl; + int rval; + + ql_dbg(ql_dbg_init, vha, 0x0286, "%s: entered.\n", __func__); + + ql_log(ql_log_warn, vha, 0x0287, + "Processing ABTS xchg=%#x oxid=%#x rxid=%#x seqid=%#x seqcnt=%#x\n", + abts->rx_xch_addr_to_abort, abts->ox_id, abts->rx_id, + abts->seq_id, abts->seq_cnt); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0287, + "-------- ABTS RCV -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0287, + (uint8_t *)abts, sizeof(*abts)); + + rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), &dma, + GFP_KERNEL); + if (!rsp_els) { + ql_log(ql_log_warn, vha, 0x0287, + "Failed allocate dma buffer ABTS/ELS RSP.\n"); + return; + } + + /* terminate exchange */ + memset(rsp_els, 0, sizeof(*rsp_els)); + rsp_els->entry_type = ELS_IOCB_TYPE; + rsp_els->entry_count = 1; + rsp_els->nport_handle = ~0; + rsp_els->rx_xchg_address = abts->rx_xch_addr_to_abort; + rsp_els->control_flags = EPD_RX_XCHG; + ql_dbg(ql_dbg_init, vha, 0x0283, + "Sending ELS Response to terminate exchange %#x...\n", + abts->rx_xch_addr_to_abort); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0283, + "-------- ELS RSP -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0283, + (uint8_t *)rsp_els, sizeof(*rsp_els)); + rval = qla2x00_issue_iocb(vha, rsp_els, dma, 0); + if (rval) { + ql_log(ql_log_warn, vha, 0x0288, + "%s: iocb failed to execute -> %x\n", __func__, rval); + } else if (rsp_els->comp_status) { + ql_log(ql_log_warn, vha, 0x0289, + "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", + __func__, rsp_els->comp_status, + rsp_els->error_subcode_1, rsp_els->error_subcode_2); + } else { + ql_dbg(ql_dbg_init, vha, 0x028a, + "%s: abort exchange done.\n", __func__); + } + + /* send ABTS response */ + abts_rsp = (void *)rsp_els; + memset(abts_rsp, 0, sizeof(*abts_rsp)); + abts_rsp->entry_type = ABTS_RSP_TYPE; + abts_rsp->entry_count = 1; + abts_rsp->nport_handle = abts->nport_handle; + abts_rsp->vp_idx = abts->vp_idx; + abts_rsp->sof_type = abts->sof_type & 0xf0; + abts_rsp->rx_xch_addr = abts->rx_xch_addr; + abts_rsp->d_id[0] = abts->s_id[0]; + abts_rsp->d_id[1] = abts->s_id[1]; + abts_rsp->d_id[2] = abts->s_id[2]; + abts_rsp->r_ctl = FC_ROUTING_BLD | FC_R_CTL_BLD_BA_ACC; + abts_rsp->s_id[0] = abts->d_id[0]; + abts_rsp->s_id[1] = abts->d_id[1]; + abts_rsp->s_id[2] = abts->d_id[2]; + abts_rsp->cs_ctl = abts->cs_ctl; + /* include flipping bit23 in fctl */ + fctl = ~(abts->f_ctl[2] | 0x7F) << 16 | + FC_F_CTL_LAST_SEQ | FC_F_CTL_END_SEQ | FC_F_CTL_SEQ_INIT; + abts_rsp->f_ctl[0] = fctl >> 0 & 0xff; + abts_rsp->f_ctl[1] = fctl >> 8 & 0xff; + abts_rsp->f_ctl[2] = fctl >> 16 & 0xff; + abts_rsp->type = FC_TYPE_BLD; + abts_rsp->rx_id = abts->rx_id; + abts_rsp->ox_id = abts->ox_id; + abts_rsp->payload.ba_acc.aborted_rx_id = abts->rx_id; + abts_rsp->payload.ba_acc.aborted_ox_id = abts->ox_id; + abts_rsp->payload.ba_acc.high_seq_cnt = ~0; + abts_rsp->rx_xch_addr_to_abort = abts->rx_xch_addr_to_abort; + ql_dbg(ql_dbg_init, vha, 0x028b, + "Sending BA ACC response to ABTS %#x...\n", + abts->rx_xch_addr_to_abort); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x028b, + "-------- ELS RSP -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x028b, + (uint8_t *)abts_rsp, sizeof(*abts_rsp)); + rval = qla2x00_issue_iocb(vha, abts_rsp, dma, 0); + if (rval) { + ql_log(ql_log_warn, vha, 0x028c, + "%s: iocb failed to execute -> %x\n", __func__, rval); + } else if (abts_rsp->comp_status) { + ql_log(ql_log_warn, vha, 0x028d, + "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", + __func__, abts_rsp->comp_status, + abts_rsp->payload.error.subcode1, + abts_rsp->payload.error.subcode2); + } else { + ql_dbg(ql_dbg_init, vha, 0x028ea, + "%s: done.\n", __func__); + } + + dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, dma); +} + /** * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. * @irq: interrupt number @@ -716,12 +854,24 @@ skip_rio: break; case MBA_SYSTEM_ERR: /* System Error */ - mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || - IS_QLA28XX(ha)) ? - RD_REG_WORD(®24->mailbox7) : 0; - ql_log(ql_log_warn, vha, 0x5003, - "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh " - "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx); + mbx = 0; + if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || + IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + u16 m[4]; + + m[0] = RD_REG_WORD(®24->mailbox4); + m[1] = RD_REG_WORD(®24->mailbox5); + m[2] = RD_REG_WORD(®24->mailbox6); + mbx = m[3] = RD_REG_WORD(®24->mailbox7); + + ql_log(ql_log_warn, vha, 0x5003, + "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh mbx4=%xh mbx5=%xh mbx6=%xh mbx7=%xh.\n", + mb[1], mb[2], mb[3], m[0], m[1], m[2], m[3]); + } else + ql_log(ql_log_warn, vha, 0x5003, + "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n ", + mb[1], mb[2], mb[3]); + ha->fw_dump_mpi = (IS_QLA27XX(ha) || IS_QLA28XX(ha)) && RD_REG_WORD(®24->mailbox7) & BIT_8; @@ -813,13 +963,15 @@ skip_rio: "LOOP UP detected (%s Gbps).\n", qla2x00_get_link_speed_str(ha, ha->link_data_rate)); + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + if (mb[2] & BIT_0) + ql_log(ql_log_info, vha, 0x11a0, + "FEC=enabled (link up).\n"); + } + vha->flags.management_server_logged_in = 0; qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); - if (AUTO_DETECT_SFP_SUPPORT(vha)) { - set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags); - qla2xxx_wake_dpc(vha); - } break; case MBA_LOOP_DOWN: /* Loop Down Event */ @@ -1254,6 +1406,7 @@ global_port_update: ql_dbg(ql_dbg_async, vha, 0x5052, "D-Port Diagnostics: %04x %04x %04x %04x\n", mb[0], mb[1], mb[2], mb[3]); + memcpy(vha->dport_data, mb, sizeof(vha->dport_data)); if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { static char *results[] = { "start", "done(pass)", "done(error)", "undefined" }; @@ -1291,6 +1444,11 @@ global_port_update: case MBA_TRANS_INSERT: ql_dbg(ql_dbg_async, vha, 0x5091, "Transceiver Insertion: %04x\n", mb[1]); + set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags); + break; + + case MBA_TRANS_REMOVE: + ql_dbg(ql_dbg_async, vha, 0x5091, "Transceiver Removal\n"); break; default: @@ -1754,11 +1912,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, } if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) { - ql_dbg(ql_dbg_async, fcport->vha, 0x5036, - "Async-%s complete - %8phC hdl=%x portid=%02x%02x%02x " - "iop0=%x.\n", type, fcport->port_name, sp->handle, - fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa, + ql_dbg(ql_dbg_async, sp->vha, 0x5036, + "Async-%s complete: handle=%x pid=%06x wwpn=%8phC iop0=%x\n", + type, sp->handle, fcport->d_id.b24, fcport->port_name, le32_to_cpu(logio->io_parameter[0])); vha->hw->exch_starvation = 0; @@ -1837,11 +1993,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, break; } - ql_dbg(ql_dbg_async, fcport->vha, 0x5037, - "Async-%s failed - %8phC hdl=%x portid=%02x%02x%02x comp=%x " - "iop0=%x iop1=%x.\n", type, fcport->port_name, - sp->handle, fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa, + ql_dbg(ql_dbg_async, sp->vha, 0x5037, + "Async-%s failed: handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n", + type, sp->handle, fcport->d_id.b24, fcport->port_name, le16_to_cpu(logio->comp_status), le32_to_cpu(logio->io_parameter[0]), le32_to_cpu(logio->io_parameter[1])); @@ -1910,6 +2064,7 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, struct nvmefc_fcp_req *fd; uint16_t ret = QLA_SUCCESS; uint16_t comp_status = le16_to_cpu(sts->comp_status); + int logit = 0; iocb = &sp->u.iocb_cmd; fcport = sp->fcport; @@ -1920,6 +2075,12 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, if (unlikely(iocb->u.nvme.aen_op)) atomic_dec(&sp->vha->hw->nvme_active_aen_cnt); + if (unlikely(comp_status != CS_COMPLETE)) + logit = 1; + + fd->transferred_length = fd->payload_length - + le32_to_cpu(sts->residual_len); + /* * State flags: Bit 6 and 0. * If 0 is set, we don't care about 6. @@ -1930,8 +2091,20 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, */ if (!(state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP))) { iocb->u.nvme.rsp_pyld_len = 0; - } else if ((state_flags & SF_FCP_RSP_DMA)) { + } else if ((state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP)) == + (SF_FCP_RSP_DMA | SF_NVME_ERSP)) { + /* Response already DMA'd to fd->rspaddr. */ iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len); + } else if ((state_flags & SF_FCP_RSP_DMA)) { + /* + * Non-zero value in first 12 bytes of NVMe_RSP IU, treat this + * as an error. + */ + iocb->u.nvme.rsp_pyld_len = 0; + fd->transferred_length = 0; + ql_dbg(ql_dbg_io, fcport->vha, 0x307a, + "Unexpected values in NVMe_RSP IU.\n"); + logit = 1; } else if (state_flags & SF_NVME_ERSP) { uint32_t *inbuf, *outbuf; uint16_t iter; @@ -1954,16 +2127,28 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, iter = iocb->u.nvme.rsp_pyld_len >> 2; for (; iter; iter--) *outbuf++ = swab32(*inbuf++); - } else { /* unhandled case */ - ql_log(ql_log_warn, fcport->vha, 0x503a, - "NVME-%s error. Unhandled state_flags of %x\n", - sp->name, state_flags); } - fd->transferred_length = fd->payload_length - - le32_to_cpu(sts->residual_len); + if (state_flags & SF_NVME_ERSP) { + struct nvme_fc_ersp_iu *rsp_iu = fd->rspaddr; + u32 tgt_xfer_len; - if (unlikely(comp_status != CS_COMPLETE)) + tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len); + if (fd->transferred_length != tgt_xfer_len) { + ql_dbg(ql_dbg_io, fcport->vha, 0x3079, + "Dropped frame(s) detected (sent/rcvd=%u/%u).\n", + tgt_xfer_len, fd->transferred_length); + logit = 1; + } else if (comp_status == CS_DATA_UNDERRUN) { + /* + * Do not log if this is just an underflow and there + * is no data loss. + */ + logit = 0; + } + } + + if (unlikely(logit)) ql_log(ql_log_warn, fcport->vha, 0x5060, "NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n", sp->name, sp->handle, comp_status, @@ -2516,11 +2701,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) return; } - if (sp->abort) - sp->aborted = 1; - else - sp->completed = 1; - if (sp->cmd_type != TYPE_SRB) { req->outstanding_cmds[handle] = NULL; ql_dbg(ql_dbg_io, vha, 0x3015, @@ -3083,6 +3263,11 @@ process_err: qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); break; case ABTS_RECV_24XX: + if (qla_ini_mode_enabled(vha)) { + qla24xx_purex_iocb(vha, pkt, + qla24xx_process_abts); + break; + } if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { /* ensure that the ATIO queue is empty */ @@ -3127,6 +3312,19 @@ process_err: qla_ctrlvp_completed(vha, rsp->req, (struct vp_ctrl_entry_24xx *)pkt); break; + case PUREX_IOCB_TYPE: + { + struct purex_entry_24xx *purex = (void *)pkt; + + if (purex->els_frame_payload[3] != ELS_COMMAND_RDP) { + ql_dbg(ql_dbg_init, vha, 0x5091, + "Discarding ELS Request opcode %#x...\n", + purex->els_frame_payload[3]); + break; + } + qla24xx_purex_iocb(vha, pkt, qla24xx_process_purex_rdp); + break; + } default: /* Type Not Supported. */ ql_dbg(ql_dbg_async, vha, 0x5042, @@ -3442,6 +3640,25 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id) { struct qla_hw_data *ha; struct qla_qpair *qpair; + + qpair = dev_id; + if (!qpair) { + ql_log(ql_log_info, NULL, 0x505b, + "%s: NULL response queue pointer.\n", __func__); + return IRQ_NONE; + } + ha = qpair->hw; + + queue_work(ha->wq, &qpair->q_work); + + return IRQ_HANDLED; +} + +irqreturn_t +qla2xxx_msix_rsp_q_hs(int irq, void *dev_id) +{ + struct qla_hw_data *ha; + struct qla_qpair *qpair; struct device_reg_24xx __iomem *reg; unsigned long flags; @@ -3453,13 +3670,10 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id) } ha = qpair->hw; - /* Clear the interrupt, if enabled, for this response queue */ - if (unlikely(!ha->flags.disable_msix_handshake)) { - reg = &ha->iobase->isp24; - spin_lock_irqsave(&ha->hardware_lock, flags); - WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - } + reg = &ha->iobase->isp24; + spin_lock_irqsave(&ha->hardware_lock, flags); + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + spin_unlock_irqrestore(&ha->hardware_lock, flags); queue_work(ha->wq, &qpair->q_work); @@ -3478,6 +3692,7 @@ static const struct qla_init_msix_entry msix_entries[] = { { "rsp_q", qla24xx_msix_rsp_q }, { "atio_q", qla83xx_msix_atio_q }, { "qpair_multiq", qla2xxx_msix_rsp_q }, + { "qpair_multiq_hs", qla2xxx_msix_rsp_q_hs }, }; static const struct qla_init_msix_entry qla82xx_msix_entries[] = { diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 9e09964f5c0e..9fd83d1bffe0 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -117,10 +117,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__); - if (ha->pdev->error_state > pci_channel_io_frozen) { + if (ha->pdev->error_state == pci_channel_io_perm_failure) { ql_log(ql_log_warn, vha, 0x1001, - "error_state is greater than pci_channel_io_frozen, " - "exiting.\n"); + "PCI channel failed permanently, exiting.\n"); return QLA_FUNCTION_TIMEOUT; } @@ -643,30 +642,7 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, return rval; } -#define EXTENDED_BB_CREDITS BIT_0 #define NVME_ENABLE_FLAG BIT_3 -static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha) -{ - uint16_t mb4 = BIT_0; - - if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) - mb4 |= ha->long_range_distance << LR_DIST_FW_POS; - - return mb4; -} - -static inline uint16_t qla25xx_set_nvr_lr_dist(struct qla_hw_data *ha) -{ - uint16_t mb4 = BIT_0; - - if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { - struct nvram_81xx *nv = ha->nvram; - - mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features); - } - - return mb4; -} /* * qla2x00_execute_fw @@ -690,10 +666,14 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) struct qla_hw_data *ha = vha->hw; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; + u8 semaphore = 0; +#define EXE_FW_FORCE_SEMAPHORE BIT_7 + u8 retry = 3; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025, "Entered %s.\n", __func__); +again: mcp->mb[0] = MBC_EXECUTE_FIRMWARE; mcp->out_mb = MBX_0; mcp->in_mb = MBX_0; @@ -703,25 +683,13 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) mcp->mb[3] = 0; mcp->mb[4] = 0; mcp->mb[11] = 0; - ha->flags.using_lr_setting = 0; - if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || - IS_QLA27XX(ha) || IS_QLA28XX(ha)) { - if (ql2xautodetectsfp) { - if (ha->flags.detected_lr_sfp) { - mcp->mb[4] |= - qla25xx_set_sfp_lr_dist(ha); - ha->flags.using_lr_setting = 1; - } - } else { - struct nvram_81xx *nv = ha->nvram; - /* set LR distance if specified in nvram */ - if (nv->enhanced_features & - NEF_LR_DIST_ENABLE) { - mcp->mb[4] |= - qla25xx_set_nvr_lr_dist(ha); - ha->flags.using_lr_setting = 1; - } - } + + /* Enable BPM? */ + if (ha->flags.lr_detected) { + mcp->mb[4] = BIT_0; + if (IS_BPM_RANGE_CAPABLE(ha)) + mcp->mb[4] |= + ha->lr_distance << LR_DIST_FW_POS; } if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha))) @@ -747,6 +715,9 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) if (ha->flags.exchoffld_enabled) mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD; + if (semaphore) + mcp->mb[11] |= EXE_FW_FORCE_SEMAPHORE; + mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11; mcp->in_mb |= MBX_3 | MBX_2 | MBX_1; } else { @@ -763,6 +734,15 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) rval = qla2x00_mailbox_command(vha, mcp); if (rval != QLA_SUCCESS) { + if (IS_QLA28XX(ha) && rval == QLA_COMMAND_ERROR && + mcp->mb[1] == 0x27 && retry) { + semaphore = 1; + retry--; + ql_dbg(ql_dbg_async, vha, 0x1026, + "Exe FW: force semaphore.\n"); + goto again; + } + ql_dbg(ql_dbg_mbx, vha, 0x1026, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); return rval; @@ -1137,11 +1117,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22]; ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24]; if (IS_QLA28XX(ha)) { - if (mcp->mb[16] & BIT_10) { - ql_log(ql_log_info, vha, 0xffff, - "FW support secure flash updates\n"); + if (mcp->mb[16] & BIT_10) ha->flags.secure_fw = 1; - } + + ql_log(ql_log_info, vha, 0xffff, + "Secure Flash Update in FW: %s\n", + (ha->flags.secure_fw) ? "Supported" : + "Not Supported"); } } @@ -1405,17 +1387,20 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; + if (!vha->hw->flags.fw_started) + return QLA_INVALID_COMMAND; + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038, "Entered %s.\n", __func__); mcp->mb[0] = MBC_IOCB_COMMAND_A64; mcp->mb[1] = 0; - mcp->mb[2] = MSW(phys_addr); - mcp->mb[3] = LSW(phys_addr); + mcp->mb[2] = MSW(LSD(phys_addr)); + mcp->mb[3] = LSW(LSD(phys_addr)); mcp->mb[6] = MSW(MSD(phys_addr)); mcp->mb[7] = LSW(MSD(phys_addr)); mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_2|MBX_0; + mcp->in_mb = MBX_1|MBX_0; mcp->tov = tov; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); @@ -1424,13 +1409,14 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, /*EMPTY*/ ql_dbg(ql_dbg_mbx, vha, 0x1039, "Failed=%x.\n", rval); } else { - sts_entry_t *sts_entry = (sts_entry_t *) buffer; + sts_entry_t *sts_entry = buffer; /* Mask reserved bits. */ sts_entry->entry_status &= IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103a, - "Done %s.\n", __func__); + "Done %s (status=%x).\n", __func__, + sts_entry->entry_status); } return rval; @@ -1475,7 +1461,7 @@ qla2x00_abort_command(srb_t *sp) ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103b, "Entered %s.\n", __func__); - if (vha->flags.qpairs_available && sp->qpair) + if (sp->qpair) req = sp->qpair->req; else req = vha->req; @@ -2045,6 +2031,57 @@ gpd_error_out: return rval; } +int +qla24xx_get_port_database(scsi_qla_host_t *vha, u16 nport_handle, + struct port_database_24xx *pdb) +{ + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + dma_addr_t pdb_dma; + int rval; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1115, + "Entered %s.\n", __func__); + + memset(pdb, 0, sizeof(*pdb)); + + pdb_dma = dma_map_single(&vha->hw->pdev->dev, pdb, + sizeof(*pdb), DMA_FROM_DEVICE); + if (!pdb_dma) { + ql_log(ql_log_warn, vha, 0x1116, "Failed to map dma buffer.\n"); + return QLA_MEMORY_ALLOC_FAILED; + } + + mcp->mb[0] = MBC_GET_PORT_DATABASE; + mcp->mb[1] = nport_handle; + mcp->mb[2] = MSW(LSD(pdb_dma)); + mcp->mb[3] = LSW(LSD(pdb_dma)); + mcp->mb[6] = MSW(MSD(pdb_dma)); + mcp->mb[7] = LSW(MSD(pdb_dma)); + mcp->mb[9] = 0; + mcp->mb[10] = 0; + mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = sizeof(*pdb); + mcp->flags = MBX_DMA_IN; + mcp->tov = vha->hw->login_timeout * 2; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x111a, + "Failed=%x mb[0]=%x mb[1]=%x.\n", + rval, mcp->mb[0], mcp->mb[1]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111b, + "Done %s.\n", __func__); + } + + dma_unmap_single(&vha->hw->pdev->dev, pdb_dma, + sizeof(*pdb), DMA_FROM_DEVICE); + + return rval; +} + /* * qla2x00_get_firmware_state * Get adapter firmware state. @@ -2384,7 +2421,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; lg->entry_count = 1; - lg->handle = MAKE_HANDLE(req->id, lg->handle); + lg->handle = make_handle(req->id, lg->handle); lg->nport_handle = cpu_to_le16(loop_id); lg->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); if (opt & BIT_0) @@ -2654,7 +2691,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, req = vha->req; lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; lg->entry_count = 1; - lg->handle = MAKE_HANDLE(req->id, lg->handle); + lg->handle = make_handle(req->id, lg->handle); lg->nport_handle = cpu_to_le16(loop_id); lg->control_flags = cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO| @@ -3060,18 +3097,19 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - uint32_t *iter, dwords; + uint32_t *iter = (void *)stats; + ushort dwords = sizeof(*stats)/sizeof(*iter); ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088, "Entered %s.\n", __func__); memset(&mc, 0, sizeof(mc)); mc.mb[0] = MBC_GET_LINK_PRIV_STATS; - mc.mb[2] = MSW(stats_dma); - mc.mb[3] = LSW(stats_dma); + mc.mb[2] = MSW(LSD(stats_dma)); + mc.mb[3] = LSW(LSD(stats_dma)); mc.mb[6] = MSW(MSD(stats_dma)); mc.mb[7] = LSW(MSD(stats_dma)); - mc.mb[8] = sizeof(struct link_statistics) / 4; + mc.mb[8] = dwords; mc.mb[9] = cpu_to_le16(vha->vp_idx); mc.mb[10] = cpu_to_le16(options); @@ -3086,8 +3124,6 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a, "Done %s.\n", __func__); /* Re-endianize - firmware data is le32. */ - dwords = sizeof(struct link_statistics) / 4; - iter = &stats->link_fail_cnt; for ( ; dwords--; iter++) le32_to_cpus(iter); } @@ -3145,9 +3181,9 @@ qla24xx_abort_command(srb_t *sp) abt->entry_type = ABORT_IOCB_TYPE; abt->entry_count = 1; - abt->handle = MAKE_HANDLE(req->id, abt->handle); + abt->handle = make_handle(req->id, abt->handle); abt->nport_handle = cpu_to_le16(fcport->loop_id); - abt->handle_to_abort = MAKE_HANDLE(req->id, handle); + abt->handle_to_abort = make_handle(req->id, handle); abt->port_id[0] = fcport->d_id.b.al_pa; abt->port_id[1] = fcport->d_id.b.area; abt->port_id[2] = fcport->d_id.b.domain; @@ -3224,7 +3260,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE; tsk->p.tsk.entry_count = 1; - tsk->p.tsk.handle = MAKE_HANDLE(req->id, tsk->p.tsk.handle); + tsk->p.tsk.handle = make_handle(req->id, tsk->p.tsk.handle); tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id); tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); tsk->p.tsk.control_flags = cpu_to_le32(type); @@ -3888,11 +3924,29 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, fcport->scan_state = QLA_FCPORT_SCAN; fcport->n2n_flag = 0; } + id.b24 = 0; + if (wwn_to_u64(vha->port_name) > + wwn_to_u64(rptid_entry->u.f1.port_name)) { + vha->d_id.b24 = 0; + vha->d_id.b.al_pa = 1; + ha->flags.n2n_bigger = 1; + + id.b.al_pa = 2; + ql_dbg(ql_dbg_async, vha, 0x5075, + "Format 1: assign local id %x remote id %x\n", + vha->d_id.b24, id.b24); + } else { + ql_dbg(ql_dbg_async, vha, 0x5075, + "Format 1: Remote login - Waiting for WWPN %8phC.\n", + rptid_entry->u.f1.port_name); + ha->flags.n2n_bigger = 0; + } fcport = qla2x00_find_fcport_by_wwpn(vha, rptid_entry->u.f1.port_name, 1); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + if (fcport) { fcport->plogi_nack_done_deadline = jiffies + HZ; fcport->dm_login_expire = jiffies + 2*HZ; @@ -3903,6 +3957,11 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, if (vha->flags.nvme_enabled) fcport->fc4_type |= FS_FC4TYPE_NVME; + if (wwn_to_u64(vha->port_name) > + wwn_to_u64(fcport->port_name)) { + fcport->d_id = id; + } + switch (fcport->disc_state) { case DSC_DELETED: set_bit(RELOGIN_NEEDED, @@ -3915,25 +3974,6 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, break; } } else { - id.b24 = 0; - if (wwn_to_u64(vha->port_name) > - wwn_to_u64(rptid_entry->u.f1.port_name)) { - vha->d_id.b24 = 0; - vha->d_id.b.al_pa = 1; - ha->flags.n2n_bigger = 1; - ha->flags.n2n_ae = 0; - - id.b.al_pa = 2; - ql_dbg(ql_dbg_async, vha, 0x5075, - "Format 1: assign local id %x remote id %x\n", - vha->d_id.b24, id.b24); - } else { - ql_dbg(ql_dbg_async, vha, 0x5075, - "Format 1: Remote login - Waiting for WWPN %8phC.\n", - rptid_entry->u.f1.port_name); - ha->flags.n2n_bigger = 0; - ha->flags.n2n_ae = 1; - } qla24xx_post_newsess_work(vha, &id, rptid_entry->u.f1.port_name, rptid_entry->u.f1.node_name, @@ -4827,6 +4867,103 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma, return rval; } +int +qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + uint8_t *els_cmd_map; + dma_addr_t els_cmd_map_dma; + uint cmd_opcode = ELS_COMMAND_RDP; + uint index = cmd_opcode / 8; + uint bit = cmd_opcode % 8; + struct qla_hw_data *ha = vha->hw; + + if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha)) + return QLA_SUCCESS; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197, + "Entered %s.\n", __func__); + + els_cmd_map = dma_alloc_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE, + &els_cmd_map_dma, GFP_KERNEL); + if (!els_cmd_map) { + ql_log(ql_log_warn, vha, 0x7101, + "Failed to allocate RDP els command param.\n"); + return QLA_MEMORY_ALLOC_FAILED; + } + + memset(els_cmd_map, 0, ELS_CMD_MAP_SIZE); + + els_cmd_map[index] |= 1 << bit; + + mcp->mb[0] = MBC_SET_RNID_PARAMS; + mcp->mb[1] = RNID_TYPE_ELS_CMD << 8; + mcp->mb[2] = MSW(LSD(els_cmd_map_dma)); + mcp->mb[3] = LSW(LSD(els_cmd_map_dma)); + mcp->mb[6] = MSW(MSD(els_cmd_map_dma)); + mcp->mb[7] = LSW(MSD(els_cmd_map_dma)); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = MBX_DMA_OUT; + mcp->buf_size = ELS_CMD_MAP_SIZE; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x118d, + "Failed=%x (%x,%x).\n", rval, mcp->mb[0], mcp->mb[1]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c, + "Done %s.\n", __func__); + } + + dma_free_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + els_cmd_map, els_cmd_map_dma); + + return rval; +} + +int +qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc, + dma_addr_t bbc_dma) +{ + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + int rval; + + if (!IS_FWI2_CAPABLE(vha->hw)) + return QLA_FUNCTION_FAILED; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118e, + "Entered %s.\n", __func__); + + mcp->mb[0] = MBC_GET_RNID_PARAMS; + mcp->mb[1] = RNID_BUFFER_CREDITS << 8; + mcp->mb[2] = MSW(LSD(bbc_dma)); + mcp->mb[3] = LSW(LSD(bbc_dma)); + mcp->mb[6] = MSW(MSD(bbc_dma)); + mcp->mb[7] = LSW(MSD(bbc_dma)); + mcp->mb[8] = sizeof(*bbc) / sizeof(*bbc->parameter); + mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->buf_size = sizeof(*bbc); + mcp->flags = MBX_DMA_IN; + mcp->tov = MBX_TOV_SECONDS; + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x118f, + "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1190, + "Done %s.\n", __func__); + } + + return rval; +} + static int qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp) { @@ -4880,8 +5017,8 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, mcp->mb[0] = MBC_READ_SFP; mcp->mb[1] = dev; - mcp->mb[2] = MSW(sfp_dma); - mcp->mb[3] = LSW(sfp_dma); + mcp->mb[2] = MSW(LSD(sfp_dma)); + mcp->mb[3] = LSW(LSD(sfp_dma)); mcp->mb[6] = MSW(MSD(sfp_dma)); mcp->mb[7] = LSW(MSD(sfp_dma)); mcp->mb[8] = len; @@ -4934,8 +5071,8 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, mcp->mb[0] = MBC_WRITE_SFP; mcp->mb[1] = dev; - mcp->mb[2] = MSW(sfp_dma); - mcp->mb[3] = LSW(sfp_dma); + mcp->mb[2] = MSW(LSD(sfp_dma)); + mcp->mb[3] = LSW(LSD(sfp_dma)); mcp->mb[6] = MSW(MSD(sfp_dma)); mcp->mb[7] = LSW(MSD(sfp_dma)); mcp->mb[8] = len; @@ -5170,10 +5307,11 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, mcp->out_mb |= MBX_2; mcp->in_mb = MBX_0; - if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || - IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)) + if (IS_CNA_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || + IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) mcp->in_mb |= MBX_1; - if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)) + if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) mcp->in_mb |= MBX_3; mcp->tov = MBX_TOV_SECONDS; @@ -5407,6 +5545,15 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x1107, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { + if (mcp->mb[1] != 0x7) + ha->link_data_rate = mcp->mb[1]; + + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + if (mcp->mb[4] & BIT_0) + ql_log(ql_log_info, vha, 0x11a2, + "FEC=enabled (data rate).\n"); + } + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108, "Done %s.\n", __func__); if (mcp->mb[1] != 0x7) @@ -6688,3 +6835,60 @@ int qla2xxx_read_remote_register(scsi_qla_host_t *vha, uint32_t addr, return rval; } + +int +ql26xx_led_config(scsi_qla_host_t *vha, uint16_t options, uint16_t *led) +{ + struct qla_hw_data *ha = vha->hw; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + int rval; + + if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return QLA_FUNCTION_FAILED; + + ql_dbg(ql_dbg_mbx, vha, 0x7070, "Entered %s (options=%x).\n", + __func__, options); + + mcp->mb[0] = MBC_SET_GET_FC_LED_CONFIG; + mcp->mb[1] = options; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + if (options & BIT_0) { + if (options & BIT_1) { + mcp->mb[2] = led[2]; + mcp->out_mb |= MBX_2; + } + if (options & BIT_2) { + mcp->mb[3] = led[0]; + mcp->out_mb |= MBX_3; + } + if (options & BIT_3) { + mcp->mb[4] = led[1]; + mcp->out_mb |= MBX_4; + } + } else { + mcp->in_mb |= MBX_4|MBX_3|MBX_2; + } + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + if (rval) { + ql_dbg(ql_dbg_mbx, vha, 0x7071, "Failed %s %x (mb=%x,%x)\n", + __func__, rval, mcp->mb[0], mcp->mb[1]); + return rval; + } + + if (options & BIT_0) { + ha->beacon_blink_led = 0; + ql_dbg(ql_dbg_mbx, vha, 0x7072, "Done %s\n", __func__); + } else { + led[2] = mcp->mb[2]; + led[0] = mcp->mb[3]; + led[1] = mcp->mb[4]; + ql_dbg(ql_dbg_mbx, vha, 0x7073, "Done %s (led=%x,%x,%x)\n", + __func__, led[0], led[1], led[2]); + } + + return rval; +} diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 8ae639d089d1..d82e92da529a 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -361,6 +361,13 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) } } + if (test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)) { + if (atomic_read(&vha->loop_state) == LOOP_READY) { + qla24xx_process_purex_list(&vha->purex_list); + clear_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); + } + } + if (test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) { ql_dbg(ql_dbg_dpc, vha, 0x4016, "FCPort update scheduled.\n"); @@ -509,6 +516,9 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) vha->mgmt_svr_loop_id = qla2x00_reserve_mgmt_server_loop_id(vha); vha->dpc_flags = 0L; + ha->dpc_active = 0; + set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); + set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); /* * To fix the issue of processing a parent's RSCN for the vport before @@ -886,7 +896,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, rsp->rsp_q_out); ret = qla25xx_request_irq(ha, qpair, qpair->msix, - QLA_MSIX_QPAIR_MULTIQ_RSP_Q); + ha->flags.disable_msix_handshake ? + QLA_MSIX_QPAIR_MULTIQ_RSP_Q : QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS); if (ret) goto que_failed; diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index cad1fc2a1b28..df99911b8bb9 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -53,10 +53,9 @@ qlafx00_mailbox_command(scsi_qla_host_t *vha, struct mbx_cmd_32 *mcp) struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); - if (ha->pdev->error_state > pci_channel_io_frozen) { + if (ha->pdev->error_state == pci_channel_io_perm_failure) { ql_log(ql_log_warn, vha, 0x115c, - "error_state is greater than pci_channel_io_frozen, " - "exiting.\n"); + "PCI channel failed permanently, exiting.\n"); return QLA_FUNCTION_TIMEOUT; } @@ -3136,7 +3135,7 @@ qlafx00_start_scsi(srb_t *sp) memset(&lcmd_pkt, 0, REQUEST_ENTRY_SIZE); - lcmd_pkt.handle = MAKE_HANDLE(req->id, sp->handle); + lcmd_pkt.handle = make_handle(req->id, sp->handle); lcmd_pkt.reserved_0 = 0; lcmd_pkt.port_path_ctrl = 0; lcmd_pkt.reserved_1 = 0; @@ -3206,7 +3205,7 @@ qlafx00_tm_iocb(srb_t *sp, struct tsk_mgmt_entry_fx00 *ptm_iocb) memset(&tm_iocb, 0, sizeof(struct tsk_mgmt_entry_fx00)); tm_iocb.entry_type = TSK_MGMT_IOCB_TYPE_FX00; tm_iocb.entry_count = 1; - tm_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); + tm_iocb.handle = cpu_to_le32(make_handle(req->id, sp->handle)); tm_iocb.reserved_0 = 0; tm_iocb.tgt_id = cpu_to_le16(sp->fcport->tgt_id); tm_iocb.control_flags = cpu_to_le32(fxio->u.tmf.flags); @@ -3232,9 +3231,9 @@ qlafx00_abort_iocb(srb_t *sp, struct abort_iocb_entry_fx00 *pabt_iocb) memset(&abt_iocb, 0, sizeof(struct abort_iocb_entry_fx00)); abt_iocb.entry_type = ABORT_IOCB_TYPE_FX00; abt_iocb.entry_count = 1; - abt_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); + abt_iocb.handle = cpu_to_le32(make_handle(req->id, sp->handle)); abt_iocb.abort_handle = - cpu_to_le32(MAKE_HANDLE(req->id, fxio->u.abt.cmd_hndl)); + cpu_to_le32(make_handle(req->id, fxio->u.abt.cmd_hndl)); abt_iocb.tgt_id_sts = cpu_to_le16(sp->fcport->tgt_id); abt_iocb.req_que_no = cpu_to_le16(req->id); diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index bfcd02fdf2b8..84e2a980dea0 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -413,7 +413,7 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_nvme *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ clr_ptr = (uint32_t *)cmd_pkt + 2; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7a94e1171c72..d190db5ea7d9 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -113,7 +113,8 @@ module_param(ql2xfdmienable, int, S_IRUGO|S_IWUSR); module_param_named(fdmi, ql2xfdmienable, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ql2xfdmienable, "Enables FDMI registrations. " - "0 - no FDMI. Default is 1 - perform FDMI."); + "0 - no FDMI registrations. " + "1 - provide FDMI registrations (default)."); #define MAX_Q_DEPTH 64 static int ql2xmaxqdepth = MAX_Q_DEPTH; @@ -122,11 +123,7 @@ MODULE_PARM_DESC(ql2xmaxqdepth, "Maximum queue depth to set for each LUN. " "Default is 64."); -#if (IS_ENABLED(CONFIG_NVME_FC)) -int ql2xenabledif; -#else int ql2xenabledif = 2; -#endif module_param(ql2xenabledif, int, S_IRUGO); MODULE_PARM_DESC(ql2xenabledif, " Enable T10-CRC-DIF:\n" @@ -306,6 +303,22 @@ MODULE_PARM_DESC(ql2xdifbundlinginternalbuffers, "0 (Default). Based on check.\n" "1 Force using internal buffers\n"); +int ql2xsmartsan; +module_param(ql2xsmartsan, int, 0444); +module_param_named(smartsan, ql2xsmartsan, int, 0444); +MODULE_PARM_DESC(ql2xsmartsan, + "Send SmartSAN Management Attributes for FDMI Registration." + " Default is 0 - No SmartSAN registration," + " 1 - Register SmartSAN Management Attributes."); + +int ql2xrdpenable; +module_param(ql2xrdpenable, int, 0444); +module_param_named(rdpenable, ql2xrdpenable, int, 0444); +MODULE_PARM_DESC(ql2xrdpenable, + "Enables RDP responses. " + "0 - no RDP responses (default). " + "1 - provide RDP responses."); + static void qla2x00_clear_drv_active(struct qla_hw_data *); static void qla2x00_free_device(scsi_qla_host_t *); static int qla2xxx_map_queues(struct Scsi_Host *shost); @@ -583,6 +596,9 @@ qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) case 3: speed_str = "8.0GT/s"; break; + case 4: + speed_str = "16.0GT/s"; + break; default: speed_str = "<unknown>"; break; @@ -1253,17 +1269,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return SUCCESS; spin_lock_irqsave(qpair->qp_lock_ptr, flags); - if (sp->completed) { - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - return SUCCESS; - } - - if (sp->abort || sp->aborted) { - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - return FAILED; - } - - sp->abort = 1; sp->comp = ∁ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); @@ -1688,6 +1693,10 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) return QLA_SUCCESS; } +/* + * The caller must ensure that no completion interrupts will happen + * while this function is in progress. + */ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, unsigned long *flags) __releases(qp->qp_lock_ptr) @@ -1696,10 +1705,13 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, DECLARE_COMPLETION_ONSTACK(comp); scsi_qla_host_t *vha = qp->vha; struct qla_hw_data *ha = vha->hw; + struct scsi_cmnd *cmd = GET_CMD_SP(sp); int rval; bool ret_cmd; uint32_t ratov_j; + lockdep_assert_held(qp->qp_lock_ptr); + if (qla2x00_chip_is_down(vha)) { sp->done(sp, res); return; @@ -1715,7 +1727,6 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, } sp->comp = ∁ - sp->abort = 1; spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); rval = ha->isp_ops->abort_command(sp); @@ -1739,13 +1750,17 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, } spin_lock_irqsave(qp->qp_lock_ptr, *flags); - if (ret_cmd && (!sp->completed || !sp->aborted)) + if (ret_cmd && blk_mq_request_started(cmd->request)) sp->done(sp, res); } else { sp->done(sp, res); } } +/* + * The caller must ensure that no completion interrupts will happen + * while this function is in progress. + */ static void __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) { @@ -1792,6 +1807,10 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) spin_unlock_irqrestore(qp->qp_lock_ptr, flags); } +/* + * The caller must ensure that no completion interrupts will happen + * while this function is in progress. + */ void qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) { @@ -2285,7 +2304,7 @@ static struct isp_operations qla81xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla81xx_update_fw_options, + .update_fw_options = qla24xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, @@ -2402,7 +2421,7 @@ static struct isp_operations qla83xx_isp_ops = { .config_rings = qla24xx_config_rings, .reset_adapter = qla24xx_reset_adapter, .nvram_config = qla81xx_nvram_config, - .update_fw_options = qla81xx_update_fw_options, + .update_fw_options = qla24xx_update_fw_options, .load_risc = qla81xx_load_risc, .pci_info_str = qla24xx_pci_info_str, .fw_version_str = qla24xx_fw_version_str, @@ -3439,13 +3458,6 @@ skip_dpc: if (test_bit(UNLOADING, &base_vha->dpc_flags)) return -ENODEV; - if (ha->flags.detected_lr_sfp) { - ql_log(ql_log_info, base_vha, 0xffff, - "Reset chip to pick up LR SFP setting\n"); - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); - qla2xxx_wake_dpc(base_vha); - } - return 0; probe_failed: @@ -3806,6 +3818,20 @@ qla2x00_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } +static inline void +qla24xx_free_purex_list(struct purex_list *list) +{ + struct list_head *item, *next; + ulong flags; + + spin_lock_irqsave(&list->lock, flags); + list_for_each_safe(item, next, &list->head) { + list_del(item); + kfree(list_entry(item, struct purex_item, list)); + } + spin_unlock_irqrestore(&list->lock, flags); +} + static void qla2x00_free_device(scsi_qla_host_t *vha) { @@ -3838,6 +3864,8 @@ qla2x00_free_device(scsi_qla_host_t *vha) } + qla24xx_free_purex_list(&vha->purex_list); + qla2x00_mem_free(ha); qla82xx_md_free(vha); @@ -3907,19 +3935,6 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport, set_bit(RELOGIN_NEEDED, &vha->dpc_flags); } -/* - * qla2x00_mark_all_devices_lost - * Updates fcport state when device goes offline. - * - * Input: - * ha = adapter block pointer. - * fcport = port structure pointer. - * - * Return: - * None. - * - * Context: - */ void qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha) { @@ -3931,16 +3946,6 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha) list_for_each_entry(fcport, &vha->vp_fcports, list) { fcport->scan_state = 0; qlt_schedule_sess_for_deletion(fcport); - - if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx) - continue; - - /* - * No point in marking the device as lost, if the device is - * already DEAD. - */ - if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) - continue; } } @@ -4811,6 +4816,9 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, INIT_LIST_HEAD(&vha->gpnid_list); INIT_WORK(&vha->iocb_work, qla2x00_iocb_work_fn); + INIT_LIST_HEAD(&vha->purex_list.head); + spin_lock_init(&vha->purex_list.lock); + spin_lock_init(&vha->work_lock); spin_lock_init(&vha->cmd_list_lock); init_waitqueue_head(&vha->fcport_waitQ); @@ -5168,9 +5176,8 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) fcport->n2n_flag = 1; } fcport->fw_login_state = 0; - /* - * wait link init done before sending login - */ + + schedule_delayed_work(&vha->scan.scan_work, 5); } else { qla24xx_fcport_handle_login(vha, fcport); } @@ -5731,6 +5738,583 @@ retry_lock: return; } +static bool +qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha, + struct purex_entry_24xx *purex) +{ + char fwstr[16]; + u32 sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0]; + struct port_database_24xx *pdb; + + /* Domain Controller is always logged-out. */ + /* if RDP request is not from Domain Controller: */ + if (sid != 0xfffc01) + return false; + + ql_dbg(ql_dbg_init, vha, 0x0181, "%s: s_id=%#x\n", __func__, sid); + + pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); + if (!pdb) { + ql_dbg(ql_dbg_init, vha, 0x0181, + "%s: Failed allocate pdb\n", __func__); + } else if (qla24xx_get_port_database(vha, purex->nport_handle, pdb)) { + ql_dbg(ql_dbg_init, vha, 0x0181, + "%s: Failed get pdb sid=%x\n", __func__, sid); + } else if (pdb->current_login_state != PDS_PLOGI_COMPLETE && + pdb->current_login_state != PDS_PRLI_COMPLETE) { + ql_dbg(ql_dbg_init, vha, 0x0181, + "%s: Port not logged in sid=%#x\n", __func__, sid); + } else { + /* RDP request is from logged in port */ + kfree(pdb); + return false; + } + kfree(pdb); + + vha->hw->isp_ops->fw_version_str(vha, fwstr, sizeof(fwstr)); + fwstr[strcspn(fwstr, " ")] = 0; + /* if FW version allows RDP response length upto 2048 bytes: */ + if (strcmp(fwstr, "8.09.00") > 0 || strcmp(fwstr, "8.05.65") == 0) + return false; + + ql_dbg(ql_dbg_init, vha, 0x0181, "%s: fw=%s\n", __func__, fwstr); + + /* RDP response length is to be reduced to maximum 256 bytes */ + return true; +} + +static uint +qla25xx_rdp_port_speed_capability(struct qla_hw_data *ha) +{ + if (IS_CNA_CAPABLE(ha)) + return RDP_PORT_SPEED_10GB; + + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + unsigned int speeds = 0; + + if (ha->max_supported_speed == 2) { + if (ha->min_supported_speed <= 6) + speeds |= RDP_PORT_SPEED_64GB; + } + + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1) { + if (ha->min_supported_speed <= 5) + speeds |= RDP_PORT_SPEED_32GB; + } + + if (ha->max_supported_speed == 2 || + ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 4) + speeds |= RDP_PORT_SPEED_16GB; + } + + if (ha->max_supported_speed == 1 || + ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 3) + speeds |= RDP_PORT_SPEED_8GB; + } + + if (ha->max_supported_speed == 0) { + if (ha->min_supported_speed <= 2) + speeds |= RDP_PORT_SPEED_4GB; + } + + return speeds; + } + + if (IS_QLA2031(ha)) + return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| + RDP_PORT_SPEED_4GB; + + if (IS_QLA25XX(ha)) + return RDP_PORT_SPEED_8GB|RDP_PORT_SPEED_4GB| + RDP_PORT_SPEED_2GB|RDP_PORT_SPEED_1GB; + + if (IS_QLA24XX_TYPE(ha)) + return RDP_PORT_SPEED_4GB|RDP_PORT_SPEED_2GB| + RDP_PORT_SPEED_1GB; + + if (IS_QLA23XX(ha)) + return RDP_PORT_SPEED_2GB|RDP_PORT_SPEED_1GB; + + return RDP_PORT_SPEED_1GB; +} + +static uint +qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha) +{ + switch (ha->link_data_rate) { + case PORT_SPEED_1GB: + return RDP_PORT_SPEED_1GB; + + case PORT_SPEED_2GB: + return RDP_PORT_SPEED_2GB; + + case PORT_SPEED_4GB: + return RDP_PORT_SPEED_4GB; + + case PORT_SPEED_8GB: + return RDP_PORT_SPEED_8GB; + + case PORT_SPEED_10GB: + return RDP_PORT_SPEED_10GB; + + case PORT_SPEED_16GB: + return RDP_PORT_SPEED_16GB; + + case PORT_SPEED_32GB: + return RDP_PORT_SPEED_32GB; + + case PORT_SPEED_64GB: + return RDP_PORT_SPEED_64GB; + + default: + return RDP_PORT_SPEED_UNKNOWN; + } +} + +/* + * Function Name: qla24xx_process_purex_iocb + * + * Description: + * Prepare a RDP response and send to Fabric switch + * + * PARAMETERS: + * vha: SCSI qla host + * purex: RDP request received by HBA + */ +void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) +{ + struct qla_hw_data *ha = vha->hw; + struct purex_entry_24xx *purex = pkt; + dma_addr_t rsp_els_dma; + dma_addr_t rsp_payload_dma; + dma_addr_t stat_dma; + dma_addr_t bbc_dma; + dma_addr_t sfp_dma; + struct els_entry_24xx *rsp_els = NULL; + struct rdp_rsp_payload *rsp_payload = NULL; + struct link_statistics *stat = NULL; + struct buffer_credit_24xx *bbc = NULL; + uint8_t *sfp = NULL; + uint16_t sfp_flags = 0; + uint rsp_payload_length = sizeof(*rsp_payload); + int rval; + + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, + "%s: Enter\n", __func__); + + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0181, + "-------- ELS REQ -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0182, + (void *)purex, sizeof(*purex)); + + if (qla25xx_rdp_rsp_reduce_size(vha, purex)) { + rsp_payload_length = + offsetof(typeof(*rsp_payload), optical_elmt_desc); + ql_dbg(ql_dbg_init, vha, 0x0181, + "Reducing RSP payload length to %u bytes...\n", + rsp_payload_length); + } + + rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), + &rsp_els_dma, GFP_KERNEL); + if (!rsp_els) { + ql_log(ql_log_warn, vha, 0x0183, + "Failed allocate dma buffer ELS RSP.\n"); + goto dealloc; + } + + rsp_payload = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_payload), + &rsp_payload_dma, GFP_KERNEL); + if (!rsp_payload) { + ql_log(ql_log_warn, vha, 0x0184, + "Failed allocate dma buffer ELS RSP payload.\n"); + goto dealloc; + } + + sfp = dma_alloc_coherent(&ha->pdev->dev, SFP_RTDI_LEN, + &sfp_dma, GFP_KERNEL); + + stat = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stat), + &stat_dma, GFP_KERNEL); + + bbc = dma_alloc_coherent(&ha->pdev->dev, sizeof(*bbc), + &bbc_dma, GFP_KERNEL); + + /* Prepare Response IOCB */ + rsp_els->entry_type = ELS_IOCB_TYPE; + rsp_els->entry_count = 1; + rsp_els->sys_define = 0; + rsp_els->entry_status = 0; + rsp_els->handle = 0; + rsp_els->nport_handle = purex->nport_handle; + rsp_els->tx_dsd_count = 1; + rsp_els->vp_index = purex->vp_idx; + rsp_els->sof_type = EST_SOFI3; + rsp_els->rx_xchg_address = purex->rx_xchg_addr; + rsp_els->rx_dsd_count = 0; + rsp_els->opcode = purex->els_frame_payload[0]; + + rsp_els->d_id[0] = purex->s_id[0]; + rsp_els->d_id[1] = purex->s_id[1]; + rsp_els->d_id[2] = purex->s_id[2]; + + rsp_els->control_flags = EPD_ELS_ACC; + rsp_els->rx_byte_count = 0; + rsp_els->tx_byte_count = cpu_to_le32(rsp_payload_length); + + put_unaligned_le64(rsp_payload_dma, &rsp_els->tx_address); + rsp_els->tx_len = rsp_els->tx_byte_count; + + rsp_els->rx_address = 0; + rsp_els->rx_len = 0; + + /* Prepare Response Payload */ + rsp_payload->hdr.cmd = cpu_to_be32(0x2 << 24); /* LS_ACC */ + rsp_payload->hdr.len = cpu_to_be32( + rsp_els->tx_byte_count - sizeof(rsp_payload->hdr)); + + /* Link service Request Info Descriptor */ + rsp_payload->ls_req_info_desc.desc_tag = cpu_to_be32(0x1); + rsp_payload->ls_req_info_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc)); + rsp_payload->ls_req_info_desc.req_payload_word_0 = + cpu_to_be32p((uint32_t *)purex->els_frame_payload); + + /* Link service Request Info Descriptor 2 */ + rsp_payload->ls_req_info_desc2.desc_tag = cpu_to_be32(0x1); + rsp_payload->ls_req_info_desc2.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc2)); + rsp_payload->ls_req_info_desc2.req_payload_word_0 = + cpu_to_be32p((uint32_t *)purex->els_frame_payload); + + + rsp_payload->sfp_diag_desc.desc_tag = cpu_to_be32(0x10000); + rsp_payload->sfp_diag_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); + + if (sfp) { + /* SFP Flags */ + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x7, 2, 0); + if (!rval) { + /* SFP Flags bits 3-0: Port Tx Laser Type */ + if (sfp[0] & BIT_2 || sfp[1] & (BIT_6|BIT_5)) + sfp_flags |= BIT_0; /* short wave */ + else if (sfp[0] & BIT_1) + sfp_flags |= BIT_1; /* long wave 1310nm */ + else if (sfp[1] & BIT_4) + sfp_flags |= BIT_1|BIT_0; /* long wave 1550nm */ + } + + /* SFP Type */ + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x0, 1, 0); + if (!rval) { + sfp_flags |= BIT_4; /* optical */ + if (sfp[0] == 0x3) + sfp_flags |= BIT_6; /* sfp+ */ + } + + rsp_payload->sfp_diag_desc.sfp_flags = cpu_to_be16(sfp_flags); + + /* SFP Diagnostics */ + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0x60, 10, 0); + if (!rval) { + uint16_t *trx = (void *)sfp; /* already be16 */ + rsp_payload->sfp_diag_desc.temperature = trx[0]; + rsp_payload->sfp_diag_desc.vcc = trx[1]; + rsp_payload->sfp_diag_desc.tx_bias = trx[2]; + rsp_payload->sfp_diag_desc.tx_power = trx[3]; + rsp_payload->sfp_diag_desc.rx_power = trx[4]; + } + } + + /* Port Speed Descriptor */ + rsp_payload->port_speed_desc.desc_tag = cpu_to_be32(0x10001); + rsp_payload->port_speed_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_speed_desc)); + rsp_payload->port_speed_desc.speed_capab = cpu_to_be16( + qla25xx_rdp_port_speed_capability(ha)); + rsp_payload->port_speed_desc.operating_speed = cpu_to_be16( + qla25xx_rdp_port_speed_currently(ha)); + + /* Link Error Status Descriptor */ + rsp_payload->ls_err_desc.desc_tag = cpu_to_be32(0x10002); + rsp_payload->ls_err_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); + + if (stat) { + rval = qla24xx_get_isp_stats(vha, stat, stat_dma, 0); + if (!rval) { + rsp_payload->ls_err_desc.link_fail_cnt = + cpu_to_be32(stat->link_fail_cnt); + rsp_payload->ls_err_desc.loss_sync_cnt = + cpu_to_be32(stat->loss_sync_cnt); + rsp_payload->ls_err_desc.loss_sig_cnt = + cpu_to_be32(stat->loss_sig_cnt); + rsp_payload->ls_err_desc.prim_seq_err_cnt = + cpu_to_be32(stat->prim_seq_err_cnt); + rsp_payload->ls_err_desc.inval_xmit_word_cnt = + cpu_to_be32(stat->inval_xmit_word_cnt); + rsp_payload->ls_err_desc.inval_crc_cnt = + cpu_to_be32(stat->inval_crc_cnt); + rsp_payload->ls_err_desc.pn_port_phy_type |= BIT_6; + } + } + + /* Portname Descriptor */ + rsp_payload->port_name_diag_desc.desc_tag = cpu_to_be32(0x10003); + rsp_payload->port_name_diag_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_diag_desc)); + memcpy(rsp_payload->port_name_diag_desc.WWNN, + vha->node_name, + sizeof(rsp_payload->port_name_diag_desc.WWNN)); + memcpy(rsp_payload->port_name_diag_desc.WWPN, + vha->port_name, + sizeof(rsp_payload->port_name_diag_desc.WWPN)); + + /* F-Port Portname Descriptor */ + rsp_payload->port_name_direct_desc.desc_tag = cpu_to_be32(0x10003); + rsp_payload->port_name_direct_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_direct_desc)); + memcpy(rsp_payload->port_name_direct_desc.WWNN, + vha->fabric_node_name, + sizeof(rsp_payload->port_name_direct_desc.WWNN)); + memcpy(rsp_payload->port_name_direct_desc.WWPN, + vha->fabric_port_name, + sizeof(rsp_payload->port_name_direct_desc.WWPN)); + + /* Bufer Credit Descriptor */ + rsp_payload->buffer_credit_desc.desc_tag = cpu_to_be32(0x10006); + rsp_payload->buffer_credit_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->buffer_credit_desc)); + rsp_payload->buffer_credit_desc.fcport_b2b = 0; + rsp_payload->buffer_credit_desc.attached_fcport_b2b = cpu_to_be32(0); + rsp_payload->buffer_credit_desc.fcport_rtt = cpu_to_be32(0); + + if (bbc) { + memset(bbc, 0, sizeof(*bbc)); + rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); + if (!rval) { + rsp_payload->buffer_credit_desc.fcport_b2b = + cpu_to_be32(LSW(bbc->parameter[0])); + } + } + + if (rsp_payload_length < sizeof(*rsp_payload)) + goto send; + + /* Optical Element Descriptor, Temperature */ + rsp_payload->optical_elmt_desc[0].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[0].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Voltage */ + rsp_payload->optical_elmt_desc[1].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[1].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Tx Bias Current */ + rsp_payload->optical_elmt_desc[2].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[2].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Tx Power */ + rsp_payload->optical_elmt_desc[3].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[3].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + /* Optical Element Descriptor, Rx Power */ + rsp_payload->optical_elmt_desc[4].desc_tag = cpu_to_be32(0x10007); + rsp_payload->optical_elmt_desc[4].desc_len = + cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); + + if (sfp) { + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); + if (!rval) { + uint16_t *trx = (void *)sfp; /* already be16 */ + + /* Optical Element Descriptor, Temperature */ + rsp_payload->optical_elmt_desc[0].high_alarm = trx[0]; + rsp_payload->optical_elmt_desc[0].low_alarm = trx[1]; + rsp_payload->optical_elmt_desc[0].high_warn = trx[2]; + rsp_payload->optical_elmt_desc[0].low_warn = trx[3]; + rsp_payload->optical_elmt_desc[0].element_flags = + cpu_to_be32(1 << 28); + + /* Optical Element Descriptor, Voltage */ + rsp_payload->optical_elmt_desc[1].high_alarm = trx[4]; + rsp_payload->optical_elmt_desc[1].low_alarm = trx[5]; + rsp_payload->optical_elmt_desc[1].high_warn = trx[6]; + rsp_payload->optical_elmt_desc[1].low_warn = trx[7]; + rsp_payload->optical_elmt_desc[1].element_flags = + cpu_to_be32(2 << 28); + + /* Optical Element Descriptor, Tx Bias Current */ + rsp_payload->optical_elmt_desc[2].high_alarm = trx[8]; + rsp_payload->optical_elmt_desc[2].low_alarm = trx[9]; + rsp_payload->optical_elmt_desc[2].high_warn = trx[10]; + rsp_payload->optical_elmt_desc[2].low_warn = trx[11]; + rsp_payload->optical_elmt_desc[2].element_flags = + cpu_to_be32(3 << 28); + + /* Optical Element Descriptor, Tx Power */ + rsp_payload->optical_elmt_desc[3].high_alarm = trx[12]; + rsp_payload->optical_elmt_desc[3].low_alarm = trx[13]; + rsp_payload->optical_elmt_desc[3].high_warn = trx[14]; + rsp_payload->optical_elmt_desc[3].low_warn = trx[15]; + rsp_payload->optical_elmt_desc[3].element_flags = + cpu_to_be32(4 << 28); + + /* Optical Element Descriptor, Rx Power */ + rsp_payload->optical_elmt_desc[4].high_alarm = trx[16]; + rsp_payload->optical_elmt_desc[4].low_alarm = trx[17]; + rsp_payload->optical_elmt_desc[4].high_warn = trx[18]; + rsp_payload->optical_elmt_desc[4].low_warn = trx[19]; + rsp_payload->optical_elmt_desc[4].element_flags = + cpu_to_be32(5 << 28); + } + + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 112, 64, 0); + if (!rval) { + /* Temperature high/low alarm/warning */ + rsp_payload->optical_elmt_desc[0].element_flags |= + cpu_to_be32( + (sfp[0] >> 7 & 1) << 3 | + (sfp[0] >> 6 & 1) << 2 | + (sfp[4] >> 7 & 1) << 1 | + (sfp[4] >> 6 & 1) << 0); + + /* Voltage high/low alarm/warning */ + rsp_payload->optical_elmt_desc[1].element_flags |= + cpu_to_be32( + (sfp[0] >> 5 & 1) << 3 | + (sfp[0] >> 4 & 1) << 2 | + (sfp[4] >> 5 & 1) << 1 | + (sfp[4] >> 4 & 1) << 0); + + /* Tx Bias Current high/low alarm/warning */ + rsp_payload->optical_elmt_desc[2].element_flags |= + cpu_to_be32( + (sfp[0] >> 3 & 1) << 3 | + (sfp[0] >> 2 & 1) << 2 | + (sfp[4] >> 3 & 1) << 1 | + (sfp[4] >> 2 & 1) << 0); + + /* Tx Power high/low alarm/warning */ + rsp_payload->optical_elmt_desc[3].element_flags |= + cpu_to_be32( + (sfp[0] >> 1 & 1) << 3 | + (sfp[0] >> 0 & 1) << 2 | + (sfp[4] >> 1 & 1) << 1 | + (sfp[4] >> 0 & 1) << 0); + + /* Rx Power high/low alarm/warning */ + rsp_payload->optical_elmt_desc[4].element_flags |= + cpu_to_be32( + (sfp[1] >> 7 & 1) << 3 | + (sfp[1] >> 6 & 1) << 2 | + (sfp[5] >> 7 & 1) << 1 | + (sfp[5] >> 6 & 1) << 0); + } + } + + /* Optical Product Data Descriptor */ + rsp_payload->optical_prod_desc.desc_tag = cpu_to_be32(0x10008); + rsp_payload->optical_prod_desc.desc_len = + cpu_to_be32(RDP_DESC_LEN(rsp_payload->optical_prod_desc)); + + if (sfp) { + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 20, 64, 0); + if (!rval) { + memcpy(rsp_payload->optical_prod_desc.vendor_name, + sfp + 0, + sizeof(rsp_payload->optical_prod_desc.vendor_name)); + memcpy(rsp_payload->optical_prod_desc.part_number, + sfp + 20, + sizeof(rsp_payload->optical_prod_desc.part_number)); + memcpy(rsp_payload->optical_prod_desc.revision, + sfp + 36, + sizeof(rsp_payload->optical_prod_desc.revision)); + memcpy(rsp_payload->optical_prod_desc.serial_number, + sfp + 48, + sizeof(rsp_payload->optical_prod_desc.serial_number)); + } + + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 84, 8, 0); + if (!rval) { + memcpy(rsp_payload->optical_prod_desc.date, + sfp + 0, + sizeof(rsp_payload->optical_prod_desc.date)); + } + } + +send: + ql_dbg(ql_dbg_init, vha, 0x0183, + "Sending ELS Response to RDP Request...\n"); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0184, + "-------- ELS RSP -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0185, + (void *)rsp_els, sizeof(*rsp_els)); + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0186, + "-------- ELS RSP PAYLOAD -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0187, + (void *)rsp_payload, rsp_payload_length); + + rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); + + if (rval) { + ql_log(ql_log_warn, vha, 0x0188, + "%s: iocb failed to execute -> %x\n", __func__, rval); + } else if (rsp_els->comp_status) { + ql_log(ql_log_warn, vha, 0x0189, + "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", + __func__, rsp_els->comp_status, + rsp_els->error_subcode_1, rsp_els->error_subcode_2); + } else { + ql_dbg(ql_dbg_init, vha, 0x018a, "%s: done.\n", __func__); + } + +dealloc: + if (bbc) + dma_free_coherent(&ha->pdev->dev, sizeof(*bbc), + bbc, bbc_dma); + if (stat) + dma_free_coherent(&ha->pdev->dev, sizeof(*stat), + stat, stat_dma); + if (sfp) + dma_free_coherent(&ha->pdev->dev, SFP_RTDI_LEN, + sfp, sfp_dma); + if (rsp_payload) + dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_payload), + rsp_payload, rsp_payload_dma); + if (rsp_els) + dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), + rsp_els, rsp_els_dma); +} + +void qla24xx_process_purex_list(struct purex_list *list) +{ + struct list_head head = LIST_HEAD_INIT(head); + struct purex_item *item, *next; + ulong flags; + + spin_lock_irqsave(&list->lock, flags); + list_splice_init(&list->head, &head); + spin_unlock_irqrestore(&list->lock, flags); + + list_for_each_entry_safe(item, next, &head, list) { + list_del(&item->list); + item->process_item(item->vha, &item->iocb); + kfree(item); + } +} + void qla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id) { @@ -6254,13 +6838,14 @@ qla2x00_do_dpc(void *data) } if (test_and_clear_bit(DETECT_SFP_CHANGE, - &base_vha->dpc_flags) && - !test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) { - qla24xx_detect_sfp(base_vha); - - if (ha->flags.detected_lr_sfp != - ha->flags.using_lr_setting) - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); + &base_vha->dpc_flags)) { + /* Semantic: + * - NO-OP -- await next ISP-ABORT. Preferred method + * to minimize disruptions that will occur + * when a forced chip-reset occurs. + * - Force -- ISP-ABORT scheduled. + */ + /* set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); */ } if (test_and_clear_bit @@ -6301,6 +6886,15 @@ qla2x00_do_dpc(void *data) } } + if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags)) { + if (atomic_read(&base_vha->loop_state) == LOOP_READY) { + qla24xx_process_purex_list + (&base_vha->purex_list); + clear_bit(PROCESS_PUREX_IOCB, + &base_vha->dpc_flags); + } + } + if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) { qla2x00_update_fcports(base_vha); @@ -6692,7 +7286,8 @@ qla2x00_timer(struct timer_list *t) test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) || test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) || test_bit(VP_DPC_NEEDED, &vha->dpc_flags) || - test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) { + test_bit(RELOGIN_NEEDED, &vha->dpc_flags) || + test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags))) { ql_dbg(ql_dbg_timer, vha, 0x600b, "isp_abort_needed=%d loop_resync_needed=%d " "fcport_update_needed=%d start_dpc=%d " @@ -6705,12 +7300,13 @@ qla2x00_timer(struct timer_list *t) ql_dbg(ql_dbg_timer, vha, 0x600c, "beacon_blink_needed=%d isp_unrecoverable=%d " "fcoe_ctx_reset_needed=%d vp_dpc_needed=%d " - "relogin_needed=%d.\n", + "relogin_needed=%d, Process_purex_iocb=%d.\n", test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags), test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags), test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags), test_bit(VP_DPC_NEEDED, &vha->dpc_flags), - test_bit(RELOGIN_NEEDED, &vha->dpc_flags)); + test_bit(RELOGIN_NEEDED, &vha->dpc_flags), + test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)); qla2xxx_wake_dpc(vha); } diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 76a38bf86cbc..3da79ee1d88e 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -2683,7 +2683,7 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, uint32_t sec_mask, rest_addr, fdata; void *optrom = NULL; dma_addr_t optrom_dma; - int rval; + int rval, ret; struct secure_flash_update_block *sfub; dma_addr_t sfub_dma; uint32_t offset = faddr << 2; @@ -2939,11 +2939,12 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, write_protect: ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, "Protect flash...\n"); - rval = qla24xx_protect_flash(vha); - if (rval) { + ret = qla24xx_protect_flash(vha); + if (ret) { qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK); ql_log(ql_log_warn, vha, 0x7099, "Failed protect flash\n"); + rval = QLA_COMMAND_ERROR; } if (reset_to_rom == true) { @@ -2951,10 +2952,12 @@ write_protect: set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); - rval = qla2x00_wait_for_hba_online(vha); - if (rval != QLA_SUCCESS) + ret = qla2x00_wait_for_hba_online(vha); + if (ret != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0xffff, "Adapter did not come out of reset\n"); + rval = QLA_COMMAND_ERROR; + } } done: diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 70081b395fb2..622e7337affc 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -27,8 +27,6 @@ #include <scsi/scsi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> -#include <target/target_core_base.h> -#include <target/target_core_fabric.h> #include "qla_def.h" #include "qla_target.h" @@ -1760,7 +1758,7 @@ static int qlt_build_abts_resp_iocb(struct qla_tgt_mgmt_cmd *mcmd) qpair->req->outstanding_cmds[h] = (srb_t *)mcmd; } - resp->handle = MAKE_HANDLE(qpair->req->id, h); + resp->handle = make_handle(qpair->req->id, h); resp->entry_type = ABTS_RESP_24XX; resp->entry_count = 1; resp->nport_handle = abts->nport_handle; @@ -2582,7 +2580,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair, } else qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd; - pkt->handle = MAKE_HANDLE(qpair->req->id, h); + pkt->handle = make_handle(qpair->req->id, h); pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); @@ -3095,7 +3093,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm) } else qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd; - pkt->handle = MAKE_HANDLE(qpair->req->id, h); + pkt->handle = make_handle(qpair->req->id, h); pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); @@ -3816,7 +3814,7 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd) return; } cmd->jiffies_at_free = get_jiffies_64(); - target_free_tag(sess->se_sess, &cmd->se_cmd); + cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd); } EXPORT_SYMBOL(qlt_free_cmd); @@ -4150,7 +4148,7 @@ out_term: qlt_send_term_exchange(qpair, NULL, &cmd->atio, 1, 0); qlt_decr_num_pend_cmds(vha); - target_free_tag(sess->se_sess, &cmd->se_cmd); + cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); ha->tgt.tgt_ops->put_sess(sess); @@ -4277,24 +4275,18 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, struct fc_port *sess, struct atio_from_isp *atio) { - struct se_session *se_sess = sess->se_sess; struct qla_tgt_cmd *cmd; - int tag, cpu; - tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); - if (tag < 0) + cmd = vha->hw->tgt.tgt_ops->get_cmd(sess); + if (!cmd) return NULL; - cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; - memset(cmd, 0, sizeof(struct qla_tgt_cmd)); cmd->cmd_type = TYPE_TGT_CMD; memcpy(&cmd->atio, atio, sizeof(*atio)); cmd->state = QLA_TGT_STATE_NEW; cmd->tgt = vha->vha_tgt.qla_tgt; qlt_incr_num_pend_cmds(vha); cmd->vha = vha; - cmd->se_cmd.map_tag = tag; - cmd->se_cmd.map_cpu = cpu; cmd->sess = sess; cmd->loop_id = sess->loop_id; cmd->conf_compl_supported = sess->conf_compl_supported; @@ -4747,11 +4739,11 @@ static int qlt_handle_login(struct scsi_qla_host *vha, qla24xx_post_newsess_work(vha, &port_id, iocb->u.isp24.port_name, iocb->u.isp24.u.plogi.node_name, - pla, FC4_TYPE_UNKNOWN); + pla, 0); else qla24xx_post_newsess_work(vha, &port_id, iocb->u.isp24.port_name, NULL, - pla, FC4_TYPE_UNKNOWN); + pla, 0); goto out; } @@ -5352,9 +5344,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; struct qla_hw_data *ha = vha->hw; struct fc_port *sess; - struct se_session *se_sess; struct qla_tgt_cmd *cmd; - int tag, cpu; unsigned long flags; if (unlikely(tgt->tgt_stop)) { @@ -5384,10 +5374,8 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, if (!sess) return; - se_sess = sess->se_sess; - - tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); - if (tag < 0) { + cmd = ha->tgt.tgt_ops->get_cmd(sess); + if (!cmd) { ql_dbg(ql_dbg_io, vha, 0x3009, "qla_target(%d): %s: Allocation of cmd failed\n", vha->vp_idx, __func__); @@ -5402,9 +5390,6 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, return; } - cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; - memset(cmd, 0, sizeof(struct qla_tgt_cmd)); - qlt_incr_num_pend_cmds(vha); INIT_LIST_HEAD(&cmd->cmd_list); memcpy(&cmd->atio, atio, sizeof(*atio)); @@ -5414,7 +5399,6 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, cmd->reset_count = ha->base_qpair->chip_reset; cmd->q_full = 1; cmd->qpair = ha->base_qpair; - cmd->se_cmd.map_cpu = cpu; if (qfull) { cmd->q_full = 1; diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 6539499e9e95..3cf8590feeac 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -671,6 +671,8 @@ struct qla_tgt_func_tmpl { void (*handle_data)(struct qla_tgt_cmd *); int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, u64, uint16_t, uint32_t); + struct qla_tgt_cmd *(*get_cmd)(struct fc_port *); + void (*rel_cmd)(struct qla_tgt_cmd *); void (*free_cmd)(struct qla_tgt_cmd *); void (*free_mcmd)(struct qla_tgt_mgmt_cmd *); void (*free_session)(struct fc_port *); diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index 5b0c057def2b..6aeb1c3fb7a8 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -870,7 +870,7 @@ bailout: static void qla27xx_time_stamp(struct qla27xx_fwdt_template *tmp) { - tmp->capture_timestamp = jiffies; + tmp->capture_timestamp = cpu_to_le32(jiffies); } static void @@ -882,9 +882,10 @@ qla27xx_driver_info(struct qla27xx_fwdt_template *tmp) "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", v+0, v+1, v+2, v+3, v+4, v+5) != 6); - tmp->driver_info[0] = v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]; - tmp->driver_info[1] = v[5] << 8 | v[4]; - tmp->driver_info[2] = 0x12345678; + tmp->driver_info[0] = cpu_to_le32( + v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]); + tmp->driver_info[1] = cpu_to_le32(v[5] << 8 | v[4]); + tmp->driver_info[2] = __constant_cpu_to_le32(0x12345678); } static void @@ -894,10 +895,10 @@ qla27xx_firmware_info(struct scsi_qla_host *vha, tmp->firmware_version[0] = vha->hw->fw_major_version; tmp->firmware_version[1] = vha->hw->fw_minor_version; tmp->firmware_version[2] = vha->hw->fw_subminor_version; - tmp->firmware_version[3] = - vha->hw->fw_attributes_h << 16 | vha->hw->fw_attributes; - tmp->firmware_version[4] = - vha->hw->fw_attributes_ext[1] << 16 | vha->hw->fw_attributes_ext[0]; + tmp->firmware_version[3] = cpu_to_le32( + vha->hw->fw_attributes_h << 16 | vha->hw->fw_attributes); + tmp->firmware_version[4] = cpu_to_le32( + vha->hw->fw_attributes_ext[1] << 16 | vha->hw->fw_attributes_ext[0]); } static void diff --git a/drivers/scsi/qla2xxx/qla_tmpl.h b/drivers/scsi/qla2xxx/qla_tmpl.h index d2a0014e8b21..bba8dc90acfb 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.h +++ b/drivers/scsi/qla2xxx/qla_tmpl.h @@ -18,11 +18,11 @@ struct __packed qla27xx_fwdt_template { __le32 entry_count; uint32_t template_version; - uint32_t capture_timestamp; + __le32 capture_timestamp; uint32_t template_checksum; uint32_t reserved_2; - uint32_t driver_info[3]; + __le32 driver_info[3]; uint32_t saved_state[16]; diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index bb03c022e023..8ccd9ba1ddef 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.01.00.22-k" +#define QLA2XXX_VERSION "10.01.00.25-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 1 diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index abe7f79bb789..1f0a185b2a95 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -268,6 +268,29 @@ static void tcm_qla2xxx_complete_free(struct work_struct *work) transport_generic_free_cmd(&cmd->se_cmd, 0); } +static struct qla_tgt_cmd *tcm_qla2xxx_get_cmd(struct fc_port *sess) +{ + struct se_session *se_sess = sess->se_sess; + struct qla_tgt_cmd *cmd; + int tag, cpu; + + tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); + if (tag < 0) + return NULL; + + cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; + memset(cmd, 0, sizeof(struct qla_tgt_cmd)); + cmd->se_cmd.map_tag = tag; + cmd->se_cmd.map_cpu = cpu; + + return cmd; +} + +static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd) +{ + target_free_tag(cmd->sess->se_sess, &cmd->se_cmd); +} + /* * Called from qla_target_template->free_cmd(), and will call * tcm_qla2xxx_release_cmd via normal struct target_core_fabric_ops @@ -1549,6 +1572,8 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { .handle_cmd = tcm_qla2xxx_handle_cmd, .handle_data = tcm_qla2xxx_handle_data, .handle_tmr = tcm_qla2xxx_handle_tmr, + .get_cmd = tcm_qla2xxx_get_cmd, + .rel_cmd = tcm_qla2xxx_rel_cmd, .free_cmd = tcm_qla2xxx_free_cmd, .free_mcmd = tcm_qla2xxx_free_mcmd, .free_session = tcm_qla2xxx_free_session, diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 930e4803d888..56c24a73e0c7 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -94,20 +94,6 @@ EXPORT_SYMBOL(scsi_logging_level); ASYNC_DOMAIN_EXCLUSIVE(scsi_sd_pm_domain); EXPORT_SYMBOL(scsi_sd_pm_domain); -/** - * scsi_put_command - Free a scsi command block - * @cmd: command block to free - * - * Returns: Nothing. - * - * Notes: The command must not belong to any lists. - */ -void scsi_put_command(struct scsi_cmnd *cmd) -{ - scsi_del_cmd_from_list(cmd); - BUG_ON(delayed_work_pending(&cmd->abort_work)); -} - #ifdef CONFIG_SCSI_LOGGING void scsi_log_send(struct scsi_cmnd *cmd) { @@ -764,10 +750,6 @@ MODULE_LICENSE("GPL"); module_param(scsi_logging_level, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels"); -/* This should go away in the future, it doesn't do anything anymore */ -bool scsi_use_blk_mq = true; -module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO); - static int __init init_scsi(void) { int error; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index ae2fa170f6ad..978be1602f71 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -2412,7 +2412,6 @@ scsi_ioctl_reset(struct scsi_device *dev, int __user *arg) wake_up(&shost->host_wait); scsi_run_host_queues(shost); - scsi_put_command(scmd); kfree(rq); out_put_autopm_host: diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 610ee41fa54c..47835c4b4ee0 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -562,7 +562,6 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) { scsi_mq_free_sgtables(cmd); scsi_uninit_cmd(cmd); - scsi_del_cmd_from_list(cmd); } /* Returns false when no more bytes to process, true if there are more */ @@ -1098,36 +1097,7 @@ static void scsi_cleanup_rq(struct request *rq) } } -/* Add a command to the list used by the aacraid and dpt_i2o drivers */ -void scsi_add_cmd_to_list(struct scsi_cmnd *cmd) -{ - struct scsi_device *sdev = cmd->device; - struct Scsi_Host *shost = sdev->host; - unsigned long flags; - - if (shost->use_cmd_list) { - spin_lock_irqsave(&sdev->list_lock, flags); - list_add_tail(&cmd->list, &sdev->cmd_list); - spin_unlock_irqrestore(&sdev->list_lock, flags); - } -} - -/* Remove a command from the list used by the aacraid and dpt_i2o drivers */ -void scsi_del_cmd_from_list(struct scsi_cmnd *cmd) -{ - struct scsi_device *sdev = cmd->device; - struct Scsi_Host *shost = sdev->host; - unsigned long flags; - - if (shost->use_cmd_list) { - spin_lock_irqsave(&sdev->list_lock, flags); - BUG_ON(list_empty(&cmd->list)); - list_del_init(&cmd->list); - spin_unlock_irqrestore(&sdev->list_lock, flags); - } -} - -/* Called after a request has been started. */ +/* Called before a request is prepared. See also scsi_mq_prep_fn(). */ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) { void *buf = cmd->sense_buffer; @@ -1135,7 +1105,7 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) struct request *rq = blk_mq_rq_from_pdu(cmd); unsigned int flags = cmd->flags & SCMD_PRESERVED_FLAGS; unsigned long jiffies_at_alloc; - int retries; + int retries, to_clear; bool in_flight; if (!blk_rq_is_scsi(rq) && !(flags & SCMD_INITIALIZED)) { @@ -1146,9 +1116,15 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) jiffies_at_alloc = cmd->jiffies_at_alloc; retries = cmd->retries; in_flight = test_bit(SCMD_STATE_INFLIGHT, &cmd->state); - /* zero out the cmd, except for the embedded scsi_request */ - memset((char *)cmd + sizeof(cmd->req), 0, - sizeof(*cmd) - sizeof(cmd->req) + dev->host->hostt->cmd_size); + /* + * Zero out the cmd, except for the embedded scsi_request. Only clear + * the driver-private command data if the LLD does not supply a + * function to initialize that data. + */ + to_clear = sizeof(*cmd) - sizeof(cmd->req); + if (!dev->host->hostt->init_cmd_priv) + to_clear += dev->host->hostt->cmd_size; + memset((char *)cmd + sizeof(cmd->req), 0, to_clear); cmd->device = dev; cmd->sense_buffer = buf; @@ -1160,7 +1136,6 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) if (in_flight) __set_bit(SCMD_STATE_INFLIGHT, &cmd->state); - scsi_add_cmd_to_list(cmd); } static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev, @@ -1240,8 +1215,11 @@ scsi_prep_state_check(struct scsi_device *sdev, struct request *req) * commands. The device must be brought online * before trying any recovery commands. */ - sdev_printk(KERN_ERR, sdev, - "rejecting I/O to offline device\n"); + if (!sdev->offline_already) { + sdev->offline_already = true; + sdev_printk(KERN_ERR, sdev, + "rejecting I/O to offline device\n"); + } return BLK_STS_IOERR; case SDEV_DEL: /* @@ -1742,6 +1720,7 @@ static int scsi_mq_init_request(struct blk_mq_tag_set *set, struct request *rq, const bool unchecked_isa_dma = shost->unchecked_isa_dma; struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); struct scatterlist *sg; + int ret = 0; if (unchecked_isa_dma) cmd->flags |= SCMD_UNCHECKED_ISA_DMA; @@ -1757,14 +1736,24 @@ static int scsi_mq_init_request(struct blk_mq_tag_set *set, struct request *rq, cmd->prot_sdb = (void *)sg + scsi_mq_inline_sgl_size(shost); } - return 0; + if (shost->hostt->init_cmd_priv) { + ret = shost->hostt->init_cmd_priv(shost, cmd); + if (ret < 0) + scsi_free_sense_buffer(unchecked_isa_dma, + cmd->sense_buffer); + } + + return ret; } static void scsi_mq_exit_request(struct blk_mq_tag_set *set, struct request *rq, unsigned int hctx_idx) { + struct Scsi_Host *shost = set->driver_data; struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); + if (shost->hostt->exit_cmd_priv) + shost->hostt->exit_cmd_priv(shost, cmd); scsi_free_sense_buffer(cmd->flags & SCMD_UNCHECKED_ISA_DMA, cmd->sense_buffer); } @@ -2340,6 +2329,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) break; } + sdev->offline_already = false; sdev->sdev_state = state; return 0; @@ -2845,6 +2835,36 @@ scsi_target_unblock(struct device *dev, enum scsi_device_state new_state) } EXPORT_SYMBOL_GPL(scsi_target_unblock); +int +scsi_host_block(struct Scsi_Host *shost) +{ + struct scsi_device *sdev; + int ret = 0; + + shost_for_each_device(sdev, shost) { + ret = scsi_internal_device_block(sdev); + if (ret) + break; + } + return ret; +} +EXPORT_SYMBOL_GPL(scsi_host_block); + +int +scsi_host_unblock(struct Scsi_Host *shost, int new_state) +{ + struct scsi_device *sdev; + int ret = 0; + + shost_for_each_device(sdev, shost) { + ret = scsi_internal_device_unblock(sdev, new_state); + if (ret) + break; + } + return ret; +} +EXPORT_SYMBOL_GPL(scsi_host_unblock); + /** * scsi_kmap_atomic_sg - find and atomically map an sg-elemnt * @sgl: scatter-gather list diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 3bff9f7aa684..22b6585e28b4 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -29,7 +29,6 @@ extern int scsi_init_hosts(void); extern void scsi_exit_hosts(void); /* scsi.c */ -extern bool scsi_use_blk_mq; int scsi_init_sense_cache(struct Scsi_Host *shost); void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd); #ifdef CONFIG_SCSI_LOGGING @@ -84,8 +83,6 @@ int scsi_eh_get_sense(struct list_head *work_q, int scsi_noretry_cmd(struct scsi_cmnd *scmd); /* scsi_lib.c */ -extern void scsi_add_cmd_to_list(struct scsi_cmnd *cmd); -extern void scsi_del_cmd_from_list(struct scsi_cmnd *cmd); extern int scsi_maybe_unblock_host(struct scsi_device *sdev); extern void scsi_device_unbusy(struct scsi_device *sdev, struct scsi_cmnd *cmd); extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 058079f915f1..f2437a7570ce 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -236,7 +236,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, sdev->sdev_state = SDEV_CREATED; INIT_LIST_HEAD(&sdev->siblings); INIT_LIST_HEAD(&sdev->same_target_siblings); - INIT_LIST_HEAD(&sdev->cmd_list); INIT_LIST_HEAD(&sdev->starved_entry); INIT_LIST_HEAD(&sdev->event_list); spin_lock_init(&sdev->list_lock); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 677b5c5403d2..163dbcb741c1 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -856,7 +856,7 @@ show_vpd_##_page(struct file *filp, struct kobject *kobj, \ struct bin_attribute *bin_attr, \ char *buf, loff_t off, size_t count) \ { \ - struct device *dev = container_of(kobj, struct device, kobj); \ + struct device *dev = kobj_to_dev(kobj); \ struct scsi_device *sdev = to_scsi_device(dev); \ struct scsi_vpd *vpd_page; \ int ret = -EINVAL; \ @@ -884,7 +884,7 @@ static ssize_t show_inquiry(struct file *filep, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct scsi_device *sdev = to_scsi_device(dev); if (!sdev->inquiry) @@ -1045,14 +1045,14 @@ sdev_show_blacklist(struct device *dev, struct device_attribute *attr, name = sdev_bflags_name[i]; if (name) - len += snprintf(buf + len, PAGE_SIZE - len, - "%s%s", len ? " " : "", name); + len += scnprintf(buf + len, PAGE_SIZE - len, + "%s%s", len ? " " : "", name); else - len += snprintf(buf + len, PAGE_SIZE - len, - "%sINVALID_BIT(%d)", len ? " " : "", i); + len += scnprintf(buf + len, PAGE_SIZE - len, + "%sINVALID_BIT(%d)", len ? " " : "", i); } if (len) - len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); return len; } static DEVICE_ATTR(blacklist, S_IRUGO, sdev_show_blacklist, NULL); @@ -1181,7 +1181,7 @@ static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR, static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj, struct attribute *attr, int i) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct scsi_device *sdev = to_scsi_device(dev); @@ -1207,7 +1207,7 @@ static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj, static umode_t scsi_sdev_bin_attr_is_visible(struct kobject *kobj, struct bin_attribute *attr, int i) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct scsi_device *sdev = to_scsi_device(dev); diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c index ac35c301c792..41a950075913 100644 --- a/drivers/scsi/scsi_trace.c +++ b/drivers/scsi/scsi_trace.c @@ -18,11 +18,9 @@ static const char * scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len) { const char *ret = trace_seq_buffer_ptr(p); - u32 lba = 0, txlen; + u32 lba, txlen; - lba |= ((cdb[1] & 0x1F) << 16); - lba |= (cdb[2] << 8); - lba |= cdb[3]; + lba = get_unaligned_be24(&cdb[1]) & 0x1fffff; /* * From SBC-2: a TRANSFER LENGTH field set to zero specifies that 256 * logical blocks shall be read (READ(6)) or written (WRITE(6)). diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index dfc726fa34e3..0ec1b31c75a9 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -86,9 +86,17 @@ struct iscsi_internal { struct transport_container session_cont; }; +/* Worker to perform connection failure on unresponsive connections + * completely in kernel space. + */ +static void stop_conn_work_fn(struct work_struct *work); +static DECLARE_WORK(stop_conn_work, stop_conn_work_fn); + static atomic_t iscsi_session_nr; /* sysfs session id for next new session */ static struct workqueue_struct *iscsi_eh_timer_workq; +static struct workqueue_struct *iscsi_destroy_workq; + static DEFINE_IDA(iscsi_sess_ida); /* * list of registered transports and lock that must @@ -1609,8 +1617,10 @@ static struct sock *nls; static DEFINE_MUTEX(rx_queue_mutex); static LIST_HEAD(sesslist); +static LIST_HEAD(sessdestroylist); static DEFINE_SPINLOCK(sesslock); static LIST_HEAD(connlist); +static LIST_HEAD(connlist_err); static DEFINE_SPINLOCK(connlock); static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn) @@ -2028,6 +2038,14 @@ static void __iscsi_unbind_session(struct work_struct *work) ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n"); } +static void __iscsi_destroy_session(struct work_struct *work) +{ + struct iscsi_cls_session *session = + container_of(work, struct iscsi_cls_session, destroy_work); + + session->transport->destroy_session(session); +} + struct iscsi_cls_session * iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, int dd_size) @@ -2050,6 +2068,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, INIT_WORK(&session->block_work, __iscsi_block_session); INIT_WORK(&session->unbind_work, __iscsi_unbind_session); INIT_WORK(&session->scan_work, iscsi_scan_session); + INIT_WORK(&session->destroy_work, __iscsi_destroy_session); spin_lock_init(&session->lock); /* this is released in the dev's release function */ @@ -2254,8 +2273,10 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid) mutex_init(&conn->ep_mutex); INIT_LIST_HEAD(&conn->conn_list); + INIT_LIST_HEAD(&conn->conn_list_err); conn->transport = transport; conn->cid = cid; + conn->state = ISCSI_CONN_DOWN; /* this is released in the dev's release function */ if (!get_device(&session->dev)) @@ -2307,6 +2328,7 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn) spin_lock_irqsave(&connlock, flags); list_del(&conn->conn_list); + list_del(&conn->conn_list_err); spin_unlock_irqrestore(&connlock, flags); transport_unregister_device(&conn->dev); @@ -2421,6 +2443,51 @@ int iscsi_offload_mesg(struct Scsi_Host *shost, } EXPORT_SYMBOL_GPL(iscsi_offload_mesg); +static void stop_conn_work_fn(struct work_struct *work) +{ + struct iscsi_cls_conn *conn, *tmp; + unsigned long flags; + LIST_HEAD(recovery_list); + + spin_lock_irqsave(&connlock, flags); + if (list_empty(&connlist_err)) { + spin_unlock_irqrestore(&connlock, flags); + return; + } + list_splice_init(&connlist_err, &recovery_list); + spin_unlock_irqrestore(&connlock, flags); + + list_for_each_entry_safe(conn, tmp, &recovery_list, conn_list_err) { + uint32_t sid = iscsi_conn_get_sid(conn); + struct iscsi_cls_session *session; + + mutex_lock(&rx_queue_mutex); + + session = iscsi_session_lookup(sid); + if (session) { + if (system_state != SYSTEM_RUNNING) { + session->recovery_tmo = 0; + conn->transport->stop_conn(conn, + STOP_CONN_TERM); + } else { + conn->transport->stop_conn(conn, + STOP_CONN_RECOVER); + } + } + + list_del_init(&conn->conn_list_err); + + mutex_unlock(&rx_queue_mutex); + + /* we don't want to hold rx_queue_mutex for too long, + * for instance if many conns failed at the same time, + * since this stall other iscsi maintenance operations. + * Give other users a chance to proceed. + */ + cond_resched(); + } +} + void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error) { struct nlmsghdr *nlh; @@ -2428,6 +2495,12 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error) struct iscsi_uevent *ev; struct iscsi_internal *priv; int len = nlmsg_total_size(sizeof(*ev)); + unsigned long flags; + + spin_lock_irqsave(&connlock, flags); + list_add(&conn->conn_list_err, &connlist_err); + spin_unlock_irqrestore(&connlock, flags); + queue_work(system_unbound_wq, &stop_conn_work); priv = iscsi_if_transport_lookup(conn->transport); if (!priv) @@ -2757,11 +2830,19 @@ static int iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) { struct iscsi_cls_conn *conn; + unsigned long flags; conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid); if (!conn) return -EINVAL; + spin_lock_irqsave(&connlock, flags); + if (!list_empty(&conn->conn_list_err)) { + spin_unlock_irqrestore(&connlock, flags); + return -EAGAIN; + } + spin_unlock_irqrestore(&connlock, flags); + ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n"); if (transport->destroy_conn) transport->destroy_conn(conn); @@ -3563,6 +3644,23 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) else transport->destroy_session(session); break; + case ISCSI_UEVENT_DESTROY_SESSION_ASYNC: + session = iscsi_session_lookup(ev->u.d_session.sid); + if (!session) + err = -EINVAL; + else if (iscsi_session_has_conns(ev->u.d_session.sid)) + err = -EBUSY; + else { + unsigned long flags; + + /* Prevent this session from being found again */ + spin_lock_irqsave(&sesslock, flags); + list_move(&session->sess_list, &sessdestroylist); + spin_unlock_irqrestore(&sesslock, flags); + + queue_work(iscsi_destroy_workq, &session->destroy_work); + } + break; case ISCSI_UEVENT_UNBIND_SESSION: session = iscsi_session_lookup(ev->u.d_session.sid); if (session) @@ -3612,8 +3710,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) break; case ISCSI_UEVENT_START_CONN: conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid); - if (conn) + if (conn) { ev->r.retcode = transport->start_conn(conn); + if (!ev->r.retcode) + conn->state = ISCSI_CONN_UP; + } else err = -EINVAL; break; @@ -3810,6 +3911,26 @@ iscsi_conn_attr(tcp_xmit_wsf, ISCSI_PARAM_TCP_XMIT_WSF); iscsi_conn_attr(tcp_recv_wsf, ISCSI_PARAM_TCP_RECV_WSF); iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR); +static const char *const connection_state_names[] = { + [ISCSI_CONN_UP] = "up", + [ISCSI_CONN_DOWN] = "down", + [ISCSI_CONN_FAILED] = "failed" +}; + +static ssize_t show_conn_state(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); + const char *state = "unknown"; + + if (conn->state >= 0 && + conn->state < ARRAY_SIZE(connection_state_names)) + state = connection_state_names[conn->state]; + + return sprintf(buf, "%s\n", state); +} +static ISCSI_CLASS_ATTR(conn, state, S_IRUGO, show_conn_state, + NULL); #define iscsi_conn_ep_attr_show(param) \ static ssize_t show_conn_ep_param_##param(struct device *dev, \ @@ -3879,6 +4000,7 @@ static struct attribute *iscsi_conn_attrs[] = { &dev_attr_conn_tcp_xmit_wsf.attr, &dev_attr_conn_tcp_recv_wsf.attr, &dev_attr_conn_local_ipaddr.attr, + &dev_attr_conn_state.attr, NULL, }; @@ -3950,6 +4072,8 @@ static umode_t iscsi_conn_attr_is_visible(struct kobject *kobj, param = ISCSI_PARAM_TCP_RECV_WSF; else if (attr == &dev_attr_conn_local_ipaddr.attr) param = ISCSI_PARAM_LOCAL_IPADDR; + else if (attr == &dev_attr_conn_state.attr) + return S_IRUGO; else { WARN_ONCE(1, "Invalid conn attr"); return 0; @@ -4608,8 +4732,16 @@ static __init int iscsi_transport_init(void) goto release_nls; } + iscsi_destroy_workq = create_singlethread_workqueue("iscsi_destroy"); + if (!iscsi_destroy_workq) { + err = -ENOMEM; + goto destroy_wq; + } + return 0; +destroy_wq: + destroy_workqueue(iscsi_eh_timer_workq); release_nls: netlink_kernel_release(nls); unregister_flashnode_bus: @@ -4631,6 +4763,7 @@ unregister_transport_class: static void __exit iscsi_transport_exit(void) { + destroy_workqueue(iscsi_destroy_workq); destroy_workqueue(iscsi_eh_timer_workq); netlink_kernel_release(nls); bus_unregister(&iscsi_flashnode_bus); diff --git a/drivers/scsi/smartpqi/Kconfig b/drivers/scsi/smartpqi/Kconfig index bc6506884e3b..d3311c014863 100644 --- a/drivers/scsi/smartpqi/Kconfig +++ b/drivers/scsi/smartpqi/Kconfig @@ -53,4 +53,4 @@ config SCSI_SMARTPQI Note: the aacraid driver will not manage a smartpqi controller. You need to enable smartpqi for smartpqi controllers. For more information, please see - Documentation/scsi/smartpqi.txt + Documentation/scsi/smartpqi.rst diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index b7492568e02f..cd157f11eb22 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -1614,28 +1614,28 @@ static void pqi_dev_info(struct pqi_ctrl_info *ctrl_info, "%d:%d:", ctrl_info->scsi_host->host_no, device->bus); if (device->target_lun_valid) - count += snprintf(buffer + count, + count += scnprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count, "%d:%d", device->target, device->lun); else - count += snprintf(buffer + count, + count += scnprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count, "-:-"); if (pqi_is_logical_device(device)) - count += snprintf(buffer + count, + count += scnprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count, " %08x%08x", *((u32 *)&device->scsi3addr), *((u32 *)&device->scsi3addr[4])); else - count += snprintf(buffer + count, + count += scnprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count, " %016llx", device->sas_address); - count += snprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count, + count += scnprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count, " %s %.8s %.16s ", pqi_device_type(device), device->vendor, @@ -1643,19 +1643,19 @@ static void pqi_dev_info(struct pqi_ctrl_info *ctrl_info, if (pqi_is_logical_device(device)) { if (device->devtype == TYPE_DISK) - count += snprintf(buffer + count, + count += scnprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count, "SSDSmartPathCap%c En%c %-12s", device->raid_bypass_configured ? '+' : '-', device->raid_bypass_enabled ? '+' : '-', pqi_raid_level_to_string(device->raid_level)); } else { - count += snprintf(buffer + count, + count += scnprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count, "AIO%c", device->aio_enabled ? '+' : '-'); if (device->devtype == TYPE_DISK || device->devtype == TYPE_ZBC) - count += snprintf(buffer + count, + count += scnprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count, " qd=%-6d", device->queue_depth); } @@ -6191,14 +6191,14 @@ static ssize_t pqi_lockup_action_show(struct device *dev, for (i = 0; i < ARRAY_SIZE(pqi_lockup_actions); i++) { if (pqi_lockup_actions[i].action == pqi_lockup_action) - count += snprintf(buffer + count, PAGE_SIZE - count, + count += scnprintf(buffer + count, PAGE_SIZE - count, "[%s] ", pqi_lockup_actions[i].name); else - count += snprintf(buffer + count, PAGE_SIZE - count, + count += scnprintf(buffer + count, PAGE_SIZE - count, "%s ", pqi_lockup_actions[i].name); } - count += snprintf(buffer + count, PAGE_SIZE - count, "\n"); + count += scnprintf(buffer + count, PAGE_SIZE - count, "\n"); return count; } diff --git a/drivers/scsi/snic/vnic_devcmd.h b/drivers/scsi/snic/vnic_devcmd.h index d81b4f0ceaaa..0e0fa38f8d90 100644 --- a/drivers/scsi/snic/vnic_devcmd.h +++ b/drivers/scsi/snic/vnic_devcmd.h @@ -208,7 +208,7 @@ struct vnic_devcmd_notify { struct vnic_devcmd_provinfo { u8 oui[3]; u8 type; - u8 data[0]; + u8 data[]; }; /* diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index e4240e4ae8bb..1c270e6034d5 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -79,7 +79,6 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM); CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \ CDC_MRW|CDC_MRW_W|CDC_RAM) -static DEFINE_MUTEX(sr_mutex); static int sr_probe(struct device *); static int sr_remove(struct device *); static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt); @@ -536,9 +535,9 @@ static int sr_block_open(struct block_device *bdev, fmode_t mode) scsi_autopm_get_device(sdev); check_disk_change(bdev); - mutex_lock(&sr_mutex); + mutex_lock(&cd->lock); ret = cdrom_open(&cd->cdi, bdev, mode); - mutex_unlock(&sr_mutex); + mutex_unlock(&cd->lock); scsi_autopm_put_device(sdev); if (ret) @@ -551,10 +550,10 @@ out: static void sr_block_release(struct gendisk *disk, fmode_t mode) { struct scsi_cd *cd = scsi_cd(disk); - mutex_lock(&sr_mutex); + mutex_lock(&cd->lock); cdrom_release(&cd->cdi, mode); scsi_cd_put(cd); - mutex_unlock(&sr_mutex); + mutex_unlock(&cd->lock); } static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, @@ -565,7 +564,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, void __user *argp = (void __user *)arg; int ret; - mutex_lock(&sr_mutex); + mutex_lock(&cd->lock); ret = scsi_ioctl_block_when_processing_errors(sdev, cmd, (mode & FMODE_NDELAY) != 0); @@ -595,7 +594,7 @@ put: scsi_autopm_put_device(sdev); out: - mutex_unlock(&sr_mutex); + mutex_unlock(&cd->lock); return ret; } @@ -608,7 +607,7 @@ static int sr_block_compat_ioctl(struct block_device *bdev, fmode_t mode, unsign void __user *argp = compat_ptr(arg); int ret; - mutex_lock(&sr_mutex); + mutex_lock(&cd->lock); ret = scsi_ioctl_block_when_processing_errors(sdev, cmd, (mode & FMODE_NDELAY) != 0); @@ -638,7 +637,7 @@ put: scsi_autopm_put_device(sdev); out: - mutex_unlock(&sr_mutex); + mutex_unlock(&cd->lock); return ret; } @@ -745,6 +744,7 @@ static int sr_probe(struct device *dev) disk = alloc_disk(1); if (!disk) goto fail_free; + mutex_init(&cd->lock); spin_lock(&sr_index_lock); minor = find_first_zero_bit(sr_index_bits, SR_DISKS); @@ -1055,6 +1055,8 @@ static void sr_kref_release(struct kref *kref) put_disk(disk); + mutex_destroy(&cd->lock); + kfree(cd); } diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h index a2bb7b8bace5..339c624e04d8 100644 --- a/drivers/scsi/sr.h +++ b/drivers/scsi/sr.h @@ -20,6 +20,7 @@ #include <linux/genhd.h> #include <linux/kref.h> +#include <linux/mutex.h> #define MAX_RETRIES 3 #define SR_TIMEOUT (30 * HZ) @@ -51,6 +52,7 @@ typedef struct scsi_cd { bool ignore_get_event:1; /* GET_EVENT is unreliable, use TUR */ struct cdrom_device_info cdi; + struct mutex lock; /* We hold gendisk and scsi_device references on probe and use * the refs on this kref to decide when to release them */ struct kref kref; diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c index 17a56c87d383..1f988a1b9166 100644 --- a/drivers/scsi/sr_vendor.c +++ b/drivers/scsi/sr_vendor.c @@ -67,9 +67,6 @@ void sr_vendor_init(Scsi_CD *cd) { -#ifndef CONFIG_BLK_DEV_SR_VENDOR - cd->vendor = VENDOR_SCSI3; -#else const char *vendor = cd->device->vendor; const char *model = cd->device->model; @@ -118,7 +115,6 @@ void sr_vendor_init(Scsi_CD *cd) CDC_PLAY_AUDIO ); } -#endif } @@ -132,10 +128,8 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength) struct ccs_modesel_head *modesel; int rc, density = 0; -#ifdef CONFIG_BLK_DEV_SR_VENDOR if (cd->vendor == VENDOR_TOSHIBA) density = (blocklength > 2048) ? 0x81 : 0x83; -#endif buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) @@ -223,7 +217,6 @@ int sr_cd_check(struct cdrom_device_info *cdi) } break; -#ifdef CONFIG_BLK_DEV_SR_VENDOR case VENDOR_NEC:{ unsigned long min, sec, frame; cgc.cmd[0] = 0xde; @@ -316,7 +309,6 @@ int sr_cd_check(struct cdrom_device_info *cdi) sector = buffer[11] + (buffer[10] << 8) + (buffer[9] << 16) + (buffer[8] << 24); break; -#endif /* CONFIG_BLK_DEV_SR_VENDOR */ default: /* should not happen */ diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 393f3019ccac..c5f9b348b438 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying - file Documentation/scsi/st.txt for more information. + file Documentation/scsi/st.rst for more information. History: Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara. @@ -45,6 +45,7 @@ static const char *verstr = "20160209"; #include <linux/uaccess.h> #include <asm/dma.h> +#include <asm/unaligned.h> #include <scsi/scsi.h> #include <scsi/scsi_dbg.h> @@ -2680,8 +2681,7 @@ static void deb_space_print(struct scsi_tape *STp, int direction, char *units, u if (!debugging) return; - sc = cmd[2] & 0x80 ? 0xff000000 : 0; - sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4]; + sc = sign_extend32(get_unaligned_be24(&cmd[2]), 23); if (direction) sc = -sc; st_printk(ST_DEB_MSG, STp, "Spacing tape %s over %d %s.\n", diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 33287b6bdf0e..d4f10c0d813c 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -236,7 +236,7 @@ struct req_msg { u8 data_dir; u8 payload_sz; /* payload size in 4-byte, not used */ u8 cdb[STEX_CDB_LENGTH]; - u32 variable[0]; + u32 variable[]; }; struct status_msg { diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index d14c2243e02a..e2005aeddc2d 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -46,7 +46,7 @@ config SCSI_UFSHCD The module will be called ufshcd. To compile this driver as a module, choose M here and read - <file:Documentation/scsi/ufs.txt>. + <file:Documentation/scsi/ufs.rst>. However, do not compile this as a module if your root file system (the one containing the directory /) is located on a UFS device. diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c index 56a6a1ed5ec2..da065a259f6e 100644 --- a/drivers/scsi/ufs/cdns-pltfrm.c +++ b/drivers/scsi/ufs/cdns-pltfrm.c @@ -192,7 +192,7 @@ static int cdns_ufs_link_startup_notify(struct ufs_hba *hba, * and device TX LCC are disabled once link startup is * completed. */ - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); + ufshcd_disable_host_tx_lcc(hba); /* * Disabling Autohibern8 feature in cadence UFS diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c index 5d6487350a6c..074a6a055a4c 100644 --- a/drivers/scsi/ufs/ufs-hisi.c +++ b/drivers/scsi/ufs/ufs-hisi.c @@ -235,7 +235,7 @@ static int ufs_hisi_link_startup_pre_change(struct ufs_hba *hba) ufshcd_writel(hba, reg, REG_AUTO_HIBERNATE_IDLE_TIMER); /* Unipro PA_Local_TX_LCC_Enable */ - ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x155E, 0x0), 0x0); + ufshcd_disable_host_tx_lcc(hba); /* close Unipro VS_Mk2ExtnSupport */ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), 0x0); ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), &value); diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 53eae5fe2ade..40a66b31b31f 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -66,6 +66,21 @@ static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable) } } +static int ufs_mtk_hce_enable_notify(struct ufs_hba *hba, + enum ufs_notify_change_status status) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + if (status == PRE_CHANGE) { + if (host->unipro_lpm) + hba->hba_enable_delay_us = 0; + else + hba->hba_enable_delay_us = 600; + } + + return 0; +} + static int ufs_mtk_bind_mphy(struct ufs_hba *hba) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); @@ -107,6 +122,7 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) if (on) { ufs_mtk_ref_clk_notify(on, res); + ufshcd_delay_us(host->ref_clk_ungating_wait_us, 10); ufshcd_writel(hba, REFCLK_REQUEST, REG_UFS_REFCLK_CTRL); } else { ufshcd_writel(hba, REFCLK_RELEASE, REG_UFS_REFCLK_CTRL); @@ -132,12 +148,40 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) out: host->ref_clk_enabled = on; - if (!on) + if (!on) { + ufshcd_delay_us(host->ref_clk_gating_wait_us, 10); ufs_mtk_ref_clk_notify(on, res); + } return 0; } +static void ufs_mtk_setup_ref_clk_wait_us(struct ufs_hba *hba, + u16 gating_us, u16 ungating_us) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + if (hba->dev_info.clk_gating_wait_us) { + host->ref_clk_gating_wait_us = + hba->dev_info.clk_gating_wait_us; + } else { + host->ref_clk_gating_wait_us = gating_us; + } + + host->ref_clk_ungating_wait_us = ungating_us; +} + +static u32 ufs_mtk_link_get_state(struct ufs_hba *hba) +{ + u32 val; + + ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL); + val = ufshcd_readl(hba, REG_UFS_PROBE); + val = val >> 28; + + return val; +} + /** * ufs_mtk_setup_clocks - enables/disable clocks * @hba: host controller instance @@ -150,7 +194,7 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, enum ufs_notify_change_status status) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); - int ret = -EINVAL; + int ret = 0; /* * In case ufs_mtk_init() is not yet done, simply ignore. @@ -160,19 +204,24 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, if (!host) return 0; - switch (status) { - case PRE_CHANGE: - if (!on) { + if (!on && status == PRE_CHANGE) { + if (!ufshcd_is_link_active(hba)) { ufs_mtk_setup_ref_clk(hba, on); ret = phy_power_off(host->mphy); + } else { + /* + * Gate ref-clk if link state is in Hibern8 + * triggered by Auto-Hibern8. + */ + if (!ufshcd_can_hibern8_during_gating(hba) && + ufshcd_is_auto_hibern8_enabled(hba) && + ufs_mtk_link_get_state(hba) == + VS_LINK_HIBERN8) + ufs_mtk_setup_ref_clk(hba, on); } - break; - case POST_CHANGE: - if (on) { - ret = phy_power_on(host->mphy); - ufs_mtk_setup_ref_clk(hba, on); - } - break; + } else if (on && status == POST_CHANGE) { + ret = phy_power_on(host->mphy); + ufs_mtk_setup_ref_clk(hba, on); } return ret; @@ -285,11 +334,36 @@ static int ufs_mtk_pwr_change_notify(struct ufs_hba *hba, return ret; } +static int ufs_mtk_unipro_set_pm(struct ufs_hba *hba, u32 lpm) +{ + int ret; + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + ret = ufshcd_dme_set(hba, + UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), + lpm); + if (!ret) + host->unipro_lpm = lpm; + + return ret; +} + static int ufs_mtk_pre_link(struct ufs_hba *hba) { int ret; u32 tmp; + ufs_mtk_unipro_set_pm(hba, 0); + + /* + * Setting PA_Local_TX_LCC_Enable to 0 before link startup + * to make sure that both host and device TX LCC are disabled + * once link startup is completed. + */ + ret = ufshcd_disable_host_tx_lcc(hba); + if (ret) + return ret; + /* disable deep stall */ ret = ufshcd_dme_get(hba, UIC_ARG_MIB(VS_SAVEPOWERCONTROL), &tmp); if (ret) @@ -321,9 +395,6 @@ static void ufs_mtk_setup_clk_gating(struct ufs_hba *hba) static int ufs_mtk_post_link(struct ufs_hba *hba) { - /* disable device LCC */ - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); - /* enable unipro clock gating feature */ ufs_mtk_cfg_unipro_cg(hba, true); @@ -390,9 +461,7 @@ static int ufs_mtk_link_set_hpm(struct ufs_hba *hba) if (err) return err; - err = ufshcd_dme_set(hba, - UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), - 0); + err = ufs_mtk_unipro_set_pm(hba, 0); if (err) return err; @@ -413,14 +482,10 @@ static int ufs_mtk_link_set_lpm(struct ufs_hba *hba) { int err; - err = ufshcd_dme_set(hba, - UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), - 1); + err = ufs_mtk_unipro_set_pm(hba, 1); if (err) { /* Resume UniPro state for following error recovery */ - ufshcd_dme_set(hba, - UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), - 0); + ufs_mtk_unipro_set_pm(hba, 0); return err; } @@ -436,10 +501,11 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) err = ufs_mtk_link_set_lpm(hba); if (err) return -EAGAIN; - phy_power_off(host->mphy); - ufs_mtk_setup_ref_clk(hba, false); } + if (!ufshcd_is_link_active(hba)) + phy_power_off(host->mphy); + return 0; } @@ -448,9 +514,10 @@ static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) struct ufs_mtk_host *host = ufshcd_get_variant(hba); int err; - if (ufshcd_is_link_hibern8(hba)) { - ufs_mtk_setup_ref_clk(hba, true); + if (!ufshcd_is_link_active(hba)) phy_power_on(host->mphy); + + if (ufshcd_is_link_hibern8(hba)) { err = ufs_mtk_link_set_hpm(hba); if (err) return err; @@ -477,9 +544,24 @@ static void ufs_mtk_dbg_register_dump(struct ufs_hba *hba) static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba) { struct ufs_dev_info *dev_info = &hba->dev_info; + u16 mid = dev_info->wmanufacturerid; - if (dev_info->wmanufacturerid == UFS_VENDOR_SAMSUNG) + if (mid == UFS_VENDOR_SAMSUNG) { + hba->dev_quirks &= ~UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE; ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 6); + } + + /* + * Decide waiting time before gating reference clock and + * after ungating reference clock according to vendors' + * requirements. + */ + if (mid == UFS_VENDOR_SAMSUNG) + ufs_mtk_setup_ref_clk_wait_us(hba, 1, 1); + else if (mid == UFS_VENDOR_SKHYNIX) + ufs_mtk_setup_ref_clk_wait_us(hba, 30, 30); + else if (mid == UFS_VENDOR_TOSHIBA) + ufs_mtk_setup_ref_clk_wait_us(hba, 100, 32); return 0; } @@ -494,6 +576,7 @@ static struct ufs_hba_variant_ops ufs_hba_mtk_vops = { .name = "mediatek.ufshci", .init = ufs_mtk_init, .setup_clocks = ufs_mtk_setup_clocks, + .hce_enable_notify = ufs_mtk_hce_enable_notify, .link_startup_notify = ufs_mtk_link_startup_notify, .pwr_change_notify = ufs_mtk_pwr_change_notify, .apply_dev_quirks = ufs_mtk_apply_dev_quirks, diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index fccdd979d6fb..5bbd3e9cbae2 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -54,6 +54,18 @@ #define VS_UNIPROPOWERDOWNCONTROL 0xD0A8 /* + * Vendor specific link state + */ +enum { + VS_LINK_DISABLED = 0, + VS_LINK_DOWN = 1, + VS_LINK_UP = 2, + VS_LINK_HIBERN8 = 3, + VS_LINK_LOST = 4, + VS_LINK_CFG = 5, +}; + +/* * SiP commands */ #define MTK_SIP_UFS_CONTROL MTK_SIP_SMC_CMD(0x276) @@ -79,7 +91,10 @@ enum { struct ufs_mtk_host { struct ufs_hba *hba; struct phy *mphy; + bool unipro_lpm; bool ref_clk_enabled; + u16 ref_clk_ungating_wait_us; + u16 ref_clk_gating_wait_us; }; #endif /* !_UFS_MEDIATEK_H */ diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index c69c29a1ceb9..19aa5c44e0da 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -10,6 +10,7 @@ #include <linux/phy/phy.h> #include <linux/gpio/consumer.h> #include <linux/reset-controller.h> +#include <linux/devfreq.h> #include "ufshcd.h" #include "ufshcd-pltfrm.h" @@ -38,7 +39,6 @@ enum { static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS]; -static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote); static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host); static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba, u32 clk_cycles); @@ -554,9 +554,7 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, * completed. */ if (ufshcd_get_local_unipro_ver(hba) != UFS_UNIPRO_VER_1_41) - err = ufshcd_dme_set(hba, - UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), - 0); + err = ufshcd_disable_host_tx_lcc(hba); break; case POST_CHANGE: @@ -674,7 +672,7 @@ static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result) } } -static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) +static int __ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) { int err = 0; @@ -705,7 +703,7 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) vote = ufs_qcom_get_bus_vote(host, mode); if (vote >= 0) - err = ufs_qcom_set_bus_vote(host, vote); + err = __ufs_qcom_set_bus_vote(host, vote); else err = vote; @@ -716,6 +714,35 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) return err; } +static int ufs_qcom_set_bus_vote(struct ufs_hba *hba, bool on) +{ + struct ufs_qcom_host *host = ufshcd_get_variant(hba); + int vote, err; + + /* + * In case ufs_qcom_init() is not yet done, simply ignore. + * This ufs_qcom_set_bus_vote() shall be called from + * ufs_qcom_init() after init is done. + */ + if (!host) + return 0; + + if (on) { + vote = host->bus_vote.saved_vote; + if (vote == host->bus_vote.min_bw_vote) + ufs_qcom_update_bus_bw_vote(host); + } else { + vote = host->bus_vote.min_bw_vote; + } + + err = __ufs_qcom_set_bus_vote(host, vote); + if (err) + dev_err(hba->dev, "%s: set bus vote failed %d\n", + __func__, err); + + return err; +} + static ssize_t show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr, char *buf) @@ -792,7 +819,7 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) return 0; } -static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) +static int ufs_qcom_set_bus_vote(struct ufs_hba *host, bool on) { return 0; } @@ -817,11 +844,27 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable) /* * If we are here to disable this clock it might be immediately * after entering into hibern8 in which case we need to make - * sure that device ref_clk is active at least 1us after the + * sure that device ref_clk is active for specific time after * hibern8 enter. */ - if (!enable) - udelay(1); + if (!enable) { + unsigned long gating_wait; + + gating_wait = host->hba->dev_info.clk_gating_wait_us; + if (!gating_wait) { + udelay(1); + } else { + /* + * bRefClkGatingWaitTime defines the minimum + * time for which the reference clock is + * required by device during transition from + * HS-MODE to LS-MODE or HIBERN8 state. Give it + * more delay to be on the safe side. + */ + gating_wait += 10; + usleep_range(gating_wait, gating_wait + 10); + } + } writel_relaxed(temp, host->dev_ref_clk_ctrl_mmio); @@ -898,6 +941,20 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, if (!ufshcd_is_hs_mode(&hba->pwr_info) && ufshcd_is_hs_mode(dev_req_params)) ufs_qcom_dev_ref_clk_ctrl(host, true); + + if (host->hw_ver.major >= 0x4) { + if (dev_req_params->gear_tx == UFS_HS_G4) { + /* INITIAL ADAPT */ + ufshcd_dme_set(hba, + UIC_ARG_MIB(PA_TXHSADAPTTYPE), + PA_INITIAL_ADAPT); + } else { + /* NO ADAPT */ + ufshcd_dme_set(hba, + UIC_ARG_MIB(PA_TXHSADAPTTYPE), + PA_NO_ADAPT); + } + } break; case POST_CHANGE: if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx, @@ -956,6 +1013,9 @@ static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba) if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME) err = ufs_qcom_quirk_host_pa_saveconfigtime(hba); + if (hba->dev_info.wmanufacturerid == UFS_VENDOR_WDC) + hba->dev_quirks |= UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE; + return err; } @@ -1030,8 +1090,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, enum ufs_notify_change_status status) { struct ufs_qcom_host *host = ufshcd_get_variant(hba); - int err; - int vote = 0; + int err = 0; /* * In case ufs_qcom_init() is not yet done, simply ignore. @@ -1041,28 +1100,28 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, if (!host) return 0; - if (on && (status == POST_CHANGE)) { - /* enable the device ref clock for HS mode*/ - if (ufshcd_is_hs_mode(&hba->pwr_info)) - ufs_qcom_dev_ref_clk_ctrl(host, true); - vote = host->bus_vote.saved_vote; - if (vote == host->bus_vote.min_bw_vote) - ufs_qcom_update_bus_bw_vote(host); - - } else if (!on && (status == PRE_CHANGE)) { - if (!ufs_qcom_is_link_active(hba)) { - /* disable device ref_clk */ - ufs_qcom_dev_ref_clk_ctrl(host, false); + switch (status) { + case PRE_CHANGE: + if (on) { + err = ufs_qcom_set_bus_vote(hba, true); + } else { + if (!ufs_qcom_is_link_active(hba)) { + /* disable device ref_clk */ + ufs_qcom_dev_ref_clk_ctrl(host, false); + } } - - vote = host->bus_vote.min_bw_vote; + break; + case POST_CHANGE: + if (on) { + /* enable the device ref clock for HS mode*/ + if (ufshcd_is_hs_mode(&hba->pwr_info)) + ufs_qcom_dev_ref_clk_ctrl(host, true); + } else { + err = ufs_qcom_set_bus_vote(hba, false); + } + break; } - err = ufs_qcom_set_bus_vote(host, vote); - if (err) - dev_err(hba->dev, "%s: set bus vote failed %d\n", - __func__, err); - return err; } @@ -1238,6 +1297,7 @@ static int ufs_qcom_init(struct ufs_hba *hba) ufs_qcom_set_caps(hba); ufs_qcom_advertise_quirks(hba); + ufs_qcom_set_bus_vote(hba, true); ufs_qcom_setup_clocks(hba, true, POST_CHANGE); if (hba->dev->id < MAX_UFS_QCOM_HOSTS) @@ -1630,6 +1690,29 @@ static void ufs_qcom_device_reset(struct ufs_hba *hba) usleep_range(10, 15); } +#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) +static void ufs_qcom_config_scaling_param(struct ufs_hba *hba, + struct devfreq_dev_profile *p, + void *data) +{ + static struct devfreq_simple_ondemand_data *d; + + if (!data) + return; + + d = (struct devfreq_simple_ondemand_data *)data; + p->polling_ms = 60; + d->upthreshold = 70; + d->downdifferential = 5; +} +#else +static void ufs_qcom_config_scaling_param(struct ufs_hba *hba, + struct devfreq_dev_profile *p, + void *data) +{ +} +#endif + /** * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations * @@ -1651,6 +1734,7 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { .resume = ufs_qcom_resume, .dbg_register_dump = ufs_qcom_dump_dbg_regs, .device_reset = ufs_qcom_device_reset, + .config_scaling_param = ufs_qcom_config_scaling_param, }; /** diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index dbdf8b01abed..92a63eebdca9 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -210,8 +210,10 @@ static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba, if (param_size > 8) return -EINVAL; + pm_runtime_get_sync(hba->dev); ret = ufshcd_read_desc_param(hba, desc_id, desc_index, param_offset, desc_buf, param_size); + pm_runtime_put_sync(hba->dev); if (ret) return -EINVAL; switch (param_size) { @@ -558,6 +560,7 @@ static ssize_t _name##_show(struct device *dev, \ desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC); \ if (!desc_buf) \ return -ENOMEM; \ + pm_runtime_get_sync(hba->dev); \ ret = ufshcd_query_descriptor_retry(hba, \ UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE, \ 0, 0, desc_buf, &desc_len); \ @@ -574,6 +577,7 @@ static ssize_t _name##_show(struct device *dev, \ goto out; \ ret = snprintf(buf, PAGE_SIZE, "%s\n", desc_buf); \ out: \ + pm_runtime_put_sync(hba->dev); \ kfree(desc_buf); \ return ret; \ } \ @@ -604,9 +608,13 @@ static ssize_t _name##_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ bool flag; \ + int ret; \ struct ufs_hba *hba = dev_get_drvdata(dev); \ - if (ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG, \ - QUERY_FLAG_IDN##_uname, &flag)) \ + pm_runtime_get_sync(hba->dev); \ + ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG, \ + QUERY_FLAG_IDN##_uname, &flag); \ + pm_runtime_put_sync(hba->dev); \ + if (ret) \ return -EINVAL; \ return sprintf(buf, "%s\n", flag ? "true" : "false"); \ } \ @@ -644,8 +652,12 @@ static ssize_t _name##_show(struct device *dev, \ { \ struct ufs_hba *hba = dev_get_drvdata(dev); \ u32 value; \ - if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \ - QUERY_ATTR_IDN##_uname, 0, 0, &value)) \ + int ret; \ + pm_runtime_get_sync(hba->dev); \ + ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \ + QUERY_ATTR_IDN##_uname, 0, 0, &value); \ + pm_runtime_put_sync(hba->dev); \ + if (ret) \ return -EINVAL; \ return sprintf(buf, "0x%08X\n", value); \ } \ @@ -766,9 +778,13 @@ static ssize_t dyn_cap_needed_attribute_show(struct device *dev, struct scsi_device *sdev = to_scsi_device(dev); struct ufs_hba *hba = shost_priv(sdev->host); u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun); + int ret; - if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, - QUERY_ATTR_IDN_DYN_CAP_NEEDED, lun, 0, &value)) + pm_runtime_get_sync(hba->dev); + ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_DYN_CAP_NEEDED, lun, 0, &value); + pm_runtime_put_sync(hba->dev); + if (ret) return -EINVAL; return sprintf(buf, "0x%08X\n", value); } diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index cfe380348bf0..990cb48e2403 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -167,6 +167,7 @@ enum attr_idn { QUERY_ATTR_IDN_FFU_STATUS = 0x14, QUERY_ATTR_IDN_PSA_STATE = 0x15, QUERY_ATTR_IDN_PSA_DATA_SIZE = 0x16, + QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME = 0x17, }; /* Descriptor idn for Query requests */ @@ -534,6 +535,8 @@ struct ufs_dev_info { u16 wmanufacturerid; /*UFS device Product Name */ u8 *model; + u16 wspecversion; + u32 clk_gating_wait_us; }; /** diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index d0ab147f98d3..df7a1e6805a3 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -15,6 +15,7 @@ #define UFS_VENDOR_TOSHIBA 0x198 #define UFS_VENDOR_SAMSUNG 0x1CE #define UFS_VENDOR_SKHYNIX 0x1AD +#define UFS_VENDOR_WDC 0x145 /** * ufs_dev_fix - ufs device quirk info diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 3b19de3ae9a3..8f78a8151499 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -44,7 +44,7 @@ static int ufs_intel_disable_lcc(struct ufs_hba *hba) ufshcd_dme_get(hba, attr, &lcc_enable); if (lcc_enable) - ufshcd_dme_set(hba, attr, 0); + ufshcd_disable_host_tx_lcc(hba); return 0; } diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 2d705694636c..e04e8b8bdca6 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -42,6 +42,7 @@ #include <linux/nls.h> #include <linux/of.h> #include <linux/bitfield.h> +#include <linux/blk-pm.h> #include "ufshcd.h" #include "ufs_quirks.h" #include "unipro.h" @@ -91,6 +92,9 @@ /* default delay of autosuspend: 2000 ms */ #define RPM_AUTOSUSPEND_DELAY_MS 2000 +/* Default value of wait time before gating device ref clock */ +#define UFSHCD_REF_CLK_GATING_WAIT_US 0xFF /* microsecs */ + #define ufshcd_toggle_vreg(_dev, _vreg, _on) \ ({ \ int _ret; \ @@ -532,6 +536,18 @@ static void ufshcd_print_pwr_info(struct ufs_hba *hba) hba->pwr_info.hs_rate); } +void ufshcd_delay_us(unsigned long us, unsigned long tolerance) +{ + if (!us) + return; + + if (us < 10) + udelay(us); + else + usleep_range(us, us + tolerance); +} +EXPORT_SYMBOL_GPL(ufshcd_delay_us); + /* * ufshcd_wait_for_register - wait for register value to change * @hba - per-adapter interface @@ -642,11 +658,7 @@ static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp) */ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos) { - if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR) - ufshcd_writel(hba, (1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR); - else - ufshcd_writel(hba, ~(1 << pos), - REG_UTP_TRANSFER_REQ_LIST_CLEAR); + ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR); } /** @@ -656,10 +668,7 @@ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos) */ static inline void ufshcd_utmrl_clear(struct ufs_hba *hba, u32 pos) { - if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR) - ufshcd_writel(hba, (1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); - else - ufshcd_writel(hba, ~(1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); + ufshcd_writel(hba, ~(1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); } /** @@ -1191,6 +1200,9 @@ static int ufshcd_devfreq_target(struct device *dev, if (!ufshcd_is_clkscaling_supported(hba)) return -EINVAL; + clki = list_first_entry(&hba->clk_list_head, struct ufs_clk_info, list); + /* Override with the closest supported frequency */ + *freq = (unsigned long) clk_round_rate(clki->clk, *freq); spin_lock_irqsave(hba->host->host_lock, irq_flags); if (ufshcd_eh_in_progress(hba)) { spin_unlock_irqrestore(hba->host->host_lock, irq_flags); @@ -1205,8 +1217,11 @@ static int ufshcd_devfreq_target(struct device *dev, goto out; } - clki = list_first_entry(&hba->clk_list_head, struct ufs_clk_info, list); + /* Decide based on the rounded-off frequency and update */ scale_up = (*freq == clki->max_freq) ? true : false; + if (!scale_up) + *freq = clki->min_freq; + /* Update the frequency */ if (!ufshcd_is_devfreq_scaling_required(hba, scale_up)) { spin_unlock_irqrestore(hba->host->host_lock, irq_flags); ret = 0; @@ -1254,6 +1269,8 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev, struct ufs_hba *hba = dev_get_drvdata(dev); struct ufs_clk_scaling *scaling = &hba->clk_scaling; unsigned long flags; + struct list_head *clk_list = &hba->clk_list_head; + struct ufs_clk_info *clki; if (!ufshcd_is_clkscaling_supported(hba)) return -EINVAL; @@ -1264,6 +1281,13 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev, if (!scaling->window_start_t) goto start_window; + clki = list_first_entry(clk_list, struct ufs_clk_info, list); + /* + * If current frequency is 0, then the ondemand governor considers + * there's no initial frequency set. And it always requests to set + * to max. frequency. + */ + stat->current_frequency = clki->curr_freq; if (scaling->is_busy_started) scaling->tot_busy_t += ktime_to_us(ktime_sub(ktime_get(), scaling->busy_start_t)); @@ -1292,6 +1316,17 @@ static struct devfreq_dev_profile ufs_devfreq_profile = { .get_dev_status = ufshcd_devfreq_get_dev_status, }; +#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) +static struct devfreq_simple_ondemand_data ufs_ondemand_data = { + .upthreshold = 70, + .downdifferential = 5, +}; + +static void *gov_data = &ufs_ondemand_data; +#else +static void *gov_data; /* NULL */ +#endif + static int ufshcd_devfreq_init(struct ufs_hba *hba) { struct list_head *clk_list = &hba->clk_list_head; @@ -1307,10 +1342,12 @@ static int ufshcd_devfreq_init(struct ufs_hba *hba) dev_pm_opp_add(hba->dev, clki->min_freq, 0); dev_pm_opp_add(hba->dev, clki->max_freq, 0); + ufshcd_vops_config_scaling_param(hba, &ufs_devfreq_profile, + gov_data); devfreq = devfreq_add_device(hba->dev, &ufs_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND, - NULL); + gov_data); if (IS_ERR(devfreq)) { ret = PTR_ERR(devfreq); dev_err(hba->dev, "Unable to register with devfreq %d\n", ret); @@ -1518,6 +1555,11 @@ start: */ if (ufshcd_can_hibern8_during_gating(hba) && ufshcd_is_link_hibern8(hba)) { + if (async) { + rc = -EAGAIN; + hba->clk_gating.active_reqs--; + break; + } spin_unlock_irqrestore(hba->host->host_lock, flags); flush_work(&hba->clk_gating.ungate_work); spin_lock_irqsave(hba->host->host_lock, flags); @@ -2093,13 +2135,8 @@ static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) return sg_segments; if (sg_segments) { - if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) - lrbp->utr_descriptor_ptr->prd_table_length = - cpu_to_le16((u16)(sg_segments * - sizeof(struct ufshcd_sg_entry))); - else - lrbp->utr_descriptor_ptr->prd_table_length = - cpu_to_le16((u16) (sg_segments)); + lrbp->utr_descriptor_ptr->prd_table_length = + cpu_to_le16((u16)sg_segments); prd_table = (struct ufshcd_sg_entry *)lrbp->ucd_prdt_ptr; @@ -2363,6 +2400,27 @@ static inline u16 ufshcd_upiu_wlun_to_scsi_wlun(u8 upiu_wlun_id) return (upiu_wlun_id & ~UFS_UPIU_WLUN_ID) | SCSI_W_LUN_BASE; } +static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i) +{ + struct utp_transfer_cmd_desc *cmd_descp = hba->ucdl_base_addr; + struct utp_transfer_req_desc *utrdlp = hba->utrdl_base_addr; + dma_addr_t cmd_desc_element_addr = hba->ucdl_dma_addr + + i * sizeof(struct utp_transfer_cmd_desc); + u16 response_offset = offsetof(struct utp_transfer_cmd_desc, + response_upiu); + u16 prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table); + + lrb->utr_descriptor_ptr = utrdlp + i; + lrb->utrd_dma_addr = hba->utrdl_dma_addr + + i * sizeof(struct utp_transfer_req_desc); + lrb->ucd_req_ptr = (struct utp_upiu_req *)(cmd_descp + i); + lrb->ucd_req_dma_addr = cmd_desc_element_addr; + lrb->ucd_rsp_ptr = (struct utp_upiu_rsp *)cmd_descp[i].response_upiu; + lrb->ucd_rsp_dma_addr = cmd_desc_element_addr + response_offset; + lrb->ucd_prdt_ptr = (struct ufshcd_sg_entry *)cmd_descp[i].prd_table; + lrb->ucd_prdt_dma_addr = cmd_desc_element_addr + prdt_offset; +} + /** * ufshcd_queuecommand - main entry point for SCSI requests * @host: SCSI host pointer @@ -2452,7 +2510,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) /* issue command to the controller */ spin_lock_irqsave(hba->host->host_lock, flags); - ufshcd_vops_setup_xfer_req(hba, tag, (lrbp->cmd ? true : false)); + ufshcd_vops_setup_xfer_req(hba, tag, true); ufshcd_send_command(hba, tag); out_unlock: spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -2639,7 +2697,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, /* Make sure descriptors are ready before ringing the doorbell */ wmb(); spin_lock_irqsave(hba->host->host_lock, flags); - ufshcd_vops_setup_xfer_req(hba, tag, (lrbp->cmd ? true : false)); + ufshcd_vops_setup_xfer_req(hba, tag, false); ufshcd_send_command(hba, tag); spin_unlock_irqrestore(hba->host->host_lock, flags); @@ -3276,6 +3334,31 @@ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba, param_offset, param_read_buf, param_size); } +static int ufshcd_get_ref_clk_gating_wait(struct ufs_hba *hba) +{ + int err = 0; + u32 gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US; + + if (hba->dev_info.wspecversion >= 0x300) { + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME, 0, 0, + &gating_wait); + if (err) + dev_err(hba->dev, "Failed reading bRefClkGatingWait. err = %d, use default %uus\n", + err, gating_wait); + + if (gating_wait == 0) { + gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US; + dev_err(hba->dev, "Undefined ref clk gating wait time, use default %uus\n", + gating_wait); + } + + hba->dev_info.clk_gating_wait_us = gating_wait; + } + + return err; +} + /** * ufshcd_memory_alloc - allocate memory for host memory space data structures * @hba: per adapter instance @@ -3373,7 +3456,6 @@ out: */ static void ufshcd_host_memory_configure(struct ufs_hba *hba) { - struct utp_transfer_cmd_desc *cmd_descp; struct utp_transfer_req_desc *utrdlp; dma_addr_t cmd_desc_dma_addr; dma_addr_t cmd_desc_element_addr; @@ -3383,7 +3465,6 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) int i; utrdlp = hba->utrdl_base_addr; - cmd_descp = hba->ucdl_base_addr; response_offset = offsetof(struct utp_transfer_cmd_desc, response_upiu); @@ -3403,36 +3484,13 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) cpu_to_le32(upper_32_bits(cmd_desc_element_addr)); /* Response upiu and prdt offset should be in double words */ - if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) { - utrdlp[i].response_upiu_offset = - cpu_to_le16(response_offset); - utrdlp[i].prd_table_offset = - cpu_to_le16(prdt_offset); - utrdlp[i].response_upiu_length = - cpu_to_le16(ALIGNED_UPIU_SIZE); - } else { - utrdlp[i].response_upiu_offset = - cpu_to_le16((response_offset >> 2)); - utrdlp[i].prd_table_offset = - cpu_to_le16((prdt_offset >> 2)); - utrdlp[i].response_upiu_length = - cpu_to_le16(ALIGNED_UPIU_SIZE >> 2); - } + utrdlp[i].response_upiu_offset = + cpu_to_le16(response_offset >> 2); + utrdlp[i].prd_table_offset = cpu_to_le16(prdt_offset >> 2); + utrdlp[i].response_upiu_length = + cpu_to_le16(ALIGNED_UPIU_SIZE >> 2); - hba->lrb[i].utr_descriptor_ptr = (utrdlp + i); - hba->lrb[i].utrd_dma_addr = hba->utrdl_dma_addr + - (i * sizeof(struct utp_transfer_req_desc)); - hba->lrb[i].ucd_req_ptr = - (struct utp_upiu_req *)(cmd_descp + i); - hba->lrb[i].ucd_req_dma_addr = cmd_desc_element_addr; - hba->lrb[i].ucd_rsp_ptr = - (struct utp_upiu_rsp *)cmd_descp[i].response_upiu; - hba->lrb[i].ucd_rsp_dma_addr = cmd_desc_element_addr + - response_offset; - hba->lrb[i].ucd_prdt_ptr = - (struct ufshcd_sg_entry *)cmd_descp[i].prd_table; - hba->lrb[i].ucd_prdt_dma_addr = cmd_desc_element_addr + - prdt_offset; + ufshcd_init_lrb(hba, &hba->lrb[i], i); } } @@ -3460,52 +3518,6 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) "dme-link-startup: error code %d\n", ret); return ret; } -/** - * ufshcd_dme_reset - UIC command for DME_RESET - * @hba: per adapter instance - * - * DME_RESET command is issued in order to reset UniPro stack. - * This function now deal with cold reset. - * - * Returns 0 on success, non-zero value on failure - */ -static int ufshcd_dme_reset(struct ufs_hba *hba) -{ - struct uic_command uic_cmd = {0}; - int ret; - - uic_cmd.command = UIC_CMD_DME_RESET; - - ret = ufshcd_send_uic_cmd(hba, &uic_cmd); - if (ret) - dev_err(hba->dev, - "dme-reset: error code %d\n", ret); - - return ret; -} - -/** - * ufshcd_dme_enable - UIC command for DME_ENABLE - * @hba: per adapter instance - * - * DME_ENABLE command is issued in order to enable UniPro stack. - * - * Returns 0 on success, non-zero value on failure - */ -static int ufshcd_dme_enable(struct ufs_hba *hba) -{ - struct uic_command uic_cmd = {0}; - int ret; - - uic_cmd.command = UIC_CMD_DME_ENABLE; - - ret = ufshcd_send_uic_cmd(hba, &uic_cmd); - if (ret) - dev_err(hba->dev, - "dme-reset: error code %d\n", ret); - - return ret; -} static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba) { @@ -4224,7 +4236,7 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep) } /** - * ufshcd_hba_execute_hce - initialize the controller + * ufshcd_hba_enable - initialize the controller * @hba: per adapter instance * * The controller resets itself and controller firmware initialization @@ -4233,7 +4245,7 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep) * * Returns 0 on success, non-zero value on failure */ -static int ufshcd_hba_execute_hce(struct ufs_hba *hba) +int ufshcd_hba_enable(struct ufs_hba *hba) { int retry; @@ -4259,10 +4271,10 @@ static int ufshcd_hba_execute_hce(struct ufs_hba *hba) * instruction might be read back. * This delay can be changed based on the controller. */ - usleep_range(1000, 1100); + ufshcd_delay_us(hba->hba_enable_delay_us, 100); /* wait for the host controller to complete initialization */ - retry = 10; + retry = 50; while (ufshcd_is_hba_active(hba)) { if (retry) { retry--; @@ -4271,7 +4283,7 @@ static int ufshcd_hba_execute_hce(struct ufs_hba *hba) "Controller enable failed\n"); return -EIO; } - usleep_range(5000, 5100); + usleep_range(1000, 1100); } /* enable UIC related interrupts */ @@ -4281,37 +4293,11 @@ static int ufshcd_hba_execute_hce(struct ufs_hba *hba) return 0; } - -int ufshcd_hba_enable(struct ufs_hba *hba) -{ - int ret; - - if (hba->quirks & UFSHCI_QUIRK_BROKEN_HCE) { - ufshcd_set_link_off(hba); - ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE); - - /* enable UIC related interrupts */ - ufshcd_enable_intr(hba, UFSHCD_UIC_MASK); - ret = ufshcd_dme_reset(hba); - if (!ret) { - ret = ufshcd_dme_enable(hba); - if (!ret) - ufshcd_vops_hce_enable_notify(hba, POST_CHANGE); - if (ret) - dev_err(hba->dev, - "Host controller enable failed with non-hce\n"); - } - } else { - ret = ufshcd_hba_execute_hce(hba); - } - - return ret; -} EXPORT_SYMBOL_GPL(ufshcd_hba_enable); static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer) { - int tx_lanes, i, err = 0; + int tx_lanes = 0, i, err = 0; if (!peer) ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), @@ -4737,8 +4723,15 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) * UFS device needs urgent BKOPs. */ if (!hba->pm_op_in_progress && - ufshcd_is_exception_event(lrbp->ucd_rsp_ptr)) - schedule_work(&hba->eeh_work); + ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) && + schedule_work(&hba->eeh_work)) { + /* + * Prevent suspend once eeh_work is scheduled + * to avoid deadlock between ufshcd_suspend + * and exception event handler. + */ + pm_runtime_get_noresume(hba->dev); + } break; case UPIU_TRANSACTION_REJECT_UPIU: /* TODO: handle Reject UPIU Response */ @@ -4876,8 +4869,7 @@ static irqreturn_t ufshcd_transfer_req_compl(struct ufs_hba *hba) * false interrupt if device completes another request after resetting * aggregation and before reading the DB. */ - if (ufshcd_is_intr_aggr_allowed(hba) && - !(hba->quirks & UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR)) + if (ufshcd_is_intr_aggr_allowed(hba)) ufshcd_reset_intr_aggr(hba); tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); @@ -5191,7 +5183,14 @@ static void ufshcd_exception_event_handler(struct work_struct *work) out: ufshcd_scsi_unblock_requests(hba); - pm_runtime_put_sync(hba->dev); + /* + * pm_runtime_get_noresume is called while scheduling + * eeh_work to avoid suspend racing with exception work. + * Hence decrement usage counter using pm_runtime_put_noidle + * to allow suspend on completion of exception event handler. + */ + pm_runtime_put_noidle(hba->dev); + pm_runtime_put(hba->dev); return; } @@ -5486,7 +5485,8 @@ static irqreturn_t ufshcd_update_uic_error(struct ufs_hba *hba) static bool ufshcd_is_auto_hibern8_error(struct ufs_hba *hba, u32 intr_mask) { - if (!ufshcd_is_auto_hibern8_supported(hba)) + if (!ufshcd_is_auto_hibern8_supported(hba) || + !ufshcd_is_auto_hibern8_enabled(hba)) return false; if (!(intr_mask & UFSHCD_UIC_HIBERN8_MASK)) @@ -6482,11 +6482,12 @@ out: return icc_level; } -static void ufshcd_init_icc_levels(struct ufs_hba *hba) +static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba) { int ret; int buff_len = hba->desc_size.pwr_desc; u8 *desc_buf; + u32 icc_level; desc_buf = kmalloc(buff_len, GFP_KERNEL); if (!desc_buf) @@ -6501,25 +6502,32 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) goto out; } - hba->init_prefetch_data.icc_level = - ufshcd_find_max_sup_active_icc_level(hba, - desc_buf, buff_len); - dev_dbg(hba->dev, "%s: setting icc_level 0x%x", - __func__, hba->init_prefetch_data.icc_level); + icc_level = ufshcd_find_max_sup_active_icc_level(hba, desc_buf, + buff_len); + dev_dbg(hba->dev, "%s: setting icc_level 0x%x", __func__, icc_level); ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, - QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, - &hba->init_prefetch_data.icc_level); + QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, &icc_level); if (ret) dev_err(hba->dev, "%s: Failed configuring bActiveICCLevel = %d ret = %d", - __func__, hba->init_prefetch_data.icc_level , ret); + __func__, icc_level, ret); out: kfree(desc_buf); } +static inline void ufshcd_blk_pm_runtime_init(struct scsi_device *sdev) +{ + scsi_autopm_get_device(sdev); + blk_pm_runtime_init(sdev->request_queue, &sdev->sdev_gendev); + if (sdev->rpm_autosuspend) + pm_runtime_set_autosuspend_delay(&sdev->sdev_gendev, + RPM_AUTOSUSPEND_DELAY_MS); + scsi_autopm_put_device(sdev); +} + /** * ufshcd_scsi_add_wlus - Adds required W-LUs * @hba: per-adapter instance @@ -6559,6 +6567,7 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) hba->sdev_ufs_device = NULL; goto out; } + ufshcd_blk_pm_runtime_init(hba->sdev_ufs_device); scsi_device_put(hba->sdev_ufs_device); sdev_rpmb = __scsi_add_device(hba->host, 0, 0, @@ -6567,14 +6576,17 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) ret = PTR_ERR(sdev_rpmb); goto remove_sdev_ufs_device; } + ufshcd_blk_pm_runtime_init(sdev_rpmb); scsi_device_put(sdev_rpmb); sdev_boot = __scsi_add_device(hba->host, 0, 0, ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); - if (IS_ERR(sdev_boot)) + if (IS_ERR(sdev_boot)) { dev_err(hba->dev, "%s: BOOT WLUN not found\n", __func__); - else + } else { + ufshcd_blk_pm_runtime_init(sdev_boot); scsi_device_put(sdev_boot); + } goto out; remove_sdev_ufs_device: @@ -6614,6 +6626,10 @@ static int ufs_get_device_desc(struct ufs_hba *hba) dev_info->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 | desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1]; + /* getting Specification Version in big endian format */ + dev_info->wspecversion = desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 | + desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1]; + model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME]; err = ufshcd_read_string_desc(hba, model_index, &dev_info->model, SD_ASCII_STD); @@ -6811,14 +6827,14 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) ufshcd_tune_pa_hibern8time(hba); } + ufshcd_vops_apply_dev_quirks(hba); + if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE) /* set 1ms timeout for PA_TACTIVATE */ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10); if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE) ufshcd_quirk_tune_host_pa_tactivate(hba); - - ufshcd_vops_apply_dev_quirks(hba); } static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) @@ -6991,6 +7007,8 @@ static int ufshcd_device_params_init(struct ufs_hba *hba) goto out; } + ufshcd_get_ref_clk_gating_wait(hba); + ufs_fixup_device_setup(hba); if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG, @@ -7014,8 +7032,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba) { int ret; - ufshcd_init_icc_levels(hba); - /* Add required well known logical units to scsi mid layer */ ret = ufshcd_scsi_add_wlus(hba); if (ret) @@ -7113,6 +7129,14 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async) } } + /* + * bActiveICCLevel is volatile for UFS device (as per latest v2.1 spec) + * and for removable UFS card as well, hence always set the parameter. + * Note: Error handler may issue the device reset hence resetting + * bActiveICCLevel as well so it is always safe to set this here. + */ + ufshcd_set_active_icc_lvl(hba); + /* set the state as operational after switching to desired gear */ hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; @@ -7241,6 +7265,11 @@ static int ufshcd_config_vreg(struct device *dev, name = vreg->name; if (regulator_count_voltages(reg) > 0) { + uA_load = on ? vreg->max_uA : 0; + ret = ufshcd_config_vreg_load(dev, vreg, uA_load); + if (ret) + goto out; + if (vreg->min_uV && vreg->max_uV) { min_uV = on ? vreg->min_uV : 0; ret = regulator_set_voltage(reg, min_uV, vreg->max_uV); @@ -7251,11 +7280,6 @@ static int ufshcd_config_vreg(struct device *dev, goto out; } } - - uA_load = on ? vreg->max_uA : 0; - ret = ufshcd_config_vreg_load(dev, vreg, uA_load); - if (ret) - goto out; } out: return ret; @@ -7395,16 +7419,9 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, if (list_empty(head)) goto out; - /* - * vendor specific setup_clocks ops may depend on clocks managed by - * this standard driver hence call the vendor specific setup_clocks - * before disabling the clocks managed here. - */ - if (!on) { - ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE); - if (ret) - return ret; - } + ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE); + if (ret) + return ret; list_for_each_entry(clki, head, list) { if (!IS_ERR_OR_NULL(clki->clk)) { @@ -7428,16 +7445,9 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, } } - /* - * vendor specific setup_clocks ops may depend on clocks managed by - * this standard driver hence call the vendor specific setup_clocks - * after enabling the clocks managed here. - */ - if (on) { - ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE); - if (ret) - return ret; - } + ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE); + if (ret) + return ret; out: if (ret) { @@ -7931,6 +7941,7 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) goto enable_gating; } + flush_work(&hba->eeh_work); ret = ufshcd_link_state_transition(hba, req_link_state, 1); if (ret) goto set_dev_active; @@ -8402,6 +8413,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) hba->mmio_base = mmio_base; hba->irq = irq; + hba->hba_enable_delay_us = 1000; err = ufshcd_hba_init(hba); if (err) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 2ae6c7c8528c..dd1ee277069a 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -55,6 +55,8 @@ #include <linux/clk.h> #include <linux/completion.h> #include <linux/regulator/consumer.h> +#include <linux/bitfield.h> +#include <linux/devfreq.h> #include "unipro.h" #include <asm/irq.h> @@ -326,6 +328,9 @@ struct ufs_hba_variant_ops { void (*dbg_register_dump)(struct ufs_hba *hba); int (*phy_initialization)(struct ufs_hba *); void (*device_reset)(struct ufs_hba *hba); + void (*config_scaling_param)(struct ufs_hba *hba, + struct devfreq_dev_profile *profile, + void *data); }; /* clock gating state */ @@ -403,15 +408,6 @@ struct ufs_clk_scaling { bool is_suspended; }; -/** - * struct ufs_init_prefetch - contains data that is pre-fetched once during - * initialization - * @icc_level: icc level which was read during initialization - */ -struct ufs_init_prefetch { - u32 icc_level; -}; - #define UFS_ERR_REG_HIST_LENGTH 8 /** * struct ufs_err_reg_hist - keeps history of errors @@ -469,6 +465,85 @@ struct ufs_stats { struct ufs_err_reg_hist task_abort; }; +enum ufshcd_quirks { + /* Interrupt aggregation support is broken */ + UFSHCD_QUIRK_BROKEN_INTR_AGGR = 1 << 0, + + /* + * delay before each dme command is required as the unipro + * layer has shown instabilities + */ + UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS = 1 << 1, + + /* + * If UFS host controller is having issue in processing LCC (Line + * Control Command) coming from device then enable this quirk. + * When this quirk is enabled, host controller driver should disable + * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE + * attribute of device to 0). + */ + UFSHCD_QUIRK_BROKEN_LCC = 1 << 2, + + /* + * The attribute PA_RXHSUNTERMCAP specifies whether or not the + * inbound Link supports unterminated line in HS mode. Setting this + * attribute to 1 fixes moving to HS gear. + */ + UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP = 1 << 3, + + /* + * This quirk needs to be enabled if the host controller only allows + * accessing the peer dme attributes in AUTO mode (FAST AUTO or + * SLOW AUTO). + */ + UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE = 1 << 4, + + /* + * This quirk needs to be enabled if the host controller doesn't + * advertise the correct version in UFS_VER register. If this quirk + * is enabled, standard UFS host driver will call the vendor specific + * ops (get_ufs_hci_version) to get the correct version. + */ + UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION = 1 << 5, +}; + +enum ufshcd_caps { + /* Allow dynamic clk gating */ + UFSHCD_CAP_CLK_GATING = 1 << 0, + + /* Allow hiberb8 with clk gating */ + UFSHCD_CAP_HIBERN8_WITH_CLK_GATING = 1 << 1, + + /* Allow dynamic clk scaling */ + UFSHCD_CAP_CLK_SCALING = 1 << 2, + + /* Allow auto bkops to enabled during runtime suspend */ + UFSHCD_CAP_AUTO_BKOPS_SUSPEND = 1 << 3, + + /* + * This capability allows host controller driver to use the UFS HCI's + * interrupt aggregation capability. + * CAUTION: Enabling this might reduce overall UFS throughput. + */ + UFSHCD_CAP_INTR_AGGR = 1 << 4, + + /* + * This capability allows the device auto-bkops to be always enabled + * except during suspend (both runtime and suspend). + * Enabling this capability means that device will always be allowed + * to do background operation when it's active but it might degrade + * the performance of ongoing read/write operations. + */ + UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND = 1 << 5, + + /* + * This capability allows host controller driver to automatically + * enable runtime power management by itself instead of waiting + * for userspace to control the power management. + */ + UFSHCD_CAP_RPM_AUTOSUSPEND = 1 << 6, +}; + /** * struct ufs_hba - per adapter private structure * @mmio_base: UFSHCI base register address @@ -501,7 +576,6 @@ struct ufs_stats { * @intr_mask: Interrupt Mask Bits * @ee_ctrl_mask: Exception event control mask * @is_powered: flag to check if HBA is powered - * @init_prefetch_data: data pre-fetched during initialization * @eh_work: Worker to handle UFS errors that require s/w attention * @eeh_work: Worker to handle exception events * @errors: HBA errors @@ -572,68 +646,6 @@ struct ufs_hba { bool is_irq_enabled; enum ufs_ref_clk_freq dev_ref_clk_freq; - /* Interrupt aggregation support is broken */ - #define UFSHCD_QUIRK_BROKEN_INTR_AGGR 0x1 - - /* - * delay before each dme command is required as the unipro - * layer has shown instabilities - */ - #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS 0x2 - - /* - * If UFS host controller is having issue in processing LCC (Line - * Control Command) coming from device then enable this quirk. - * When this quirk is enabled, host controller driver should disable - * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE - * attribute of device to 0). - */ - #define UFSHCD_QUIRK_BROKEN_LCC 0x4 - - /* - * The attribute PA_RXHSUNTERMCAP specifies whether or not the - * inbound Link supports unterminated line in HS mode. Setting this - * attribute to 1 fixes moving to HS gear. - */ - #define UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP 0x8 - - /* - * This quirk needs to be enabled if the host contoller only allows - * accessing the peer dme attributes in AUTO mode (FAST AUTO or - * SLOW AUTO). - */ - #define UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE 0x10 - - /* - * This quirk needs to be enabled if the host contoller doesn't - * advertise the correct version in UFS_VER register. If this quirk - * is enabled, standard UFS host driver will call the vendor specific - * ops (get_ufs_hci_version) to get the correct version. - */ - #define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION 0x20 - - /* - * This quirk needs to be enabled if the host contoller regards - * resolution of the values of PRDTO and PRDTL in UTRD as byte. - */ - #define UFSHCD_QUIRK_PRDT_BYTE_GRAN 0x80 - - /* - * Clear handling for transfer/task request list is just opposite. - */ - #define UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR 0x100 - - /* - * This quirk needs to be enabled if host controller doesn't allow - * that the interrupt aggregation timer and counter are reset by s/w. - */ - #define UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR 0x200 - - /* - * This quirks needs to be enabled if host controller cannot be - * enabled via HCE register. - */ - #define UFSHCI_QUIRK_BROKEN_HCE 0x400 unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ @@ -650,8 +662,8 @@ struct ufs_hba { u32 eh_flags; u32 intr_mask; u16 ee_ctrl_mask; + u16 hba_enable_delay_us; bool is_powered; - struct ufs_init_prefetch init_prefetch_data; /* Work Queues */ struct work_struct eh_work; @@ -688,34 +700,6 @@ struct ufs_hba { struct ufs_clk_gating clk_gating; /* Control to enable/disable host capabilities */ u32 caps; - /* Allow dynamic clk gating */ -#define UFSHCD_CAP_CLK_GATING (1 << 0) - /* Allow hiberb8 with clk gating */ -#define UFSHCD_CAP_HIBERN8_WITH_CLK_GATING (1 << 1) - /* Allow dynamic clk scaling */ -#define UFSHCD_CAP_CLK_SCALING (1 << 2) - /* Allow auto bkops to enabled during runtime suspend */ -#define UFSHCD_CAP_AUTO_BKOPS_SUSPEND (1 << 3) - /* - * This capability allows host controller driver to use the UFS HCI's - * interrupt aggregation capability. - * CAUTION: Enabling this might reduce overall UFS throughput. - */ -#define UFSHCD_CAP_INTR_AGGR (1 << 4) - /* - * This capability allows the device auto-bkops to be always enabled - * except during suspend (both runtime and suspend). - * Enabling this capability means that device will always be allowed - * to do background operation when it's active but it might degrade - * the performance of ongoing read/write operations. - */ -#define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 5) - /* - * This capability allows host controller driver to automatically - * enable runtime power management by itself instead of waiting - * for userspace to control the power management. - */ -#define UFSHCD_CAP_RPM_AUTOSUSPEND (1 << 6) struct devfreq *devfreq; struct ufs_clk_scaling clk_scaling; @@ -773,6 +757,11 @@ static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba) return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT); } +static inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba) +{ + return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit) ? true : false; +} + #define ufshcd_writel(hba, val, reg) \ writel((val), (hba)->mmio_base + (reg)) #define ufshcd_readl(hba, reg) \ @@ -802,6 +791,7 @@ int ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int); int ufshcd_make_hba_operational(struct ufs_hba *hba); void ufshcd_remove(struct ufs_hba *); int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); +void ufshcd_delay_us(unsigned long us, unsigned long tolerance); int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask, u32 val, unsigned long interval_us, unsigned long timeout_ms, bool can_sleep); @@ -908,6 +898,11 @@ static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info) pwr_info->pwr_tx == FASTAUTO_MODE); } +static inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba) +{ + return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); +} + /* Expose Query-Request API */ int ufshcd_query_descriptor_retry(struct ufs_hba *hba, enum query_opcode opcode, @@ -1092,6 +1087,14 @@ static inline void ufshcd_vops_device_reset(struct ufs_hba *hba) } } +static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba, + struct devfreq_dev_profile + *profile, void *data) +{ + if (hba->vops && hba->vops->config_scaling_param) + hba->vops->config_scaling_param(hba, profile, data); +} + extern struct ufs_pm_lvl_states ufs_pm_lvl_states[]; /* diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h index 3dc4d8b76509..766d551df3fc 100644 --- a/drivers/scsi/ufs/unipro.h +++ b/drivers/scsi/ufs/unipro.h @@ -146,6 +146,12 @@ #define PA_SLEEPNOCONFIGTIME 0x15A2 #define PA_STALLNOCONFIGTIME 0x15A3 #define PA_SAVECONFIGTIME 0x15A4 +#define PA_TXHSADAPTTYPE 0x15D4 + +/* Adpat type for PA_TXHSADAPTTYPE attribute */ +#define PA_REFRESH_ADAPT 0x00 +#define PA_INITIAL_ADAPT 0x01 +#define PA_NO_ADAPT 0x03 #define PA_TACTIVATE_TIME_UNIT_US 10 #define PA_HIBERN8_TIME_UNIT_US 100 @@ -203,6 +209,7 @@ enum ufs_hs_gear_tag { UFS_HS_G1, /* HS Gear 1 (default for reset) */ UFS_HS_G2, /* HS Gear 2 */ UFS_HS_G3, /* HS Gear 3 */ + UFS_HS_G4, /* HS Gear 4 */ }; enum ufs_unipro_ver { diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index bfec84aacd90..0e0910c5b942 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -742,7 +742,6 @@ static struct scsi_host_template virtscsi_host_template = { .dma_boundary = UINT_MAX, .map_queues = virtscsi_map_queues, .track_queue_depth = 1, - .force_blk_mq = 1, }; #define virtscsi_config_get(vdev, fld) \ diff --git a/drivers/scsi/zorro_esp.c b/drivers/scsi/zorro_esp.c index bdd82e497d5f..c6727bcbc2e3 100644 --- a/drivers/scsi/zorro_esp.c +++ b/drivers/scsi/zorro_esp.c @@ -801,8 +801,7 @@ static int zorro_esp_probe(struct zorro_dev *z, /* additional setup required for Fastlane */ if (zep->zorro3 && ent->driver_data == ZORRO_BLZ1230II) { /* map full address space up to ESP base for DMA */ - zep->board_base = ioremap(board, - FASTLANE_ESP_ADDR-1); + zep->board_base = ioremap(board, FASTLANE_ESP_ADDR - 1); if (!zep->board_base) { pr_err("Cannot allocate board address space\n"); err = -ENOMEM; @@ -843,7 +842,7 @@ static int zorro_esp_probe(struct zorro_dev *z, * dma_registers size if adding any more */ esp->dma_regs = ioremap(dmaaddr, - sizeof(struct fastlane_dma_registers)); + sizeof(struct fastlane_dma_registers)); } else /* ZorroII address space remapped nocache by early startup */ esp->dma_regs = ZTWO_VADDR(dmaaddr); diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 09e55ea0bf5d..59379d662626 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -4301,30 +4301,37 @@ int iscsit_close_connection( if (!atomic_read(&sess->session_reinstatement) && atomic_read(&sess->session_fall_back_to_erl0)) { spin_unlock_bh(&sess->conn_lock); + complete_all(&sess->session_wait_comp); iscsit_close_session(sess); return 0; } else if (atomic_read(&sess->session_logout)) { pr_debug("Moving to TARG_SESS_STATE_FREE.\n"); sess->session_state = TARG_SESS_STATE_FREE; - spin_unlock_bh(&sess->conn_lock); - if (atomic_read(&sess->sleep_on_sess_wait_comp)) - complete(&sess->session_wait_comp); + if (atomic_read(&sess->session_close)) { + spin_unlock_bh(&sess->conn_lock); + complete_all(&sess->session_wait_comp); + iscsit_close_session(sess); + } else { + spin_unlock_bh(&sess->conn_lock); + } return 0; } else { pr_debug("Moving to TARG_SESS_STATE_FAILED.\n"); sess->session_state = TARG_SESS_STATE_FAILED; - if (!atomic_read(&sess->session_continuation)) { - spin_unlock_bh(&sess->conn_lock); + if (!atomic_read(&sess->session_continuation)) iscsit_start_time2retain_handler(sess); - } else - spin_unlock_bh(&sess->conn_lock); - if (atomic_read(&sess->sleep_on_sess_wait_comp)) - complete(&sess->session_wait_comp); + if (atomic_read(&sess->session_close)) { + spin_unlock_bh(&sess->conn_lock); + complete_all(&sess->session_wait_comp); + iscsit_close_session(sess); + } else { + spin_unlock_bh(&sess->conn_lock); + } return 0; } @@ -4368,8 +4375,7 @@ int iscsit_close_session(struct iscsi_session *sess) * restart the timer and exit. */ if (!in_interrupt()) { - if (iscsit_check_session_usage_count(sess) == 1) - iscsit_stop_session(sess, 1, 1); + iscsit_check_session_usage_count(sess); } else { if (iscsit_check_session_usage_count(sess) == 2) { atomic_set(&sess->session_logout, 0); @@ -4430,9 +4436,9 @@ static void iscsit_logout_post_handler_closesession( complete(&conn->conn_logout_comp); iscsit_dec_conn_usage_count(conn); + atomic_set(&sess->session_close, 1); iscsit_stop_session(sess, sleep, sleep); iscsit_dec_session_usage_count(sess); - iscsit_close_session(sess); } static void iscsit_logout_post_handler_samecid( @@ -4567,49 +4573,6 @@ void iscsit_fail_session(struct iscsi_session *sess) sess->session_state = TARG_SESS_STATE_FAILED; } -int iscsit_free_session(struct iscsi_session *sess) -{ - u16 conn_count = atomic_read(&sess->nconn); - struct iscsi_conn *conn, *conn_tmp = NULL; - int is_last; - - spin_lock_bh(&sess->conn_lock); - atomic_set(&sess->sleep_on_sess_wait_comp, 1); - - list_for_each_entry_safe(conn, conn_tmp, &sess->sess_conn_list, - conn_list) { - if (conn_count == 0) - break; - - if (list_is_last(&conn->conn_list, &sess->sess_conn_list)) { - is_last = 1; - } else { - iscsit_inc_conn_usage_count(conn_tmp); - is_last = 0; - } - iscsit_inc_conn_usage_count(conn); - - spin_unlock_bh(&sess->conn_lock); - iscsit_cause_connection_reinstatement(conn, 1); - spin_lock_bh(&sess->conn_lock); - - iscsit_dec_conn_usage_count(conn); - if (is_last == 0) - iscsit_dec_conn_usage_count(conn_tmp); - - conn_count--; - } - - if (atomic_read(&sess->nconn)) { - spin_unlock_bh(&sess->conn_lock); - wait_for_completion(&sess->session_wait_comp); - } else - spin_unlock_bh(&sess->conn_lock); - - iscsit_close_session(sess); - return 0; -} - void iscsit_stop_session( struct iscsi_session *sess, int session_sleep, @@ -4620,8 +4583,6 @@ void iscsit_stop_session( int is_last; spin_lock_bh(&sess->conn_lock); - if (session_sleep) - atomic_set(&sess->sleep_on_sess_wait_comp, 1); if (connection_sleep) { list_for_each_entry_safe(conn, conn_tmp, &sess->sess_conn_list, @@ -4679,12 +4640,15 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) spin_lock(&sess->conn_lock); if (atomic_read(&sess->session_fall_back_to_erl0) || atomic_read(&sess->session_logout) || + atomic_read(&sess->session_close) || (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) { spin_unlock(&sess->conn_lock); continue; } + iscsit_inc_session_usage_count(sess); atomic_set(&sess->session_reinstatement, 1); atomic_set(&sess->session_fall_back_to_erl0, 1); + atomic_set(&sess->session_close, 1); spin_unlock(&sess->conn_lock); list_move_tail(&se_sess->sess_list, &free_list); @@ -4694,7 +4658,9 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) { sess = (struct iscsi_session *)se_sess->fabric_sess_ptr; - iscsit_free_session(sess); + list_del_init(&se_sess->sess_list); + iscsit_stop_session(sess, 1, 1); + iscsit_dec_session_usage_count(sess); session_count++; } diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h index c95f56a3ce31..7409ce2a6607 100644 --- a/drivers/target/iscsi/iscsi_target.h +++ b/drivers/target/iscsi/iscsi_target.h @@ -43,7 +43,6 @@ extern int iscsi_target_rx_thread(void *); extern int iscsit_close_connection(struct iscsi_conn *); extern int iscsit_close_session(struct iscsi_session *); extern void iscsit_fail_session(struct iscsi_session *); -extern int iscsit_free_session(struct iscsi_session *); extern void iscsit_stop_session(struct iscsi_session *, int, int); extern int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *, int); diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 42b369fc415e..0fa1d57b26fa 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -1476,20 +1476,23 @@ static void lio_tpg_close_session(struct se_session *se_sess) spin_lock(&sess->conn_lock); if (atomic_read(&sess->session_fall_back_to_erl0) || atomic_read(&sess->session_logout) || + atomic_read(&sess->session_close) || (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) { spin_unlock(&sess->conn_lock); spin_unlock_bh(&se_tpg->session_lock); return; } + iscsit_inc_session_usage_count(sess); atomic_set(&sess->session_reinstatement, 1); atomic_set(&sess->session_fall_back_to_erl0, 1); + atomic_set(&sess->session_close, 1); spin_unlock(&sess->conn_lock); iscsit_stop_time2retain_timer(sess); spin_unlock_bh(&se_tpg->session_lock); iscsit_stop_session(sess, 1, 1); - iscsit_close_session(sess); + iscsit_dec_session_usage_count(sess); } static u32 lio_tpg_get_inst_index(struct se_portal_group *se_tpg) diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index f53330813207..731ee67fe914 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -156,6 +156,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) spin_lock(&sess_p->conn_lock); if (atomic_read(&sess_p->session_fall_back_to_erl0) || atomic_read(&sess_p->session_logout) || + atomic_read(&sess_p->session_close) || (sess_p->time2retain_timer_flags & ISCSI_TF_EXPIRED)) { spin_unlock(&sess_p->conn_lock); continue; @@ -166,6 +167,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) (sess_p->sess_ops->SessionType == sessiontype))) { atomic_set(&sess_p->session_reinstatement, 1); atomic_set(&sess_p->session_fall_back_to_erl0, 1); + atomic_set(&sess_p->session_close, 1); spin_unlock(&sess_p->conn_lock); iscsit_inc_session_usage_count(sess_p); iscsit_stop_time2retain_timer(sess_p); @@ -190,7 +192,6 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) if (sess->session_state == TARG_SESS_STATE_FAILED) { spin_unlock_bh(&sess->conn_lock); iscsit_dec_session_usage_count(sess); - iscsit_close_session(sess); return 0; } spin_unlock_bh(&sess->conn_lock); @@ -198,7 +199,6 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) iscsit_stop_session(sess, 1, 1); iscsit_dec_session_usage_count(sess); - iscsit_close_session(sess); return 0; } @@ -486,6 +486,7 @@ static int iscsi_login_non_zero_tsih_s2( sess_p = (struct iscsi_session *)se_sess->fabric_sess_ptr; if (atomic_read(&sess_p->session_fall_back_to_erl0) || atomic_read(&sess_p->session_logout) || + atomic_read(&sess_p->session_close) || (sess_p->time2retain_timer_flags & ISCSI_TF_EXPIRED)) continue; if (!memcmp(sess_p->isid, pdu->isid, 6) && diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index e6e175597860..ff82b21fdcce 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -684,7 +684,9 @@ static ssize_t emulate_ua_intlck_ctrl_store(struct config_item *item, if (ret < 0) return ret; - if (val != 0 && val != 1 && val != 2) { + if (val != TARGET_UA_INTLCK_CTRL_CLEAR + && val != TARGET_UA_INTLCK_CTRL_NO_CLEAR + && val != TARGET_UA_INTLCK_CTRL_ESTABLISH_UA) { pr_err("Illegal value %d\n", val); return -EINVAL; } diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 2d19f0e332b0..4cee1138284b 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -767,7 +767,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.emulate_fua_write = 1; dev->dev_attrib.emulate_fua_read = 1; dev->dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE; - dev->dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL; + dev->dev_attrib.emulate_ua_intlck_ctrl = TARGET_UA_INTLCK_CTRL_CLEAR; dev->dev_attrib.emulate_tas = DA_EMULATE_TAS; dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU; dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; @@ -829,7 +829,7 @@ bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, attrib->unmap_granularity = q->limits.discard_granularity / block_size; attrib->unmap_granularity_alignment = q->limits.discard_alignment / block_size; - attrib->unmap_zeroes_data = (q->limits.max_write_zeroes_sectors); + attrib->unmap_zeroes_data = !!(q->limits.max_write_zeroes_sectors); return true; } EXPORT_SYMBOL(target_configure_unmap_from_queue); diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 6d4cf2643c0a..ca5579ebc81d 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -847,8 +847,17 @@ static int spc_modesense_control(struct se_cmd *cmd, u8 pc, u8 *p) * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless * to the number of commands completed with one of those status codes. */ - p[4] = (dev->dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 : - (dev->dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00; + switch (dev->dev_attrib.emulate_ua_intlck_ctrl) { + case TARGET_UA_INTLCK_CTRL_ESTABLISH_UA: + p[4] = 0x30; + break; + case TARGET_UA_INTLCK_CTRL_NO_CLEAR: + p[4] = 0x20; + break; + default: /* TARGET_UA_INTLCK_CTRL_CLEAR */ + p[4] = 0x00; + break; + } /* * From spc4r17, section 7.4.6 Control mode Page * diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index feeba3966617..afbd492c76a9 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -78,7 +78,7 @@ static int target_check_cdb_and_preempt(struct list_head *list, } static bool __target_check_io_state(struct se_cmd *se_cmd, - struct se_session *tmr_sess, int tas) + struct se_session *tmr_sess, bool tas) { struct se_session *sess = se_cmd->se_sess; @@ -251,7 +251,7 @@ static void core_tmr_drain_state_list( struct se_device *dev, struct se_cmd *prout_cmd, struct se_session *tmr_sess, - int tas, + bool tas, struct list_head *preempt_and_abort_list) { LIST_HEAD(drain_task_list); @@ -334,7 +334,7 @@ int core_tmr_lun_reset( struct se_node_acl *tmr_nacl = NULL; struct se_portal_group *tmr_tpg = NULL; struct se_session *tmr_sess = NULL; - int tas; + bool tas; /* * TASK_ABORTED status bit, this is configurable via ConfigFS * struct se_device attributes. spc4r17 section 7.4.6 Control mode page diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 0ae9e60fc4d5..594b724bbf79 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1898,7 +1898,8 @@ void transport_generic_request_failure(struct se_cmd *cmd, * See spc4r17, section 7.4.6 Control Mode Page, Table 349 */ if (cmd->se_sess && - cmd->se_dev->dev_attrib.emulate_ua_intlck_ctrl == 2) { + cmd->se_dev->dev_attrib.emulate_ua_intlck_ctrl + == TARGET_UA_INTLCK_CTRL_ESTABLISH_UA) { target_ua_allocate_lun(cmd->se_sess->se_node_acl, cmd->orig_fe_lun, 0x2C, ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index 151b56002da5..4276690fb6cb 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c @@ -199,6 +199,8 @@ bool core_scsi3_ua_for_check_condition(struct se_cmd *cmd, u8 *key, u8 *asc, struct se_node_acl *nacl; struct se_ua *ua = NULL, *ua_p; int head = 1; + bool dev_ua_intlck_clear = (dev->dev_attrib.emulate_ua_intlck_ctrl + == TARGET_UA_INTLCK_CTRL_CLEAR); if (WARN_ON_ONCE(!sess)) return false; @@ -229,7 +231,7 @@ bool core_scsi3_ua_for_check_condition(struct se_cmd *cmd, u8 *key, u8 *asc, * highest priority UNIT_ATTENTION and ASC/ASCQ without * clearing it. */ - if (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) { + if (!dev_ua_intlck_clear) { *asc = ua->ua_asc; *ascq = ua->ua_ascq; break; @@ -254,8 +256,8 @@ bool core_scsi3_ua_for_check_condition(struct se_cmd *cmd, u8 *key, u8 *asc, " INTLCK_CTRL: %d, mapped LUN: %llu, got CDB: 0x%02x" " reported ASC: 0x%02x, ASCQ: 0x%02x\n", nacl->se_tpg->se_tpg_tfo->fabric_name, - (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" : - "Releasing", dev->dev_attrib.emulate_ua_intlck_ctrl, + dev_ua_intlck_clear ? "Releasing" : "Reporting", + dev->dev_attrib.emulate_ua_intlck_ctrl, cmd->orig_fe_lun, cmd->t_task_cdb[0], *asc, *ascq); return head == 0; diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 7c96c4665178..950d2a85f098 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -216,6 +216,7 @@ #include <linux/freezer.h> #include <linux/module.h> #include <linux/uaccess.h> +#include <asm/unaligned.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h index e5e3a2553aaa..bdeb1e233fc9 100644 --- a/drivers/usb/gadget/function/storage_common.h +++ b/drivers/usb/gadget/function/storage_common.h @@ -172,11 +172,6 @@ enum data_direction { DATA_DIR_NONE }; -static inline u32 get_unaligned_be24(u8 *buf) -{ - return 0xffffff & (u32) get_unaligned_be32(buf - 1); -} - static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev) { return container_of(dev, struct fsg_lun, dev); diff --git a/include/linux/unaligned/be_byteshift.h b/include/linux/unaligned/be_byteshift.h index 8bdb8fa01bd4..c43ff5918c8a 100644 --- a/include/linux/unaligned/be_byteshift.h +++ b/include/linux/unaligned/be_byteshift.h @@ -40,17 +40,17 @@ static inline void __put_unaligned_be64(u64 val, u8 *p) static inline u16 get_unaligned_be16(const void *p) { - return __get_unaligned_be16((const u8 *)p); + return __get_unaligned_be16(p); } static inline u32 get_unaligned_be32(const void *p) { - return __get_unaligned_be32((const u8 *)p); + return __get_unaligned_be32(p); } static inline u64 get_unaligned_be64(const void *p) { - return __get_unaligned_be64((const u8 *)p); + return __get_unaligned_be64(p); } static inline void put_unaligned_be16(u16 val, void *p) diff --git a/include/linux/unaligned/generic.h b/include/linux/unaligned/generic.h index 57d3114656e5..303289492859 100644 --- a/include/linux/unaligned/generic.h +++ b/include/linux/unaligned/generic.h @@ -2,6 +2,8 @@ #ifndef _LINUX_UNALIGNED_GENERIC_H #define _LINUX_UNALIGNED_GENERIC_H +#include <linux/types.h> + /* * Cause a link-time error if we try an unaligned access other than * 1,2,4 or 8 bytes long @@ -66,4 +68,48 @@ extern void __bad_unaligned_access_size(void); } \ (void)0; }) +static inline u32 __get_unaligned_be24(const u8 *p) +{ + return p[0] << 16 | p[1] << 8 | p[2]; +} + +static inline u32 get_unaligned_be24(const void *p) +{ + return __get_unaligned_be24(p); +} + +static inline u32 __get_unaligned_le24(const u8 *p) +{ + return p[0] | p[1] << 8 | p[2] << 16; +} + +static inline u32 get_unaligned_le24(const void *p) +{ + return __get_unaligned_le24(p); +} + +static inline void __put_unaligned_be24(const u32 val, u8 *p) +{ + *p++ = val >> 16; + *p++ = val >> 8; + *p++ = val; +} + +static inline void put_unaligned_be24(const u32 val, void *p) +{ + __put_unaligned_be24(val, p); +} + +static inline void __put_unaligned_le24(const u32 val, u8 *p) +{ + *p++ = val; + *p++ = val >> 8; + *p++ = val >> 16; +} + +static inline void put_unaligned_le24(const u32 val, void *p) +{ + __put_unaligned_le24(val, p); +} + #endif /* _LINUX_UNALIGNED_GENERIC_H */ diff --git a/include/linux/unaligned/le_byteshift.h b/include/linux/unaligned/le_byteshift.h index 1628b75866f0..2248dcb0df76 100644 --- a/include/linux/unaligned/le_byteshift.h +++ b/include/linux/unaligned/le_byteshift.h @@ -40,17 +40,17 @@ static inline void __put_unaligned_le64(u64 val, u8 *p) static inline u16 get_unaligned_le16(const void *p) { - return __get_unaligned_le16((const u8 *)p); + return __get_unaligned_le16(p); } static inline u32 get_unaligned_le32(const void *p) { - return __get_unaligned_le32((const u8 *)p); + return __get_unaligned_le32(p); } static inline u64 get_unaligned_le64(const void *p) { - return __get_unaligned_le64((const u8 *)p); + return __get_unaligned_le64(p); } static inline void put_unaligned_le16(u16 val, void *p) diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 92b11c7e0b4f..5225a23f2d0e 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -60,6 +60,7 @@ enum iscsi_uevent_e { ISCSI_UEVENT_LOGOUT_FLASHNODE_SID = UEVENT_BASE + 30, ISCSI_UEVENT_SET_CHAP = UEVENT_BASE + 31, ISCSI_UEVENT_GET_HOST_STATS = UEVENT_BASE + 32, + ISCSI_UEVENT_DESTROY_SESSION_ASYNC = UEVENT_BASE + 33, /* up events */ ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, @@ -311,7 +312,7 @@ enum iscsi_param_type { struct iscsi_param_info { uint32_t len; /* Actual length of the param value */ uint16_t param; /* iscsi param */ - uint8_t value[0]; /* length sized value follows */ + uint8_t value[]; /* length sized value follows */ } __packed; struct iscsi_iface_param_info { @@ -320,7 +321,7 @@ struct iscsi_iface_param_info { uint16_t param; /* iscsi param value */ uint8_t iface_type; /* IPv4 or IPv6 */ uint8_t param_type; /* iscsi_param_type */ - uint8_t value[0]; /* length sized value follows */ + uint8_t value[]; /* length sized value follows */ } __packed; /* @@ -697,7 +698,7 @@ enum iscsi_flashnode_param { struct iscsi_flashnode_param_info { uint32_t len; /* Actual length of the param */ uint16_t param; /* iscsi param value */ - uint8_t value[0]; /* length sized value follows */ + uint8_t value[]; /* length sized value follows */ } __packed; enum iscsi_discovery_parent_type { @@ -815,7 +816,7 @@ struct iscsi_stats { * up to ISCSI_STATS_CUSTOM_MAX */ uint32_t custom_length; - struct iscsi_stats_custom custom[0] + struct iscsi_stats_custom custom[] __attribute__ ((aligned (sizeof(uint64_t)))); }; @@ -946,7 +947,7 @@ struct iscsi_offload_host_stats { * up to ISCSI_HOST_STATS_CUSTOM_MAX */ uint32_t custom_length; - struct iscsi_host_stats_custom custom[0] + struct iscsi_host_stats_custom custom[] __aligned(sizeof(uint64_t)); }; diff --git a/include/scsi/scsi_bsg_iscsi.h b/include/scsi/scsi_bsg_iscsi.h index fa0c820a1663..6b8128005af8 100644 --- a/include/scsi/scsi_bsg_iscsi.h +++ b/include/scsi/scsi_bsg_iscsi.h @@ -52,7 +52,7 @@ struct iscsi_bsg_host_vendor { uint64_t vendor_id; /* start of vendor command area */ - uint32_t vendor_cmd[0]; + uint32_t vendor_cmd[]; }; /* Response: diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index a2849bb9cd19..80ac89e47b47 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -159,7 +159,6 @@ static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) return *(struct scsi_driver **)cmd->request->rq_disk->private_data; } -extern void scsi_put_command(struct scsi_cmnd *); extern void scsi_finish_command(struct scsi_cmnd *cmd); extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index f8312a3e5b42..c3cba2aaf934 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -110,7 +110,6 @@ struct scsi_device { atomic_t device_blocked; /* Device returned QUEUE_FULL. */ spinlock_t list_lock; - struct list_head cmd_list; /* queue of in use SCSI Command structures */ struct list_head starved_entry; unsigned short queue_depth; /* How deep of a queue we want */ unsigned short max_queue_depth; /* max queue depth */ @@ -204,6 +203,9 @@ struct scsi_device { unsigned unmap_limit_for_ws:1; /* Use the UNMAP limit for WRITE SAME */ unsigned rpm_autosuspend:1; /* Enable runtime autosuspend at device * creation time */ + + bool offline_already; /* Device offline message logged */ + atomic_t disk_events_disable_depth; /* disable depth for disk events */ DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ @@ -231,7 +233,7 @@ struct scsi_device { struct mutex state_mutex; enum scsi_device_state sdev_state; struct task_struct *quiesced_by; - unsigned long sdev_data[0]; + unsigned long sdev_data[]; } __attribute__((aligned(sizeof(unsigned long)))); #define to_scsi_device(d) \ @@ -315,7 +317,7 @@ struct scsi_target { char scsi_level; enum scsi_target_state state; void *hostdata; /* available to low-level driver */ - unsigned long starget_data[0]; /* for the transport */ + unsigned long starget_data[]; /* for the transport */ /* starget_data must be the last element!!!! */ } __attribute__((aligned(sizeof(unsigned long)))); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index f577647bf5f2..822e8cda8d9b 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -62,6 +62,9 @@ struct scsi_host_template { void __user *arg); #endif + int (*init_cmd_priv)(struct Scsi_Host *shost, struct scsi_cmnd *cmd); + int (*exit_cmd_priv)(struct Scsi_Host *shost, struct scsi_cmnd *cmd); + /* * The queuecommand function is used to queue up a scsi * command block to the LLDD. When the driver finished @@ -426,9 +429,6 @@ struct scsi_host_template { /* True if the controller does not support WRITE SAME */ unsigned no_write_same:1; - /* True if the low-level driver supports blk-mq only */ - unsigned force_blk_mq:1; - /* * Countdown for host blocking with no commands outstanding. */ @@ -627,8 +627,6 @@ struct Scsi_Host { /* The controller does not support WRITE SAME */ unsigned no_write_same:1; - unsigned use_cmd_list:1; - /* Host responded with short (<36 bytes) INQUIRY result */ unsigned short_inquiry:1; @@ -685,7 +683,7 @@ struct Scsi_Host { * and also because some compilers (m68k) don't automatically force * alignment to a long boundary. */ - unsigned long hostdata[0] /* Used for storage of host specific stuff */ + unsigned long hostdata[] /* Used for storage of host specific stuff */ __attribute__ ((aligned (sizeof(unsigned long)))); }; @@ -735,6 +733,8 @@ extern int scsi_host_busy(struct Scsi_Host *shost); extern void scsi_host_put(struct Scsi_Host *t); extern struct Scsi_Host *scsi_host_lookup(unsigned short); extern const char *scsi_host_state_name(enum scsi_host_state); +extern void scsi_host_complete_all_commands(struct Scsi_Host *shost, + int status); static inline int __must_check scsi_add_host(struct Scsi_Host *host, struct device *dev) @@ -759,6 +759,11 @@ static inline int scsi_host_scan_allowed(struct Scsi_Host *shost) extern void scsi_unblock_requests(struct Scsi_Host *); extern void scsi_block_requests(struct Scsi_Host *); +extern int scsi_host_block(struct Scsi_Host *shost); +extern int scsi_host_unblock(struct Scsi_Host *shost, int new_state); + +void scsi_host_busy_iter(struct Scsi_Host *, + bool (*fn)(struct scsi_cmnd *, void *, bool), void *priv); struct class_container; diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h index 4fe69d863b5d..b465799f4d2d 100644 --- a/include/scsi/scsi_ioctl.h +++ b/include/scsi/scsi_ioctl.h @@ -27,7 +27,7 @@ struct scsi_device; typedef struct scsi_ioctl_command { unsigned int inlen; unsigned int outlen; - unsigned char data[0]; + unsigned char data[]; } Scsi_Ioctl_Command; typedef struct scsi_idlun { diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 325ae731d9ad..bdcb6d69d154 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -188,8 +188,16 @@ extern void iscsi_ping_comp_event(uint32_t host_no, uint32_t status, uint32_t pid, uint32_t data_size, uint8_t *data); +/* iscsi class connection state */ +enum iscsi_connection_state { + ISCSI_CONN_UP = 0, + ISCSI_CONN_DOWN, + ISCSI_CONN_FAILED, +}; + struct iscsi_cls_conn { struct list_head conn_list; /* item in connlist */ + struct list_head conn_list_err; /* item in connlist_err */ void *dd_data; /* LLD private data */ struct iscsi_transport *transport; uint32_t cid; /* connection id */ @@ -197,6 +205,7 @@ struct iscsi_cls_conn { struct iscsi_endpoint *ep; struct device dev; /* sysfs transport/container device */ + enum iscsi_connection_state state; }; #define iscsi_dev_to_conn(_dev) \ @@ -225,6 +234,7 @@ struct iscsi_cls_session { struct work_struct unblock_work; struct work_struct scan_work; struct work_struct unbind_work; + struct work_struct destroy_work; /* recovery fields */ int recovery_tmo; diff --git a/include/scsi/sg.h b/include/scsi/sg.h index 29c7ad04d2e2..7327e12f3373 100644 --- a/include/scsi/sg.h +++ b/include/scsi/sg.h @@ -24,7 +24,7 @@ * http://sg.danny.cz/sg [alternatively check the MAINTAINERS file] * The documentation for the sg version 3 driver can be found at: * http://sg.danny.cz/sg/p/sg_v3_ho.html - * Also see: <kernel_source>/Documentation/scsi/scsi-generic.txt + * Also see: <kernel_source>/Documentation/scsi/scsi-generic.rst * * For utility and test programs see: http://sg.danny.cz/sg/sg3_utils.html */ diff --git a/include/scsi/srp.h b/include/scsi/srp.h index 9220758d5087..177d8026e96f 100644 --- a/include/scsi/srp.h +++ b/include/scsi/srp.h @@ -109,7 +109,7 @@ struct srp_direct_buf { struct srp_indirect_buf { struct srp_direct_buf table_desc; __be32 len; - struct srp_direct_buf desc_list[0]; + struct srp_direct_buf desc_list[]; } __attribute__((packed)); /* Immediate data buffer descriptor as defined in SRP2. */ @@ -244,7 +244,7 @@ struct srp_cmd { u8 reserved4; u8 add_cdb_len; u8 cdb[16]; - u8 add_data[0]; + u8 add_data[]; }; enum { @@ -274,7 +274,7 @@ struct srp_rsp { __be32 data_in_res_cnt; __be32 sense_data_len; __be32 resp_data_len; - u8 data[0]; + u8 data[]; } __attribute__((packed)); struct srp_cred_req { @@ -306,7 +306,7 @@ struct srp_aer_req { struct scsi_lun lun; __be32 sense_data_len; u32 reserved3; - u8 sense_data[0]; + u8 sense_data[]; } __attribute__((packed)); struct srp_aer_rsp { diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index a49d37140a64..591cd9e4692c 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -676,7 +676,7 @@ struct iscsi_session { atomic_t session_logout; atomic_t session_reinstatement; atomic_t session_stop_active; - atomic_t sleep_on_sess_wait_comp; + atomic_t session_close; /* connection list */ struct list_head sess_conn_list; struct list_head cr_active_list; diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 51b6f50eabee..1b752d8ea529 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -116,10 +116,4 @@ static inline bool target_dev_configured(struct se_device *se_dev) return !!(se_dev->dev_flags & DF_CONFIGURED); } -/* Only use get_unaligned_be24() if reading p - 1 is allowed. */ -static inline uint32_t get_unaligned_be24(const uint8_t *const p) -{ - return get_unaligned_be32(p - 1) & 0xffffffU; -} - #endif /* TARGET_CORE_BACKEND_H */ diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 1728e883b7b2..6d4a694f6ea7 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -74,8 +74,6 @@ #define DA_EMULATE_MODEL_ALIAS 0 /* Emulation for WriteCache and SYNCHRONIZE_CACHE */ #define DA_EMULATE_WRITE_CACHE 0 -/* Emulation for UNIT ATTENTION Interlock Control */ -#define DA_EMULATE_UA_INTLLCK_CTRL 0 /* Emulation for TASK_ABORTED status (TAS) by default */ #define DA_EMULATE_TAS 1 /* Emulation for Thin Provisioning UNMAP using block/blk-lib.c:blkdev_issue_discard() */ @@ -433,6 +431,13 @@ enum target_prot_type { TARGET_DIF_TYPE3_PROT, }; +/* Emulation for UNIT ATTENTION Interlock Control */ +enum target_ua_intlck_ctrl { + TARGET_UA_INTLCK_CTRL_CLEAR = 0, + TARGET_UA_INTLCK_CTRL_NO_CLEAR = 1, + TARGET_UA_INTLCK_CTRL_ESTABLISH_UA = 2, +}; + enum target_core_dif_check { TARGET_DIF_CHECK_GUARD = 0x1 << 0, TARGET_DIF_CHECK_APPTAG = 0x1 << 1, @@ -663,26 +668,26 @@ struct se_dev_entry { }; struct se_dev_attrib { - int emulate_model_alias; - int emulate_dpo; - int emulate_fua_write; - int emulate_fua_read; - int emulate_write_cache; - int emulate_ua_intlck_ctrl; - int emulate_tas; - int emulate_tpu; - int emulate_tpws; - int emulate_caw; - int emulate_3pc; - int emulate_pr; + bool emulate_model_alias; + bool emulate_dpo; /* deprecated */ + bool emulate_fua_write; + bool emulate_fua_read; /* deprecated */ + bool emulate_write_cache; + enum target_ua_intlck_ctrl emulate_ua_intlck_ctrl; + bool emulate_tas; + bool emulate_tpu; + bool emulate_tpws; + bool emulate_caw; + bool emulate_3pc; + bool emulate_pr; enum target_prot_type pi_prot_type; enum target_prot_type hw_pi_prot_type; - int pi_prot_verify; - int enforce_pr_isids; - int force_pr_aptpl; - int is_nonrot; - int emulate_rest_reord; - int unmap_zeroes_data; + bool pi_prot_verify; + bool enforce_pr_isids; + bool force_pr_aptpl; + bool is_nonrot; + bool emulate_rest_reord; + bool unmap_zeroes_data; u32 hw_block_size; u32 block_size; u32 hw_max_sectors; diff --git a/include/trace/events/qla.h b/include/trace/events/qla.h new file mode 100644 index 000000000000..b71f680968eb --- /dev/null +++ b/include/trace/events/qla.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#if !defined(_TRACE_QLA_H_) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_QLA_H_ + +#include <linux/tracepoint.h> + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM qla + +#define QLA_MSG_MAX 256 + +DECLARE_EVENT_CLASS(qla_log_event, + TP_PROTO(const char *buf, + struct va_format *vaf), + + TP_ARGS(buf, vaf), + + TP_STRUCT__entry( + __string(buf, buf) + __dynamic_array(char, msg, QLA_MSG_MAX) + ), + TP_fast_assign( + __assign_str(buf, buf); + vsnprintf(__get_str(msg), QLA_MSG_MAX, vaf->fmt, *vaf->va); + ), + + TP_printk("%s %s", __get_str(buf), __get_str(msg)) +); + +DEFINE_EVENT(qla_log_event, ql_dbg_log, + TP_PROTO(const char *buf, struct va_format *vaf), + TP_ARGS(buf, vaf) +); + +#endif /* _TRACE_QLA_H */ + +#define TRACE_INCLUDE_FILE qla + +#include <trace/define_trace.h> diff --git a/include/trace/events/target.h b/include/trace/events/target.h index 914a872dd343..77408edd29d2 100644 --- a/include/trace/events/target.h +++ b/include/trace/events/target.h @@ -137,6 +137,7 @@ TRACE_EVENT(target_sequencer_start, TP_STRUCT__entry( __field( unsigned int, unpacked_lun ) + __field( unsigned long long, tag ) __field( unsigned int, opcode ) __field( unsigned int, data_length ) __field( unsigned int, task_attribute ) @@ -146,6 +147,7 @@ TRACE_EVENT(target_sequencer_start, TP_fast_assign( __entry->unpacked_lun = cmd->orig_fe_lun; + __entry->tag = cmd->tag; __entry->opcode = cmd->t_task_cdb[0]; __entry->data_length = cmd->data_length; __entry->task_attribute = cmd->sam_task_attr; @@ -153,9 +155,9 @@ TRACE_EVENT(target_sequencer_start, __assign_str(initiator, cmd->se_sess->se_node_acl->initiatorname); ), - TP_printk("%s -> LUN %03u %s data_length %6u CDB %s (TA:%s C:%02x)", + TP_printk("%s -> LUN %03u tag %#llx %s data_length %6u CDB %s (TA:%s C:%02x)", __get_str(initiator), __entry->unpacked_lun, - show_opcode_name(__entry->opcode), + __entry->tag, show_opcode_name(__entry->opcode), __entry->data_length, __print_hex(__entry->cdb, 16), show_task_attribute_name(__entry->task_attribute), scsi_command_size(__entry->cdb) <= 16 ? @@ -172,6 +174,7 @@ TRACE_EVENT(target_cmd_complete, TP_STRUCT__entry( __field( unsigned int, unpacked_lun ) + __field( unsigned long long, tag ) __field( unsigned int, opcode ) __field( unsigned int, data_length ) __field( unsigned int, task_attribute ) @@ -184,6 +187,7 @@ TRACE_EVENT(target_cmd_complete, TP_fast_assign( __entry->unpacked_lun = cmd->orig_fe_lun; + __entry->tag = cmd->tag; __entry->opcode = cmd->t_task_cdb[0]; __entry->data_length = cmd->data_length; __entry->task_attribute = cmd->sam_task_attr; @@ -195,8 +199,9 @@ TRACE_EVENT(target_cmd_complete, __assign_str(initiator, cmd->se_sess->se_node_acl->initiatorname); ), - TP_printk("%s <- LUN %03u status %s (sense len %d%s%s) %s data_length %6u CDB %s (TA:%s C:%02x)", + TP_printk("%s <- LUN %03u tag %#llx status %s (sense len %d%s%s) %s data_length %6u CDB %s (TA:%s C:%02x)", __get_str(initiator), __entry->unpacked_lun, + __entry->tag, show_scsi_status_name(__entry->scsi_status), __entry->sense_length, __entry->sense_length ? " / " : "", __print_hex(__entry->sense_data, __entry->sense_length), diff --git a/include/uapi/scsi/fc/fc_els.h b/include/uapi/scsi/fc/fc_els.h index 76f627f0d13b..66318c44acd7 100644 --- a/include/uapi/scsi/fc/fc_els.h +++ b/include/uapi/scsi/fc/fc_els.h @@ -9,6 +9,7 @@ #define _FC_ELS_H_ #include <linux/types.h> +#include <asm/byteorder.h> /* * Fibre Channel Switch - Enhanced Link Services definitions. @@ -40,6 +41,7 @@ enum fc_els_cmd { ELS_REC = 0x13, /* read exchange concise */ ELS_SRR = 0x14, /* sequence retransmission request */ ELS_FPIN = 0x16, /* Fabric Performance Impact Notification */ + ELS_RDF = 0x19, /* Register Diagnostic Functions */ ELS_PRLI = 0x20, /* process login */ ELS_PRLO = 0x21, /* process logout */ ELS_SCN = 0x22, /* state change notification */ @@ -108,6 +110,7 @@ enum fc_els_cmd { [ELS_REC] = "REC", \ [ELS_SRR] = "SRR", \ [ELS_FPIN] = "FPIN", \ + [ELS_RDF] = "RDF", \ [ELS_PRLI] = "PRLI", \ [ELS_PRLO] = "PRLO", \ [ELS_SCN] = "SCN", \ @@ -208,6 +211,99 @@ enum fc_els_rjt_explan { }; /* + * Link Service TLV Descriptor Tag Values + */ +enum fc_ls_tlv_dtag { + ELS_DTAG_LS_REQ_INFO = 0x00000001, + /* Link Service Request Information Descriptor */ + ELS_DTAG_LNK_INTEGRITY = 0x00020001, + /* Link Integrity Notification Descriptor */ + ELS_DTAG_DELIVERY = 0x00020002, + /* Delivery Notification Descriptor */ + ELS_DTAG_PEER_CONGEST = 0x00020003, + /* Peer Congestion Notification Descriptor */ + ELS_DTAG_CONGESTION = 0x00020004, + /* Congestion Notification Descriptor */ + ELS_DTAG_FPIN_REGISTER = 0x00030001, + /* FPIN Registration Descriptor */ +}; + +/* + * Initializer useful for decoding table. + * Please keep this in sync with the above definitions. + */ +#define FC_LS_TLV_DTAG_INIT { \ + { ELS_DTAG_LS_REQ_INFO, "Link Service Request Information" }, \ + { ELS_DTAG_LNK_INTEGRITY, "Link Integrity Notification" }, \ + { ELS_DTAG_DELIVERY, "Delivery Notification Present" }, \ + { ELS_DTAG_PEER_CONGEST, "Peer Congestion Notification" }, \ + { ELS_DTAG_CONGESTION, "Congestion Notification" }, \ + { ELS_DTAG_FPIN_REGISTER, "FPIN Registration" }, \ +} + + +/* + * Generic Link Service TLV Descriptor format + * + * This structure, as it defines no payload, will also be referred to + * as the "tlv header" - which contains the tag and len fields. + */ +struct fc_tlv_desc { + __be32 desc_tag; /* Notification Descriptor Tag */ + __be32 desc_len; /* Length of Descriptor (in bytes). + * Size of descriptor excluding + * desc_tag and desc_len fields. + */ + __u8 desc_value[0]; /* Descriptor Value */ +}; + +/* Descriptor tag and len fields are considered the mandatory header + * for a descriptor + */ +#define FC_TLV_DESC_HDR_SZ sizeof(struct fc_tlv_desc) + +/* + * Macro, used when initializing payloads, to return the descriptor length. + * Length is size of descriptor minus the tag and len fields. + */ +#define FC_TLV_DESC_LENGTH_FROM_SZ(desc) \ + (sizeof(desc) - FC_TLV_DESC_HDR_SZ) + +/* Macro, used on received payloads, to return the descriptor length */ +#define FC_TLV_DESC_SZ_FROM_LENGTH(tlv) \ + (__be32_to_cpu((tlv)->desc_len) + FC_TLV_DESC_HDR_SZ) + +/* + * This helper is used to walk descriptors in a descriptor list. + * Given the address of the current descriptor, which minimally contains a + * tag and len field, calculate the address of the next descriptor based + * on the len field. + */ +static inline void *fc_tlv_next_desc(void *desc) +{ + struct fc_tlv_desc *tlv = desc; + + return (desc + FC_TLV_DESC_SZ_FROM_LENGTH(tlv)); +} + + +/* + * Link Service Request Information Descriptor + */ +struct fc_els_lsri_desc { + __be32 desc_tag; /* descriptor tag (0x0000 0001) */ + __be32 desc_len; /* Length of Descriptor (in bytes) (4). + * Size of descriptor excluding + * desc_tag and desc_len fields. + */ + struct { + __u8 cmd; /* ELS cmd byte */ + __u8 bytes[3]; /* bytes 1..3 */ + } rqst_w0; /* Request word 0 */ +}; + + +/* * Common service parameters (N ports). */ struct fc_els_csp { @@ -819,24 +915,61 @@ enum fc_els_clid_ic { }; +enum fc_fpin_li_event_types { + FPIN_LI_UNKNOWN = 0x0, + FPIN_LI_LINK_FAILURE = 0x1, + FPIN_LI_LOSS_OF_SYNC = 0x2, + FPIN_LI_LOSS_OF_SIG = 0x3, + FPIN_LI_PRIM_SEQ_ERR = 0x4, + FPIN_LI_INVALID_TX_WD = 0x5, + FPIN_LI_INVALID_CRC = 0x6, + FPIN_LI_DEVICE_SPEC = 0xF, +}; + /* - * Fabric Notification Descriptor Tag values + * Initializer useful for decoding table. + * Please keep this in sync with the above definitions. */ -enum fc_fn_dtag { - ELS_FN_DTAG_LNK_INTEGRITY = 0x00020001, /* Link Integrity */ - ELS_FN_DTAG_PEER_CONGEST = 0x00020003, /* Peer Congestion */ - ELS_FN_DTAG_CONGESTION = 0x00020004, /* Congestion */ -}; +#define FC_FPIN_LI_EVT_TYPES_INIT { \ + { FPIN_LI_UNKNOWN, "Unknown" }, \ + { FPIN_LI_LINK_FAILURE, "Link Failure" }, \ + { FPIN_LI_LOSS_OF_SYNC, "Loss of Synchronization" }, \ + { FPIN_LI_LOSS_OF_SIG, "Loss of Signal" }, \ + { FPIN_LI_PRIM_SEQ_ERR, "Primitive Sequence Protocol Error" }, \ + { FPIN_LI_INVALID_TX_WD, "Invalid Transmission Word" }, \ + { FPIN_LI_INVALID_CRC, "Invalid CRC" }, \ + { FPIN_LI_DEVICE_SPEC, "Device Specific" }, \ +} + /* - * Fabric Notification Descriptor + * Link Integrity Notification Descriptor */ -struct fc_fn_desc { - __be32 fn_desc_tag; /* Notification Descriptor Tag */ - __be32 fn_desc_value_len; /* Length of Descriptor Value field - * (in bytes) - */ - __u8 fn_desc_value[0]; /* Descriptor Value */ +struct fc_fn_li_desc { + __be32 desc_tag; /* Descriptor Tag (0x00020001) */ + __be32 desc_len; /* Length of Descriptor (in bytes). + * Size of descriptor excluding + * desc_tag and desc_len fields. + */ + __be64 detecting_wwpn; /* Port Name that detected event */ + __be64 attached_wwpn; /* Port Name of device attached to + * detecting Port Name + */ + __be16 event_type; /* see enum fc_fpin_li_event_types */ + __be16 event_modifier; /* Implementation specific value + * describing the event type + */ + __be32 event_threshold;/* duration in ms of the link + * integrity detection cycle + */ + __be32 event_count; /* minimum number of event + * occurrences during the event + * threshold to caause the LI event + */ + __be32 pname_count; /* number of portname_list elements */ + __be64 pname_list[0]; /* list of N_Port_Names accessible + * through the attached port + */ }; /* @@ -845,8 +978,56 @@ struct fc_fn_desc { struct fc_els_fpin { __u8 fpin_cmd; /* command (0x16) */ __u8 fpin_zero[3]; /* specified as zero - part of cmd */ - __be32 fpin_desc_cnt; /* count of descriptors */ - struct fc_fn_desc fpin_desc[0]; /* Descriptor list */ + __be32 desc_len; /* Length of Descriptor List (in bytes). + * Size of ELS excluding fpin_cmd, + * fpin_zero and desc_len fields. + */ + struct fc_tlv_desc fpin_desc[0]; /* Descriptor list */ +}; + +/* Diagnostic Function Descriptor - FPIN Registration */ +struct fc_df_desc_fpin_reg { + __be32 desc_tag; /* FPIN Registration (0x00030001) */ + __be32 desc_len; /* Length of Descriptor (in bytes). + * Size of descriptor excluding + * desc_tag and desc_len fields. + */ + __be32 count; /* Number of desc_tags elements */ + __be32 desc_tags[0]; /* Array of Descriptor Tags. + * Each tag indicates a function + * supported by the N_Port (request) + * or by the N_Port and Fabric + * Controller (reply; may be a subset + * of the request). + * See ELS_FN_DTAG_xxx for tag values. + */ }; +/* + * ELS_RDF - Register Diagnostic Functions + */ +struct fc_els_rdf { + __u8 fpin_cmd; /* command (0x19) */ + __u8 fpin_zero[3]; /* specified as zero - part of cmd */ + __be32 desc_len; /* Length of Descriptor List (in bytes). + * Size of ELS excluding fpin_cmd, + * fpin_zero and desc_len fields. + */ + struct fc_tlv_desc desc[0]; /* Descriptor list */ +}; + +/* + * ELS RDF LS_ACC Response. + */ +struct fc_els_rdf_resp { + struct fc_els_ls_acc acc_hdr; + __be32 desc_list_len; /* Length of response (in + * bytes). Excludes acc_hdr + * and desc_list_len fields. + */ + struct fc_els_lsri_desc lsri; + struct fc_tlv_desc desc[0]; /* Supported Descriptor list */ +}; + + #endif /* _FC_ELS_H_ */ diff --git a/include/uapi/scsi/scsi_bsg_fc.h b/include/uapi/scsi/scsi_bsg_fc.h index 3ae65e93235c..7f5930801f72 100644 --- a/include/uapi/scsi/scsi_bsg_fc.h +++ b/include/uapi/scsi/scsi_bsg_fc.h @@ -209,7 +209,7 @@ struct fc_bsg_host_vendor { __u64 vendor_id; /* start of vendor command area */ - __u32 vendor_cmd[0]; + __u32 vendor_cmd[]; }; /* Response: diff --git a/scripts/documentation-file-ref-check b/scripts/documentation-file-ref-check index 997202a18ddb..9a8cc10cffd0 100755 --- a/scripts/documentation-file-ref-check +++ b/scripts/documentation-file-ref-check @@ -12,7 +12,7 @@ use Getopt::Long qw(:config no_auto_abbrev); # to mention a past documentation file, for example, to give credits for # the original work. my %false_positives = ( - "Documentation/scsi/scsi_mid_low_api.txt" => "Documentation/Configure.help", + "Documentation/scsi/scsi_mid_low_api.rst" => "Documentation/Configure.help", "drivers/vhost/vhost.c" => "Documentation/virtual/lguest/lguest.c", ); |