diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-06 20:10:32 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-06 20:10:32 -0700 |
commit | 6b22df74f7af62137772c280791c932855f7635b (patch) | |
tree | 1ae52bc548b48eb9d243c41363b5c39fb93a5ca6 | |
parent | 930e0312bcdc96d15f02ed6812d4a6c947855a2d (diff) | |
parent | a93cb871cdeace7de7d865555ed492e8bc8075b5 (diff) | |
download | op-kernel-dev-6b22df74f7af62137772c280791c932855f7635b.zip op-kernel-dev-6b22df74f7af62137772c280791c932855f7635b.tar.gz |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This patch set consists of the usual driver updates (ufs, storvsc,
pm8001 hpsa). It also has removal of the user space target driver
code (everyone is using LIO now), a partial PCI MSI-X update, more
multi-queue updates, conversion to 64 bit LUNs (so we could
theoretically cope with any LUN returned by a device) and placeholder
support for the ZBC device type (Shingle drives), plus an assortment
of minor updates and bug fixes"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (143 commits)
scsi: do not issue SCSI RSOC command to Promise Vtrak E610f
vmw_pvscsi: Use pci_enable_msix_exact() instead of pci_enable_msix()
pm8001: Fix invalid return when request_irq() failed
lpfc: Remove superfluous call to pci_disable_msix()
isci: Use pci_enable_msix_exact() instead of pci_enable_msix()
bfa: Use pci_enable_msix_exact() instead of pci_enable_msix()
bfa: Cleanup bfad_setup_intr() function
bfa: Do not call pci_enable_msix() after it failed once
fnic: Use pci_enable_msix_exact() instead of pci_enable_msix()
scsi: use short driver name for per-driver cmd slab caches
scsi_debug: support scsi-mq, queues and locks
Drivers: add blist flags
scsi: ufs: fix endianness sparse warnings
scsi: ufs: make undeclared functions static
bnx2i: Update driver version to 2.7.10.1
pm8001: fix a memory leak in nvmd_resp
pm8001: fix update_flash
pm8001: fix a memory leak in flash_update
pm8001: Cleaning up uninitialized variables
pm8001: Fix to remove null pointer checks that could never happen
...
231 files changed, 4936 insertions, 6265 deletions
diff --git a/Documentation/scsi/tmscsim.txt b/Documentation/scsi/tmscsim.txt index 3303d21..0810132 100644 --- a/Documentation/scsi/tmscsim.txt +++ b/Documentation/scsi/tmscsim.txt @@ -317,8 +317,6 @@ Each of the parameters is a number, containing the described information: 4 0x10 16 Immediate return on BIOS seek command. (Not used) (*)5 0x20 32 Check for LUNs >= 1. - The default for LUN Check depends on CONFIG_SCSI_MULTI_LUN. - * TaggedCmnds is a number indicating the maximum number of Tagged Commands. It is the binary logarithm - 1 of the actual number. Max is 4 (32). Value Number of Tagged Commands diff --git a/MAINTAINERS b/MAINTAINERS index 731c8a4..e33ca84 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2022,13 +2022,13 @@ S: Supported F: drivers/net/wireless/brcm80211/ BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER -M: Eddie Wai <eddie.wai@broadcom.com> +M: QLogic-Storage-Upstream@qlogic.com L: linux-scsi@vger.kernel.org S: Supported F: drivers/scsi/bnx2fc/ BROADCOM BNX2I 1/10 GIGABIT iSCSI DRIVER -M: Eddie Wai <eddie.wai@broadcom.com> +M: QLogic-Storage-Upstream@qlogic.com L: linux-scsi@vger.kernel.org S: Supported F: drivers/scsi/bnx2i/ diff --git a/arch/arm/configs/msm_defconfig b/arch/arm/configs/msm_defconfig index 7f52dad..dd18c9e 100644 --- a/arch/arm/configs/msm_defconfig +++ b/arch/arm/configs/msm_defconfig @@ -45,7 +45,6 @@ CONFIG_RFKILL=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_SCSI=y -CONFIG_SCSI_TGT=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=y diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index eb4d204..f314236 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -225,7 +225,6 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=m CONFIG_BLK_DEV_PLATFORM=y CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index d7eac833a..399df88 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -257,7 +257,6 @@ CONFIG_BLK_DEV_GAYLE=y CONFIG_BLK_DEV_BUDDHA=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 650ee75..be16740 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -244,7 +244,6 @@ CONFIG_ATA_OVER_ETH=m CONFIG_DUMMY_IRQ=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 3142e69..391e185 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -251,7 +251,6 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_FALCON_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index 0daa8a1..d0e705d 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -242,7 +242,6 @@ CONFIG_ATA_OVER_ETH=m CONFIG_DUMMY_IRQ=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 88af78f..fdc7e96 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -244,7 +244,6 @@ CONFIG_ATA_OVER_ETH=m CONFIG_DUMMY_IRQ=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index 66f9155..3d34564 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -251,7 +251,6 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_MAC_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index 5eaa499..59aa420 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -273,7 +273,6 @@ CONFIG_BLK_DEV_MAC_IDE=y CONFIG_BLK_DEV_Q40IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index 324d0b4..066b24a 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -241,7 +241,6 @@ CONFIG_ATA_OVER_ETH=m CONFIG_DUMMY_IRQ=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index f0cb433..9326ea6 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -242,7 +242,6 @@ CONFIG_ATA_OVER_ETH=m CONFIG_DUMMY_IRQ=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index d6cf088..d7d1101e3 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -249,7 +249,6 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_Q40IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index f4e88d1..98522e8 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -239,7 +239,6 @@ CONFIG_ATA_OVER_ETH=m CONFIG_DUMMY_IRQ=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 49f4032..5128a8c 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -239,7 +239,6 @@ CONFIG_ATA_OVER_ETH=m CONFIG_DUMMY_IRQ=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/mips/configs/db1xxx_defconfig b/arch/mips/configs/db1xxx_defconfig index a64b30b..46e8f76 100644 --- a/arch/mips/configs/db1xxx_defconfig +++ b/arch/mips/configs/db1xxx_defconfig @@ -116,7 +116,6 @@ CONFIG_MTD_NAND_PLATFORM=y CONFIG_MTD_SPI_NOR=y CONFIG_EEPROM_AT24=y CONFIG_EEPROM_AT25=y -CONFIG_SCSI_TGT=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_MULTI_LUN=y diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig index 87d0340..ebc011c 100644 --- a/arch/mips/configs/decstation_defconfig +++ b/arch/mips/configs/decstation_defconfig @@ -45,7 +45,6 @@ CONFIG_VLAN_8021Q=m CONFIG_CONNECTOR=m CONFIG_BLK_DEV_LOOP=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index 936ec5a..57ed466 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig @@ -219,7 +219,6 @@ CONFIG_ATA_OVER_ETH=m # CONFIG_MISC_DEVICES is not set CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 0e36abc..cc07560 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -106,7 +106,6 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_ATA_OVER_ETH=m # CONFIG_MISC_DEVICES is not set CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=m diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 7bbd521..70ffe9b 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -54,7 +54,6 @@ CONFIG_BLK_DEV_NBD=m CONFIG_SGI_IOC4=y CONFIG_RAID_ATTRS=y CONFIG_SCSI=y -CONFIG_SCSI_TGT=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig index 0315ee3..2575302 100644 --- a/arch/mips/configs/jazz_defconfig +++ b/arch/mips/configs/jazz_defconfig @@ -208,7 +208,6 @@ CONFIG_CDROM_PKTCDVD=m CONFIG_ATA_OVER_ETH=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig index ea1761f..fca91a8 100644 --- a/arch/mips/configs/loongson3_defconfig +++ b/arch/mips/configs/loongson3_defconfig @@ -120,7 +120,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_RAID_ATTRS=m -CONFIG_SCSI_TGT=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y CONFIG_CHR_DEV_SG=y diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig index b745b6a..e18741e 100644 --- a/arch/mips/configs/malta_defconfig +++ b/arch/mips/configs/malta_defconfig @@ -253,7 +253,6 @@ CONFIG_BLK_DEV_IT8213=m CONFIG_BLK_DEV_TC86C001=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=m -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=m CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig index 4f7d952..cf0e01f 100644 --- a/arch/mips/configs/malta_kvm_defconfig +++ b/arch/mips/configs/malta_kvm_defconfig @@ -254,7 +254,6 @@ CONFIG_BLK_DEV_IT8213=m CONFIG_BLK_DEV_TC86C001=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=m -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=m CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/mips/configs/malta_kvm_guest_defconfig b/arch/mips/configs/malta_kvm_guest_defconfig index e36681c..edd9ec9 100644 --- a/arch/mips/configs/malta_kvm_guest_defconfig +++ b/arch/mips/configs/malta_kvm_guest_defconfig @@ -254,7 +254,6 @@ CONFIG_BLK_DEV_IT8213=m CONFIG_BLK_DEV_TC86C001=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=m -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=m CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m diff --git a/arch/mips/configs/markeins_defconfig b/arch/mips/configs/markeins_defconfig index 4c2c0c4..0f08e46 100644 --- a/arch/mips/configs/markeins_defconfig +++ b/arch/mips/configs/markeins_defconfig @@ -134,7 +134,6 @@ CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_SGI_IOC4=m CONFIG_SCSI=m -CONFIG_SCSI_TGT=m # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=m CONFIG_CHR_DEV_SG=m diff --git a/arch/mips/configs/nlm_xlp_defconfig b/arch/mips/configs/nlm_xlp_defconfig index 5468b1c..2f660e9 100644 --- a/arch/mips/configs/nlm_xlp_defconfig +++ b/arch/mips/configs/nlm_xlp_defconfig @@ -334,7 +334,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=65536 CONFIG_CDROM_PKTCDVD=y CONFIG_RAID_ATTRS=m -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m @@ -346,10 +345,8 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_SCSI_SPI_ATTRS=m -CONFIG_SCSI_FC_TGT_ATTRS=y CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_ISCSI_TCP=m CONFIG_LIBFCOE=m CONFIG_SCSI_DEBUG=m diff --git a/arch/mips/configs/nlm_xlr_defconfig b/arch/mips/configs/nlm_xlr_defconfig index 44b4734..c6f8465 100644 --- a/arch/mips/configs/nlm_xlr_defconfig +++ b/arch/mips/configs/nlm_xlr_defconfig @@ -311,7 +311,6 @@ CONFIG_CDROM_PKTCDVD=y CONFIG_MISC_DEVICES=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m @@ -323,10 +322,8 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_SCSI_SPI_ATTRS=m -CONFIG_SCSI_FC_TGT_ATTRS=y CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_ISCSI_TCP=m CONFIG_LIBFCOE=m CONFIG_SCSI_DEBUG=m diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index 73e7bf4..29d79ae 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -221,7 +221,6 @@ CONFIG_ATA_OVER_ETH=m CONFIG_SGI_IOC4=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig index d99b190..9327b3a 100644 --- a/arch/mips/configs/tb0226_defconfig +++ b/arch/mips/configs/tb0226_defconfig @@ -39,7 +39,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_XIP=y # CONFIG_MISC_DEVICES is not set CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_SCAN_ASYNC=y diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig index c415c4f..a967289 100644 --- a/arch/mips/configs/tb0287_defconfig +++ b/arch/mips/configs/tb0287_defconfig @@ -44,7 +44,6 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_XIP=y # CONFIG_MISC_DEVICES is not set -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_SCSI_SCAN_ASYNC=y # CONFIG_SCSI_LOWLEVEL is not set diff --git a/arch/powerpc/configs/52xx/motionpro_defconfig b/arch/powerpc/configs/52xx/motionpro_defconfig index c05310a..c936fab 100644 --- a/arch/powerpc/configs/52xx/motionpro_defconfig +++ b/arch/powerpc/configs/52xx/motionpro_defconfig @@ -43,7 +43,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=32768 CONFIG_MISC_DEVICES=y CONFIG_EEPROM_LEGACY=y -CONFIG_SCSI_TGT=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y CONFIG_ATA=y diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig index bcbe747..9b192bb 100644 --- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig +++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig @@ -54,7 +54,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=131072 CONFIG_IDE=y -CONFIG_SCSI_TGT=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y CONFIG_ATA=y diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig index 530601e..69fd8ad 100644 --- a/arch/powerpc/configs/mpc5200_defconfig +++ b/arch/powerpc/configs/mpc5200_defconfig @@ -47,7 +47,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=32768 CONFIG_EEPROM_AT24=y -CONFIG_SCSI_TGT=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y CONFIG_ATA=y diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig index c910669..fec5870 100644 --- a/arch/powerpc/configs/ppc6xx_defconfig +++ b/arch/powerpc/configs/ppc6xx_defconfig @@ -425,10 +425,8 @@ CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_SCSI_SPI_ATTRS=m CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_MESH=m CONFIG_SCSI_MAC53C94=m -CONFIG_SCSI_SRP=m CONFIG_SCSI_LOWLEVEL_PCMCIA=y CONFIG_SCSI_DH=y CONFIG_SCSI_DH_RDAC=m diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig index fd09a10..3ca1894 100644 --- a/arch/s390/configs/default_defconfig +++ b/arch/s390/configs/default_defconfig @@ -366,7 +366,6 @@ CONFIG_VIRTIO_BLK=y CONFIG_ENCLOSURE_SERVICES=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m @@ -380,7 +379,6 @@ CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SPI_ATTRS=m CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_ISCSI_TCP=m CONFIG_LIBFCOE=m CONFIG_SCSI_DEBUG=m diff --git a/arch/s390/configs/gcov_defconfig b/arch/s390/configs/gcov_defconfig index b061180..4830aa6 100644 --- a/arch/s390/configs/gcov_defconfig +++ b/arch/s390/configs/gcov_defconfig @@ -363,7 +363,6 @@ CONFIG_VIRTIO_BLK=y CONFIG_ENCLOSURE_SERVICES=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m @@ -377,7 +376,6 @@ CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SPI_ATTRS=m CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_ISCSI_TCP=m CONFIG_LIBFCOE=m CONFIG_SCSI_DEBUG=m diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig index d279baa..61db449 100644 --- a/arch/s390/configs/performance_defconfig +++ b/arch/s390/configs/performance_defconfig @@ -361,7 +361,6 @@ CONFIG_VIRTIO_BLK=y CONFIG_ENCLOSURE_SERVICES=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_CHR_DEV_OSST=m @@ -375,7 +374,6 @@ CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SPI_ATTRS=m CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_ISCSI_TCP=m CONFIG_LIBFCOE=m CONFIG_SCSI_DEBUG=m diff --git a/arch/sh/configs/sh2007_defconfig b/arch/sh/configs/sh2007_defconfig index 0c08d92..e741b1e 100644 --- a/arch/sh/configs/sh2007_defconfig +++ b/arch/sh/configs/sh2007_defconfig @@ -52,7 +52,6 @@ CONFIG_CDROM_PKTCDVD=y # CONFIG_MISC_DEVICES is not set CONFIG_RAID_ATTRS=y CONFIG_SCSI=y -CONFIG_SCSI_TGT=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y CONFIG_CHR_DEV_SG=y diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig index 730e40d..91de7dd 100644 --- a/arch/tile/configs/tilegx_defconfig +++ b/arch/tile/configs/tilegx_defconfig @@ -170,7 +170,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_ATA_OVER_ETH=m CONFIG_RAID_ATTRS=m -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig index 80fc32e..c7702b7a 100644 --- a/arch/tile/configs/tilepro_defconfig +++ b/arch/tile/configs/tilepro_defconfig @@ -301,7 +301,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_ATA_OVER_ETH=m CONFIG_RAID_ATTRS=m -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 72691fd..0586f66 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3945,7 +3945,7 @@ void ata_scsi_hotplug(struct work_struct *work) * Zero. */ int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, unsigned int lun) + unsigned int id, u64 lun) { struct ata_port *ap = ata_shost_to_port(shost); unsigned long flags; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 45b5ab3..5f4e0cc 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -144,7 +144,7 @@ extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); extern void ata_scsi_dev_rescan(struct work_struct *work); extern int ata_bus_probe(struct ata_port *ap); extern int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, unsigned int lun); + unsigned int id, u64 lun); /* libata-eh.c */ diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index ebc0af7..a896d94 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -649,12 +649,10 @@ mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) case MPI_FUNCTION_CONFIG: case MPI_FUNCTION_SAS_IO_UNIT_CONTROL: ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; - if (reply) { - ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID; - memcpy(ioc->mptbase_cmds.reply, reply, - min(MPT_DEFAULT_FRAME_SIZE, - 4 * reply->u.reply.MsgLength)); - } + ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID; + memcpy(ioc->mptbase_cmds.reply, reply, + min(MPT_DEFAULT_FRAME_SIZE, + 4 * reply->u.reply.MsgLength)); if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) { ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING; complete(&ioc->mptbase_cmds.done); @@ -1408,8 +1406,8 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product * **/ -static void -mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name) +static const char* +mpt_get_product_name(u16 vendor, u16 device, u8 revision) { char *product_str = NULL; @@ -1635,8 +1633,7 @@ mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name) } out: - if (product_str) - sprintf(prod_name, "%s", product_str); + return product_str; } /** @@ -1887,8 +1884,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n", ioc->name, &ioc->facts, &ioc->pfacts[0])); - mpt_get_product_name(pdev->vendor, pdev->device, pdev->revision, - ioc->prod_name); + ioc->prod_name = mpt_get_product_name(pdev->vendor, pdev->device, + pdev->revision); switch (pdev->device) { @@ -7007,7 +7004,7 @@ EXPORT_SYMBOL(mpt_halt_firmware); * IOC doesn't reply to any outstanding request. This will transfer IOC * to READY state. **/ -int +static int mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag) { int rc; diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 76c05bc..8f14090 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -405,7 +405,7 @@ typedef struct _VirtTarget { typedef struct _VirtDevice { VirtTarget *vtarget; u8 configured_lun; - int lun; + u64 lun; } VirtDevice; /* @@ -605,7 +605,7 @@ typedef struct _MPT_ADAPTER int id; /* Unique adapter id N {0,1,2,...} */ int pci_irq; /* This irq */ char name[MPT_NAME_LENGTH]; /* "iocN" */ - char prod_name[MPT_NAME_LENGTH]; /* "LSIFC9x9" */ + const char *prod_name; /* "LSIFC9x9" */ #ifdef CONFIG_FUSION_LOGGING /* used in mpt_display_event_info */ char evStr[EVENT_DESCR_STR_SZ]; diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 8a050e8..b0a892a 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1261,19 +1261,11 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) else return -EFAULT; - karg = kmalloc(data_size, GFP_KERNEL); - if (karg == NULL) { - printk(KERN_ERR MYNAM "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n", - __FILE__, __LINE__); - return -ENOMEM; - } - - if (copy_from_user(karg, uarg, data_size)) { - printk(KERN_ERR MYNAM "%s@%d::mptctl_getiocinfo - " - "Unable to read in mpt_ioctl_iocinfo struct @ %p\n", - __FILE__, __LINE__, uarg); - kfree(karg); - return -EFAULT; + karg = memdup_user(uarg, data_size); + if (IS_ERR(karg)) { + printk(KERN_ERR MYNAM "%s@%d::mpt_ioctl_iocinfo() - memdup_user returned error [%ld]\n", + __FILE__, __LINE__, PTR_ERR(karg)); + return PTR_ERR(karg); } if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) || diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 02a3eef..d8bf84a 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -204,7 +204,7 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt, || (loops > 0 && ioc->active == 0)) { spin_unlock_irqrestore(shost->host_lock, flags); dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT - "mptfc_block_error_handler.%d: %d:%d, port status is " + "mptfc_block_error_handler.%d: %d:%llu, port status is " "%x, active flag %d, deferring %s recovery.\n", ioc->name, ioc->sh->host_no, SCpnt->device->id, SCpnt->device->lun, @@ -218,7 +218,7 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt, if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata || ioc->active == 0) { dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT - "%s.%d: %d:%d, failing recovery, " + "%s.%d: %d:%llu, failing recovery, " "port state %x, active %d, vdevice %p.\n", caller, ioc->name, ioc->sh->host_no, SCpnt->device->id, SCpnt->device->lun, ready, @@ -226,7 +226,7 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt, return FAILED; } dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT - "%s.%d: %d:%d, executing recovery.\n", caller, + "%s.%d: %d:%llu, executing recovery.\n", caller, ioc->name, ioc->sh->host_no, SCpnt->device->id, SCpnt->device->lun)); return (*func)(SCpnt); @@ -525,8 +525,7 @@ mptfc_target_destroy(struct scsi_target *starget) if (ri) /* better be! */ ri->starget = NULL; } - if (starget->hostdata) - kfree(starget->hostdata); + kfree(starget->hostdata); starget->hostdata = NULL; } diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 711fcb5..0707fa2 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -990,11 +990,10 @@ mptsas_queue_device_delete(MPT_ADAPTER *ioc, MpiEventDataSasDeviceStatusChange_t *sas_event_data) { struct fw_event_work *fw_event; - int sz; - sz = offsetof(struct fw_event_work, event_data) + - sizeof(MpiEventDataSasDeviceStatusChange_t); - fw_event = kzalloc(sz, GFP_ATOMIC); + fw_event = kzalloc(sizeof(*fw_event) + + sizeof(MpiEventDataSasDeviceStatusChange_t), + GFP_ATOMIC); if (!fw_event) { printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name, __func__, __LINE__); @@ -1011,10 +1010,8 @@ static void mptsas_queue_rescan(MPT_ADAPTER *ioc) { struct fw_event_work *fw_event; - int sz; - sz = offsetof(struct fw_event_work, event_data); - fw_event = kzalloc(sz, GFP_ATOMIC); + fw_event = kzalloc(sizeof(*fw_event), GFP_ATOMIC); if (!fw_event) { printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name, __func__, __LINE__); @@ -1206,27 +1203,28 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) "(mf = %p, mr = %p)\n", ioc->name, mf, mr)); pScsiTmReply = (SCSITaskMgmtReply_t *)mr; - if (pScsiTmReply) { - dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n" - "\ttask_type = 0x%02X, iocstatus = 0x%04X " - "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, " - "term_cmnds = %d\n", ioc->name, - pScsiTmReply->Bus, pScsiTmReply->TargetID, - pScsiTmReply->TaskType, - le16_to_cpu(pScsiTmReply->IOCStatus), - le32_to_cpu(pScsiTmReply->IOCLogInfo), - pScsiTmReply->ResponseCode, - le32_to_cpu(pScsiTmReply->TerminationCount))); - - if (pScsiTmReply->ResponseCode) - mptscsih_taskmgmt_response_code(ioc, - pScsiTmReply->ResponseCode); - } - - if (pScsiTmReply && (pScsiTmReply->TaskType == + if (!pScsiTmReply) + return 0; + + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n" + "\ttask_type = 0x%02X, iocstatus = 0x%04X " + "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, " + "term_cmnds = %d\n", ioc->name, + pScsiTmReply->Bus, pScsiTmReply->TargetID, + pScsiTmReply->TaskType, + le16_to_cpu(pScsiTmReply->IOCStatus), + le32_to_cpu(pScsiTmReply->IOCLogInfo), + pScsiTmReply->ResponseCode, + le32_to_cpu(pScsiTmReply->TerminationCount))); + + if (pScsiTmReply->ResponseCode) + mptscsih_taskmgmt_response_code(ioc, + pScsiTmReply->ResponseCode); + + if (pScsiTmReply->TaskType == MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType == - MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) { + MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET) { ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID; memcpy(ioc->taskmgmt_cmds.reply, mr, @@ -1575,7 +1573,7 @@ mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info) mptsas_port_delete(ioc, phy_info->port_details); } -struct mptsas_phyinfo * +static struct mptsas_phyinfo * mptsas_refreshing_device_handles(MPT_ADAPTER *ioc, struct mptsas_devinfo *sas_device) { @@ -3648,7 +3646,7 @@ mptsas_send_expander_event(struct fw_event_work *fw_event) * @handle: * */ -struct mptsas_portinfo * +static struct mptsas_portinfo * mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle) { struct mptsas_portinfo buffer, *port_info; @@ -3763,7 +3761,7 @@ mptsas_send_link_status_event(struct fw_event_work *fw_event) printk(MYIOC_s_DEBUG_FMT "SDEV OUTSTANDING CMDS" "%d\n", ioc->name, - sdev->device_busy)); + atomic_read(&sdev->device_busy))); } } @@ -3856,10 +3854,8 @@ retry_page: phy_info = mptsas_find_phyinfo_by_sas_address(ioc, sas_info->sas_address); - if (phy_info) { - mptsas_del_end_device(ioc, phy_info); - goto redo_device_scan; - } + mptsas_del_end_device(ioc, phy_info); + goto redo_device_scan; } else mptsas_volume_delete(ioc, sas_info->fw.id); } @@ -3870,9 +3866,8 @@ retry_page: redo_expander_scan: list_for_each_entry(port_info, &ioc->sas_topology, list) { - if (port_info->phy_info && - (!(port_info->phy_info[0].identify.device_info & - MPI_SAS_DEVICE_INFO_SMP_TARGET))) + if (!(port_info->phy_info[0].identify.device_info & + MPI_SAS_DEVICE_INFO_SMP_TARGET)) continue; found_expander = 0; handle = 0xFFFF; @@ -4983,7 +4978,7 @@ static int mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) { u32 event = le32_to_cpu(reply->Event); - int sz, event_data_sz; + int event_data_sz; struct fw_event_work *fw_event; unsigned long delay; @@ -5093,8 +5088,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) event_data_sz = ((reply->MsgLength * 4) - offsetof(EventNotificationReply_t, Data)); - sz = offsetof(struct fw_event_work, event_data) + event_data_sz; - fw_event = kzalloc(sz, GFP_ATOMIC); + fw_event = kzalloc(sizeof(*fw_event) + event_data_sz, GFP_ATOMIC); if (!fw_event) { printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name, __func__, __LINE__); @@ -5321,7 +5315,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) return error; } -void +static void mptsas_shutdown(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h index 57e86ab..c396483 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; - u8 __attribute__((aligned(4))) event_data[1]; + char event_data[0] __aligned(4); }; struct mptsas_discovery_event { diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 2a1c6f2..e7dcb25 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -95,7 +95,7 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, - int lun, int ctx2abort, ulong timeout); + u64 lun, int ctx2abort, ulong timeout); int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); @@ -536,7 +536,7 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc } scsi_print_command(sc); - printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %d\n", + printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %llu\n", ioc->name, pScsiReply->Bus, pScsiReply->TargetID, sc->device->lun); printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, " "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow, @@ -692,7 +692,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) */ if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && pScsiReply->ResponseInfo) { - printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] " + printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%llu] " "FCP_ResponseInfo=%08xh\n", ioc->name, sc->device->host->host_no, sc->device->channel, sc->device->id, sc->device->lun, @@ -1155,7 +1155,7 @@ mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSI return; ioc = hd->ioc; if (time - hd->last_queue_full > 10 * HZ) { - dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", + dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%llu) reported QUEUE_FULL!\n", ioc->name, 0, sc->device->id, sc->device->lun)); hd->last_queue_full = time; } @@ -1271,15 +1271,13 @@ mptscsih_info(struct Scsi_Host *SChost) h = shost_priv(SChost); - if (h) { - if (h->info_kbuf == NULL) - if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) - return h->info_kbuf; - h->info_kbuf[0] = '\0'; + if (h->info_kbuf == NULL) + if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) + return h->info_kbuf; + h->info_kbuf[0] = '\0'; - mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0); - h->info_kbuf[size-1] = '\0'; - } + mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0); + h->info_kbuf[size-1] = '\0'; return h->info_kbuf; } @@ -1368,8 +1366,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt) /* Default to untagged. Once a target structure has been allocated, * use the Inquiry data to determine if device supports tagged. */ - if (vdevice - && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) + if ((vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) && (SCpnt->device->tagged_supported)) { scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; if (SCpnt->request && SCpnt->request->ioprio) { @@ -1518,7 +1515,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) * **/ int -mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, +mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u64 lun, int ctx2abort, ulong timeout) { MPT_FRAME_HDR *mf; @@ -2380,7 +2377,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) vdevice = sdev->hostdata; dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "device @ %p, channel=%d, id=%d, lun=%d\n", + "device @ %p, channel=%d, id=%d, lun=%llu\n", ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); if (ioc->bus_type == SPI) dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT @@ -2971,7 +2968,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) + (my_idx * MPT_SENSE_BUFFER_ALLOC)); devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n", + "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%llu\n", ioc->name, __func__, cmd, io->channel, io->id, io->lun)); if (dir == MPI_SCSIIO_CONTROL_READ) diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 99e3390..e1b1a19 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -98,7 +98,7 @@ typedef struct _internal_cmd { u8 cmd; /* SCSI Op Code */ u8 channel; /* bus number */ u8 id; /* SCSI ID (virtual) */ - int lun; + u64 lun; u8 flags; /* Bit Field - See above */ u8 physDiskNum; /* Phys disk number, -1 else */ u8 rsvd2; @@ -115,7 +115,7 @@ extern int mptscsih_show_info(struct seq_file *, struct Scsi_Host *); extern const char * mptscsih_info(struct Scsi_Host *SChost); extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt); extern int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, - u8 id, int lun, int ctx2abort, ulong timeout); + u8 id, u64 lun, int ctx2abort, ulong timeout); extern void mptscsih_slave_destroy(struct scsi_device *device); extern int mptscsih_slave_configure(struct scsi_device *device); extern int mptscsih_abort(struct scsi_cmnd * SCpnt); diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 49d1133..787933d 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -461,8 +461,7 @@ static int mptspi_target_alloc(struct scsi_target *starget) static void mptspi_target_destroy(struct scsi_target *starget) { - if (starget->hostdata) - kfree(starget->hostdata); + kfree(starget->hostdata); starget->hostdata = NULL; } @@ -620,7 +619,7 @@ static void mptspi_read_parameters(struct scsi_target *starget) spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0; } -int +static int mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) { MPT_ADAPTER *ioc = hd->ioc; diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index 1d31d72..8152e9fa 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -78,7 +78,7 @@ static unsigned int i2o_scsi_max_lun = 255; struct i2o_scsi_host { struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ struct i2o_controller *iop; /* pointer to the I2O controller */ - unsigned int lun; /* lun's used for block devices */ + u64 lun; /* lun's used for block devices */ struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ }; @@ -287,9 +287,8 @@ static int i2o_scsi_probe(struct device *dev) } if (le64_to_cpu(lun) >= scsi_host->max_lun) { - osm_warn("SCSI device lun (%lu) >= max_lun of I2O host (%d)", - (long unsigned int)le64_to_cpu(lun), - scsi_host->max_lun); + osm_warn("SCSI device lun (%llu) >= max_lun of I2O host (%llu)", + le64_to_cpu(lun), scsi_host->max_lun); return -EFAULT; } @@ -308,9 +307,9 @@ static int i2o_scsi_probe(struct device *dev) if (rc) goto err; - osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %ld\n", + osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %llu\n", i2o_dev->lct_data.tid, channel, le32_to_cpu(id), - (long unsigned int)le64_to_cpu(lun)); + le64_to_cpu(lun)); return 0; diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 0ca6448..5d7fbe4 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -418,7 +418,8 @@ void zfcp_dbf_scsi(char *tag, struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf) rec->scsi_retries = sc->retries; rec->scsi_allowed = sc->allowed; rec->scsi_id = sc->device->id; - rec->scsi_lun = sc->device->lun; + /* struct zfcp_dbf_scsi needs to be updated to handle 64bit LUNs */ + rec->scsi_lun = (u32)sc->device->lun; rec->host_scribble = (unsigned long)sc->host_scribble; memcpy(rec->scsi_opcode, sc->cmnd, diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 39f5446..157d3d2 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -21,7 +21,7 @@ void zfcp_unit_scsi_scan(struct zfcp_unit *unit) { struct fc_rport *rport = unit->port->rport; - unsigned int lun; + u64 lun; lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun); @@ -188,7 +188,7 @@ struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit) { struct Scsi_Host *shost; struct zfcp_port *port; - unsigned int lun; + u64 lun; lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun); port = unit->port; diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h index 49dcf03..29b0b84e 100644 --- a/drivers/scsi/3w-xxxx.h +++ b/drivers/scsi/3w-xxxx.h @@ -392,6 +392,8 @@ typedef struct TAG_TW_Passthru unsigned char padding[12]; } TW_Passthru; +#pragma pack() + typedef struct TAG_TW_Device_Extension { u32 base_addr; unsigned long *alignment_virtual_address[TW_Q_LENGTH]; @@ -430,6 +432,4 @@ typedef struct TAG_TW_Device_Extension { wait_queue_head_t ioctl_wqueue; } TW_Device_Extension; -#pragma pack() - #endif /* _3W_XXXX_H */ diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index a3adfb4..fabd4be 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -1005,7 +1005,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, DMA_TO_DEVICE); cmnd[0] = REQUEST_SENSE; - cmnd[1] = (SCp->device->lun & 0x7) << 5; + cmnd[1] = (lun & 0x7) << 5; cmnd[2] = 0; cmnd[3] = 0; cmnd[4] = SCSI_SENSE_BUFFERSIZE; @@ -1396,7 +1396,8 @@ NCR_700_start_command(struct scsi_cmnd *SCp) struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0]; __u16 count = 1; /* for IDENTIFY message */ - + u8 lun = SCp->device->lun; + if(hostdata->state != NCR_700_HOST_FREE) { /* keep this inside the lock to close the race window where * the running command finishes on another CPU while we don't @@ -1415,7 +1416,7 @@ NCR_700_start_command(struct scsi_cmnd *SCp) hostdata->msgout[0] = NCR_700_identify((SCp->cmnd[0] != REQUEST_SENSE && slot->flags != NCR_700_FLAG_AUTOSENSE), - SCp->device->lun); + lun); /* for INQUIRY or REQUEST_SENSE commands, we cannot be sure * if the negotiated transfer parameters still hold, so * always renegotiate them */ diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index baca589..18a3358 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -40,13 +40,6 @@ config SCSI_DMA bool default n -config SCSI_TGT - tristate "SCSI target support" - depends on SCSI - ---help--- - If you want to use SCSI target mode drivers enable this option. - If you choose M, the module will be called scsi_tgt. - config SCSI_NETLINK bool default n @@ -197,20 +190,6 @@ config SCSI_ENCLOSURE it has an enclosure device. Selecting this option will just allow certain enclosure conditions to be reported and is not required. -config SCSI_MULTI_LUN - bool "Probe all LUNs on each SCSI device" - depends on SCSI - help - Some devices support more than one LUN (Logical Unit Number) in order - to allow access to several media, e.g. CD jukebox, USB card reader, - mobile phone in mass storage mode. This option forces the kernel to - probe for all LUNs by default. This setting can be overridden by - max_luns boot/module parameter. Note that this option does not affect - devices conforming to SCSI-3 or higher as they can explicitly report - their number of LUNs. It is safe to say Y here unless you have one of - those rare devices which reacts in an unexpected way when probed for - multiple LUNs. - config SCSI_CONSTANTS bool "Verbose SCSI error reporting (kernel size +=12K)" depends on SCSI @@ -285,13 +264,6 @@ config SCSI_FC_ATTRS each attached FiberChannel device to sysfs, say Y. Otherwise, say N. -config SCSI_FC_TGT_ATTRS - bool "SCSI target support for FiberChannel Transport Attributes" - depends on SCSI_FC_ATTRS - depends on SCSI_TGT = y || SCSI_TGT = SCSI_FC_ATTRS - help - If you want to use SCSI target mode drivers enable this option. - config SCSI_ISCSI_ATTRS tristate "iSCSI Transport Attributes" depends on SCSI && NET @@ -318,13 +290,6 @@ config SCSI_SRP_ATTRS If you wish to export transport-specific information about each attached SRP device to sysfs, say Y. -config SCSI_SRP_TGT_ATTRS - bool "SCSI target support for SRP Transport Attributes" - depends on SCSI_SRP_ATTRS - depends on SCSI_TGT = y || SCSI_TGT = SCSI_SRP_ATTRS - help - If you want to use SCSI target mode drivers enable this option. - endmenu menuconfig SCSI_LOWLEVEL @@ -528,7 +493,7 @@ config SCSI_DPT_I2O config SCSI_ADVANSYS tristate "AdvanSys SCSI support" - depends on SCSI && VIRT_TO_BUS + depends on SCSI && VIRT_TO_BUS && !ARM depends on ISA || EISA || PCI help This is a driver for all SCSI host adapters manufactured by @@ -848,20 +813,6 @@ config SCSI_IBMVSCSI To compile this driver as a module, choose M here: the module will be called ibmvscsi. -config SCSI_IBMVSCSIS - tristate "IBM Virtual SCSI Server support" - depends on PPC_PSERIES && SCSI_SRP && SCSI_SRP_TGT_ATTRS - help - This is the SRP target driver for IBM pSeries virtual environments. - - The userspace component needed to initialize the driver and - documentation can be found: - - http://stgt.berlios.de/ - - To compile this driver as a module, choose M here: the - module will be called ibmvstgt. - config SCSI_IBMVFC tristate "IBM Virtual FC support" depends on PPC_PSERIES && SCSI @@ -1750,16 +1701,6 @@ config SCSI_PM8001 This driver supports PMC-Sierra PCIE SAS/SATA 8x6G SPC 8001 chip based host adapters. -config SCSI_SRP - tristate "SCSI RDMA Protocol helper library" - depends on SCSI && PCI - select SCSI_TGT - help - If you wish to use SRP target drivers, say Y. - - To compile this driver as a module, choose M here: the - module will be called libsrp. - config SCSI_BFA_FC tristate "Brocade BFA Fibre Channel Support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index e172d4f..5f0d299 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -20,7 +20,6 @@ CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ -DGDTH_STATISTICS obj-$(CONFIG_PCMCIA) += pcmcia/ obj-$(CONFIG_SCSI) += scsi_mod.o -obj-$(CONFIG_SCSI_TGT) += scsi_tgt.o obj-$(CONFIG_RAID_ATTRS) += raid_class.o @@ -127,9 +126,7 @@ obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o obj-$(CONFIG_SCSI_IPR) += ipr.o -obj-$(CONFIG_SCSI_SRP) += libsrp.o obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ -obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/ obj-$(CONFIG_SCSI_IBMVFC) += ibmvscsi/ obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o obj-$(CONFIG_SCSI_STEX) += stex.o @@ -173,8 +170,6 @@ scsi_mod-$(CONFIG_PM) += scsi_pm.o hv_storvsc-y := storvsc_drv.o -scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o - sd_mod-objs := sd.o sd_mod-$(CONFIG_BLK_DEV_INTEGRITY) += sd_dif.o diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 93d13fc..45da3c8 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -762,7 +762,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, static void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m) { - SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun); + SPRINTF("scsi%d : destination target %d, lun %llu\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun); SPRINTF(" command = "); lprint_command(cmd->cmnd, m); } @@ -1039,9 +1039,10 @@ static void NCR5380_main(struct work_struct *work) for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) { if (prev != tmp) - dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun); + dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun); /* When we find one, remove it from the issue queue. */ - if (!(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))) { + if (!(hostdata->busy[tmp->device->id] & + (1 << (u8)(tmp->device->lun & 0xff)))) { if (prev) { REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble); prev->host_scribble = tmp->host_scribble; @@ -1057,7 +1058,7 @@ static void NCR5380_main(struct work_struct *work) * On failure, we must add the command back to the * issue queue so we can keep trying. */ - dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun); + dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %llu removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun); /* * A successful selection is defined as one that @@ -1524,7 +1525,7 @@ part2: dprintk(NDEBUG_SELECTION, "scsi%d : nexus established.\n", instance->host_no); /* XXX need to handle errors here */ hostdata->connected = cmd; - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF)); initialize_SCp(cmd); @@ -2210,14 +2211,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { case LINKED_FLG_CMD_COMPLETE: /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %d linked command complete.\n", instance->host_no, cmd->device->id, cmd->device->lun); + dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked command complete.\n", instance->host_no, cmd->device->id, cmd->device->lun); /* * Sanity check : A linked command should only terminate with * one of these messages if there are more linked commands * available. */ if (!cmd->next_link) { - printk("scsi%d : target %d lun %d linked command complete, no next_link\n" instance->host_no, cmd->device->id, cmd->device->lun); + printk("scsi%d : target %d lun %llu linked command complete, no next_link\n" instance->host_no, cmd->device->id, cmd->device->lun); sink = 1; do_abort(instance); return; @@ -2226,7 +2227,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { /* The next command is still part of this process */ cmd->next_link->tag = cmd->tag; cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %d linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun); + dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun); collect_stats(hostdata, cmd); cmd->scsi_done(cmd); cmd = hostdata->connected; @@ -2238,8 +2239,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { sink = 1; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); hostdata->connected = NULL; - dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d, lun %d completed\n", instance->host_no, cmd->device->id, cmd->device->lun); - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d, lun %llu completed\n", instance->host_no, cmd->device->id, cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF)); /* * I'm not sure what the correct thing to do here is : @@ -2304,7 +2305,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { case ORDERED_QUEUE_TAG: case SIMPLE_QUEUE_TAG: cmd->device->simple_tags = 0; - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF)); break; default: break; @@ -2318,7 +2319,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { hostdata->disconnected_queue; hostdata->connected = NULL; hostdata->disconnected_queue = cmd; - dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d lun %d was moved from connected to" " the disconnected_queue\n", instance->host_no, cmd->device->id, cmd->device->lun); + dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d lun %llu was moved from connected to" " the disconnected_queue\n", instance->host_no, cmd->device->id, cmd->device->lun); /* * Restore phase bits to 0 so an interrupted selection, * arbitration can resume. @@ -2426,7 +2427,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { hostdata->last_message = msgout; NCR5380_transfer_pio(instance, &phase, &len, &data); if (msgout == ABORT) { - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF)); hostdata->connected = NULL; cmd->result = DID_ERROR << 16; collect_stats(hostdata, cmd); @@ -2562,7 +2563,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) - if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun) + if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun) ) { if (prev) { REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble); @@ -2588,7 +2589,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { do_abort(instance); } else { hostdata->connected = tmp; - dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag); + dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %llu, tag = %d\n", instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag); } } diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index c91888a..42c7161 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -595,7 +595,7 @@ static int NCR53c406a_release(struct Scsi_Host *shost) { if (shost->irq) free_irq(shost->irq, NULL); -#ifdef USE_DMA +#if USE_DMA if (shost->dma_channel != 0xff) free_dma(shost->dma_channel); #endif @@ -698,7 +698,7 @@ static int NCR53c406a_queue_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) int i; VDEB(printk("NCR53c406a_queue called\n")); - DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt))); + DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->target, (u8)SCpnt->device->lun, scsi_bufflen(SCpnt))); #if 0 VDEB(for (i = 0; i < SCpnt->cmd_len; i++) diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 0163457..522570d 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -891,7 +891,7 @@ static int inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struc printk("max cdb length= %x\b", cmd->cmd_len); scb->cdb_len = IMAX_CDB; } - scb->ident = cmd->device->lun | DISC_ALLOW; + scb->ident = (u8)(cmd->device->lun & 0xff) | DISC_ALLOW; if (cmd->device->tagged_supported) { /* Tag Support */ scb->tag_msg = SIMPLE_QUEUE_TAG; /* Do simple tag only */ } else { diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 4921ed19..63f576c 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -551,7 +551,7 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) int count; int ret = FAILED; - printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n", + printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%llu)\n", AAC_DRIVERNAME, host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun); switch (cmd->cmnd[0]) { diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index d814588..43761c1 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -2512,7 +2512,7 @@ static void asc_prt_scsi_host(struct Scsi_Host *s) printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev)); printk(" host_busy %u, host_no %d,\n", - s->host_busy, s->host_no); + atomic_read(&s->host_busy), s->host_no); printk(" base 0x%lx, io_port 0x%lx, irq %d,\n", (ulong)s->base, (ulong)s->io_port, boardp->irq); @@ -3345,8 +3345,8 @@ static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost) shost->host_no); seq_printf(m, - " host_busy %u, max_id %u, max_lun %u, max_channel %u\n", - shost->host_busy, shost->max_id, + " host_busy %u, max_id %u, max_lun %llu, max_channel %u\n", + atomic_read(&shost->host_busy), shost->max_id, shost->max_lun, shost->max_channel); seq_printf(m, diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index e86eb6a..e77b72f 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -321,7 +321,7 @@ static LIST_HEAD(aha152x_host_list); #define CMDINFO(cmd) \ (cmd) ? ((cmd)->device->host->host_no) : -1, \ (cmd) ? ((cmd)->device->id & 0x0f) : -1, \ - (cmd) ? ((cmd)->device->lun & 0x07) : -1 + (cmd) ? ((u8)(cmd)->device->lun & 0x07) : -1 static inline void CMD_INC_RESID(struct scsi_cmnd *cmd, int inc) @@ -1602,7 +1602,7 @@ static void busfree_run(struct Scsi_Host *shpnt) #if defined(AHA152X_DEBUG) int hostno=DONE_SC->device->host->host_no; int id=DONE_SC->device->id & 0xf; - int lun=DONE_SC->device->lun & 0x7; + int lun=((u8)DONE_SC->device->lun) & 0x7; #endif Scsi_Cmnd *ptr = DONE_SC; DONE_SC=NULL; @@ -2984,7 +2984,7 @@ static void get_command(struct seq_file *m, Scsi_Cmnd * ptr) int i; SPRINTF("%p: target=%d; lun=%d; cmnd=( ", - ptr, ptr->device->id, ptr->device->lun); + ptr, ptr->device->id, (u8)ptr->device->lun); for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++) SPRINTF("0x%02x ", ptr->cmnd[i]); diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c index 0cb8ef6..3d401d0 100644 --- a/drivers/scsi/aic7xxx/aic7770_osm.c +++ b/drivers/scsi/aic7xxx/aic7770_osm.c @@ -85,10 +85,9 @@ aic7770_probe(struct device *dev) int error; sprintf(buf, "ahc_eisa:%d", eisaBase >> 12); - name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); + name = kstrdup(buf, GFP_ATOMIC); if (name == NULL) return (ENOMEM); - strcpy(name, buf); ahc = ahc_alloc(&aic7xxx_driver_template, name); if (ahc == NULL) return (ENOMEM); diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 113874c..df2e0e5 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -115,7 +115,7 @@ struct scb_platform_data; #endif #define AHD_BUILD_COL_IDX(target, lun) \ - (((lun) << 4) | target) + ((((u8)lun) << 4) | target) #define AHD_GET_SCB_COL_IDX(ahd, scb) \ ((SCB_GET_LUN(scb) << 4) | SCB_GET_TARGET(ahd, scb)) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 69d5c43..ed333669 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -2137,7 +2137,7 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) if (do_fallback) { printk("%s: device overrun (status %x) on %d:%d:%d\n", ahd_name(ahd), status, cmd->device->channel, - cmd->device->id, cmd->device->lun); + cmd->device->id, (u8)cmd->device->lun); } ahd_cmd_set_transaction_status(cmd, new_status); @@ -2253,13 +2253,13 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) disconnected = TRUE; if (ahd_search_qinfifo(ahd, cmd->device->id, cmd->device->channel + 'A', - cmd->device->lun, + cmd->device->lun, pending_scb->hscb->tag, ROLE_INITIATOR, CAM_REQ_ABORTED, SEARCH_COMPLETE) > 0) { printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", ahd_name(ahd), cmd->device->channel, - cmd->device->id, cmd->device->lun); + cmd->device->id, (u8)cmd->device->lun); retval = SUCCESS; goto done; } diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 3c85873..8466aa7 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -178,10 +178,9 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ahd_get_pci_bus(pci), ahd_get_pci_slot(pci), ahd_get_pci_function(pci)); - name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); + name = kstrdup(buf, GFP_ATOMIC); if (name == NULL) return (-ENOMEM); - strcpy(name, buf); ahd = ahd_alloc(NULL, name); if (ahd == NULL) return (-ENOMEM); diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c index e9778b4..27dbfcc 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c @@ -197,7 +197,7 @@ ahd_dump_device_state(struct seq_file *m, struct scsi_device *sdev) seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n", sdev->sdev_target->channel + 'A', - sdev->sdev_target->id, sdev->lun); + sdev->sdev_target->id, (u8)sdev->lun); seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued); seq_printf(m, "\t\tCommands Active %d\n", dev->active); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 114ff0c..d2c9bf3 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -2110,7 +2110,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) */ printk("%s:%d:%d:%d: Is not an active device\n", ahc_name(ahc), cmd->device->channel, cmd->device->id, - cmd->device->lun); + (u8)cmd->device->lun); retval = SUCCESS; goto no_cmd; } @@ -2118,11 +2118,11 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0 && ahc_search_untagged_queues(ahc, cmd, cmd->device->id, cmd->device->channel + 'A', - cmd->device->lun, + (u8)cmd->device->lun, CAM_REQ_ABORTED, SEARCH_COMPLETE) != 0) { printk("%s:%d:%d:%d: Command found on untagged queue\n", ahc_name(ahc), cmd->device->channel, cmd->device->id, - cmd->device->lun); + (u8)cmd->device->lun); retval = SUCCESS; goto done; } @@ -2188,13 +2188,14 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) SEARCH_COMPLETE) > 0) { printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", ahc_name(ahc), cmd->device->channel, - cmd->device->id, cmd->device->lun); + cmd->device->id, (u8)cmd->device->lun); retval = SUCCESS; goto done; } } else if (ahc_search_qinfifo(ahc, cmd->device->id, cmd->device->channel + 'A', - cmd->device->lun, pending_scb->hscb->tag, + cmd->device->lun, + pending_scb->hscb->tag, ROLE_INITIATOR, /*status*/0, SEARCH_COUNT) > 0) { disconnected = FALSE; diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index ee05e84..0fc14da 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -225,10 +225,9 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ahc_get_pci_bus(pci), ahc_get_pci_slot(pci), ahc_get_pci_function(pci)); - name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); + name = kstrdup(buf, GFP_ATOMIC); if (name == NULL) return (-ENOMEM); - strcpy(name, buf); ahc = ahc_alloc(NULL, name); if (ahc == NULL) return (-ENOMEM); diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index 383a3d1..64eec6c 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c @@ -175,7 +175,7 @@ ahc_dump_device_state(struct seq_file *m, struct scsi_device *sdev) seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n", sdev->sdev_target->channel + 'A', - sdev->sdev_target->id, sdev->lun); + sdev->sdev_target->id, (u8)sdev->lun); seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued); seq_printf(m, "\t\tCommands Active %d\n", dev->active); diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 652b41b..b13764c 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -2335,7 +2335,7 @@ static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, " poll command abort successfully \n" , acb->host->host_no , ccb->pcmd->device->id - , ccb->pcmd->device->lun + , (u32)ccb->pcmd->device->lun , ccb); ccb->pcmd->result = DID_ABORT << 16; arcmsr_ccb_complete(ccb); @@ -2399,7 +2399,7 @@ static int arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, " poll command abort successfully \n" ,acb->host->host_no ,ccb->pcmd->device->id - ,ccb->pcmd->device->lun + ,(u32)ccb->pcmd->device->lun ,ccb); ccb->pcmd->result = DID_ABORT << 16; arcmsr_ccb_complete(ccb); @@ -2456,7 +2456,7 @@ polling_hbc_ccb_retry: " poll command abort successfully \n" , acb->host->host_no , pCCB->pcmd->device->id - , pCCB->pcmd->device->lun + , (u32)pCCB->pcmd->device->lun , pCCB); pCCB->pcmd->result = DID_ABORT << 16; arcmsr_ccb_complete(pCCB); @@ -3058,7 +3058,7 @@ static int arcmsr_abort(struct scsi_cmnd *cmd) int rtn = FAILED; printk(KERN_NOTICE "arcmsr%d: abort device command of scsi id = %d lun = %d \n", - acb->host->host_no, cmd->device->id, cmd->device->lun); + acb->host->host_no, cmd->device->id, (u32)cmd->device->lun); acb->acb_flags |= ACB_F_ABORT; acb->num_aborts++; /* diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index 2e797a3..d89b9b4 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -760,7 +760,8 @@ intr_ret_t acornscsi_kick(AS_Host *host) SCpnt->tag = SCpnt->device->current_tag; } else #endif - set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); + set_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x07), host->busyluns); host->stats.removes += 1; @@ -863,7 +864,8 @@ static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp, if (!SCpnt->scsi_done) panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no); - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); + clear_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x7), host->busyluns); SCpnt->scsi_done(SCpnt); } else @@ -1576,7 +1578,8 @@ void acornscsi_message(AS_Host *host) printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n", host->host->host_no, acornscsi_target(host)); host->SCpnt->device->simple_tags = 0; - set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns); + set_bit(host->SCpnt->device->id * 8 + + (u8)(host->SCpnt->device->lun & 0x7), host->busyluns); break; #endif case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8): @@ -2671,7 +2674,8 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) //#if (DEBUG & DEBUG_ABORT) printk("clear "); //#endif - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); + clear_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x7), host->busyluns); /* * We found the command, and cleared it out. Either @@ -2853,7 +2857,7 @@ static int acornscsi_show_info(struct seq_file *m, struct Scsi_Host *instance) shost_for_each_device(scd, instance) { seq_printf(m, "Device/Lun TaggedQ Sync\n"); - seq_printf(m, " %d/%d ", scd->id, scd->lun); + seq_printf(m, " %d/%llu ", scd->id, scd->lun); if (scd->tagged_supported) seq_printf(m, "%3sabled(%3d) ", scd->simple_tags ? "en" : "dis", diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index b46a6f6..71cfb1e 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -1821,7 +1821,8 @@ static void fas216_allocate_tag(FAS216_Info *info, struct scsi_cmnd *SCpnt) SCpnt->tag = SCpnt->device->current_tag; } else #endif - set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); + set_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x7), info->busyluns); info->stats.removes += 1; switch (SCpnt->cmnd[0]) { @@ -2171,7 +2172,8 @@ static void fas216_done(FAS216_Info *info, unsigned int result) * status. */ info->device[SCpnt->device->id].parity_check = 0; - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); + clear_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x7), info->busyluns); fn = (void (*)(FAS216_Info *, struct scsi_cmnd *, unsigned int))SCpnt->host_scribble; fn(info, SCpnt, result); @@ -2398,7 +2400,8 @@ static enum res_find fas216_find_command(FAS216_Info *info, * been set. */ info->origSCpnt = NULL; - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); + clear_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x7), info->busyluns); printk("waiting for execution "); res = res_success; } else @@ -3000,7 +3003,7 @@ void fas216_print_devices(FAS216_Info *info, struct seq_file *m) shost_for_each_device(scd, info->host) { dev = &info->device[scd->id]; - seq_printf(m, " %d/%d ", scd->id, scd->lun); + seq_printf(m, " %d/%llu ", scd->id, scd->lun); if (scd->tagged_supported) seq_printf(m, "%3sabled(%3d) ", scd->simple_tags ? "en" : "dis", diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c index cb11cce..3441ce3 100644 --- a/drivers/scsi/arm/queue.c +++ b/drivers/scsi/arm/queue.c @@ -167,7 +167,8 @@ struct scsi_cmnd *queue_remove_exclude(Queue_t *queue, unsigned long *exclude) spin_lock_irqsave(&queue->queue_lock, flags); list_for_each(l, &queue->head) { QE_t *q = list_entry(l, QE_t, list); - if (!test_bit(q->SCpnt->device->id * 8 + q->SCpnt->device->lun, exclude)) { + if (!test_bit(q->SCpnt->device->id * 8 + + (u8)(q->SCpnt->device->lun & 0x7), exclude)) { SCpnt = __queue_remove(queue, l); break; } diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 1814aa2..79e6f04 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -361,17 +361,18 @@ static void __init init_tags(void) static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); - if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)) + if (hostdata->busy[cmd->device->id] & (1 << lun)) return 1; if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) return 0; - if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >= - TagAlloc[cmd->device->id][cmd->device->lun].queue_size) { + if (TagAlloc[cmd->device->id][lun].nr_allocated >= + TagAlloc[cmd->device->id][lun].queue_size) { dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d: no free tags\n", - H_NO(cmd), cmd->device->id, cmd->device->lun); + H_NO(cmd), cmd->device->id, lun); return 1; } return 0; @@ -385,6 +386,7 @@ static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged) static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); /* If we or the target don't support tagged queuing, allocate the LUN for @@ -393,11 +395,11 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged) if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) { cmd->tag = TAG_NONE; - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= (1 << lun); dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d now allocated by untagged " - "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun); + "command\n", H_NO(cmd), cmd->device->id, lun); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun]; cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS); set_bit(cmd->tag, ta->allocated); @@ -405,7 +407,7 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged) dprintk(NDEBUG_TAGS, "scsi%d: using tag %d for target %d lun %d " "(now %d tags in use)\n", H_NO(cmd), cmd->tag, cmd->device->id, - cmd->device->lun, ta->nr_allocated); + lun, ta->nr_allocated); } } @@ -416,21 +418,22 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged) static void cmd_free_tag(Scsi_Cmnd *cmd) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); if (cmd->tag == TAG_NONE) { - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << lun); dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d untagged cmd finished\n", - H_NO(cmd), cmd->device->id, cmd->device->lun); + H_NO(cmd), cmd->device->id, lun); } else if (cmd->tag >= MAX_TAGS) { printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n", H_NO(cmd), cmd->tag); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun]; clear_bit(cmd->tag, ta->allocated); ta->nr_allocated--; dprintk(NDEBUG_TAGS, "scsi%d: freed tag %d for target %d lun %d\n", - H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun); + H_NO(cmd), cmd->tag, cmd->device->id, lun); } } @@ -713,7 +716,7 @@ static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd) { int i, s; unsigned char *command; - printk("scsi%d: destination target %d, lun %d\n", + printk("scsi%d: destination target %d, lun %llu\n", H_NO(cmd), cmd->device->id, cmd->device->lun); printk(KERN_CONT " command = "); command = cmd->cmnd; @@ -759,7 +762,7 @@ static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m) { int i, s; unsigned char *command; - seq_printf(m, "scsi%d: destination target %d, lun %d\n", + seq_printf(m, "scsi%d: destination target %d, lun %llu\n", H_NO(cmd), cmd->device->id, cmd->device->lun); seq_printf(m, " command = "); command = cmd->cmnd; @@ -1060,12 +1063,13 @@ static void NCR5380_main(struct work_struct *work) #endif for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) { + u8 lun = tmp->device->lun; #if (NDEBUG & NDEBUG_LISTS) if (prev != tmp) - printk("MAIN tmp=%p target=%d busy=%d lun=%d\n", + printk("MAIN tmp=%p target=%d busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], - tmp->device->lun); + lun); #endif /* When we find one, remove it from the issue queue. */ /* ++guenther: possible race with Falcon locking */ @@ -1073,7 +1077,7 @@ static void NCR5380_main(struct work_struct *work) #ifdef SUPPORT_TAGS !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE) #else - !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun)) + !(hostdata->busy[tmp->device->id] & (1 << lun)) #endif ) { /* ++guenther: just to be sure, this must be atomic */ @@ -1099,7 +1103,7 @@ static void NCR5380_main(struct work_struct *work) */ dprintk(NDEBUG_MAIN, "scsi%d: main(): command for target %d " "lun %d removed from issue_queue\n", - HOSTNO, tmp->device->id, tmp->device->lun); + HOSTNO, tmp->device->id, lun); /* * REQUEST SENSE commands are issued without tagged * queueing, even on SCSI-II devices because the @@ -2061,7 +2065,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * accesses to this device will use the * polled-IO. */ printk(KERN_NOTICE "scsi%d: switching target %d " - "lun %d to slow handshake\n", HOSTNO, + "lun %llu to slow handshake\n", HOSTNO, cmd->device->id, cmd->device->lun); cmd->device->borken = 1; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | @@ -2113,7 +2117,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked command " + dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked command " "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun); /* Enable reselect interrupts */ @@ -2125,7 +2129,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) */ if (!cmd->next_link) { - printk(KERN_NOTICE "scsi%d: target %d lun %d " + printk(KERN_NOTICE "scsi%d: target %d lun %llu " "linked command complete, no next_link\n", HOSTNO, cmd->device->id, cmd->device->lun); sink = 1; @@ -2138,7 +2142,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * and don't free it! */ cmd->next_link->tag = cmd->tag; cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked request " + dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request " "done, calling scsi_done().\n", HOSTNO, cmd->device->id, cmd->device->lun); #ifdef NCR5380_STATS @@ -2155,7 +2159,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* ++guenther: possible race with Falcon locking */ falcon_dont_release++; hostdata->connected = NULL; - dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %d " + dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu " "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); #ifdef SUPPORT_TAGS cmd_free_tag(cmd); @@ -2169,7 +2173,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* ++Andreas: the mid level code knows about QUEUE_FULL now. */ TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d returned " + dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned " "QUEUE_FULL after %d commands\n", HOSTNO, cmd->device->id, cmd->device->lun, ta->nr_allocated); @@ -2267,7 +2271,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) cmd->device->tagged_supported = 0; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); cmd->tag = TAG_NONE; - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d rejected " + dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu rejected " "QUEUE_TAG message; tagged queuing " "disabled\n", HOSTNO, cmd->device->id, cmd->device->lun); @@ -2284,7 +2288,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) hostdata->connected = NULL; hostdata->disconnected_queue = cmd; local_irq_restore(flags); - dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %d was " + dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %llu was " "moved from connected to the " "disconnected_queue\n", HOSTNO, cmd->device->id, cmd->device->lun); @@ -2385,12 +2389,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) printk("\n"); } else if (tmp != EXTENDED_MESSAGE) printk(KERN_DEBUG "scsi%d: rejecting unknown " - "message %02x from target %d, lun %d\n", + "message %02x from target %d, lun %llu\n", HOSTNO, tmp, cmd->device->id, cmd->device->lun); else printk(KERN_DEBUG "scsi%d: rejecting unknown " "extended message " - "code %02x, length %d from target %d, lun %d\n", + "code %02x, length %d from target %d, lun %llu\n", HOSTNO, extended_msg[1], extended_msg[0], cmd->device->id, cmd->device->lun); @@ -2588,7 +2592,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); hostdata->connected = tmp; - dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %d, tag = %d\n", + dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n", HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag); falcon_dont_release--; } diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index fd284ff..8616281 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -914,7 +914,7 @@ void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, stats->r2t_pdus = conn->r2t_pdus_cnt; stats->digest_err = 0; stats->timeout_err = 0; - stats->custom_length = 0; + stats->custom_length = 1; strcpy(stats->custom[0].desc, "eh_abort_cnt"); stats->custom[0].value = conn->eh_abort_cnt; } diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 07934b0..a3e5648 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -1015,7 +1015,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, if (if_info->dhcp_state) { beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, "BG_%d : DHCP Already Enabled\n"); - return 0; + goto exit; } /* The ip_param->len is 1 in DHCP case. Setting proper IP len as this it is used while @@ -1033,7 +1033,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, sizeof(*reldhcp)); if (rc) - return rc; + goto exit; reldhcp = nonemb_cmd.va; reldhcp->interface_hndl = phba->interface_handle; @@ -1044,7 +1044,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, "BG_%d : Failed to Delete existing dhcp\n"); - return rc; + goto exit; } } } @@ -1054,7 +1054,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL, IP_ACTION_DEL); if (rc) - return rc; + goto exit; } /* Delete the Gateway settings if mode change is to DHCP */ @@ -1064,7 +1064,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, if (rc) { beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, "BG_%d : Failed to Get Gateway Addr\n"); - return rc; + goto exit; } if (gtway_addr_set.ip_addr.addr[0]) { @@ -1076,7 +1076,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, "BG_%d : Failed to clear Gateway Addr Set\n"); - return rc; + goto exit; } } } @@ -1087,7 +1087,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR, sizeof(*dhcpreq)); if (rc) - return rc; + goto exit; dhcpreq = nonemb_cmd.va; dhcpreq->flags = BLOCKING; @@ -1095,12 +1095,14 @@ int mgmt_set_ip(struct beiscsi_hba *phba, dhcpreq->interface_hndl = phba->interface_handle; dhcpreq->ip_type = BE2_DHCP_V4; - return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); + rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); } else { - return mgmt_static_ip_modify(phba, if_info, ip_param, + rc = mgmt_static_ip_modify(phba, if_info, ip_param, subnet_param, IP_ACTION_ADD); } +exit: + kfree(if_info); return rc; } diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index a3ab5cc..0f19455 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -81,7 +81,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, bfa->fcs = BFA_TRUE; fcbuild_init(); - for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { + for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) { mod = &fcs_modules[i]; if (mod->attach) mod->attach(fcs); @@ -97,7 +97,7 @@ bfa_fcs_init(struct bfa_fcs_s *fcs) int i; struct bfa_fcs_mod_s *mod; - for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { + for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) { mod = &fcs_modules[i]; if (mod->modinit) mod->modinit(fcs); @@ -184,7 +184,7 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs) bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs); - nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]); + nmods = ARRAY_SIZE(fcs_modules); for (i = 0; i < nmods; i++) { diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 2e28392..a38aafa0 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -72,7 +72,7 @@ struct bfa_sge_s { } while (0) #define bfa_swap_words(_x) ( \ - ((_x) << 32) | ((_x) >> 32)) + ((u64)(_x) << 32) | ((u64)(_x) >> 32)) #ifdef __BIG_ENDIAN #define bfa_sge_to_be(_x) diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 7593b7c..e90a374 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -1219,7 +1219,7 @@ bfad_install_msix_handler(struct bfad_s *bfad) int bfad_setup_intr(struct bfad_s *bfad) { - int error = 0; + int error; u32 mask = 0, i, num_bit = 0, max_bit = 0; struct msix_entry msix_entries[MAX_MSIX_ENTRY]; struct pci_dev *pdev = bfad->pcidev; @@ -1234,34 +1234,24 @@ bfad_setup_intr(struct bfad_s *bfad) if ((bfa_asic_id_ctc(pdev->device) && !msix_disable_ct) || (bfa_asic_id_cb(pdev->device) && !msix_disable_cb)) { - error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec); - if (error) { - /* In CT1 & CT2, try to allocate just one vector */ - if (bfa_asic_id_ctc(pdev->device)) { - printk(KERN_WARNING "bfa %s: trying one msix " - "vector failed to allocate %d[%d]\n", - bfad->pci_name, bfad->nvec, error); - bfad->nvec = 1; - error = pci_enable_msix(bfad->pcidev, - msix_entries, bfad->nvec); - } + error = pci_enable_msix_exact(bfad->pcidev, + msix_entries, bfad->nvec); + /* In CT1 & CT2, try to allocate just one vector */ + if (error == -ENOSPC && bfa_asic_id_ctc(pdev->device)) { + printk(KERN_WARNING "bfa %s: trying one msix " + "vector failed to allocate %d[%d]\n", + bfad->pci_name, bfad->nvec, error); + bfad->nvec = 1; + error = pci_enable_msix_exact(bfad->pcidev, + msix_entries, 1); + } - /* - * Only error number of vector is available. - * We don't have a mechanism to map multiple - * interrupts into one vector, so even if we - * can try to request less vectors, we don't - * know how to associate interrupt events to - * vectors. Linux doesn't duplicate vectors - * in the MSIX table for this case. - */ - if (error) { - printk(KERN_WARNING "bfad%d: " - "pci_enable_msix failed (%d), " - "use line based.\n", - bfad->inst_no, error); - goto line_based; - } + if (error) { + printk(KERN_WARNING "bfad%d: " + "pci_enable_msix_exact failed (%d), " + "use line based.\n", + bfad->inst_no, error); + goto line_based; } /* Disable INTX in MSI-X mode */ @@ -1281,20 +1271,18 @@ bfad_setup_intr(struct bfad_s *bfad) bfad->bfad_flags |= BFAD_MSIX_ON; - return error; + return 0; } line_based: - error = 0; - if (request_irq - (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS, - BFAD_DRIVER_NAME, bfad) != 0) { - /* Enable interrupt handler failed */ - return 1; - } + error = request_irq(bfad->pcidev->irq, (irq_handler_t)bfad_intx, + BFAD_IRQ_FLAGS, BFAD_DRIVER_NAME, bfad); + if (error) + return error; + bfad->bfad_flags |= BFAD_INTX_ON; - return error; + return 0; } void diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 8994fb8..023b9d4 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -26,7 +26,6 @@ int bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; - int rc = 0; unsigned long flags; spin_lock_irqsave(&bfad->bfad_lock, flags); @@ -34,7 +33,7 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd) if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) { spin_unlock_irqrestore(&bfad->bfad_lock, flags); iocmd->status = BFA_STATUS_OK; - return rc; + return 0; } init_completion(&bfad->enable_comp); @@ -43,21 +42,20 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd) spin_unlock_irqrestore(&bfad->bfad_lock, flags); wait_for_completion(&bfad->enable_comp); - return rc; + return 0; } int bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; - int rc = 0; unsigned long flags; spin_lock_irqsave(&bfad->bfad_lock, flags); if (bfa_ioc_is_disabled(&bfad->bfa.ioc)) { spin_unlock_irqrestore(&bfad->bfad_lock, flags); iocmd->status = BFA_STATUS_OK; - return rc; + return 0; } if (bfad->disable_active) { @@ -74,7 +72,7 @@ bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd) bfad->disable_active = BFA_FALSE; iocmd->status = BFA_STATUS_OK; - return rc; + return 0; } static int @@ -3270,13 +3268,13 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf, /* Allocate dma coherent memory */ buf_info = buf_base; buf_info->size = payload_len; - buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, buf_info->size, - &buf_info->phys, GFP_KERNEL); + buf_info->virt = dma_zalloc_coherent(&bfad->pcidev->dev, + buf_info->size, &buf_info->phys, + GFP_KERNEL); if (!buf_info->virt) goto out_free_mem; /* copy the linear bsg buffer to buf_info */ - memset(buf_info->virt, 0, buf_info->size); memcpy(buf_info->virt, payload_kbuf, buf_info->size); /* diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h index e1f1e34..fe2106c 100644 --- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h +++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h @@ -1,3 +1,16 @@ +/* 57xx_hsi_bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver. + * Handles operations such as session offload/upload etc, and manages + * session resources such as connection id and qp resources. + * + * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + */ + #ifndef __57XX_FCOE_HSI_LINUX_LE__ #define __57XX_FCOE_HSI_LINUX_LE__ diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig index cfcad8b..f245d54 100644 --- a/drivers/scsi/bnx2fc/Kconfig +++ b/drivers/scsi/bnx2fc/Kconfig @@ -1,5 +1,5 @@ config SCSI_BNX2X_FCOE - tristate "Broadcom NetXtreme II FCoE support" + tristate "QLogic NetXtreme II FCoE support" depends on PCI select NETDEVICES select ETHERNET @@ -8,5 +8,5 @@ config SCSI_BNX2X_FCOE select LIBFCOE select CNIC ---help--- - This driver supports FCoE offload for the Broadcom NetXtreme II + This driver supports FCoE offload for the QLogic NetXtreme II devices. diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 6a97665..1346e05 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -1,8 +1,7 @@ -#ifndef _BNX2FC_H_ -#define _BNX2FC_H_ -/* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver. +/* bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -11,6 +10,8 @@ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com) */ +#ifndef _BNX2FC_H_ +#define _BNX2FC_H_ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h> diff --git a/drivers/scsi/bnx2fc/bnx2fc_constants.h b/drivers/scsi/bnx2fc/bnx2fc_constants.h index dad9924..e147cc7 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_constants.h +++ b/drivers/scsi/bnx2fc/bnx2fc_constants.h @@ -1,3 +1,16 @@ +/* bnx2fc_constants.h: QLogic NetXtreme II Linux FCoE offload driver. + * Handles operations such as session offload/upload etc, and manages + * session resources such as connection id and qp resources. + * + * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + */ + #ifndef __BNX2FC_CONSTANTS_H_ #define __BNX2FC_CONSTANTS_H_ diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.c b/drivers/scsi/bnx2fc/bnx2fc_debug.c index 0cbee1b..d055df0 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_debug.c +++ b/drivers/scsi/bnx2fc/bnx2fc_debug.c @@ -1,3 +1,16 @@ +/* bnx2fc_debug.c: QLogic NetXtreme II Linux FCoE offload driver. + * Handles operations such as session offload/upload etc, and manages + * session resources such as connection id and qp resources. + * + * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + */ + #include "bnx2fc.h" void BNX2FC_IO_DBG(const struct bnx2fc_cmd *io_req, const char *fmt, ...) diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.h b/drivers/scsi/bnx2fc/bnx2fc_debug.h index 4808ff9..2b90067 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_debug.h +++ b/drivers/scsi/bnx2fc/bnx2fc_debug.h @@ -1,3 +1,16 @@ +/* bnx2fc_debug.h: QLogic NetXtreme II Linux FCoE offload driver. + * Handles operations such as session offload/upload etc, and manages + * session resources such as connection id and qp resources. + * + * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + */ + #ifndef __BNX2FC_DEBUG__ #define __BNX2FC_DEBUG__ diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c index b1c9a4f..ca75c7c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_els.c +++ b/drivers/scsi/bnx2fc/bnx2fc_els.c @@ -1,9 +1,10 @@ /* - * bnx2fc_els.c: Broadcom NetXtreme II Linux FCoE offload driver. + * bnx2fc_els.c: QLogic NetXtreme II Linux FCoE offload driver. * This file contains helper routines that handle ELS requests * and responses. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 785d0d7..79e5c94 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1,9 +1,10 @@ -/* bnx2fc_fcoe.c: Broadcom NetXtreme II Linux FCoE offload driver. +/* bnx2fc_fcoe.c: QLogic NetXtreme II Linux FCoE offload driver. * This file contains the code that interacts with libfc, libfcoe, * cnic modules to create FCoE instances, send/receive non-offloaded * FIP/FCoE packets, listen to link events etc. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,12 +27,12 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); static char version[] = - "Broadcom NetXtreme II FCoE Driver " DRV_MODULE_NAME \ + "QLogic NetXtreme II FCoE Driver " DRV_MODULE_NAME \ " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Bhanu Prakash Gollapudi <bprakash@broadcom.com>"); -MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 FCoE Driver"); +MODULE_DESCRIPTION("QLogic NetXtreme II BCM57710 FCoE Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); @@ -692,7 +693,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev) if (!lport->vport) fc_host_max_npiv_vports(lport->host) = USHRT_MAX; snprintf(fc_host_symbolic_name(lport->host), 256, - "%s (Broadcom %s) v%s over %s", + "%s (QLogic %s) v%s over %s", BNX2FC_NAME, hba->chip_num, BNX2FC_VERSION, interface->netdev->name); @@ -2775,7 +2776,7 @@ static struct fc_function_template bnx2fc_vport_xport_function = { */ static struct scsi_host_template bnx2fc_shost_template = { .module = THIS_MODULE, - .name = "Broadcom Offload FCoE Initiator", + .name = "QLogic Offload FCoE Initiator", .queuecommand = bnx2fc_queuecommand, .eh_abort_handler = bnx2fc_eh_abort, /* abts */ .eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */ diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index 512aed3..c6688d7 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -1,8 +1,9 @@ -/* bnx2fc_hwi.c: Broadcom NetXtreme II Linux FCoE offload driver. +/* bnx2fc_hwi.c: QLogic NetXtreme II Linux FCoE offload driver. * This file contains the code that low level functions that interact * with 57712 FCoE firmware. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 7bc47fc..4c5891e 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -1,7 +1,8 @@ -/* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver. +/* bnx2fc_io.c: QLogic NetXtreme II Linux FCoE offload driver. * IO manager and SCSI IO processing. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1450,9 +1451,9 @@ static void bnx2fc_lun_reset_cmpl(struct bnx2fc_cmd *io_req) struct scsi_cmnd *sc_cmd = io_req->sc_cmd; struct bnx2fc_rport *tgt = io_req->tgt; struct bnx2fc_cmd *cmd, *tmp; - int tm_lun = sc_cmd->device->lun; + u64 tm_lun = sc_cmd->device->lun; + u64 lun; int rc = 0; - int lun; /* called with tgt_lock held */ BNX2FC_IO_DBG(io_req, "Entered bnx2fc_lun_reset_cmpl\n"); diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c index 6870cf6..c66c708 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c +++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c @@ -1,8 +1,9 @@ -/* bnx2fc_tgt.c: Broadcom NetXtreme II Linux FCoE offload driver. +/* bnx2fc_tgt.c: QLogic NetXtreme II Linux FCoE offload driver. * Handles operations such as session offload/upload etc, and manages * session resources such as connection id and qp resources. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h index 3d33767..9175341 100644 --- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h +++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h @@ -1,13 +1,15 @@ -/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI +/* 57xx_iscsi_constants.h: QLogic NetXtreme II iSCSI HSI * * Copyright (c) 2006 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #ifndef __57XX_ISCSI_CONSTANTS_H_ #define __57XX_ISCSI_CONSTANTS_H_ diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h index 7052a83..19b3a97 100644 --- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h +++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h @@ -1,13 +1,15 @@ -/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI. +/* 57xx_iscsi_hsi.h: QLogic NetXtreme II iSCSI HSI. * * Copyright (c) 2006 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #ifndef __57XX_ISCSI_HSI_LINUX_LE__ #define __57XX_ISCSI_HSI_LINUX_LE__ diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig index 01cff18..44ce54e 100644 --- a/drivers/scsi/bnx2i/Kconfig +++ b/drivers/scsi/bnx2i/Kconfig @@ -1,5 +1,5 @@ config SCSI_BNX2_ISCSI - tristate "Broadcom NetXtreme II iSCSI support" + tristate "QLogic NetXtreme II iSCSI support" depends on NET depends on PCI select SCSI_ISCSI_ATTRS @@ -8,5 +8,5 @@ config SCSI_BNX2_ISCSI select NET_VENDOR_BROADCOM select CNIC ---help--- - This driver supports iSCSI offload for the Broadcom NetXtreme II + This driver supports iSCSI offload for the QLogic NetXtreme II devices. diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index c73bbcb..ed7f322 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h @@ -1,15 +1,17 @@ -/* bnx2i.h: Broadcom NetXtreme II iSCSI driver. +/* bnx2i.h: QLogic NetXtreme II iSCSI driver. * * Copyright (c) 2006 - 2013 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #ifndef _BNX2I_H_ diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index d6d491c..fb072cc 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1,15 +1,17 @@ -/* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver. +/* bnx2i_hwi.c: QLogic NetXtreme II iSCSI driver. * * Copyright (c) 2006 - 2013 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #include <linux/gfp.h> diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 80c03b4..c8b410c 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -1,15 +1,17 @@ -/* bnx2i.c: Broadcom NetXtreme II iSCSI driver. +/* bnx2i.c: QLogic NetXtreme II iSCSI driver. * * Copyright (c) 2006 - 2013 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #include "bnx2i.h" @@ -18,18 +20,18 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list); static u32 adapter_count; #define DRV_MODULE_NAME "bnx2i" -#define DRV_MODULE_VERSION "2.7.6.2" -#define DRV_MODULE_RELDATE "Jun 06, 2013" +#define DRV_MODULE_VERSION "2.7.10.1" +#define DRV_MODULE_RELDATE "Jul 16, 2014" static char version[] = - "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ + "QLogic NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and " "Eddie Wai <eddie.wai@broadcom.com>"); -MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712" +MODULE_DESCRIPTION("QLogic NetXtreme II BCM5706/5708/5709/57710/57711/57712" "/57800/57810/57840 iSCSI Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 166543f..40e2249 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1,16 +1,18 @@ /* - * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver. + * bnx2i_iscsi.c: QLogic NetXtreme II iSCSI driver. * * Copyright (c) 2006 - 2013 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #include <linux/slab.h> @@ -1643,12 +1645,11 @@ static void bnx2i_conn_get_stats(struct iscsi_cls_conn *cls_conn, stats->r2t_pdus = conn->r2t_pdus_cnt; stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt; stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; - stats->custom_length = 3; - strcpy(stats->custom[2].desc, "eh_abort_cnt"); - stats->custom[2].value = conn->eh_abort_cnt; stats->digest_err = 0; stats->timeout_err = 0; - stats->custom_length = 0; + strcpy(stats->custom[0].desc, "eh_abort_cnt"); + stats->custom[0].value = conn->eh_abort_cnt; + stats->custom_length = 1; } @@ -2249,7 +2250,7 @@ static umode_t bnx2i_attr_is_visible(int param_type, int param) */ static struct scsi_host_template bnx2i_host_template = { .module = THIS_MODULE, - .name = "Broadcom Offload iSCSI Initiator", + .name = "QLogic Offload iSCSI Initiator", .proc_name = "bnx2i", .queuecommand = iscsi_queuecommand, .eh_abort_handler = iscsi_eh_abort, diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c index a0a3d9f..6d56fd6 100644 --- a/drivers/scsi/bnx2i/bnx2i_sysfs.c +++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c @@ -1,13 +1,15 @@ -/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver. +/* bnx2i_sysfs.c: QLogic NetXtreme II iSCSI driver. * * Copyright (c) 2004 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #include "bnx2i.h" diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 2a32374..ef5ae0d 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -84,15 +84,19 @@ static const char * vendor_labels[CH_TYPES-4] = { }; // module_param_string_array(vendor_labels, NULL, 0444); +#define ch_printk(prefix, ch, fmt, a...) \ + sdev_printk(prefix, (ch)->device, "[%s] " fmt, \ + (ch)->name, ##a) + #define DPRINTK(fmt, arg...) \ do { \ if (debug) \ - printk(KERN_DEBUG "%s: " fmt, ch->name, ##arg); \ + ch_printk(KERN_DEBUG, ch, fmt, ##arg); \ } while (0) #define VPRINTK(level, fmt, arg...) \ do { \ if (verbose) \ - printk(level "%s: " fmt, ch->name, ##arg); \ + ch_printk(level, ch, fmt, ##arg); \ } while (0) /* ------------------------------------------------------------------- */ @@ -196,7 +200,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, __scsi_print_command(cmd); } - result = scsi_execute_req(ch->device, cmd, direction, buffer, + result = scsi_execute_req(ch->device, cmd, direction, buffer, buflength, &sshdr, timeout * HZ, MAX_RETRIES, NULL); @@ -247,7 +251,7 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data) retry: memset(cmd,0,sizeof(cmd)); cmd[0] = READ_ELEMENT_STATUS; - cmd[1] = (ch->device->lun << 5) | + cmd[1] = ((ch->device->lun & 0x7) << 5) | (ch->voltags ? 0x10 : 0) | ch_elem_to_typecode(ch,elem); cmd[2] = (elem >> 8) & 0xff; @@ -283,7 +287,7 @@ ch_init_elem(scsi_changer *ch) VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...\n"); memset(cmd,0,sizeof(cmd)); cmd[0] = INITIALIZE_ELEMENT_STATUS; - cmd[1] = ch->device->lun << 5; + cmd[1] = (ch->device->lun & 0x7) << 5; err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE); VPRINTK(KERN_INFO, "... finished\n"); return err; @@ -303,7 +307,7 @@ ch_readconfig(scsi_changer *ch) memset(cmd,0,sizeof(cmd)); cmd[0] = MODE_SENSE; - cmd[1] = ch->device->lun << 5; + cmd[1] = (ch->device->lun & 0x7) << 5; cmd[2] = 0x1d; cmd[4] = 255; result = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE); @@ -428,7 +432,7 @@ ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate) trans = ch->firsts[CHET_MT]; memset(cmd,0,sizeof(cmd)); cmd[0] = POSITION_TO_ELEMENT; - cmd[1] = ch->device->lun << 5; + cmd[1] = (ch->device->lun & 0x7) << 5; cmd[2] = (trans >> 8) & 0xff; cmd[3] = trans & 0xff; cmd[4] = (elem >> 8) & 0xff; @@ -447,7 +451,7 @@ ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate) trans = ch->firsts[CHET_MT]; memset(cmd,0,sizeof(cmd)); cmd[0] = MOVE_MEDIUM; - cmd[1] = ch->device->lun << 5; + cmd[1] = (ch->device->lun & 0x7) << 5; cmd[2] = (trans >> 8) & 0xff; cmd[3] = trans & 0xff; cmd[4] = (src >> 8) & 0xff; @@ -470,7 +474,7 @@ ch_exchange(scsi_changer *ch, u_int trans, u_int src, trans = ch->firsts[CHET_MT]; memset(cmd,0,sizeof(cmd)); cmd[0] = EXCHANGE_MEDIUM; - cmd[1] = ch->device->lun << 5; + cmd[1] = (ch->device->lun & 0x7) << 5; cmd[2] = (trans >> 8) & 0xff; cmd[3] = trans & 0xff; cmd[4] = (src >> 8) & 0xff; @@ -518,7 +522,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem, elem, tag); memset(cmd,0,sizeof(cmd)); cmd[0] = SEND_VOLUME_TAG; - cmd[1] = (ch->device->lun << 5) | + cmd[1] = ((ch->device->lun & 0x7) << 5) | ch_elem_to_typecode(ch,elem); cmd[2] = (elem >> 8) & 0xff; cmd[3] = elem & 0xff; @@ -754,7 +758,7 @@ static long ch_ioctl(struct file *file, voltag_retry: memset(ch_cmd, 0, sizeof(ch_cmd)); ch_cmd[0] = READ_ELEMENT_STATUS; - ch_cmd[1] = (ch->device->lun << 5) | + ch_cmd[1] = ((ch->device->lun & 0x7) << 5) | (ch->voltags ? 0x10 : 0) | ch_elem_to_typecode(ch,elem); ch_cmd[2] = (elem >> 8) & 0xff; @@ -924,8 +928,8 @@ static int ch_probe(struct device *dev) MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch, "s%s", ch->name); if (IS_ERR(class_dev)) { - printk(KERN_WARNING "ch%d: device_create failed\n", - ch->minor); + sdev_printk(KERN_WARNING, sd, "ch%d: device_create failed\n", + ch->minor); ret = PTR_ERR(class_dev); goto remove_idr; } diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c index 7494e4b..86103c8 100644 --- a/drivers/scsi/csiostor/csio_scsi.c +++ b/drivers/scsi/csiostor/csio_scsi.c @@ -1657,7 +1657,7 @@ csio_scsi_err_handler(struct csio_hw *hw, struct csio_ioreq *req) case FW_SCSI_UNDER_FLOW_ERR: csio_warn(hw, "Under-flow error,cmnd:0x%x expected" - " len:0x%x resid:0x%x lun:0x%x ssn:0x%x\n", + " len:0x%x resid:0x%x lun:0x%llx ssn:0x%x\n", cmnd->cmnd[0], scsi_bufflen(cmnd), scsi_get_resid(cmnd), cmnd->device->lun, rn->flowid); @@ -1957,7 +1957,7 @@ csio_eh_abort_handler(struct scsi_cmnd *cmnd) csio_dbg(hw, "Request to abort ioreq:%p cmd:%p cdb:%08llx" - " ssni:0x%x lun:%d iq:0x%x\n", + " ssni:0x%x lun:%llu iq:0x%x\n", ioreq, cmnd, *((uint64_t *)cmnd->cmnd), rn->flowid, cmnd->device->lun, csio_q_physiqid(hw, ioreq->iq_idx)); @@ -2015,13 +2015,13 @@ inval_scmnd: /* FW successfully aborted the request */ if (host_byte(cmnd->result) == DID_REQUEUE) { csio_info(hw, - "Aborted SCSI command to (%d:%d) serial#:0x%lx\n", + "Aborted SCSI command to (%d:%llu) serial#:0x%lx\n", cmnd->device->id, cmnd->device->lun, cmnd->serial_number); return SUCCESS; } else { csio_info(hw, - "Failed to abort SCSI command, (%d:%d) serial#:0x%lx\n", + "Failed to abort SCSI command, (%d:%llu) serial#:0x%lx\n", cmnd->device->id, cmnd->device->lun, cmnd->serial_number); return FAILED; @@ -2100,13 +2100,13 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) if (!rn) goto fail; - csio_dbg(hw, "Request to reset LUN:%d (ssni:0x%x tgtid:%d)\n", + csio_dbg(hw, "Request to reset LUN:%llu (ssni:0x%x tgtid:%d)\n", cmnd->device->lun, rn->flowid, rn->scsi_id); if (!csio_is_lnode_ready(ln)) { csio_err(hw, "LUN reset cannot be issued on non-ready" - " local node vnpi:0x%x (LUN:%d)\n", + " local node vnpi:0x%x (LUN:%llu)\n", ln->vnp_flowid, cmnd->device->lun); goto fail; } @@ -2126,7 +2126,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) if (fc_remote_port_chkready(rn->rport)) { csio_err(hw, "LUN reset cannot be issued on non-ready" - " remote node ssni:0x%x (LUN:%d)\n", + " remote node ssni:0x%x (LUN:%llu)\n", rn->flowid, cmnd->device->lun); goto fail; } @@ -2168,7 +2168,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) sld.level = CSIO_LEV_LUN; sld.lnode = ioreq->lnode; sld.rnode = ioreq->rnode; - sld.oslun = (uint64_t)cmnd->device->lun; + sld.oslun = cmnd->device->lun; spin_lock_irqsave(&hw->lock, flags); /* Kick off TM SM on the ioreq */ @@ -2190,7 +2190,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) /* LUN reset timed-out */ if (((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) == cmnd) { - csio_err(hw, "LUN reset (%d:%d) timed out\n", + csio_err(hw, "LUN reset (%d:%llu) timed out\n", cmnd->device->id, cmnd->device->lun); spin_lock_irq(&hw->lock); @@ -2203,7 +2203,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) /* LUN reset returned, check cached status */ if (cmnd->SCp.Status != FW_SUCCESS) { - csio_err(hw, "LUN reset failed (%d:%d), status: %d\n", + csio_err(hw, "LUN reset failed (%d:%llu), status: %d\n", cmnd->device->id, cmnd->device->lun, cmnd->SCp.Status); goto fail; } @@ -2223,7 +2223,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) /* Aborts may have timed out */ if (retval != 0) { csio_err(hw, - "Attempt to abort I/Os during LUN reset of %d" + "Attempt to abort I/Os during LUN reset of %llu" " returned %d\n", cmnd->device->lun, retval); /* Return I/Os back to active_q */ spin_lock_irq(&hw->lock); @@ -2234,7 +2234,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) CSIO_INC_STATS(rn, n_lun_rst); - csio_info(hw, "LUN reset occurred (%d:%d)\n", + csio_info(hw, "LUN reset occurred (%d:%llu)\n", cmnd->device->id, cmnd->device->lun); return SUCCESS; diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 3d5322d..d65df6d 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -283,7 +283,7 @@ void cxgbi_hbas_remove(struct cxgbi_device *cdev) } EXPORT_SYMBOL_GPL(cxgbi_hbas_remove); -int cxgbi_hbas_add(struct cxgbi_device *cdev, unsigned int max_lun, +int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun, unsigned int max_id, struct scsi_host_template *sht, struct scsi_transport_template *stt) { diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 8ad73d9..b3e6e75 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -709,7 +709,7 @@ void cxgbi_device_unregister(struct cxgbi_device *); void cxgbi_device_unregister_all(unsigned int flag); struct cxgbi_device *cxgbi_device_find_by_lldev(void *); struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *, int *); -int cxgbi_hbas_add(struct cxgbi_device *, unsigned int, unsigned int, +int cxgbi_hbas_add(struct cxgbi_device *, u64, unsigned int, struct scsi_host_template *, struct scsi_transport_template *); void cxgbi_hbas_remove(struct cxgbi_device *); diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 83d9bf6..0c6be0a 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -519,9 +519,7 @@ static struct ParameterData cfg_data[] = { CFG_PARAM_UNSET, 0, 0x2f, -#ifdef CONFIG_SCSI_MULTI_LUN - NAC_SCANLUN | -#endif + NAC_SCANLUN | NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET /*| NAC_ACTIVE_NEG*/, NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET | 0x08 @@ -1089,7 +1087,7 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)cmd->device->host->hostdata; dprintkdbg(DBG_0, "queue_command: (0x%p) <%02i-%i> cmnd=0x%02x\n", - cmd, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd, cmd->device->id, (u8)cmd->device->lun, cmd->cmnd[0]); /* Assume BAD_TARGET; will be cleared later */ cmd->result = DID_BAD_TARGET << 16; @@ -1104,7 +1102,7 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s /* does the specified lun on the specified device exist */ if (!(acb->dcb_map[cmd->device->id] & (1 << cmd->device->lun))) { dprintkl(KERN_INFO, "queue_command: Ignore target <%02i-%i>\n", - cmd->device->id, cmd->device->lun); + cmd->device->id, (u8)cmd->device->lun); goto complete; } @@ -1113,7 +1111,7 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s if (!dcb) { /* should never happen */ dprintkl(KERN_ERR, "queue_command: No such device <%02i-%i>", - cmd->device->id, cmd->device->lun); + cmd->device->id, (u8)cmd->device->lun); goto complete; } @@ -1209,7 +1207,7 @@ static void dump_register_info(struct AdapterCtlBlk *acb, "cmnd=0x%02x <%02i-%i>\n", srb, srb->cmd, srb->cmd->cmnd[0], srb->cmd->device->id, - srb->cmd->device->lun); + (u8)srb->cmd->device->lun); printk(" sglist=%p cnt=%i idx=%i len=%zu\n", srb->segment_x, srb->sg_count, srb->sg_index, srb->total_xfer_length); @@ -1304,7 +1302,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd) (struct AdapterCtlBlk *)cmd->device->host->hostdata; dprintkl(KERN_INFO, "eh_bus_reset: (0%p) target=<%02i-%i> cmd=%p\n", - cmd, cmd->device->id, cmd->device->lun, cmd); + cmd, cmd->device->id, (u8)cmd->device->lun, cmd); if (timer_pending(&acb->waiting_timer)) del_timer(&acb->waiting_timer); @@ -1371,7 +1369,7 @@ static int dc395x_eh_abort(struct scsi_cmnd *cmd) struct DeviceCtlBlk *dcb; struct ScsiReqBlk *srb; dprintkl(KERN_INFO, "eh_abort: (0x%p) target=<%02i-%i> cmd=%p\n", - cmd, cmd->device->id, cmd->device->lun, cmd); + cmd, cmd->device->id, (u8)cmd->device->lun, cmd); dcb = find_dcb(acb, cmd->device->id, cmd->device->lun); if (!dcb) { @@ -1607,7 +1605,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, dprintkl(KERN_WARNING, "start_scsi: (0x%p) " "Out of tags target=<%02i-%i>)\n", srb->cmd, srb->cmd->device->id, - srb->cmd->device->lun); + (u8)srb->cmd->device->lun); srb->state = SRB_READY; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_HWRESELECT); @@ -1625,7 +1623,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, /*polling:*/ /* Send CDB ..command block ......... */ dprintkdbg(DBG_KG, "start_scsi: (0x%p) <%02i-%i> cmnd=0x%02x tag=%i\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun, srb->cmd->cmnd[0], srb->tag_number); if (srb->flag & AUTO_REQSENSE) { DC395x_write8(acb, TRM_S1040_SCSI_FIFO, REQUEST_SENSE); @@ -2043,7 +2041,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 scsi_status = *pscsi_status; u32 d_left_counter = 0; dprintkdbg(DBG_0, "data_out_phase0: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); /* * KG: We need to drain the buffers before we draw any conclusions! @@ -2173,7 +2171,7 @@ static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "data_out_phase1: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); clear_fifo(acb, "data_out_phase1"); /* do prepare before transfer when data out phase */ data_io_transfer(acb, srb, XFERDATAOUT); @@ -2185,7 +2183,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 scsi_status = *pscsi_status; dprintkdbg(DBG_0, "data_in_phase0: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); /* * KG: DataIn is much more tricky than DataOut. When the device is finished @@ -2396,7 +2394,7 @@ static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "data_in_phase1: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); data_io_transfer(acb, srb, XFERDATAIN); } @@ -2408,7 +2406,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, u8 bval; dprintkdbg(DBG_0, "data_io_transfer: (0x%p) <%02i-%i> %c len=%i, sg=(%i/%i)\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun, ((io_dir & DMACMD_DIR) ? 'r' : 'w'), srb->total_xfer_length, srb->sg_index, srb->sg_count); if (srb == acb->tmp_srb) @@ -2581,7 +2579,7 @@ static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "status_phase0: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); /* get message */ srb->state = SRB_COMPLETED; @@ -2595,7 +2593,7 @@ static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "status_phase1: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); srb->state = SRB_STATUS; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_COMP); @@ -3320,7 +3318,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, int ckc_only = 1; dprintkdbg(DBG_1, "srb_done: (0x%p) <%02i-%i>\n", srb->cmd, - srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->device->id, (u8)srb->cmd->device->lun); dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n", srb, scsi_sg_count(cmd), srb->sg_index, srb->sg_count, scsi_sgtalbe(cmd)); @@ -3500,7 +3498,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, if (srb->total_xfer_length) dprintkdbg(DBG_KG, "srb_done: (0x%p) <%02i-%i> " "cmnd=0x%02x Missed %i bytes\n", - cmd, cmd->device->id, cmd->device->lun, + cmd, cmd->device->id, (u8)cmd->device->lun, cmd->cmnd[0], srb->total_xfer_length); } @@ -3540,7 +3538,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, dir = p->sc_data_direction; result = MK_RES(0, did_flag, 0, 0); printk("G:%p(%02i-%i) ", p, - p->device->id, p->device->lun); + p->device->id, (u8)p->device->lun); srb_going_remove(dcb, srb); free_tag(dcb, srb); srb_free_insert(acb, srb); @@ -3570,7 +3568,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, result = MK_RES(0, did_flag, 0, 0); printk("W:%p<%02i-%i>", p, p->device->id, - p->device->lun); + (u8)p->device->lun); srb_waiting_remove(dcb, srb); srb_free_insert(acb, srb); p->result = result; @@ -3679,7 +3677,7 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, { struct scsi_cmnd *cmd = srb->cmd; dprintkdbg(DBG_1, "request_sense: (0x%p) <%02i-%i>\n", - cmd, cmd->device->id, cmd->device->lun); + cmd, cmd->device->id, (u8)cmd->device->lun); srb->flag |= AUTO_REQSENSE; srb->adapter_status = 0; @@ -4434,15 +4432,10 @@ static void adapter_init_scsi_host(struct Scsi_Host *host) if (host->max_id - 1 == eeprom->scsi_id) host->max_id--; -#ifdef CONFIG_SCSI_MULTI_LUN if (eeprom->channel_cfg & NAC_SCANLUN) host->max_lun = 8; else host->max_lun = 1; -#else - host->max_lun = 1; -#endif - } @@ -4645,7 +4638,7 @@ static int dc395x_show_info(struct seq_file *m, struct Scsi_Host *host) SPRINTF("irq_level 0x%04x, ", acb->irq_level); SPRINTF(" SelTimeout %ims\n", (1638 * acb->sel_timeout) / 1000); - SPRINTF("MaxID %i, MaxLUN %i, ", host->max_id, host->max_lun); + SPRINTF("MaxID %i, MaxLUN %llu, ", host->max_id, host->max_lun); SPRINTF("AdapterID %i\n", host->this_id); SPRINTF("tag_max_num %i", acb->tag_max_num); diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index c0ae8fa..67283ef 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -459,7 +459,7 @@ static int adpt_queue_lck(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd * to the device structure. This should be a TEST_UNIT_READY * command from scan_scsis_single. */ - if ((pDev = adpt_find_device(pHba, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun)) == NULL) { + if ((pDev = adpt_find_device(pHba, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun)) == NULL) { // TODO: if any luns are at this bus, scsi id then fake a TEST_UNIT_READY and INQUIRY response // with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue. cmd->result = (DID_NO_CONNECT << 16); @@ -579,8 +579,8 @@ static int adpt_show_info(struct seq_file *m, struct Scsi_Host *host) seq_printf(m," Rev: %-8.8s\n", d->pScsi_dev->rev); unit = d->pI2o_dev->lct_data.tid; - seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d) (%s)\n\n", - unit, (int)d->scsi_channel, (int)d->scsi_id, (int)d->scsi_lun, + seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%llu) (%s)\n\n", + unit, (int)d->scsi_channel, (int)d->scsi_id, d->scsi_lun, scsi_device_online(d->pScsi_dev)? "online":"offline"); d = d->next_lun; } @@ -1162,7 +1162,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) } } -static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun) +static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun) { struct adpt_device* d; @@ -1462,7 +1462,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba) i2o_lct *lct = pHba->lct; u8 bus_no = 0; s16 scsi_id; - s16 scsi_lun; + u64 scsi_lun; u32 buf[10]; // larger than 7, or 8 ... struct adpt_device* pDev; @@ -1496,7 +1496,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba) } bus_no = buf[0]>>16; scsi_id = buf[1]; - scsi_lun = (buf[2]>>8 )&0xff; + scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]); if(bus_no >= MAX_CHANNEL) { // Something wrong skip it printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no); continue; @@ -1571,7 +1571,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba) if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)>=0) { bus_no = buf[0]>>16; scsi_id = buf[1]; - scsi_lun = (buf[2]>>8 )&0xff; + scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]); if(bus_no >= MAX_CHANNEL) { // Something wrong skip it continue; } @@ -2407,8 +2407,8 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) case I2O_SCSI_DSC_COMMAND_TIMEOUT: case I2O_SCSI_DSC_NO_ADAPTER: case I2O_SCSI_DSC_RESOURCE_UNAVAILABLE: - printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%d) hba status=0x%x, dev status=0x%x, cmd=0x%x\n", - pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]); + printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%llu) hba status=0x%x, dev status=0x%x, cmd=0x%x\n", + pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]); cmd->result = (DID_TIME_OUT << 16); break; case I2O_SCSI_DSC_ADAPTER_BUSY: @@ -2447,8 +2447,8 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) case I2O_SCSI_DSC_QUEUE_FROZEN: case I2O_SCSI_DSC_REQUEST_INVALID: default: - printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", - pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, + printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", + pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]); cmd->result = (DID_ERROR << 16); break; @@ -2464,8 +2464,8 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) cmd->sense_buffer[2] == DATA_PROTECT ){ /* This is to handle an array failed */ cmd->result = (DID_TIME_OUT << 16); - printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", - pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, + printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", + pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]); } @@ -2476,8 +2476,8 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) * for a limitted number of retries. */ cmd->result = (DID_TIME_OUT << 16); - printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%d) tid=%d, cmd=0x%x\n", - pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, + printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%llu) tid=%d, cmd=0x%x\n", + pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, ((struct adpt_device*)(cmd->device->hostdata))->tid, cmd->cmnd[0]); } @@ -2517,7 +2517,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) i2o_lct *lct = pHba->lct; u8 bus_no = 0; s16 scsi_id; - s16 scsi_lun; + u64 scsi_lun; u32 buf[10]; // at least 8 u32's struct adpt_device* pDev = NULL; struct i2o_device* pI2o_dev = NULL; @@ -2564,7 +2564,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) } scsi_id = buf[1]; - scsi_lun = (buf[2]>>8 )&0xff; + scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]); pDev = pHba->channel[bus_no].device[scsi_id]; /* da lun */ while(pDev) { @@ -2633,7 +2633,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) while(pDev) { if(pDev->scsi_lun == scsi_lun) { if(!scsi_device_online(pDev->pScsi_dev)) { - printk(KERN_WARNING"%s: Setting device (%d,%d,%d) back online\n", + printk(KERN_WARNING"%s: Setting device (%d,%d,%llu) back online\n", pHba->name,bus_no,scsi_id,scsi_lun); if (pDev->pScsi_dev) { scsi_device_set_state(pDev->pScsi_dev, SDEV_RUNNING); @@ -2665,7 +2665,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) // in the LCT table if (pDev->state & DPTI_DEV_UNSCANNED){ pDev->state = DPTI_DEV_OFFLINE; - printk(KERN_WARNING"%s: Device (%d,%d,%d) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun); + printk(KERN_WARNING"%s: Device (%d,%d,%llu) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun); if (pDev->pScsi_dev) { scsi_device_set_state(pDev->pScsi_dev, SDEV_OFFLINE); } diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index aeb0461..1fa345a 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -184,7 +184,7 @@ struct adpt_device { u32 block_size; u8 scsi_channel; u8 scsi_id; - u8 scsi_lun; + u64 scsi_lun; u8 state; u16 tid; struct i2o_device* pI2o_dev; @@ -231,7 +231,7 @@ typedef struct _adpt_hba { u32 sg_tablesize; // Scatter/Gather List Size. u8 top_scsi_channel; u8 top_scsi_id; - u8 top_scsi_lun; + u64 top_scsi_lun; u8 dma64; i2o_status_block* status_block; @@ -300,7 +300,7 @@ 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, u32 lun); +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); static void adpt_i2o_post_wait_complete(u32, int); diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index ebf5736..03372cf 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -1399,7 +1399,7 @@ static int port_detect(unsigned long port_base, unsigned int j, if (shost->max_id > 8 || shost->max_lun > 8) printk - ("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", + ("%s: wide SCSI support enabled, max_id %u, max_lun %llu.\n", ha->board_name, shost->max_id, shost->max_lun); for (i = 0; i <= shost->max_channel; i++) @@ -2449,7 +2449,7 @@ static irqreturn_t ihdlr(struct Scsi_Host *shost) "target_status 0x%x, sense key 0x%x.\n", ha->board_name, SCpnt->device->channel, SCpnt->device->id, - SCpnt->device->lun, + (u8)SCpnt->device->lun, spp->target_status, SCpnt->sense_buffer[2]); ha->target_to[SCpnt->device->id][SCpnt->device->channel] = 0; diff --git a/drivers/scsi/fnic/fnic_isr.c b/drivers/scsi/fnic/fnic_isr.c index 7d9b54a..a0dd1b6 100644 --- a/drivers/scsi/fnic/fnic_isr.c +++ b/drivers/scsi/fnic/fnic_isr.c @@ -257,8 +257,8 @@ int fnic_set_intr_mode(struct fnic *fnic) fnic->raw_wq_count >= m && fnic->wq_copy_count >= o && fnic->cq_count >= n + m + o) { - if (!pci_enable_msix(fnic->pdev, fnic->msix_entry, - n + m + o + 1)) { + if (!pci_enable_msix_exact(fnic->pdev, fnic->msix_entry, + n + m + o + 1)) { fnic->rq_count = n; fnic->raw_wq_count = m; fnic->wq_copy_count = o; diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index ea28b5c..961bdf5 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -1753,7 +1753,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) tag = sc->request->tag; FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, - "Abort Cmd called FCID 0x%x, LUN 0x%x TAG %x flags %x\n", + "Abort Cmd called FCID 0x%x, LUN 0x%llx TAG %x flags %x\n", rport->port_id, sc->device->lun, tag, CMD_FLAGS(sc)); CMD_FLAGS(sc) = FNIC_NO_FLAGS; @@ -2207,7 +2207,7 @@ int fnic_device_reset(struct scsi_cmnd *sc) rport = starget_to_rport(scsi_target(sc->device)); FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, - "Device reset called FCID 0x%x, LUN 0x%x sc 0x%p\n", + "Device reset called FCID 0x%x, LUN 0x%llx sc 0x%p\n", rport->port_id, sc->device->lun, sc); if (lp->state != LPORT_ST_READY || !(lp->link_up)) @@ -2224,6 +2224,22 @@ int fnic_device_reset(struct scsi_cmnd *sc) tag = sc->request->tag; if (unlikely(tag < 0)) { + /* + * XXX(hch): current the midlayer fakes up a struct + * request for the explicit reset ioctls, and those + * don't have a tag allocated to them. The below + * code pokes into midlayer structures to paper over + * this design issue, but that won't work for blk-mq. + * + * Either someone who can actually test the hardware + * will have to come up with a similar hack for the + * blk-mq case, or we'll have to bite the bullet and + * fix the way the EH ioctls work for real, but until + * that happens we fail these explicit requests here. + */ + if (shost_use_blk_mq(sc->device->host)) + goto fnic_device_reset_end; + tag = fnic_scsi_host_start_tag(fnic, sc); if (unlikely(tag == SCSI_NO_TAG)) goto fnic_device_reset_end; diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index a1bc8ca9..b331272 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -768,7 +768,7 @@ static void sprint_command(struct seq_file *m, unsigned char *command) static void sprint_Scsi_Cmnd(struct seq_file *m, Scsi_Cmnd * cmd) { - PRINTP("host number %d destination target %d, lun %d\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun); + PRINTP("host number %d destination target %d, lun %llu\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun); PRINTP(" command = "); sprint_command(m, cmd->cmnd); } diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 3cbb57a..6de80e3 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -204,18 +204,33 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, struct scsi_host_template *sht = shost->hostt; int error = -EINVAL; - printk(KERN_INFO "scsi%d : %s\n", shost->host_no, + shost_printk(KERN_INFO, shost, "%s\n", sht->info ? sht->info(shost) : sht->name); if (!shost->can_queue) { - printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", - sht->name); + shost_printk(KERN_ERR, shost, + "can_queue = 0 no longer supported\n"); goto fail; } + if (shost_use_blk_mq(shost)) { + error = scsi_mq_setup_tags(shost); + if (error) + goto fail; + } + + /* + * Note that we allocate the freelist even for the MQ case for now, + * as we need a command set aside for scsi_reset_provider. Having + * the full host freelist and one command available for that is a + * little heavy-handed, but avoids introducing a special allocator + * just for this. Eventually the structure of scsi_reset_provider + * will need a major overhaul. + */ error = scsi_setup_command_freelist(shost); if (error) - goto fail; + goto out_destroy_tags; + if (!shost->shost_gendev.parent) shost->shost_gendev.parent = dev ? dev : &platform_bus; @@ -226,7 +241,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, error = device_add(&shost->shost_gendev); if (error) - goto out; + goto out_destroy_freelist; pm_runtime_set_active(&shost->shost_gendev); pm_runtime_enable(&shost->shost_gendev); @@ -279,8 +294,11 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, device_del(&shost->shost_dev); out_del_gendev: device_del(&shost->shost_gendev); - out: + out_destroy_freelist: scsi_destroy_command_freelist(shost); + out_destroy_tags: + if (shost_use_blk_mq(shost)) + scsi_mq_destroy_tags(shost); fail: return error; } @@ -309,8 +327,13 @@ static void scsi_host_dev_release(struct device *dev) } scsi_destroy_command_freelist(shost); - if (shost->bqt) - blk_free_tags(shost->bqt); + if (shost_use_blk_mq(shost)) { + if (shost->tag_set.tags) + scsi_mq_destroy_tags(shost); + } else { + if (shost->bqt) + blk_free_tags(shost->bqt); + } kfree(shost->shost_data); @@ -436,6 +459,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) else shost->dma_boundary = 0xffffffff; + shost->use_blk_mq = scsi_use_blk_mq && !shost->hostt->disable_blk_mq; + device_initialize(&shost->shost_gendev); dev_set_name(&shost->shost_gendev, "host%d", shost->host_no); shost->shost_gendev.bus = &scsi_bus_type; @@ -450,8 +475,9 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->ehandler = kthread_run(scsi_error_handler, shost, "scsi_eh_%d", shost->host_no); if (IS_ERR(shost->ehandler)) { - printk(KERN_WARNING "scsi%d: error handler thread failed to spawn, error = %ld\n", - shost->host_no, PTR_ERR(shost->ehandler)); + shost_printk(KERN_WARNING, shost, + "error handler thread failed to spawn, error = %ld\n", + PTR_ERR(shost->ehandler)); goto fail_kfree; } @@ -584,7 +610,7 @@ EXPORT_SYMBOL(scsi_is_host_device); int scsi_queue_work(struct Scsi_Host *shost, struct work_struct *work) { if (unlikely(!shost->work_q)) { - printk(KERN_ERR + shost_printk(KERN_ERR, shost, "ERROR: Scsi host '%s' attempted to queue scsi-work, " "when no workqueue created.\n", shost->hostt->name); dump_stack(); @@ -603,7 +629,7 @@ EXPORT_SYMBOL_GPL(scsi_queue_work); void scsi_flush_work(struct Scsi_Host *shost) { if (!shost->work_q) { - printk(KERN_ERR + shost_printk(KERN_ERR, shost, "ERROR: Scsi host '%s' attempted to flush scsi-work, " "when no workqueue created.\n", shost->hostt->name); dump_stack(); diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 31184b3..8545d18 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1708,7 +1708,14 @@ static void complete_scsi_command(struct CommandList *cp) cmd->result |= ei->ScsiStatus; - /* copy the sense data whether we need to or not. */ + scsi_set_resid(cmd, ei->ResidualCnt); + if (ei->CommandStatus == 0) { + cmd_free(h, cp); + cmd->scsi_done(cmd); + return; + } + + /* copy the sense data */ if (SCSI_SENSE_BUFFERSIZE < sizeof(ei->SenseInfo)) sense_data_size = SCSI_SENSE_BUFFERSIZE; else @@ -1717,13 +1724,6 @@ static void complete_scsi_command(struct CommandList *cp) sense_data_size = ei->SenseLen; memcpy(cmd->sense_buffer, ei->SenseInfo, sense_data_size); - scsi_set_resid(cmd, ei->ResidualCnt); - - if (ei->CommandStatus == 0) { - cmd_free(h, cp); - cmd->scsi_done(cmd); - return; - } /* For I/O accelerator commands, copy over some fields to the normal * CISS header used below for error handling. @@ -3686,6 +3686,8 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, (((u64) cmd->cmnd[2]) << 8) | cmd->cmnd[3]; block_cnt = cmd->cmnd[4]; + if (block_cnt == 0) + block_cnt = 256; break; case WRITE_10: is_write = 1; @@ -3734,7 +3736,6 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, default: return IO_ACCEL_INELIGIBLE; /* process via normal I/O path */ } - BUG_ON(block_cnt == 0); last_block = first_block + block_cnt - 1; /* check for write to non-RAID-0 */ @@ -4590,7 +4591,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc) return FAILED; memset(msg, 0, sizeof(msg)); - ml += sprintf(msg+ml, "ABORT REQUEST on C%d:B%d:T%d:L%d ", + ml += sprintf(msg+ml, "ABORT REQUEST on C%d:B%d:T%d:L%llu ", h->scsi_host->host_no, sc->device->channel, sc->device->id, sc->device->lun); @@ -5092,7 +5093,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) } if (ioc->Request.Type.Direction & XFER_WRITE) { if (copy_from_user(buff[sg_used], data_ptr, sz)) { - status = -ENOMEM; + status = -EFAULT; goto cleanup1; } } else @@ -6365,9 +6366,9 @@ static inline void hpsa_set_driver_support_bits(struct ctlr_info *h) { u32 driver_support; -#ifdef CONFIG_X86 - /* Need to enable prefetch in the SCSI core for 6400 in x86 */ driver_support = readl(&(h->cfgtable->driver_support)); + /* Need to enable prefetch in the SCSI core for 6400 in x86 */ +#ifdef CONFIG_X86 driver_support |= ENABLE_SCSI_PREFETCH; #endif driver_support |= ENABLE_UNIT_ATTN; @@ -6913,8 +6914,12 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h) d = list_entry(this, struct offline_device_entry, offline_list); spin_unlock_irqrestore(&h->offline_device_lock, flags); - if (!hpsa_volume_offline(h, d->scsi3addr)) + if (!hpsa_volume_offline(h, d->scsi3addr)) { + spin_lock_irqsave(&h->offline_device_lock, flags); + list_del(&d->offline_list); + spin_unlock_irqrestore(&h->offline_device_lock, flags); return 1; + } spin_lock_irqsave(&h->offline_device_lock, flags); } spin_unlock_irqrestore(&h->offline_device_lock, flags); @@ -6995,8 +7000,10 @@ reinit_after_soft_reset: /* Allocate and clear per-cpu variable lockup_detected */ h->lockup_detected = alloc_percpu(u32); - if (!h->lockup_detected) + if (!h->lockup_detected) { + rc = -ENOMEM; goto clean1; + } set_lockup_detected_for_all_cpus(h, 0); rc = hpsa_pci_init(h); diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index ee196b3..dedb62c 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1024,7 +1024,7 @@ static int hptiop_queuecommand_lck(struct scsi_cmnd *scp, _req->scp = scp; - dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%08x-%08x-%08x-%08x) " + dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%llu cdb=(%08x-%08x-%08x-%08x) " "req_index=%d, req=%p\n", scp, host->host_no, scp->device->channel, diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile index cb150d1..3840c64 100644 --- a/drivers/scsi/ibmvscsi/Makefile +++ b/drivers/scsi/ibmvscsi/Makefile @@ -1,3 +1,2 @@ obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi.o -obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o obj-$(CONFIG_SCSI_IBMVFC) += ibmvfc.o diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 8dd4768..598c42c 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -46,7 +46,7 @@ static unsigned int init_timeout = IBMVFC_INIT_TIMEOUT; static unsigned int default_timeout = IBMVFC_DEFAULT_TIMEOUT; -static unsigned int max_lun = IBMVFC_MAX_LUN; +static u64 max_lun = IBMVFC_MAX_LUN; static unsigned int max_targets = IBMVFC_MAX_TARGETS; static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT; static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS; @@ -71,7 +71,7 @@ MODULE_PARM_DESC(default_timeout, module_param_named(max_requests, max_requests, uint, S_IRUGO); MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter. " "[Default=" __stringify(IBMVFC_MAX_REQUESTS_DEFAULT) "]"); -module_param_named(max_lun, max_lun, uint, S_IRUGO); +module_param_named(max_lun, max_lun, ullong, S_IRUGO); MODULE_PARM_DESC(max_lun, "Maximum allowed LUN. " "[Default=" __stringify(IBMVFC_MAX_LUN) "]"); module_param_named(max_targets, max_targets, uint, S_IRUGO); @@ -166,13 +166,13 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt) switch (entry->fmt) { case IBMVFC_CMD_FORMAT: entry->op_code = vfc_cmd->iu.cdb[0]; - entry->scsi_id = vfc_cmd->tgt_scsi_id; + entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id); entry->lun = scsilun_to_int(&vfc_cmd->iu.lun); entry->tmf_flags = vfc_cmd->iu.tmf_flags; - entry->u.start.xfer_len = vfc_cmd->iu.xfer_len; + entry->u.start.xfer_len = be32_to_cpu(vfc_cmd->iu.xfer_len); break; case IBMVFC_MAD_FORMAT: - entry->op_code = mad->opcode; + entry->op_code = be32_to_cpu(mad->opcode); break; default: break; @@ -199,18 +199,18 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt) switch (entry->fmt) { case IBMVFC_CMD_FORMAT: entry->op_code = vfc_cmd->iu.cdb[0]; - entry->scsi_id = vfc_cmd->tgt_scsi_id; + entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id); entry->lun = scsilun_to_int(&vfc_cmd->iu.lun); entry->tmf_flags = vfc_cmd->iu.tmf_flags; - entry->u.end.status = vfc_cmd->status; - entry->u.end.error = vfc_cmd->error; + entry->u.end.status = be16_to_cpu(vfc_cmd->status); + entry->u.end.error = be16_to_cpu(vfc_cmd->error); entry->u.end.fcp_rsp_flags = vfc_cmd->rsp.flags; entry->u.end.rsp_code = vfc_cmd->rsp.data.info.rsp_code; entry->u.end.scsi_status = vfc_cmd->rsp.scsi_status; break; case IBMVFC_MAD_FORMAT: - entry->op_code = mad->opcode; - entry->u.end.status = mad->status; + entry->op_code = be32_to_cpu(mad->opcode); + entry->u.end.status = be16_to_cpu(mad->status); break; default: break; @@ -270,14 +270,14 @@ static int ibmvfc_get_err_result(struct ibmvfc_cmd *vfc_cmd) { int err; struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; - int fc_rsp_len = rsp->fcp_rsp_len; + int fc_rsp_len = be32_to_cpu(rsp->fcp_rsp_len); if ((rsp->flags & FCP_RSP_LEN_VALID) && ((fc_rsp_len && fc_rsp_len != 4 && fc_rsp_len != 8) || rsp->data.info.rsp_code)) return DID_ERROR << 16; - err = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error); + err = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error)); if (err >= 0) return rsp->scsi_status | (cmd_status[err].result << 16); return rsp->scsi_status | (DID_ERROR << 16); @@ -807,7 +807,7 @@ static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code) evt->cmnd->result = (error_code << 16); evt->done = ibmvfc_scsi_eh_done; } else - evt->xfer_iu->mad_common.status = IBMVFC_MAD_DRIVER_FAILED; + evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_DRIVER_FAILED); list_del(&evt->queue); del_timer(&evt->timer); @@ -955,7 +955,7 @@ static void ibmvfc_get_host_speed(struct Scsi_Host *shost) spin_lock_irqsave(shost->host_lock, flags); if (vhost->state == IBMVFC_ACTIVE) { - switch (vhost->login_buf->resp.link_speed / 100) { + switch (be64_to_cpu(vhost->login_buf->resp.link_speed) / 100) { case 1: fc_host_speed(shost) = FC_PORTSPEED_1GBIT; break; @@ -976,7 +976,7 @@ static void ibmvfc_get_host_speed(struct Scsi_Host *shost) break; default: ibmvfc_log(vhost, 3, "Unknown port speed: %lld Gbit\n", - vhost->login_buf->resp.link_speed / 100); + be64_to_cpu(vhost->login_buf->resp.link_speed) / 100); fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; break; } @@ -1171,21 +1171,21 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost) memset(login_info, 0, sizeof(*login_info)); - login_info->ostype = IBMVFC_OS_LINUX; - login_info->max_dma_len = IBMVFC_MAX_SECTORS << 9; - login_info->max_payload = sizeof(struct ibmvfc_fcp_cmd_iu); - login_info->max_response = sizeof(struct ibmvfc_fcp_rsp); - login_info->partition_num = vhost->partition_number; - login_info->vfc_frame_version = 1; - login_info->fcp_version = 3; - login_info->flags = IBMVFC_FLUSH_ON_HALT; + login_info->ostype = cpu_to_be32(IBMVFC_OS_LINUX); + login_info->max_dma_len = cpu_to_be64(IBMVFC_MAX_SECTORS << 9); + login_info->max_payload = cpu_to_be32(sizeof(struct ibmvfc_fcp_cmd_iu)); + login_info->max_response = cpu_to_be32(sizeof(struct ibmvfc_fcp_rsp)); + login_info->partition_num = cpu_to_be32(vhost->partition_number); + login_info->vfc_frame_version = cpu_to_be32(1); + login_info->fcp_version = cpu_to_be16(3); + login_info->flags = cpu_to_be16(IBMVFC_FLUSH_ON_HALT); if (vhost->client_migrated) - login_info->flags |= IBMVFC_CLIENT_MIGRATED; + login_info->flags |= cpu_to_be16(IBMVFC_CLIENT_MIGRATED); - login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ; - login_info->capabilities = IBMVFC_CAN_MIGRATE; - login_info->async.va = vhost->async_crq.msg_token; - login_info->async.len = vhost->async_crq.size * sizeof(*vhost->async_crq.msgs); + login_info->max_cmds = cpu_to_be32(max_requests + IBMVFC_NUM_INTERNAL_REQ); + login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE); + login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token); + login_info->async.len = cpu_to_be32(vhost->async_crq.size * sizeof(*vhost->async_crq.msgs)); strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME); strncpy(login_info->device_name, dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME); @@ -1225,7 +1225,7 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost) struct ibmvfc_event *evt = &pool->events[i]; atomic_set(&evt->free, 1); evt->crq.valid = 0x80; - evt->crq.ioba = pool->iu_token + (sizeof(*evt->xfer_iu) * i); + evt->crq.ioba = cpu_to_be64(pool->iu_token + (sizeof(*evt->xfer_iu) * i)); evt->xfer_iu = pool->iu_storage + i; evt->vhost = vhost; evt->ext_list = NULL; @@ -1310,8 +1310,8 @@ static void ibmvfc_map_sg_list(struct scsi_cmnd *scmd, int nseg, struct scatterlist *sg; scsi_for_each_sg(scmd, sg, nseg, i) { - md[i].va = sg_dma_address(sg); - md[i].len = sg_dma_len(sg); + md[i].va = cpu_to_be64(sg_dma_address(sg)); + md[i].len = cpu_to_be32(sg_dma_len(sg)); md[i].key = 0; } } @@ -1337,7 +1337,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, sg_mapped = scsi_dma_map(scmd); if (!sg_mapped) { - vfc_cmd->flags |= IBMVFC_NO_MEM_DESC; + vfc_cmd->flags |= cpu_to_be16(IBMVFC_NO_MEM_DESC); return 0; } else if (unlikely(sg_mapped < 0)) { if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) @@ -1346,10 +1346,10 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, } if (scmd->sc_data_direction == DMA_TO_DEVICE) { - vfc_cmd->flags |= IBMVFC_WRITE; + vfc_cmd->flags |= cpu_to_be16(IBMVFC_WRITE); vfc_cmd->iu.add_cdb_len |= IBMVFC_WRDATA; } else { - vfc_cmd->flags |= IBMVFC_READ; + vfc_cmd->flags |= cpu_to_be16(IBMVFC_READ); vfc_cmd->iu.add_cdb_len |= IBMVFC_RDDATA; } @@ -1358,7 +1358,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, return 0; } - vfc_cmd->flags |= IBMVFC_SCATTERLIST; + vfc_cmd->flags |= cpu_to_be16(IBMVFC_SCATTERLIST); if (!evt->ext_list) { evt->ext_list = dma_pool_alloc(vhost->sg_pool, GFP_ATOMIC, @@ -1374,8 +1374,8 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, ibmvfc_map_sg_list(scmd, sg_mapped, evt->ext_list); - data->va = evt->ext_list_token; - data->len = sg_mapped * sizeof(struct srp_direct_buf); + data->va = cpu_to_be64(evt->ext_list_token); + data->len = cpu_to_be32(sg_mapped * sizeof(struct srp_direct_buf)); data->key = 0; return 0; } @@ -1404,15 +1404,15 @@ static void ibmvfc_timeout(struct ibmvfc_event *evt) static int ibmvfc_send_event(struct ibmvfc_event *evt, struct ibmvfc_host *vhost, unsigned long timeout) { - u64 *crq_as_u64 = (u64 *) &evt->crq; + __be64 *crq_as_u64 = (__be64 *) &evt->crq; int rc; /* Copy the IU into the transfer area */ *evt->xfer_iu = evt->iu; if (evt->crq.format == IBMVFC_CMD_FORMAT) - evt->xfer_iu->cmd.tag = (u64)evt; + evt->xfer_iu->cmd.tag = cpu_to_be64((u64)evt); else if (evt->crq.format == IBMVFC_MAD_FORMAT) - evt->xfer_iu->mad_common.tag = (u64)evt; + evt->xfer_iu->mad_common.tag = cpu_to_be64((u64)evt); else BUG(); @@ -1428,7 +1428,8 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt, mb(); - if ((rc = ibmvfc_send_crq(vhost, crq_as_u64[0], crq_as_u64[1]))) { + if ((rc = ibmvfc_send_crq(vhost, be64_to_cpu(crq_as_u64[0]), + be64_to_cpu(crq_as_u64[1])))) { list_del(&evt->queue); del_timer(&evt->timer); @@ -1451,7 +1452,7 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt, evt->cmnd->result = DID_ERROR << 16; evt->done = ibmvfc_scsi_eh_done; } else - evt->xfer_iu->mad_common.status = IBMVFC_MAD_CRQ_ERROR; + evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_CRQ_ERROR); evt->done(evt); } else @@ -1472,7 +1473,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt) struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; struct scsi_cmnd *cmnd = evt->cmnd; const char *err = unknown_error; - int index = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error); + int index = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error)); int logerr = 0; int rsp_code = 0; @@ -1526,13 +1527,13 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt) struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; struct scsi_cmnd *cmnd = evt->cmnd; u32 rsp_len = 0; - u32 sense_len = rsp->fcp_sense_len; + u32 sense_len = be32_to_cpu(rsp->fcp_sense_len); if (cmnd) { - if (vfc_cmd->response_flags & IBMVFC_ADAPTER_RESID_VALID) - scsi_set_resid(cmnd, vfc_cmd->adapter_resid); + if (be16_to_cpu(vfc_cmd->response_flags) & IBMVFC_ADAPTER_RESID_VALID) + scsi_set_resid(cmnd, be32_to_cpu(vfc_cmd->adapter_resid)); else if (rsp->flags & FCP_RESID_UNDER) - scsi_set_resid(cmnd, rsp->fcp_resid); + scsi_set_resid(cmnd, be32_to_cpu(rsp->fcp_resid)); else scsi_set_resid(cmnd, 0); @@ -1540,12 +1541,13 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt) cmnd->result = ibmvfc_get_err_result(vfc_cmd); if (rsp->flags & FCP_RSP_LEN_VALID) - rsp_len = rsp->fcp_rsp_len; + rsp_len = be32_to_cpu(rsp->fcp_rsp_len); if ((sense_len + rsp_len) > SCSI_SENSE_BUFFERSIZE) sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len; if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8) memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len); - if ((vfc_cmd->status & IBMVFC_VIOS_FAILURE) && (vfc_cmd->error == IBMVFC_PLOGI_REQUIRED)) + if ((be16_to_cpu(vfc_cmd->status) & IBMVFC_VIOS_FAILURE) && + (be16_to_cpu(vfc_cmd->error) == IBMVFC_PLOGI_REQUIRED)) ibmvfc_relogin(cmnd->device); if (!cmnd->result && (!scsi_get_resid(cmnd) || (rsp->flags & FCP_RESID_OVER))) @@ -1630,19 +1632,19 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd, cmnd->scsi_done = done; vfc_cmd = &evt->iu.cmd; memset(vfc_cmd, 0, sizeof(*vfc_cmd)); - vfc_cmd->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); - vfc_cmd->resp.len = sizeof(vfc_cmd->rsp); - vfc_cmd->frame_type = IBMVFC_SCSI_FCP_TYPE; - vfc_cmd->payload_len = sizeof(vfc_cmd->iu); - vfc_cmd->resp_len = sizeof(vfc_cmd->rsp); - vfc_cmd->cancel_key = (unsigned long)cmnd->device->hostdata; - vfc_cmd->tgt_scsi_id = rport->port_id; - vfc_cmd->iu.xfer_len = scsi_bufflen(cmnd); + vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); + vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->rsp)); + vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); + vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->iu)); + vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->rsp)); + vfc_cmd->cancel_key = cpu_to_be32((unsigned long)cmnd->device->hostdata); + vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id); + vfc_cmd->iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd)); int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun); memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len); if (scsi_populate_tag_msg(cmnd, tag)) { - vfc_cmd->task_tag = tag[1]; + vfc_cmd->task_tag = cpu_to_be64(tag[1]); switch (tag[0]) { case MSG_SIMPLE_TAG: vfc_cmd->iu.pri_task_attr = IBMVFC_SIMPLE_TASK; @@ -1732,12 +1734,12 @@ static int ibmvfc_bsg_timeout(struct fc_bsg_job *job) tmf = &evt->iu.tmf; memset(tmf, 0, sizeof(*tmf)); - tmf->common.version = 1; - tmf->common.opcode = IBMVFC_TMF_MAD; - tmf->common.length = sizeof(*tmf); - tmf->scsi_id = port_id; - tmf->cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY; - tmf->my_cancel_key = IBMVFC_INTERNAL_CANCEL_KEY; + tmf->common.version = cpu_to_be32(1); + tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); + tmf->common.length = cpu_to_be16(sizeof(*tmf)); + tmf->scsi_id = cpu_to_be64(port_id); + tmf->cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY); + tmf->my_cancel_key = cpu_to_be32(IBMVFC_INTERNAL_CANCEL_KEY); rc = ibmvfc_send_event(evt, vhost, default_timeout); if (rc != 0) { @@ -1789,10 +1791,10 @@ static int ibmvfc_bsg_plogi(struct ibmvfc_host *vhost, unsigned int port_id) ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT); plogi = &evt->iu.plogi; memset(plogi, 0, sizeof(*plogi)); - plogi->common.version = 1; - plogi->common.opcode = IBMVFC_PORT_LOGIN; - plogi->common.length = sizeof(*plogi); - plogi->scsi_id = port_id; + plogi->common.version = cpu_to_be32(1); + plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN); + plogi->common.length = cpu_to_be16(sizeof(*plogi)); + plogi->scsi_id = cpu_to_be64(port_id); evt->sync_iu = &rsp_iu; init_completion(&evt->comp); @@ -1904,26 +1906,26 @@ static int ibmvfc_bsg_request(struct fc_bsg_job *job) mad = &evt->iu.passthru; memset(mad, 0, sizeof(*mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_PASSTHRU; - mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu); - - mad->cmd_ioba.va = (u64)evt->crq.ioba + - offsetof(struct ibmvfc_passthru_mad, iu); - mad->cmd_ioba.len = sizeof(mad->iu); - - mad->iu.cmd_len = job->request_payload.payload_len; - mad->iu.rsp_len = job->reply_payload.payload_len; - mad->iu.flags = fc_flags; - mad->iu.cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY; - - mad->iu.cmd.va = sg_dma_address(job->request_payload.sg_list); - mad->iu.cmd.len = sg_dma_len(job->request_payload.sg_list); - mad->iu.rsp.va = sg_dma_address(job->reply_payload.sg_list); - mad->iu.rsp.len = sg_dma_len(job->reply_payload.sg_list); - mad->iu.scsi_id = port_id; - mad->iu.tag = (u64)evt; - rsp_len = mad->iu.rsp.len; + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU); + mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu)); + + mad->cmd_ioba.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + + offsetof(struct ibmvfc_passthru_mad, iu)); + mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu)); + + mad->iu.cmd_len = cpu_to_be32(job->request_payload.payload_len); + mad->iu.rsp_len = cpu_to_be32(job->reply_payload.payload_len); + mad->iu.flags = cpu_to_be32(fc_flags); + mad->iu.cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY); + + mad->iu.cmd.va = cpu_to_be64(sg_dma_address(job->request_payload.sg_list)); + mad->iu.cmd.len = cpu_to_be32(sg_dma_len(job->request_payload.sg_list)); + mad->iu.rsp.va = cpu_to_be64(sg_dma_address(job->reply_payload.sg_list)); + mad->iu.rsp.len = cpu_to_be32(sg_dma_len(job->reply_payload.sg_list)); + mad->iu.scsi_id = cpu_to_be64(port_id); + mad->iu.tag = cpu_to_be64((u64)evt); + rsp_len = be32_to_cpu(mad->iu.rsp.len); evt->sync_iu = &rsp_iu; init_completion(&evt->comp); @@ -1986,15 +1988,15 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) tmf = &evt->iu.cmd; memset(tmf, 0, sizeof(*tmf)); - tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); - tmf->resp.len = sizeof(tmf->rsp); - tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; - tmf->payload_len = sizeof(tmf->iu); - tmf->resp_len = sizeof(tmf->rsp); - tmf->cancel_key = (unsigned long)sdev->hostdata; - tmf->tgt_scsi_id = rport->port_id; + tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); + tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp)); + tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); + tmf->payload_len = cpu_to_be32(sizeof(tmf->iu)); + tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp)); + tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); + tmf->tgt_scsi_id = cpu_to_be64(rport->port_id); int_to_scsilun(sdev->lun, &tmf->iu.lun); - tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); + tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); tmf->iu.tmf_flags = type; evt->sync_iu = &rsp_iu; @@ -2020,8 +2022,8 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) rsp_code = fc_rsp->data.info.rsp_code; sdev_printk(KERN_ERR, sdev, "%s reset failed: %s (%x:%x) " - "flags: %x fcp_rsp: %x, scsi_status: %x\n", - desc, ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), + "flags: %x fcp_rsp: %x, scsi_status: %x\n", desc, + ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)), rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, fc_rsp->scsi_status); rsp_rc = -EIO; @@ -2185,19 +2187,19 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) tmf = &evt->iu.tmf; memset(tmf, 0, sizeof(*tmf)); - tmf->common.version = 1; - tmf->common.opcode = IBMVFC_TMF_MAD; - tmf->common.length = sizeof(*tmf); - tmf->scsi_id = rport->port_id; + tmf->common.version = cpu_to_be32(1); + tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); + tmf->common.length = cpu_to_be16(sizeof(*tmf)); + tmf->scsi_id = cpu_to_be64(rport->port_id); int_to_scsilun(sdev->lun, &tmf->lun); - if (!(vhost->login_buf->resp.capabilities & IBMVFC_CAN_SUPPRESS_ABTS)) + if (!(be64_to_cpu(vhost->login_buf->resp.capabilities) & IBMVFC_CAN_SUPPRESS_ABTS)) type &= ~IBMVFC_TMF_SUPPRESS_ABTS; if (vhost->state == IBMVFC_ACTIVE) - tmf->flags = (type | IBMVFC_TMF_LUA_VALID); + tmf->flags = cpu_to_be32((type | IBMVFC_TMF_LUA_VALID)); else - tmf->flags = ((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID); - tmf->cancel_key = (unsigned long)sdev->hostdata; - tmf->my_cancel_key = (unsigned long)starget->hostdata; + tmf->flags = cpu_to_be32(((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID)); + tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); + tmf->my_cancel_key = cpu_to_be32((unsigned long)starget->hostdata); evt->sync_iu = &rsp; init_completion(&evt->comp); @@ -2217,7 +2219,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) sdev_printk(KERN_INFO, sdev, "Cancelling outstanding commands.\n"); wait_for_completion(&evt->comp); - status = rsp.mad_common.status; + status = be16_to_cpu(rsp.mad_common.status); spin_lock_irqsave(vhost->host->host_lock, flags); ibmvfc_free_event(evt); spin_unlock_irqrestore(vhost->host->host_lock, flags); @@ -2252,7 +2254,7 @@ static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key) unsigned long cancel_key = (unsigned long)key; if (evt->crq.format == IBMVFC_CMD_FORMAT && - evt->iu.cmd.cancel_key == cancel_key) + be32_to_cpu(evt->iu.cmd.cancel_key) == cancel_key) return 1; return 0; } @@ -2316,15 +2318,15 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) tmf = &evt->iu.cmd; memset(tmf, 0, sizeof(*tmf)); - tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); - tmf->resp.len = sizeof(tmf->rsp); - tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; - tmf->payload_len = sizeof(tmf->iu); - tmf->resp_len = sizeof(tmf->rsp); - tmf->cancel_key = (unsigned long)sdev->hostdata; - tmf->tgt_scsi_id = rport->port_id; + tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); + tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp)); + tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); + tmf->payload_len = cpu_to_be32(sizeof(tmf->iu)); + tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp)); + tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); + tmf->tgt_scsi_id = cpu_to_be64(rport->port_id); int_to_scsilun(sdev->lun, &tmf->iu.lun); - tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); + tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; evt->sync_iu = &rsp_iu; @@ -2380,7 +2382,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " "flags: %x fcp_rsp: %x, scsi_status: %x\n", - ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), + ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)), rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, fc_rsp->scsi_status); rsp_rc = -EIO; @@ -2641,14 +2643,14 @@ static const char *ibmvfc_get_link_state(enum ibmvfc_ae_link_state state) static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, struct ibmvfc_host *vhost) { - const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(crq->event); + const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(be64_to_cpu(crq->event)); struct ibmvfc_target *tgt; ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwpn: %llx," " node_name: %llx%s\n", desc->desc, crq->scsi_id, crq->wwpn, crq->node_name, ibmvfc_get_link_state(crq->link_state)); - switch (crq->event) { + switch (be64_to_cpu(crq->event)) { case IBMVFC_AE_RESUME: switch (crq->link_state) { case IBMVFC_AE_LS_LINK_DOWN: @@ -2691,15 +2693,15 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, list_for_each_entry(tgt, &vhost->targets, queue) { if (!crq->scsi_id && !crq->wwpn && !crq->node_name) break; - if (crq->scsi_id && tgt->scsi_id != crq->scsi_id) + if (crq->scsi_id && cpu_to_be64(tgt->scsi_id) != crq->scsi_id) continue; - if (crq->wwpn && tgt->ids.port_name != crq->wwpn) + if (crq->wwpn && cpu_to_be64(tgt->ids.port_name) != crq->wwpn) continue; - if (crq->node_name && tgt->ids.node_name != crq->node_name) + if (crq->node_name && cpu_to_be64(tgt->ids.node_name) != crq->node_name) continue; - if (tgt->need_login && crq->event == IBMVFC_AE_ELS_LOGO) + if (tgt->need_login && be64_to_cpu(crq->event) == IBMVFC_AE_ELS_LOGO) tgt->logo_rcvd = 1; - if (!tgt->need_login || crq->event == IBMVFC_AE_ELS_PLOGI) { + if (!tgt->need_login || be64_to_cpu(crq->event) == IBMVFC_AE_ELS_PLOGI) { ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ibmvfc_reinit_host(vhost); } @@ -2730,7 +2732,7 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost) { long rc; - struct ibmvfc_event *evt = (struct ibmvfc_event *)crq->ioba; + struct ibmvfc_event *evt = (struct ibmvfc_event *)be64_to_cpu(crq->ioba); switch (crq->valid) { case IBMVFC_CRQ_INIT_RSP: @@ -3336,7 +3338,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli; struct ibmvfc_prli_svc_parms *parms = &rsp->parms; - u32 status = rsp->common.status; + u32 status = be16_to_cpu(rsp->common.status); int index, level = IBMVFC_DEFAULT_LOG_LEVEL; vhost->discovery_threads--; @@ -3347,14 +3349,14 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) parms->type, parms->flags, parms->service_parms); if (parms->type == IBMVFC_SCSI_FCP_TYPE) { - index = ibmvfc_get_prli_rsp(parms->flags); + index = ibmvfc_get_prli_rsp(be16_to_cpu(parms->flags)); if (prli_rsp[index].logged_in) { - if (parms->flags & IBMVFC_PRLI_EST_IMG_PAIR) { + if (be16_to_cpu(parms->flags) & IBMVFC_PRLI_EST_IMG_PAIR) { tgt->need_login = 0; tgt->ids.roles = 0; - if (parms->service_parms & IBMVFC_PRLI_TARGET_FUNC) + if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_TARGET_FUNC) tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET; - if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC) + if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_INITIATOR_FUNC) tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; tgt->add_rport = 1; } else @@ -3373,17 +3375,18 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) break; case IBMVFC_MAD_FAILED: default: - if ((rsp->status & IBMVFC_VIOS_FAILURE) && rsp->error == IBMVFC_PLOGI_REQUIRED) + if ((be16_to_cpu(rsp->status) & IBMVFC_VIOS_FAILURE) && + be16_to_cpu(rsp->error) == IBMVFC_PLOGI_REQUIRED) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); else if (tgt->logo_rcvd) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); - else if (ibmvfc_retry_cmd(rsp->status, rsp->error)) + 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); tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n", - ibmvfc_get_cmd_error(rsp->status, rsp->error), + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), rsp->status, rsp->error, status); break; }; @@ -3414,14 +3417,14 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt) evt->tgt = tgt; prli = &evt->iu.prli; memset(prli, 0, sizeof(*prli)); - prli->common.version = 1; - prli->common.opcode = IBMVFC_PROCESS_LOGIN; - prli->common.length = sizeof(*prli); - prli->scsi_id = tgt->scsi_id; + prli->common.version = cpu_to_be32(1); + prli->common.opcode = cpu_to_be32(IBMVFC_PROCESS_LOGIN); + prli->common.length = cpu_to_be16(sizeof(*prli)); + prli->scsi_id = cpu_to_be64(tgt->scsi_id); prli->parms.type = IBMVFC_SCSI_FCP_TYPE; - prli->parms.flags = IBMVFC_PRLI_EST_IMG_PAIR; - prli->parms.service_parms = IBMVFC_PRLI_INITIATOR_FUNC; + prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR); + prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC); ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); if (ibmvfc_send_event(evt, vhost, default_timeout)) { @@ -3442,7 +3445,7 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) struct ibmvfc_target *tgt = evt->tgt; struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_port_login *rsp = &evt->xfer_iu->plogi; - u32 status = rsp->common.status; + u32 status = be16_to_cpu(rsp->common.status); int level = IBMVFC_DEFAULT_LOG_LEVEL; vhost->discovery_threads--; @@ -3472,15 +3475,15 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) break; case IBMVFC_MAD_FAILED: default: - if (ibmvfc_retry_cmd(rsp->status, rsp->error)) + 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); tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", - ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error, - ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type, - ibmvfc_get_ls_explain(rsp->fc_explain), rsp->fc_explain, status); + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), rsp->status, rsp->error, + ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), rsp->fc_type, + ibmvfc_get_ls_explain(be16_to_cpu(rsp->fc_explain)), rsp->fc_explain, status); break; }; @@ -3512,10 +3515,10 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt) evt->tgt = tgt; plogi = &evt->iu.plogi; memset(plogi, 0, sizeof(*plogi)); - plogi->common.version = 1; - plogi->common.opcode = IBMVFC_PORT_LOGIN; - plogi->common.length = sizeof(*plogi); - plogi->scsi_id = tgt->scsi_id; + plogi->common.version = cpu_to_be32(1); + plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN); + plogi->common.length = cpu_to_be16(sizeof(*plogi)); + plogi->scsi_id = cpu_to_be64(tgt->scsi_id); if (ibmvfc_send_event(evt, vhost, default_timeout)) { vhost->discovery_threads--; @@ -3535,7 +3538,7 @@ static void ibmvfc_tgt_implicit_logout_done(struct ibmvfc_event *evt) struct ibmvfc_target *tgt = evt->tgt; struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_implicit_logout *rsp = &evt->xfer_iu->implicit_logout; - u32 status = rsp->common.status; + u32 status = be16_to_cpu(rsp->common.status); vhost->discovery_threads--; ibmvfc_free_event(evt); @@ -3585,10 +3588,10 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) evt->tgt = tgt; mad = &evt->iu.implicit_logout; memset(mad, 0, sizeof(*mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_IMPLICIT_LOGOUT; - mad->common.length = sizeof(*mad); - mad->old_scsi_id = tgt->scsi_id; + mad->common.version = cpu_to_be32(1); + 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); ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); if (ibmvfc_send_event(evt, vhost, default_timeout)) { @@ -3616,7 +3619,7 @@ static int ibmvfc_adisc_needs_plogi(struct ibmvfc_passthru_mad *mad, if (memcmp(&mad->fc_iu.response[4], &tgt->ids.node_name, sizeof(tgt->ids.node_name))) return 1; - if (mad->fc_iu.response[6] != tgt->scsi_id) + if (be32_to_cpu(mad->fc_iu.response[6]) != tgt->scsi_id) return 1; return 0; } @@ -3631,7 +3634,7 @@ static void ibmvfc_tgt_adisc_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 = mad->common.status; + u32 status = be16_to_cpu(mad->common.status); u8 fc_reason, fc_explain; vhost->discovery_threads--; @@ -3649,10 +3652,10 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt) case IBMVFC_MAD_FAILED: default: ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); - fc_reason = (mad->fc_iu.response[1] & 0x00ff0000) >> 16; - fc_explain = (mad->fc_iu.response[1] & 0x0000ff00) >> 8; + 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", - ibmvfc_get_cmd_error(mad->iu.status, mad->iu.error), + ibmvfc_get_cmd_error(be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error)), mad->iu.status, mad->iu.error, ibmvfc_get_fc_type(fc_reason), fc_reason, ibmvfc_get_ls_explain(fc_explain), fc_explain, status); @@ -3674,22 +3677,22 @@ static void ibmvfc_init_passthru(struct ibmvfc_event *evt) struct ibmvfc_passthru_mad *mad = &evt->iu.passthru; memset(mad, 0, sizeof(*mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_PASSTHRU; - mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu); - mad->cmd_ioba.va = (u64)evt->crq.ioba + - offsetof(struct ibmvfc_passthru_mad, iu); - mad->cmd_ioba.len = sizeof(mad->iu); - mad->iu.cmd_len = sizeof(mad->fc_iu.payload); - mad->iu.rsp_len = sizeof(mad->fc_iu.response); - mad->iu.cmd.va = (u64)evt->crq.ioba + + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU); + mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu)); + mad->cmd_ioba.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) + + offsetof(struct ibmvfc_passthru_mad, iu)); + mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu)); + mad->iu.cmd_len = cpu_to_be32(sizeof(mad->fc_iu.payload)); + mad->iu.rsp_len = cpu_to_be32(sizeof(mad->fc_iu.response)); + mad->iu.cmd.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_passthru_mad, fc_iu) + - offsetof(struct ibmvfc_passthru_fc_iu, payload); - mad->iu.cmd.len = sizeof(mad->fc_iu.payload); - mad->iu.rsp.va = (u64)evt->crq.ioba + + offsetof(struct ibmvfc_passthru_fc_iu, payload)); + mad->iu.cmd.len = cpu_to_be32(sizeof(mad->fc_iu.payload)); + mad->iu.rsp.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_passthru_mad, fc_iu) + - offsetof(struct ibmvfc_passthru_fc_iu, response); - mad->iu.rsp.len = sizeof(mad->fc_iu.response); + offsetof(struct ibmvfc_passthru_fc_iu, response)); + mad->iu.rsp.len = cpu_to_be32(sizeof(mad->fc_iu.response)); } /** @@ -3748,11 +3751,11 @@ static void ibmvfc_adisc_timeout(struct ibmvfc_target *tgt) evt->tgt = tgt; tmf = &evt->iu.tmf; memset(tmf, 0, sizeof(*tmf)); - tmf->common.version = 1; - tmf->common.opcode = IBMVFC_TMF_MAD; - tmf->common.length = sizeof(*tmf); - tmf->scsi_id = tgt->scsi_id; - tmf->cancel_key = tgt->cancel_key; + tmf->common.version = cpu_to_be32(1); + tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); + tmf->common.length = cpu_to_be16(sizeof(*tmf)); + tmf->scsi_id = cpu_to_be64(tgt->scsi_id); + tmf->cancel_key = cpu_to_be32(tgt->cancel_key); rc = ibmvfc_send_event(evt, vhost, default_timeout); @@ -3794,16 +3797,16 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt) ibmvfc_init_passthru(evt); mad = &evt->iu.passthru; - mad->iu.flags = IBMVFC_FC_ELS; - mad->iu.scsi_id = tgt->scsi_id; - mad->iu.cancel_key = tgt->cancel_key; + mad->iu.flags = cpu_to_be32(IBMVFC_FC_ELS); + mad->iu.scsi_id = cpu_to_be64(tgt->scsi_id); + mad->iu.cancel_key = cpu_to_be32(tgt->cancel_key); - mad->fc_iu.payload[0] = IBMVFC_ADISC; + mad->fc_iu.payload[0] = cpu_to_be32(IBMVFC_ADISC); memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name, sizeof(vhost->login_buf->resp.port_name)); memcpy(&mad->fc_iu.payload[4], &vhost->login_buf->resp.node_name, sizeof(vhost->login_buf->resp.node_name)); - mad->fc_iu.payload[6] = vhost->login_buf->resp.scsi_id & 0x00ffffff; + mad->fc_iu.payload[6] = cpu_to_be32(be64_to_cpu(vhost->login_buf->resp.scsi_id) & 0x00ffffff); if (timer_pending(&tgt->timer)) mod_timer(&tgt->timer, jiffies + (IBMVFC_ADISC_TIMEOUT * HZ)); @@ -3834,7 +3837,7 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) struct ibmvfc_target *tgt = evt->tgt; struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_query_tgt *rsp = &evt->xfer_iu->query_tgt; - u32 status = rsp->common.status; + u32 status = be16_to_cpu(rsp->common.status); int level = IBMVFC_DEFAULT_LOG_LEVEL; vhost->discovery_threads--; @@ -3842,8 +3845,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 = rsp->scsi_id; - if (rsp->scsi_id != tgt->scsi_id) + 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); else ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc); @@ -3855,19 +3858,20 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) break; case IBMVFC_MAD_FAILED: default: - if ((rsp->status & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED && - rsp->error == IBMVFC_UNABLE_TO_PERFORM_REQ && - rsp->fc_explain == IBMVFC_PORT_NAME_NOT_REG) + 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); - else if (ibmvfc_retry_cmd(rsp->status, rsp->error)) + 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); tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", - ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error, - ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type, - ibmvfc_get_gs_explain(rsp->fc_explain), rsp->fc_explain, status); + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), + rsp->status, rsp->error, ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), + rsp->fc_type, ibmvfc_get_gs_explain(be16_to_cpu(rsp->fc_explain)), + rsp->fc_explain, status); break; }; @@ -3897,10 +3901,10 @@ static void ibmvfc_tgt_query_target(struct ibmvfc_target *tgt) ibmvfc_init_event(evt, ibmvfc_tgt_query_target_done, IBMVFC_MAD_FORMAT); query_tgt = &evt->iu.query_tgt; memset(query_tgt, 0, sizeof(*query_tgt)); - query_tgt->common.version = 1; - query_tgt->common.opcode = IBMVFC_QUERY_TARGET; - query_tgt->common.length = sizeof(*query_tgt); - query_tgt->wwpn = tgt->ids.port_name; + query_tgt->common.version = cpu_to_be32(1); + query_tgt->common.opcode = cpu_to_be32(IBMVFC_QUERY_TARGET); + query_tgt->common.length = cpu_to_be16(sizeof(*query_tgt)); + query_tgt->wwpn = cpu_to_be64(tgt->ids.port_name); ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); if (ibmvfc_send_event(evt, vhost, default_timeout)) { @@ -3971,7 +3975,8 @@ static int ibmvfc_alloc_targets(struct ibmvfc_host *vhost) for (i = 0, rc = 0; !rc && i < vhost->num_targets; i++) rc = ibmvfc_alloc_target(vhost, - vhost->disc_buf->scsi_id[i] & IBMVFC_DISC_TGT_SCSI_ID_MASK); + be32_to_cpu(vhost->disc_buf->scsi_id[i]) & + IBMVFC_DISC_TGT_SCSI_ID_MASK); return rc; } @@ -3985,19 +3990,20 @@ static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt) { struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_discover_targets *rsp = &evt->xfer_iu->discover_targets; - u32 mad_status = rsp->common.status; + u32 mad_status = be16_to_cpu(rsp->common.status); int level = IBMVFC_DEFAULT_LOG_LEVEL; switch (mad_status) { case IBMVFC_MAD_SUCCESS: ibmvfc_dbg(vhost, "Discover Targets succeeded\n"); - vhost->num_targets = rsp->num_written; + vhost->num_targets = be32_to_cpu(rsp->num_written); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_ALLOC_TGTS); break; case IBMVFC_MAD_FAILED: level += ibmvfc_retry_host_init(vhost); ibmvfc_log(vhost, level, "Discover Targets failed: %s (%x:%x)\n", - ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error); + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), + rsp->status, rsp->error); break; case IBMVFC_MAD_DRIVER_FAILED: break; @@ -4024,12 +4030,12 @@ static void ibmvfc_discover_targets(struct ibmvfc_host *vhost) ibmvfc_init_event(evt, ibmvfc_discover_targets_done, IBMVFC_MAD_FORMAT); mad = &evt->iu.discover_targets; memset(mad, 0, sizeof(*mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_DISC_TARGETS; - mad->common.length = sizeof(*mad); - mad->bufflen = vhost->disc_buf_sz; - mad->buffer.va = vhost->disc_buf_dma; - mad->buffer.len = vhost->disc_buf_sz; + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_DISC_TARGETS); + mad->common.length = cpu_to_be16(sizeof(*mad)); + mad->bufflen = cpu_to_be32(vhost->disc_buf_sz); + mad->buffer.va = cpu_to_be64(vhost->disc_buf_dma); + mad->buffer.len = cpu_to_be32(vhost->disc_buf_sz); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT); if (!ibmvfc_send_event(evt, vhost, default_timeout)) @@ -4046,7 +4052,7 @@ static void ibmvfc_discover_targets(struct ibmvfc_host *vhost) static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) { struct ibmvfc_host *vhost = evt->vhost; - u32 mad_status = evt->xfer_iu->npiv_login.common.status; + u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_login.common.status); struct ibmvfc_npiv_login_resp *rsp = &vhost->login_buf->resp; unsigned int npiv_max_sectors; int level = IBMVFC_DEFAULT_LOG_LEVEL; @@ -4056,12 +4062,13 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) ibmvfc_free_event(evt); break; case IBMVFC_MAD_FAILED: - if (ibmvfc_retry_cmd(rsp->status, rsp->error)) + if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_host_init(vhost); else ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); ibmvfc_log(vhost, level, "NPIV Login failed: %s (%x:%x)\n", - ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error); + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), + rsp->status, rsp->error); ibmvfc_free_event(evt); return; case IBMVFC_MAD_CRQ_ERROR: @@ -4078,7 +4085,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) vhost->client_migrated = 0; - if (!(rsp->flags & IBMVFC_NATIVE_FC)) { + if (!(be32_to_cpu(rsp->flags) & IBMVFC_NATIVE_FC)) { dev_err(vhost->dev, "Virtual adapter does not support FC. %x\n", rsp->flags); ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); @@ -4086,7 +4093,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) return; } - if (rsp->max_cmds <= IBMVFC_NUM_INTERNAL_REQ) { + if (be32_to_cpu(rsp->max_cmds) <= IBMVFC_NUM_INTERNAL_REQ) { dev_err(vhost->dev, "Virtual adapter supported queue depth too small: %d\n", rsp->max_cmds); ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); @@ -4095,27 +4102,27 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) } vhost->logged_in = 1; - npiv_max_sectors = min((uint)(rsp->max_dma_len >> 9), IBMVFC_MAX_SECTORS); + npiv_max_sectors = min((uint)(be64_to_cpu(rsp->max_dma_len) >> 9), IBMVFC_MAX_SECTORS); dev_info(vhost->dev, "Host partition: %s, device: %s %s %s max sectors %u\n", rsp->partition_name, rsp->device_name, rsp->port_loc_code, rsp->drc_name, npiv_max_sectors); - fc_host_fabric_name(vhost->host) = rsp->node_name; - fc_host_node_name(vhost->host) = rsp->node_name; - fc_host_port_name(vhost->host) = rsp->port_name; - fc_host_port_id(vhost->host) = rsp->scsi_id; + fc_host_fabric_name(vhost->host) = be64_to_cpu(rsp->node_name); + fc_host_node_name(vhost->host) = be64_to_cpu(rsp->node_name); + fc_host_port_name(vhost->host) = be64_to_cpu(rsp->port_name); + fc_host_port_id(vhost->host) = be64_to_cpu(rsp->scsi_id); fc_host_port_type(vhost->host) = FC_PORTTYPE_NPIV; fc_host_supported_classes(vhost->host) = 0; - if (rsp->service_parms.class1_parms[0] & 0x80000000) + if (be32_to_cpu(rsp->service_parms.class1_parms[0]) & 0x80000000) fc_host_supported_classes(vhost->host) |= FC_COS_CLASS1; - if (rsp->service_parms.class2_parms[0] & 0x80000000) + if (be32_to_cpu(rsp->service_parms.class2_parms[0]) & 0x80000000) fc_host_supported_classes(vhost->host) |= FC_COS_CLASS2; - if (rsp->service_parms.class3_parms[0] & 0x80000000) + if (be32_to_cpu(rsp->service_parms.class3_parms[0]) & 0x80000000) fc_host_supported_classes(vhost->host) |= FC_COS_CLASS3; fc_host_maxframe_size(vhost->host) = - rsp->service_parms.common.bb_rcv_sz & 0x0fff; + be16_to_cpu(rsp->service_parms.common.bb_rcv_sz) & 0x0fff; - vhost->host->can_queue = rsp->max_cmds - IBMVFC_NUM_INTERNAL_REQ; + vhost->host->can_queue = be32_to_cpu(rsp->max_cmds) - IBMVFC_NUM_INTERNAL_REQ; vhost->host->max_sectors = npiv_max_sectors; ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY); wake_up(&vhost->work_wait_q); @@ -4138,11 +4145,11 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost) memcpy(vhost->login_buf, &vhost->login_info, sizeof(vhost->login_info)); mad = &evt->iu.npiv_login; memset(mad, 0, sizeof(struct ibmvfc_npiv_login_mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_NPIV_LOGIN; - mad->common.length = sizeof(struct ibmvfc_npiv_login_mad); - mad->buffer.va = vhost->login_buf_dma; - mad->buffer.len = sizeof(*vhost->login_buf); + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGIN); + mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_login_mad)); + mad->buffer.va = cpu_to_be64(vhost->login_buf_dma); + mad->buffer.len = cpu_to_be32(sizeof(*vhost->login_buf)); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT); @@ -4160,7 +4167,7 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost) static void ibmvfc_npiv_logout_done(struct ibmvfc_event *evt) { struct ibmvfc_host *vhost = evt->vhost; - u32 mad_status = evt->xfer_iu->npiv_logout.common.status; + u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_logout.common.status); ibmvfc_free_event(evt); @@ -4199,9 +4206,9 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *vhost) mad = &evt->iu.npiv_logout; memset(mad, 0, sizeof(*mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_NPIV_LOGOUT; - mad->common.length = sizeof(struct ibmvfc_npiv_logout_mad); + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGOUT); + mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_logout_mad)); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_LOGO_WAIT); @@ -4343,14 +4350,14 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) if (rport) { tgt_dbg(tgt, "rport add succeeded\n"); tgt->rport = rport; - rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff; + rport->maxframe_size = be16_to_cpu(tgt->service_parms.common.bb_rcv_sz) & 0x0fff; rport->supported_classes = 0; tgt->target_id = rport->scsi_target_id; - if (tgt->service_parms.class1_parms[0] & 0x80000000) + if (be32_to_cpu(tgt->service_parms.class1_parms[0]) & 0x80000000) rport->supported_classes |= FC_COS_CLASS1; - if (tgt->service_parms.class2_parms[0] & 0x80000000) + if (be32_to_cpu(tgt->service_parms.class2_parms[0]) & 0x80000000) rport->supported_classes |= FC_COS_CLASS2; - if (tgt->service_parms.class3_parms[0] & 0x80000000) + if (be32_to_cpu(tgt->service_parms.class3_parms[0]) & 0x80000000) rport->supported_classes |= FC_COS_CLASS3; if (rport->rqst_q) blk_queue_max_segments(rport->rqst_q, 1); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 017a529..8fae032 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -135,12 +135,12 @@ enum ibmvfc_mad_types { }; struct ibmvfc_mad_common { - u32 version; - u32 reserved; - u32 opcode; - u16 status; - u16 length; - u64 tag; + __be32 version; + __be32 reserved; + __be32 opcode; + __be16 status; + __be16 length; + __be64 tag; }__attribute__((packed, aligned (8))); struct ibmvfc_npiv_login_mad { @@ -155,76 +155,76 @@ struct ibmvfc_npiv_logout_mad { #define IBMVFC_MAX_NAME 256 struct ibmvfc_npiv_login { - u32 ostype; + __be32 ostype; #define IBMVFC_OS_LINUX 0x02 - u32 pad; - u64 max_dma_len; - u32 max_payload; - u32 max_response; - u32 partition_num; - u32 vfc_frame_version; - u16 fcp_version; - u16 flags; + __be32 pad; + __be64 max_dma_len; + __be32 max_payload; + __be32 max_response; + __be32 partition_num; + __be32 vfc_frame_version; + __be16 fcp_version; + __be16 flags; #define IBMVFC_CLIENT_MIGRATED 0x01 #define IBMVFC_FLUSH_ON_HALT 0x02 - u32 max_cmds; - u64 capabilities; + __be32 max_cmds; + __be64 capabilities; #define IBMVFC_CAN_MIGRATE 0x01 - u64 node_name; + __be64 node_name; struct srp_direct_buf async; u8 partition_name[IBMVFC_MAX_NAME]; u8 device_name[IBMVFC_MAX_NAME]; u8 drc_name[IBMVFC_MAX_NAME]; - u64 reserved2[2]; + __be64 reserved2[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_common_svc_parms { - u16 fcph_version; - u16 b2b_credit; - u16 features; - u16 bb_rcv_sz; /* upper nibble is BB_SC_N */ - u32 ratov; - u32 edtov; + __be16 fcph_version; + __be16 b2b_credit; + __be16 features; + __be16 bb_rcv_sz; /* upper nibble is BB_SC_N */ + __be32 ratov; + __be32 edtov; }__attribute__((packed, aligned (4))); struct ibmvfc_service_parms { struct ibmvfc_common_svc_parms common; u8 port_name[8]; u8 node_name[8]; - u32 class1_parms[4]; - u32 class2_parms[4]; - u32 class3_parms[4]; - u32 obsolete[4]; - u32 vendor_version[4]; - u32 services_avail[2]; - u32 ext_len; - u32 reserved[30]; - u32 clk_sync_qos[2]; + __be32 class1_parms[4]; + __be32 class2_parms[4]; + __be32 class3_parms[4]; + __be32 obsolete[4]; + __be32 vendor_version[4]; + __be32 services_avail[2]; + __be32 ext_len; + __be32 reserved[30]; + __be32 clk_sync_qos[2]; }__attribute__((packed, aligned (4))); struct ibmvfc_npiv_login_resp { - u32 version; - u16 status; - u16 error; - u32 flags; + __be32 version; + __be16 status; + __be16 error; + __be32 flags; #define IBMVFC_NATIVE_FC 0x01 - u32 reserved; - u64 capabilities; + __be32 reserved; + __be64 capabilities; #define IBMVFC_CAN_FLUSH_ON_HALT 0x08 #define IBMVFC_CAN_SUPPRESS_ABTS 0x10 - u32 max_cmds; - u32 scsi_id_sz; - u64 max_dma_len; - u64 scsi_id; - u64 port_name; - u64 node_name; - u64 link_speed; + __be32 max_cmds; + __be32 scsi_id_sz; + __be64 max_dma_len; + __be64 scsi_id; + __be64 port_name; + __be64 node_name; + __be64 link_speed; u8 partition_name[IBMVFC_MAX_NAME]; u8 device_name[IBMVFC_MAX_NAME]; u8 port_loc_code[IBMVFC_MAX_NAME]; u8 drc_name[IBMVFC_MAX_NAME]; struct ibmvfc_service_parms service_parms; - u64 reserved2; + __be64 reserved2; }__attribute__((packed, aligned (8))); union ibmvfc_npiv_login_data { @@ -233,20 +233,20 @@ union ibmvfc_npiv_login_data { }__attribute__((packed, aligned (8))); struct ibmvfc_discover_targets_buf { - u32 scsi_id[1]; + __be32 scsi_id[1]; #define IBMVFC_DISC_TGT_SCSI_ID_MASK 0x00ffffff }; struct ibmvfc_discover_targets { struct ibmvfc_mad_common common; struct srp_direct_buf buffer; - u32 flags; - u16 status; - u16 error; - u32 bufflen; - u32 num_avail; - u32 num_written; - u64 reserved[2]; + __be32 flags; + __be16 status; + __be16 error; + __be32 bufflen; + __be32 num_avail; + __be32 num_written; + __be64 reserved[2]; }__attribute__((packed, aligned (8))); enum ibmvfc_fc_reason { @@ -278,32 +278,32 @@ enum ibmvfc_gs_explain { struct ibmvfc_port_login { struct ibmvfc_mad_common common; - u64 scsi_id; - u16 reserved; - u16 fc_service_class; - u32 blksz; - u32 hdr_per_blk; - u16 status; - u16 error; /* also fc_reason */ - u16 fc_explain; - u16 fc_type; - u32 reserved2; + __be64 scsi_id; + __be16 reserved; + __be16 fc_service_class; + __be32 blksz; + __be32 hdr_per_blk; + __be16 status; + __be16 error; /* also fc_reason */ + __be16 fc_explain; + __be16 fc_type; + __be32 reserved2; struct ibmvfc_service_parms service_parms; struct ibmvfc_service_parms service_parms_change; - u64 reserved3[2]; + __be64 reserved3[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_prli_svc_parms { u8 type; #define IBMVFC_SCSI_FCP_TYPE 0x08 u8 type_ext; - u16 flags; + __be16 flags; #define IBMVFC_PRLI_ORIG_PA_VALID 0x8000 #define IBMVFC_PRLI_RESP_PA_VALID 0x4000 #define IBMVFC_PRLI_EST_IMG_PAIR 0x2000 - u32 orig_pa; - u32 resp_pa; - u32 service_parms; + __be32 orig_pa; + __be32 resp_pa; + __be32 service_parms; #define IBMVFC_PRLI_TASK_RETRY 0x00000200 #define IBMVFC_PRLI_RETRY 0x00000100 #define IBMVFC_PRLI_DATA_OVERLAY 0x00000040 @@ -315,47 +315,47 @@ struct ibmvfc_prli_svc_parms { struct ibmvfc_process_login { struct ibmvfc_mad_common common; - u64 scsi_id; + __be64 scsi_id; struct ibmvfc_prli_svc_parms parms; u8 reserved[48]; - u16 status; - u16 error; /* also fc_reason */ - u32 reserved2; - u64 reserved3[2]; + __be16 status; + __be16 error; /* also fc_reason */ + __be32 reserved2; + __be64 reserved3[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_query_tgt { struct ibmvfc_mad_common common; - u64 wwpn; - u64 scsi_id; - u16 status; - u16 error; - u16 fc_explain; - u16 fc_type; - u64 reserved[2]; + __be64 wwpn; + __be64 scsi_id; + __be16 status; + __be16 error; + __be16 fc_explain; + __be16 fc_type; + __be64 reserved[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_implicit_logout { struct ibmvfc_mad_common common; - u64 old_scsi_id; - u64 reserved[2]; + __be64 old_scsi_id; + __be64 reserved[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_tmf { struct ibmvfc_mad_common common; - u64 scsi_id; + __be64 scsi_id; struct scsi_lun lun; - u32 flags; + __be32 flags; #define IBMVFC_TMF_ABORT_TASK 0x02 #define IBMVFC_TMF_ABORT_TASK_SET 0x04 #define IBMVFC_TMF_LUN_RESET 0x10 #define IBMVFC_TMF_TGT_RESET 0x20 #define IBMVFC_TMF_LUA_VALID 0x40 #define IBMVFC_TMF_SUPPRESS_ABTS 0x80 - u32 cancel_key; - u32 my_cancel_key; - u32 pad; - u64 reserved[2]; + __be32 cancel_key; + __be32 my_cancel_key; + __be32 pad; + __be64 reserved[2]; }__attribute__((packed, aligned (8))); enum ibmvfc_fcp_rsp_info_codes { @@ -366,7 +366,7 @@ enum ibmvfc_fcp_rsp_info_codes { }; struct ibmvfc_fcp_rsp_info { - u16 reserved; + __be16 reserved; u8 rsp_code; u8 reserved2[4]; }__attribute__((packed, aligned (2))); @@ -388,13 +388,13 @@ union ibmvfc_fcp_rsp_data { }__attribute__((packed, aligned (8))); struct ibmvfc_fcp_rsp { - u64 reserved; - u16 retry_delay_timer; + __be64 reserved; + __be16 retry_delay_timer; u8 flags; u8 scsi_status; - u32 fcp_resid; - u32 fcp_sense_len; - u32 fcp_rsp_len; + __be32 fcp_resid; + __be32 fcp_sense_len; + __be32 fcp_rsp_len; union ibmvfc_fcp_rsp_data data; }__attribute__((packed, aligned (8))); @@ -429,58 +429,58 @@ struct ibmvfc_fcp_cmd_iu { #define IBMVFC_RDDATA 0x02 #define IBMVFC_WRDATA 0x01 u8 cdb[IBMVFC_MAX_CDB_LEN]; - u32 xfer_len; + __be32 xfer_len; }__attribute__((packed, aligned (4))); struct ibmvfc_cmd { - u64 task_tag; - u32 frame_type; - u32 payload_len; - u32 resp_len; - u32 adapter_resid; - u16 status; - u16 error; - u16 flags; - u16 response_flags; + __be64 task_tag; + __be32 frame_type; + __be32 payload_len; + __be32 resp_len; + __be32 adapter_resid; + __be16 status; + __be16 error; + __be16 flags; + __be16 response_flags; #define IBMVFC_ADAPTER_RESID_VALID 0x01 - u32 cancel_key; - u32 exchange_id; + __be32 cancel_key; + __be32 exchange_id; struct srp_direct_buf ext_func; struct srp_direct_buf ioba; struct srp_direct_buf resp; - u64 correlation; - u64 tgt_scsi_id; - u64 tag; - u64 reserved3[2]; + __be64 correlation; + __be64 tgt_scsi_id; + __be64 tag; + __be64 reserved3[2]; struct ibmvfc_fcp_cmd_iu iu; struct ibmvfc_fcp_rsp rsp; }__attribute__((packed, aligned (8))); struct ibmvfc_passthru_fc_iu { - u32 payload[7]; + __be32 payload[7]; #define IBMVFC_ADISC 0x52000000 - u32 response[7]; + __be32 response[7]; }; struct ibmvfc_passthru_iu { - u64 task_tag; - u32 cmd_len; - u32 rsp_len; - u16 status; - u16 error; - u32 flags; + __be64 task_tag; + __be32 cmd_len; + __be32 rsp_len; + __be16 status; + __be16 error; + __be32 flags; #define IBMVFC_FC_ELS 0x01 #define IBMVFC_FC_CT_IU 0x02 - u32 cancel_key; + __be32 cancel_key; #define IBMVFC_PASSTHRU_CANCEL_KEY 0x80000000 #define IBMVFC_INTERNAL_CANCEL_KEY 0x80000001 - u32 reserved; + __be32 reserved; struct srp_direct_buf cmd; struct srp_direct_buf rsp; - u64 correlation; - u64 scsi_id; - u64 tag; - u64 reserved2[2]; + __be64 correlation; + __be64 scsi_id; + __be64 tag; + __be64 reserved2[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_passthru_mad { @@ -552,7 +552,7 @@ struct ibmvfc_crq { volatile u8 valid; volatile u8 format; u8 reserved[6]; - volatile u64 ioba; + volatile __be64 ioba; }__attribute__((packed, aligned (8))); struct ibmvfc_crq_queue { @@ -572,12 +572,12 @@ struct ibmvfc_async_crq { volatile u8 valid; u8 link_state; u8 pad[2]; - u32 pad2; - volatile u64 event; - volatile u64 scsi_id; - volatile u64 wwpn; - volatile u64 node_name; - u64 reserved; + __be32 pad2; + volatile __be64 event; + volatile __be64 scsi_id; + volatile __be64 wwpn; + volatile __be64 node_name; + __be64 reserved; }__attribute__((packed, aligned (8))); struct ibmvfc_async_crq_queue { diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c deleted file mode 100644 index 56f8a86..0000000 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ /dev/null @@ -1,1001 +0,0 @@ -/* - * IBM eServer i/pSeries Virtual SCSI Target Driver - * Copyright (C) 2003-2005 Dave Boutcher (boutcher@us.ibm.com) IBM Corp. - * Santiago Leon (santil@us.ibm.com) IBM Corp. - * Linda Xie (lxie@us.ibm.com) IBM Corp. - * - * Copyright (C) 2005-2006 FUJITA Tomonori <tomof@acm.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <scsi/scsi.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_transport_srp.h> -#include <scsi/scsi_tgt.h> -#include <scsi/libsrp.h> -#include <asm/hvcall.h> -#include <asm/iommu.h> -#include <asm/prom.h> -#include <asm/vio.h> - -#include "ibmvscsi.h" - -#define INITIAL_SRP_LIMIT 16 -#define DEFAULT_MAX_SECTORS 256 - -#define TGT_NAME "ibmvstgt" - -/* - * Hypervisor calls. - */ -#define h_copy_rdma(l, sa, sb, da, db) \ - plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db) -#define h_send_crq(ua, l, h) \ - plpar_hcall_norets(H_SEND_CRQ, ua, l, h) -#define h_reg_crq(ua, tok, sz)\ - plpar_hcall_norets(H_REG_CRQ, ua, tok, sz); -#define h_free_crq(ua) \ - plpar_hcall_norets(H_FREE_CRQ, ua); - -/* tmp - will replace with SCSI logging stuff */ -#define eprintk(fmt, args...) \ -do { \ - printk("%s(%d) " fmt, __func__, __LINE__, ##args); \ -} while (0) -/* #define dprintk eprintk */ -#define dprintk(fmt, args...) - -struct vio_port { - struct vio_dev *dma_dev; - - struct crq_queue crq_queue; - struct work_struct crq_work; - - unsigned long liobn; - unsigned long riobn; - struct srp_target *target; - - struct srp_rport *rport; -}; - -static struct workqueue_struct *vtgtd; -static struct scsi_transport_template *ibmvstgt_transport_template; - -/* - * These are fixed for the system and come from the Open Firmware device tree. - * We just store them here to save getting them every time. - */ -static char system_id[64] = ""; -static char partition_name[97] = "UNKNOWN"; -static unsigned int partition_number = -1; - -static struct vio_port *target_to_port(struct srp_target *target) -{ - return (struct vio_port *) target->ldata; -} - -static inline union viosrp_iu *vio_iu(struct iu_entry *iue) -{ - return (union viosrp_iu *) (iue->sbuf->buf); -} - -static int send_iu(struct iu_entry *iue, uint64_t length, uint8_t format) -{ - struct srp_target *target = iue->target; - struct vio_port *vport = target_to_port(target); - long rc, rc1; - union { - struct viosrp_crq cooked; - uint64_t raw[2]; - } crq; - - /* First copy the SRP */ - rc = h_copy_rdma(length, vport->liobn, iue->sbuf->dma, - vport->riobn, iue->remote_token); - - if (rc) - eprintk("Error %ld transferring data\n", rc); - - crq.cooked.valid = 0x80; - crq.cooked.format = format; - crq.cooked.reserved = 0x00; - crq.cooked.timeout = 0x00; - crq.cooked.IU_length = length; - crq.cooked.IU_data_ptr = vio_iu(iue)->srp.rsp.tag; - - if (rc == 0) - crq.cooked.status = 0x99; /* Just needs to be non-zero */ - else - crq.cooked.status = 0x00; - - rc1 = h_send_crq(vport->dma_dev->unit_address, crq.raw[0], crq.raw[1]); - - if (rc1) { - eprintk("%ld sending response\n", rc1); - return rc1; - } - - return rc; -} - -#define SRP_RSP_SENSE_DATA_LEN 18 - -static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc, - unsigned char status, unsigned char asc) -{ - union viosrp_iu *iu = vio_iu(iue); - uint64_t tag = iu->srp.rsp.tag; - - /* If the linked bit is on and status is good */ - if (test_bit(V_LINKED, &iue->flags) && (status == NO_SENSE)) - status = 0x10; - - memset(iu, 0, sizeof(struct srp_rsp)); - iu->srp.rsp.opcode = SRP_RSP; - iu->srp.rsp.req_lim_delta = 1; - iu->srp.rsp.tag = tag; - - if (test_bit(V_DIOVER, &iue->flags)) - iu->srp.rsp.flags |= SRP_RSP_FLAG_DIOVER; - - iu->srp.rsp.data_in_res_cnt = 0; - iu->srp.rsp.data_out_res_cnt = 0; - - iu->srp.rsp.flags &= ~SRP_RSP_FLAG_RSPVALID; - - iu->srp.rsp.resp_data_len = 0; - iu->srp.rsp.status = status; - if (status) { - uint8_t *sense = iu->srp.rsp.data; - - if (sc) { - iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; - iu->srp.rsp.sense_data_len = SCSI_SENSE_BUFFERSIZE; - memcpy(sense, sc->sense_buffer, SCSI_SENSE_BUFFERSIZE); - } else { - iu->srp.rsp.status = SAM_STAT_CHECK_CONDITION; - iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; - iu->srp.rsp.sense_data_len = SRP_RSP_SENSE_DATA_LEN; - - /* Valid bit and 'current errors' */ - sense[0] = (0x1 << 7 | 0x70); - /* Sense key */ - sense[2] = status; - /* Additional sense length */ - sense[7] = 0xa; /* 10 bytes */ - /* Additional sense code */ - sense[12] = asc; - } - } - - send_iu(iue, sizeof(iu->srp.rsp) + SRP_RSP_SENSE_DATA_LEN, - VIOSRP_SRP_FORMAT); - - return 0; -} - -static void handle_cmd_queue(struct srp_target *target) -{ - struct Scsi_Host *shost = target->shost; - struct srp_rport *rport = target_to_port(target)->rport; - struct iu_entry *iue; - struct srp_cmd *cmd; - unsigned long flags; - int err; - -retry: - spin_lock_irqsave(&target->lock, flags); - - list_for_each_entry(iue, &target->cmd_queue, ilist) { - if (!test_and_set_bit(V_FLYING, &iue->flags)) { - spin_unlock_irqrestore(&target->lock, flags); - cmd = iue->sbuf->buf; - err = srp_cmd_queue(shost, cmd, iue, - (unsigned long)rport, 0); - if (err) { - eprintk("cannot queue cmd %p %d\n", cmd, err); - srp_iu_put(iue); - } - goto retry; - } - } - - spin_unlock_irqrestore(&target->lock, flags); -} - -static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg, - struct srp_direct_buf *md, int nmd, - enum dma_data_direction dir, unsigned int rest) -{ - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; - struct srp_target *target = iue->target; - struct vio_port *vport = target_to_port(target); - dma_addr_t token; - long err; - unsigned int done = 0; - int i, sidx, soff; - - sidx = soff = 0; - token = sg_dma_address(sg + sidx); - - for (i = 0; i < nmd && rest; i++) { - unsigned int mdone, mlen; - - mlen = min(rest, md[i].len); - for (mdone = 0; mlen;) { - int slen = min(sg_dma_len(sg + sidx) - soff, mlen); - - if (dir == DMA_TO_DEVICE) - err = h_copy_rdma(slen, - vport->riobn, - md[i].va + mdone, - vport->liobn, - token + soff); - else - err = h_copy_rdma(slen, - vport->liobn, - token + soff, - vport->riobn, - md[i].va + mdone); - - if (err != H_SUCCESS) { - eprintk("rdma error %d %d %ld\n", dir, slen, err); - return -EIO; - } - - mlen -= slen; - mdone += slen; - soff += slen; - done += slen; - - if (soff == sg_dma_len(sg + sidx)) { - sidx++; - soff = 0; - token = sg_dma_address(sg + sidx); - - if (sidx > nsg) { - eprintk("out of sg %p %d %d\n", - iue, sidx, nsg); - return -EIO; - } - } - }; - - rest -= mlen; - } - return 0; -} - -static int ibmvstgt_cmd_done(struct scsi_cmnd *sc, - void (*done)(struct scsi_cmnd *)) -{ - unsigned long flags; - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; - struct srp_target *target = iue->target; - int err = 0; - - dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0], - scsi_sg_count(sc)); - - if (scsi_sg_count(sc)) - err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); - - spin_lock_irqsave(&target->lock, flags); - list_del(&iue->ilist); - spin_unlock_irqrestore(&target->lock, flags); - - if (err|| sc->result != SAM_STAT_GOOD) { - eprintk("operation failed %p %d %x\n", - iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]); - send_rsp(iue, sc, HARDWARE_ERROR, 0x00); - } else - send_rsp(iue, sc, NO_SENSE, 0x00); - - done(sc); - srp_iu_put(iue); - return 0; -} - -int send_adapter_info(struct iu_entry *iue, - dma_addr_t remote_buffer, uint16_t length) -{ - struct srp_target *target = iue->target; - struct vio_port *vport = target_to_port(target); - struct Scsi_Host *shost = target->shost; - dma_addr_t data_token; - struct mad_adapter_info_data *info; - int err; - - info = dma_alloc_coherent(target->dev, sizeof(*info), &data_token, - GFP_KERNEL); - if (!info) { - eprintk("bad dma_alloc_coherent %p\n", target); - return 1; - } - - /* Get remote info */ - err = h_copy_rdma(sizeof(*info), vport->riobn, remote_buffer, - vport->liobn, data_token); - if (err == H_SUCCESS) { - dprintk("Client connect: %s (%d)\n", - info->partition_name, info->partition_number); - } - - memset(info, 0, sizeof(*info)); - - strcpy(info->srp_version, "16.a"); - strncpy(info->partition_name, partition_name, - sizeof(info->partition_name)); - info->partition_number = partition_number; - info->mad_version = 1; - info->os_type = 2; - info->port_max_txu[0] = shost->hostt->max_sectors << 9; - - /* Send our info to remote */ - err = h_copy_rdma(sizeof(*info), vport->liobn, data_token, - vport->riobn, remote_buffer); - - dma_free_coherent(target->dev, sizeof(*info), info, data_token); - - if (err != H_SUCCESS) { - eprintk("Error sending adapter info %d\n", err); - return 1; - } - - return 0; -} - -static void process_login(struct iu_entry *iue) -{ - union viosrp_iu *iu = vio_iu(iue); - struct srp_login_rsp *rsp = &iu->srp.login_rsp; - uint64_t tag = iu->srp.rsp.tag; - struct Scsi_Host *shost = iue->target->shost; - struct srp_target *target = host_to_srp_target(shost); - struct vio_port *vport = target_to_port(target); - struct srp_rport_identifiers ids; - - memset(&ids, 0, sizeof(ids)); - sprintf(ids.port_id, "%x", vport->dma_dev->unit_address); - ids.roles = SRP_RPORT_ROLE_INITIATOR; - if (!vport->rport) - vport->rport = srp_rport_add(shost, &ids); - - /* TODO handle case that requested size is wrong and - * buffer format is wrong - */ - memset(iu, 0, sizeof(struct srp_login_rsp)); - rsp->opcode = SRP_LOGIN_RSP; - rsp->req_lim_delta = INITIAL_SRP_LIMIT; - rsp->tag = tag; - rsp->max_it_iu_len = sizeof(union srp_iu); - rsp->max_ti_iu_len = sizeof(union srp_iu); - /* direct and indirect */ - rsp->buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; - - send_iu(iue, sizeof(*rsp), VIOSRP_SRP_FORMAT); -} - -static inline void queue_cmd(struct iu_entry *iue) -{ - struct srp_target *target = iue->target; - unsigned long flags; - - spin_lock_irqsave(&target->lock, flags); - list_add_tail(&iue->ilist, &target->cmd_queue); - spin_unlock_irqrestore(&target->lock, flags); -} - -static int process_tsk_mgmt(struct iu_entry *iue) -{ - union viosrp_iu *iu = vio_iu(iue); - int fn; - - dprintk("%p %u\n", iue, iu->srp.tsk_mgmt.tsk_mgmt_func); - - switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { - case SRP_TSK_ABORT_TASK: - fn = ABORT_TASK; - break; - case SRP_TSK_ABORT_TASK_SET: - fn = ABORT_TASK_SET; - break; - case SRP_TSK_CLEAR_TASK_SET: - fn = CLEAR_TASK_SET; - break; - case SRP_TSK_LUN_RESET: - fn = LOGICAL_UNIT_RESET; - break; - case SRP_TSK_CLEAR_ACA: - fn = CLEAR_ACA; - break; - default: - fn = 0; - } - if (fn) - scsi_tgt_tsk_mgmt_request(iue->target->shost, - (unsigned long)iue->target->shost, - fn, - iu->srp.tsk_mgmt.task_tag, - (struct scsi_lun *) &iu->srp.tsk_mgmt.lun, - iue); - else - send_rsp(iue, NULL, ILLEGAL_REQUEST, 0x20); - - return !fn; -} - -static int process_mad_iu(struct iu_entry *iue) -{ - union viosrp_iu *iu = vio_iu(iue); - struct viosrp_adapter_info *info; - struct viosrp_host_config *conf; - - switch (iu->mad.empty_iu.common.type) { - case VIOSRP_EMPTY_IU_TYPE: - eprintk("%s\n", "Unsupported EMPTY MAD IU"); - break; - case VIOSRP_ERROR_LOG_TYPE: - eprintk("%s\n", "Unsupported ERROR LOG MAD IU"); - iu->mad.error_log.common.status = 1; - send_iu(iue, sizeof(iu->mad.error_log), VIOSRP_MAD_FORMAT); - break; - case VIOSRP_ADAPTER_INFO_TYPE: - info = &iu->mad.adapter_info; - info->common.status = send_adapter_info(iue, info->buffer, - info->common.length); - send_iu(iue, sizeof(*info), VIOSRP_MAD_FORMAT); - break; - case VIOSRP_HOST_CONFIG_TYPE: - conf = &iu->mad.host_config; - conf->common.status = 1; - send_iu(iue, sizeof(*conf), VIOSRP_MAD_FORMAT); - break; - default: - eprintk("Unknown type %u\n", iu->srp.rsp.opcode); - } - - return 1; -} - -static int process_srp_iu(struct iu_entry *iue) -{ - union viosrp_iu *iu = vio_iu(iue); - int done = 1; - u8 opcode = iu->srp.rsp.opcode; - - switch (opcode) { - case SRP_LOGIN_REQ: - process_login(iue); - break; - case SRP_TSK_MGMT: - done = process_tsk_mgmt(iue); - break; - case SRP_CMD: - queue_cmd(iue); - done = 0; - break; - case SRP_LOGIN_RSP: - case SRP_I_LOGOUT: - case SRP_T_LOGOUT: - case SRP_RSP: - case SRP_CRED_REQ: - case SRP_CRED_RSP: - case SRP_AER_REQ: - case SRP_AER_RSP: - eprintk("Unsupported type %u\n", opcode); - break; - default: - eprintk("Unknown type %u\n", opcode); - } - - return done; -} - -static void process_iu(struct viosrp_crq *crq, struct srp_target *target) -{ - struct vio_port *vport = target_to_port(target); - struct iu_entry *iue; - long err; - int done = 1; - - iue = srp_iu_get(target); - if (!iue) { - eprintk("Error getting IU from pool, %p\n", target); - return; - } - - iue->remote_token = crq->IU_data_ptr; - - err = h_copy_rdma(crq->IU_length, vport->riobn, - iue->remote_token, vport->liobn, iue->sbuf->dma); - - if (err != H_SUCCESS) { - eprintk("%ld transferring data error %p\n", err, iue); - goto out; - } - - if (crq->format == VIOSRP_MAD_FORMAT) - done = process_mad_iu(iue); - else - done = process_srp_iu(iue); -out: - if (done) - srp_iu_put(iue); -} - -static irqreturn_t ibmvstgt_interrupt(int dummy, void *data) -{ - struct srp_target *target = data; - struct vio_port *vport = target_to_port(target); - - vio_disable_interrupts(vport->dma_dev); - queue_work(vtgtd, &vport->crq_work); - - return IRQ_HANDLED; -} - -static int crq_queue_create(struct crq_queue *queue, struct srp_target *target) -{ - int err; - struct vio_port *vport = target_to_port(target); - - queue->msgs = (struct viosrp_crq *) get_zeroed_page(GFP_KERNEL); - if (!queue->msgs) - goto malloc_failed; - queue->size = PAGE_SIZE / sizeof(*queue->msgs); - - queue->msg_token = dma_map_single(target->dev, queue->msgs, - queue->size * sizeof(*queue->msgs), - DMA_BIDIRECTIONAL); - - if (dma_mapping_error(target->dev, queue->msg_token)) - goto map_failed; - - err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token, - PAGE_SIZE); - - /* If the adapter was left active for some reason (like kexec) - * try freeing and re-registering - */ - if (err == H_RESOURCE) { - do { - err = h_free_crq(vport->dma_dev->unit_address); - } while (err == H_BUSY || H_IS_LONG_BUSY(err)); - - err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token, - PAGE_SIZE); - } - - if (err != H_SUCCESS && err != 2) { - eprintk("Error 0x%x opening virtual adapter\n", err); - goto reg_crq_failed; - } - - err = request_irq(vport->dma_dev->irq, &ibmvstgt_interrupt, - 0, "ibmvstgt", target); - if (err) - goto req_irq_failed; - - vio_enable_interrupts(vport->dma_dev); - - h_send_crq(vport->dma_dev->unit_address, 0xC001000000000000, 0); - - queue->cur = 0; - spin_lock_init(&queue->lock); - - return 0; - -req_irq_failed: - do { - err = h_free_crq(vport->dma_dev->unit_address); - } while (err == H_BUSY || H_IS_LONG_BUSY(err)); - -reg_crq_failed: - dma_unmap_single(target->dev, queue->msg_token, - queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); -map_failed: - free_page((unsigned long) queue->msgs); - -malloc_failed: - return -ENOMEM; -} - -static void crq_queue_destroy(struct srp_target *target) -{ - struct vio_port *vport = target_to_port(target); - struct crq_queue *queue = &vport->crq_queue; - int err; - - free_irq(vport->dma_dev->irq, target); - do { - err = h_free_crq(vport->dma_dev->unit_address); - } while (err == H_BUSY || H_IS_LONG_BUSY(err)); - - dma_unmap_single(target->dev, queue->msg_token, - queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); - - free_page((unsigned long) queue->msgs); -} - -static void process_crq(struct viosrp_crq *crq, struct srp_target *target) -{ - struct vio_port *vport = target_to_port(target); - dprintk("%x %x\n", crq->valid, crq->format); - - switch (crq->valid) { - case 0xC0: - /* initialization */ - switch (crq->format) { - case 0x01: - h_send_crq(vport->dma_dev->unit_address, - 0xC002000000000000, 0); - break; - case 0x02: - break; - default: - eprintk("Unknown format %u\n", crq->format); - } - break; - case 0xFF: - /* transport event */ - break; - case 0x80: - /* real payload */ - switch (crq->format) { - case VIOSRP_SRP_FORMAT: - case VIOSRP_MAD_FORMAT: - process_iu(crq, target); - break; - case VIOSRP_OS400_FORMAT: - case VIOSRP_AIX_FORMAT: - case VIOSRP_LINUX_FORMAT: - case VIOSRP_INLINE_FORMAT: - eprintk("Unsupported format %u\n", crq->format); - break; - default: - eprintk("Unknown format %u\n", crq->format); - } - break; - default: - eprintk("unknown message type 0x%02x!?\n", crq->valid); - } -} - -static inline struct viosrp_crq *next_crq(struct crq_queue *queue) -{ - struct viosrp_crq *crq; - unsigned long flags; - - spin_lock_irqsave(&queue->lock, flags); - crq = &queue->msgs[queue->cur]; - if (crq->valid & 0x80) { - if (++queue->cur == queue->size) - queue->cur = 0; - } else - crq = NULL; - spin_unlock_irqrestore(&queue->lock, flags); - - return crq; -} - -static void handle_crq(struct work_struct *work) -{ - struct vio_port *vport = container_of(work, struct vio_port, crq_work); - struct srp_target *target = vport->target; - struct viosrp_crq *crq; - int done = 0; - - while (!done) { - while ((crq = next_crq(&vport->crq_queue)) != NULL) { - process_crq(crq, target); - crq->valid = 0x00; - } - - vio_enable_interrupts(vport->dma_dev); - - crq = next_crq(&vport->crq_queue); - if (crq) { - vio_disable_interrupts(vport->dma_dev); - process_crq(crq, target); - crq->valid = 0x00; - } else - done = 1; - } - - handle_cmd_queue(target); -} - - -static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc) -{ - unsigned long flags; - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; - struct srp_target *target = iue->target; - - dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]); - - spin_lock_irqsave(&target->lock, flags); - list_del(&iue->ilist); - spin_unlock_irqrestore(&target->lock, flags); - - srp_iu_put(iue); - - return 0; -} - -static int ibmvstgt_tsk_mgmt_response(struct Scsi_Host *shost, - u64 itn_id, u64 mid, int result) -{ - struct iu_entry *iue = (struct iu_entry *) ((void *) mid); - union viosrp_iu *iu = vio_iu(iue); - unsigned char status, asc; - - eprintk("%p %d\n", iue, result); - status = NO_SENSE; - asc = 0; - - switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { - case SRP_TSK_ABORT_TASK: - asc = 0x14; - if (result) - status = ABORTED_COMMAND; - break; - default: - break; - } - - send_rsp(iue, NULL, status, asc); - srp_iu_put(iue); - - return 0; -} - -static int ibmvstgt_it_nexus_response(struct Scsi_Host *shost, u64 itn_id, - int result) -{ - struct srp_target *target = host_to_srp_target(shost); - struct vio_port *vport = target_to_port(target); - - if (result) { - eprintk("%p %d\n", shost, result); - srp_rport_del(vport->rport); - vport->rport = NULL; - } - return 0; -} - -static ssize_t system_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", system_id); -} - -static ssize_t partition_number_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%x\n", partition_number); -} - -static ssize_t unit_address_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct srp_target *target = host_to_srp_target(shost); - struct vio_port *vport = target_to_port(target); - return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address); -} - -static DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL); -static DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL); -static DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL); - -static struct device_attribute *ibmvstgt_attrs[] = { - &dev_attr_system_id, - &dev_attr_partition_number, - &dev_attr_unit_address, - NULL, -}; - -static struct scsi_host_template ibmvstgt_sht = { - .name = TGT_NAME, - .module = THIS_MODULE, - .can_queue = INITIAL_SRP_LIMIT, - .sg_tablesize = SG_ALL, - .use_clustering = DISABLE_CLUSTERING, - .max_sectors = DEFAULT_MAX_SECTORS, - .transfer_response = ibmvstgt_cmd_done, - .eh_abort_handler = ibmvstgt_eh_abort_handler, - .shost_attrs = ibmvstgt_attrs, - .proc_name = TGT_NAME, - .supported_mode = MODE_TARGET, -}; - -static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) -{ - struct Scsi_Host *shost; - struct srp_target *target; - struct vio_port *vport; - unsigned int *dma, dma_size; - int err = -ENOMEM; - - vport = kzalloc(sizeof(struct vio_port), GFP_KERNEL); - if (!vport) - return err; - shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target)); - if (!shost) - goto free_vport; - shost->transportt = ibmvstgt_transport_template; - - target = host_to_srp_target(shost); - target->shost = shost; - vport->dma_dev = dev; - target->ldata = vport; - vport->target = target; - err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT, - SRP_MAX_IU_LEN); - if (err) - goto put_host; - - dma = (unsigned int *) vio_get_attribute(dev, "ibm,my-dma-window", - &dma_size); - if (!dma || dma_size != 40) { - eprintk("Couldn't get window property %d\n", dma_size); - err = -EIO; - goto free_srp_target; - } - vport->liobn = dma[0]; - vport->riobn = dma[5]; - - INIT_WORK(&vport->crq_work, handle_crq); - - err = scsi_add_host(shost, target->dev); - if (err) - goto free_srp_target; - - err = scsi_tgt_alloc_queue(shost); - if (err) - goto remove_host; - - err = crq_queue_create(&vport->crq_queue, target); - if (err) - goto free_queue; - - return 0; -free_queue: - scsi_tgt_free_queue(shost); -remove_host: - scsi_remove_host(shost); -free_srp_target: - srp_target_free(target); -put_host: - scsi_host_put(shost); -free_vport: - kfree(vport); - return err; -} - -static int ibmvstgt_remove(struct vio_dev *dev) -{ - struct srp_target *target = dev_get_drvdata(&dev->dev); - struct Scsi_Host *shost = target->shost; - struct vio_port *vport = target->ldata; - - crq_queue_destroy(target); - srp_remove_host(shost); - scsi_remove_host(shost); - scsi_tgt_free_queue(shost); - srp_target_free(target); - kfree(vport); - scsi_host_put(shost); - return 0; -} - -static struct vio_device_id ibmvstgt_device_table[] = { - {"v-scsi-host", "IBM,v-scsi-host"}, - {"",""} -}; - -MODULE_DEVICE_TABLE(vio, ibmvstgt_device_table); - -static struct vio_driver ibmvstgt_driver = { - .id_table = ibmvstgt_device_table, - .probe = ibmvstgt_probe, - .remove = ibmvstgt_remove, - .name = "ibmvscsis", -}; - -static int get_system_info(void) -{ - struct device_node *rootdn; - const char *id, *model, *name; - const unsigned int *num; - - rootdn = of_find_node_by_path("/"); - if (!rootdn) - return -ENOENT; - - model = of_get_property(rootdn, "model", NULL); - id = of_get_property(rootdn, "system-id", NULL); - if (model && id) - snprintf(system_id, sizeof(system_id), "%s-%s", model, id); - - name = of_get_property(rootdn, "ibm,partition-name", NULL); - if (name) - strncpy(partition_name, name, sizeof(partition_name)); - - num = of_get_property(rootdn, "ibm,partition-no", NULL); - if (num) - partition_number = *num; - - of_node_put(rootdn); - return 0; -} - -static struct srp_function_template ibmvstgt_transport_functions = { - .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, - .it_nexus_response = ibmvstgt_it_nexus_response, -}; - -static int __init ibmvstgt_init(void) -{ - int err = -ENOMEM; - - printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n"); - - ibmvstgt_transport_template = - srp_attach_transport(&ibmvstgt_transport_functions); - if (!ibmvstgt_transport_template) - return err; - - vtgtd = create_workqueue("ibmvtgtd"); - if (!vtgtd) - goto release_transport; - - err = get_system_info(); - if (err) - goto destroy_wq; - - err = vio_register_driver(&ibmvstgt_driver); - if (err) - goto destroy_wq; - - return 0; -destroy_wq: - destroy_workqueue(vtgtd); -release_transport: - srp_release_transport(ibmvstgt_transport_template); - return err; -} - -static void __exit ibmvstgt_exit(void) -{ - printk("Unregister IBM virtual SCSI driver\n"); - - destroy_workqueue(vtgtd); - vio_unregister_driver(&ibmvstgt_driver); - srp_release_transport(ibmvstgt_transport_template); -} - -MODULE_DESCRIPTION("IBM Virtual SCSI Target"); -MODULE_AUTHOR("Santiago Leon"); -MODULE_LICENSE("GPL"); - -module_init(ibmvstgt_init); -module_exit(ibmvstgt_exit); diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index b1c4d83..ddf0694 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -2251,14 +2251,14 @@ static int in2000_show_info(struct seq_file *m, struct Scsi_Host *instance) seq_printf(m, "\nconnected: "); if (hd->connected) { cmd = (Scsi_Cmnd *) hd->connected; - seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); } } if (hd->proc & PR_INPUTQ) { seq_printf(m, "\ninput_Q: "); cmd = (Scsi_Cmnd *) hd->input_Q; while (cmd) { - seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); cmd = (Scsi_Cmnd *) cmd->host_scribble; } } @@ -2266,7 +2266,7 @@ static int in2000_show_info(struct seq_file *m, struct Scsi_Host *instance) seq_printf(m, "\ndisconnected_Q:"); cmd = (Scsi_Cmnd *) hd->disconnected_Q; while (cmd) { - seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); cmd = (Scsi_Cmnd *) cmd->host_scribble; } } diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 695b34e..4198e45 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -356,7 +356,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev) for (i = 0; i < num_msix; i++) pci_info->msix_entries[i].entry = i; - err = pci_enable_msix(pdev, pci_info->msix_entries, num_msix); + err = pci_enable_msix_exact(pdev, pci_info->msix_entries, num_msix); if (err) goto intx; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 3d1bc67..f9f3a12 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -260,7 +260,7 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) { struct iscsi_conn *conn = task->conn; struct iscsi_tm *tmf = &conn->tmhdr; - unsigned int hdr_lun; + u64 hdr_lun; if (conn->tmf_state == TMF_INITIAL) return 0; @@ -1859,8 +1859,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, * Fail commands. session lock held and recv side suspended and xmit * thread flushed */ -static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun, - int error) +static void fail_scsi_tasks(struct iscsi_conn *conn, u64 lun, int error) { struct iscsi_task *task; int i; @@ -2279,7 +2278,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; - ISCSI_DBG_EH(session, "LU Reset [sc %p lun %u]\n", sc, sc->device->lun); + ISCSI_DBG_EH(session, "LU Reset [sc %p lun %llu]\n", sc, + sc->device->lun); mutex_lock(&session->eh_mutex); spin_lock_bh(&session->frwd_lock); @@ -2971,7 +2971,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) */ for (;;) { spin_lock_irqsave(session->host->host_lock, flags); - if (!session->host->host_busy) { /* OK for ERL == 0 */ + if (!atomic_read(&session->host->host_busy)) { /* OK for ERL == 0 */ spin_unlock_irqrestore(session->host->host_lock, flags); break; } @@ -2979,7 +2979,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) msleep_interruptible(500); iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): " "host_busy %d host_failed %d\n", - session->host->host_busy, + atomic_read(&session->host->host_busy), session->host->host_failed); /* * force eh_abort() to unblock diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 25d0f127..24e477d 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -404,7 +404,7 @@ static int sas_recover_lu(struct domain_device *dev, struct scsi_cmnd *cmd) int_to_scsilun(cmd->device->lun, &lun); - SAS_DPRINTK("eh: device %llx LUN %x has the task\n", + SAS_DPRINTK("eh: device %llx LUN %llx has the task\n", SAS_ADDR(dev->sas_addr), cmd->device->lun); @@ -490,7 +490,8 @@ static void sas_wait_eh(struct domain_device *dev) } EXPORT_SYMBOL(sas_wait_eh); -static int sas_queue_reset(struct domain_device *dev, int reset_type, int lun, int wait) +static int sas_queue_reset(struct domain_device *dev, int reset_type, + u64 lun, int wait) { struct sas_ha_struct *ha = dev->port->ha; int scheduled = 0, tries = 100; @@ -689,7 +690,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * reset: tmf_resp = sas_recover_lu(task->dev, cmd); if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { - SAS_DPRINTK("dev %016llx LU %x is " + SAS_DPRINTK("dev %016llx LU %llx is " "recovered\n", SAS_ADDR(task->dev), cmd->device->lun); @@ -742,7 +743,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * * of effort could recover from errors. Quite * possibly the HA just disappeared. */ - SAS_DPRINTK("error from device %llx, LUN %x " + SAS_DPRINTK("error from device %llx, LUN %llx " "couldn't be recovered in any way\n", SAS_ADDR(task->dev->sas_addr), cmd->device->lun); @@ -812,7 +813,7 @@ retry: spin_unlock_irq(shost->host_lock); SAS_DPRINTK("Enter %s busy: %d failed: %d\n", - __func__, shost->host_busy, shost->host_failed); + __func__, atomic_read(&shost->host_busy), shost->host_failed); /* * Deal with commands that still have SAS tasks (i.e. they didn't * complete via the normal sas_task completion mechanism), @@ -857,7 +858,8 @@ out: goto retry; SAS_DPRINTK("--- Exit %s: busy: %d failed: %d tries: %d\n", - __func__, shost->host_busy, shost->host_failed, tries); + __func__, atomic_read(&shost->host_busy), + shost->host_failed, tries); } enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) @@ -941,7 +943,7 @@ int sas_slave_configure(struct scsi_device *scsi_dev) scsi_set_tag_type(scsi_dev, MSG_SIMPLE_TAG); scsi_activate_tcq(scsi_dev, SAS_DEF_QD); } else { - SAS_DPRINTK("device %llx, LUN %x doesn't support " + SAS_DPRINTK("device %llx, LUN %llx doesn't support " "TCQ\n", SAS_ADDR(dev->sas_addr), scsi_dev->lun); scsi_dev->tagged_supported = 0; diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c deleted file mode 100644 index 0707ecd..0000000 --- a/drivers/scsi/libsrp.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * SCSI RDMA Protocol lib functions - * - * Copyright (C) 2006 FUJITA Tomonori <tomof@acm.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/kfifo.h> -#include <linux/scatterlist.h> -#include <linux/dma-mapping.h> -#include <linux/module.h> -#include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_tcq.h> -#include <scsi/scsi_tgt.h> -#include <scsi/srp.h> -#include <scsi/libsrp.h> - -enum srp_task_attributes { - SRP_SIMPLE_TASK = 0, - SRP_HEAD_TASK = 1, - SRP_ORDERED_TASK = 2, - SRP_ACA_TASK = 4 -}; - -/* tmp - will replace with SCSI logging stuff */ -#define eprintk(fmt, args...) \ -do { \ - printk("%s(%d) " fmt, __func__, __LINE__, ##args); \ -} while (0) -/* #define dprintk eprintk */ -#define dprintk(fmt, args...) - -static int srp_iu_pool_alloc(struct srp_queue *q, size_t max, - struct srp_buf **ring) -{ - int i; - struct iu_entry *iue; - - q->pool = kcalloc(max, sizeof(struct iu_entry *), GFP_KERNEL); - if (!q->pool) - return -ENOMEM; - q->items = kcalloc(max, sizeof(struct iu_entry), GFP_KERNEL); - if (!q->items) - goto free_pool; - - spin_lock_init(&q->lock); - kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *)); - - for (i = 0, iue = q->items; i < max; i++) { - kfifo_in(&q->queue, (void *) &iue, sizeof(void *)); - iue->sbuf = ring[i]; - iue++; - } - return 0; - - kfree(q->items); -free_pool: - kfree(q->pool); - return -ENOMEM; -} - -static void srp_iu_pool_free(struct srp_queue *q) -{ - kfree(q->items); - kfree(q->pool); -} - -static struct srp_buf **srp_ring_alloc(struct device *dev, - size_t max, size_t size) -{ - int i; - struct srp_buf **ring; - - ring = kcalloc(max, sizeof(struct srp_buf *), GFP_KERNEL); - if (!ring) - return NULL; - - for (i = 0; i < max; i++) { - ring[i] = kzalloc(sizeof(struct srp_buf), GFP_KERNEL); - if (!ring[i]) - goto out; - ring[i]->buf = dma_alloc_coherent(dev, size, &ring[i]->dma, - GFP_KERNEL); - if (!ring[i]->buf) - goto out; - } - return ring; - -out: - for (i = 0; i < max && ring[i]; i++) { - if (ring[i]->buf) - dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma); - kfree(ring[i]); - } - kfree(ring); - - return NULL; -} - -static void srp_ring_free(struct device *dev, struct srp_buf **ring, size_t max, - size_t size) -{ - int i; - - for (i = 0; i < max; i++) { - dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma); - kfree(ring[i]); - } - kfree(ring); -} - -int srp_target_alloc(struct srp_target *target, struct device *dev, - size_t nr, size_t iu_size) -{ - int err; - - spin_lock_init(&target->lock); - INIT_LIST_HEAD(&target->cmd_queue); - - target->dev = dev; - dev_set_drvdata(target->dev, target); - - target->srp_iu_size = iu_size; - target->rx_ring_size = nr; - target->rx_ring = srp_ring_alloc(target->dev, nr, iu_size); - if (!target->rx_ring) - return -ENOMEM; - err = srp_iu_pool_alloc(&target->iu_queue, nr, target->rx_ring); - if (err) - goto free_ring; - - return 0; - -free_ring: - srp_ring_free(target->dev, target->rx_ring, nr, iu_size); - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(srp_target_alloc); - -void srp_target_free(struct srp_target *target) -{ - srp_ring_free(target->dev, target->rx_ring, target->rx_ring_size, - target->srp_iu_size); - srp_iu_pool_free(&target->iu_queue); -} -EXPORT_SYMBOL_GPL(srp_target_free); - -struct iu_entry *srp_iu_get(struct srp_target *target) -{ - struct iu_entry *iue = NULL; - - if (kfifo_out_locked(&target->iu_queue.queue, (void *) &iue, - sizeof(void *), &target->iu_queue.lock) != sizeof(void *)) { - WARN_ONCE(1, "unexpected fifo state"); - return NULL; - } - if (!iue) - return iue; - iue->target = target; - INIT_LIST_HEAD(&iue->ilist); - iue->flags = 0; - return iue; -} -EXPORT_SYMBOL_GPL(srp_iu_get); - -void srp_iu_put(struct iu_entry *iue) -{ - kfifo_in_locked(&iue->target->iu_queue.queue, (void *) &iue, - sizeof(void *), &iue->target->iu_queue.lock); -} -EXPORT_SYMBOL_GPL(srp_iu_put); - -static int srp_direct_data(struct scsi_cmnd *sc, struct srp_direct_buf *md, - enum dma_data_direction dir, srp_rdma_t rdma_io, - int dma_map, int ext_desc) -{ - struct iu_entry *iue = NULL; - struct scatterlist *sg = NULL; - int err, nsg = 0, len; - - if (dma_map) { - iue = (struct iu_entry *) sc->SCp.ptr; - sg = scsi_sglist(sc); - - dprintk("%p %u %u %d\n", iue, scsi_bufflen(sc), - md->len, scsi_sg_count(sc)); - - nsg = dma_map_sg(iue->target->dev, sg, scsi_sg_count(sc), - DMA_BIDIRECTIONAL); - if (!nsg) { - printk("fail to map %p %d\n", iue, scsi_sg_count(sc)); - return 0; - } - len = min(scsi_bufflen(sc), md->len); - } else - len = md->len; - - err = rdma_io(sc, sg, nsg, md, 1, dir, len); - - if (dma_map) - dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL); - - return err; -} - -static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, - struct srp_indirect_buf *id, - enum dma_data_direction dir, srp_rdma_t rdma_io, - int dma_map, int ext_desc) -{ - struct iu_entry *iue = NULL; - struct srp_direct_buf *md = NULL; - struct scatterlist dummy, *sg = NULL; - dma_addr_t token = 0; - int err = 0; - int nmd, nsg = 0, len; - - if (dma_map || ext_desc) { - iue = (struct iu_entry *) sc->SCp.ptr; - sg = scsi_sglist(sc); - - dprintk("%p %u %u %d %d\n", - iue, scsi_bufflen(sc), id->len, - cmd->data_in_desc_cnt, cmd->data_out_desc_cnt); - } - - nmd = id->table_desc.len / sizeof(struct srp_direct_buf); - - if ((dir == DMA_FROM_DEVICE && nmd == cmd->data_in_desc_cnt) || - (dir == DMA_TO_DEVICE && nmd == cmd->data_out_desc_cnt)) { - md = &id->desc_list[0]; - goto rdma; - } - - if (ext_desc && dma_map) { - md = dma_alloc_coherent(iue->target->dev, id->table_desc.len, - &token, GFP_KERNEL); - if (!md) { - eprintk("Can't get dma memory %u\n", id->table_desc.len); - return -ENOMEM; - } - - sg_init_one(&dummy, md, id->table_desc.len); - sg_dma_address(&dummy) = token; - sg_dma_len(&dummy) = id->table_desc.len; - err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE, - id->table_desc.len); - if (err) { - eprintk("Error copying indirect table %d\n", err); - goto free_mem; - } - } else { - eprintk("This command uses external indirect buffer\n"); - return -EINVAL; - } - -rdma: - if (dma_map) { - nsg = dma_map_sg(iue->target->dev, sg, scsi_sg_count(sc), - DMA_BIDIRECTIONAL); - if (!nsg) { - eprintk("fail to map %p %d\n", iue, scsi_sg_count(sc)); - err = -EIO; - goto free_mem; - } - len = min(scsi_bufflen(sc), id->len); - } else - len = id->len; - - err = rdma_io(sc, sg, nsg, md, nmd, dir, len); - - if (dma_map) - dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL); - -free_mem: - if (token && dma_map) - dma_free_coherent(iue->target->dev, id->table_desc.len, md, token); - - return err; -} - -static int data_out_desc_size(struct srp_cmd *cmd) -{ - int size = 0; - u8 fmt = cmd->buf_fmt >> 4; - - switch (fmt) { - case SRP_NO_DATA_DESC: - break; - case SRP_DATA_DESC_DIRECT: - size = sizeof(struct srp_direct_buf); - break; - case SRP_DATA_DESC_INDIRECT: - size = sizeof(struct srp_indirect_buf) + - sizeof(struct srp_direct_buf) * cmd->data_out_desc_cnt; - break; - default: - eprintk("client error. Invalid data_out_format %x\n", fmt); - break; - } - return size; -} - -/* - * TODO: this can be called multiple times for a single command if it - * has very long data. - */ -int srp_transfer_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, - srp_rdma_t rdma_io, int dma_map, int ext_desc) -{ - struct srp_direct_buf *md; - struct srp_indirect_buf *id; - enum dma_data_direction dir; - int offset, err = 0; - u8 format; - - offset = cmd->add_cdb_len & ~3; - - dir = srp_cmd_direction(cmd); - if (dir == DMA_FROM_DEVICE) - offset += data_out_desc_size(cmd); - - if (dir == DMA_TO_DEVICE) - format = cmd->buf_fmt >> 4; - else - format = cmd->buf_fmt & ((1U << 4) - 1); - - switch (format) { - case SRP_NO_DATA_DESC: - break; - case SRP_DATA_DESC_DIRECT: - md = (struct srp_direct_buf *) - (cmd->add_data + offset); - err = srp_direct_data(sc, md, dir, rdma_io, dma_map, ext_desc); - break; - case SRP_DATA_DESC_INDIRECT: - id = (struct srp_indirect_buf *) - (cmd->add_data + offset); - err = srp_indirect_data(sc, cmd, id, dir, rdma_io, dma_map, - ext_desc); - break; - default: - eprintk("Unknown format %d %x\n", dir, format); - err = -EINVAL; - } - - return err; -} -EXPORT_SYMBOL_GPL(srp_transfer_data); - -static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir) -{ - struct srp_direct_buf *md; - struct srp_indirect_buf *id; - int len = 0, offset = cmd->add_cdb_len & ~3; - u8 fmt; - - if (dir == DMA_TO_DEVICE) - fmt = cmd->buf_fmt >> 4; - else { - fmt = cmd->buf_fmt & ((1U << 4) - 1); - offset += data_out_desc_size(cmd); - } - - switch (fmt) { - case SRP_NO_DATA_DESC: - break; - case SRP_DATA_DESC_DIRECT: - md = (struct srp_direct_buf *) (cmd->add_data + offset); - len = md->len; - break; - case SRP_DATA_DESC_INDIRECT: - id = (struct srp_indirect_buf *) (cmd->add_data + offset); - len = id->len; - break; - default: - eprintk("invalid data format %x\n", fmt); - break; - } - return len; -} - -int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info, - u64 itn_id, u64 addr) -{ - enum dma_data_direction dir; - struct scsi_cmnd *sc; - int tag, len, err; - - switch (cmd->task_attr) { - case SRP_SIMPLE_TASK: - tag = MSG_SIMPLE_TAG; - break; - case SRP_ORDERED_TASK: - tag = MSG_ORDERED_TAG; - break; - case SRP_HEAD_TASK: - tag = MSG_HEAD_TAG; - break; - default: - eprintk("Task attribute %d not supported\n", cmd->task_attr); - tag = MSG_ORDERED_TAG; - } - - dir = srp_cmd_direction(cmd); - len = vscsis_data_length(cmd, dir); - - dprintk("%p %x %lx %d %d %d %llx\n", info, cmd->cdb[0], - cmd->lun, dir, len, tag, (unsigned long long) cmd->tag); - - sc = scsi_host_get_command(shost, dir, GFP_KERNEL); - if (!sc) - return -ENOMEM; - - sc->SCp.ptr = info; - memcpy(sc->cmnd, cmd->cdb, MAX_COMMAND_SIZE); - sc->sdb.length = len; - sc->sdb.table.sgl = (void *) (unsigned long) addr; - sc->tag = tag; - err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun, - cmd->tag); - if (err) - scsi_host_put_command(shost, sc); - - return err; -} -EXPORT_SYMBOL_GPL(srp_cmd_queue); - -MODULE_DESCRIPTION("SCSI RDMA Protocol lib functions"); -MODULE_AUTHOR("FUJITA Tomonori"); -MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 1d7a5c3..6eed9e7 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1998,6 +1998,14 @@ lpfc_vport_param_show(name)\ lpfc_vport_param_init(name, defval, minval, maxval)\ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) +#define LPFC_VPORT_ULL_ATTR_R(name, defval, minval, maxval, desc) \ +static uint64_t lpfc_##name = defval;\ +module_param(lpfc_##name, ullong, S_IRUGO);\ +MODULE_PARM_DESC(lpfc_##name, desc);\ +lpfc_vport_param_show(name)\ +lpfc_vport_param_init(name, defval, minval, maxval)\ +static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) + #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \ static uint lpfc_##name = defval;\ module_param(lpfc_##name, uint, S_IRUGO);\ @@ -4596,7 +4604,7 @@ LPFC_VPORT_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands " # Value range is [0,65535]. Default value is 255. # NOTE: The SCSI layer might probe all allowed LUN on some old targets. */ -LPFC_VPORT_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID"); +LPFC_VPORT_ULL_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID"); /* # lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring. diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 06f9a5b..a5769a9 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -8242,7 +8242,7 @@ lpfc_sli_enable_msix(struct lpfc_hba *phba) if (rc) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0420 PCI enable MSI-X failed (%d)\n", rc); - goto msi_fail_out; + goto vec_fail_out; } for (i = 0; i < LPFC_MSIX_VECTORS; i++) lpfc_printf_log(phba, KERN_INFO, LOG_INIT, @@ -8320,6 +8320,8 @@ irq_fail_out: msi_fail_out: /* Unconfigure MSI-X capability structure */ pci_disable_msix(phba->pcidev); + +vec_fail_out: return rc; } @@ -8812,7 +8814,7 @@ enable_msix_vectors: } else if (rc) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0484 PCI enable MSI-X failed (%d)\n", rc); - goto msi_fail_out; + goto vec_fail_out; } /* Log MSI-X vector assignment */ @@ -8875,9 +8877,10 @@ cfg_fail_out: &phba->sli4_hba.fcp_eq_hdl[index]); } -msi_fail_out: /* Unconfigure MSI-X capability structure */ pci_disable_msix(phba->pcidev); + +vec_fail_out: return rc; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 2df11da..7862c55 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -258,7 +258,7 @@ static void lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba, struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, - uint32_t lun, + uint64_t lun, uint32_t old_val, uint32_t new_val) { @@ -3823,7 +3823,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, if (rsplen != 0 && rsplen != 4 && rsplen != 8) { lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, "2719 Invalid response length: " - "tgt x%x lun x%x cmnd x%x rsplen x%x\n", + "tgt x%x lun x%llx cmnd x%x rsplen x%x\n", cmnd->device->id, cmnd->device->lun, cmnd->cmnd[0], rsplen); @@ -3834,7 +3834,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, "2757 Protocol failure detected during " "processing of FCP I/O op: " - "tgt x%x lun x%x cmnd x%x rspInfo3 x%x\n", + "tgt x%x lun x%llx cmnd x%x rspInfo3 x%x\n", cmnd->device->id, cmnd->device->lun, cmnd->cmnd[0], fcprsp->rspInfo3); @@ -4045,7 +4045,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, else logit = LOG_FCP | LOG_FCP_UNDER; lpfc_printf_vlog(vport, KERN_WARNING, logit, - "9030 FCP cmd x%x failed <%d/%d> " + "9030 FCP cmd x%x failed <%d/%lld> " "status: x%x result: x%x " "sid: x%x did: x%x oxid: x%x " "Data: x%x x%x\n", @@ -4157,7 +4157,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, uint32_t *lp = (uint32_t *)cmd->sense_buffer; lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, - "0710 Iodone <%d/%d> cmd %p, error " + "0710 Iodone <%d/%llu> cmd %p, error " "x%x SNS x%x x%x Data: x%x x%x\n", cmd->device->id, cmd->device->lun, cmd, cmd->result, *lp, *(lp + 3), cmd->retries, @@ -4390,7 +4390,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, static int lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, - unsigned int lun, + uint64_t lun, uint8_t task_mgmt_cmd) { struct lpfc_iocbq *piocbq; @@ -4719,12 +4719,12 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) atomic_dec(&ndlp->cmd_pending); lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, "3376 FCP could not issue IOCB err %x" - "FCP cmd x%x <%d/%d> " + "FCP cmd x%x <%d/%llu> " "sid: x%x did: x%x oxid: x%x " "Data: x%x x%x x%x x%x\n", err, cmnd->cmnd[0], cmnd->device ? cmnd->device->id : 0xffff, - cmnd->device ? cmnd->device->lun : 0xffff, + cmnd->device ? cmnd->device->lun : (u64) -1, vport->fc_myDID, ndlp->nlp_DID, phba->sli_rev == LPFC_SLI_REV4 ? lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff, @@ -4807,7 +4807,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "2873 SCSI Layer I/O Abort Request IO CMPL Status " - "x%x ID %d LUN %d\n", + "x%x ID %d LUN %llu\n", SUCCESS, cmnd->device->id, cmnd->device->lun); return SUCCESS; } @@ -4924,7 +4924,7 @@ wait_for_cmpl: lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, "0748 abort handler timed out waiting " "for abortng I/O (xri:x%x) to complete: " - "ret %#x, ID %d, LUN %d\n", + "ret %#x, ID %d, LUN %llu\n", iocb->sli4_xritag, ret, cmnd->device->id, cmnd->device->lun); } @@ -4935,7 +4935,7 @@ out_unlock: out: lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "0749 SCSI Layer I/O Abort Request Status x%x ID %d " - "LUN %d\n", ret, cmnd->device->id, + "LUN %llu\n", ret, cmnd->device->id, cmnd->device->lun); return ret; } @@ -5047,7 +5047,7 @@ lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd) **/ static int lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, - unsigned tgt_id, unsigned int lun_id, + unsigned tgt_id, uint64_t lun_id, uint8_t task_mgmt_cmd) { struct lpfc_hba *phba = vport->phba; @@ -5083,7 +5083,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, - "0702 Issue %s to TGT %d LUN %d " + "0702 Issue %s to TGT %d LUN %llu " "rpi x%x nlp_flag x%x Data: x%x x%x\n", lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, pnode->nlp_rpi, pnode->nlp_flag, iocbq->sli4_xritag, @@ -5094,7 +5094,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, if ((status != IOCB_SUCCESS) || (iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "0727 TMF %s to TGT %d LUN %d failed (%d, %d) " + "0727 TMF %s to TGT %d LUN %llu failed (%d, %d) " "iocb_flag x%x\n", lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, @@ -5238,7 +5238,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) struct lpfc_rport_data *rdata; struct lpfc_nodelist *pnode; unsigned tgt_id = cmnd->device->id; - unsigned int lun_id = cmnd->device->lun; + uint64_t lun_id = cmnd->device->lun; struct lpfc_scsi_event_header scsi_event; int status; @@ -5273,7 +5273,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) FCP_LUN_RESET); lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "0713 SCSI layer issued Device Reset (%d, %d) " + "0713 SCSI layer issued Device Reset (%d, %llu) " "return x%x\n", tgt_id, lun_id, status); /* @@ -5308,7 +5308,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) struct lpfc_rport_data *rdata; struct lpfc_nodelist *pnode; unsigned tgt_id = cmnd->device->id; - unsigned int lun_id = cmnd->device->lun; + uint64_t lun_id = cmnd->device->lun; struct lpfc_scsi_event_header scsi_event; int status; @@ -5343,7 +5343,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) FCP_TARGET_RESET); lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "0723 SCSI layer issued Target Reset (%d, %d) " + "0723 SCSI layer issued Target Reset (%d, %llu) " "return x%x\n", tgt_id, lun_id, status); /* diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index b777051..ac5d94c 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -1860,7 +1860,7 @@ megaraid_info(struct Scsi_Host *host) "LSI Logic MegaRAID %s %d commands %d targs %d chans %d luns", adapter->fw_version, adapter->product_info.max_commands, adapter->host->max_id, adapter->host->max_channel, - adapter->host->max_lun); + (u32)adapter->host->max_lun); return buffer; } @@ -1941,8 +1941,8 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) printk(KERN_WARNING "megaraid: %s cmd=%x <c=%d t=%d l=%d>\n", (aor == SCB_ABORT)? "ABORTING":"RESET", - cmd->cmnd[0], cmd->device->channel, - cmd->device->id, cmd->device->lun); + cmd->cmnd[0], cmd->device->channel, + cmd->device->id, (u32)cmd->device->lun); if(list_empty(&adapter->pending_list)) return FALSE; diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h index 5ead128..1d037ed 100644 --- a/drivers/scsi/megaraid/mega_common.h +++ b/drivers/scsi/megaraid/mega_common.h @@ -204,7 +204,7 @@ typedef struct { #define SCP2HOSTDATA(scp) SCP2HOST(scp)->hostdata // to soft state #define SCP2CHANNEL(scp) (scp)->device->channel // to channel #define SCP2TARGET(scp) (scp)->device->id // to target -#define SCP2LUN(scp) (scp)->device->lun // to LUN +#define SCP2LUN(scp) (u32)(scp)->device->lun // to LUN // generic macro to convert scsi command and host to controller's soft state #define SCSIHOST2ADAP(host) (((caddr_t *)(host->hostdata))[0]) diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 2260041..3ed03df 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -1690,7 +1690,7 @@ NonFastPath: MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); } io_request->RaidContext.VirtualDiskTgtId = cpu_to_le16(device_id); - io_request->LUN[1] = scmd->device->lun; + int_to_scsilun(scmd->device->lun, (struct scsi_lun *)io_request->LUN); } /** @@ -1713,7 +1713,7 @@ megasas_build_io_fusion(struct megasas_instance *instance, device_id = MEGASAS_DEV_INDEX(instance, scp); /* Zero out some fields so they don't get reused */ - io_request->LUN[1] = 0; + memset(io_request->LUN, 0x0, 8); io_request->CDB.EEDP32.PrimaryReferenceTag = 0; io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0; io_request->EEDPFlags = 0; diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index e8a04ae..7a6160f 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1230,7 +1230,7 @@ static void handle_msgin(struct mesh_state *ms) ms->msgphase = msg_out; } else if (code != cmd->device->lun + IDENTIFY_BASE) { printk(KERN_WARNING "mesh: lun mismatch " - "(%d != %d) on reselection from " + "(%d != %llu) on reselection from " "target %d\n", code - IDENTIFY_BASE, cmd->device->lun, ms->conn_tgt); } diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 8b88118..2f262be 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -277,7 +277,7 @@ mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc) ioc->fault_reset_work_q = NULL; spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); if (wq) { - if (!cancel_delayed_work(&ioc->fault_reset_work)) + if (!cancel_delayed_work_sync(&ioc->fault_reset_work)) flush_workqueue(wq); destroy_workqueue(wq); } @@ -1332,53 +1332,35 @@ _base_request_irq(struct MPT2SAS_ADAPTER *ioc, u8 index, u32 vector) static void _base_assign_reply_queues(struct MPT2SAS_ADAPTER *ioc) { - struct adapter_reply_queue *reply_q; - int cpu_id; - int cpu_grouping, loop, grouping, grouping_mod; + unsigned int cpu, nr_cpus, nr_msix, index = 0; if (!_base_is_controller_msix_enabled(ioc)) return; memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz); - /* when there are more cpus than available msix vectors, - * then group cpus togeather on same irq - */ - if (ioc->cpu_count > ioc->msix_vector_count) { - grouping = ioc->cpu_count / ioc->msix_vector_count; - grouping_mod = ioc->cpu_count % ioc->msix_vector_count; - if (grouping < 2 || (grouping == 2 && !grouping_mod)) - cpu_grouping = 2; - else if (grouping < 4 || (grouping == 4 && !grouping_mod)) - cpu_grouping = 4; - else if (grouping < 8 || (grouping == 8 && !grouping_mod)) - cpu_grouping = 8; - else - cpu_grouping = 16; - } else - cpu_grouping = 0; - - loop = 0; - reply_q = list_entry(ioc->reply_queue_list.next, - struct adapter_reply_queue, list); - for_each_online_cpu(cpu_id) { - if (!cpu_grouping) { - ioc->cpu_msix_table[cpu_id] = reply_q->msix_index; - reply_q = list_entry(reply_q->list.next, - struct adapter_reply_queue, list); - } else { - if (loop < cpu_grouping) { - ioc->cpu_msix_table[cpu_id] = - reply_q->msix_index; - loop++; - } else { - reply_q = list_entry(reply_q->list.next, - struct adapter_reply_queue, list); - ioc->cpu_msix_table[cpu_id] = - reply_q->msix_index; - loop = 1; - } + + nr_cpus = num_online_cpus(); + nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count, + ioc->facts.MaxMSIxVectors); + if (!nr_msix) + return; + + cpu = cpumask_first(cpu_online_mask); + + do { + unsigned int i, group = nr_cpus / nr_msix; + + if (index < nr_cpus % nr_msix) + group++; + + for (i = 0 ; i < group ; i++) { + ioc->cpu_msix_table[cpu] = index; + cpu = cpumask_next(cpu, cpu_online_mask); } - } + + index++; + + } while (cpu < nr_cpus); } /** @@ -4295,12 +4277,13 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) goto out_free_resources; if (ioc->is_warpdrive) { - ioc->reply_post_host_index[0] = - (resource_size_t *)&ioc->chip->ReplyPostHostIndex; + ioc->reply_post_host_index[0] = (resource_size_t __iomem *) + &ioc->chip->ReplyPostHostIndex; for (i = 1; i < ioc->cpu_msix_table_sz; i++) - ioc->reply_post_host_index[i] = (resource_size_t *) - ((u8 *)&ioc->chip->Doorbell + (0x4000 + ((i - 1) + ioc->reply_post_host_index[i] = + (resource_size_t __iomem *) + ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1) * 4))); } diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index fd3b998..0ac5815 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -837,7 +837,7 @@ struct MPT2SAS_ADAPTER { u8 msix_enable; u16 msix_vector_count; u8 *cpu_msix_table; - resource_size_t **reply_post_host_index; + resource_size_t __iomem **reply_post_host_index; u16 cpu_msix_table_sz; u32 ioc_reset_count; MPT2SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds; diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 5055f92..dd46101 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -173,7 +173,7 @@ struct fw_event_work { u8 VP_ID; u8 ignore; u16 event; - void *event_data; + char event_data[0] __aligned(4); }; /* raid transport support */ @@ -1292,7 +1292,8 @@ _scsih_target_alloc(struct scsi_target *starget) unsigned long flags; struct sas_rphy *rphy; - sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL); + sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data), + GFP_KERNEL); if (!sas_target_priv_data) return -ENOMEM; @@ -1406,7 +1407,8 @@ _scsih_slave_alloc(struct scsi_device *sdev) struct _sas_device *sas_device; unsigned long flags; - sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); + sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data), + GFP_KERNEL); if (!sas_device_priv_data) return -ENOMEM; @@ -2832,7 +2834,6 @@ _scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work spin_lock_irqsave(&ioc->fw_event_lock, flags); list_del(&fw_event->list); - kfree(fw_event->event_data); kfree(fw_event); spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } @@ -2899,11 +2900,10 @@ _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc) return; list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) { - if (cancel_delayed_work(&fw_event->delayed_work)) { + if (cancel_delayed_work_sync(&fw_event->delayed_work)) { _scsih_fw_event_free(ioc, fw_event); continue; } - fw_event->cancel_pending_work = 1; } } @@ -3518,7 +3518,8 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || fw_event->ignore) continue; - local_event_data = fw_event->event_data; + local_event_data = (Mpi2EventDataSasTopologyChangeList_t *) + fw_event->event_data; if (local_event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED || local_event_data->ExpStatus == @@ -5502,7 +5503,9 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u64 sas_address; unsigned long flags; u8 link_rate, prev_link_rate; - Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; + Mpi2EventDataSasTopologyChangeList_t *event_data = + (Mpi2EventDataSasTopologyChangeList_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -5697,7 +5700,8 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, u64 sas_address; unsigned long flags; Mpi2EventDataSasDeviceStatusChange_t *event_data = - fw_event->event_data; + (Mpi2EventDataSasDeviceStatusChange_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -5792,6 +5796,7 @@ _scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc, #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) _scsih_sas_enclosure_dev_status_change_event_debug(ioc, + (Mpi2EventDataSasEnclDevStatusChange_t *) fw_event->event_data); #endif } @@ -5816,7 +5821,9 @@ _scsih_sas_broadcast_primitive_event(struct MPT2SAS_ADAPTER *ioc, u32 termination_count; u32 query_count; Mpi2SCSITaskManagementReply_t *mpi_reply; - Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; + Mpi2EventDataSasBroadcastPrimitive_t *event_data = + (Mpi2EventDataSasBroadcastPrimitive_t *) + fw_event->event_data; u16 ioc_status; unsigned long flags; int r; @@ -5967,7 +5974,9 @@ static void _scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { - Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data; + Mpi2EventDataSasDiscovery_t *event_data = + (Mpi2EventDataSasDiscovery_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { @@ -6355,7 +6364,9 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, Mpi2EventIrConfigElement_t *element; int i; u8 foreign_config; - Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data; + Mpi2EventDataIrConfigChangeList_t *event_data = + (Mpi2EventDataIrConfigChangeList_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -6423,7 +6434,9 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u16 handle; u32 state; int rc; - Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; + Mpi2EventDataIrVolume_t *event_data = + (Mpi2EventDataIrVolume_t *) + fw_event->event_data; if (ioc->shost_recovery) return; @@ -6507,7 +6520,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; u32 ioc_status; - Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; + Mpi2EventDataIrPhysicalDisk_t *event_data = + (Mpi2EventDataIrPhysicalDisk_t *) + fw_event->event_data; u64 sas_address; if (ioc->shost_recovery) @@ -6630,7 +6645,9 @@ static void _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { - Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data; + Mpi2EventDataIrOperationStatus_t *event_data = + (Mpi2EventDataIrOperationStatus_t *) + fw_event->event_data; static struct _raid_device *raid_device; unsigned long flags; u16 handle; @@ -7401,7 +7418,7 @@ _firmware_event_work(struct work_struct *work) struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; /* the queue is being flushed so ignore this event */ - if (ioc->remove_host || fw_event->cancel_pending_work || + if (ioc->remove_host || ioc->pci_error_recovery) { _scsih_fw_event_free(ioc, fw_event); return; @@ -7590,23 +7607,15 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, return; } - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); - if (!fw_event) { - printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; - fw_event->event_data = kzalloc(sz, GFP_ATOMIC); - if (!fw_event->event_data) { + fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC); + if (!fw_event) { printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, __func__); - kfree(fw_event); return; } - memcpy(fw_event->event_data, mpi_reply->EventData, - sz); + memcpy(fw_event->event_data, mpi_reply->EventData, sz); fw_event->ioc = ioc; fw_event->VF_ID = mpi_reply->VF_ID; fw_event->VP_ID = mpi_reply->VP_ID; @@ -7857,9 +7866,9 @@ _scsih_remove(struct pci_dev *pdev) } sas_remove_host(shost); + scsi_remove_host(shost); mpt2sas_base_detach(ioc); list_del(&ioc->list); - scsi_remove_host(shost); scsi_host_put(shost); } @@ -8200,13 +8209,6 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } - if ((scsi_add_host(shost, &pdev->dev))) { - printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - list_del(&ioc->list); - goto out_add_shost_fail; - } - /* register EEDP capabilities with SCSI layer */ if (prot_mask) scsi_host_set_prot(shost, prot_mask); @@ -8248,16 +8250,23 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } else ioc->hide_drives = 0; + + if ((scsi_add_host(shost, &pdev->dev))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out_add_shost_fail; + } + scsi_scan_host(shost); return 0; + out_add_shost_fail: + mpt2sas_base_detach(ioc); out_attach_fail: destroy_workqueue(ioc->firmware_event_thread); out_thread_fail: list_del(&ioc->list); - scsi_remove_host(shost); - out_add_shost_fail: scsi_host_put(shost); return -ENODEV; } diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 0cf4f70..93ce2b2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -266,7 +266,7 @@ mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc) ioc->fault_reset_work_q = NULL; spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); if (wq) { - if (!cancel_delayed_work(&ioc->fault_reset_work)) + if (!cancel_delayed_work_sync(&ioc->fault_reset_work)) flush_workqueue(wq); destroy_workqueue(wq); } @@ -1624,66 +1624,35 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector) static void _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc) { - struct adapter_reply_queue *reply_q; - int cpu_id; - int cpu_grouping, loop, grouping, grouping_mod; - int reply_queue; + unsigned int cpu, nr_cpus, nr_msix, index = 0; if (!_base_is_controller_msix_enabled(ioc)) return; memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz); - /* NUMA Hardware bug workaround - drop to less reply queues */ - if (ioc->reply_queue_count > ioc->facts.MaxMSIxVectors) { - ioc->reply_queue_count = ioc->facts.MaxMSIxVectors; - reply_queue = 0; - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - reply_q->msix_index = reply_queue; - if (++reply_queue == ioc->reply_queue_count) - reply_queue = 0; - } - } + nr_cpus = num_online_cpus(); + nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count, + ioc->facts.MaxMSIxVectors); + if (!nr_msix) + return; - /* when there are more cpus than available msix vectors, - * then group cpus togeather on same irq - */ - if (ioc->cpu_count > ioc->msix_vector_count) { - grouping = ioc->cpu_count / ioc->msix_vector_count; - grouping_mod = ioc->cpu_count % ioc->msix_vector_count; - if (grouping < 2 || (grouping == 2 && !grouping_mod)) - cpu_grouping = 2; - else if (grouping < 4 || (grouping == 4 && !grouping_mod)) - cpu_grouping = 4; - else if (grouping < 8 || (grouping == 8 && !grouping_mod)) - cpu_grouping = 8; - else - cpu_grouping = 16; - } else - cpu_grouping = 0; - - loop = 0; - reply_q = list_entry(ioc->reply_queue_list.next, - struct adapter_reply_queue, list); - for_each_online_cpu(cpu_id) { - if (!cpu_grouping) { - ioc->cpu_msix_table[cpu_id] = reply_q->msix_index; - reply_q = list_entry(reply_q->list.next, - struct adapter_reply_queue, list); - } else { - if (loop < cpu_grouping) { - ioc->cpu_msix_table[cpu_id] = - reply_q->msix_index; - loop++; - } else { - reply_q = list_entry(reply_q->list.next, - struct adapter_reply_queue, list); - ioc->cpu_msix_table[cpu_id] = - reply_q->msix_index; - loop = 1; - } + cpu = cpumask_first(cpu_online_mask); + + do { + unsigned int i, group = nr_cpus / nr_msix; + + if (index < nr_cpus % nr_msix) + group++; + + for (i = 0 ; i < group ; i++) { + ioc->cpu_msix_table[cpu] = index; + cpu = cpumask_next(cpu, cpu_online_mask); } - } + + index++; + + } while (cpu < nr_cpus); } /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 18e713d..7cf48c5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -112,8 +112,8 @@ MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay"); /* scsi-mid layer global parmeter is max_report_luns, which is 511 */ #define MPT3SAS_MAX_LUN (16895) -static int max_lun = MPT3SAS_MAX_LUN; -module_param(max_lun, int, 0); +static u64 max_lun = MPT3SAS_MAX_LUN; +module_param(max_lun, ullong, 0); MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); @@ -190,7 +190,7 @@ struct fw_event_work { u8 VP_ID; u8 ignore; u16 event; - void *event_data; + char event_data[0] __aligned(4); }; /* raid transport support */ @@ -1163,7 +1163,8 @@ _scsih_target_alloc(struct scsi_target *starget) unsigned long flags; struct sas_rphy *rphy; - sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL); + sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data), + GFP_KERNEL); if (!sas_target_priv_data) return -ENOMEM; @@ -1277,7 +1278,8 @@ _scsih_slave_alloc(struct scsi_device *sdev) struct _sas_device *sas_device; unsigned long flags; - sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); + sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data), + GFP_KERNEL); if (!sas_device_priv_data) return -ENOMEM; @@ -2490,7 +2492,6 @@ _scsih_fw_event_free(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work spin_lock_irqsave(&ioc->fw_event_lock, flags); list_del(&fw_event->list); - kfree(fw_event->event_data); kfree(fw_event); spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } @@ -2511,12 +2512,10 @@ mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc, if (ioc->is_driver_loading) return; - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); + fw_event = kzalloc(sizeof(*fw_event) + sizeof(*event_data), + GFP_ATOMIC); if (!fw_event) return; - fw_event->event_data = kzalloc(sizeof(*event_data), GFP_ATOMIC); - if (!fw_event->event_data) - return; fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG; fw_event->ioc = ioc; memcpy(fw_event->event_data, event_data, sizeof(*event_data)); @@ -2582,11 +2581,10 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) return; list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) { - if (cancel_delayed_work(&fw_event->delayed_work)) { + if (cancel_delayed_work_sync(&fw_event->delayed_work)) { _scsih_fw_event_free(ioc, fw_event); continue; } - fw_event->cancel_pending_work = 1; } } @@ -3211,7 +3209,8 @@ _scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc, if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || fw_event->ignore) continue; - local_event_data = fw_event->event_data; + local_event_data = (Mpi2EventDataSasTopologyChangeList_t *) + fw_event->event_data; if (local_event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED || local_event_data->ExpStatus == @@ -5043,7 +5042,9 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, u64 sas_address; unsigned long flags; u8 link_rate, prev_link_rate; - Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; + Mpi2EventDataSasTopologyChangeList_t *event_data = + (Mpi2EventDataSasTopologyChangeList_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT3SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -5241,7 +5242,8 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, u64 sas_address; unsigned long flags; Mpi2EventDataSasDeviceStatusChange_t *event_data = - fw_event->event_data; + (Mpi2EventDataSasDeviceStatusChange_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT3SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -5337,6 +5339,7 @@ _scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc, #ifdef CONFIG_SCSI_MPT3SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) _scsih_sas_enclosure_dev_status_change_event_debug(ioc, + (Mpi2EventDataSasEnclDevStatusChange_t *) fw_event->event_data); #endif } @@ -5361,7 +5364,9 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc, u32 termination_count; u32 query_count; Mpi2SCSITaskManagementReply_t *mpi_reply; - Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; + Mpi2EventDataSasBroadcastPrimitive_t *event_data = + (Mpi2EventDataSasBroadcastPrimitive_t *) + fw_event->event_data; u16 ioc_status; unsigned long flags; int r; @@ -5513,7 +5518,8 @@ static void _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { - Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data; + Mpi2EventDataSasDiscovery_t *event_data = + (Mpi2EventDataSasDiscovery_t *) fw_event->event_data; #ifdef CONFIG_SCSI_MPT3SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { @@ -5999,7 +6005,9 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc, Mpi2EventIrConfigElement_t *element; int i; u8 foreign_config; - Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data; + Mpi2EventDataIrConfigChangeList_t *event_data = + (Mpi2EventDataIrConfigChangeList_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT3SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -6069,7 +6077,8 @@ _scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc, u16 handle; u32 state; int rc; - Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; + Mpi2EventDataIrVolume_t *event_data = + (Mpi2EventDataIrVolume_t *) fw_event->event_data; if (ioc->shost_recovery) return; @@ -6152,7 +6161,8 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; u32 ioc_status; - Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; + Mpi2EventDataIrPhysicalDisk_t *event_data = + (Mpi2EventDataIrPhysicalDisk_t *) fw_event->event_data; u64 sas_address; if (ioc->shost_recovery) @@ -6272,7 +6282,9 @@ static void _scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { - Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data; + Mpi2EventDataIrOperationStatus_t *event_data = + (Mpi2EventDataIrOperationStatus_t *) + fw_event->event_data; static struct _raid_device *raid_device; unsigned long flags; u16 handle; @@ -7026,7 +7038,7 @@ static void _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { /* the queue is being flushed so ignore this event */ - if (ioc->remove_host || fw_event->cancel_pending_work || + if (ioc->remove_host || ioc->pci_error_recovery) { _scsih_fw_event_free(ioc, fw_event); return; @@ -7034,7 +7046,9 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) switch (fw_event->event) { case MPT3SAS_PROCESS_TRIGGER_DIAG: - mpt3sas_process_trigger_data(ioc, fw_event->event_data); + mpt3sas_process_trigger_data(ioc, + (struct SL_WH_TRIGGERS_EVENT_DATA_T *) + fw_event->event_data); break; case MPT3SAS_REMOVE_UNRESPONDING_DEVICES: while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery) @@ -7192,18 +7206,11 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, return 1; } - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); - if (!fw_event) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 1; - } sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; - fw_event->event_data = kzalloc(sz, GFP_ATOMIC); - if (!fw_event->event_data) { + fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC); + if (!fw_event) { pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, __func__); - kfree(fw_event); return 1; } @@ -7431,9 +7438,9 @@ static void _scsih_remove(struct pci_dev *pdev) } sas_remove_host(shost); + scsi_remove_host(shost); mpt3sas_base_detach(ioc); list_del(&ioc->list); - scsi_remove_host(shost); scsi_host_put(shost); } @@ -7801,13 +7808,6 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } - if ((scsi_add_host(shost, &pdev->dev))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - list_del(&ioc->list); - goto out_add_shost_fail; - } - /* register EEDP capabilities with SCSI layer */ if (prot_mask > 0) scsi_host_set_prot(shost, prot_mask); @@ -7835,15 +7835,21 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->name, __FILE__, __LINE__, __func__); goto out_attach_fail; } + if ((scsi_add_host(shost, &pdev->dev))) { + pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + list_del(&ioc->list); + goto out_add_shost_fail; + } + scsi_scan_host(shost); return 0; - +out_add_shost_fail: + mpt3sas_base_detach(ioc); out_attach_fail: destroy_workqueue(ioc->firmware_event_thread); out_thread_fail: list_del(&ioc->list); - scsi_remove_host(shost); - out_add_shost_fail: scsi_host_put(shost); return -ENODEV; } diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 7d014b1..a7305ff 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -6633,7 +6633,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) ** patch requested size into sense command */ cp->sensecmd[0] = 0x03; - cp->sensecmd[1] = cmd->device->lun << 5; + cp->sensecmd[1] = (cmd->device->lun & 0x7) << 5; cp->sensecmd[4] = sizeof(cp->sense_buf); /* diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h index 0e008da..02901c5 100644 --- a/drivers/scsi/ncr53c8xx.h +++ b/drivers/scsi/ncr53c8xx.h @@ -264,11 +264,7 @@ #define SCSI_NCR_SG_TABLESIZE (SCSI_NCR_MAX_SCATTER) #define SCSI_NCR_TIMER_INTERVAL (HZ) -#if 1 /* defined CONFIG_SCSI_MULTI_LUN */ #define SCSI_NCR_MAX_LUN (16) -#else -#define SCSI_NCR_MAX_LUN (1) -#endif /* * IO functions definition for big/little endian CPU support. diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index 0665f9c..50b086a 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -915,7 +915,7 @@ static int nsp32_queuecommand_lck(struct scsi_cmnd *SCpnt, void (*done)(struct s int ret; nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, - "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x " + "enter. target: 0x%x LUN: 0x%llu cmnd: 0x%x cmndlen: 0x%x " "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x", SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd[0], SCpnt->cmd_len, scsi_sg_count(SCpnt), scsi_sglist(SCpnt), scsi_bufflen(SCpnt)); diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 0d78a4d..80bacb5 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -607,8 +607,6 @@ static int pas16_release(struct Scsi_Host *shost) if (shost->irq) free_irq(shost->irq, shost); NCR5380_exit(shost); - if (shost->dma_channel != 0xff) - free_dma(shost->dma_channel); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 987fbb1..340ceff 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -195,7 +195,7 @@ static int nsp_queuecommand_lck(struct scsi_cmnd *SCpnt, nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; nsp_dbg(NSP_DEBUG_QUEUECOMMAND, - "SCpnt=0x%p target=%d lun=%d sglist=0x%p bufflen=%d sg_count=%d", + "SCpnt=0x%p target=%d lun=%llu sglist=0x%p bufflen=%d sg_count=%d", SCpnt, target, SCpnt->device->lun, scsi_sglist(SCpnt), scsi_bufflen(SCpnt), scsi_sg_count(SCpnt)); //nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "before CurrentSC=0x%p", data->CurrentSC); diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index f5b5273..155f957 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -558,7 +558,7 @@ SYM53C500_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id, - SCpnt->device->lun, scsi_bufflen(SCpnt))); + (u8)SCpnt->device->lun, scsi_bufflen(SCpnt))); VDEB(for (i = 0; i < SCpnt->cmd_len; i++) printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i])); diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index a368d77..d3a08ae 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -397,7 +397,10 @@ static ssize_t pm8001_ctl_bios_version_show(struct device *cdev, payload.func_specific = kzalloc(4096, GFP_KERNEL); if (!payload.func_specific) return -ENOMEM; - PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); + if (PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload)) { + kfree(payload.func_specific); + return -ENOMEM; + } wait_for_completion(&completion); virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr; for (bios_index = BIOSOFFSET; bios_index < BIOS_OFFSET_LIMIT; @@ -614,11 +617,11 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) pm8001_ha->nvmd_completion = &completion; ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload); + if (ret) + break; wait_for_completion(&completion); - if (ret || (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS)) { + if (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS) { ret = fwControl->retcode; - kfree(ioctlbuffer); - ioctlbuffer = NULL; break; } } diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index a97be01..1738310 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1346,7 +1346,7 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, &pMessage) < 0) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("No free mpi buffer\n")); - return -1; + return -ENOMEM; } BUG_ON(!payload); /*Copy to the payload*/ @@ -1751,6 +1751,8 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha, task_abort.tag = cpu_to_le32(ccb_tag); ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); + if (ret) + pm8001_tag_free(pm8001_ha, ccb_tag); } @@ -1778,6 +1780,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); if (res) { + sas_free_task(task); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot allocate tag !!!\n")); return; @@ -1788,14 +1791,14 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, */ dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC); if (!dev) { + sas_free_task(task); + pm8001_tag_free(pm8001_ha, ccb_tag); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Domain device cannot be allocated\n")); - sas_free_task(task); return; - } else { - task->dev = dev; - task->dev->lldd_dev = pm8001_ha_dev; } + task->dev = dev; + task->dev->lldd_dev = pm8001_ha_dev; ccb = &pm8001_ha->ccb_info[ccb_tag]; ccb->device = pm8001_ha_dev; @@ -1821,7 +1824,11 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); - + if (res) { + sas_free_task(task); + pm8001_tag_free(pm8001_ha, ccb_tag); + kfree(dev); + } } /** @@ -3100,7 +3107,7 @@ void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, complete(pm8001_dev->setds_completion); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; - pm8001_ccb_free(pm8001_ha, tag); + pm8001_tag_free(pm8001_ha, tag); } void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) @@ -3119,13 +3126,12 @@ void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) } ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; - pm8001_ccb_free(pm8001_ha, tag); + pm8001_tag_free(pm8001_ha, tag); } void pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) { - struct fw_control_ex *fw_control_context; struct get_nvm_data_resp *pPayload = (struct get_nvm_data_resp *)(piomb + 4); u32 tag = le32_to_cpu(pPayload->tag); @@ -3134,7 +3140,6 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) u32 ir_tds_bn_dps_das_nvm = le32_to_cpu(pPayload->ir_tda_bn_dps_das_nvm); void *virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr; - fw_control_context = ccb->fw_control_context; PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Get nvm data complete!\n")); if ((dlen_status & NVMD_STAT) != 0) { @@ -3175,13 +3180,11 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("Get NVMD success, IR=0, dataLen=%d\n", (dlen_status & NVMD_LEN) >> 24)); } - memcpy(fw_control_context->usrAddr, - pm8001_ha->memoryMap.region[NVMD].virt_ptr, - fw_control_context->len); - complete(pm8001_ha->nvmd_completion); + kfree(ccb->fw_control_context); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; - pm8001_ccb_free(pm8001_ha, tag); + pm8001_tag_free(pm8001_ha, tag); + complete(pm8001_ha->nvmd_completion); } int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb) @@ -3588,7 +3591,7 @@ int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) complete(pm8001_dev->dcompletion); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; - pm8001_ccb_free(pm8001_ha, htag); + pm8001_tag_free(pm8001_ha, htag); return 0; } @@ -3617,15 +3620,11 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) { u32 status; - struct fw_control_ex fw_control_context; struct fw_flash_Update_resp *ppayload = (struct fw_flash_Update_resp *)(piomb + 4); u32 tag = le32_to_cpu(ppayload->tag); struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag]; status = le32_to_cpu(ppayload->status); - memcpy(&fw_control_context, - ccb->fw_control_context, - sizeof(fw_control_context)); switch (status) { case FLASH_UPDATE_COMPLETE_PENDING_REBOOT: PM8001_MSG_DBG(pm8001_ha, @@ -3668,11 +3667,11 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, pm8001_printk("No matched status = %d\n", status)); break; } - ccb->fw_control_context->fw_control->retcode = status; - complete(pm8001_ha->nvmd_completion); + kfree(ccb->fw_control_context); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; - pm8001_ccb_free(pm8001_ha, tag); + pm8001_tag_free(pm8001_ha, tag); + complete(pm8001_ha->nvmd_completion); return 0; } @@ -4257,7 +4256,11 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha, smp_cmd.long_smp_req.long_resp_size = cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4); build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd); - pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, + (u32 *)&smp_cmd, 0); + if (rc) + goto err_out_2; + return 0; err_out_2: @@ -4398,7 +4401,7 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, /* Check for read log for failed drive and return */ if (sata_cmd.sata_fis.command == 0x2f) { - if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) || + if (((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) || (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) || (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) { struct task_status_struct *ts; @@ -4789,6 +4792,10 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, break; } rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0); + if (rc) { + kfree(fw_control_context); + pm8001_tag_free(pm8001_ha, tag); + } return rc; } @@ -4869,6 +4876,10 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, break; } rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0); + if (rc) { + kfree(fw_control_context); + pm8001_tag_free(pm8001_ha, tag); + } return rc; } @@ -5061,7 +5072,7 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha) memset(&payload, 0, sizeof(payload)); rc = pm8001_tag_alloc(pm8001_ha, &tag); if (rc) - return -1; + return -ENOMEM; ccb = &pm8001_ha->ccb_info[tag]; ccb->ccb_tag = tag; circularQ = &pm8001_ha->inbnd_q_tbl[0]; @@ -5070,6 +5081,8 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha) payload.sata_hol_tmo = cpu_to_le32(80); payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); return rc; } diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e90c89f..e49623a 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -246,6 +246,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, { int i; spin_lock_init(&pm8001_ha->lock); + spin_lock_init(&pm8001_ha->bitmap_lock); PM8001_INIT_DBG(pm8001_ha, pm8001_printk("pm8001_alloc: PHY:%x\n", pm8001_ha->chip->n_phy)); @@ -621,6 +622,8 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) DECLARE_COMPLETION_ONSTACK(completion); struct pm8001_ioctl_payload payload; u16 deviceid; + int rc; + pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); pm8001_ha->nvmd_completion = &completion; @@ -638,7 +641,16 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) } payload.offset = 0; payload.func_specific = kzalloc(payload.length, GFP_KERNEL); - PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); + if (!payload.func_specific) { + PM8001_INIT_DBG(pm8001_ha, pm8001_printk("mem alloc fail\n")); + return; + } + rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); + if (rc) { + kfree(payload.func_specific); + PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n")); + return; + } wait_for_completion(&completion); for (i = 0, j = 0; i <= 7; i++, j++) { @@ -661,6 +673,7 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) pm8001_printk("phy %d sas_addr = %016llx\n", i, pm8001_ha->phy[i].dev_sas_addr)); } + kfree(payload.func_specific); #else for (i = 0; i < pm8001_ha->chip->n_phy; i++) { pm8001_ha->phy[i].dev_sas_addr = 0x50010c600047f9d0ULL; @@ -684,6 +697,7 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) /*OPTION ROM FLASH read for the SPC cards */ DECLARE_COMPLETION_ONSTACK(completion); struct pm8001_ioctl_payload payload; + int rc; pm8001_ha->nvmd_completion = &completion; /* SAS ADDRESS read from flash / EEPROM */ @@ -694,7 +708,12 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) if (!payload.func_specific) return -ENOMEM; /* Read phy setting values from flash */ - PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); + rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); + if (rc) { + kfree(payload.func_specific); + PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n")); + return -ENOMEM; + } wait_for_completion(&completion); pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific); kfree(payload.func_specific); @@ -744,9 +763,10 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) pm8001_ha->irq_vector[i].irq_id = i; pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; - if (request_irq(pm8001_ha->msix_entries[i].vector, + rc = request_irq(pm8001_ha->msix_entries[i].vector, pm8001_interrupt_handler_msix, flag, - intr_drvname[i], &(pm8001_ha->irq_vector[i]))) { + intr_drvname[i], &(pm8001_ha->irq_vector[i])); + if (rc) { for (j = 0; j < i; j++) free_irq( pm8001_ha->msix_entries[j].vector, @@ -964,6 +984,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) int i, j; u32 device_state; pm8001_ha = sha->lldd_ha; + sas_suspend_ha(sha); flush_workqueue(pm8001_wq); scsi_block_requests(pm8001_ha->shost); if (!pdev->pm_cap) { @@ -1013,6 +1034,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev) int rc; u8 i = 0, j; u32 device_state; + DECLARE_COMPLETION_ONSTACK(completion); pm8001_ha = sha->lldd_ha; device_state = pdev->current_state; @@ -1033,7 +1055,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev) rc = pci_go_44(pdev); if (rc) goto err_out_disable; - + sas_prep_resume_ha(sha); /* chip soft rst only for spc */ if (pm8001_ha->chip_id == chip_8001) { PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); @@ -1065,7 +1087,13 @@ static int pm8001_pci_resume(struct pci_dev *pdev) for (i = 1; i < pm8001_ha->number_of_intr; i++) PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); } - scsi_unblock_requests(pm8001_ha->shost); + pm8001_ha->flags = PM8001F_RUN_TIME; + for (i = 0; i < pm8001_ha->chip->n_phy; i++) { + pm8001_ha->phy[i].enable_completion = &completion; + PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i); + wait_for_completion(&completion); + } + sas_resume_ha(sha); return 0; err_out_disable: diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 8a44bc9..34cea82 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -58,25 +58,14 @@ static int pm8001_find_tag(struct sas_task *task, u32 *tag) } /** - * pm8001_tag_clear - clear the tags bitmap + * pm8001_tag_free - free the no more needed tag * @pm8001_ha: our hba struct * @tag: the found tag associated with the task */ -static void pm8001_tag_clear(struct pm8001_hba_info *pm8001_ha, u32 tag) -{ - void *bitmap = pm8001_ha->tags; - clear_bit(tag, bitmap); -} - void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag) { - pm8001_tag_clear(pm8001_ha, tag); -} - -static void pm8001_tag_set(struct pm8001_hba_info *pm8001_ha, u32 tag) -{ void *bitmap = pm8001_ha->tags; - set_bit(tag, bitmap); + clear_bit(tag, bitmap); } /** @@ -86,14 +75,18 @@ static void pm8001_tag_set(struct pm8001_hba_info *pm8001_ha, u32 tag) */ inline int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out) { - unsigned int index, tag; + unsigned int tag; void *bitmap = pm8001_ha->tags; + unsigned long flags; - index = find_first_zero_bit(bitmap, pm8001_ha->tags_num); - tag = index; - if (tag >= pm8001_ha->tags_num) + spin_lock_irqsave(&pm8001_ha->bitmap_lock, flags); + tag = find_first_zero_bit(bitmap, pm8001_ha->tags_num); + if (tag >= pm8001_ha->tags_num) { + spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags); return -SAS_QUEUE_FULL; - pm8001_tag_set(pm8001_ha, tag); + } + set_bit(tag, bitmap); + spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags); *tag_out = tag; return 0; } @@ -102,7 +95,7 @@ void pm8001_tag_init(struct pm8001_hba_info *pm8001_ha) { int i; for (i = 0; i < pm8001_ha->tags_num; ++i) - pm8001_tag_clear(pm8001_ha, i); + pm8001_tag_free(pm8001_ha, i); } /** @@ -501,11 +494,6 @@ int pm8001_queue_command(struct sas_task *task, const int num, return pm8001_task_exec(task, num, gfp_flags, 0, NULL); } -void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha, u32 ccb_idx) -{ - pm8001_tag_clear(pm8001_ha, ccb_idx); -} - /** * pm8001_ccb_task_free - free the sg for ssp and smp command, free the ccb. * @pm8001_ha: our hba card information @@ -542,7 +530,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha, ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; ccb->open_retry = 0; - pm8001_ccb_free(pm8001_ha, ccb_idx); + pm8001_tag_free(pm8001_ha, ccb_idx); } /** diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 1ee06f2..f6b2ac5 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -475,6 +475,7 @@ struct pm8001_hba_info { struct list_head list; unsigned long flags; spinlock_t lock;/* host-wide lock */ + spinlock_t bitmap_lock; struct pci_dev *pdev;/* our device */ struct device *dev; struct pm8001_hba_memspace io_mem[6]; @@ -616,7 +617,6 @@ extern struct workqueue_struct *pm8001_wq; int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out); void pm8001_tag_init(struct pm8001_hba_info *pm8001_ha); u32 pm8001_get_ncq_tag(struct sas_task *task, u32 *tag); -void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha, u32 ccb_idx); void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha, struct sas_task *task, struct pm8001_ccb_info *ccb, u32 ccb_idx); int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index d70587f..b06443a 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -856,6 +856,8 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); return rc; } @@ -936,6 +938,8 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha) sizeof(SASProtocolTimerConfig_t)); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); return rc; } @@ -948,7 +952,7 @@ static int pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) { u32 scratch3_value; - int ret; + int ret = -1; /* Read encryption status from SCRATCH PAD 3 */ scratch3_value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3); @@ -982,7 +986,7 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) pm8001_ha->encrypt_info.status = 0xFFFFFFFF; pm8001_ha->encrypt_info.cipher_mode = 0; pm8001_ha->encrypt_info.sec_mode = 0; - return 0; + ret = 0; } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) == SCRATCH_PAD3_ENC_DIS_ERR) { pm8001_ha->encrypt_info.status = @@ -1004,7 +1008,6 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) scratch3_value, pm8001_ha->encrypt_info.cipher_mode, pm8001_ha->encrypt_info.sec_mode, pm8001_ha->encrypt_info.status)); - ret = -1; } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) == SCRATCH_PAD3_ENC_ENA_ERR) { @@ -1028,7 +1031,6 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) scratch3_value, pm8001_ha->encrypt_info.cipher_mode, pm8001_ha->encrypt_info.sec_mode, pm8001_ha->encrypt_info.status)); - ret = -1; } return ret; } @@ -1059,6 +1061,8 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha) KEK_MGMT_SUBOP_KEYCARDUPDATE); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); return rc; } @@ -1383,8 +1387,10 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, task->task_done = pm8001_task_done; res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); - if (res) + if (res) { + sas_free_task(task); return; + } ccb = &pm8001_ha->ccb_info[ccb_tag]; ccb->device = pm8001_ha_dev; @@ -1399,7 +1405,10 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, task_abort.tag = cpu_to_le32(ccb_tag); ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); - + if (ret) { + sas_free_task(task); + pm8001_tag_free(pm8001_ha, ccb_tag); + } } static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, @@ -1426,6 +1435,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); if (res) { + sas_free_task(task); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot allocate tag !!!\n")); return; @@ -1436,15 +1446,16 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, */ dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC); if (!dev) { + sas_free_task(task); + pm8001_tag_free(pm8001_ha, ccb_tag); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Domain device cannot be allocated\n")); - sas_free_task(task); return; - } else { - task->dev = dev; - task->dev->lldd_dev = pm8001_ha_dev; } + task->dev = dev; + task->dev->lldd_dev = pm8001_ha_dev; + ccb = &pm8001_ha->ccb_info[ccb_tag]; ccb->device = pm8001_ha_dev; ccb->ccb_tag = ccb_tag; @@ -1469,7 +1480,11 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); - + if (res) { + sas_free_task(task); + pm8001_tag_free(pm8001_ha, ccb_tag); + kfree(dev); + } } /** @@ -3815,7 +3830,10 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd, pm8001_ha->smp_exp_mode, length); - pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, + (u32 *)&smp_cmd, 0); + if (rc) + goto err_out_2; return 0; err_out_2: @@ -4406,6 +4424,8 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, SAS_ADDR_SIZE); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); return rc; } @@ -4484,7 +4504,9 @@ void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i)); j++; } - pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); } void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index be8ce54..017f8b9 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -237,7 +237,7 @@ static int pmcraid_slave_configure(struct scsi_device *scsi_dev) scsi_dev->host->unique_id, scsi_dev->channel, scsi_dev->id, - scsi_dev->lun); + (u8)scsi_dev->lun); if (RES_IS_GSCSI(res->cfg_entry)) { scsi_dev->allow_restart = 1; diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c index e6e2a30..ef23fab 100644 --- a/drivers/scsi/ps3rom.c +++ b/drivers/scsi/ps3rom.c @@ -78,7 +78,7 @@ static int ps3rom_slave_configure(struct scsi_device *scsi_dev) struct ps3rom_private *priv = shost_priv(scsi_dev->host); struct ps3_storage_device *dev = priv->dev; - dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %u, channel %u\n", __func__, + dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %llu, channel %u\n", __func__, __LINE__, scsi_dev->id, scsi_dev->lun, scsi_dev->channel); /* diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index de5d0ae..b643991 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -320,8 +320,8 @@ struct srb_iocb { * defined in tsk_mgmt_entry struct * for control_flags field in qla_fw.h. */ + uint64_t lun; uint32_t flags; - uint32_t lun; uint32_t data; struct completion comp; __le16 comp_status; @@ -2529,8 +2529,8 @@ struct isp_operations { void (*disable_intrs) (struct qla_hw_data *); int (*abort_command) (srb_t *); - int (*target_reset) (struct fc_port *, unsigned int, int); - int (*lun_reset) (struct fc_port *, unsigned int, int); + int (*target_reset) (struct fc_port *, uint64_t, int); + int (*lun_reset) (struct fc_port *, uint64_t, int); int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t, uint8_t, uint8_t, uint16_t *, uint8_t); int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t, diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index d48dea8..d646540 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -113,7 +113,7 @@ extern int ql2xenabledif; extern int ql2xenablehba_err_chk; extern int ql2xtargetreset; extern int ql2xdontresethba; -extern unsigned int ql2xmaxlun; +extern uint64_t ql2xmaxlun; extern int ql2xmdcapmask; extern int ql2xmdenable; @@ -212,7 +212,7 @@ extern void qla2x00_build_scsi_iocbs_64(srb_t *, cmd_entry_t *, uint16_t); extern int qla2x00_start_scsi(srb_t *sp); extern int qla24xx_start_scsi(srb_t *sp); int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, - uint16_t, uint16_t, uint8_t); + uint16_t, uint64_t, uint8_t); extern int qla2x00_start_sp(srb_t *); extern int qla24xx_dif_start_scsi(srb_t *); extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t); @@ -262,10 +262,10 @@ extern int qla2x00_abort_command(srb_t *); extern int -qla2x00_abort_target(struct fc_port *, unsigned int, int); +qla2x00_abort_target(struct fc_port *, uint64_t, int); extern int -qla2x00_lun_reset(struct fc_port *, unsigned int, int); +qla2x00_lun_reset(struct fc_port *, uint64_t, int); extern int qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, @@ -339,12 +339,12 @@ qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *, extern int qla24xx_abort_command(srb_t *); extern int qla24xx_async_abort_command(srb_t *); extern int -qla24xx_abort_target(struct fc_port *, unsigned int, int); +qla24xx_abort_target(struct fc_port *, uint64_t, int); extern int -qla24xx_lun_reset(struct fc_port *, unsigned int, int); +qla24xx_lun_reset(struct fc_port *, uint64_t, int); extern int qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *, unsigned int, - unsigned int, enum nexus_wait_type); + uint64_t, enum nexus_wait_type); extern int qla2x00_system_error(scsi_qla_host_t *); @@ -617,8 +617,8 @@ extern char *qlafx00_fw_version_str(struct scsi_qla_host *, char *); extern irqreturn_t qlafx00_intr_handler(int, void *); extern void qlafx00_enable_intrs(struct qla_hw_data *); extern void qlafx00_disable_intrs(struct qla_hw_data *); -extern int qlafx00_abort_target(fc_port_t *, unsigned int, int); -extern int qlafx00_lun_reset(fc_port_t *, unsigned int, int); +extern int qlafx00_abort_target(fc_port_t *, uint64_t, int); +extern int qlafx00_lun_reset(fc_port_t *, uint64_t, int); extern int qlafx00_start_scsi(srb_t *); extern int qlafx00_abort_isp(scsi_qla_host_t *); extern int qlafx00_iospace_config(struct qla_hw_data *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e218441..46990f4 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1526,8 +1526,8 @@ try_fce: FCE_SIZE, ha->fce, ha->fce_dma); /* Allocate memory for Fibre Channel Event Buffer. */ - tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, - GFP_KERNEL); + tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, + GFP_KERNEL); if (!tc) { ql_log(ql_log_warn, vha, 0x00be, "Unable to allocate (%d KB) for FCE.\n", @@ -1535,7 +1535,6 @@ try_fce: goto try_eft; } - memset(tc, 0, FCE_SIZE); rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS, ha->fce_mb, &ha->fce_bufs); if (rval) { @@ -1560,8 +1559,8 @@ try_eft: EFT_SIZE, ha->eft, ha->eft_dma); /* Allocate memory for Extended Trace Buffer. */ - tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, - GFP_KERNEL); + tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, + GFP_KERNEL); if (!tc) { ql_log(ql_log_warn, vha, 0x00c1, "Unable to allocate (%d KB) for EFT.\n", @@ -1569,7 +1568,6 @@ try_eft: goto cont_alloc; } - memset(tc, 0, EFT_SIZE); rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS); if (rval) { ql_log(ql_log_warn, vha, 0x00c2, diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 7609315..150529d 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -520,7 +520,7 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) static int __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, struct rsp_que *rsp, uint16_t loop_id, - uint16_t lun, uint8_t type) + uint64_t lun, uint8_t type) { mrk_entry_t *mrk; struct mrk_entry_24xx *mrk24 = NULL; @@ -543,14 +543,13 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, if (IS_FWI2_CAPABLE(ha)) { mrk24 = (struct mrk_entry_24xx *) mrk; mrk24->nport_handle = cpu_to_le16(loop_id); - mrk24->lun[1] = LSB(lun); - mrk24->lun[2] = MSB(lun); + 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); } else { SET_TARGET_ID(ha, mrk->target, loop_id); - mrk->lun = cpu_to_le16(lun); + mrk->lun = cpu_to_le16((uint16_t)lun); } } wmb(); @@ -562,7 +561,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, int qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, - struct rsp_que *rsp, uint16_t loop_id, uint16_t lun, + struct rsp_que *rsp, uint16_t loop_id, uint64_t lun, uint8_t type) { int ret; @@ -2047,7 +2046,7 @@ static void qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) { uint32_t flags; - unsigned int lun; + uint64_t lun; struct fc_port *fcport = sp->fcport; scsi_qla_host_t *vha = fcport->vha; struct qla_hw_data *ha = vha->hw; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index a56825c..550a4a3 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1659,7 +1659,7 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, if (sense_len) { ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x301c, - "Check condition Sense data, nexus%ld:%d:%d cmd=%p.\n", + "Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n", sp->fcport->vha->host_no, cp->device->id, cp->device->lun, cp); ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302b, @@ -2281,7 +2281,7 @@ check_scsi_status: out: if (logit) ql_dbg(ql_dbg_io, fcport->vha, 0x3022, - "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%d " + "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu " "portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x " "rsp_info=0x%x resid=0x%x fw_resid=0x%x.\n", comp_status, scsi_status, res, vha->host_no, diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 1c33a77..d9aafc0 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -947,7 +947,7 @@ qla2x00_abort_command(srb_t *sp) } int -qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) +qla2x00_abort_target(struct fc_port *fcport, uint64_t l, int tag) { int rval, rval2; mbx_cmd_t mc; @@ -1000,7 +1000,7 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) } int -qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag) +qla2x00_lun_reset(struct fc_port *fcport, uint64_t l, int tag) { int rval, rval2; mbx_cmd_t mc; @@ -1022,7 +1022,7 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag) mcp->mb[1] = fcport->loop_id; else mcp->mb[1] = fcport->loop_id << 8; - mcp->mb[2] = l; + mcp->mb[2] = (u32)l; mcp->mb[3] = 0; mcp->mb[9] = vha->vp_idx; @@ -2666,7 +2666,7 @@ struct tsk_mgmt_cmd { static int __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, - unsigned int l, int tag) + uint64_t l, int tag) { int rval, rval2; struct tsk_mgmt_cmd *tsk; @@ -2760,7 +2760,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, } int -qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag) +qla24xx_abort_target(struct fc_port *fcport, uint64_t l, int tag) { struct qla_hw_data *ha = fcport->vha->hw; @@ -2771,7 +2771,7 @@ qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag) } int -qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag) +qla24xx_lun_reset(struct fc_port *fcport, uint64_t l, int tag) { struct qla_hw_data *ha = fcport->vha->hw; diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index abeb390..4775baa 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -726,13 +726,13 @@ qlafx00_disable_intrs(struct qla_hw_data *ha) } int -qlafx00_abort_target(fc_port_t *fcport, unsigned int l, int tag) +qlafx00_abort_target(fc_port_t *fcport, uint64_t l, int tag) { return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag); } int -qlafx00_lun_reset(fc_port_t *fcport, unsigned int l, int tag) +qlafx00_lun_reset(fc_port_t *fcport, uint64_t l, int tag) { return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag); } @@ -2159,7 +2159,7 @@ qlafx00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, if (sense_len) { ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3039, - "Check condition Sense data, nexus%ld:%d:%d cmd=%p.\n", + "Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n", sp->fcport->vha->host_no, cp->device->id, cp->device->lun, cp); ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3049, @@ -2524,7 +2524,7 @@ check_scsi_status: if (logit) ql_dbg(ql_dbg_io, fcport->vha, 0x3058, - "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%d " + "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu " "tgt_id: 0x%x lscsi_status: 0x%x cdb=%10phN len=0x%x " "rsp_info=0x%x resid=0x%x fw_resid=0x%x sense_len=0x%x, " "par_sense_len=0x%x, rsp_info_len=0x%x\n", diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d96bfb5..be9698d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -202,8 +202,8 @@ MODULE_PARM_DESC(ql2xdontresethba, " 0 (Default) -- Reset on failure.\n" " 1 -- Do not reset on failure.\n"); -uint ql2xmaxlun = MAX_LUNS; -module_param(ql2xmaxlun, uint, S_IRUGO); +uint64_t ql2xmaxlun = MAX_LUNS; +module_param(ql2xmaxlun, ullong, S_IRUGO); MODULE_PARM_DESC(ql2xmaxlun, "Defines the maximum LU number to register with the SCSI " "midlayer. Default is 65535."); @@ -920,7 +920,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) scsi_qla_host_t *vha = shost_priv(cmd->device->host); srb_t *sp; int ret; - unsigned int id, lun; + unsigned int id; + uint64_t lun; unsigned long flags; int rval, wait = 0; struct qla_hw_data *ha = vha->hw; @@ -944,7 +945,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) } ql_dbg(ql_dbg_taskm, vha, 0x8002, - "Aborting from RISC nexus=%ld:%d:%d sp=%p cmd=%p\n", + "Aborting from RISC nexus=%ld:%d:%llu sp=%p cmd=%p\n", vha->host_no, id, lun, sp, cmd); /* Get a reference to the sp and drop the lock.*/ @@ -995,7 +996,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) } ql_log(ql_log_info, vha, 0x801c, - "Abort command issued nexus=%ld:%d:%d -- %d %x.\n", + "Abort command issued nexus=%ld:%d:%llu -- %d %x.\n", vha->host_no, id, lun, wait, ret); return ret; @@ -1003,7 +1004,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) int qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, - unsigned int l, enum nexus_wait_type type) + uint64_t l, enum nexus_wait_type type) { int cnt, match, status; unsigned long flags; @@ -1060,7 +1061,7 @@ static char *reset_errors[] = { static int __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, - struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int, int)) + struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, uint64_t, int)) { scsi_qla_host_t *vha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; @@ -1075,7 +1076,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, return err; ql_log(ql_log_info, vha, 0x8009, - "%s RESET ISSUED nexus=%ld:%d:%d cmd=%p.\n", name, vha->host_no, + "%s RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", name, vha->host_no, cmd->device->id, cmd->device->lun, cmd); err = 0; @@ -1100,14 +1101,14 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, } ql_log(ql_log_info, vha, 0x800e, - "%s RESET SUCCEEDED nexus:%ld:%d:%d cmd=%p.\n", name, + "%s RESET SUCCEEDED nexus:%ld:%d:%llu cmd=%p.\n", name, vha->host_no, cmd->device->id, cmd->device->lun, cmd); return SUCCESS; eh_reset_failed: ql_log(ql_log_info, vha, 0x800f, - "%s RESET FAILED: %s nexus=%ld:%d:%d cmd=%p.\n", name, + "%s RESET FAILED: %s nexus=%ld:%d:%llu cmd=%p.\n", name, reset_errors[err], vha->host_no, cmd->device->id, cmd->device->lun, cmd); return FAILED; @@ -1154,7 +1155,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) scsi_qla_host_t *vha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; int ret = FAILED; - unsigned int id, lun; + unsigned int id; + uint64_t lun; id = cmd->device->id; lun = cmd->device->lun; @@ -1169,7 +1171,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) ret = FAILED; ql_log(ql_log_info, vha, 0x8012, - "BUS RESET ISSUED nexus=%ld:%d:%d.\n", vha->host_no, id, lun); + "BUS RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun); if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { ql_log(ql_log_fatal, vha, 0x8013, @@ -1193,7 +1195,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) eh_bus_reset_done: ql_log(ql_log_warn, vha, 0x802b, - "BUS RESET %s nexus=%ld:%d:%d.\n", + "BUS RESET %s nexus=%ld:%d:%llu.\n", (ret == FAILED) ? "FAILED" : "SUCCEEDED", vha->host_no, id, lun); return ret; @@ -1220,14 +1222,15 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) scsi_qla_host_t *vha = shost_priv(cmd->device->host); struct qla_hw_data *ha = vha->hw; int ret = FAILED; - unsigned int id, lun; + unsigned int id; + uint64_t lun; scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); id = cmd->device->id; lun = cmd->device->lun; ql_log(ql_log_info, vha, 0x8018, - "ADAPTER RESET ISSUED nexus=%ld:%d:%d.\n", vha->host_no, id, lun); + "ADAPTER RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun); /* * No point in issuing another reset if one is active. Also do not @@ -1273,7 +1276,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) eh_host_reset_lock: ql_log(ql_log_info, vha, 0x8017, - "ADAPTER RESET %s nexus=%ld:%d:%d.\n", + "ADAPTER RESET %s nexus=%ld:%d:%llu.\n", (ret == FAILED) ? "FAILED" : "SUCCEEDED", vha->host_no, id, lun); return ret; @@ -1409,7 +1412,7 @@ static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth) return; ql_dbg(ql_dbg_io, fcport->vha, 0x3029, - "Queue depth adjusted-down to %d for nexus=%ld:%d:%d.\n", + "Queue depth adjusted-down to %d for nexus=%ld:%d:%llu.\n", sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun); } @@ -1432,7 +1435,7 @@ static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth) scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth); ql_dbg(ql_dbg_io, vha, 0x302a, - "Queue depth adjusted-up to %d for nexus=%ld:%d:%d.\n", + "Queue depth adjusted-up to %d for nexus=%ld:%d:%llu.\n", sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun); } @@ -2661,14 +2664,19 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) else host->max_cmd_len = MAX_CMDSZ; host->max_channel = MAX_BUSES - 1; - host->max_lun = ql2xmaxlun; + /* Older HBAs support only 16-bit LUNs */ + if (!IS_QLAFX00(ha) && !IS_FWI2_CAPABLE(ha) && + ql2xmaxlun > 0xffff) + host->max_lun = 0xffff; + else + host->max_lun = ql2xmaxlun; host->transportt = qla2xxx_transport_template; sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC); ql_dbg(ql_dbg_init, base_vha, 0x0033, "max_id=%d this_id=%d " "cmd_per_len=%d unique_id=%d max_cmd_len=%d max_channel=%d " - "max_lun=%d transportt=%p, vendor_id=%llu.\n", host->max_id, + "max_lun=%llu transportt=%p, vendor_id=%llu.\n", host->max_id, host->this_id, host->cmd_per_lun, host->unique_id, host->max_cmd_len, host->max_channel, host->max_lun, host->transportt, sht->vendor_id); diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 5f58b45..2559144 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -23,7 +23,7 @@ void qla4xxx_process_aen(struct scsi_qla_host *ha, uint8_t process_aen); int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host *ha); int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb); int qla4xxx_reset_lun(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry, - int lun); + uint64_t lun); int qla4xxx_reset_target(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry); int qla4xxx_get_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr, @@ -76,7 +76,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, uint32_t state, uint32_t conn_error); void qla4xxx_dump_buffer(void *b, uint32_t size); int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod); + struct ddb_entry *ddb_entry, uint64_t lun, uint16_t mrkr_mod); int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr, uint32_t offset, uint32_t length, uint32_t options); int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index e5697ab..08ab6da 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -83,7 +83,7 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, * This routine issues a marker IOCB. **/ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod) + struct ddb_entry *ddb_entry, uint64_t lun, uint16_t mrkr_mod) { struct qla4_marker_entry *marker_entry; unsigned long flags = 0; diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 081b6b7..4f9c0f2 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -26,7 +26,7 @@ static void qla4xxx_copy_sense(struct scsi_qla_host *ha, memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); sense_len = le16_to_cpu(sts_entry->senseDataByteCnt); if (sense_len == 0) { - DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%d: %s:" + DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%llu: %s:" " sense len 0\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__)); @@ -43,7 +43,7 @@ static void qla4xxx_copy_sense(struct scsi_qla_host *ha, sense_len = min_t(uint16_t, sense_len, IOCB_MAX_SENSEDATA_LEN); memcpy(cmd->sense_buffer, sts_entry->senseData, sense_len); - DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: %s: sense key = %x, " + DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: %s: sense key = %x, " "ASL= %02x, ASC/ASCQ = %02x/%02x\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__, @@ -169,7 +169,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, cmd->result = DID_ERROR << 16; - DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " + DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: " "Mid-layer Data underrun0, " "xferlen = 0x%x, " "residual = 0x%x\n", ha->host_no, @@ -197,7 +197,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; case SCS_RESET_OCCURRED: - DEBUG2(printk("scsi%ld:%d:%d:%d: %s: Device RESET occurred\n", + DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: Device RESET occurred\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__)); @@ -205,7 +205,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; case SCS_ABORTED: - DEBUG2(printk("scsi%ld:%d:%d:%d: %s: Abort occurred\n", + DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: Abort occurred\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__)); @@ -213,7 +213,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; case SCS_TIMEOUT: - DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: Timeout\n", + DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: Timeout\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun)); @@ -232,7 +232,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, case SCS_DATA_OVERRUN: if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) || (sts_entry->completionStatus == SCS_DATA_OVERRUN)) { - DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun\n", + DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: " "Data overrun\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__)); @@ -259,7 +259,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, if (!scsi_status && (scsi_bufflen(cmd) - residual) < cmd->underflow) { DEBUG2(ql4_printk(KERN_INFO, ha, - "scsi%ld:%d:%d:%d: %s: Mid-layer Data underrun, xferlen = 0x%x,residual = 0x%x\n", + "scsi%ld:%d:%d:%llu: %s: Mid-layer Data underrun, xferlen = 0x%x,residual = 0x%x\n", ha->host_no, cmd->device->channel, cmd->device->id, @@ -291,7 +291,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, */ DEBUG2(ql4_printk(KERN_INFO, ha, - "scsi%ld:%d:%d:%d: %s: Dropped frame(s) detected (0x%x of 0x%x bytes).\n", + "scsi%ld:%d:%d:%llu: %s: Dropped frame(s) detected (0x%x of 0x%x bytes).\n", ha->host_no, cmd->device->channel, cmd->device->id, @@ -313,7 +313,7 @@ check_scsi_status: case SCS_DEVICE_LOGGED_OUT: case SCS_DEVICE_UNAVAILABLE: - DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: SCS_DEVICE " + DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: SCS_DEVICE " "state: 0x%x\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, sts_entry->completionStatus)); @@ -333,7 +333,7 @@ check_scsi_status: * SCSI Mid-Layer handles device queue full */ cmd->result = DID_OK << 16 | sts_entry->scsiStatus; - DEBUG2(printk("scsi%ld:%d:%d: %s: QUEUE FULL detected " + DEBUG2(printk("scsi%ld:%d:%llu: %s: QUEUE FULL detected " "compl=%02x, scsi=%02x, state=%02x, iFlags=%02x," " iResp=%02x\n", ha->host_no, cmd->device->id, cmd->device->lun, __func__, diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 0a3312c..fdfae79 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1205,7 +1205,7 @@ int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb) if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) { status = QLA_ERROR; - DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%d: abort task FAILED: " + DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%llu: abort task FAILED: " "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n", ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0], mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4])); @@ -1225,14 +1225,14 @@ int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb) * are valid before calling this routine. **/ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, - int lun) + uint64_t lun) { uint32_t mbox_cmd[MBOX_REG_COUNT]; uint32_t mbox_sts[MBOX_REG_COUNT]; uint32_t scsi_lun[2]; int status = QLA_SUCCESS; - DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no, + DEBUG2(printk("scsi%ld:%d:%llu: lun reset issued\n", ha->host_no, ddb_entry->fw_ddb_index, lun)); /* diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 3202063..c5d9564 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -9223,20 +9223,20 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) { struct scsi_qla_host *ha = to_qla_host(cmd->device->host); unsigned int id = cmd->device->id; - unsigned int lun = cmd->device->lun; + uint64_t lun = cmd->device->lun; unsigned long flags; struct srb *srb = NULL; int ret = SUCCESS; int wait = 0; - ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d: Abort command issued cmd=%p, cdb=0x%x\n", + ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued cmd=%p, cdb=0x%x\n", ha->host_no, id, lun, cmd, cmd->cmnd[0]); spin_lock_irqsave(&ha->hardware_lock, flags); srb = (struct srb *) CMD_SP(cmd); if (!srb) { spin_unlock_irqrestore(&ha->hardware_lock, flags); - ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d: Specified command has already completed.\n", + ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Specified command has already completed.\n", ha->host_no, id, lun); return SUCCESS; } @@ -9244,11 +9244,11 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) spin_unlock_irqrestore(&ha->hardware_lock, flags); if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) { - DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx failed.\n", + DEBUG3(printk("scsi%ld:%d:%llu: Abort_task mbx failed.\n", ha->host_no, id, lun)); ret = FAILED; } else { - DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx success.\n", + DEBUG3(printk("scsi%ld:%d:%llu: Abort_task mbx success.\n", ha->host_no, id, lun)); wait = 1; } @@ -9258,14 +9258,14 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) /* Wait for command to complete */ if (wait) { if (!qla4xxx_eh_wait_on_command(ha, cmd)) { - DEBUG2(printk("scsi%ld:%d:%d: Abort handler timed out\n", + DEBUG2(printk("scsi%ld:%d:%llu: Abort handler timed out\n", ha->host_no, id, lun)); ret = FAILED; } } ql4_printk(KERN_INFO, ha, - "scsi%ld:%d:%d: Abort command - %s\n", + "scsi%ld:%d:%llu: Abort command - %s\n", ha->host_no, id, lun, (ret == SUCCESS) ? "succeeded" : "failed"); return ret; @@ -9293,7 +9293,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) ret = FAILED; ql4_printk(KERN_INFO, ha, - "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no, + "scsi%ld:%d:%d:%llu: DEVICE RESET ISSUED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); DEBUG2(printk(KERN_INFO @@ -9323,7 +9323,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) goto eh_dev_reset_done; ql4_printk(KERN_INFO, ha, - "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", + "scsi(%ld:%d:%d:%llu): DEVICE RESET SUCCEEDED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); @@ -9440,7 +9440,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) } ql4_printk(KERN_INFO, ha, - "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, + "scsi(%ld:%d:%d:%llu): HOST RESET ISSUED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) { diff --git a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c index 13d628b..a22bb1b 100644 --- a/drivers/scsi/qlogicfas.c +++ b/drivers/scsi/qlogicfas.c @@ -171,8 +171,6 @@ static int qlogicfas_release(struct Scsi_Host *shost) qlogicfas408_disable_ints(priv); free_irq(shost->irq, shost); } - if (shost->dma_channel != 0xff) - free_dma(shost->dma_channel); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_host_put(shost); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 6d48d30..740ae49 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -959,7 +959,7 @@ static inline void update_can_queue(struct Scsi_Host *host, u_int in_ptr, u_int /* Temporary workaround until bug is found and fixed (one bug has been found already, but fixing it makes things even worse) -jj */ int num_free = QLOGICPTI_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr) - 64; - host->can_queue = host->host_busy + num_free; + host->can_queue = atomic_read(&host->host_busy) + num_free; host->sg_tablesize = QLOGICPTI_MAX_SG(num_free); } diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 88d46fe..df33060 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -72,8 +72,6 @@ #define CREATE_TRACE_POINTS #include <trace/events/scsi.h> -static void scsi_done(struct scsi_cmnd *cmd); - /* * Definitions and constants. */ @@ -124,6 +122,8 @@ static const char *const scsi_device_types[] = { "Bridge controller", "Object storage ", "Automation/Drive ", + "Security Manager ", + "Direct-Access-ZBC", }; /** @@ -235,7 +235,8 @@ fail: * Description: allocate a struct scsi_cmd from host's slab, recycling from the * host's free_list if necessary. */ -struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) +static struct scsi_cmnd * +__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) { struct scsi_cmnd *cmd = scsi_host_alloc_command(shost, gfp_mask); @@ -265,7 +266,6 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) return cmd; } -EXPORT_SYMBOL_GPL(__scsi_get_command); /** * scsi_get_command - Allocate and setup a scsi command block @@ -291,14 +291,13 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) cmd->jiffies_at_alloc = jiffies; return cmd; } -EXPORT_SYMBOL(scsi_get_command); /** * __scsi_put_command - Free a struct scsi_cmnd * @shost: dev->host * @cmd: Command to free */ -void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) +static void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) { unsigned long flags; @@ -314,7 +313,6 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) if (likely(cmd != NULL)) scsi_host_free_command(shost, cmd); } -EXPORT_SYMBOL(__scsi_put_command); /** * scsi_put_command - Free a scsi command block @@ -334,11 +332,10 @@ void scsi_put_command(struct scsi_cmnd *cmd) list_del_init(&cmd->list); spin_unlock_irqrestore(&cmd->device->list_lock, flags); - cancel_delayed_work(&cmd->abort_work); + BUG_ON(delayed_work_pending(&cmd->abort_work)); __scsi_put_command(cmd->device->host, cmd); } -EXPORT_SYMBOL(scsi_put_command); static struct scsi_host_cmd_pool * scsi_find_host_cmd_pool(struct Scsi_Host *shost) @@ -368,8 +365,8 @@ scsi_alloc_host_cmd_pool(struct Scsi_Host *shost) if (!pool) return NULL; - pool->cmd_name = kasprintf(GFP_KERNEL, "%s_cmd", hostt->name); - pool->sense_name = kasprintf(GFP_KERNEL, "%s_sense", hostt->name); + pool->cmd_name = kasprintf(GFP_KERNEL, "%s_cmd", hostt->proc_name); + pool->sense_name = kasprintf(GFP_KERNEL, "%s_sense", hostt->proc_name); if (!pool->cmd_name || !pool->sense_name) { scsi_free_host_cmd_pool(pool); return NULL; @@ -605,7 +602,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) if (level > 3) scmd_printk(KERN_INFO, cmd, "scsi host busy %d failed %d\n", - cmd->device->host->host_busy, + atomic_read(&cmd->device->host->host_busy), cmd->device->host->host_failed); } } @@ -648,33 +645,24 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * returns an immediate error upwards, and signals * that the device is no longer present */ cmd->result = DID_NO_CONNECT << 16; - scsi_done(cmd); - /* return 0 (because the command has been processed) */ - goto out; + goto done; } /* Check to see if the scsi lld made this device blocked. */ if (unlikely(scsi_device_blocked(cmd->device))) { - /* + /* * in blocked state, the command is just put back on * the device queue. The suspend state has already * blocked the queue so future requests should not * occur until the device transitions out of the * suspend state. */ - - scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); - - SCSI_LOG_MLQUEUE(3, printk("queuecommand : device blocked \n")); - - /* - * NOTE: rtn is still zero here because we don't need the - * queue to be plugged on return (it's already stopped) - */ - goto out; + SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, + "queuecommand : device blocked\n")); + return SCSI_MLQUEUE_DEVICE_BUSY; } - /* + /* * If SCSI-2 or lower, store the LUN value in cmnd. */ if (cmd->device->scsi_level <= SCSI_2 && @@ -690,57 +678,36 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * length exceeds what the host adapter can handle. */ if (cmd->cmd_len > cmd->device->host->max_cmd_len) { - SCSI_LOG_MLQUEUE(3, - printk("queuecommand : command too long. " + SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, + "queuecommand : command too long. " "cdb_size=%d host->max_cmd_len=%d\n", cmd->cmd_len, cmd->device->host->max_cmd_len)); cmd->result = (DID_ABORT << 16); - - scsi_done(cmd); - goto out; + goto done; } if (unlikely(host->shost_state == SHOST_DEL)) { cmd->result = (DID_NO_CONNECT << 16); - scsi_done(cmd); - } else { - trace_scsi_dispatch_cmd_start(cmd); - cmd->scsi_done = scsi_done; - rtn = host->hostt->queuecommand(host, cmd); + goto done; + } + trace_scsi_dispatch_cmd_start(cmd); + rtn = host->hostt->queuecommand(host, cmd); if (rtn) { trace_scsi_dispatch_cmd_error(cmd, rtn); if (rtn != SCSI_MLQUEUE_DEVICE_BUSY && rtn != SCSI_MLQUEUE_TARGET_BUSY) rtn = SCSI_MLQUEUE_HOST_BUSY; - scsi_queue_insert(cmd, rtn); - - SCSI_LOG_MLQUEUE(3, - printk("queuecommand : request rejected\n")); + SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, + "queuecommand : request rejected\n")); } - out: - SCSI_LOG_MLQUEUE(3, printk("leaving scsi_dispatch_cmnd()\n")); return rtn; -} - -/** - * scsi_done - Invoke completion on finished SCSI command. - * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives - * ownership back to SCSI Core -- i.e. the LLDD has finished with it. - * - * Description: This function is the mid-level's (SCSI Core) interrupt routine, - * which regains ownership of the SCSI command (de facto) from a LLDD, and - * calls blk_complete_request() for further processing. - * - * This function is interrupt context safe. - */ -static void scsi_done(struct scsi_cmnd *cmd) -{ - trace_scsi_dispatch_cmd_done(cmd); - blk_complete_request(cmd->request); + done: + cmd->scsi_done(cmd); + return 0; } /** @@ -761,17 +728,16 @@ void scsi_finish_command(struct scsi_cmnd *cmd) scsi_device_unbusy(sdev); - /* - * Clear the flags which say that the device/host is no longer - * capable of accepting new commands. These are set in scsi_queue.c - * for both the queue full condition on a device, and for a - * host full condition on the host. - * - * XXX(hch): What about locking? - */ - shost->host_blocked = 0; - starget->target_blocked = 0; - sdev->device_blocked = 0; + /* + * Clear the flags that say that the device/target/host is no longer + * capable of accepting new commands. + */ + if (atomic_read(&shost->host_blocked)) + atomic_set(&shost->host_blocked, 0); + if (atomic_read(&starget->target_blocked)) + atomic_set(&starget->target_blocked, 0); + if (atomic_read(&sdev->device_blocked)) + atomic_set(&sdev->device_blocked, 0); /* * If we have valid sense information, then some kind of recovery @@ -801,7 +767,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd) } scsi_io_completion(cmd, good_bytes); } -EXPORT_SYMBOL(scsi_finish_command); /** * scsi_adjust_queue_depth - Let low level drivers change a device's queue depth @@ -842,7 +807,7 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) * is more IO than the LLD's can_queue (so there are not enuogh * tags) request_fn's host queue ready check will handle it. */ - if (!sdev->host->bqt) { + if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) { if (blk_queue_tagged(sdev->request_queue) && blk_queue_resize_tags(sdev->request_queue, tags) != 0) goto out; @@ -850,6 +815,10 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) sdev->queue_depth = tags; switch (tagged) { + case 0: + sdev->ordered_tags = 0; + sdev->simple_tags = 0; + break; case MSG_ORDERED_TAG: sdev->ordered_tags = 1; sdev->simple_tags = 1; @@ -859,13 +828,11 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) sdev->simple_tags = 1; break; default: + sdev->ordered_tags = 0; + sdev->simple_tags = 0; sdev_printk(KERN_WARNING, sdev, "scsi_adjust_queue_depth, bad queue type, " "disabled\n"); - case 0: - sdev->ordered_tags = sdev->simple_tags = 0; - sdev->queue_depth = tags; - break; } out: spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); @@ -1291,7 +1258,7 @@ EXPORT_SYMBOL(__starget_for_each_device); * really want to use scsi_device_lookup_by_target instead. **/ struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *starget, - uint lun) + u64 lun) { struct scsi_device *sdev; @@ -1316,7 +1283,7 @@ EXPORT_SYMBOL(__scsi_device_lookup_by_target); * needs to be released with scsi_device_put once you're done with it. **/ struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *starget, - uint lun) + u64 lun) { struct scsi_device *sdev; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); @@ -1349,7 +1316,7 @@ EXPORT_SYMBOL(scsi_device_lookup_by_target); * really want to use scsi_device_lookup instead. **/ struct scsi_device *__scsi_device_lookup(struct Scsi_Host *shost, - uint channel, uint id, uint lun) + uint channel, uint id, u64 lun) { struct scsi_device *sdev; @@ -1375,7 +1342,7 @@ EXPORT_SYMBOL(__scsi_device_lookup); * needs to be released with scsi_device_put once you're done with it. **/ struct scsi_device *scsi_device_lookup(struct Scsi_Host *shost, - uint channel, uint id, uint lun) + uint channel, uint id, u64 lun) { struct scsi_device *sdev; unsigned long flags; @@ -1396,6 +1363,9 @@ 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"); +bool scsi_use_blk_mq = false; +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_debug.c b/drivers/scsi/scsi_debug.c index 1328a26..d19c0e3 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -42,6 +42,10 @@ #include <linux/scatterlist.h> #include <linux/blkdev.h> #include <linux/crc-t10dif.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> +#include <linux/atomic.h> +#include <linux/hrtimer.h> #include <net/checksum.h> @@ -53,13 +57,16 @@ #include <scsi/scsi_host.h> #include <scsi/scsicam.h> #include <scsi/scsi_eh.h> +#include <scsi/scsi_tcq.h> #include <scsi/scsi_dbg.h> #include "sd.h" #include "scsi_logging.h" -#define SCSI_DEBUG_VERSION "1.82" -static const char * scsi_debug_version_date = "20100324"; +#define SCSI_DEBUG_VERSION "1.84" +static const char *scsi_debug_version_date = "20140706"; + +#define MY_NAME "scsi_debug" /* Additional Sense Code (ASC) */ #define NO_ADDITIONAL_SENSE 0x0 @@ -72,7 +79,11 @@ static const char * scsi_debug_version_date = "20100324"; #define INVALID_COMMAND_OPCODE 0x20 #define INVALID_FIELD_IN_CDB 0x24 #define INVALID_FIELD_IN_PARAM_LIST 0x26 -#define POWERON_RESET 0x29 +#define UA_RESET_ASC 0x29 +#define UA_CHANGED_ASC 0x2a +#define POWER_ON_RESET_ASCQ 0x0 +#define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */ +#define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */ #define SAVING_PARAMS_UNSUP 0x39 #define TRANSPORT_PROBLEM 0x4b #define THRESHOLD_EXCEEDED 0x5d @@ -81,7 +92,6 @@ static const char * scsi_debug_version_date = "20100324"; /* Additional Sense Code Qualifier (ASCQ) */ #define ACK_NAK_TO 0x3 -#define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ /* Default values for driver parameters */ #define DEF_NUM_HOST 1 @@ -91,7 +101,7 @@ static const char * scsi_debug_version_date = "20100324"; * (id 0) containing 1 logical unit (lun 0). That is 1 device. */ #define DEF_ATO 1 -#define DEF_DELAY 1 +#define DEF_DELAY 1 /* if > 0 unit is a jiffy */ #define DEF_DEV_SIZE_MB 8 #define DEF_DIF 0 #define DEF_DIX 0 @@ -99,11 +109,13 @@ static const char * scsi_debug_version_date = "20100324"; #define DEF_EVERY_NTH 0 #define DEF_FAKE_RW 0 #define DEF_GUARD 0 +#define DEF_HOST_LOCK 0 #define DEF_LBPU 0 #define DEF_LBPWS 0 #define DEF_LBPWS10 0 #define DEF_LBPRZ 1 #define DEF_LOWEST_ALIGNED 0 +#define DEF_NDELAY 0 /* if > 0 unit is a nanosecond */ #define DEF_NO_LUN_0 0 #define DEF_NUM_PARTS 0 #define DEF_OPTS 0 @@ -113,6 +125,7 @@ static const char * scsi_debug_version_date = "20100324"; #define DEF_REMOVABLE false #define DEF_SCSI_LEVEL 5 /* INQUIRY, byte2 [5->SPC-3] */ #define DEF_SECTOR_SIZE 512 +#define DEF_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ #define DEF_UNMAP_ALIGNMENT 0 #define DEF_UNMAP_GRANULARITY 1 #define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF @@ -120,6 +133,7 @@ static const char * scsi_debug_version_date = "20100324"; #define DEF_VIRTUAL_GB 0 #define DEF_VPD_USE_HOSTNO 1 #define DEF_WRITESAME_LENGTH 0xFFFF +#define DELAY_OVERRIDDEN -9999 /* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 @@ -130,7 +144,14 @@ static const char * scsi_debug_version_date = "20100324"; #define SCSI_DEBUG_OPT_DIF_ERR 32 #define SCSI_DEBUG_OPT_DIX_ERR 64 #define SCSI_DEBUG_OPT_MAC_TIMEOUT 128 -#define SCSI_DEBUG_OPT_SHORT_TRANSFER 256 +#define SCSI_DEBUG_OPT_SHORT_TRANSFER 0x100 +#define SCSI_DEBUG_OPT_Q_NOISE 0x200 +#define SCSI_DEBUG_OPT_ALL_TSF 0x400 +#define SCSI_DEBUG_OPT_RARE_TSF 0x800 +#define SCSI_DEBUG_OPT_N_WCE 0x1000 +#define SCSI_DEBUG_OPT_RESET_NOISE 0x2000 +#define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000 +#define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000) /* When "every_nth" > 0 then modulo "every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write @@ -148,6 +169,19 @@ static const char * scsi_debug_version_date = "20100324"; * writing a new value (other than -1 or 1) to every_nth via sysfs). */ +/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in + * priority order. In the subset implemented here lower numbers have higher + * priority. The UA numbers should be a sequence starting from 0 with + * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */ +#define SDEBUG_UA_POR 0 /* Power on, reset, or bus device reset */ +#define SDEBUG_UA_BUS_RESET 1 +#define SDEBUG_UA_MODE_CHANGED 2 +#define SDEBUG_NUM_UAS 3 + +/* for check_readiness() */ +#define UAS_ONLY 1 +#define UAS_TUR 0 + /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this * sector on read commands: */ #define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */ @@ -158,9 +192,19 @@ static const char * scsi_debug_version_date = "20100324"; #define SAM2_LUN_ADDRESS_METHOD 0 #define SAM2_WLUN_REPORT_LUNS 0xc101 -/* Can queue up to this number of commands. Typically commands that - * that have a non-zero delay are queued. */ -#define SCSI_DEBUG_CANQUEUE 255 +/* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued + * (for response) at one time. Can be reduced by max_queue option. Command + * responses are not queued when delay=0 and ndelay=0. The per-device + * DEF_CMD_PER_LUN can be changed via sysfs: + * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed + * SCSI_DEBUG_CANQUEUE. */ +#define SCSI_DEBUG_CANQUEUE_WORDS 9 /* a WORD is bits in a long */ +#define SCSI_DEBUG_CANQUEUE (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG) +#define DEF_CMD_PER_LUN 255 + +#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE +#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE" +#endif static int scsi_debug_add_host = DEF_NUM_HOST; static int scsi_debug_ato = DEF_ATO; @@ -175,6 +219,8 @@ static unsigned int scsi_debug_guard = DEF_GUARD; static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; static int scsi_debug_max_luns = DEF_MAX_LUNS; static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE; +static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */ +static int scsi_debug_ndelay = DEF_NDELAY; static int scsi_debug_no_lun_0 = DEF_NO_LUN_0; static int scsi_debug_no_uld = 0; static int scsi_debug_num_parts = DEF_NUM_PARTS; @@ -198,8 +244,11 @@ static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC; static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH; static bool scsi_debug_removable = DEF_REMOVABLE; static bool scsi_debug_clustering; +static bool scsi_debug_host_lock = DEF_HOST_LOCK; -static int scsi_debug_cmnd_count = 0; +static atomic_t sdebug_cmnd_count; +static atomic_t sdebug_completions; +static atomic_t sdebug_a_tsf; /* counter of 'almost' TSFs */ #define DEV_READONLY(TGT) (0) @@ -214,24 +263,23 @@ static int sdebug_sectors_per; /* sectors per cylinder */ #define SDEBUG_MAX_PARTS 4 -#define SDEBUG_SENSE_LEN 32 - #define SCSI_DEBUG_MAX_CMD_LEN 32 static unsigned int scsi_debug_lbp(void) { - return scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10; + return ((0 == scsi_debug_fake_rw) && + (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10)); } struct sdebug_dev_info { struct list_head dev_list; - unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */ unsigned int channel; unsigned int target; - unsigned int lun; + u64 lun; struct sdebug_host_info *sdbg_host; - unsigned int wlun; - char reset; + u64 wlun; + unsigned long uas_bm[1]; + atomic_t num_in_q; char stopped; char used; }; @@ -249,26 +297,33 @@ struct sdebug_host_info { static LIST_HEAD(sdebug_host_list); static DEFINE_SPINLOCK(sdebug_host_list_lock); -typedef void (* done_funct_t) (struct scsi_cmnd *); + +struct sdebug_hrtimer { /* ... is derived from hrtimer */ + struct hrtimer hrt; /* must be first element */ + int qa_indx; +}; struct sdebug_queued_cmd { - int in_use; - struct timer_list cmnd_timer; - done_funct_t done_funct; + /* in_use flagged by a bit in queued_in_use_bm[] */ + struct timer_list *cmnd_timerp; + struct tasklet_struct *tletp; + struct sdebug_hrtimer *sd_hrtp; struct scsi_cmnd * a_cmnd; - int scsi_result; }; static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; +static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS]; + static unsigned char * fake_storep; /* ramdisk storage */ static struct sd_dif_tuple *dif_storep; /* protection info */ static void *map_storep; /* provisioning map */ static unsigned long map_size; -static int num_aborts = 0; -static int num_dev_resets = 0; -static int num_bus_resets = 0; -static int num_host_resets = 0; +static int num_aborts; +static int num_dev_resets; +static int num_target_resets; +static int num_bus_resets; +static int num_host_resets; static int dix_writes; static int dix_reads; static int dif_errors; @@ -276,7 +331,8 @@ static int dif_errors; static DEFINE_SPINLOCK(queued_arr_lock); static DEFINE_RWLOCK(atomic_rw); -static char sdebug_proc_name[] = "scsi_debug"; +static char sdebug_proc_name[] = MY_NAME; +static const char *my_name = MY_NAME; static struct bus_type pseudo_lld_bus; @@ -291,6 +347,12 @@ static const int check_condition_result = static const int illegal_condition_result = (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION; +static const int device_qfull_result = + (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL; + +static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, + 0, 0, 0, 0}; static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0x2, 0x4b}; static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, @@ -332,19 +394,24 @@ static void sdebug_max_tgts_luns(void) spin_unlock(&sdebug_host_list_lock); } -static void mk_sense_buffer(struct sdebug_dev_info *devip, int key, - int asc, int asq) +static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq) { unsigned char *sbuff; - sbuff = devip->sense_buff; - memset(sbuff, 0, SDEBUG_SENSE_LEN); + sbuff = scp->sense_buffer; + if (!sbuff) { + sdev_printk(KERN_ERR, scp->device, + "%s: sense_buffer is NULL\n", __func__); + return; + } + memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE); scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq); if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: " - "[0x%x,0x%x,0x%x]\n", key, asc, asq); + sdev_printk(KERN_INFO, scp->device, + "%s: [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n", + my_name, key, asc, asq); } static void get_data_transfer_info(unsigned char *cmd, @@ -409,29 +476,71 @@ static void get_data_transfer_info(unsigned char *cmd, static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) { if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { - printk(KERN_INFO "scsi_debug: ioctl: cmd=0x%x\n", cmd); + if (0x1261 == cmd) + sdev_printk(KERN_INFO, dev, + "%s: BLKFLSBUF [0x1261]\n", __func__); + else if (0x5331 == cmd) + sdev_printk(KERN_INFO, dev, + "%s: CDROM_GET_CAPABILITY [0x5331]\n", + __func__); + else + sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n", + __func__, cmd); } return -EINVAL; /* return -ENOTTY; // correct return but upsets fdisk */ } -static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only, +static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, struct sdebug_dev_info * devip) { - if (devip->reset) { - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: Reporting Unit " - "attention: power on reset\n"); - devip->reset = 0; - mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0); + int k; + bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts); + + k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS); + if (k != SDEBUG_NUM_UAS) { + const char *cp = NULL; + + switch (k) { + case SDEBUG_UA_POR: + mk_sense_buffer(SCpnt, UNIT_ATTENTION, + UA_RESET_ASC, POWER_ON_RESET_ASCQ); + if (debug) + cp = "power on reset"; + break; + case SDEBUG_UA_BUS_RESET: + mk_sense_buffer(SCpnt, UNIT_ATTENTION, + UA_RESET_ASC, BUS_RESET_ASCQ); + if (debug) + cp = "bus reset"; + break; + case SDEBUG_UA_MODE_CHANGED: + mk_sense_buffer(SCpnt, UNIT_ATTENTION, + UA_CHANGED_ASC, MODE_CHANGED_ASCQ); + if (debug) + cp = "mode parameters changed"; + break; + default: + pr_warn("%s: unexpected unit attention code=%d\n", + __func__, k); + if (debug) + cp = "unknown"; + break; + } + clear_bit(k, devip->uas_bm); + if (debug) + sdev_printk(KERN_INFO, SCpnt->device, + "%s reports: Unit attention: %s\n", + my_name, cp); return check_condition_result; } - if ((0 == reset_only) && devip->stopped) { - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: Reporting Not " - "ready: initializing command required\n"); - mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY, + if ((UAS_TUR == uas_only) && devip->stopped) { + mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); + if (debug) + sdev_printk(KERN_INFO, SCpnt->device, + "%s reports: Not ready: %s\n", my_name, + "initializing command required"); return check_condition_result; } return 0; @@ -471,8 +580,9 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, static const char * inq_vendor_id = "Linux "; static const char * inq_product_id = "scsi_debug "; -static const char * inq_product_rev = "0004"; +static const char *inq_product_rev = "0184"; /* version less '.' */ +/* Device identification VPD page. Returns number of bytes placed in arr */ static int inquiry_evpd_83(unsigned char * arr, int port_group_id, int target_dev_id, int dev_id_num, const char * dev_id_str, @@ -573,12 +683,14 @@ static unsigned char vpd84_data[] = { 0x22,0x22,0x22,0x0,0xbb,0x2, }; +/* Software interface identification VPD page */ static int inquiry_evpd_84(unsigned char * arr) { memcpy(arr, vpd84_data, sizeof(vpd84_data)); return sizeof(vpd84_data); } +/* Management network addresses VPD page */ static int inquiry_evpd_85(unsigned char * arr) { int num = 0; @@ -713,6 +825,7 @@ static unsigned char vpd89_data[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51, }; +/* ATA Information VPD page */ static int inquiry_evpd_89(unsigned char * arr) { memcpy(arr, vpd89_data, sizeof(vpd89_data)); @@ -720,7 +833,6 @@ static int inquiry_evpd_89(unsigned char * arr) } -/* Block limits VPD page (SBC-3) */ static unsigned char vpdb0_data[] = { /* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -728,6 +840,7 @@ static unsigned char vpdb0_data[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; +/* Block limits VPD page (SBC-3) */ static int inquiry_evpd_b0(unsigned char * arr) { unsigned int gran; @@ -811,7 +924,7 @@ static int inquiry_evpd_b2(unsigned char *arr) #define SDEBUG_LONG_INQ_SZ 96 #define SDEBUG_MAX_INQ_ARR_SZ 584 -static int resp_inquiry(struct scsi_cmnd * scp, int target, +static int resp_inquiry(struct scsi_cmnd *scp, int target, struct sdebug_dev_info * devip) { unsigned char pq_pdt; @@ -831,7 +944,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, pq_pdt = (scsi_debug_ptype & 0x1f); arr[0] = pq_pdt; if (0x2 & cmd[1]) { /* CMDDT bit set */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); kfree(arr); return check_condition_result; @@ -917,7 +1030,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, arr[3] = inquiry_evpd_b2(&arr[4]); } else { /* Illegal request, invalid field in cdb */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); kfree(arr); return check_condition_result; @@ -963,15 +1076,13 @@ static int resp_requests(struct scsi_cmnd * scp, { unsigned char * sbuff; unsigned char *cmd = (unsigned char *)scp->cmnd; - unsigned char arr[SDEBUG_SENSE_LEN]; + unsigned char arr[SCSI_SENSE_BUFFERSIZE]; int want_dsense; int len = 18; memset(arr, 0, sizeof(arr)); - if (devip->reset == 1) - mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0); want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense; - sbuff = devip->sense_buff; + sbuff = scp->sense_buffer; if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { if (want_dsense) { arr[0] = 0x72; @@ -986,7 +1097,7 @@ static int resp_requests(struct scsi_cmnd * scp, arr[13] = 0xff; /* TEST set and MRIE==6 */ } } else { - memcpy(arr, sbuff, SDEBUG_SENSE_LEN); + memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE); if ((cmd[1] & 1) && (! scsi_debug_dsense)) { /* DESC bit set and sense_buff in fixed format */ memset(arr, 0, sizeof(arr)); @@ -997,7 +1108,7 @@ static int resp_requests(struct scsi_cmnd * scp, len = 8; } } - mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0); + mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0); return fill_from_dev_buffer(scp, arr, len); } @@ -1007,11 +1118,12 @@ static int resp_start_stop(struct scsi_cmnd * scp, unsigned char *cmd = (unsigned char *)scp->cmnd; int power_cond, errsts, start; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; power_cond = (cmd[4] & 0xf0) >> 4; if (power_cond) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1038,7 +1150,8 @@ static int resp_readcap(struct scsi_cmnd * scp, unsigned int capac; int errsts; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; /* following just in case virtual_gb changed */ sdebug_capacity = get_sdebug_capacity(); @@ -1069,7 +1182,8 @@ static int resp_readcap16(struct scsi_cmnd * scp, unsigned long long capac; int errsts, k, alloc_len; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8) + cmd[13]); @@ -1230,12 +1344,18 @@ static int resp_format_pg(unsigned char * p, int pcontrol, int target) static int resp_caching_pg(unsigned char * p, int pcontrol, int target) { /* Caching page for mode_sense */ - unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, + unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0}; + if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts) + caching_pg[2] &= ~0x4; /* set WCE=0 (default WCE=1) */ memcpy(p, caching_pg, sizeof(caching_pg)); if (1 == pcontrol) - memset(p + 2, 0, sizeof(caching_pg) - 2); + memcpy(p + 2, ch_caching_pg, sizeof(ch_caching_pg)); + else if (2 == pcontrol) + memcpy(p, d_caching_pg, sizeof(d_caching_pg)); return sizeof(caching_pg); } @@ -1350,7 +1470,8 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; unsigned char *cmd = (unsigned char *)scp->cmnd; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; dbd = !!(cmd[1] & 0x8); pcontrol = (cmd[2] & 0xc0) >> 6; @@ -1365,8 +1486,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]); memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); if (0x3 == pcontrol) { /* Saving values not supported */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, - 0); + mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0); return check_condition_result; } target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) + @@ -1422,7 +1542,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) { /* TODO: Control Extension page */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1449,7 +1569,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, break; case 0x19: /* if spc==1 then sas phy, control+discover */ if ((subpcode > 0x2) && (subpcode < 0xff)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1482,14 +1602,14 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, } len += resp_iec_m_pg(ap + len, pcontrol, target); } else { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } offset += len; break; default: - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1512,14 +1632,15 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, unsigned char arr[SDEBUG_MAX_MSELECT_SZ]; unsigned char *cmd = (unsigned char *)scp->cmnd; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; memset(arr, 0, sizeof(arr)); pf = cmd[1] & 0x10; sp = cmd[1] & 0x1; param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]); if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1528,12 +1649,13 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, return (DID_ERROR << 16); else if ((res < param_len) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) - printk(KERN_INFO "scsi_debug: mode_select: cdb indicated=%d, " - " IO sent=%d bytes\n", param_len, res); + sdev_printk(KERN_INFO, scp->device, + "%s: cdb indicated=%d, IO sent=%d bytes\n", + __func__, param_len, res); md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2); bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]); if (md_len > 2) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_PARAM_LIST, 0); return check_condition_result; } @@ -1541,7 +1663,7 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, mpage = arr[off] & 0x3f; ps = !!(arr[off] & 0x80); if (ps) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_PARAM_LIST, 0); return check_condition_result; } @@ -1549,32 +1671,42 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) : (arr[off + 1] + 2); if ((pg_len + off) > param_len) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, PARAMETER_LIST_LENGTH_ERR, 0); return check_condition_result; } switch (mpage) { + case 0x8: /* Caching Mode page */ + if (caching_pg[1] == arr[off + 1]) { + memcpy(caching_pg + 2, arr + off + 2, + sizeof(caching_pg) - 2); + goto set_mode_changed_ua; + } + break; case 0xa: /* Control Mode page */ if (ctrl_m_pg[1] == arr[off + 1]) { memcpy(ctrl_m_pg + 2, arr + off + 2, sizeof(ctrl_m_pg) - 2); scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4); - return 0; + goto set_mode_changed_ua; } break; case 0x1c: /* Informational Exceptions Mode page */ if (iec_m_pg[1] == arr[off + 1]) { memcpy(iec_m_pg + 2, arr + off + 2, sizeof(iec_m_pg) - 2); - return 0; + goto set_mode_changed_ua; } break; default: break; } - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_PARAM_LIST, 0); return check_condition_result; +set_mode_changed_ua: + set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm); + return 0; } static int resp_temp_l_pg(unsigned char * arr) @@ -1609,13 +1741,14 @@ static int resp_log_sense(struct scsi_cmnd * scp, unsigned char arr[SDEBUG_MAX_LSENSE_SZ]; unsigned char *cmd = (unsigned char *)scp->cmnd; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; memset(arr, 0, sizeof(arr)); ppc = cmd[1] & 0x2; sp = cmd[1] & 0x1; if (ppc || sp) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1640,7 +1773,7 @@ static int resp_log_sense(struct scsi_cmnd * scp, arr[3] = resp_ie_l_pg(arr + 4); break; default: - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1673,12 +1806,12 @@ static int resp_log_sense(struct scsi_cmnd * scp, arr[3] = n - 4; break; default: - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } } else { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1687,16 +1820,16 @@ static int resp_log_sense(struct scsi_cmnd * scp, min(len, SDEBUG_MAX_INQ_ARR_SZ)); } -static int check_device_access_params(struct sdebug_dev_info *devi, +static int check_device_access_params(struct scsi_cmnd *scp, unsigned long long lba, unsigned int num) { if (lba + num > sdebug_capacity) { - mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0); + mk_sense_buffer(scp, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0); return check_condition_result; } /* transfer length excessive (tie in to block limits VPD page) */ if (num > sdebug_store_sectors) { - mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } return 0; @@ -1704,7 +1837,6 @@ static int check_device_access_params(struct sdebug_dev_info *devi, /* Returns number of bytes copied or -1 if error. */ static int do_device_access(struct scsi_cmnd *scmd, - struct sdebug_dev_info *devi, unsigned long long lba, unsigned int num, int write) { int ret; @@ -1861,13 +1993,12 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, } static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, - unsigned int num, struct sdebug_dev_info *devip, - u32 ei_lba) + unsigned int num, u32 ei_lba) { unsigned long iflags; int ret; - ret = check_device_access_params(devip, lba, num); + ret = check_device_access_params(SCpnt, lba, num); if (ret) return ret; @@ -1875,16 +2006,16 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) && ((lba + num) > OPT_MEDIUM_ERR_ADDR)) { /* claim unrecoverable read error */ - mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0); + mk_sense_buffer(SCpnt, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0); /* set info field and valid bit for fixed descriptor */ - if (0x70 == (devip->sense_buff[0] & 0x7f)) { - devip->sense_buff[0] |= 0x80; /* Valid bit */ + if (0x70 == (SCpnt->sense_buffer[0] & 0x7f)) { + SCpnt->sense_buffer[0] |= 0x80; /* Valid bit */ ret = (lba < OPT_MEDIUM_ERR_ADDR) ? OPT_MEDIUM_ERR_ADDR : (int)lba; - devip->sense_buff[3] = (ret >> 24) & 0xff; - devip->sense_buff[4] = (ret >> 16) & 0xff; - devip->sense_buff[5] = (ret >> 8) & 0xff; - devip->sense_buff[6] = ret & 0xff; + SCpnt->sense_buffer[3] = (ret >> 24) & 0xff; + SCpnt->sense_buffer[4] = (ret >> 16) & 0xff; + SCpnt->sense_buffer[5] = (ret >> 8) & 0xff; + SCpnt->sense_buffer[6] = ret & 0xff; } scsi_set_resid(SCpnt, scsi_bufflen(SCpnt)); return check_condition_result; @@ -1898,12 +2029,12 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, if (prot_ret) { read_unlock_irqrestore(&atomic_rw, iflags); - mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret); + mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, prot_ret); return illegal_condition_result; } } - ret = do_device_access(SCpnt, devip, lba, num, 0); + ret = do_device_access(SCpnt, lba, num, 0); read_unlock_irqrestore(&atomic_rw, iflags); if (ret == -1) return DID_ERROR << 16; @@ -1915,22 +2046,23 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, void dump_sector(unsigned char *buf, int len) { - int i, j; - - printk(KERN_ERR ">>> Sector Dump <<<\n"); + int i, j, n; + pr_err(">>> Sector Dump <<<\n"); for (i = 0 ; i < len ; i += 16) { - printk(KERN_ERR "%04d: ", i); + char b[128]; - for (j = 0 ; j < 16 ; j++) { + for (j = 0, n = 0; j < 16; j++) { unsigned char c = buf[i+j]; + if (c >= 0x20 && c < 0x7e) - printk(" %c ", buf[i+j]); + n += scnprintf(b + n, sizeof(b) - n, + " %c ", buf[i+j]); else - printk("%02x ", buf[i+j]); + n += scnprintf(b + n, sizeof(b) - n, + "%02x ", buf[i+j]); } - - printk("\n"); + pr_err("%04d: %s\n", i, b); } } @@ -2092,13 +2224,12 @@ static void unmap_region(sector_t lba, unsigned int len) } static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, - unsigned int num, struct sdebug_dev_info *devip, - u32 ei_lba) + unsigned int num, u32 ei_lba) { unsigned long iflags; int ret; - ret = check_device_access_params(devip, lba, num); + ret = check_device_access_params(SCpnt, lba, num); if (ret) return ret; @@ -2110,12 +2241,13 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, if (prot_ret) { write_unlock_irqrestore(&atomic_rw, iflags); - mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret); + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, + prot_ret); return illegal_condition_result; } } - ret = do_device_access(SCpnt, devip, lba, num, 1); + ret = do_device_access(SCpnt, lba, num, 1); if (scsi_debug_lbp()) map_region(lba, num); write_unlock_irqrestore(&atomic_rw, iflags); @@ -2123,26 +2255,26 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, return (DID_ERROR << 16); else if ((ret < (num * scsi_debug_sector_size)) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) - printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, " - " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret); + sdev_printk(KERN_INFO, SCpnt->device, + "%s: write: cdb indicated=%u, IO sent=%d bytes\n", + my_name, num * scsi_debug_sector_size, ret); return 0; } static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba, - unsigned int num, struct sdebug_dev_info *devip, - u32 ei_lba, unsigned int unmap) + unsigned int num, u32 ei_lba, unsigned int unmap) { unsigned long iflags; unsigned long long i; int ret; - ret = check_device_access_params(devip, lba, num); + ret = check_device_access_params(scmd, lba, num); if (ret) return ret; if (num > scsi_debug_write_same_length) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scmd, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -2164,8 +2296,10 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba, return (DID_ERROR << 16); } else if ((ret < (num * scsi_debug_sector_size)) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) - printk(KERN_INFO "scsi_debug: write same: cdb indicated=%u, " - " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret); + sdev_printk(KERN_INFO, scmd->device, + "%s: %s: cdb indicated=%u, IO sent=%d bytes\n", + my_name, "write same", + num * scsi_debug_sector_size, ret); /* Copy first sector to remaining blocks */ for (i = 1 ; i < num ; i++) @@ -2195,7 +2329,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) int ret; unsigned long iflags; - ret = check_readiness(scmd, 1, devip); + ret = check_readiness(scmd, UAS_ONLY, devip); if (ret) return ret; @@ -2221,7 +2355,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) unsigned long long lba = get_unaligned_be64(&desc[i].lba); unsigned int num = get_unaligned_be32(&desc[i].blocks); - ret = check_device_access_params(devip, lba, num); + ret = check_device_access_params(scmd, lba, num); if (ret) goto out; @@ -2247,7 +2381,7 @@ static int resp_get_lba_status(struct scsi_cmnd * scmd, unsigned char arr[SDEBUG_GET_LBA_STATUS_LEN]; int ret; - ret = check_readiness(scmd, 1, devip); + ret = check_readiness(scmd, UAS_ONLY, devip); if (ret) return ret; @@ -2257,7 +2391,7 @@ static int resp_get_lba_status(struct scsi_cmnd * scmd, if (alloc_len < 24) return 0; - ret = check_device_access_params(devip, lba, 1); + ret = check_device_access_params(scmd, lba, 1); if (ret) return ret; @@ -2278,7 +2412,8 @@ static int resp_report_luns(struct scsi_cmnd * scp, struct sdebug_dev_info * devip) { unsigned int alloc_len; - int lun_cnt, i, upper, num, n, wlun, lun; + int lun_cnt, i, upper, num, n; + u64 wlun, lun; unsigned char *cmd = (unsigned char *)scp->cmnd; int select_report = (int)cmd[2]; struct scsi_lun *one_lun; @@ -2287,7 +2422,7 @@ static int resp_report_luns(struct scsi_cmnd * scp, alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); if ((alloc_len < 4) || (select_report > 2)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -2341,7 +2476,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, /* better not to use temporary buffer. */ buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); if (!buf) { - mk_sense_buffer(devip, NOT_READY, + mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); return check_condition_result; } @@ -2365,34 +2500,125 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, return 0; } -/* When timer goes off this function is called. */ -static void timer_intr_handler(unsigned long indx) +/* When timer or tasklet goes off this function is called. */ +static void sdebug_q_cmd_complete(unsigned long indx) { - struct sdebug_queued_cmd * sqcp; + int qa_indx; + int retiring = 0; unsigned long iflags; + struct sdebug_queued_cmd *sqcp; + struct scsi_cmnd *scp; + struct sdebug_dev_info *devip; - if (indx >= scsi_debug_max_queue) { - printk(KERN_ERR "scsi_debug:timer_intr_handler: indx too " - "large\n"); + atomic_inc(&sdebug_completions); + qa_indx = indx; + if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { + pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx); return; } spin_lock_irqsave(&queued_arr_lock, iflags); - sqcp = &queued_arr[(int)indx]; - if (! sqcp->in_use) { - printk(KERN_ERR "scsi_debug:timer_intr_handler: Unexpected " - "interrupt\n"); + sqcp = &queued_arr[qa_indx]; + scp = sqcp->a_cmnd; + if (NULL == scp) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: scp is NULL\n", __func__); + return; + } + devip = (struct sdebug_dev_info *)scp->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + else + pr_err("%s: devip=NULL\n", __func__); + if (atomic_read(&retired_max_queue) > 0) + retiring = 1; + + sqcp->a_cmnd = NULL; + if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: Unexpected completion\n", __func__); return; } - sqcp->in_use = 0; - if (sqcp->done_funct) { - sqcp->a_cmnd->result = sqcp->scsi_result; - sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */ + + if (unlikely(retiring)) { /* user has reduced max_queue */ + int k, retval; + + retval = atomic_read(&retired_max_queue); + if (qa_indx >= retval) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: index %d too large\n", __func__, retval); + return; + } + k = find_last_bit(queued_in_use_bm, retval); + if ((k < scsi_debug_max_queue) || (k == retval)) + atomic_set(&retired_max_queue, 0); + else + atomic_set(&retired_max_queue, k + 1); } - sqcp->done_funct = NULL; spin_unlock_irqrestore(&queued_arr_lock, iflags); + scp->scsi_done(scp); /* callback to mid level */ } +/* When high resolution timer goes off this function is called. */ +static enum hrtimer_restart +sdebug_q_cmd_hrt_complete(struct hrtimer *timer) +{ + int qa_indx; + int retiring = 0; + unsigned long iflags; + struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer; + struct sdebug_queued_cmd *sqcp; + struct scsi_cmnd *scp; + struct sdebug_dev_info *devip; + + atomic_inc(&sdebug_completions); + qa_indx = sd_hrtp->qa_indx; + if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { + pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx); + goto the_end; + } + spin_lock_irqsave(&queued_arr_lock, iflags); + sqcp = &queued_arr[qa_indx]; + scp = sqcp->a_cmnd; + if (NULL == scp) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: scp is NULL\n", __func__); + goto the_end; + } + devip = (struct sdebug_dev_info *)scp->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + else + pr_err("%s: devip=NULL\n", __func__); + if (atomic_read(&retired_max_queue) > 0) + retiring = 1; + + sqcp->a_cmnd = NULL; + if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: Unexpected completion\n", __func__); + goto the_end; + } + + if (unlikely(retiring)) { /* user has reduced max_queue */ + int k, retval; + + retval = atomic_read(&retired_max_queue); + if (qa_indx >= retval) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: index %d too large\n", __func__, retval); + goto the_end; + } + k = find_last_bit(queued_in_use_bm, retval); + if ((k < scsi_debug_max_queue) || (k == retval)) + atomic_set(&retired_max_queue, 0); + else + atomic_set(&retired_max_queue, k + 1); + } + spin_unlock_irqrestore(&queued_arr_lock, iflags); + scp->scsi_done(scp); /* callback to mid level */ +the_end: + return HRTIMER_NORESTART; +} static struct sdebug_dev_info * sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags) @@ -2418,7 +2644,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) return devip; sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host); if (!sdbg_host) { - printk(KERN_ERR "Host info NULL\n"); + pr_err("%s: Host info NULL\n", __func__); return NULL; } list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { @@ -2444,15 +2670,9 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) open_devip->target = sdev->id; open_devip->lun = sdev->lun; open_devip->sdbg_host = sdbg_host; - open_devip->reset = 1; + atomic_set(&open_devip->num_in_q, 0); + set_bit(SDEBUG_UA_POR, open_devip->uas_bm); open_devip->used = 1; - memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN); - if (scsi_debug_dsense) - open_devip->sense_buff[0] = 0x72; - else { - open_devip->sense_buff[0] = 0x70; - open_devip->sense_buff[7] = 0xa; - } if (sdev->lun == SAM2_WLUN_REPORT_LUNS) open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff; @@ -2462,7 +2682,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) static int scsi_debug_slave_alloc(struct scsi_device *sdp) { if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", + printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue); return 0; @@ -2473,7 +2693,7 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp) struct sdebug_dev_info *devip; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n", + printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; @@ -2481,10 +2701,11 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp) if (NULL == devip) return 1; /* no resources, will be marked offline */ sdp->hostdata = devip; + sdp->tagged_supported = 1; if (sdp->host->cmd_per_lun) - scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, - sdp->host->cmd_per_lun); - blk_queue_max_segment_size(sdp->request_queue, 256 * 1024); + scsi_adjust_queue_depth(sdp, DEF_TAGGED_QUEUING, + DEF_CMD_PER_LUN); + blk_queue_max_segment_size(sdp->request_queue, -1U); if (scsi_debug_no_uld) sdp->no_uld_attach = 1; return 0; @@ -2496,7 +2717,7 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) (struct sdebug_dev_info *)sdp->hostdata; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n", + printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (devip) { /* make this slot available for re-use */ @@ -2505,150 +2726,230 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) } } -/* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */ +/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */ static int stop_queued_cmnd(struct scsi_cmnd *cmnd) { unsigned long iflags; - int k; + int k, qmax, r_qmax; struct sdebug_queued_cmd *sqcp; + struct sdebug_dev_info *devip; spin_lock_irqsave(&queued_arr_lock, iflags); - for (k = 0; k < scsi_debug_max_queue; ++k) { - sqcp = &queued_arr[k]; - if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) { - del_timer_sync(&sqcp->cmnd_timer); - sqcp->in_use = 0; - sqcp->a_cmnd = NULL; - break; + qmax = scsi_debug_max_queue; + r_qmax = atomic_read(&retired_max_queue); + if (r_qmax > qmax) + qmax = r_qmax; + for (k = 0; k < qmax; ++k) { + if (test_bit(k, queued_in_use_bm)) { + sqcp = &queued_arr[k]; + if (cmnd == sqcp->a_cmnd) { + if (scsi_debug_ndelay > 0) { + if (sqcp->sd_hrtp) + hrtimer_cancel( + &sqcp->sd_hrtp->hrt); + } else if (scsi_debug_delay > 0) { + if (sqcp->cmnd_timerp) + del_timer_sync( + sqcp->cmnd_timerp); + } else if (scsi_debug_delay < 0) { + if (sqcp->tletp) + tasklet_kill(sqcp->tletp); + } + __clear_bit(k, queued_in_use_bm); + devip = (struct sdebug_dev_info *) + cmnd->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + sqcp->a_cmnd = NULL; + break; + } } } spin_unlock_irqrestore(&queued_arr_lock, iflags); - return (k < scsi_debug_max_queue) ? 1 : 0; + return (k < qmax) ? 1 : 0; } -/* Deletes (stops) timers of all queued commands */ +/* Deletes (stops) timers or tasklets of all queued commands */ static void stop_all_queued(void) { unsigned long iflags; int k; struct sdebug_queued_cmd *sqcp; + struct sdebug_dev_info *devip; spin_lock_irqsave(&queued_arr_lock, iflags); - for (k = 0; k < scsi_debug_max_queue; ++k) { - sqcp = &queued_arr[k]; - if (sqcp->in_use && sqcp->a_cmnd) { - del_timer_sync(&sqcp->cmnd_timer); - sqcp->in_use = 0; - sqcp->a_cmnd = NULL; + for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { + if (test_bit(k, queued_in_use_bm)) { + sqcp = &queued_arr[k]; + if (sqcp->a_cmnd) { + if (scsi_debug_ndelay > 0) { + if (sqcp->sd_hrtp) + hrtimer_cancel( + &sqcp->sd_hrtp->hrt); + } else if (scsi_debug_delay > 0) { + if (sqcp->cmnd_timerp) + del_timer_sync( + sqcp->cmnd_timerp); + } else if (scsi_debug_delay < 0) { + if (sqcp->tletp) + tasklet_kill(sqcp->tletp); + } + __clear_bit(k, queued_in_use_bm); + devip = (struct sdebug_dev_info *) + sqcp->a_cmnd->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + sqcp->a_cmnd = NULL; + } } } spin_unlock_irqrestore(&queued_arr_lock, iflags); } -static int scsi_debug_abort(struct scsi_cmnd * SCpnt) +/* Free queued command memory on heap */ +static void free_all_queued(void) { - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: abort\n"); - ++num_aborts; - stop_queued_cmnd(SCpnt); - return SUCCESS; + unsigned long iflags; + int k; + struct sdebug_queued_cmd *sqcp; + + spin_lock_irqsave(&queued_arr_lock, iflags); + for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { + sqcp = &queued_arr[k]; + kfree(sqcp->cmnd_timerp); + sqcp->cmnd_timerp = NULL; + kfree(sqcp->tletp); + sqcp->tletp = NULL; + kfree(sqcp->sd_hrtp); + sqcp->sd_hrtp = NULL; + } + spin_unlock_irqrestore(&queued_arr_lock, iflags); } -static int scsi_debug_biosparam(struct scsi_device *sdev, - struct block_device * bdev, sector_t capacity, int *info) +static int scsi_debug_abort(struct scsi_cmnd *SCpnt) { - int res; - unsigned char *buf; - - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: biosparam\n"); - buf = scsi_bios_ptable(bdev); - if (buf) { - res = scsi_partsize(buf, capacity, - &info[2], &info[0], &info[1]); - kfree(buf); - if (! res) - return res; - } - info[0] = sdebug_heads; - info[1] = sdebug_sectors_per; - info[2] = sdebug_cylinders_per; - return 0; + ++num_aborts; + if (SCpnt) { + if (SCpnt->device && + (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)) + sdev_printk(KERN_INFO, SCpnt->device, "%s\n", + __func__); + stop_queued_cmnd(SCpnt); + } + return SUCCESS; } static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt) { struct sdebug_dev_info * devip; - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: device_reset\n"); ++num_dev_resets; - if (SCpnt) { - devip = devInfoReg(SCpnt->device); + if (SCpnt && SCpnt->device) { + struct scsi_device *sdp = SCpnt->device; + + if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, "%s\n", __func__); + devip = devInfoReg(sdp); if (devip) - devip->reset = 1; + set_bit(SDEBUG_UA_POR, devip->uas_bm); + } + return SUCCESS; +} + +static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt) +{ + struct sdebug_host_info *sdbg_host; + struct sdebug_dev_info *devip; + struct scsi_device *sdp; + struct Scsi_Host *hp; + int k = 0; + + ++num_target_resets; + if (!SCpnt) + goto lie; + sdp = SCpnt->device; + if (!sdp) + goto lie; + if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, "%s\n", __func__); + hp = sdp->host; + if (!hp) + goto lie; + sdbg_host = *(struct sdebug_host_info **)shost_priv(hp); + if (sdbg_host) { + list_for_each_entry(devip, + &sdbg_host->dev_info_list, + dev_list) + if (devip->target == sdp->id) { + set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); + ++k; + } } + if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, + "%s: %d device(s) found in target\n", __func__, k); +lie: return SUCCESS; } static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) { struct sdebug_host_info *sdbg_host; - struct sdebug_dev_info * dev_info; + struct sdebug_dev_info *devip; struct scsi_device * sdp; struct Scsi_Host * hp; + int k = 0; - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: bus_reset\n"); ++num_bus_resets; - if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) { + if (!(SCpnt && SCpnt->device)) + goto lie; + sdp = SCpnt->device; + if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, "%s\n", __func__); + hp = sdp->host; + if (hp) { sdbg_host = *(struct sdebug_host_info **)shost_priv(hp); if (sdbg_host) { - list_for_each_entry(dev_info, + list_for_each_entry(devip, &sdbg_host->dev_info_list, - dev_list) - dev_info->reset = 1; + dev_list) { + set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); + ++k; + } } } + if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, + "%s: %d device(s) found in host\n", __func__, k); +lie: return SUCCESS; } static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt) { struct sdebug_host_info * sdbg_host; - struct sdebug_dev_info * dev_info; + struct sdebug_dev_info *devip; + int k = 0; - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: host_reset\n"); ++num_host_resets; + if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)) + sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__); spin_lock(&sdebug_host_list_lock); list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { - list_for_each_entry(dev_info, &sdbg_host->dev_info_list, - dev_list) - dev_info->reset = 1; + list_for_each_entry(devip, &sdbg_host->dev_info_list, + dev_list) { + set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); + ++k; + } } spin_unlock(&sdebug_host_list_lock); stop_all_queued(); + if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, SCpnt->device, + "%s: %d device(s) found\n", __func__, k); return SUCCESS; } -/* Initializes timers in queued array */ -static void __init init_all_queued(void) -{ - unsigned long iflags; - int k; - struct sdebug_queued_cmd * sqcp; - - spin_lock_irqsave(&queued_arr_lock, iflags); - for (k = 0; k < scsi_debug_max_queue; ++k) { - sqcp = &queued_arr[k]; - init_timer(&sqcp->cmnd_timer); - sqcp->in_use = 0; - sqcp->a_cmnd = NULL; - } - spin_unlock_irqrestore(&queued_arr_lock, iflags); -} - static void __init sdebug_build_parts(unsigned char *ramp, unsigned long store_size) { @@ -2662,8 +2963,8 @@ static void __init sdebug_build_parts(unsigned char *ramp, return; if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) { scsi_debug_num_parts = SDEBUG_MAX_PARTS; - printk(KERN_WARNING "scsi_debug:build_parts: reducing " - "partitions to %d\n", SDEBUG_MAX_PARTS); + pr_warn("%s: reducing partitions to %d\n", __func__, + SDEBUG_MAX_PARTS); } num_sectors = (int)sdebug_store_sectors; sectors_per_part = (num_sectors - sdebug_sectors_per) @@ -2700,62 +3001,130 @@ static void __init sdebug_build_parts(unsigned char *ramp, } } -static int schedule_resp(struct scsi_cmnd * cmnd, - struct sdebug_dev_info * devip, - done_funct_t done, int scsi_result, int delta_jiff) +static int +schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, + int scsi_result, int delta_jiff) { - if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) { - if (scsi_result) { - struct scsi_device * sdp = cmnd->device; + unsigned long iflags; + int k, num_in_q, tsf, qdepth, inject; + struct sdebug_queued_cmd *sqcp = NULL; + struct scsi_device *sdp = cmnd->device; + + if (NULL == cmnd || NULL == devip) { + pr_warn("%s: called with NULL cmnd or devip pointer\n", + __func__); + /* no particularly good error to report back */ + return SCSI_MLQUEUE_HOST_BUSY; + } + if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) + sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", + __func__, scsi_result); + if (delta_jiff == 0) { + /* using same thread to call back mid-layer */ + cmnd->result = scsi_result; + cmnd->scsi_done(cmnd); + return 0; + } - printk(KERN_INFO "scsi_debug: <%u %u %u %u> " - "non-zero result=0x%x\n", sdp->host->host_no, - sdp->channel, sdp->id, sdp->lun, scsi_result); + /* deferred response cases */ + spin_lock_irqsave(&queued_arr_lock, iflags); + num_in_q = atomic_read(&devip->num_in_q); + qdepth = cmnd->device->queue_depth; + k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue); + tsf = 0; + inject = 0; + if ((qdepth > 0) && (num_in_q >= qdepth)) + tsf = 1; + else if ((scsi_debug_every_nth != 0) && + (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts)) { + if ((num_in_q == (qdepth - 1)) && + (atomic_inc_return(&sdebug_a_tsf) >= + abs(scsi_debug_every_nth))) { + atomic_set(&sdebug_a_tsf, 0); + inject = 1; + tsf = 1; } } - if (cmnd && devip) { - /* simulate autosense by this driver */ - if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff)) - memcpy(cmnd->sense_buffer, devip->sense_buff, - (SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ? - SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE); - } - if (delta_jiff <= 0) { - if (cmnd) - cmnd->result = scsi_result; - if (done) - done(cmnd); - return 0; - } else { - unsigned long iflags; - int k; - struct sdebug_queued_cmd * sqcp = NULL; - spin_lock_irqsave(&queued_arr_lock, iflags); - for (k = 0; k < scsi_debug_max_queue; ++k) { - sqcp = &queued_arr[k]; - if (! sqcp->in_use) - break; + /* if (tsf) simulate device reporting SCSI status of TASK SET FULL. + * Might override existing CHECK CONDITION. */ + if (tsf) + scsi_result = device_qfull_result; + if (k >= scsi_debug_max_queue) { + if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts) + tsf = 1; + spin_unlock_irqrestore(&queued_arr_lock, iflags); + if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, + "%s: num_in_q=%d, bypass q, %s%s\n", + __func__, num_in_q, + (inject ? "<inject> " : ""), + (tsf ? "status: TASK SET FULL" : + "report: host busy")); + if (tsf) { + /* queued_arr full so respond in same thread */ + cmnd->result = scsi_result; + cmnd->scsi_done(cmnd); + /* As scsi_done() is called "inline" must return 0 */ + return 0; + } else + return SCSI_MLQUEUE_HOST_BUSY; + } + __set_bit(k, queued_in_use_bm); + atomic_inc(&devip->num_in_q); + sqcp = &queued_arr[k]; + sqcp->a_cmnd = cmnd; + cmnd->result = scsi_result; + spin_unlock_irqrestore(&queued_arr_lock, iflags); + if (delta_jiff > 0) { + if (NULL == sqcp->cmnd_timerp) { + sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list), + GFP_ATOMIC); + if (NULL == sqcp->cmnd_timerp) + return SCSI_MLQUEUE_HOST_BUSY; + init_timer(sqcp->cmnd_timerp); } - if (k >= scsi_debug_max_queue) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); - printk(KERN_WARNING "scsi_debug: can_queue exceeded\n"); - return 1; /* report busy to mid level */ + sqcp->cmnd_timerp->function = sdebug_q_cmd_complete; + sqcp->cmnd_timerp->data = k; + sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff; + add_timer(sqcp->cmnd_timerp); + } else if (scsi_debug_ndelay > 0) { + ktime_t kt = ktime_set(0, scsi_debug_ndelay); + struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp; + + if (NULL == sd_hp) { + sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC); + if (NULL == sd_hp) + return SCSI_MLQUEUE_HOST_BUSY; + sqcp->sd_hrtp = sd_hp; + hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + sd_hp->hrt.function = sdebug_q_cmd_hrt_complete; + sd_hp->qa_indx = k; } - sqcp->in_use = 1; - sqcp->a_cmnd = cmnd; - sqcp->scsi_result = scsi_result; - sqcp->done_funct = done; - sqcp->cmnd_timer.function = timer_intr_handler; - sqcp->cmnd_timer.data = k; - sqcp->cmnd_timer.expires = jiffies + delta_jiff; - add_timer(&sqcp->cmnd_timer); - spin_unlock_irqrestore(&queued_arr_lock, iflags); - if (cmnd) - cmnd->result = 0; - return 0; + hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL); + } else { /* delay < 0 */ + if (NULL == sqcp->tletp) { + sqcp->tletp = kmalloc(sizeof(*sqcp->tletp), + GFP_ATOMIC); + if (NULL == sqcp->tletp) + return SCSI_MLQUEUE_HOST_BUSY; + tasklet_init(sqcp->tletp, + sdebug_q_cmd_complete, k); + } + if (-1 == delta_jiff) + tasklet_hi_schedule(sqcp->tletp); + else + tasklet_schedule(sqcp->tletp); } + if (tsf && (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)) + sdev_printk(KERN_INFO, sdp, + "%s: num_in_q=%d +1, %s%s\n", __func__, + num_in_q, (inject ? "<inject> " : ""), + "status: TASK SET FULL"); + return 0; } + /* Note: The following macros create attribute files in the /sys/module/scsi_debug/parameters directory. Unfortunately this driver is unaware of a change and cannot trigger auxiliary actions @@ -2773,6 +3142,7 @@ module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR); module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR); module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR); module_param_named(guard, scsi_debug_guard, uint, S_IRUGO); +module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR); module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO); module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO); module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO); @@ -2780,6 +3150,7 @@ module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO); module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO); module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR); module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR); +module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR); module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR); module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO); module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO); @@ -2809,7 +3180,7 @@ MODULE_VERSION(SCSI_DEBUG_VERSION); MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)"); MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)"); -MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)"); +MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny"); MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)"); MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)"); MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)"); @@ -2817,13 +3188,15 @@ MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)"); MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)"); MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)"); MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); +MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)"); MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)"); MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)"); MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)"); MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)"); MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)"); MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); -MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to 255(def))"); +MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))"); +MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)"); MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)"); MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))"); MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); @@ -2854,9 +3227,7 @@ static const char * scsi_debug_info(struct Scsi_Host * shp) return sdebug_info; } -/* scsi_debug_proc_info - * Used if the driver currently has no own support for /proc/scsi - */ +/* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length) { char arr[16]; @@ -2871,27 +3242,49 @@ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int lengt return -EINVAL; scsi_debug_opts = opts; if (scsi_debug_every_nth != 0) - scsi_debug_cmnd_count = 0; + atomic_set(&sdebug_cmnd_count, 0); return length; } +/* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the + * same for each scsi_debug host (if more than one). Some of the counters + * output are not atomics so might be inaccurate in a busy system. */ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) { - seq_printf(m, "scsi_debug adapter driver, version " - "%s [%s]\n" - "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, " - "every_nth=%d(curr:%d)\n" - "delay=%d, max_luns=%d, scsi_level=%d\n" - "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" - "number of aborts=%d, device_reset=%d, bus_resets=%d, " - "host_resets=%d\ndix_reads=%d dix_writes=%d dif_errors=%d\n", - SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts, - scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, - scsi_debug_cmnd_count, scsi_debug_delay, - scsi_debug_max_luns, scsi_debug_scsi_level, - scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, - sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets, - num_host_resets, dix_reads, dix_writes, dif_errors); + int f, l; + char b[32]; + + if (scsi_debug_every_nth > 0) + snprintf(b, sizeof(b), " (curr:%d)", + ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ? + atomic_read(&sdebug_a_tsf) : + atomic_read(&sdebug_cmnd_count))); + else + b[0] = '\0'; + + seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n" + "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, " + "every_nth=%d%s\n" + "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n" + "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" + "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, " + "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d " + "usec_in_jiffy=%lu\n", + SCSI_DEBUG_VERSION, scsi_debug_version_date, + scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts, + scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay, + scsi_debug_max_luns, atomic_read(&sdebug_completions), + scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, + sdebug_sectors_per, num_aborts, num_dev_resets, + num_target_resets, num_bus_resets, num_host_resets, + dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000); + + f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue); + if (f != scsi_debug_max_queue) { + l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue); + seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n", + "queued_in_use_bm", f, l); + } return 0; } @@ -2899,23 +3292,69 @@ static ssize_t delay_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay); } - +/* Returns -EBUSY if delay is being changed and commands are queued */ static ssize_t delay_store(struct device_driver *ddp, const char *buf, size_t count) { - int delay; - char work[20]; - - if (1 == sscanf(buf, "%10s", work)) { - if ((1 == sscanf(work, "%d", &delay)) && (delay >= 0)) { - scsi_debug_delay = delay; - return count; + int delay, res; + + if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) { + res = count; + if (scsi_debug_delay != delay) { + unsigned long iflags; + int k; + + spin_lock_irqsave(&queued_arr_lock, iflags); + k = find_first_bit(queued_in_use_bm, + scsi_debug_max_queue); + if (k != scsi_debug_max_queue) + res = -EBUSY; /* have queued commands */ + else { + scsi_debug_delay = delay; + scsi_debug_ndelay = 0; + } + spin_unlock_irqrestore(&queued_arr_lock, iflags); } + return res; } return -EINVAL; } static DRIVER_ATTR_RW(delay); +static ssize_t ndelay_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay); +} +/* Returns -EBUSY if ndelay is being changed and commands are queued */ +/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */ +static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, + size_t count) +{ + unsigned long iflags; + int ndelay, res, k; + + if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) && + (ndelay >= 0) && (ndelay < 1000000000)) { + res = count; + if (scsi_debug_ndelay != ndelay) { + spin_lock_irqsave(&queued_arr_lock, iflags); + k = find_first_bit(queued_in_use_bm, + scsi_debug_max_queue); + if (k != scsi_debug_max_queue) + res = -EBUSY; /* have queued commands */ + else { + scsi_debug_ndelay = ndelay; + scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN + : DEF_DELAY; + } + spin_unlock_irqrestore(&queued_arr_lock, iflags); + } + return res; + } + return -EINVAL; +} +static DRIVER_ATTR_RW(ndelay); + static ssize_t opts_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts); @@ -2939,7 +3378,8 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf, return -EINVAL; opts_done: scsi_debug_opts = opts; - scsi_debug_cmnd_count = 0; + atomic_set(&sdebug_cmnd_count, 0); + atomic_set(&sdebug_a_tsf, 0); return count; } static DRIVER_ATTR_RW(opts); @@ -2988,7 +3428,24 @@ static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf, int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - scsi_debug_fake_rw = n; + n = (n > 0); + scsi_debug_fake_rw = (scsi_debug_fake_rw > 0); + if (scsi_debug_fake_rw != n) { + if ((0 == n) && (NULL == fake_storep)) { + unsigned long sz = + (unsigned long)scsi_debug_dev_size_mb * + 1048576; + + fake_storep = vmalloc(sz); + if (NULL == fake_storep) { + pr_err("%s: out of memory, 9\n", + __func__); + return -ENOMEM; + } + memset(fake_storep, 0, sz); + } + scsi_debug_fake_rw = n; + } return count; } return -EINVAL; @@ -3053,7 +3510,7 @@ static ssize_t every_nth_store(struct device_driver *ddp, const char *buf, if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) { scsi_debug_every_nth = nth; - scsi_debug_cmnd_count = 0; + atomic_set(&sdebug_cmnd_count, 0); return count; } return -EINVAL; @@ -3082,14 +3539,26 @@ static ssize_t max_queue_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue); } +/* N.B. max_queue can be changed while there are queued commands. In flight + * commands beyond the new max_queue will be completed. */ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, size_t count) { - int n; + unsigned long iflags; + int n, k; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) && (n <= SCSI_DEBUG_CANQUEUE)) { + spin_lock_irqsave(&queued_arr_lock, iflags); + k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE); scsi_debug_max_queue = n; + if (SCSI_DEBUG_CANQUEUE == k) + atomic_set(&retired_max_queue, 0); + else if (k >= n) + atomic_set(&retired_max_queue, k + 1); + else + atomic_set(&retired_max_queue, 0); + spin_unlock_irqrestore(&queued_arr_lock, iflags); return count; } return -EINVAL; @@ -3234,6 +3703,40 @@ static ssize_t removable_store(struct device_driver *ddp, const char *buf, } static DRIVER_ATTR_RW(removable); +static ssize_t host_lock_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock); +} +/* Returns -EBUSY if host_lock is being changed and commands are queued */ +static ssize_t host_lock_store(struct device_driver *ddp, const char *buf, + size_t count) +{ + int n, res; + + if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { + bool new_host_lock = (n > 0); + + res = count; + if (new_host_lock != scsi_debug_host_lock) { + unsigned long iflags; + int k; + + spin_lock_irqsave(&queued_arr_lock, iflags); + k = find_first_bit(queued_in_use_bm, + scsi_debug_max_queue); + if (k != scsi_debug_max_queue) + res = -EBUSY; /* have queued commands */ + else + scsi_debug_host_lock = new_host_lock; + spin_unlock_irqrestore(&queued_arr_lock, iflags); + } + return res; + } + return -EINVAL; +} +static DRIVER_ATTR_RW(host_lock); + + /* Note: The following array creates attribute files in the /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these files (over those found in the /sys/module/scsi_debug/parameters @@ -3266,6 +3769,8 @@ static struct attribute *sdebug_drv_attrs[] = { &driver_attr_ato.attr, &driver_attr_map.attr, &driver_attr_removable.attr, + &driver_attr_host_lock.attr, + &driver_attr_ndelay.attr, NULL, }; ATTRIBUTE_GROUPS(sdebug_drv); @@ -3279,6 +3784,17 @@ static int __init scsi_debug_init(void) int k; int ret; + atomic_set(&sdebug_cmnd_count, 0); + atomic_set(&sdebug_completions, 0); + atomic_set(&retired_max_queue, 0); + + if (scsi_debug_ndelay >= 1000000000) { + pr_warn("%s: ndelay must be less than 1 second, ignored\n", + __func__); + scsi_debug_ndelay = 0; + } else if (scsi_debug_ndelay > 0) + scsi_debug_delay = DELAY_OVERRIDDEN; + switch (scsi_debug_sector_size) { case 512: case 1024: @@ -3286,7 +3802,7 @@ static int __init scsi_debug_init(void) case 4096: break; default: - printk(KERN_ERR "scsi_debug_init: invalid sector_size %d\n", + pr_err("%s: invalid sector_size %d\n", __func__, scsi_debug_sector_size); return -EINVAL; } @@ -3300,28 +3816,28 @@ static int __init scsi_debug_init(void) break; default: - printk(KERN_ERR "scsi_debug_init: dif must be 0, 1, 2 or 3\n"); + pr_err("%s: dif must be 0, 1, 2 or 3\n", __func__); return -EINVAL; } if (scsi_debug_guard > 1) { - printk(KERN_ERR "scsi_debug_init: guard must be 0 or 1\n"); + pr_err("%s: guard must be 0 or 1\n", __func__); return -EINVAL; } if (scsi_debug_ato > 1) { - printk(KERN_ERR "scsi_debug_init: ato must be 0 or 1\n"); + pr_err("%s: ato must be 0 or 1\n", __func__); return -EINVAL; } if (scsi_debug_physblk_exp > 15) { - printk(KERN_ERR "scsi_debug_init: invalid physblk_exp %u\n", + pr_err("%s: invalid physblk_exp %u\n", __func__, scsi_debug_physblk_exp); return -EINVAL; } if (scsi_debug_lowest_aligned > 0x3fff) { - printk(KERN_ERR "scsi_debug_init: lowest_aligned too big: %u\n", + pr_err("%s: lowest_aligned too big: %u\n", __func__, scsi_debug_lowest_aligned); return -EINVAL; } @@ -3349,14 +3865,16 @@ static int __init scsi_debug_init(void) (sdebug_sectors_per * sdebug_heads); } - fake_storep = vmalloc(sz); - if (NULL == fake_storep) { - printk(KERN_ERR "scsi_debug_init: out of memory, 1\n"); - return -ENOMEM; + if (0 == scsi_debug_fake_rw) { + fake_storep = vmalloc(sz); + if (NULL == fake_storep) { + pr_err("%s: out of memory, 1\n", __func__); + return -ENOMEM; + } + memset(fake_storep, 0, sz); + if (scsi_debug_num_parts > 0) + sdebug_build_parts(fake_storep, sz); } - memset(fake_storep, 0, sz); - if (scsi_debug_num_parts > 0) - sdebug_build_parts(fake_storep, sz); if (scsi_debug_dix) { int dif_size; @@ -3364,11 +3882,11 @@ static int __init scsi_debug_init(void) dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); dif_storep = vmalloc(dif_size); - printk(KERN_ERR "scsi_debug_init: dif_storep %u bytes @ %p\n", - dif_size, dif_storep); + pr_err("%s: dif_storep %u bytes @ %p\n", __func__, dif_size, + dif_storep); if (dif_storep == NULL) { - printk(KERN_ERR "scsi_debug_init: out of mem. (DIX)\n"); + pr_err("%s: out of mem. (DIX)\n", __func__); ret = -ENOMEM; goto free_vm; } @@ -3390,8 +3908,7 @@ static int __init scsi_debug_init(void) if (scsi_debug_unmap_alignment && scsi_debug_unmap_granularity <= scsi_debug_unmap_alignment) { - printk(KERN_ERR - "%s: ERR: unmap_granularity <= unmap_alignment\n", + pr_err("%s: ERR: unmap_granularity <= unmap_alignment\n", __func__); return -EINVAL; } @@ -3399,11 +3916,10 @@ static int __init scsi_debug_init(void) map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1; map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long)); - printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n", - map_size); + pr_info("%s: %lu provisioning blocks\n", __func__, map_size); if (map_storep == NULL) { - printk(KERN_ERR "scsi_debug_init: out of mem. (MAP)\n"); + pr_err("%s: out of mem. (MAP)\n", __func__); ret = -ENOMEM; goto free_vm; } @@ -3417,39 +3933,35 @@ static int __init scsi_debug_init(void) pseudo_primary = root_device_register("pseudo_0"); if (IS_ERR(pseudo_primary)) { - printk(KERN_WARNING "scsi_debug: root_device_register() error\n"); + pr_warn("%s: root_device_register() error\n", __func__); ret = PTR_ERR(pseudo_primary); goto free_vm; } ret = bus_register(&pseudo_lld_bus); if (ret < 0) { - printk(KERN_WARNING "scsi_debug: bus_register error: %d\n", - ret); + pr_warn("%s: bus_register error: %d\n", __func__, ret); goto dev_unreg; } ret = driver_register(&sdebug_driverfs_driver); if (ret < 0) { - printk(KERN_WARNING "scsi_debug: driver_register error: %d\n", - ret); + pr_warn("%s: driver_register error: %d\n", __func__, ret); goto bus_unreg; } - init_all_queued(); - host_to_add = scsi_debug_add_host; scsi_debug_add_host = 0; for (k = 0; k < host_to_add; k++) { if (sdebug_add_adapter()) { - printk(KERN_ERR "scsi_debug_init: " - "sdebug_add_adapter failed k=%d\n", k); + pr_err("%s: sdebug_add_adapter failed k=%d\n", + __func__, k); break; } } if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { - printk(KERN_INFO "scsi_debug_init: built %d host(s)\n", - scsi_debug_add_host); + pr_info("%s: built %d host(s)\n", __func__, + scsi_debug_add_host); } return 0; @@ -3472,6 +3984,7 @@ static void __exit scsi_debug_exit(void) int k = scsi_debug_add_host; stop_all_queued(); + free_all_queued(); for (; k; k--) sdebug_remove_adapter(); driver_unregister(&sdebug_driverfs_driver); @@ -3569,8 +4082,8 @@ static void sdebug_remove_adapter(void) --scsi_debug_add_host; } -static -int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) +static int +scsi_debug_queuecommand(struct scsi_cmnd *SCpnt) { unsigned char *cmd = (unsigned char *) SCpnt->cmnd; int len, k; @@ -3589,32 +4102,34 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) int unmap = 0; scsi_set_resid(SCpnt, 0); - if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) { - printk(KERN_INFO "scsi_debug: cmd "); - for (k = 0, len = SCpnt->cmd_len; k < len; ++k) - printk("%02x ", (int)cmd[k]); - printk("\n"); - } - - if (target == SCpnt->device->host->hostt->this_id) { - printk(KERN_INFO "scsi_debug: initiator's id used as " - "target!\n"); - return schedule_resp(SCpnt, NULL, done, - DID_NO_CONNECT << 16, 0); + if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && + !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts) && cmd) { + char b[120]; + int n; + + len = SCpnt->cmd_len; + if (len > 32) + strcpy(b, "too long, over 32 bytes"); + else { + for (k = 0, n = 0; k < len; ++k) + n += scnprintf(b + n, sizeof(b) - n, "%02x ", + (unsigned int)cmd[k]); + } + sdev_printk(KERN_INFO, SCpnt->device, "%s: cmd %s\n", my_name, + b); } if ((SCpnt->device->lun >= scsi_debug_max_luns) && (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS)) - return schedule_resp(SCpnt, NULL, done, - DID_NO_CONNECT << 16, 0); + return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0); devip = devInfoReg(SCpnt->device); if (NULL == devip) - return schedule_resp(SCpnt, NULL, done, - DID_NO_CONNECT << 16, 0); + return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0); if ((scsi_debug_every_nth != 0) && - (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) { - scsi_debug_cmnd_count = 0; + (atomic_inc_return(&sdebug_cmnd_count) >= + abs(scsi_debug_every_nth))) { + atomic_set(&sdebug_cmnd_count, 0); if (scsi_debug_every_nth < -1) scsi_debug_every_nth = -1; if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) @@ -3645,11 +4160,10 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: Opcode: 0x%x " "not supported for wlun\n", *cmd); - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0); errsts = check_condition_result; - return schedule_resp(SCpnt, devip, done, errsts, - 0); + return schedule_resp(SCpnt, devip, errsts, 0); } } @@ -3667,7 +4181,7 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) errsts = resp_start_stop(SCpnt, devip); break; case ALLOW_MEDIUM_REMOVAL: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); if (errsts) break; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) @@ -3675,23 +4189,23 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) cmd[4] ? "inhibited" : "enabled"); break; case SEND_DIAGNOSTIC: /* mandatory */ - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case TEST_UNIT_READY: /* mandatory */ - delay_override = 1; - errsts = check_readiness(SCpnt, 0, devip); + /* delay_override = 1; */ + errsts = check_readiness(SCpnt, UAS_TUR, devip); break; case RESERVE: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case RESERVE_10: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case RELEASE: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case RELEASE_10: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case READ_CAPACITY: errsts = resp_readcap(SCpnt, devip); @@ -3702,20 +4216,20 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) else if (cmd[1] == SAI_GET_LBA_STATUS) { if (scsi_debug_lbp() == 0) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_COMMAND_OPCODE, 0); errsts = check_condition_result; } else errsts = resp_get_lba_status(SCpnt, devip); } else { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0); errsts = check_condition_result; } break; case MAINTENANCE_IN: if (MI_REPORT_TARGET_PGS != cmd[1]) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0); errsts = check_condition_result; break; @@ -3728,7 +4242,7 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) /* READ{10,12,16} and DIF Type 2 are natural enemies */ if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && cmd[1] & 0xe0) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_COMMAND_OPCODE, 0); errsts = check_condition_result; break; @@ -3742,7 +4256,7 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) /* fall through */ case READ_6: read: - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); if (errsts) break; if (scsi_debug_fake_rw) @@ -3752,20 +4266,21 @@ read: if (inj_short) num /= 2; - errsts = resp_read(SCpnt, lba, num, devip, ei_lba); + errsts = resp_read(SCpnt, lba, num, ei_lba); if (inj_recovered && (0 == errsts)) { - mk_sense_buffer(devip, RECOVERED_ERROR, + mk_sense_buffer(SCpnt, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); errsts = check_condition_result; } else if (inj_transport && (0 == errsts)) { - mk_sense_buffer(devip, ABORTED_COMMAND, + mk_sense_buffer(SCpnt, ABORTED_COMMAND, TRANSPORT_PROBLEM, ACK_NAK_TO); errsts = check_condition_result; } else if (inj_dif && (0 == errsts)) { - mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1); + /* Logical block guard check failed */ + mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1); errsts = illegal_condition_result; } else if (inj_dix && (0 == errsts)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1); + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1); errsts = illegal_condition_result; } break; @@ -3774,7 +4289,7 @@ read: errsts = resp_report_luns(SCpnt, devip); break; case VERIFY: /* 10 byte SBC-2 command */ - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); break; case WRITE_16: case WRITE_12: @@ -3782,7 +4297,7 @@ read: /* WRITE{10,12,16} and DIF Type 2 are natural enemies */ if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && cmd[1] & 0xe0) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_COMMAND_OPCODE, 0); errsts = check_condition_result; break; @@ -3796,22 +4311,22 @@ read: /* fall through */ case WRITE_6: write: - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); if (errsts) break; if (scsi_debug_fake_rw) break; get_data_transfer_info(cmd, &lba, &num, &ei_lba); - errsts = resp_write(SCpnt, lba, num, devip, ei_lba); + errsts = resp_write(SCpnt, lba, num, ei_lba); if (inj_recovered && (0 == errsts)) { - mk_sense_buffer(devip, RECOVERED_ERROR, + mk_sense_buffer(SCpnt, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); errsts = check_condition_result; } else if (inj_dif && (0 == errsts)) { - mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1); + mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1); errsts = illegal_condition_result; } else if (inj_dix && (0 == errsts)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1); + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1); errsts = illegal_condition_result; } break; @@ -3820,7 +4335,7 @@ write: if (cmd[1] & 0x8) { if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) || (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); errsts = check_condition_result; } else @@ -3828,19 +4343,23 @@ write: } if (errsts) break; - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); if (errsts) break; + if (scsi_debug_fake_rw) + break; get_data_transfer_info(cmd, &lba, &num, &ei_lba); - errsts = resp_write_same(SCpnt, lba, num, devip, ei_lba, unmap); + errsts = resp_write_same(SCpnt, lba, num, ei_lba, unmap); break; case UNMAP: - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); if (errsts) break; + if (scsi_debug_fake_rw) + break; if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_COMMAND_OPCODE, 0); errsts = check_condition_result; } else @@ -3861,29 +4380,29 @@ write: break; case SYNCHRONIZE_CACHE: delay_override = 1; - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); break; case WRITE_BUFFER: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case XDWRITEREAD_10: if (!scsi_bidi_cmnd(SCpnt)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); errsts = check_condition_result; break; } - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); if (errsts) break; if (scsi_debug_fake_rw) break; get_data_transfer_info(cmd, &lba, &num, &ei_lba); - errsts = resp_read(SCpnt, lba, num, devip, ei_lba); + errsts = resp_read(SCpnt, lba, num, ei_lba); if (errsts) break; - errsts = resp_write(SCpnt, lba, num, devip, ei_lba); + errsts = resp_write(SCpnt, lba, num, ei_lba); if (errsts) break; errsts = resp_xdwriteread(SCpnt, lba, num, devip); @@ -3906,27 +4425,138 @@ write: } } - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); errsts = check_condition_result; break; - + case 0x85: + if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, SCpnt->device, + "%s: ATA PASS-THROUGH(16) not supported\n", my_name); + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, + INVALID_OPCODE, 0); + errsts = check_condition_result; + break; default: if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " - "supported\n", *cmd); - errsts = check_readiness(SCpnt, 1, devip); + sdev_printk(KERN_INFO, SCpnt->device, + "%s: Opcode: 0x%x not supported\n", + my_name, *cmd); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); if (errsts) break; /* Unit attention takes precedence */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0); + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0); errsts = check_condition_result; break; } - return schedule_resp(SCpnt, devip, done, errsts, + return schedule_resp(SCpnt, devip, errsts, (delay_override ? 0 : scsi_debug_delay)); } -static DEF_SCSI_QCMD(scsi_debug_queuecommand) +static int +sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd) +{ + if (scsi_debug_host_lock) { + unsigned long iflags; + int rc; + + spin_lock_irqsave(shost->host_lock, iflags); + rc = scsi_debug_queuecommand(cmd); + spin_unlock_irqrestore(shost->host_lock, iflags); + return rc; + } else + return scsi_debug_queuecommand(cmd); +} + +static int +sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason) +{ + int num_in_q = 0; + int bad = 0; + unsigned long iflags; + struct sdebug_dev_info *devip; + + spin_lock_irqsave(&queued_arr_lock, iflags); + devip = (struct sdebug_dev_info *)sdev->hostdata; + if (NULL == devip) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + return -ENODEV; + } + num_in_q = atomic_read(&devip->num_in_q); + spin_unlock_irqrestore(&queued_arr_lock, iflags); + if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) { + if (qdepth < 1) + qdepth = 1; + /* allow to exceed max host queued_arr elements for testing */ + if (qdepth > SCSI_DEBUG_CANQUEUE + 10) + qdepth = SCSI_DEBUG_CANQUEUE + 10; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); + } else if (reason == SCSI_QDEPTH_QFULL) + scsi_track_queue_full(sdev, qdepth); + else + bad = 1; + if (bad) + sdev_printk(KERN_WARNING, sdev, + "%s: unknown reason=0x%x\n", __func__, reason); + if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { + if (SCSI_QDEPTH_QFULL == reason) + sdev_printk(KERN_INFO, sdev, + "%s: -> %d, num_in_q=%d, reason: queue full\n", + __func__, qdepth, num_in_q); + else { + const char *cp; + + switch (reason) { + case SCSI_QDEPTH_DEFAULT: + cp = "default (sysfs ?)"; + break; + case SCSI_QDEPTH_RAMP_UP: + cp = "ramp up"; + break; + default: + cp = "unknown"; + break; + } + sdev_printk(KERN_INFO, sdev, + "%s: qdepth=%d, num_in_q=%d, reason: %s\n", + __func__, qdepth, num_in_q, cp); + } + } + return sdev->queue_depth; +} + +static int +sdebug_change_qtype(struct scsi_device *sdev, int qtype) +{ + if (sdev->tagged_supported) { + scsi_set_tag_type(sdev, qtype); + if (qtype) + scsi_activate_tcq(sdev, sdev->queue_depth); + else + scsi_deactivate_tcq(sdev, sdev->queue_depth); + } else + qtype = 0; + if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { + const char *cp; + + switch (qtype) { + case 0: + cp = "untagged"; + break; + case MSG_SIMPLE_TAG: + cp = "simple tags"; + break; + case MSG_ORDERED_TAG: + cp = "ordered tags"; + break; + default: + cp = "unknown"; + break; + } + sdev_printk(KERN_INFO, sdev, "%s: to %s\n", __func__, cp); + } + return qtype; +} static struct scsi_host_template sdebug_driver_template = { .show_info = scsi_debug_show_info, @@ -3938,17 +4568,19 @@ static struct scsi_host_template sdebug_driver_template = { .slave_configure = scsi_debug_slave_configure, .slave_destroy = scsi_debug_slave_destroy, .ioctl = scsi_debug_ioctl, - .queuecommand = scsi_debug_queuecommand, + .queuecommand = sdebug_queuecommand_lock_or_not, + .change_queue_depth = sdebug_change_qdepth, + .change_queue_type = sdebug_change_qtype, .eh_abort_handler = scsi_debug_abort, - .eh_bus_reset_handler = scsi_debug_bus_reset, .eh_device_reset_handler = scsi_debug_device_reset, + .eh_target_reset_handler = scsi_debug_target_reset, + .eh_bus_reset_handler = scsi_debug_bus_reset, .eh_host_reset_handler = scsi_debug_host_reset, - .bios_param = scsi_debug_biosparam, .can_queue = SCSI_DEBUG_CANQUEUE, .this_id = 7, - .sg_tablesize = 256, - .cmd_per_lun = 16, - .max_sectors = 0xffff, + .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .cmd_per_lun = DEF_CMD_PER_LUN, + .max_sectors = -1U, .use_clustering = DISABLE_CLUSTERING, .module = THIS_MODULE, }; @@ -4032,8 +4664,7 @@ static int sdebug_driver_probe(struct device * dev) } else scsi_scan_host(hpnt); - - return error; + return error; } static int sdebug_driver_remove(struct device * dev) diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index f969aca..49014a1 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -222,6 +222,7 @@ static struct { {"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC}, {"Promise", "", NULL, BLIST_SPARSELUN}, {"QUANTUM", "XP34301", "1071", BLIST_NOTQ}, {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 7e95791..5db8454 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -59,11 +59,11 @@ static int scsi_try_to_abort_cmd(struct scsi_host_template *, /* called with shost->host_lock held */ void scsi_eh_wakeup(struct Scsi_Host *shost) { - if (shost->host_busy == shost->host_failed) { + if (atomic_read(&shost->host_busy) == shost->host_failed) { trace_scsi_eh_wakeup(shost); wake_up_process(shost->ehandler); - SCSI_LOG_ERROR_RECOVERY(5, - printk("Waking error handler thread\n")); + SCSI_LOG_ERROR_RECOVERY(5, shost_printk(KERN_INFO, shost, + "Waking error handler thread\n")); } } @@ -193,7 +193,7 @@ scsi_abort_command(struct scsi_cmnd *scmd) SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, "scmd %p previous abort failed\n", scmd)); - cancel_delayed_work(&scmd->abort_work); + BUG_ON(delayed_work_pending(&scmd->abort_work)); return FAILED; } @@ -319,8 +319,8 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev) online = scsi_device_online(sdev); - SCSI_LOG_ERROR_RECOVERY(5, printk("%s: rtn: %d\n", __func__, - online)); + SCSI_LOG_ERROR_RECOVERY(5, sdev_printk(KERN_INFO, sdev, + "%s: rtn: %d\n", __func__, online)); return online; } @@ -365,8 +365,9 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost, } } - SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d commands on %d" - " devices require eh work\n", + SCSI_LOG_ERROR_RECOVERY(2, shost_printk(KERN_INFO, shost, + "Total of %d commands on %d" + " devices require eh work\n", total_failures, devices_failed)); } #endif @@ -738,8 +739,8 @@ static void scsi_eh_done(struct scsi_cmnd *scmd) { struct completion *eh_action; - SCSI_LOG_ERROR_RECOVERY(3, - printk("%s scmd: %p result: %x\n", + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "%s scmd: %p result: %x\n", __func__, scmd, scmd->result)); eh_action = scmd->device->host->eh_action; @@ -758,8 +759,8 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd) struct Scsi_Host *host = scmd->device->host; struct scsi_host_template *hostt = host->hostt; - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n", - __func__)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, host, "Snd Host RST\n")); if (!hostt->eh_host_reset_handler) return FAILED; @@ -788,8 +789,8 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd) struct Scsi_Host *host = scmd->device->host; struct scsi_host_template *hostt = host->hostt; - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n", - __func__)); + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "%s: Snd Bus RST\n", __func__)); if (!hostt->eh_bus_reset_handler) return FAILED; @@ -1036,8 +1037,8 @@ retry: scsi_log_completion(scmd, rtn); - SCSI_LOG_ERROR_RECOVERY(3, - printk("%s: scmd: %p, timeleft: %ld\n", + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "%s: scmd: %p, timeleft: %ld\n", __func__, scmd, timeleft)); /* @@ -1051,9 +1052,8 @@ retry: */ if (timeleft) { rtn = scsi_eh_completed_normally(scmd); - SCSI_LOG_ERROR_RECOVERY(3, - printk("%s: scsi_eh_completed_normally %x\n", - __func__, rtn)); + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "%s: scsi_eh_completed_normally %x\n", __func__, rtn)); switch (rtn) { case SUCCESS: @@ -1177,9 +1177,9 @@ int scsi_eh_get_sense(struct list_head *work_q, if (rtn != SUCCESS) continue; - SCSI_LOG_ERROR_RECOVERY(3, printk("sense requested for %p" - " result %x\n", scmd, - scmd->result)); + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "sense requested for %p result %x\n", + scmd, scmd->result)); SCSI_LOG_ERROR_RECOVERY(3, scsi_print_sense("bh", scmd)); rtn = scsi_decide_disposition(scmd); @@ -1220,8 +1220,8 @@ retry_tur: rtn = scsi_send_eh_cmnd(scmd, tur_command, 6, scmd->device->eh_timeout, 0); - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n", - __func__, scmd, rtn)); + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "%s: scmd %p rtn %x\n", __func__, scmd, rtn)); switch (rtn) { case NEEDS_RETRY: @@ -1323,16 +1323,16 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, __func__)); return list_empty(work_q); } - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:" - "0x%p\n", current->comm, - scmd)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: aborting cmd: 0x%p\n", + current->comm, scmd)); rtn = scsi_try_to_abort_cmd(shost->hostt, scmd); if (rtn == FAILED) { - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting" - " cmd failed:" - "0x%p\n", - current->comm, - scmd)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: aborting cmd failed: 0x%p\n", + current->comm, scmd)); list_splice_init(&check_list, work_q); return list_empty(work_q); } @@ -1406,8 +1406,10 @@ static int scsi_eh_stu(struct Scsi_Host *shost, if (!stu_scmd) continue; - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending START_UNIT to sdev:" - " 0x%p\n", current->comm, sdev)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Sending START_UNIT to sdev: 0x%p\n", + current->comm, sdev)); if (!scsi_eh_try_stu(stu_scmd)) { if (!scsi_device_online(sdev) || @@ -1421,8 +1423,9 @@ static int scsi_eh_stu(struct Scsi_Host *shost, } } else { SCSI_LOG_ERROR_RECOVERY(3, - printk("%s: START_UNIT failed to sdev:" - " 0x%p\n", current->comm, sdev)); + shost_printk(KERN_INFO, shost, + "%s: START_UNIT failed to sdev:" + " 0x%p\n", current->comm, sdev)); } } @@ -1468,9 +1471,10 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, if (!bdr_scmd) continue; - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending BDR sdev:" - " 0x%p\n", current->comm, - sdev)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Sending BDR sdev: 0x%p\n", + current->comm, sdev)); rtn = scsi_try_bus_device_reset(bdr_scmd); if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { if (!scsi_device_online(sdev) || @@ -1485,11 +1489,10 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, } } } else { - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BDR" - " failed sdev:" - "0x%p\n", - current->comm, - sdev)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: BDR failed sdev: 0x%p\n", + current->comm, sdev)); } } @@ -1533,15 +1536,17 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry); id = scmd_id(scmd); - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset " - "to target %d\n", - current->comm, id)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Sending target reset to target %d\n", + current->comm, id)); rtn = scsi_try_target_reset(scmd); if (rtn != SUCCESS && rtn != FAST_IO_FAIL) - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset" - " failed target: " - "%d\n", - current->comm, id)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Target reset failed" + " target: %d\n", + current->comm, id)); list_for_each_entry_safe(scmd, next, &tmp_list, eh_entry) { if (scmd_id(scmd) != id) continue; @@ -1605,9 +1610,10 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, if (!chan_scmd) continue; - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending BRST chan:" - " %d\n", current->comm, - channel)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Sending BRST chan: %d\n", + current->comm, channel)); rtn = scsi_try_bus_reset(chan_scmd); if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { list_for_each_entry_safe(scmd, next, work_q, eh_entry) { @@ -1621,10 +1627,10 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, } } } else { - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BRST" - " failed chan: %d\n", - current->comm, - channel)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: BRST failed chan: %d\n", + current->comm, channel)); } } return scsi_eh_test_devices(&check_list, work_q, done_q, 0); @@ -1635,7 +1641,8 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, * @work_q: list_head for processed commands. * @done_q: list_head for processed commands. */ -static int scsi_eh_host_reset(struct list_head *work_q, +static int scsi_eh_host_reset(struct Scsi_Host *shost, + struct list_head *work_q, struct list_head *done_q) { struct scsi_cmnd *scmd, *next; @@ -1646,8 +1653,10 @@ static int scsi_eh_host_reset(struct list_head *work_q, scmd = list_entry(work_q->next, struct scsi_cmnd, eh_entry); - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending HRST\n" - , current->comm)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Sending HRST\n", + current->comm)); rtn = scsi_try_host_reset(scmd); if (rtn == SUCCESS) { @@ -1657,9 +1666,10 @@ static int scsi_eh_host_reset(struct list_head *work_q, scsi_eh_finish_cmd(scmd, done_q); } } else { - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: HRST" - " failed\n", - current->comm)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: HRST failed\n", + current->comm)); } } return scsi_eh_test_devices(&check_list, work_q, done_q, 1); @@ -1751,9 +1761,8 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) * up to the top level. */ if (!scsi_device_online(scmd->device)) { - SCSI_LOG_ERROR_RECOVERY(5, printk("%s: device offline - report" - " as SUCCESS\n", - __func__)); + SCSI_LOG_ERROR_RECOVERY(5, scmd_printk(KERN_INFO, scmd, + "%s: device offline - report as SUCCESS\n", __func__)); return SUCCESS; } @@ -1999,8 +2008,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost) * ioctls to queued block devices. */ SCSI_LOG_ERROR_RECOVERY(3, - printk("scsi_eh_%d waking up host to restart\n", - shost->host_no)); + shost_printk(KERN_INFO, shost, "waking up host to restart\n")); spin_lock_irqsave(shost->host_lock, flags); if (scsi_host_set_state(shost, SHOST_RUNNING)) @@ -2047,7 +2055,7 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost, if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) if (!scsi_eh_target_reset(shost, work_q, done_q)) if (!scsi_eh_bus_reset(shost, work_q, done_q)) - if (!scsi_eh_host_reset(work_q, done_q)) + if (!scsi_eh_host_reset(shost, work_q, done_q)) scsi_eh_offline_sdevs(work_q, done_q); } @@ -2066,10 +2074,10 @@ void scsi_eh_flush_done_q(struct list_head *done_q) if (scsi_device_online(scmd->device) && !scsi_noretry_cmd(scmd) && (++scmd->retries <= scmd->allowed)) { - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush" - " retry cmd: %p\n", - current->comm, - scmd)); + SCSI_LOG_ERROR_RECOVERY(3, + scmd_printk(KERN_INFO, scmd, + "%s: flush retry cmd: %p\n", + current->comm, scmd)); scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY); } else { /* @@ -2079,9 +2087,10 @@ void scsi_eh_flush_done_q(struct list_head *done_q) */ if (!scmd->result) scmd->result |= (DRIVER_TIMEOUT << 24); - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush finish" - " cmd: %p\n", - current->comm, scmd)); + SCSI_LOG_ERROR_RECOVERY(3, + scmd_printk(KERN_INFO, scmd, + "%s: flush finish cmd: %p\n", + current->comm, scmd)); scsi_finish_command(scmd); } } @@ -2155,19 +2164,22 @@ int scsi_error_handler(void *data) while (!kthread_should_stop()) { set_current_state(TASK_INTERRUPTIBLE); if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || - shost->host_failed != shost->host_busy) { + shost->host_failed != atomic_read(&shost->host_busy)) { SCSI_LOG_ERROR_RECOVERY(1, - printk("scsi_eh_%d: sleeping\n", - shost->host_no)); + shost_printk(KERN_INFO, shost, + "scsi_eh_%d: sleeping\n", + shost->host_no)); schedule(); continue; } __set_current_state(TASK_RUNNING); SCSI_LOG_ERROR_RECOVERY(1, - printk("scsi_eh_%d: waking up %d/%d/%d\n", - shost->host_no, shost->host_eh_scheduled, - shost->host_failed, shost->host_busy)); + shost_printk(KERN_INFO, shost, + "scsi_eh_%d: waking up %d/%d/%d\n", + shost->host_no, shost->host_eh_scheduled, + shost->host_failed, + atomic_read(&shost->host_busy))); /* * We have a host that is failing for some reason. Figure out @@ -2201,7 +2213,9 @@ int scsi_error_handler(void *data) __set_current_state(TASK_RUNNING); SCSI_LOG_ERROR_RECOVERY(1, - printk("Error handler scsi_eh_%d exiting\n", shost->host_no)); + shost_printk(KERN_INFO, shost, + "Error handler scsi_eh_%d exiting\n", + shost->host_no)); shost->ehandler = NULL; return 0; } @@ -2362,8 +2376,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag) * suspended while we performed the TMF. */ SCSI_LOG_ERROR_RECOVERY(3, - printk("%s: waking up host to restart after TMF\n", - __func__)); + shost_printk(KERN_INFO, shost, + "waking up host to restart after TMF\n")); wake_up(&shost->host_wait); diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index d9564fb..1aaaf43 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -91,12 +91,14 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, int result; struct scsi_sense_hdr sshdr; - SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); + SCSI_LOG_IOCTL(1, sdev_printk(KERN_INFO, sdev, + "Trying ioctl with scsi command %d\n", *cmd)); result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr, timeout, retries, NULL); - SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result)); + SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, + "Ioctl returned 0x%x\n", result)); if ((driver_byte(result) & DRIVER_SENSE) && (scsi_sense_valid(&sshdr))) { @@ -105,9 +107,11 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, if (cmd[0] == ALLOW_MEDIUM_REMOVAL) sdev->lockable = 0; else - printk(KERN_INFO "ioctl_internal_command: " - "ILLEGAL REQUEST asc=0x%x ascq=0x%x\n", - sshdr.asc, sshdr.ascq); + sdev_printk(KERN_INFO, sdev, + "ioctl_internal_command: " + "ILLEGAL REQUEST " + "asc=0x%x ascq=0x%x\n", + sshdr.asc, sshdr.ascq); break; case NOT_READY: /* This happens if there is no disc in drive */ if (sdev->removable) @@ -127,7 +131,8 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, } } - SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); + SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, + "IOCTL Releasing command\n")); return result; } diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 3f50dfc..9c44392 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1,5 +1,6 @@ /* - * scsi_lib.c Copyright (C) 1999 Eric Youngdale + * Copyright (C) 1999 Eric Youngdale + * Copyright (C) 2014 Christoph Hellwig * * SCSI queueing library. * Initial versions: Eric Youngdale (eric@andante.org). @@ -20,6 +21,7 @@ #include <linux/delay.h> #include <linux/hardirq.h> #include <linux/scatterlist.h> +#include <linux/blk-mq.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -29,6 +31,8 @@ #include <scsi/scsi_eh.h> #include <scsi/scsi_host.h> +#include <trace/events/scsi.h> + #include "scsi_priv.h" #include "scsi_logging.h" @@ -75,28 +79,12 @@ struct kmem_cache *scsi_sdb_cache; */ #define SCSI_QUEUE_DELAY 3 -/** - * __scsi_queue_insert - private queue insertion - * @cmd: The SCSI command being requeued - * @reason: The reason for the requeue - * @unbusy: Whether the queue should be unbusied - * - * This is a private queue insertion. The public interface - * scsi_queue_insert() always assumes the queue should be unbusied - * because it's always called before the completion. This function is - * for a requeue after completion, which should only occur in this - * file. - */ -static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) +static void +scsi_set_blocked(struct scsi_cmnd *cmd, int reason) { struct Scsi_Host *host = cmd->device->host; struct scsi_device *device = cmd->device; struct scsi_target *starget = scsi_target(device); - struct request_queue *q = device->request_queue; - unsigned long flags; - - SCSI_LOG_MLQUEUE(1, - printk("Inserting command %p into mlqueue\n", cmd)); /* * Set the appropriate busy bit for the device/host. @@ -113,16 +101,52 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) */ switch (reason) { case SCSI_MLQUEUE_HOST_BUSY: - host->host_blocked = host->max_host_blocked; + atomic_set(&host->host_blocked, host->max_host_blocked); break; case SCSI_MLQUEUE_DEVICE_BUSY: case SCSI_MLQUEUE_EH_RETRY: - device->device_blocked = device->max_device_blocked; + atomic_set(&device->device_blocked, + device->max_device_blocked); break; case SCSI_MLQUEUE_TARGET_BUSY: - starget->target_blocked = starget->max_target_blocked; + atomic_set(&starget->target_blocked, + starget->max_target_blocked); break; } +} + +static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd) +{ + struct scsi_device *sdev = cmd->device; + struct request_queue *q = cmd->request->q; + + blk_mq_requeue_request(cmd->request); + blk_mq_kick_requeue_list(q); + put_device(&sdev->sdev_gendev); +} + +/** + * __scsi_queue_insert - private queue insertion + * @cmd: The SCSI command being requeued + * @reason: The reason for the requeue + * @unbusy: Whether the queue should be unbusied + * + * This is a private queue insertion. The public interface + * scsi_queue_insert() always assumes the queue should be unbusied + * because it's always called before the completion. This function is + * for a requeue after completion, which should only occur in this + * file. + */ +static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) +{ + struct scsi_device *device = cmd->device; + struct request_queue *q = device->request_queue; + unsigned long flags; + + SCSI_LOG_MLQUEUE(1, scmd_printk(KERN_INFO, cmd, + "Inserting command %p into mlqueue\n", cmd)); + + scsi_set_blocked(cmd, reason); /* * Decrement the counters, since these commands are no longer @@ -138,6 +162,10 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) * before blk_cleanup_queue() finishes. */ cmd->result = 0; + if (q->mq_ops) { + scsi_mq_requeue_cmd(cmd); + return; + } spin_lock_irqsave(q->queue_lock, flags); blk_requeue_request(q, cmd->request); kblockd_schedule_work(&device->requeue_work); @@ -282,16 +310,26 @@ void scsi_device_unbusy(struct scsi_device *sdev) struct scsi_target *starget = scsi_target(sdev); unsigned long flags; - spin_lock_irqsave(shost->host_lock, flags); - shost->host_busy--; - starget->target_busy--; + atomic_dec(&shost->host_busy); + if (starget->can_queue > 0) + atomic_dec(&starget->target_busy); + if (unlikely(scsi_host_in_recovery(shost) && - (shost->host_failed || shost->host_eh_scheduled))) + (shost->host_failed || shost->host_eh_scheduled))) { + spin_lock_irqsave(shost->host_lock, flags); scsi_eh_wakeup(shost); - spin_unlock(shost->host_lock); - spin_lock(sdev->request_queue->queue_lock); - sdev->device_busy--; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); + spin_unlock_irqrestore(shost->host_lock, flags); + } + + atomic_dec(&sdev->device_busy); +} + +static void scsi_kick_queue(struct request_queue *q) +{ + if (q->mq_ops) + blk_mq_start_hw_queues(q); + else + blk_run_queue(q); } /* @@ -318,7 +356,7 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) * but in most cases, we will be first. Ideally, each LU on the * target would get some limited time or requests on the target. */ - blk_run_queue(current_sdev->request_queue); + scsi_kick_queue(current_sdev->request_queue); spin_lock_irqsave(shost->host_lock, flags); if (starget->starget_sdev_user) @@ -331,7 +369,7 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) continue; spin_unlock_irqrestore(shost->host_lock, flags); - blk_run_queue(sdev->request_queue); + scsi_kick_queue(sdev->request_queue); spin_lock_irqsave(shost->host_lock, flags); scsi_device_put(sdev); @@ -340,28 +378,36 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) spin_unlock_irqrestore(shost->host_lock, flags); } -static inline int scsi_device_is_busy(struct scsi_device *sdev) +static inline bool scsi_device_is_busy(struct scsi_device *sdev) { - if (sdev->device_busy >= sdev->queue_depth || sdev->device_blocked) - return 1; - - return 0; + if (atomic_read(&sdev->device_busy) >= sdev->queue_depth) + return true; + if (atomic_read(&sdev->device_blocked) > 0) + return true; + return false; } -static inline int scsi_target_is_busy(struct scsi_target *starget) +static inline bool scsi_target_is_busy(struct scsi_target *starget) { - return ((starget->can_queue > 0 && - starget->target_busy >= starget->can_queue) || - starget->target_blocked); + if (starget->can_queue > 0) { + if (atomic_read(&starget->target_busy) >= starget->can_queue) + return true; + if (atomic_read(&starget->target_blocked) > 0) + return true; + } + return false; } -static inline int scsi_host_is_busy(struct Scsi_Host *shost) +static inline bool scsi_host_is_busy(struct Scsi_Host *shost) { - if ((shost->can_queue > 0 && shost->host_busy >= shost->can_queue) || - shost->host_blocked || shost->host_self_blocked) - return 1; - - return 0; + if (shost->can_queue > 0 && + atomic_read(&shost->host_busy) >= shost->can_queue) + return true; + if (atomic_read(&shost->host_blocked) > 0) + return true; + if (shost->host_self_blocked) + return true; + return false; } static void scsi_starved_list_run(struct Scsi_Host *shost) @@ -413,7 +459,7 @@ static void scsi_starved_list_run(struct Scsi_Host *shost) continue; spin_unlock_irqrestore(shost->host_lock, flags); - blk_run_queue(slq); + scsi_kick_queue(slq); blk_put_queue(slq); spin_lock_irqsave(shost->host_lock, flags); @@ -444,7 +490,10 @@ static void scsi_run_queue(struct request_queue *q) if (!list_empty(&sdev->host->starved_list)) scsi_starved_list_run(sdev->host); - blk_run_queue(q); + if (q->mq_ops) + blk_mq_start_stopped_hw_queues(q, false); + else + blk_run_queue(q); } void scsi_requeue_run_queue(struct work_struct *work) @@ -542,25 +591,70 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) return mempool_alloc(sgp->pool, gfp_mask); } +static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq) +{ + if (mq && sdb->table.nents <= SCSI_MAX_SG_SEGMENTS) + return; + __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); +} + static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, - gfp_t gfp_mask) + gfp_t gfp_mask, bool mq) { + struct scatterlist *first_chunk = NULL; int ret; BUG_ON(!nents); + if (mq) { + if (nents <= SCSI_MAX_SG_SEGMENTS) { + sdb->table.nents = nents; + sg_init_table(sdb->table.sgl, sdb->table.nents); + return 0; + } + first_chunk = sdb->table.sgl; + } + ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS, - gfp_mask, scsi_sg_alloc); + first_chunk, gfp_mask, scsi_sg_alloc); if (unlikely(ret)) - __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, - scsi_sg_free); - + scsi_free_sgtable(sdb, mq); return ret; } -static void scsi_free_sgtable(struct scsi_data_buffer *sdb) +static void scsi_uninit_cmd(struct scsi_cmnd *cmd) +{ + if (cmd->request->cmd_type == REQ_TYPE_FS) { + struct scsi_driver *drv = scsi_cmd_to_driver(cmd); + + if (drv->uninit_command) + drv->uninit_command(cmd); + } +} + +static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) { - __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free); + if (cmd->sdb.table.nents) + scsi_free_sgtable(&cmd->sdb, true); + if (cmd->request->next_rq && cmd->request->next_rq->special) + scsi_free_sgtable(cmd->request->next_rq->special, true); + if (scsi_prot_sg_count(cmd)) + scsi_free_sgtable(cmd->prot_sdb, true); +} + +static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) +{ + struct scsi_device *sdev = cmd->device; + unsigned long flags; + + BUG_ON(list_empty(&cmd->list)); + + scsi_mq_free_sgtables(cmd); + scsi_uninit_cmd(cmd); + + spin_lock_irqsave(&sdev->list_lock, flags); + list_del_init(&cmd->list); + spin_unlock_irqrestore(&sdev->list_lock, flags); } /* @@ -579,27 +673,79 @@ static void scsi_free_sgtable(struct scsi_data_buffer *sdb) * the __init_io() function. Primarily this would involve * the scatter-gather table. */ -void scsi_release_buffers(struct scsi_cmnd *cmd) +static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb); + scsi_free_sgtable(&cmd->sdb, false); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(cmd->prot_sdb); + scsi_free_sgtable(cmd->prot_sdb, false); } -EXPORT_SYMBOL(scsi_release_buffers); static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd) { struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; - scsi_free_sgtable(bidi_sdb); + scsi_free_sgtable(bidi_sdb, false); kmem_cache_free(scsi_sdb_cache, bidi_sdb); cmd->request->next_rq->special = NULL; } +static bool scsi_end_request(struct request *req, int error, + unsigned int bytes, unsigned int bidi_bytes) +{ + struct scsi_cmnd *cmd = req->special; + struct scsi_device *sdev = cmd->device; + struct request_queue *q = sdev->request_queue; + + if (blk_update_request(req, error, bytes)) + return true; + + /* Bidi request must be completed as a whole */ + if (unlikely(bidi_bytes) && + blk_update_request(req->next_rq, error, bidi_bytes)) + return true; + + if (blk_queue_add_random(q)) + add_disk_randomness(req->rq_disk); + + if (req->mq_ctx) { + /* + * In the MQ case the command gets freed by __blk_mq_end_io, + * so we have to do all cleanup that depends on it earlier. + * + * We also can't kick the queues from irq context, so we + * will have to defer it to a workqueue. + */ + scsi_mq_uninit_cmd(cmd); + + __blk_mq_end_io(req, error); + + if (scsi_target(sdev)->single_lun || + !list_empty(&sdev->host->starved_list)) + kblockd_schedule_work(&sdev->requeue_work); + else + blk_mq_start_stopped_hw_queues(q, true); + + put_device(&sdev->sdev_gendev); + } else { + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + blk_finish_request(req, error); + spin_unlock_irqrestore(q->queue_lock, flags); + + if (bidi_bytes) + scsi_release_bidi_buffers(cmd); + scsi_release_buffers(cmd); + scsi_next_command(cmd); + } + + return false; +} + /** * __scsi_error_from_host_byte - translate SCSI error code into errno * @cmd: SCSI command (unused) @@ -672,7 +818,7 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result) * be put back on the queue and retried using the same * command as before, possibly after a delay. * - * c) We can call blk_end_request() with -EIO to fail + * c) We can call scsi_end_request() with -EIO to fail * the remainder of the request. */ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) @@ -686,7 +832,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) int sense_deferred = 0; enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY, ACTION_DELAYED_RETRY} action; - char *description = NULL; unsigned long wait_for = (cmd->allowed + 1) * req->timeout; if (result) { @@ -724,13 +869,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) * both sides at once. */ req->next_rq->resid_len = scsi_in(cmd)->resid; - - scsi_release_buffers(cmd); - scsi_release_bidi_buffers(cmd); - - blk_end_request_all(req, 0); - - scsi_next_command(cmd); + if (scsi_end_request(req, 0, blk_rq_bytes(req), + blk_rq_bytes(req->next_rq))) + BUG(); return; } } else if (blk_rq_bytes(req) == 0 && result && !sense_deferred) { @@ -750,9 +891,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) * Next deal with any sectors which we were able to correctly * handle. */ - SCSI_LOG_HLCOMPLETE(1, printk("%u sectors total, " - "%d bytes done.\n", - blk_rq_sectors(req), good_bytes)); + SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, cmd, + "%u sectors total, %d bytes done.\n", + blk_rq_sectors(req), good_bytes)); /* * Recovered errors need reporting, but they're always treated @@ -777,15 +918,16 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) /* * If we finished all bytes in the request we are done now. */ - if (!blk_end_request(req, error, good_bytes)) - goto next_command; + if (!scsi_end_request(req, error, good_bytes, 0)) + return; /* * Kill remainder if no retrys. */ if (error && scsi_noretry_cmd(cmd)) { - blk_end_request_all(req, error); - goto next_command; + if (scsi_end_request(req, error, blk_rq_bytes(req), 0)) + BUG(); + return; } /* @@ -811,7 +953,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) * and quietly refuse further access. */ cmd->device->changed = 1; - description = "Media Changed"; action = ACTION_FAIL; } else { /* Must have been a power glitch, or a @@ -839,27 +980,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) cmd->device->use_10_for_rw = 0; action = ACTION_REPREP; } else if (sshdr.asc == 0x10) /* DIX */ { - description = "Host Data Integrity Failure"; action = ACTION_FAIL; error = -EILSEQ; /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */ } else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) { - switch (cmd->cmnd[0]) { - case UNMAP: - description = "Discard failure"; - break; - case WRITE_SAME: - case WRITE_SAME_16: - if (cmd->cmnd[1] & 0x8) - description = "Discard failure"; - else - description = - "Write same failure"; - break; - default: - description = "Invalid command failure"; - break; - } action = ACTION_FAIL; error = -EREMOTEIO; } else @@ -867,10 +991,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) break; case ABORTED_COMMAND: action = ACTION_FAIL; - if (sshdr.asc == 0x10) { /* DIF */ - description = "Target Data Integrity Failure"; + if (sshdr.asc == 0x10) /* DIF */ error = -EILSEQ; - } break; case NOT_READY: /* If the device is in the process of becoming @@ -889,57 +1011,52 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) action = ACTION_DELAYED_RETRY; break; default: - description = "Device not ready"; action = ACTION_FAIL; break; } - } else { - description = "Device not ready"; + } else action = ACTION_FAIL; - } break; case VOLUME_OVERFLOW: /* See SSC3rXX or current. */ action = ACTION_FAIL; break; default: - description = "Unhandled sense code"; action = ACTION_FAIL; break; } - } else { - description = "Unhandled error code"; + } else action = ACTION_FAIL; - } if (action != ACTION_FAIL && - time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { + time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) action = ACTION_FAIL; - description = "Command timed out"; - } switch (action) { case ACTION_FAIL: /* Give up and fail the remainder of the request */ if (!(req->cmd_flags & REQ_QUIET)) { - if (description) - scmd_printk(KERN_INFO, cmd, "%s\n", - description); scsi_print_result(cmd); if (driver_byte(result) & DRIVER_SENSE) scsi_print_sense("", cmd); scsi_print_command(cmd); } - if (!blk_end_request_err(req, error)) - goto next_command; + if (!scsi_end_request(req, error, blk_rq_err_bytes(req), 0)) + return; /*FALLTHRU*/ case ACTION_REPREP: requeue: /* Unprep the request and put it back at the head of the queue. * A new command will be prepared and issued. */ - scsi_release_buffers(cmd); - scsi_requeue_command(q, cmd); + if (q->mq_ops) { + cmd->request->cmd_flags &= ~REQ_DONTPREP; + scsi_mq_uninit_cmd(cmd); + scsi_mq_requeue_cmd(cmd); + } else { + scsi_release_buffers(cmd); + scsi_requeue_command(q, cmd); + } break; case ACTION_RETRY: /* Retry the same command immediately */ @@ -950,11 +1067,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) __scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY, 0); break; } - return; - -next_command: - scsi_release_buffers(cmd); - scsi_next_command(cmd); } static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb, @@ -966,9 +1078,8 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb, * If sg table allocation fails, requeue request later. */ if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments, - gfp_mask))) { + gfp_mask, req->mq_ctx != NULL))) return BLKPREP_DEFER; - } /* * Next, walk the list, and fill in the addresses and sizes of @@ -996,21 +1107,29 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) { struct scsi_device *sdev = cmd->device; struct request *rq = cmd->request; + bool is_mq = (rq->mq_ctx != NULL); + int error; + + BUG_ON(!rq->nr_phys_segments); - int error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask); + error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask); if (error) goto err_exit; if (blk_bidi_rq(rq)) { - struct scsi_data_buffer *bidi_sdb = kmem_cache_zalloc( - scsi_sdb_cache, GFP_ATOMIC); - if (!bidi_sdb) { - error = BLKPREP_DEFER; - goto err_exit; + if (!rq->q->mq_ops) { + struct scsi_data_buffer *bidi_sdb = + kmem_cache_zalloc(scsi_sdb_cache, GFP_ATOMIC); + if (!bidi_sdb) { + error = BLKPREP_DEFER; + goto err_exit; + } + + rq->next_rq->special = bidi_sdb; } - rq->next_rq->special = bidi_sdb; - error = scsi_init_sgtable(rq->next_rq, bidi_sdb, GFP_ATOMIC); + error = scsi_init_sgtable(rq->next_rq, rq->next_rq->special, + GFP_ATOMIC); if (error) goto err_exit; } @@ -1022,7 +1141,7 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) BUG_ON(prot_sdb == NULL); ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask)) { + if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask, is_mq)) { error = BLKPREP_DEFER; goto err_exit; } @@ -1036,13 +1155,16 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) cmd->prot_sdb->table.nents = count; } - return BLKPREP_OK ; - + return BLKPREP_OK; err_exit: - scsi_release_buffers(cmd); - cmd->request->special = NULL; - scsi_put_command(cmd); - put_device(&sdev->sdev_gendev); + if (is_mq) { + scsi_mq_free_sgtables(cmd); + } else { + scsi_release_buffers(cmd); + cmd->request->special = NULL; + scsi_put_command(cmd); + put_device(&sdev->sdev_gendev); + } return error; } EXPORT_SYMBOL(scsi_init_io); @@ -1077,7 +1199,7 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, return cmd; } -int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) +static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd = req->special; @@ -1088,11 +1210,7 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) * submit a request without an attached bio. */ if (req->bio) { - int ret; - - BUG_ON(!req->nr_phys_segments); - - ret = scsi_init_io(cmd, GFP_ATOMIC); + int ret = scsi_init_io(cmd, GFP_ATOMIC); if (unlikely(ret)) return ret; } else { @@ -1102,25 +1220,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) } cmd->cmd_len = req->cmd_len; - if (!blk_rq_bytes(req)) - cmd->sc_data_direction = DMA_NONE; - else if (rq_data_dir(req) == WRITE) - cmd->sc_data_direction = DMA_TO_DEVICE; - else - cmd->sc_data_direction = DMA_FROM_DEVICE; - cmd->transfersize = blk_rq_bytes(req); cmd->allowed = req->retries; return BLKPREP_OK; } -EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd); /* - * Setup a REQ_TYPE_FS command. These are simple read/write request - * from filesystems that still need to be translated to SCSI CDBs from - * the ULD. + * Setup a REQ_TYPE_FS command. These are simple request from filesystems + * that still need to be translated to SCSI CDBs from the ULD. */ -int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) +static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd = req->special; @@ -1131,15 +1240,30 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) return ret; } - /* - * Filesystem requests must transfer data. - */ - BUG_ON(!req->nr_phys_segments); - memset(cmd->cmnd, 0, BLK_MAX_CDB); - return scsi_init_io(cmd, GFP_ATOMIC); + return scsi_cmd_to_driver(cmd)->init_command(cmd); +} + +static int scsi_setup_cmnd(struct scsi_device *sdev, struct request *req) +{ + struct scsi_cmnd *cmd = req->special; + + if (!blk_rq_bytes(req)) + cmd->sc_data_direction = DMA_NONE; + else if (rq_data_dir(req) == WRITE) + cmd->sc_data_direction = DMA_TO_DEVICE; + else + cmd->sc_data_direction = DMA_FROM_DEVICE; + + switch (req->cmd_type) { + case REQ_TYPE_FS: + return scsi_setup_fs_cmnd(sdev, req); + case REQ_TYPE_BLOCK_PC: + return scsi_setup_blk_pc_cmnd(sdev, req); + default: + return BLKPREP_KILL; + } } -EXPORT_SYMBOL(scsi_setup_fs_cmnd); static int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) @@ -1218,7 +1342,7 @@ scsi_prep_return(struct request_queue *q, struct request *req, int ret) * queue must be restarted, so we schedule a callback to happen * shortly. */ - if (sdev->device_busy == 0) + if (atomic_read(&sdev->device_busy) == 0) blk_delay_queue(q, SCSI_QUEUE_DELAY); break; default: @@ -1244,26 +1368,14 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) goto out; } - if (req->cmd_type == REQ_TYPE_FS) - ret = scsi_cmd_to_driver(cmd)->init_command(cmd); - else if (req->cmd_type == REQ_TYPE_BLOCK_PC) - ret = scsi_setup_blk_pc_cmnd(sdev, req); - else - ret = BLKPREP_KILL; - + ret = scsi_setup_cmnd(sdev, req); out: return scsi_prep_return(q, req, ret); } static void scsi_unprep_fn(struct request_queue *q, struct request *req) { - if (req->cmd_type == REQ_TYPE_FS) { - struct scsi_cmnd *cmd = req->special; - struct scsi_driver *drv = scsi_cmd_to_driver(cmd); - - if (drv->uninit_command) - drv->uninit_command(cmd); - } + scsi_uninit_cmd(req->special); } /* @@ -1275,99 +1387,144 @@ static void scsi_unprep_fn(struct request_queue *q, struct request *req) static inline int scsi_dev_queue_ready(struct request_queue *q, struct scsi_device *sdev) { - if (sdev->device_busy == 0 && sdev->device_blocked) { + unsigned int busy; + + busy = atomic_inc_return(&sdev->device_busy) - 1; + if (atomic_read(&sdev->device_blocked)) { + if (busy) + goto out_dec; + /* * unblock after device_blocked iterates to zero */ - if (--sdev->device_blocked == 0) { - SCSI_LOG_MLQUEUE(3, - sdev_printk(KERN_INFO, sdev, - "unblocking device at zero depth\n")); - } else { - blk_delay_queue(q, SCSI_QUEUE_DELAY); - return 0; + if (atomic_dec_return(&sdev->device_blocked) > 0) { + /* + * For the MQ case we take care of this in the caller. + */ + if (!q->mq_ops) + blk_delay_queue(q, SCSI_QUEUE_DELAY); + goto out_dec; } + SCSI_LOG_MLQUEUE(3, sdev_printk(KERN_INFO, sdev, + "unblocking device at zero depth\n")); } - if (scsi_device_is_busy(sdev)) - return 0; + + if (busy >= sdev->queue_depth) + goto out_dec; return 1; +out_dec: + atomic_dec(&sdev->device_busy); + return 0; } - /* * scsi_target_queue_ready: checks if there we can send commands to target * @sdev: scsi device on starget to check. - * - * Called with the host lock held. */ static inline int scsi_target_queue_ready(struct Scsi_Host *shost, struct scsi_device *sdev) { struct scsi_target *starget = scsi_target(sdev); + unsigned int busy; if (starget->single_lun) { + spin_lock_irq(shost->host_lock); if (starget->starget_sdev_user && - starget->starget_sdev_user != sdev) + starget->starget_sdev_user != sdev) { + spin_unlock_irq(shost->host_lock); return 0; + } starget->starget_sdev_user = sdev; + spin_unlock_irq(shost->host_lock); } - if (starget->target_busy == 0 && starget->target_blocked) { + if (starget->can_queue <= 0) + return 1; + + busy = atomic_inc_return(&starget->target_busy) - 1; + if (atomic_read(&starget->target_blocked) > 0) { + if (busy) + goto starved; + /* * unblock after target_blocked iterates to zero */ - if (--starget->target_blocked == 0) { - SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget, - "unblocking target at zero depth\n")); - } else - return 0; - } + if (atomic_dec_return(&starget->target_blocked) > 0) + goto out_dec; - if (scsi_target_is_busy(starget)) { - list_move_tail(&sdev->starved_entry, &shost->starved_list); - return 0; + SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget, + "unblocking target at zero depth\n")); } + if (busy >= starget->can_queue) + goto starved; + return 1; + +starved: + spin_lock_irq(shost->host_lock); + list_move_tail(&sdev->starved_entry, &shost->starved_list); + spin_unlock_irq(shost->host_lock); +out_dec: + if (starget->can_queue > 0) + atomic_dec(&starget->target_busy); + return 0; } /* * scsi_host_queue_ready: if we can send requests to shost, return 1 else * return 0. We must end up running the queue again whenever 0 is * returned, else IO can hang. - * - * Called with host_lock held. */ static inline int scsi_host_queue_ready(struct request_queue *q, struct Scsi_Host *shost, struct scsi_device *sdev) { + unsigned int busy; + if (scsi_host_in_recovery(shost)) return 0; - if (shost->host_busy == 0 && shost->host_blocked) { + + busy = atomic_inc_return(&shost->host_busy) - 1; + if (atomic_read(&shost->host_blocked) > 0) { + if (busy) + goto starved; + /* * unblock after host_blocked iterates to zero */ - if (--shost->host_blocked == 0) { - SCSI_LOG_MLQUEUE(3, - printk("scsi%d unblocking host at zero depth\n", - shost->host_no)); - } else { - return 0; - } - } - if (scsi_host_is_busy(shost)) { - if (list_empty(&sdev->starved_entry)) - list_add_tail(&sdev->starved_entry, &shost->starved_list); - return 0; + if (atomic_dec_return(&shost->host_blocked) > 0) + goto out_dec; + + SCSI_LOG_MLQUEUE(3, + shost_printk(KERN_INFO, shost, + "unblocking host at zero depth\n")); } + if (shost->can_queue > 0 && busy >= shost->can_queue) + goto starved; + if (shost->host_self_blocked) + goto starved; + /* We're OK to process the command, so we can't be starved */ - if (!list_empty(&sdev->starved_entry)) - list_del_init(&sdev->starved_entry); + if (!list_empty(&sdev->starved_entry)) { + spin_lock_irq(shost->host_lock); + if (!list_empty(&sdev->starved_entry)) + list_del_init(&sdev->starved_entry); + spin_unlock_irq(shost->host_lock); + } return 1; + +starved: + spin_lock_irq(shost->host_lock); + if (list_empty(&sdev->starved_entry)) + list_add_tail(&sdev->starved_entry, &shost->starved_list); + spin_unlock_irq(shost->host_lock); +out_dec: + atomic_dec(&shost->host_busy); + return 0; } /* @@ -1430,13 +1587,10 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) * bump busy counts. To bump the counters, we need to dance * with the locks as normal issue path does. */ - sdev->device_busy++; - spin_unlock(sdev->request_queue->queue_lock); - spin_lock(shost->host_lock); - shost->host_busy++; - starget->target_busy++; - spin_unlock(shost->host_lock); - spin_lock(sdev->request_queue->queue_lock); + atomic_inc(&sdev->device_busy); + atomic_inc(&shost->host_busy); + if (starget->can_queue > 0) + atomic_inc(&starget->target_busy); blk_complete_request(req); } @@ -1461,7 +1615,7 @@ static void scsi_softirq_done(struct request *rq) wait_for/HZ); disposition = SUCCESS; } - + scsi_log_completion(cmd, disposition); switch (disposition) { @@ -1480,6 +1634,23 @@ static void scsi_softirq_done(struct request *rq) } } +/** + * scsi_done - Invoke completion on finished SCSI command. + * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives + * ownership back to SCSI Core -- i.e. the LLDD has finished with it. + * + * Description: This function is the mid-level's (SCSI Core) interrupt routine, + * which regains ownership of the SCSI command (de facto) from a LLDD, and + * calls blk_complete_request() for further processing. + * + * This function is interrupt context safe. + */ +static void scsi_done(struct scsi_cmnd *cmd) +{ + trace_scsi_dispatch_cmd_done(cmd); + blk_complete_request(cmd->request); +} + /* * Function: scsi_request_fn() * @@ -1509,11 +1680,11 @@ static void scsi_request_fn(struct request_queue *q) int rtn; /* * get next queueable request. We do this early to make sure - * that the request is fully prepared even if we cannot + * that the request is fully prepared even if we cannot * accept it. */ req = blk_peek_request(q); - if (!req || !scsi_dev_queue_ready(q, sdev)) + if (!req) break; if (unlikely(!scsi_device_online(sdev))) { @@ -1523,15 +1694,16 @@ static void scsi_request_fn(struct request_queue *q) continue; } + if (!scsi_dev_queue_ready(q, sdev)) + break; /* * Remove the request from the request list. */ if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req))) blk_start_request(req); - sdev->device_busy++; - spin_unlock(q->queue_lock); + spin_unlock_irq(q->queue_lock); cmd = req->special; if (unlikely(cmd == NULL)) { printk(KERN_CRIT "impossible request in %s.\n" @@ -1541,7 +1713,6 @@ static void scsi_request_fn(struct request_queue *q) blk_dump_rq_flags(req, "foo"); BUG(); } - spin_lock(shost->host_lock); /* * We hit this when the driver is using a host wide @@ -1552,9 +1723,11 @@ static void scsi_request_fn(struct request_queue *q) * a run when a tag is freed. */ if (blk_queue_tagged(q) && !blk_rq_tagged(req)) { + spin_lock_irq(shost->host_lock); if (list_empty(&sdev->starved_entry)) list_add_tail(&sdev->starved_entry, &shost->starved_list); + spin_unlock_irq(shost->host_lock); goto not_ready; } @@ -1562,16 +1735,7 @@ static void scsi_request_fn(struct request_queue *q) goto not_ready; if (!scsi_host_queue_ready(q, shost, sdev)) - goto not_ready; - - scsi_target(sdev)->target_busy++; - shost->host_busy++; - - /* - * XXX(hch): This is rather suboptimal, scsi_dispatch_cmd will - * take the lock again. - */ - spin_unlock_irq(shost->host_lock); + goto host_not_ready; /* * Finally, initialize any error handling parameters, and set up @@ -1582,17 +1746,22 @@ static void scsi_request_fn(struct request_queue *q) /* * Dispatch the command to the low-level driver. */ + cmd->scsi_done = scsi_done; rtn = scsi_dispatch_cmd(cmd); - spin_lock_irq(q->queue_lock); - if (rtn) + if (rtn) { + scsi_queue_insert(cmd, rtn); + spin_lock_irq(q->queue_lock); goto out_delay; + } + spin_lock_irq(q->queue_lock); } return; + host_not_ready: + if (scsi_target(sdev)->can_queue > 0) + atomic_dec(&scsi_target(sdev)->target_busy); not_ready: - spin_unlock_irq(shost->host_lock); - /* * lock q, handle tag, requeue req, and decrement device_busy. We * must return with queue_lock held. @@ -1603,13 +1772,187 @@ static void scsi_request_fn(struct request_queue *q) */ spin_lock_irq(q->queue_lock); blk_requeue_request(q, req); - sdev->device_busy--; + atomic_dec(&sdev->device_busy); out_delay: - if (sdev->device_busy == 0) + if (atomic_read(&sdev->device_busy) && !scsi_device_blocked(sdev)) blk_delay_queue(q, SCSI_QUEUE_DELAY); } -u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) +static inline int prep_to_mq(int ret) +{ + switch (ret) { + case BLKPREP_OK: + return 0; + case BLKPREP_DEFER: + return BLK_MQ_RQ_QUEUE_BUSY; + default: + return BLK_MQ_RQ_QUEUE_ERROR; + } +} + +static int scsi_mq_prep_fn(struct request *req) +{ + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req); + struct scsi_device *sdev = req->q->queuedata; + struct Scsi_Host *shost = sdev->host; + unsigned char *sense_buf = cmd->sense_buffer; + struct scatterlist *sg; + + memset(cmd, 0, sizeof(struct scsi_cmnd)); + + req->special = cmd; + + cmd->request = req; + cmd->device = sdev; + cmd->sense_buffer = sense_buf; + + cmd->tag = req->tag; + + req->cmd = req->__cmd; + cmd->cmnd = req->cmd; + cmd->prot_op = SCSI_PROT_NORMAL; + + INIT_LIST_HEAD(&cmd->list); + INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler); + cmd->jiffies_at_alloc = jiffies; + + /* + * XXX: cmd_list lookups are only used by two drivers, try to get + * rid of this list in common code. + */ + spin_lock_irq(&sdev->list_lock); + list_add_tail(&cmd->list, &sdev->cmd_list); + spin_unlock_irq(&sdev->list_lock); + + sg = (void *)cmd + sizeof(struct scsi_cmnd) + shost->hostt->cmd_size; + cmd->sdb.table.sgl = sg; + + if (scsi_host_get_prot(shost)) { + cmd->prot_sdb = (void *)sg + + shost->sg_tablesize * sizeof(struct scatterlist); + memset(cmd->prot_sdb, 0, sizeof(struct scsi_data_buffer)); + + cmd->prot_sdb->table.sgl = + (struct scatterlist *)(cmd->prot_sdb + 1); + } + + if (blk_bidi_rq(req)) { + struct request *next_rq = req->next_rq; + struct scsi_data_buffer *bidi_sdb = blk_mq_rq_to_pdu(next_rq); + + memset(bidi_sdb, 0, sizeof(struct scsi_data_buffer)); + bidi_sdb->table.sgl = + (struct scatterlist *)(bidi_sdb + 1); + + next_rq->special = bidi_sdb; + } + + return scsi_setup_cmnd(sdev, req); +} + +static void scsi_mq_done(struct scsi_cmnd *cmd) +{ + trace_scsi_dispatch_cmd_done(cmd); + blk_mq_complete_request(cmd->request); +} + +static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) +{ + struct request_queue *q = req->q; + struct scsi_device *sdev = q->queuedata; + struct Scsi_Host *shost = sdev->host; + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req); + int ret; + int reason; + + ret = prep_to_mq(scsi_prep_state_check(sdev, req)); + if (ret) + goto out; + + ret = BLK_MQ_RQ_QUEUE_BUSY; + if (!get_device(&sdev->sdev_gendev)) + goto out; + + if (!scsi_dev_queue_ready(q, sdev)) + goto out_put_device; + if (!scsi_target_queue_ready(shost, sdev)) + goto out_dec_device_busy; + if (!scsi_host_queue_ready(q, shost, sdev)) + goto out_dec_target_busy; + + if (!(req->cmd_flags & REQ_DONTPREP)) { + ret = prep_to_mq(scsi_mq_prep_fn(req)); + if (ret) + goto out_dec_host_busy; + req->cmd_flags |= REQ_DONTPREP; + } + + scsi_init_cmd_errh(cmd); + cmd->scsi_done = scsi_mq_done; + + reason = scsi_dispatch_cmd(cmd); + if (reason) { + scsi_set_blocked(cmd, reason); + ret = BLK_MQ_RQ_QUEUE_BUSY; + goto out_dec_host_busy; + } + + return BLK_MQ_RQ_QUEUE_OK; + +out_dec_host_busy: + atomic_dec(&shost->host_busy); +out_dec_target_busy: + if (scsi_target(sdev)->can_queue > 0) + atomic_dec(&scsi_target(sdev)->target_busy); +out_dec_device_busy: + atomic_dec(&sdev->device_busy); +out_put_device: + put_device(&sdev->sdev_gendev); +out: + switch (ret) { + case BLK_MQ_RQ_QUEUE_BUSY: + blk_mq_stop_hw_queue(hctx); + if (atomic_read(&sdev->device_busy) == 0 && + !scsi_device_blocked(sdev)) + blk_mq_delay_queue(hctx, SCSI_QUEUE_DELAY); + break; + case BLK_MQ_RQ_QUEUE_ERROR: + /* + * Make sure to release all allocated ressources when + * we hit an error, as we will never see this command + * again. + */ + if (req->cmd_flags & REQ_DONTPREP) + scsi_mq_uninit_cmd(cmd); + break; + default: + break; + } + return ret; +} + +static int scsi_init_request(void *data, struct request *rq, + unsigned int hctx_idx, unsigned int request_idx, + unsigned int numa_node) +{ + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); + + cmd->sense_buffer = kzalloc_node(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL, + numa_node); + if (!cmd->sense_buffer) + return -ENOMEM; + return 0; +} + +static void scsi_exit_request(void *data, struct request *rq, + unsigned int hctx_idx, unsigned int request_idx) +{ + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); + + kfree(cmd->sense_buffer); +} + +static u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) { struct device *host_dev; u64 bounce_limit = 0xffffffff; @@ -1629,18 +1972,11 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) return bounce_limit; } -EXPORT_SYMBOL(scsi_calculate_bounce_limit); -struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, - request_fn_proc *request_fn) +static void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q) { - struct request_queue *q; struct device *dev = shost->dma_dev; - q = blk_init_queue(request_fn, NULL); - if (!q) - return NULL; - /* * this limit is imposed by hardware restrictions */ @@ -1671,7 +2007,17 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, * blk_queue_update_dma_alignment() later. */ blk_queue_dma_alignment(q, 0x03); +} +struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, + request_fn_proc *request_fn) +{ + struct request_queue *q; + + q = blk_init_queue(request_fn, NULL); + if (!q) + return NULL; + __scsi_init_queue(shost, q); return q; } EXPORT_SYMBOL(__scsi_alloc_queue); @@ -1692,6 +2038,55 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) return q; } +static struct blk_mq_ops scsi_mq_ops = { + .map_queue = blk_mq_map_queue, + .queue_rq = scsi_queue_rq, + .complete = scsi_softirq_done, + .timeout = scsi_times_out, + .init_request = scsi_init_request, + .exit_request = scsi_exit_request, +}; + +struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev) +{ + sdev->request_queue = blk_mq_init_queue(&sdev->host->tag_set); + if (IS_ERR(sdev->request_queue)) + return NULL; + + sdev->request_queue->queuedata = sdev; + __scsi_init_queue(sdev->host, sdev->request_queue); + return sdev->request_queue; +} + +int scsi_mq_setup_tags(struct Scsi_Host *shost) +{ + unsigned int cmd_size, sgl_size, tbl_size; + + tbl_size = shost->sg_tablesize; + if (tbl_size > SCSI_MAX_SG_SEGMENTS) + tbl_size = SCSI_MAX_SG_SEGMENTS; + sgl_size = tbl_size * sizeof(struct scatterlist); + cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size + sgl_size; + if (scsi_host_get_prot(shost)) + cmd_size += sizeof(struct scsi_data_buffer) + sgl_size; + + memset(&shost->tag_set, 0, sizeof(shost->tag_set)); + shost->tag_set.ops = &scsi_mq_ops; + shost->tag_set.nr_hw_queues = 1; + shost->tag_set.queue_depth = shost->can_queue; + shost->tag_set.cmd_size = cmd_size; + shost->tag_set.numa_node = NUMA_NO_NODE; + shost->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE; + shost->tag_set.driver_data = shost; + + return blk_mq_alloc_tag_set(&shost->tag_set); +} + +void scsi_mq_destroy_tags(struct Scsi_Host *shost) +{ + blk_mq_free_tag_set(&shost->tag_set); +} + /* * Function: scsi_block_requests() * @@ -2147,9 +2542,9 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) return 0; illegal: - SCSI_LOG_ERROR_RECOVERY(1, + SCSI_LOG_ERROR_RECOVERY(1, sdev_printk(KERN_ERR, sdev, - "Illegal state transition %s->%s\n", + "Illegal state transition %s->%s", scsi_device_state_name(oldstate), scsi_device_state_name(state)) ); @@ -2345,7 +2740,7 @@ scsi_device_quiesce(struct scsi_device *sdev) return err; scsi_run_queue(sdev->request_queue); - while (sdev->device_busy) { + while (atomic_read(&sdev->device_busy)) { msleep_interruptible(200); scsi_run_queue(sdev->request_queue); } @@ -2437,9 +2832,13 @@ scsi_internal_device_block(struct scsi_device *sdev) * block layer from calling the midlayer with this device's * request queue. */ - spin_lock_irqsave(q->queue_lock, flags); - blk_stop_queue(q); - spin_unlock_irqrestore(q->queue_lock, flags); + if (q->mq_ops) { + blk_mq_stop_hw_queues(q); + } else { + spin_lock_irqsave(q->queue_lock, flags); + blk_stop_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + } return 0; } @@ -2485,9 +2884,13 @@ scsi_internal_device_unblock(struct scsi_device *sdev, sdev->sdev_state != SDEV_OFFLINE) return -EINVAL; - spin_lock_irqsave(q->queue_lock, flags); - blk_start_queue(q); - spin_unlock_irqrestore(q->queue_lock, flags); + if (q->mq_ops) { + blk_mq_start_stopped_hw_queues(q, false); + } else { + spin_lock_irqsave(q->queue_lock, flags); + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + } return 0; } diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 48e5b65..12b8e1b 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -88,6 +88,9 @@ extern void scsi_next_command(struct scsi_cmnd *cmd); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_run_host_queues(struct Scsi_Host *shost); extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); +extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev); +extern int scsi_mq_setup_tags(struct Scsi_Host *shost); +extern void scsi_mq_destroy_tags(struct Scsi_Host *shost); extern int scsi_init_queue(void); extern void scsi_exit_queue(void); struct request_queue; @@ -115,7 +118,7 @@ extern void scsi_exit_procfs(void); extern char scsi_scan_type[]; extern int scsi_complete_async_scans(void); extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, - unsigned int, unsigned int, int); + unsigned int, u64, int); extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_rescan_device(struct device *); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 86f0c5d..6fcefa2 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -185,7 +185,7 @@ static int proc_print_scsidevice(struct device *dev, void *data) sdev = to_scsi_device(dev); seq_printf(s, - "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n Vendor: ", + "Host: scsi%d Channel: %02d Id: %02d Lun: %02llu\n Vendor: ", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); for (i = 0; i < 8; i++) { if (sdev->vendor[i] >= 0x20) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index e02b3aa..56675db 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -81,15 +81,11 @@ static const char *scsi_null_device_strs = "nullnullnullnull"; #define MAX_SCSI_LUNS 512 -#ifdef CONFIG_SCSI_MULTI_LUN -static unsigned int max_scsi_luns = MAX_SCSI_LUNS; -#else -static unsigned int max_scsi_luns = 1; -#endif +static u64 max_scsi_luns = MAX_SCSI_LUNS; -module_param_named(max_luns, max_scsi_luns, uint, S_IRUGO|S_IWUSR); +module_param_named(max_luns, max_scsi_luns, ullong, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(max_luns, - "last scsi LUN (should be between 1 and 2^32-1)"); + "last scsi LUN (should be between 1 and 2^64-1)"); #ifdef CONFIG_SCSI_SCAN_ASYNC #define SCSI_SCAN_TYPE_DEFAULT "async" @@ -198,7 +194,7 @@ static void scsi_unlock_floptical(struct scsi_device *sdev, { unsigned char scsi_cmd[MAX_COMMAND_SIZE]; - printk(KERN_NOTICE "scsi: unlocking floptical drive\n"); + sdev_printk(KERN_NOTICE, sdev, "unlocking floptical drive\n"); scsi_cmd[0] = MODE_SENSE; scsi_cmd[1] = 0; scsi_cmd[2] = 0x2e; @@ -224,7 +220,7 @@ static void scsi_unlock_floptical(struct scsi_device *sdev, * scsi_Device pointer, or NULL on failure. **/ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, - unsigned int lun, void *hostdata) + u64 lun, void *hostdata) { struct scsi_device *sdev; int display_failure_msg = 1, ret; @@ -277,7 +273,10 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, */ sdev->borken = 1; - sdev->request_queue = scsi_alloc_queue(sdev); + if (shost_use_blk_mq(shost)) + sdev->request_queue = scsi_mq_alloc_queue(sdev); + else + sdev->request_queue = scsi_alloc_queue(sdev); if (!sdev->request_queue) { /* release fn is set up in scsi_sysfs_device_initialise, so * have to free and put manually here */ @@ -600,8 +599,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, HZ / 2 + HZ * scsi_inq_timeout, 3, &resid); - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " - "with code 0x%x\n", + SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, + "scsi scan: INQUIRY %s with code 0x%x\n", result ? "failed" : "successful", result)); if (result) { @@ -671,9 +670,10 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, } } else if (pass == 2) { - printk(KERN_INFO "scsi scan: %d byte inquiry failed. " - "Consider BLIST_INQUIRY_36 for this device\n", - try_inquiry_len); + sdev_printk(KERN_INFO, sdev, + "scsi scan: %d byte inquiry failed. " + "Consider BLIST_INQUIRY_36 for this device\n", + try_inquiry_len); /* If this pass failed, the third pass goes back and transfers * the same amount as we successfully got in the first pass. */ @@ -706,8 +706,9 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, * strings. */ if (sdev->inquiry_len < 36) { - printk(KERN_INFO "scsi scan: INQUIRY result too short (%d)," - " using 36\n", sdev->inquiry_len); + sdev_printk(KERN_INFO, sdev, + "scsi scan: INQUIRY result too short (%d)," + " using 36\n", sdev->inquiry_len); sdev->inquiry_len = 36; } @@ -806,29 +807,6 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, sdev->removable = (inq_result[1] & 0x80) >> 7; } - switch (sdev->type) { - case TYPE_RBC: - case TYPE_TAPE: - case TYPE_DISK: - case TYPE_PRINTER: - case TYPE_MOD: - case TYPE_PROCESSOR: - case TYPE_SCANNER: - case TYPE_MEDIUM_CHANGER: - case TYPE_ENCLOSURE: - case TYPE_COMM: - case TYPE_RAID: - case TYPE_OSD: - sdev->writeable = 1; - break; - case TYPE_ROM: - case TYPE_WORM: - sdev->writeable = 0; - break; - default: - printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type); - } - if (sdev->type == TYPE_RBC || sdev->type == TYPE_ROM) { /* RBC and MMC devices can return SCSI-3 compliance and yet * still not support REPORT LUNS, so make them act as @@ -922,6 +900,12 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, if (*bflags & BLIST_USE_10_BYTE_MS) sdev->use_10_for_ms = 1; + /* some devices don't like REPORT SUPPORTED OPERATION CODES + * and will simply timeout causing sd_mod init to take a very + * very long time */ + if (*bflags & BLIST_NO_RSOC) + sdev->no_report_opcodes = 1; + /* set the device running here so that slave configure * may do I/O */ ret = scsi_device_set_state(sdev, SDEV_RUNNING); @@ -950,7 +934,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT; - if (*bflags & BLIST_SKIP_VPD_PAGES) + if (*bflags & BLIST_TRY_VPD_PAGES) + sdev->try_vpd_pages = 1; + else if (*bflags & BLIST_SKIP_VPD_PAGES) sdev->skip_vpd_pages = 1; transport_configure_device(&sdev->sdev_gendev); @@ -1032,7 +1018,7 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized **/ static int scsi_probe_and_add_lun(struct scsi_target *starget, - uint lun, int *bflagsp, + u64 lun, int *bflagsp, struct scsi_device **sdevp, int rescan, void *hostdata) { @@ -1048,7 +1034,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, sdev = scsi_device_lookup_by_target(starget, lun); if (sdev) { if (rescan || !scsi_device_created(sdev)) { - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO + SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, "scsi scan: device exists on %s\n", dev_name(&sdev->sdev_gendev))); if (sdevp) @@ -1135,7 +1121,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, if (((result[0] >> 5) == 1 || starget->pdt_1f_for_no_lun) && (result[0] & 0x1f) == 0x1f && !scsi_is_wlun(lun)) { - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO + SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, "scsi scan: peripheral device type" " of 31, no device added\n")); res = SCSI_SCAN_TARGET_PRESENT; @@ -1185,11 +1171,12 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, static void scsi_sequential_lun_scan(struct scsi_target *starget, int bflags, int scsi_level, int rescan) { - unsigned int sparse_lun, lun, max_dev_lun; + uint max_dev_lun; + u64 sparse_lun, lun; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: Sequential scan of" - "%s\n", dev_name(&starget->dev))); + SCSI_LOG_SCAN_BUS(3, starget_printk(KERN_INFO, starget, + "scsi scan: Sequential scan\n")); max_dev_lun = min(max_scsi_luns, shost->max_lun); /* @@ -1239,6 +1226,12 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, max_dev_lun = min(8U, max_dev_lun); /* + * Stop scanning at 255 unless BLIST_SCSI3LUN + */ + if (!(bflags & BLIST_SCSI3LUN)) + max_dev_lun = min(256U, max_dev_lun); + + /* * We have already scanned LUN 0, so start at LUN 1. Keep scanning * until we reach the max, or no LUN is found and we are not * sparse_lun. @@ -1260,24 +1253,25 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, * truncation before using this function. * * Notes: - * The struct scsi_lun is assumed to be four levels, with each level - * effectively containing a SCSI byte-ordered (big endian) short; the - * addressing bits of each level are ignored (the highest two bits). * For a description of the LUN format, post SCSI-3 see the SCSI * Architecture Model, for SCSI-3 see the SCSI Controller Commands. * - * Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns - * the integer: 0x0b030a04 + * Given a struct scsi_lun of: d2 04 0b 03 00 00 00 00, this function + * returns the integer: 0x0b03d204 + * + * This encoding will return a standard integer LUN for LUNs smaller + * than 256, which typically use a single level LUN structure with + * addressing method 0. **/ -int scsilun_to_int(struct scsi_lun *scsilun) +u64 scsilun_to_int(struct scsi_lun *scsilun) { int i; - unsigned int lun; + u64 lun; lun = 0; for (i = 0; i < sizeof(lun); i += 2) - lun = lun | (((scsilun->scsi_lun[i] << 8) | - scsilun->scsi_lun[i + 1]) << (i * 8)); + lun = lun | (((u64)scsilun->scsi_lun[i] << ((i + 1) * 8)) | + ((u64)scsilun->scsi_lun[i + 1] << (i * 8))); return lun; } EXPORT_SYMBOL(scsilun_to_int); @@ -1291,16 +1285,13 @@ EXPORT_SYMBOL(scsilun_to_int); * Reverts the functionality of the scsilun_to_int, which packed * an 8-byte lun value into an int. This routine unpacks the int * back into the lun value. - * Note: the scsilun_to_int() routine does not truly handle all - * 8bytes of the lun value. This functions restores only as much - * as was set by the routine. * * Notes: - * Given an integer : 0x0b030a04, this function returns a - * scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00 + * Given an integer : 0x0b03d204, this function returns a + * struct scsi_lun of: d2 04 0b 03 00 00 00 00 * **/ -void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun) +void int_to_scsilun(u64 lun, struct scsi_lun *scsilun) { int i; @@ -1340,7 +1331,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, char devname[64]; unsigned char scsi_cmd[MAX_COMMAND_SIZE]; unsigned int length; - unsigned int lun; + u64 lun; unsigned int num_luns; unsigned int retries; int result; @@ -1430,17 +1421,19 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, * a retry. */ for (retries = 0; retries < 3; retries++) { - SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" - " REPORT LUNS to %s (try %d)\n", devname, + SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev, + "scsi scan: Sending REPORT LUNS to (try %d)\n", retries)); result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, lun_data, length, &sshdr, SCSI_TIMEOUT + 4 * HZ, 3, NULL); - SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" - " %s (try %d) result 0x%x\n", result - ? "failed" : "successful", retries, result)); + SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev, + "scsi scan: REPORT LUNS" + " %s (try %d) result 0x%x\n", + result ? "failed" : "successful", + retries, result)); if (result == 0) break; else if (scsi_sense_valid(&sshdr)) { @@ -1466,10 +1459,11 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, num_luns = (length / sizeof(struct scsi_lun)); if (num_luns > max_scsi_report_luns) { - printk(KERN_WARNING "scsi: On %s only %d (max_scsi_report_luns)" - " of %d luns reported, try increasing" - " max_scsi_report_luns.\n", devname, - max_scsi_report_luns, num_luns); + sdev_printk(KERN_WARNING, sdev, + "Only %d (max_scsi_report_luns)" + " of %d luns reported, try increasing" + " max_scsi_report_luns.\n", + max_scsi_report_luns, num_luns); num_luns = max_scsi_report_luns; } @@ -1483,27 +1477,10 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, for (lunp = &lun_data[1]; lunp <= &lun_data[num_luns]; lunp++) { lun = scsilun_to_int(lunp); - /* - * Check if the unused part of lunp is non-zero, and so - * does not fit in lun. - */ - if (memcmp(&lunp->scsi_lun[sizeof(lun)], "\0\0\0\0", 4)) { - int i; - - /* - * Output an error displaying the LUN in byte order, - * this differs from what linux would print for the - * integer LUN value. - */ - printk(KERN_WARNING "scsi: %s lun 0x", devname); - data = (char *)lunp->scsi_lun; - for (i = 0; i < sizeof(struct scsi_lun); i++) - printk("%02x", data[i]); - printk(" has a LUN larger than currently supported.\n"); - } else if (lun > sdev->host->max_lun) { - printk(KERN_WARNING "scsi: %s lun%d has a LUN larger" - " than allowed by the host adapter\n", - devname, lun); + if (lun > sdev->host->max_lun) { + sdev_printk(KERN_WARNING, sdev, + "lun%llu has a LUN larger than" + " allowed by the host adapter\n", lun); } else { int res; @@ -1515,8 +1492,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, */ sdev_printk(KERN_ERR, sdev, "Unexpected response" - " from lun %d while scanning, scan" - " aborted\n", lun); + " from lun %llu while scanning, scan" + " aborted\n", (unsigned long long)lun); break; } } @@ -1535,7 +1512,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, } struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, - uint id, uint lun, void *hostdata) + uint id, u64 lun, void *hostdata) { struct scsi_device *sdev = ERR_PTR(-ENODEV); struct device *parent = &shost->shost_gendev; @@ -1571,7 +1548,7 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, EXPORT_SYMBOL(__scsi_add_device); int scsi_add_device(struct Scsi_Host *host, uint channel, - uint target, uint lun) + uint target, u64 lun) { struct scsi_device *sdev = __scsi_add_device(host, channel, target, lun, NULL); @@ -1600,7 +1577,7 @@ void scsi_rescan_device(struct device *dev) EXPORT_SYMBOL(scsi_rescan_device); static void __scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, unsigned int lun, int rescan) + unsigned int id, u64 lun, int rescan) { struct Scsi_Host *shost = dev_to_shost(parent); int bflags = 0; @@ -1668,7 +1645,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * sequential scan of LUNs on the target id. **/ void scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, unsigned int lun, int rescan) + unsigned int id, u64 lun, int rescan) { struct Scsi_Host *shost = dev_to_shost(parent); @@ -1688,7 +1665,7 @@ void scsi_scan_target(struct device *parent, unsigned int channel, EXPORT_SYMBOL(scsi_scan_target); static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, unsigned int lun, int rescan) + unsigned int id, u64 lun, int rescan) { uint order_id; @@ -1719,10 +1696,10 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, } int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, unsigned int lun, int rescan) + unsigned int id, u64 lun, int rescan) { SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost, - "%s: <%u:%u:%u>\n", + "%s: <%u:%u:%llu>\n", __func__, channel, id, lun)); if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || @@ -1781,8 +1758,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) return NULL; if (shost->async_scan) { - printk("%s called twice for host %d", __func__, - shost->host_no); + shost_printk(KERN_INFO, shost, "%s called twice\n", __func__); dump_stack(); return NULL; } @@ -1835,8 +1811,7 @@ static void scsi_finish_async_scan(struct async_scan_data *data) mutex_lock(&shost->scan_mutex); if (!shost->async_scan) { - printk("%s called twice for host %d", __func__, - shost->host_no); + shost_printk(KERN_INFO, shost, "%s called twice\n", __func__); dump_stack(); mutex_unlock(&shost->scan_mutex); return; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 074e8cc..406b303 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -80,7 +80,7 @@ const char *scsi_host_state_name(enum scsi_host_state state) return name; } -static int check_set(unsigned int *val, char *src) +static int check_set(unsigned long long *val, char *src) { char *last; @@ -90,7 +90,7 @@ static int check_set(unsigned int *val, char *src) /* * Doesn't check for int overflow */ - *val = simple_strtoul(src, &last, 0); + *val = simple_strtoull(src, &last, 0); if (*last != '\0') return 1; } @@ -99,11 +99,11 @@ static int check_set(unsigned int *val, char *src) static int scsi_scan(struct Scsi_Host *shost, const char *str) { - char s1[15], s2[15], s3[15], junk; - unsigned int channel, id, lun; + char s1[15], s2[15], s3[17], junk; + unsigned long long channel, id, lun; int res; - res = sscanf(str, "%10s %10s %10s %c", s1, s2, s3, &junk); + res = sscanf(str, "%10s %10s %16s %c", s1, s2, s3, &junk); if (res != 3) return -EINVAL; if (check_set(&channel, s1)) @@ -333,8 +333,8 @@ store_shost_eh_deadline(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store_shost_eh_deadline); +shost_rd_attr(use_blk_mq, "%d\n"); shost_rd_attr(unique_id, "%u\n"); -shost_rd_attr(host_busy, "%hu\n"); shost_rd_attr(cmd_per_lun, "%hd\n"); shost_rd_attr(can_queue, "%hd\n"); shost_rd_attr(sg_tablesize, "%hu\n"); @@ -344,7 +344,16 @@ shost_rd_attr(prot_capabilities, "%u\n"); shost_rd_attr(prot_guard_type, "%hd\n"); shost_rd_attr2(proc_name, hostt->proc_name, "%s\n"); +static ssize_t +show_host_busy(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + return snprintf(buf, 20, "%d\n", atomic_read(&shost->host_busy)); +} +static DEVICE_ATTR(host_busy, S_IRUGO, show_host_busy, NULL); + static struct attribute *scsi_sysfs_shost_attrs[] = { + &dev_attr_use_blk_mq.attr, &dev_attr_unique_id.attr, &dev_attr_host_busy.attr, &dev_attr_cmd_per_lun.attr, @@ -577,14 +586,30 @@ static int scsi_sdev_check_buf_bit(const char *buf) /* * Create the actual show/store functions and data structures. */ -sdev_rd_attr (device_blocked, "%d\n"); -sdev_rd_attr (device_busy, "%d\n"); sdev_rd_attr (type, "%d\n"); sdev_rd_attr (scsi_level, "%d\n"); sdev_rd_attr (vendor, "%.8s\n"); sdev_rd_attr (model, "%.16s\n"); sdev_rd_attr (rev, "%.4s\n"); +static ssize_t +sdev_show_device_busy(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + return snprintf(buf, 20, "%d\n", atomic_read(&sdev->device_busy)); +} +static DEVICE_ATTR(device_busy, S_IRUGO, sdev_show_device_busy, NULL); + +static ssize_t +sdev_show_device_blocked(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + return snprintf(buf, 20, "%d\n", atomic_read(&sdev->device_blocked)); +} +static DEVICE_ATTR(device_blocked, S_IRUGO, sdev_show_device_blocked, NULL); + /* * TODO: can we make these symlinks to the block layer ones? */ @@ -1230,13 +1255,13 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) device_initialize(&sdev->sdev_gendev); sdev->sdev_gendev.bus = &scsi_bus_type; sdev->sdev_gendev.type = &scsi_dev_type; - dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%d", + dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%llu", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); device_initialize(&sdev->sdev_dev); sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev); sdev->sdev_dev.class = &sdev_class; - dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%d", + dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%llu", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); sdev->scsi_level = starget->scsi_level; transport_setup_device(&sdev->sdev_gendev); diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c deleted file mode 100644 index 6209110..0000000 --- a/drivers/scsi/scsi_tgt_if.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * SCSI target kernel/user interface functions - * - * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org> - * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ -#include <linux/miscdevice.h> -#include <linux/gfp.h> -#include <linux/file.h> -#include <linux/export.h> -#include <net/tcp.h> -#include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_tgt.h> -#include <scsi/scsi_tgt_if.h> - -#include <asm/cacheflush.h> - -#include "scsi_tgt_priv.h" - -#if TGT_RING_SIZE < PAGE_SIZE -# define TGT_RING_SIZE PAGE_SIZE -#endif - -#define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT) -#define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event)) -#define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES) - -struct tgt_ring { - u32 tr_idx; - unsigned long tr_pages[TGT_RING_PAGES]; - spinlock_t tr_lock; -}; - -/* tx_ring : kernel->user, rx_ring : user->kernel */ -static struct tgt_ring tx_ring, rx_ring; -static DECLARE_WAIT_QUEUE_HEAD(tgt_poll_wait); - -static inline void tgt_ring_idx_inc(struct tgt_ring *ring) -{ - if (ring->tr_idx == TGT_MAX_EVENTS - 1) - ring->tr_idx = 0; - else - ring->tr_idx++; -} - -static struct tgt_event *tgt_head_event(struct tgt_ring *ring, u32 idx) -{ - u32 pidx, off; - - pidx = idx / TGT_EVENT_PER_PAGE; - off = idx % TGT_EVENT_PER_PAGE; - - return (struct tgt_event *) - (ring->tr_pages[pidx] + sizeof(struct tgt_event) * off); -} - -static int tgt_uspace_send_event(u32 type, struct tgt_event *p) -{ - struct tgt_event *ev; - struct tgt_ring *ring = &tx_ring; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&ring->tr_lock, flags); - - ev = tgt_head_event(ring, ring->tr_idx); - if (!ev->hdr.status) - tgt_ring_idx_inc(ring); - else - err = -BUSY; - - spin_unlock_irqrestore(&ring->tr_lock, flags); - - if (err) - return err; - - memcpy(ev, p, sizeof(*ev)); - ev->hdr.type = type; - mb(); - ev->hdr.status = 1; - - flush_dcache_page(virt_to_page(ev)); - - wake_up_interruptible(&tgt_poll_wait); - - return 0; -} - -int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id, - struct scsi_lun *lun, u64 tag) -{ - struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); - struct tgt_event ev; - int err; - - memset(&ev, 0, sizeof(ev)); - ev.p.cmd_req.host_no = shost->host_no; - ev.p.cmd_req.itn_id = itn_id; - ev.p.cmd_req.data_len = scsi_bufflen(cmd); - memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb)); - memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun)); - ev.p.cmd_req.attribute = cmd->tag; - ev.p.cmd_req.tag = tag; - - dprintk("%p %d %u %x %llx\n", cmd, shost->host_no, - ev.p.cmd_req.data_len, cmd->tag, - (unsigned long long) ev.p.cmd_req.tag); - - err = tgt_uspace_send_event(TGT_KEVENT_CMD_REQ, &ev); - if (err) - eprintk("tx buf is full, could not send\n"); - - return err; -} - -int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag) -{ - struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); - struct tgt_event ev; - int err; - - memset(&ev, 0, sizeof(ev)); - ev.p.cmd_done.host_no = shost->host_no; - ev.p.cmd_done.itn_id = itn_id; - ev.p.cmd_done.tag = tag; - ev.p.cmd_done.result = cmd->result; - - dprintk("%p %d %llu %u %x\n", cmd, shost->host_no, - (unsigned long long) ev.p.cmd_req.tag, - ev.p.cmd_req.data_len, cmd->tag); - - err = tgt_uspace_send_event(TGT_KEVENT_CMD_DONE, &ev); - if (err) - eprintk("tx buf is full, could not send\n"); - - return err; -} - -int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function, - u64 tag, struct scsi_lun *scsilun, void *data) -{ - struct tgt_event ev; - int err; - - memset(&ev, 0, sizeof(ev)); - ev.p.tsk_mgmt_req.host_no = host_no; - ev.p.tsk_mgmt_req.itn_id = itn_id; - ev.p.tsk_mgmt_req.function = function; - ev.p.tsk_mgmt_req.tag = tag; - memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun)); - ev.p.tsk_mgmt_req.mid = (u64) (unsigned long) data; - - dprintk("%d %x %llx %llx\n", host_no, function, (unsigned long long) tag, - (unsigned long long) ev.p.tsk_mgmt_req.mid); - - err = tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ, &ev); - if (err) - eprintk("tx buf is full, could not send\n"); - - return err; -} - -int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 itn_id, - int function, char *initiator_id) -{ - struct tgt_event ev; - int err; - - memset(&ev, 0, sizeof(ev)); - ev.p.it_nexus_req.host_no = host_no; - ev.p.it_nexus_req.function = function; - ev.p.it_nexus_req.itn_id = itn_id; - if (initiator_id) - strncpy(ev.p.it_nexus_req.initiator_id, initiator_id, - sizeof(ev.p.it_nexus_req.initiator_id)); - - dprintk("%d %x %llx\n", host_no, function, (unsigned long long)itn_id); - - err = tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ, &ev); - if (err) - eprintk("tx buf is full, could not send\n"); - - return err; -} - -static int event_recv_msg(struct tgt_event *ev) -{ - int err = 0; - - switch (ev->hdr.type) { - case TGT_UEVENT_CMD_RSP: - err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, - ev->p.cmd_rsp.itn_id, - ev->p.cmd_rsp.result, - ev->p.cmd_rsp.tag, - ev->p.cmd_rsp.uaddr, - ev->p.cmd_rsp.len, - ev->p.cmd_rsp.sense_uaddr, - ev->p.cmd_rsp.sense_len, - ev->p.cmd_rsp.rw); - break; - case TGT_UEVENT_TSK_MGMT_RSP: - err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no, - ev->p.tsk_mgmt_rsp.itn_id, - ev->p.tsk_mgmt_rsp.mid, - ev->p.tsk_mgmt_rsp.result); - break; - case TGT_UEVENT_IT_NEXUS_RSP: - err = scsi_tgt_kspace_it_nexus_rsp(ev->p.it_nexus_rsp.host_no, - ev->p.it_nexus_rsp.itn_id, - ev->p.it_nexus_rsp.result); - break; - default: - eprintk("unknown type %d\n", ev->hdr.type); - err = -EINVAL; - } - - return err; -} - -static ssize_t tgt_write(struct file *file, const char __user * buffer, - size_t count, loff_t * ppos) -{ - struct tgt_event *ev; - struct tgt_ring *ring = &rx_ring; - - while (1) { - ev = tgt_head_event(ring, ring->tr_idx); - /* do we need this? */ - flush_dcache_page(virt_to_page(ev)); - - if (!ev->hdr.status) - break; - - tgt_ring_idx_inc(ring); - event_recv_msg(ev); - ev->hdr.status = 0; - }; - - return count; -} - -static unsigned int tgt_poll(struct file * file, struct poll_table_struct *wait) -{ - struct tgt_event *ev; - struct tgt_ring *ring = &tx_ring; - unsigned long flags; - unsigned int mask = 0; - u32 idx; - - poll_wait(file, &tgt_poll_wait, wait); - - spin_lock_irqsave(&ring->tr_lock, flags); - - idx = ring->tr_idx ? ring->tr_idx - 1 : TGT_MAX_EVENTS - 1; - ev = tgt_head_event(ring, idx); - if (ev->hdr.status) - mask |= POLLIN | POLLRDNORM; - - spin_unlock_irqrestore(&ring->tr_lock, flags); - - return mask; -} - -static int uspace_ring_map(struct vm_area_struct *vma, unsigned long addr, - struct tgt_ring *ring) -{ - int i, err; - - for (i = 0; i < TGT_RING_PAGES; i++) { - struct page *page = virt_to_page(ring->tr_pages[i]); - err = vm_insert_page(vma, addr, page); - if (err) - return err; - addr += PAGE_SIZE; - } - - return 0; -} - -static int tgt_mmap(struct file *filp, struct vm_area_struct *vma) -{ - unsigned long addr; - int err; - - if (vma->vm_pgoff) - return -EINVAL; - - if (vma->vm_end - vma->vm_start != TGT_RING_SIZE * 2) { - eprintk("mmap size must be %lu, not %lu \n", - TGT_RING_SIZE * 2, vma->vm_end - vma->vm_start); - return -EINVAL; - } - - addr = vma->vm_start; - err = uspace_ring_map(vma, addr, &tx_ring); - if (err) - return err; - err = uspace_ring_map(vma, addr + TGT_RING_SIZE, &rx_ring); - - return err; -} - -static int tgt_open(struct inode *inode, struct file *file) -{ - tx_ring.tr_idx = rx_ring.tr_idx = 0; - - return 0; -} - -static const struct file_operations tgt_fops = { - .owner = THIS_MODULE, - .open = tgt_open, - .poll = tgt_poll, - .write = tgt_write, - .mmap = tgt_mmap, - .llseek = noop_llseek, -}; - -static struct miscdevice tgt_miscdev = { - .minor = MISC_DYNAMIC_MINOR, - .name = "tgt", - .fops = &tgt_fops, -}; - -static void tgt_ring_exit(struct tgt_ring *ring) -{ - int i; - - for (i = 0; i < TGT_RING_PAGES; i++) - free_page(ring->tr_pages[i]); -} - -static int tgt_ring_init(struct tgt_ring *ring) -{ - int i; - - spin_lock_init(&ring->tr_lock); - - for (i = 0; i < TGT_RING_PAGES; i++) { - ring->tr_pages[i] = get_zeroed_page(GFP_KERNEL); - if (!ring->tr_pages[i]) { - eprintk("out of memory\n"); - return -ENOMEM; - } - } - - return 0; -} - -void scsi_tgt_if_exit(void) -{ - tgt_ring_exit(&tx_ring); - tgt_ring_exit(&rx_ring); - misc_deregister(&tgt_miscdev); -} - -int scsi_tgt_if_init(void) -{ - int err; - - err = tgt_ring_init(&tx_ring); - if (err) - return err; - - err = tgt_ring_init(&rx_ring); - if (err) - goto free_tx_ring; - - err = misc_register(&tgt_miscdev); - if (err) - goto free_rx_ring; - - return 0; -free_rx_ring: - tgt_ring_exit(&rx_ring); -free_tx_ring: - tgt_ring_exit(&tx_ring); - - return err; -} diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c deleted file mode 100644 index e51add0..0000000 --- a/drivers/scsi/scsi_tgt_lib.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * SCSI target lib functions - * - * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu> - * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ -#include <linux/blkdev.h> -#include <linux/hash.h> -#include <linux/module.h> -#include <linux/pagemap.h> -#include <linux/slab.h> -#include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_transport.h> -#include <scsi/scsi_tgt.h> - -#include "scsi_tgt_priv.h" - -static struct workqueue_struct *scsi_tgtd; -static struct kmem_cache *scsi_tgt_cmd_cache; - -/* - * TODO: this struct will be killed when the block layer supports large bios - * and James's work struct code is in - */ -struct scsi_tgt_cmd { - /* TODO replace work with James b's code */ - struct work_struct work; - /* TODO fix limits of some drivers */ - struct bio *bio; - - struct list_head hash_list; - struct request *rq; - u64 itn_id; - u64 tag; -}; - -#define TGT_HASH_ORDER 4 -#define cmd_hashfn(tag) hash_long((unsigned long) (tag), TGT_HASH_ORDER) - -struct scsi_tgt_queuedata { - struct Scsi_Host *shost; - struct list_head cmd_hash[1 << TGT_HASH_ORDER]; - spinlock_t cmd_hash_lock; -}; - -/* - * Function: scsi_host_get_command() - * - * Purpose: Allocate and setup a scsi command block and blk request - * - * Arguments: shost - scsi host - * data_dir - dma data dir - * gfp_mask- allocator flags - * - * Returns: The allocated scsi command structure. - * - * This should be called by target LLDs to get a command. - */ -struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, - enum dma_data_direction data_dir, - gfp_t gfp_mask) -{ - int write = (data_dir == DMA_TO_DEVICE); - struct request *rq; - struct scsi_cmnd *cmd; - struct scsi_tgt_cmd *tcmd; - - /* Bail if we can't get a reference to the device */ - if (!get_device(&shost->shost_gendev)) - return NULL; - - tcmd = kmem_cache_alloc(scsi_tgt_cmd_cache, GFP_ATOMIC); - if (!tcmd) - goto put_dev; - - /* - * The blk helpers are used to the READ/WRITE requests - * transferring data from a initiator point of view. Since - * we are in target mode we want the opposite. - */ - rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask); - if (!rq) - goto free_tcmd; - - cmd = __scsi_get_command(shost, gfp_mask); - if (!cmd) - goto release_rq; - - cmd->sc_data_direction = data_dir; - cmd->jiffies_at_alloc = jiffies; - cmd->request = rq; - - cmd->cmnd = rq->cmd; - - rq->special = cmd; - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->cmd_flags |= REQ_TYPE_BLOCK_PC; - rq->end_io_data = tcmd; - - tcmd->rq = rq; - - return cmd; - -release_rq: - blk_put_request(rq); -free_tcmd: - kmem_cache_free(scsi_tgt_cmd_cache, tcmd); -put_dev: - put_device(&shost->shost_gendev); - return NULL; - -} -EXPORT_SYMBOL_GPL(scsi_host_get_command); - -/* - * Function: scsi_host_put_command() - * - * Purpose: Free a scsi command block - * - * Arguments: shost - scsi host - * cmd - command block to free - * - * Returns: Nothing. - * - * Notes: The command must not belong to any lists. - */ -void scsi_host_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) -{ - struct request_queue *q = shost->uspace_req_q; - struct request *rq = cmd->request; - struct scsi_tgt_cmd *tcmd = rq->end_io_data; - unsigned long flags; - - kmem_cache_free(scsi_tgt_cmd_cache, tcmd); - - spin_lock_irqsave(q->queue_lock, flags); - __blk_put_request(q, rq); - spin_unlock_irqrestore(q->queue_lock, flags); - - __scsi_put_command(shost, cmd); - put_device(&shost->shost_gendev); -} -EXPORT_SYMBOL_GPL(scsi_host_put_command); - -static void cmd_hashlist_del(struct scsi_cmnd *cmd) -{ - struct request_queue *q = cmd->request->q; - struct scsi_tgt_queuedata *qdata = q->queuedata; - unsigned long flags; - struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; - - spin_lock_irqsave(&qdata->cmd_hash_lock, flags); - list_del(&tcmd->hash_list); - spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); -} - -static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd) -{ - blk_rq_unmap_user(tcmd->bio); -} - -static void scsi_tgt_cmd_destroy(struct work_struct *work) -{ - struct scsi_tgt_cmd *tcmd = - container_of(work, struct scsi_tgt_cmd, work); - struct scsi_cmnd *cmd = tcmd->rq->special; - - dprintk("cmd %p %d %u\n", cmd, cmd->sc_data_direction, - rq_data_dir(cmd->request)); - scsi_unmap_user_pages(tcmd); - tcmd->rq->bio = NULL; - scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); -} - -static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, - u64 itn_id, u64 tag) -{ - struct scsi_tgt_queuedata *qdata = rq->q->queuedata; - unsigned long flags; - struct list_head *head; - - tcmd->itn_id = itn_id; - tcmd->tag = tag; - tcmd->bio = NULL; - INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); - spin_lock_irqsave(&qdata->cmd_hash_lock, flags); - head = &qdata->cmd_hash[cmd_hashfn(tag)]; - list_add(&tcmd->hash_list, head); - spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); -} - -/* - * scsi_tgt_alloc_queue - setup queue used for message passing - * shost: scsi host - * - * This should be called by the LLD after host allocation. - * And will be released when the host is released. - */ -int scsi_tgt_alloc_queue(struct Scsi_Host *shost) -{ - struct scsi_tgt_queuedata *queuedata; - struct request_queue *q; - int err, i; - - /* - * Do we need to send a netlink event or should uspace - * just respond to the hotplug event? - */ - q = __scsi_alloc_queue(shost, NULL); - if (!q) - return -ENOMEM; - - queuedata = kzalloc(sizeof(*queuedata), GFP_KERNEL); - if (!queuedata) { - err = -ENOMEM; - goto cleanup_queue; - } - queuedata->shost = shost; - q->queuedata = queuedata; - - /* - * this is a silly hack. We should probably just queue as many - * command as is recvd to userspace. uspace can then make - * sure we do not overload the HBA - */ - q->nr_requests = shost->can_queue; - /* - * We currently only support software LLDs so this does - * not matter for now. Do we need this for the cards we support? - * If so we should make it a host template value. - */ - blk_queue_dma_alignment(q, 0); - shost->uspace_req_q = q; - - for (i = 0; i < ARRAY_SIZE(queuedata->cmd_hash); i++) - INIT_LIST_HEAD(&queuedata->cmd_hash[i]); - spin_lock_init(&queuedata->cmd_hash_lock); - - return 0; - -cleanup_queue: - blk_cleanup_queue(q); - return err; -} -EXPORT_SYMBOL_GPL(scsi_tgt_alloc_queue); - -void scsi_tgt_free_queue(struct Scsi_Host *shost) -{ - int i; - unsigned long flags; - struct request_queue *q = shost->uspace_req_q; - struct scsi_cmnd *cmd; - struct scsi_tgt_queuedata *qdata = q->queuedata; - struct scsi_tgt_cmd *tcmd, *n; - LIST_HEAD(cmds); - - spin_lock_irqsave(&qdata->cmd_hash_lock, flags); - - for (i = 0; i < ARRAY_SIZE(qdata->cmd_hash); i++) { - list_for_each_entry_safe(tcmd, n, &qdata->cmd_hash[i], - hash_list) - list_move(&tcmd->hash_list, &cmds); - } - - spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); - - while (!list_empty(&cmds)) { - tcmd = list_entry(cmds.next, struct scsi_tgt_cmd, hash_list); - list_del(&tcmd->hash_list); - cmd = tcmd->rq->special; - - shost->hostt->eh_abort_handler(cmd); - scsi_tgt_cmd_destroy(&tcmd->work); - } -} -EXPORT_SYMBOL_GPL(scsi_tgt_free_queue); - -struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *cmd) -{ - struct scsi_tgt_queuedata *queue = cmd->request->q->queuedata; - return queue->shost; -} -EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host); - -/* - * scsi_tgt_queue_command - queue command for userspace processing - * @cmd: scsi command - * @scsilun: scsi lun - * @tag: unique value to identify this command for tmf - */ -int scsi_tgt_queue_command(struct scsi_cmnd *cmd, u64 itn_id, - struct scsi_lun *scsilun, u64 tag) -{ - struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; - int err; - - init_scsi_tgt_cmd(cmd->request, tcmd, itn_id, tag); - err = scsi_tgt_uspace_send_cmd(cmd, itn_id, scsilun, tag); - if (err) - cmd_hashlist_del(cmd); - - return err; -} -EXPORT_SYMBOL_GPL(scsi_tgt_queue_command); - -/* - * This is run from a interrupt handler normally and the unmap - * needs process context so we must queue - */ -static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) -{ - struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; - - dprintk("cmd %p %u\n", cmd, rq_data_dir(cmd->request)); - - scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag); - - scsi_release_buffers(cmd); - - queue_work(scsi_tgtd, &tcmd->work); -} - -static int scsi_tgt_transfer_response(struct scsi_cmnd *cmd) -{ - struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); - int err; - - dprintk("cmd %p %u\n", cmd, rq_data_dir(cmd->request)); - - err = shost->hostt->transfer_response(cmd, scsi_tgt_cmd_done); - switch (err) { - case SCSI_MLQUEUE_HOST_BUSY: - case SCSI_MLQUEUE_DEVICE_BUSY: - return -EAGAIN; - } - return 0; -} - -/* TODO: test this crap and replace bio_map_user with new interface maybe */ -static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, - unsigned long uaddr, unsigned int len, int rw) -{ - struct request_queue *q = cmd->request->q; - struct request *rq = cmd->request; - int err; - - dprintk("%lx %u\n", uaddr, len); - err = blk_rq_map_user(q, rq, NULL, (void *)uaddr, len, GFP_KERNEL); - if (err) { - /* - * TODO: need to fixup sg_tablesize, max_segment_size, - * max_sectors, etc for modern HW and software drivers - * where this value is bogus. - * - * TODO2: we can alloc a reserve buffer of max size - * we can handle and do the slow copy path for really large - * IO. - */ - eprintk("Could not handle request of size %u.\n", len); - return err; - } - - tcmd->bio = rq->bio; - err = scsi_init_io(cmd, GFP_KERNEL); - if (err) { - scsi_release_buffers(cmd); - goto unmap_rq; - } - /* - * we use REQ_TYPE_BLOCK_PC so scsi_init_io doesn't set the - * length for us. - */ - cmd->sdb.length = blk_rq_bytes(rq); - - return 0; - -unmap_rq: - scsi_unmap_user_pages(tcmd); - return err; -} - -static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr, - unsigned len) -{ - char __user *p = (char __user *) uaddr; - - if (copy_from_user(cmd->sense_buffer, p, - min_t(unsigned, SCSI_SENSE_BUFFERSIZE, len))) { - printk(KERN_ERR "Could not copy the sense buffer\n"); - return -EIO; - } - return 0; -} - -static int scsi_tgt_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd) -{ - struct scsi_tgt_cmd *tcmd; - int err; - - err = shost->hostt->eh_abort_handler(cmd); - if (err) - eprintk("fail to abort %p\n", cmd); - - tcmd = cmd->request->end_io_data; - scsi_tgt_cmd_destroy(&tcmd->work); - return err; -} - -static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) -{ - struct scsi_tgt_queuedata *qdata = q->queuedata; - struct request *rq = NULL; - struct list_head *head; - struct scsi_tgt_cmd *tcmd; - unsigned long flags; - - head = &qdata->cmd_hash[cmd_hashfn(tag)]; - spin_lock_irqsave(&qdata->cmd_hash_lock, flags); - list_for_each_entry(tcmd, head, hash_list) { - if (tcmd->tag == tag) { - rq = tcmd->rq; - list_del(&tcmd->hash_list); - break; - } - } - spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); - - return rq; -} - -int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, - unsigned long uaddr, u32 len, unsigned long sense_uaddr, - u32 sense_len, u8 rw) -{ - struct Scsi_Host *shost; - struct scsi_cmnd *cmd; - struct request *rq; - struct scsi_tgt_cmd *tcmd; - int err = 0; - - dprintk("%d %llu %d %u %lx %u\n", host_no, (unsigned long long) tag, - result, len, uaddr, rw); - - /* TODO: replace with a O(1) alg */ - shost = scsi_host_lookup(host_no); - if (!shost) { - printk(KERN_ERR "Could not find host no %d\n", host_no); - return -EINVAL; - } - - if (!shost->uspace_req_q) { - printk(KERN_ERR "Not target scsi host %d\n", host_no); - goto done; - } - - rq = tgt_cmd_hash_lookup(shost->uspace_req_q, tag); - if (!rq) { - printk(KERN_ERR "Could not find tag %llu\n", - (unsigned long long) tag); - err = -EINVAL; - goto done; - } - cmd = rq->special; - - dprintk("cmd %p scb %x result %d len %d bufflen %u %u %x\n", - cmd, cmd->cmnd[0], result, len, scsi_bufflen(cmd), - rq_data_dir(rq), cmd->cmnd[0]); - - if (result == TASK_ABORTED) { - scsi_tgt_abort_cmd(shost, cmd); - goto done; - } - /* - * store the userspace values here, the working values are - * in the request_* values - */ - tcmd = cmd->request->end_io_data; - cmd->result = result; - - if (cmd->result == SAM_STAT_CHECK_CONDITION) - scsi_tgt_copy_sense(cmd, sense_uaddr, sense_len); - - if (len) { - err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw); - if (err) { - /* - * user-space daemon bugs or OOM - * TODO: we can do better for OOM. - */ - struct scsi_tgt_queuedata *qdata; - struct list_head *head; - unsigned long flags; - - eprintk("cmd %p ret %d uaddr %lx len %d rw %d\n", - cmd, err, uaddr, len, rw); - - qdata = shost->uspace_req_q->queuedata; - head = &qdata->cmd_hash[cmd_hashfn(tcmd->tag)]; - - spin_lock_irqsave(&qdata->cmd_hash_lock, flags); - list_add(&tcmd->hash_list, head); - spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); - - goto done; - } - } - err = scsi_tgt_transfer_response(cmd); -done: - scsi_host_put(shost); - return err; -} - -int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id, - int function, u64 tag, struct scsi_lun *scsilun, - void *data) -{ - int err; - - /* TODO: need to retry if this fails. */ - err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, itn_id, - function, tag, scsilun, data); - if (err < 0) - eprintk("The task management request lost!\n"); - return err; -} -EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); - -int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) -{ - struct Scsi_Host *shost; - int err = -EINVAL; - - dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); - - shost = scsi_host_lookup(host_no); - if (!shost) { - printk(KERN_ERR "Could not find host no %d\n", host_no); - return err; - } - - if (!shost->uspace_req_q) { - printk(KERN_ERR "Not target scsi host %d\n", host_no); - goto done; - } - - err = shost->transportt->tsk_mgmt_response(shost, itn_id, mid, result); -done: - scsi_host_put(shost); - return err; -} - -int scsi_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - int err; - - /* TODO: need to retry if this fails. */ - err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, itn_id, 0, - initiator); - if (err < 0) - eprintk("The i_t_neuxs request lost, %d %llx!\n", - shost->host_no, (unsigned long long)itn_id); - return err; -} -EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create); - -int scsi_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - int err; - - /* TODO: need to retry if this fails. */ - err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, - itn_id, 1, NULL); - if (err < 0) - eprintk("The i_t_neuxs request lost, %d %llx!\n", - shost->host_no, (unsigned long long)itn_id); - return err; -} -EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy); - -int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result) -{ - struct Scsi_Host *shost; - int err = -EINVAL; - - dprintk("%d %d%llx\n", host_no, result, (unsigned long long)itn_id); - - shost = scsi_host_lookup(host_no); - if (!shost) { - printk(KERN_ERR "Could not find host no %d\n", host_no); - return err; - } - - if (!shost->uspace_req_q) { - printk(KERN_ERR "Not target scsi host %d\n", host_no); - goto done; - } - - err = shost->transportt->it_nexus_response(shost, itn_id, result); -done: - scsi_host_put(shost); - return err; -} - -static int __init scsi_tgt_init(void) -{ - int err; - - scsi_tgt_cmd_cache = KMEM_CACHE(scsi_tgt_cmd, 0); - if (!scsi_tgt_cmd_cache) - return -ENOMEM; - - scsi_tgtd = alloc_workqueue("scsi_tgtd", 0, 1); - if (!scsi_tgtd) { - err = -ENOMEM; - goto free_kmemcache; - } - - err = scsi_tgt_if_init(); - if (err) - goto destroy_wq; - - return 0; - -destroy_wq: - destroy_workqueue(scsi_tgtd); -free_kmemcache: - kmem_cache_destroy(scsi_tgt_cmd_cache); - return err; -} - -static void __exit scsi_tgt_exit(void) -{ - destroy_workqueue(scsi_tgtd); - scsi_tgt_if_exit(); - kmem_cache_destroy(scsi_tgt_cmd_cache); -} - -module_init(scsi_tgt_init); -module_exit(scsi_tgt_exit); - -MODULE_DESCRIPTION("SCSI target core"); -MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h deleted file mode 100644 index fe4c621..0000000 --- a/drivers/scsi/scsi_tgt_priv.h +++ /dev/null @@ -1,32 +0,0 @@ -struct scsi_cmnd; -struct scsi_lun; -struct Scsi_Host; -struct task_struct; - -/* tmp - will replace with SCSI logging stuff */ -#define eprintk(fmt, args...) \ -do { \ - printk("%s(%d) " fmt, __func__, __LINE__, ##args); \ -} while (0) - -#define dprintk(fmt, args...) -/* #define dprintk eprintk */ - -extern void scsi_tgt_if_exit(void); -extern int scsi_tgt_if_init(void); - -extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 it_nexus_id, - struct scsi_lun *lun, u64 tag); -extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 it_nexus_id, - u64 tag); -extern int scsi_tgt_kspace_exec(int host_no, u64 it_nexus_id, int result, u64 tag, - unsigned long uaddr, u32 len, - unsigned long sense_uaddr, u32 sense_len, u8 rw); -extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 it_nexus_id, - int function, u64 tag, - struct scsi_lun *scsilun, void *data); -extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 it_nexus_id, - u64 mid, int result); -extern int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 it_nexus_id, - int function, char *initiator); -extern int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 it_nexus_id, int result); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 521f583..5d6f348 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -39,7 +39,6 @@ #include <scsi/scsi_netlink_fc.h> #include <scsi/scsi_bsg_fc.h> #include "scsi_priv.h" -#include "scsi_transport_fc_internal.h" static int fc_queue_work(struct Scsi_Host *, struct work_struct *); static void fc_vport_sched_delete(struct work_struct *work); @@ -262,6 +261,10 @@ static const struct { { FC_PORTSPEED_8GBIT, "8 Gbit" }, { FC_PORTSPEED_16GBIT, "16 Gbit" }, { FC_PORTSPEED_32GBIT, "32 Gbit" }, + { FC_PORTSPEED_20GBIT, "20 Gbit" }, + { FC_PORTSPEED_40GBIT, "40 Gbit" }, + { FC_PORTSPEED_50GBIT, "50 Gbit" }, + { FC_PORTSPEED_100GBIT, "100 Gbit" }, { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" }, }; fc_bitfield_name_search(port_speed, fc_port_speed_names) @@ -2089,7 +2092,7 @@ fc_timed_out(struct scsi_cmnd *scmd) * on the rport. */ static void -fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun) +fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, u64 lun) { struct fc_rport *rport; unsigned long flags; @@ -2121,7 +2124,7 @@ fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun) * object as the parent. */ static int -fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, uint lun) +fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, u64 lun) { uint chlo, chhi; uint tgtlo, tgthi; @@ -3008,10 +3011,6 @@ fc_remote_port_delete(struct fc_rport *rport) spin_unlock_irqrestore(shost->host_lock, flags); - if (rport->roles & FC_PORT_ROLE_FCP_INITIATOR && - shost->active_mode & MODE_TARGET) - fc_tgt_it_nexus_destroy(shost, (unsigned long)rport); - scsi_target_block(&rport->dev); /* see if we need to kill io faster than waiting for device loss */ @@ -3052,7 +3051,6 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) struct fc_host_attrs *fc_host = shost_to_fc_host(shost); unsigned long flags; int create = 0; - int ret; spin_lock_irqsave(shost->host_lock, flags); if (roles & FC_PORT_ROLE_FCP_TARGET) { @@ -3061,12 +3059,6 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) create = 1; } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET)) create = 1; - } else if (shost->active_mode & MODE_TARGET) { - ret = fc_tgt_it_nexus_create(shost, (unsigned long)rport, - (char *)&rport->node_name); - if (ret) - printk(KERN_ERR "FC Remore Port tgt nexus failed %d\n", - ret); } rport->roles = roles; diff --git a/drivers/scsi/scsi_transport_fc_internal.h b/drivers/scsi/scsi_transport_fc_internal.h deleted file mode 100644 index e7bfbe7..0000000 --- a/drivers/scsi/scsi_transport_fc_internal.h +++ /dev/null @@ -1,26 +0,0 @@ -#include <scsi/scsi_tgt.h> - -#ifdef CONFIG_SCSI_FC_TGT_ATTRS -static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return scsi_tgt_it_nexus_create(shost, itn_id, initiator); -} - -static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return scsi_tgt_it_nexus_destroy(shost, itn_id); -} -#else -static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return 0; -} - -static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return 0; -} - -#endif diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 0102a2d..b481e62 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1780,7 +1780,7 @@ EXPORT_SYMBOL_GPL(iscsi_scan_finished); struct iscsi_scan_data { unsigned int channel; unsigned int id; - unsigned int lun; + u64 lun; }; static int iscsi_user_scan_session(struct device *dev, void *data) @@ -1827,7 +1827,7 @@ user_scan_exit: } static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, - uint id, uint lun) + uint id, u64 lun) { struct iscsi_scan_data scan_data; @@ -3059,7 +3059,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh) evchap->u.get_chap.host_no = ev->u.get_chap.host_no; evchap->u.get_chap.chap_tbl_idx = ev->u.get_chap.chap_tbl_idx; evchap->u.get_chap.num_entries = ev->u.get_chap.num_entries; - buf = (char *) ((char *)evchap + sizeof(*evchap)); + buf = (char *)evchap + sizeof(*evchap); memset(buf, 0, chap_buf_size); err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx, @@ -3463,7 +3463,7 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) evhost_stats->type = nlh->nlmsg_type; evhost_stats->u.get_host_stats.host_no = ev->u.get_host_stats.host_no; - buf = (char *)((char *)evhost_stats + sizeof(*evhost_stats)); + buf = (char *)evhost_stats + sizeof(*evhost_stats); memset(buf, 0, host_stats_size); err = transport->get_host_stats(shost, buf, host_stats_size); diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index c341f85..9a05819 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1705,7 +1705,7 @@ EXPORT_SYMBOL(scsi_is_sas_rphy); */ static int sas_user_scan(struct Scsi_Host *shost, uint channel, - uint id, uint lun) + uint id, u64 lun) { struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); struct sas_rphy *rphy; diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 13e8983..43fea22 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -33,7 +33,6 @@ #include <scsi/scsi_transport.h> #include <scsi/scsi_transport_srp.h> #include "scsi_priv.h" -#include "scsi_transport_srp_internal.h" struct srp_host_attrs { atomic_t next_port_id; @@ -746,18 +745,6 @@ struct srp_rport *srp_rport_add(struct Scsi_Host *shost, return ERR_PTR(ret); } - if (shost->active_mode & MODE_TARGET && - ids->roles == SRP_RPORT_ROLE_INITIATOR) { - ret = srp_tgt_it_nexus_create(shost, (unsigned long)rport, - rport->port_id); - if (ret) { - device_del(&rport->dev); - transport_destroy_device(&rport->dev); - put_device(&rport->dev); - return ERR_PTR(ret); - } - } - transport_add_device(&rport->dev); transport_configure_device(&rport->dev); @@ -774,11 +761,6 @@ EXPORT_SYMBOL_GPL(srp_rport_add); void srp_rport_del(struct srp_rport *rport) { struct device *dev = &rport->dev; - struct Scsi_Host *shost = dev_to_shost(dev->parent); - - if (shost->active_mode & MODE_TARGET && - rport->roles == SRP_RPORT_ROLE_INITIATOR) - srp_tgt_it_nexus_destroy(shost, (unsigned long)rport); transport_remove_device(dev); device_del(dev); diff --git a/drivers/scsi/scsi_transport_srp_internal.h b/drivers/scsi/scsi_transport_srp_internal.h deleted file mode 100644 index 8a79747..0000000 --- a/drivers/scsi/scsi_transport_srp_internal.h +++ /dev/null @@ -1,25 +0,0 @@ -#include <scsi/scsi_tgt.h> - -#ifdef CONFIG_SCSI_SRP_TGT_ATTRS -static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return scsi_tgt_it_nexus_create(shost, itn_id, initiator); -} - -static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return scsi_tgt_it_nexus_destroy(shost, itn_id); -} - -#else -static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return 0; -} -static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return 0; -} -#endif diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 6825eda..2c2041c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -134,6 +134,19 @@ static const char *sd_cache_types[] = { "write back, no read (daft)" }; +static void sd_set_flush_flag(struct scsi_disk *sdkp) +{ + unsigned flush = 0; + + if (sdkp->WCE) { + flush |= REQ_FLUSH; + if (sdkp->DPOFUA) + flush |= REQ_FUA; + } + + blk_queue_flush(sdkp->disk->queue, flush); +} + static ssize_t cache_type_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -177,6 +190,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr, if (sdkp->cache_override) { sdkp->WCE = wce; sdkp->RCD = rcd; + sd_set_flush_flag(sdkp); return count; } @@ -677,8 +691,10 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) * Will issue either UNMAP or WRITE SAME(16) depending on preference * indicated by target device. **/ -static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) +static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd) { + struct request *rq = cmd->request; + struct scsi_device *sdp = cmd->device; struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); sector_t sector = blk_rq_pos(rq); unsigned int nr_sectors = blk_rq_sectors(rq); @@ -690,9 +706,6 @@ static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) sector >>= ilog2(sdp->sector_size) - 9; nr_sectors >>= ilog2(sdp->sector_size) - 9; - rq->timeout = SD_TIMEOUT; - - memset(rq->cmd, 0, rq->cmd_len); page = alloc_page(GFP_ATOMIC | __GFP_ZERO); if (!page) @@ -702,9 +715,9 @@ static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) case SD_LBP_UNMAP: buf = page_address(page); - rq->cmd_len = 10; - rq->cmd[0] = UNMAP; - rq->cmd[8] = 24; + cmd->cmd_len = 10; + cmd->cmnd[0] = UNMAP; + cmd->cmnd[8] = 24; put_unaligned_be16(6 + 16, &buf[0]); put_unaligned_be16(16, &buf[2]); @@ -715,23 +728,23 @@ static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) break; case SD_LBP_WS16: - rq->cmd_len = 16; - rq->cmd[0] = WRITE_SAME_16; - rq->cmd[1] = 0x8; /* UNMAP */ - put_unaligned_be64(sector, &rq->cmd[2]); - put_unaligned_be32(nr_sectors, &rq->cmd[10]); + cmd->cmd_len = 16; + cmd->cmnd[0] = WRITE_SAME_16; + cmd->cmnd[1] = 0x8; /* UNMAP */ + put_unaligned_be64(sector, &cmd->cmnd[2]); + put_unaligned_be32(nr_sectors, &cmd->cmnd[10]); len = sdkp->device->sector_size; break; case SD_LBP_WS10: case SD_LBP_ZERO: - rq->cmd_len = 10; - rq->cmd[0] = WRITE_SAME; + cmd->cmd_len = 10; + cmd->cmnd[0] = WRITE_SAME; if (sdkp->provisioning_mode == SD_LBP_WS10) - rq->cmd[1] = 0x8; /* UNMAP */ - put_unaligned_be32(sector, &rq->cmd[2]); - put_unaligned_be16(nr_sectors, &rq->cmd[7]); + cmd->cmnd[1] = 0x8; /* UNMAP */ + put_unaligned_be32(sector, &cmd->cmnd[2]); + put_unaligned_be16(nr_sectors, &cmd->cmnd[7]); len = sdkp->device->sector_size; break; @@ -742,8 +755,21 @@ static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) } rq->completion_data = page; + rq->timeout = SD_TIMEOUT; + + cmd->transfersize = len; + cmd->allowed = SD_MAX_RETRIES; + + /* + * Initially __data_len is set to the amount of data that needs to be + * transferred to the target. This amount depends on whether WRITE SAME + * or UNMAP is being used. After the scatterlist has been mapped by + * scsi_init_io() we set __data_len to the size of the area to be + * discarded on disk. This allows us to report completion on the full + * amount of blocks described by the request. + */ blk_add_request_payload(rq, page, len); - ret = scsi_setup_blk_pc_cmnd(sdp, rq); + ret = scsi_init_io(cmd, GFP_ATOMIC); rq->__data_len = nr_bytes; out: @@ -785,14 +811,15 @@ out: /** * sd_setup_write_same_cmnd - write the same data to multiple blocks - * @sdp: scsi device to operate one - * @rq: Request to prepare + * @cmd: command to prepare * * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on * preference indicated by target device. **/ -static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq) +static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd) { + struct request *rq = cmd->request; + struct scsi_device *sdp = cmd->device; struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); struct bio *bio = rq->bio; sector_t sector = blk_rq_pos(rq); @@ -808,53 +835,56 @@ static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq) sector >>= ilog2(sdp->sector_size) - 9; nr_sectors >>= ilog2(sdp->sector_size) - 9; - rq->__data_len = sdp->sector_size; rq->timeout = SD_WRITE_SAME_TIMEOUT; - memset(rq->cmd, 0, rq->cmd_len); if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) { - rq->cmd_len = 16; - rq->cmd[0] = WRITE_SAME_16; - put_unaligned_be64(sector, &rq->cmd[2]); - put_unaligned_be32(nr_sectors, &rq->cmd[10]); + cmd->cmd_len = 16; + cmd->cmnd[0] = WRITE_SAME_16; + put_unaligned_be64(sector, &cmd->cmnd[2]); + put_unaligned_be32(nr_sectors, &cmd->cmnd[10]); } else { - rq->cmd_len = 10; - rq->cmd[0] = WRITE_SAME; - put_unaligned_be32(sector, &rq->cmd[2]); - put_unaligned_be16(nr_sectors, &rq->cmd[7]); + cmd->cmd_len = 10; + cmd->cmnd[0] = WRITE_SAME; + put_unaligned_be32(sector, &cmd->cmnd[2]); + put_unaligned_be16(nr_sectors, &cmd->cmnd[7]); } - ret = scsi_setup_blk_pc_cmnd(sdp, rq); - rq->__data_len = nr_bytes; + cmd->transfersize = sdp->sector_size; + cmd->allowed = SD_MAX_RETRIES; + /* + * For WRITE_SAME the data transferred in the DATA IN buffer is + * different from the amount of data actually written to the target. + * + * We set up __data_len to the amount of data transferred from the + * DATA IN buffer so that blk_rq_map_sg set up the proper S/G list + * to transfer a single sector of data first, but then reset it to + * the amount of data to be written right after so that the I/O path + * knows how much to actually write. + */ + rq->__data_len = sdp->sector_size; + ret = scsi_init_io(cmd, GFP_ATOMIC); + rq->__data_len = nr_bytes; return ret; } -static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) +static int sd_setup_flush_cmnd(struct scsi_cmnd *cmd) { - rq->timeout *= SD_FLUSH_TIMEOUT_MULTIPLIER; - rq->retries = SD_MAX_RETRIES; - rq->cmd[0] = SYNCHRONIZE_CACHE; - rq->cmd_len = 10; - - return scsi_setup_blk_pc_cmnd(sdp, rq); -} + struct request *rq = cmd->request; -static void sd_uninit_command(struct scsi_cmnd *SCpnt) -{ - struct request *rq = SCpnt->request; + /* flush requests don't perform I/O, zero the S/G table */ + memset(&cmd->sdb, 0, sizeof(cmd->sdb)); - if (rq->cmd_flags & REQ_DISCARD) - __free_page(rq->completion_data); + cmd->cmnd[0] = SYNCHRONIZE_CACHE; + cmd->cmd_len = 10; + cmd->transfersize = 0; + cmd->allowed = SD_MAX_RETRIES; - if (SCpnt->cmnd != rq->cmd) { - mempool_free(SCpnt->cmnd, sd_cdb_pool); - SCpnt->cmnd = NULL; - SCpnt->cmd_len = 0; - } + rq->timeout = rq->q->rq_timeout * SD_FLUSH_TIMEOUT_MULTIPLIER; + return BLKPREP_OK; } -static int sd_init_command(struct scsi_cmnd *SCpnt) +static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) { struct request *rq = SCpnt->request; struct scsi_device *sdp = SCpnt->device; @@ -866,21 +896,7 @@ static int sd_init_command(struct scsi_cmnd *SCpnt) int ret, host_dif; unsigned char protect; - /* - * Discard request come in as REQ_TYPE_FS but we turn them into - * block PC requests to make life easier. - */ - if (rq->cmd_flags & REQ_DISCARD) { - ret = sd_setup_discard_cmnd(sdp, rq); - goto out; - } else if (rq->cmd_flags & REQ_WRITE_SAME) { - ret = sd_setup_write_same_cmnd(sdp, rq); - goto out; - } else if (rq->cmd_flags & REQ_FLUSH) { - ret = scsi_setup_flush_cmnd(sdp, rq); - goto out; - } - ret = scsi_setup_fs_cmnd(sdp, rq); + ret = scsi_init_io(SCpnt, GFP_ATOMIC); if (ret != BLKPREP_OK) goto out; SCpnt = rq->special; @@ -976,18 +992,13 @@ static int sd_init_command(struct scsi_cmnd *SCpnt) } } if (rq_data_dir(rq) == WRITE) { - if (!sdp->writeable) { - goto out; - } SCpnt->cmnd[0] = WRITE_6; - SCpnt->sc_data_direction = DMA_TO_DEVICE; if (blk_integrity_rq(rq)) sd_dif_prepare(rq, block, sdp->sector_size); } else if (rq_data_dir(rq) == READ) { SCpnt->cmnd[0] = READ_6; - SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { scmd_printk(KERN_ERR, SCpnt, "Unknown command %llx\n", (unsigned long long) rq->cmd_flags); goto out; @@ -1042,7 +1053,7 @@ static int sd_init_command(struct scsi_cmnd *SCpnt) SCpnt->cmnd[29] = (unsigned char) (this_count >> 16) & 0xff; SCpnt->cmnd[30] = (unsigned char) (this_count >> 8) & 0xff; SCpnt->cmnd[31] = (unsigned char) this_count & 0xff; - } else if (sdp->use_16_for_rw) { + } else if (sdp->use_16_for_rw || (this_count > 0xffff)) { SCpnt->cmnd[0] += READ_16 - READ_6; SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; @@ -1061,9 +1072,6 @@ static int sd_init_command(struct scsi_cmnd *SCpnt) } else if ((this_count > 0xff) || (block > 0x1fffff) || scsi_device_protection(SCpnt->device) || SCpnt->device->use_10_for_rw) { - if (this_count > 0xffff) - this_count = 0xffff; - SCpnt->cmnd[0] += READ_10 - READ_6; SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; @@ -1116,6 +1124,34 @@ static int sd_init_command(struct scsi_cmnd *SCpnt) return ret; } +static int sd_init_command(struct scsi_cmnd *cmd) +{ + struct request *rq = cmd->request; + + if (rq->cmd_flags & REQ_DISCARD) + return sd_setup_discard_cmnd(cmd); + else if (rq->cmd_flags & REQ_WRITE_SAME) + return sd_setup_write_same_cmnd(cmd); + else if (rq->cmd_flags & REQ_FLUSH) + return sd_setup_flush_cmnd(cmd); + else + return sd_setup_read_write_cmnd(cmd); +} + +static void sd_uninit_command(struct scsi_cmnd *SCpnt) +{ + struct request *rq = SCpnt->request; + + if (rq->cmd_flags & REQ_DISCARD) + __free_page(rq->completion_data); + + if (SCpnt->cmnd != rq->cmd) { + mempool_free(SCpnt->cmnd, sd_cdb_pool); + SCpnt->cmnd = NULL; + SCpnt->cmd_len = 0; + } +} + /** * sd_open - open a scsi disk device * @inode: only i_rdev member may be used @@ -2225,7 +2261,11 @@ got_data: } } - sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff); + if (sdkp->capacity > 0xffffffff) { + sdp->use_16_for_rw = 1; + sdkp->max_xfer_blocks = SD_MAX_XFER_BLOCKS; + } else + sdkp->max_xfer_blocks = SD_DEF_XFER_BLOCKS; /* Rescale capacity to 512-byte units */ if (sector_size == 4096) @@ -2540,6 +2580,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp) { unsigned int sector_sz = sdkp->device->sector_size; const int vpd_len = 64; + u32 max_xfer_length; unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL); if (!buffer || @@ -2547,6 +2588,10 @@ static void sd_read_block_limits(struct scsi_disk *sdkp) scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len)) goto out; + max_xfer_length = get_unaligned_be32(&buffer[8]); + if (max_xfer_length) + sdkp->max_xfer_blocks = max_xfer_length; + blk_queue_io_min(sdkp->disk->queue, get_unaligned_be16(&buffer[6]) * sector_sz); blk_queue_io_opt(sdkp->disk->queue, @@ -2681,6 +2726,11 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) static int sd_try_extended_inquiry(struct scsi_device *sdp) { + /* Attempt VPD inquiry if the device blacklist explicitly calls + * for it. + */ + if (sdp->try_vpd_pages) + return 1; /* * Although VPD inquiries can go to SCSI-2 type devices, * some USB ones crash on receiving them, and the pages @@ -2701,7 +2751,7 @@ static int sd_revalidate_disk(struct gendisk *disk) struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdp = sdkp->device; unsigned char *buffer; - unsigned flush = 0; + unsigned int max_xfer; SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_revalidate_disk\n")); @@ -2747,14 +2797,12 @@ static int sd_revalidate_disk(struct gendisk *disk) * We now have all cache related info, determine how we deal * with flush requests. */ - if (sdkp->WCE) { - flush |= REQ_FLUSH; - if (sdkp->DPOFUA) - flush |= REQ_FUA; - } - - blk_queue_flush(sdkp->disk->queue, flush); + sd_set_flush_flag(sdkp); + max_xfer = min_not_zero(queue_max_hw_sectors(sdkp->disk->queue), + sdkp->max_xfer_blocks); + max_xfer <<= ilog2(sdp->sector_size) - 9; + blk_queue_max_hw_sectors(sdkp->disk->queue, max_xfer); set_capacity(disk, sdkp->capacity); sd_config_write_same(sdkp); kfree(buffer); @@ -3208,12 +3256,14 @@ static int __init init_sd(void) 0, 0, NULL); if (!sd_cdb_cache) { printk(KERN_ERR "sd: can't init extended cdb cache\n"); + err = -ENOMEM; goto err_out_class; } sd_cdb_pool = mempool_create_slab_pool(SD_MEMPOOL_SIZE, sd_cdb_cache); if (!sd_cdb_pool) { printk(KERN_ERR "sd: can't init extended cdb pool\n"); + err = -ENOMEM; goto err_out_cache; } diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 620871ef..4c3ab83 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -44,6 +44,8 @@ enum { }; enum { + SD_DEF_XFER_BLOCKS = 0xffff, + SD_MAX_XFER_BLOCKS = 0xffffffff, SD_MAX_WS10_BLOCKS = 0xffff, SD_MAX_WS16_BLOCKS = 0x7fffff, }; @@ -64,6 +66,7 @@ struct scsi_disk { struct gendisk *disk; atomic_t openers; sector_t capacity; /* size in 512-byte sectors */ + u32 max_xfer_blocks; u32 max_ws_blocks; u32 max_unmap_blocks; u32 unmap_granularity; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 53268aa..01cf888 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -7,9 +7,7 @@ * Original driver (sg.c): * Copyright (C) 1992 Lawrence Foard * Version 2 and 3 extensions to driver: - * Copyright (C) 1998 - 2005 Douglas Gilbert - * - * Modified 19-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support + * Copyright (C) 1998 - 2014 Douglas Gilbert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,11 +16,11 @@ * */ -static int sg_version_num = 30534; /* 2 digits for each component */ -#define SG_VERSION_STR "3.5.34" +static int sg_version_num = 30536; /* 2 digits for each component */ +#define SG_VERSION_STR "3.5.36" /* - * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: + * D. P. Gilbert (dgilbert@interlog.com), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First * the kernel/module needs to be built with CONFIG_SCSI_LOGGING * (otherwise the macros compile to empty statements). @@ -51,6 +49,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #include <linux/delay.h> #include <linux/blktrace_api.h> #include <linux/mutex.h> +#include <linux/atomic.h> #include <linux/ratelimit.h> #include "scsi.h" @@ -64,7 +63,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #ifdef CONFIG_SCSI_PROC_FS #include <linux/proc_fs.h> -static char *sg_version_date = "20061027"; +static char *sg_version_date = "20140603"; static int sg_proc_init(void); static void sg_proc_cleanup(void); @@ -74,6 +73,12 @@ static void sg_proc_cleanup(void); #define SG_MAX_DEVS 32768 +/* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type + * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater + * than 16 bytes are "variable length" whose length is a multiple of 4 + */ +#define SG_MAX_CDB_SIZE 252 + /* * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d) * Then when using 32 bit integers x * m may overflow during the calculation. @@ -102,18 +107,16 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ; #define SG_SECTOR_SZ 512 -static int sg_add(struct device *, struct class_interface *); -static void sg_remove(struct device *, struct class_interface *); - -static DEFINE_SPINLOCK(sg_open_exclusive_lock); +static int sg_add_device(struct device *, struct class_interface *); +static void sg_remove_device(struct device *, struct class_interface *); static DEFINE_IDR(sg_index_idr); static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock file descriptor list for device */ static struct class_interface sg_interface = { - .add_dev = sg_add, - .remove_dev = sg_remove, + .add_dev = sg_add_device, + .remove_dev = sg_remove_device, }; typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */ @@ -146,8 +149,7 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ } Sg_request; typedef struct sg_fd { /* holds the state of a file descriptor */ - /* sfd_siblings is protected by sg_index_lock */ - struct list_head sfd_siblings; + struct list_head sfd_siblings; /* protected by device's sfd_lock */ struct sg_device *parentdp; /* owning device */ wait_queue_head_t read_wait; /* queue read until command done */ rwlock_t rq_list_lock; /* protect access to list in req_arr */ @@ -161,7 +163,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ char low_dma; /* as in parent but possibly overridden to 1 */ char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */ char cmd_q; /* 1 -> allow command queuing, 0 -> don't */ - char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */ + unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */ char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */ char mmap_called; /* 0 -> mmap() never called on this fd */ struct kref f_ref; @@ -170,14 +172,15 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ typedef struct sg_device { /* holds the state of each scsi generic device */ struct scsi_device *device; - wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */ + wait_queue_head_t open_wait; /* queue open() when O_EXCL present */ + struct mutex open_rel_lock; /* held when in open() or release() */ int sg_tablesize; /* adapter's max scatter-gather table size */ u32 index; /* device index number */ - /* sfds is protected by sg_index_lock */ struct list_head sfds; - volatile char detached; /* 0->attached, 1->detached pending removal */ - /* exclude protected by sg_open_exclusive_lock */ - char exclude; /* opened for exclusive access */ + rwlock_t sfd_lock; /* protect access to sfd list */ + atomic_t detaching; /* 0->device usable, 1->device detaching */ + bool exclude; /* 1->open(O_EXCL) succeeded and is active */ + int open_cnt; /* count of opens (perhaps < num(sfds) ) */ char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */ struct gendisk *disk; struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg<n>] */ @@ -197,24 +200,28 @@ static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking); static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer); -static void sg_remove_scat(Sg_scatter_hold * schp); +static void sg_remove_scat(Sg_fd * sfp, Sg_scatter_hold * schp); static void sg_build_reserve(Sg_fd * sfp, int req_size); static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size); static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp); -static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev); +static Sg_fd *sg_add_sfp(Sg_device * sdp); static void sg_remove_sfp(struct kref *); static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request *sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); static int sg_res_in_use(Sg_fd * sfp); static Sg_device *sg_get_dev(int dev); -static void sg_put_dev(Sg_device *sdp); +static void sg_device_destroy(struct kref *kref); #define SZ_SG_HEADER sizeof(struct sg_header) #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t) #define SZ_SG_IOVEC sizeof(sg_iovec_t) #define SZ_SG_REQ_INFO sizeof(sg_req_info_t) +#define sg_printk(prefix, sdp, fmt, a...) \ + sdev_printk(prefix, (sdp)->device, "[%s] " fmt, \ + (sdp)->disk->disk_name, ##a) + static int sg_allow_access(struct file *filp, unsigned char *cmd) { struct sg_fd *sfp = filp->private_data; @@ -225,38 +232,43 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd) return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE); } -static int get_exclude(Sg_device *sdp) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&sg_open_exclusive_lock, flags); - ret = sdp->exclude; - spin_unlock_irqrestore(&sg_open_exclusive_lock, flags); - return ret; -} - -static int set_exclude(Sg_device *sdp, char val) +static int +open_wait(Sg_device *sdp, int flags) { - unsigned long flags; - - spin_lock_irqsave(&sg_open_exclusive_lock, flags); - sdp->exclude = val; - spin_unlock_irqrestore(&sg_open_exclusive_lock, flags); - return val; -} + int retval = 0; -static int sfds_list_empty(Sg_device *sdp) -{ - unsigned long flags; - int ret; + if (flags & O_EXCL) { + while (sdp->open_cnt > 0) { + mutex_unlock(&sdp->open_rel_lock); + retval = wait_event_interruptible(sdp->open_wait, + (atomic_read(&sdp->detaching) || + !sdp->open_cnt)); + mutex_lock(&sdp->open_rel_lock); + + if (retval) /* -ERESTARTSYS */ + return retval; + if (atomic_read(&sdp->detaching)) + return -ENODEV; + } + } else { + while (sdp->exclude) { + mutex_unlock(&sdp->open_rel_lock); + retval = wait_event_interruptible(sdp->open_wait, + (atomic_read(&sdp->detaching) || + !sdp->exclude)); + mutex_lock(&sdp->open_rel_lock); + + if (retval) /* -ERESTARTSYS */ + return retval; + if (atomic_read(&sdp->detaching)) + return -ENODEV; + } + } - read_lock_irqsave(&sg_index_lock, flags); - ret = list_empty(&sdp->sfds); - read_unlock_irqrestore(&sg_index_lock, flags); - return ret; + return retval; } +/* Returns 0 on success, else a negated errno value */ static int sg_open(struct inode *inode, struct file *filp) { @@ -265,17 +277,17 @@ sg_open(struct inode *inode, struct file *filp) struct request_queue *q; Sg_device *sdp; Sg_fd *sfp; - int res; int retval; nonseekable_open(inode, filp); - SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags)); + if ((flags & O_EXCL) && (O_RDONLY == (flags & O_ACCMODE))) + return -EPERM; /* Can't lock it with read only access */ sdp = sg_get_dev(dev); - if (IS_ERR(sdp)) { - retval = PTR_ERR(sdp); - sdp = NULL; - goto sg_put; - } + if (IS_ERR(sdp)) + return PTR_ERR(sdp); + + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_open: flags=0x%x\n", flags)); /* This driver's module count bumped by fops_get in <linux/fs.h> */ /* Prevent the device driver from vanishing while we sleep */ @@ -287,6 +299,9 @@ sg_open(struct inode *inode, struct file *filp) if (retval) goto sdp_put; + /* scsi_block_when_processing_errors() may block so bypass + * check if O_NONBLOCK. Permits SCSI commands to be issued + * during error recovery. Tread carefully. */ if (!((flags & O_NONBLOCK) || scsi_block_when_processing_errors(sdp->device))) { retval = -ENXIO; @@ -294,65 +309,65 @@ sg_open(struct inode *inode, struct file *filp) goto error_out; } - if (flags & O_EXCL) { - if (O_RDONLY == (flags & O_ACCMODE)) { - retval = -EPERM; /* Can't lock it with read only access */ - goto error_out; - } - if (!sfds_list_empty(sdp) && (flags & O_NONBLOCK)) { - retval = -EBUSY; - goto error_out; - } - res = wait_event_interruptible(sdp->o_excl_wait, - ((!sfds_list_empty(sdp) || get_exclude(sdp)) ? 0 : set_exclude(sdp, 1))); - if (res) { - retval = res; /* -ERESTARTSYS because signal hit process */ - goto error_out; - } - } else if (get_exclude(sdp)) { /* some other fd has an exclusive lock on dev */ - if (flags & O_NONBLOCK) { - retval = -EBUSY; - goto error_out; - } - res = wait_event_interruptible(sdp->o_excl_wait, !get_exclude(sdp)); - if (res) { - retval = res; /* -ERESTARTSYS because signal hit process */ - goto error_out; + mutex_lock(&sdp->open_rel_lock); + if (flags & O_NONBLOCK) { + if (flags & O_EXCL) { + if (sdp->open_cnt > 0) { + retval = -EBUSY; + goto error_mutex_locked; + } + } else { + if (sdp->exclude) { + retval = -EBUSY; + goto error_mutex_locked; + } } + } else { + retval = open_wait(sdp, flags); + if (retval) /* -ERESTARTSYS or -ENODEV */ + goto error_mutex_locked; } - if (sdp->detached) { - retval = -ENODEV; - goto error_out; - } - if (sfds_list_empty(sdp)) { /* no existing opens on this device */ + + /* N.B. at this point we are holding the open_rel_lock */ + if (flags & O_EXCL) + sdp->exclude = true; + + if (sdp->open_cnt < 1) { /* no existing opens */ sdp->sgdebug = 0; q = sdp->device->request_queue; sdp->sg_tablesize = queue_max_segments(q); } - if ((sfp = sg_add_sfp(sdp, dev))) - filp->private_data = sfp; - else { - if (flags & O_EXCL) { - set_exclude(sdp, 0); /* undo if error */ - wake_up_interruptible(&sdp->o_excl_wait); - } - retval = -ENOMEM; - goto error_out; + sfp = sg_add_sfp(sdp); + if (IS_ERR(sfp)) { + retval = PTR_ERR(sfp); + goto out_undo; } + + filp->private_data = sfp; + sdp->open_cnt++; + mutex_unlock(&sdp->open_rel_lock); + retval = 0; -error_out: - if (retval) { - scsi_autopm_put_device(sdp->device); -sdp_put: - scsi_device_put(sdp->device); - } sg_put: - if (sdp) - sg_put_dev(sdp); + kref_put(&sdp->d_ref, sg_device_destroy); return retval; + +out_undo: + if (flags & O_EXCL) { + sdp->exclude = false; /* undo if error */ + wake_up_interruptible(&sdp->open_wait); + } +error_mutex_locked: + mutex_unlock(&sdp->open_rel_lock); +error_out: + scsi_autopm_put_device(sdp->device); +sdp_put: + scsi_device_put(sdp->device); + goto sg_put; } -/* Following function was formerly called 'sg_close' */ +/* Release resources associated with a successful sg_open() + * Returns 0 on success, else a negated errno value */ static int sg_release(struct inode *inode, struct file *filp) { @@ -361,13 +376,22 @@ sg_release(struct inode *inode, struct file *filp) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name)); - - set_exclude(sdp, 0); - wake_up_interruptible(&sdp->o_excl_wait); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, "sg_release\n")); + mutex_lock(&sdp->open_rel_lock); scsi_autopm_put_device(sdp->device); kref_put(&sfp->f_ref, sg_remove_sfp); + sdp->open_cnt--; + + /* possibly many open()s waiting on exlude clearing, start many; + * only open(O_EXCL)s wait on 0==open_cnt so only start one */ + if (sdp->exclude) { + sdp->exclude = false; + wake_up_interruptible_all(&sdp->open_wait); + } else if (0 == sdp->open_cnt) { + wake_up_interruptible(&sdp->open_wait); + } + mutex_unlock(&sdp->open_rel_lock); return 0; } @@ -384,8 +408,8 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_read: %s, count=%d\n", - sdp->disk->disk_name, (int) count)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_read: count=%d\n", (int) count)); if (!access_ok(VERIFY_WRITE, buf, count)) return -EFAULT; @@ -419,7 +443,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) } srp = sg_get_rq_mark(sfp, req_pack_id); if (!srp) { /* now wait on packet to arrive */ - if (sdp->detached) { + if (atomic_read(&sdp->detaching)) { retval = -ENODEV; goto free_old_hdr; } @@ -428,9 +452,9 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) goto free_old_hdr; } retval = wait_event_interruptible(sfp->read_wait, - (sdp->detached || + (atomic_read(&sdp->detaching) || (srp = sg_get_rq_mark(sfp, req_pack_id)))); - if (sdp->detached) { + if (atomic_read(&sdp->detaching)) { retval = -ENODEV; goto free_old_hdr; } @@ -566,13 +590,13 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) Sg_request *srp; struct sg_header old_hdr; sg_io_hdr_t *hp; - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char cmnd[SG_MAX_CDB_SIZE]; if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_write: %s, count=%d\n", - sdp->disk->disk_name, (int) count)); - if (sdp->detached) + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_write: count=%d\n", (int) count)); + if (atomic_read(&sdp->detaching)) return -ENODEV; if (!((filp->f_flags & O_NONBLOCK) || scsi_block_when_processing_errors(sdp->device))) @@ -592,18 +616,13 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) return -EIO; /* The minimum scsi command length is 6 bytes. */ if (!(srp = sg_add_request(sfp))) { - SCSI_LOG_TIMEOUT(1, printk("sg_write: queue full\n")); + SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sdp, + "sg_write: queue full\n")); return -EDOM; } buf += SZ_SG_HEADER; __get_user(opcode, buf); if (sfp->next_cmd_len > 0) { - if (sfp->next_cmd_len > MAX_COMMAND_SIZE) { - SCSI_LOG_TIMEOUT(1, printk("sg_write: command length too long\n")); - sfp->next_cmd_len = 0; - sg_remove_request(sfp, srp); - return -EIO; - } cmd_size = sfp->next_cmd_len; sfp->next_cmd_len = 0; /* reset so only this write() effected */ } else { @@ -611,7 +630,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if ((opcode >= 0xc0) && old_hdr.twelve_byte) cmd_size = 12; } - SCSI_LOG_TIMEOUT(4, printk( + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp, "sg_write: scsi opcode=0x%02x, cmd_size=%d\n", (int) opcode, cmd_size)); /* Determine buffer size. */ input_size = count - cmd_size; @@ -675,7 +694,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, int k; Sg_request *srp; sg_io_hdr_t *hp; - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char cmnd[SG_MAX_CDB_SIZE]; int timeout; unsigned long ul_timeout; @@ -686,7 +705,8 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, sfp->cmd_q = 1; /* when sg_io_hdr seen, set command queuing on */ if (!(srp = sg_add_request(sfp))) { - SCSI_LOG_TIMEOUT(1, printk("sg_new_write: queue full\n")); + SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp, + "sg_new_write: queue full\n")); return -EDOM; } srp->sg_io_owned = sg_io_owned; @@ -743,7 +763,7 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking) { - int k, data_dir; + int k, data_dir, at_head; Sg_device *sdp = sfp->parentdp; sg_io_hdr_t *hp = &srp->header; @@ -755,16 +775,18 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, hp->host_status = 0; hp->driver_status = 0; hp->resid = 0; - SCSI_LOG_TIMEOUT(4, printk("sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n", - (int) cmnd[0], (int) hp->cmd_len)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n", + (int) cmnd[0], (int) hp->cmd_len)); k = sg_start_req(srp, cmnd); if (k) { - SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k)); + SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp, + "sg_common_write: start_req err=%d\n", k)); sg_finish_rem_req(srp); return k; /* probably out of space --> ENOMEM */ } - if (sdp->detached) { + if (atomic_read(&sdp->detaching)) { if (srp->bio) blk_end_request_all(srp->rq, -EIO); sg_finish_rem_req(srp); @@ -787,11 +809,16 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, break; } hp->duration = jiffies_to_msecs(jiffies); + if (hp->interface_id != '\0' && /* v3 (or later) interface */ + (SG_FLAG_Q_AT_TAIL & hp->flags)) + at_head = 0; + else + at_head = 1; srp->rq->timeout = timeout; kref_get(&sfp->f_ref); /* sg_rq_end_io() does kref_put(). */ blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk, - srp->rq, 1, sg_rq_end_io); + srp->rq, at_head, sg_rq_end_io); return 0; } @@ -806,6 +833,15 @@ static int srp_done(Sg_fd *sfp, Sg_request *srp) return ret; } +static int max_sectors_bytes(struct request_queue *q) +{ + unsigned int max_sectors = queue_max_sectors(q); + + max_sectors = min_t(unsigned int, max_sectors, INT_MAX >> 9); + + return max_sectors << 9; +} + static long sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) { @@ -820,13 +856,13 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: %s, cmd=0x%x\n", - sdp->disk->disk_name, (int) cmd_in)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_ioctl: cmd=0x%x\n", (int) cmd_in)); read_only = (O_RDWR != (filp->f_flags & O_ACCMODE)); switch (cmd_in) { case SG_IO: - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; if (!scsi_block_when_processing_errors(sdp->device)) return -ENXIO; @@ -837,8 +873,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) if (result < 0) return result; result = wait_event_interruptible(sfp->read_wait, - (srp_done(sfp, srp) || sdp->detached)); - if (sdp->detached) + (srp_done(sfp, srp) || atomic_read(&sdp->detaching))); + if (atomic_read(&sdp->detaching)) return -ENODEV; write_lock_irq(&sfp->rq_list_lock); if (srp->done) { @@ -873,11 +909,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) sfp->low_dma = 1; if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) { val = (int) sfp->reserve.bufflen; - sg_remove_scat(&sfp->reserve); + sg_remove_scat(sfp, &sfp->reserve); sg_build_reserve(sfp, val); } } else { - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; sfp->low_dma = sdp->device->host->unchecked_isa_dma; } @@ -890,7 +926,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) else { sg_scsi_id_t __user *sg_idp = p; - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; __put_user((int) sdp->device->host->host_no, &sg_idp->host_no); @@ -945,17 +981,17 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) if (val < 0) return -EINVAL; val = min_t(int, val, - queue_max_sectors(sdp->device->request_queue) * 512); + max_sectors_bytes(sdp->device->request_queue)); if (val != sfp->reserve.bufflen) { if (sg_res_in_use(sfp) || sfp->mmap_called) return -EBUSY; - sg_remove_scat(&sfp->reserve); + sg_remove_scat(sfp, &sfp->reserve); sg_build_reserve(sfp, val); } return 0; case SG_GET_RESERVED_SIZE: val = min_t(int, sfp->reserve.bufflen, - queue_max_sectors(sdp->device->request_queue) * 512); + max_sectors_bytes(sdp->device->request_queue)); return put_user(val, ip); case SG_SET_COMMAND_Q: result = get_user(val, ip); @@ -1032,11 +1068,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) return result; } case SG_EMULATED_HOST: - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; return put_user(sdp->device->host->hostt->emulated, ip); case SG_SCSI_RESET: - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; if (filp->f_flags & O_NONBLOCK) { if (scsi_host_in_recovery(sdp->device->host)) @@ -1069,7 +1105,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) return (scsi_reset_provider(sdp->device, val) == SUCCESS) ? 0 : -EIO; case SCSI_IOCTL_SEND_COMMAND: - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; if (read_only) { unsigned char opcode = WRITE_6; @@ -1091,11 +1127,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) case SCSI_IOCTL_GET_BUS_NUMBER: case SCSI_IOCTL_PROBE_HOST: case SG_GET_TRANSFORM: - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; return scsi_ioctl(sdp->device, cmd_in, p); case BLKSECTGET: - return put_user(queue_max_sectors(sdp->device->request_queue) * 512, + return put_user(max_sectors_bytes(sdp->device->request_queue), ip); case BLKTRACESETUP: return blk_trace_setup(sdp->device->request_queue, @@ -1165,15 +1201,15 @@ sg_poll(struct file *filp, poll_table * wait) } read_unlock_irqrestore(&sfp->rq_list_lock, iflags); - if (sdp->detached) + if (atomic_read(&sdp->detaching)) res |= POLLHUP; else if (!sfp->cmd_q) { if (0 == count) res |= POLLOUT | POLLWRNORM; } else if (count < SG_MAX_QUEUE) res |= POLLOUT | POLLWRNORM; - SCSI_LOG_TIMEOUT(3, printk("sg_poll: %s, res=0x%x\n", - sdp->disk->disk_name, (int) res)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_poll: res=0x%x\n", (int) res)); return res; } @@ -1185,8 +1221,8 @@ sg_fasync(int fd, struct file *filp, int mode) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_fasync: %s, mode=%d\n", - sdp->disk->disk_name, mode)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_fasync: mode=%d\n", mode)); return fasync_helper(fd, filp, mode, &sfp->async_qp); } @@ -1205,8 +1241,9 @@ sg_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) offset = vmf->pgoff << PAGE_SHIFT; if (offset >= rsv_schp->bufflen) return VM_FAULT_SIGBUS; - SCSI_LOG_TIMEOUT(3, printk("sg_vma_fault: offset=%lu, scatg=%d\n", - offset, rsv_schp->k_use_sg)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sfp->parentdp, + "sg_vma_fault: offset=%lu, scatg=%d\n", + offset, rsv_schp->k_use_sg)); sa = vma->vm_start; length = 1 << (PAGE_SHIFT + rsv_schp->page_order); for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) { @@ -1241,8 +1278,9 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data))) return -ENXIO; req_sz = vma->vm_end - vma->vm_start; - SCSI_LOG_TIMEOUT(3, printk("sg_mmap starting, vm_start=%p, len=%d\n", - (void *) vma->vm_start, (int) req_sz)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sfp->parentdp, + "sg_mmap starting, vm_start=%p, len=%d\n", + (void *) vma->vm_start, (int) req_sz)); if (vma->vm_pgoff) return -EINVAL; /* want no offset */ rsv_schp = &sfp->reserve; @@ -1264,7 +1302,8 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) return 0; } -static void sg_rq_end_io_usercontext(struct work_struct *work) +static void +sg_rq_end_io_usercontext(struct work_struct *work) { struct sg_request *srp = container_of(work, struct sg_request, ew.work); struct sg_fd *sfp = srp->parentfp; @@ -1277,7 +1316,8 @@ static void sg_rq_end_io_usercontext(struct work_struct *work) * This function is a "bottom half" handler that is called by the mid * level when a command is completed (or has failed). */ -static void sg_rq_end_io(struct request *rq, int uptodate) +static void +sg_rq_end_io(struct request *rq, int uptodate) { struct sg_request *srp = rq->end_io_data; Sg_device *sdp; @@ -1295,15 +1335,16 @@ static void sg_rq_end_io(struct request *rq, int uptodate) return; sdp = sfp->parentdp; - if (unlikely(sdp->detached)) - printk(KERN_INFO "sg_rq_end_io: device detached\n"); + if (unlikely(atomic_read(&sdp->detaching))) + pr_info("%s: device detaching\n", __func__); sense = rq->sense; result = rq->errors; resid = rq->resid_len; - SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n", - sdp->disk->disk_name, srp->header.pack_id, result)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp, + "sg_cmd_done: pack_id=%d, res=0x%x\n", + srp->header.pack_id, result)); srp->header.resid = resid; ms = jiffies_to_msecs(jiffies); srp->header.duration = (ms > srp->header.duration) ? @@ -1319,7 +1360,7 @@ static void sg_rq_end_io(struct request *rq, int uptodate) if ((sdp->sgdebug > 0) && ((CHECK_CONDITION == srp->header.masked_status) || (COMMAND_TERMINATED == srp->header.masked_status))) - __scsi_print_sense("sg_cmd_done", sense, + __scsi_print_sense(__func__, sense, SCSI_SENSE_BUFFERSIZE); /* Following if statement is a patch supplied by Eric Youngdale */ @@ -1378,7 +1419,8 @@ static struct class *sg_sysfs_class; static int sg_sysfs_valid = 0; -static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) +static Sg_device * +sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) { struct request_queue *q = scsidp->request_queue; Sg_device *sdp; @@ -1388,7 +1430,8 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL); if (!sdp) { - printk(KERN_WARNING "kmalloc Sg_device failure\n"); + sdev_printk(KERN_WARNING, scsidp, "%s: kmalloc Sg_device " + "failure\n", __func__); return ERR_PTR(-ENOMEM); } @@ -1403,20 +1446,25 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) scsidp->type, SG_MAX_DEVS - 1); error = -ENODEV; } else { - printk(KERN_WARNING - "idr allocation Sg_device failure: %d\n", error); + sdev_printk(KERN_WARNING, scsidp, "%s: idr " + "allocation Sg_device failure: %d\n", + __func__, error); } goto out_unlock; } k = error; - SCSI_LOG_TIMEOUT(3, printk("sg_alloc: dev=%d \n", k)); + SCSI_LOG_TIMEOUT(3, sdev_printk(KERN_INFO, scsidp, + "sg_alloc: dev=%d \n", k)); sprintf(disk->disk_name, "sg%d", k); disk->first_minor = k; sdp->disk = disk; sdp->device = scsidp; + mutex_init(&sdp->open_rel_lock); INIT_LIST_HEAD(&sdp->sfds); - init_waitqueue_head(&sdp->o_excl_wait); + init_waitqueue_head(&sdp->open_wait); + atomic_set(&sdp->detaching, 0); + rwlock_init(&sdp->sfd_lock); sdp->sg_tablesize = queue_max_segments(q); sdp->index = k; kref_init(&sdp->d_ref); @@ -1434,7 +1482,7 @@ out_unlock: } static int -sg_add(struct device *cl_dev, struct class_interface *cl_intf) +sg_add_device(struct device *cl_dev, struct class_interface *cl_intf) { struct scsi_device *scsidp = to_scsi_device(cl_dev->parent); struct gendisk *disk; @@ -1445,7 +1493,7 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf) disk = alloc_disk(1); if (!disk) { - printk(KERN_WARNING "alloc_disk failed\n"); + pr_warn("%s: alloc_disk failed\n", __func__); return -ENOMEM; } disk->major = SCSI_GENERIC_MAJOR; @@ -1453,7 +1501,7 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf) error = -ENOMEM; cdev = cdev_alloc(); if (!cdev) { - printk(KERN_WARNING "cdev_alloc failed\n"); + pr_warn("%s: cdev_alloc failed\n", __func__); goto out; } cdev->owner = THIS_MODULE; @@ -1461,7 +1509,7 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf) sdp = sg_alloc(disk, scsidp); if (IS_ERR(sdp)) { - printk(KERN_WARNING "sg_alloc failed\n"); + pr_warn("%s: sg_alloc failed\n", __func__); error = PTR_ERR(sdp); goto out; } @@ -1479,22 +1527,20 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf) sdp->index), sdp, "%s", disk->disk_name); if (IS_ERR(sg_class_member)) { - printk(KERN_ERR "sg_add: " - "device_create failed\n"); + pr_err("%s: device_create failed\n", __func__); error = PTR_ERR(sg_class_member); goto cdev_add_err; } error = sysfs_create_link(&scsidp->sdev_gendev.kobj, &sg_class_member->kobj, "generic"); if (error) - printk(KERN_ERR "sg_add: unable to make symlink " - "'generic' back to sg%d\n", sdp->index); + pr_err("%s: unable to make symlink 'generic' back " + "to sg%d\n", __func__, sdp->index); } else - printk(KERN_WARNING "sg_add: sg_sys Invalid\n"); + pr_warn("%s: sg_sys Invalid\n", __func__); - sdev_printk(KERN_NOTICE, scsidp, - "Attached scsi generic sg%d type %d\n", sdp->index, - scsidp->type); + sdev_printk(KERN_NOTICE, scsidp, "Attached scsi generic sg%d " + "type %d\n", sdp->index, scsidp->type); dev_set_drvdata(cl_dev, sdp); @@ -1513,7 +1559,8 @@ out: return error; } -static void sg_device_destroy(struct kref *kref) +static void +sg_device_destroy(struct kref *kref) { struct sg_device *sdp = container_of(kref, struct sg_device, d_ref); unsigned long flags; @@ -1528,40 +1575,45 @@ static void sg_device_destroy(struct kref *kref) write_unlock_irqrestore(&sg_index_lock, flags); SCSI_LOG_TIMEOUT(3, - printk("sg_device_destroy: %s\n", - sdp->disk->disk_name)); + sg_printk(KERN_INFO, sdp, "sg_device_destroy\n")); put_disk(sdp->disk); kfree(sdp); } -static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf) +static void +sg_remove_device(struct device *cl_dev, struct class_interface *cl_intf) { struct scsi_device *scsidp = to_scsi_device(cl_dev->parent); Sg_device *sdp = dev_get_drvdata(cl_dev); unsigned long iflags; Sg_fd *sfp; + int val; - if (!sdp || sdp->detached) + if (!sdp) return; + /* want sdp->detaching non-zero as soon as possible */ + val = atomic_inc_return(&sdp->detaching); + if (val > 1) + return; /* only want to do following once per device */ - SCSI_LOG_TIMEOUT(3, printk("sg_remove: %s\n", sdp->disk->disk_name)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "%s\n", __func__)); - /* Need a write lock to set sdp->detached. */ - write_lock_irqsave(&sg_index_lock, iflags); - sdp->detached = 1; + read_lock_irqsave(&sdp->sfd_lock, iflags); list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) { - wake_up_interruptible(&sfp->read_wait); + wake_up_interruptible_all(&sfp->read_wait); kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP); } - write_unlock_irqrestore(&sg_index_lock, iflags); + wake_up_interruptible_all(&sdp->open_wait); + read_unlock_irqrestore(&sdp->sfd_lock, iflags); sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index)); cdev_del(sdp->cdev); sdp->cdev = NULL; - sg_put_dev(sdp); + kref_put(&sdp->d_ref, sg_device_destroy); } module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR); @@ -1631,7 +1683,8 @@ exit_sg(void) idr_destroy(&sg_index_idr); } -static int sg_start_req(Sg_request *srp, unsigned char *cmd) +static int +sg_start_req(Sg_request *srp, unsigned char *cmd) { int res; struct request *rq; @@ -1645,15 +1698,28 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) struct request_queue *q = sfp->parentdp->device->request_queue; struct rq_map_data *md, map_data; int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ; + unsigned char *long_cmdp = NULL; - SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n", - dxfer_len)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_start_req: dxfer_len=%d\n", + dxfer_len)); + + if (hp->cmd_len > BLK_MAX_CDB) { + long_cmdp = kzalloc(hp->cmd_len, GFP_KERNEL); + if (!long_cmdp) + return -ENOMEM; + } rq = blk_get_request(q, rw, GFP_ATOMIC); - if (!rq) + if (!rq) { + kfree(long_cmdp); return -ENOMEM; + } blk_rq_set_block_pc(rq); + + if (hp->cmd_len > BLK_MAX_CDB) + rq->cmd = long_cmdp; memcpy(rq->cmd, cmd, hp->cmd_len); rq->cmd_len = hp->cmd_len; @@ -1726,25 +1792,30 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) return res; } -static int sg_finish_rem_req(Sg_request * srp) +static int +sg_finish_rem_req(Sg_request *srp) { int ret = 0; Sg_fd *sfp = srp->parentfp; Sg_scatter_hold *req_schp = &srp->data; - SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n", (int) srp->res_used)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_finish_rem_req: res_used=%d\n", + (int) srp->res_used)); if (srp->rq) { if (srp->bio) ret = blk_rq_unmap_user(srp->bio); + if (srp->rq->cmd != srp->rq->__cmd) + kfree(srp->rq->cmd); blk_put_request(srp->rq); } if (srp->res_used) sg_unlink_reserve(sfp, srp); else - sg_remove_scat(req_schp); + sg_remove_scat(sfp, req_schp); sg_remove_request(sfp, srp); @@ -1778,8 +1849,9 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) ++blk_size; /* don't know why */ /* round request up to next highest SG_SECTOR_SZ byte boundary */ blk_size = ALIGN(blk_size, SG_SECTOR_SZ); - SCSI_LOG_TIMEOUT(4, printk("sg_build_indirect: buff_size=%d, blk_size=%d\n", - buff_size, blk_size)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_build_indirect: buff_size=%d, blk_size=%d\n", + buff_size, blk_size)); /* N.B. ret_sz carried into this block ... */ mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize); @@ -1822,14 +1894,16 @@ retry: } } - SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, " - "ret_sz=%d\n", k, num, ret_sz)); + SCSI_LOG_TIMEOUT(5, sg_printk(KERN_INFO, sfp->parentdp, + "sg_build_indirect: k=%d, num=%d, ret_sz=%d\n", + k, num, ret_sz)); } /* end of for loop */ schp->page_order = order; schp->k_use_sg = k; - SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, " - "rem_sz=%d\n", k, rem_sz)); + SCSI_LOG_TIMEOUT(5, sg_printk(KERN_INFO, sfp->parentdp, + "sg_build_indirect: k_use_sg=%d, rem_sz=%d\n", + k, rem_sz)); schp->bufflen = blk_size; if (rem_sz > 0) /* must have failed */ @@ -1846,17 +1920,19 @@ out: } static void -sg_remove_scat(Sg_scatter_hold * schp) +sg_remove_scat(Sg_fd * sfp, Sg_scatter_hold * schp) { - SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg)); if (schp->pages && schp->sglist_len > 0) { if (!schp->dio_in_use) { int k; for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) { - SCSI_LOG_TIMEOUT(5, printk( - "sg_remove_scat: k=%d, pg=0x%p\n", - k, schp->pages[k])); + SCSI_LOG_TIMEOUT(5, + sg_printk(KERN_INFO, sfp->parentdp, + "sg_remove_scat: k=%d, pg=0x%p\n", + k, schp->pages[k])); __free_pages(schp->pages[k], schp->page_order); } @@ -1872,8 +1948,9 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer) Sg_scatter_hold *schp = &srp->data; int k, num; - SCSI_LOG_TIMEOUT(4, printk("sg_read_oxfer: num_read_xfer=%d\n", - num_read_xfer)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, srp->parentfp->parentdp, + "sg_read_oxfer: num_read_xfer=%d\n", + num_read_xfer)); if ((!outp) || (num_read_xfer <= 0)) return 0; @@ -1903,14 +1980,15 @@ sg_build_reserve(Sg_fd * sfp, int req_size) { Sg_scatter_hold *schp = &sfp->reserve; - SCSI_LOG_TIMEOUT(4, printk("sg_build_reserve: req_size=%d\n", req_size)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_build_reserve: req_size=%d\n", req_size)); do { if (req_size < PAGE_SIZE) req_size = PAGE_SIZE; if (0 == sg_build_indirect(schp, sfp, req_size)) return; else - sg_remove_scat(schp); + sg_remove_scat(sfp, schp); req_size >>= 1; /* divide by 2 */ } while (req_size > (PAGE_SIZE / 2)); } @@ -1923,7 +2001,8 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) int k, num, rem; srp->res_used = 1; - SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_link_reserve: size=%d\n", size)); rem = size; num = 1 << (PAGE_SHIFT + rsv_schp->page_order); @@ -1941,7 +2020,8 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) } if (k >= rsv_schp->k_use_sg) - SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n")); + SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp, + "sg_link_reserve: BAD size\n")); } static void @@ -1949,8 +2029,9 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp) { Sg_scatter_hold *req_schp = &srp->data; - SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n", - (int) req_schp->k_use_sg)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, srp->parentfp->parentdp, + "sg_unlink_reserve: req->k_use_sg=%d\n", + (int) req_schp->k_use_sg)); req_schp->k_use_sg = 0; req_schp->bufflen = 0; req_schp->pages = NULL; @@ -2055,7 +2136,7 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp) } static Sg_fd * -sg_add_sfp(Sg_device * sdp, int dev) +sg_add_sfp(Sg_device * sdp) { Sg_fd *sfp; unsigned long iflags; @@ -2063,7 +2144,7 @@ sg_add_sfp(Sg_device * sdp, int dev) sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN); if (!sfp) - return NULL; + return ERR_PTR(-ENOMEM); init_waitqueue_head(&sfp->read_wait); rwlock_init(&sfp->rq_list_lock); @@ -2077,25 +2158,33 @@ sg_add_sfp(Sg_device * sdp, int dev) sfp->cmd_q = SG_DEF_COMMAND_Q; sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; sfp->parentdp = sdp; - write_lock_irqsave(&sg_index_lock, iflags); + write_lock_irqsave(&sdp->sfd_lock, iflags); + if (atomic_read(&sdp->detaching)) { + write_unlock_irqrestore(&sdp->sfd_lock, iflags); + return ERR_PTR(-ENODEV); + } list_add_tail(&sfp->sfd_siblings, &sdp->sfds); - write_unlock_irqrestore(&sg_index_lock, iflags); - SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp)); + write_unlock_irqrestore(&sdp->sfd_lock, iflags); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_add_sfp: sfp=0x%p\n", sfp)); if (unlikely(sg_big_buff != def_reserved_size)) sg_big_buff = def_reserved_size; bufflen = min_t(int, sg_big_buff, - queue_max_sectors(sdp->device->request_queue) * 512); + max_sectors_bytes(sdp->device->request_queue)); sg_build_reserve(sfp, bufflen); - SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n", - sfp->reserve.bufflen, sfp->reserve.k_use_sg)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_add_sfp: bufflen=%d, k_use_sg=%d\n", + sfp->reserve.bufflen, + sfp->reserve.k_use_sg)); kref_get(&sdp->d_ref); __module_get(THIS_MODULE); return sfp; } -static void sg_remove_sfp_usercontext(struct work_struct *work) +static void +sg_remove_sfp_usercontext(struct work_struct *work) { struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work); struct sg_device *sdp = sfp->parentdp; @@ -2105,34 +2194,32 @@ static void sg_remove_sfp_usercontext(struct work_struct *work) sg_finish_rem_req(sfp->headrp); if (sfp->reserve.bufflen > 0) { - SCSI_LOG_TIMEOUT(6, - printk("sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", + SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp, + "sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", (int) sfp->reserve.bufflen, (int) sfp->reserve.k_use_sg)); - sg_remove_scat(&sfp->reserve); + sg_remove_scat(sfp, &sfp->reserve); } - SCSI_LOG_TIMEOUT(6, - printk("sg_remove_sfp: %s, sfp=0x%p\n", - sdp->disk->disk_name, - sfp)); + SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp, + "sg_remove_sfp: sfp=0x%p\n", sfp)); kfree(sfp); scsi_device_put(sdp->device); - sg_put_dev(sdp); + kref_put(&sdp->d_ref, sg_device_destroy); module_put(THIS_MODULE); } -static void sg_remove_sfp(struct kref *kref) +static void +sg_remove_sfp(struct kref *kref) { struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref); struct sg_device *sdp = sfp->parentdp; unsigned long iflags; - write_lock_irqsave(&sg_index_lock, iflags); + write_lock_irqsave(&sdp->sfd_lock, iflags); list_del(&sfp->sfd_siblings); - write_unlock_irqrestore(&sg_index_lock, iflags); - wake_up_interruptible(&sdp->o_excl_wait); + write_unlock_irqrestore(&sdp->sfd_lock, iflags); INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext); schedule_work(&sfp->ew.work); @@ -2183,7 +2270,8 @@ static Sg_device *sg_lookup_dev(int dev) return idr_find(&sg_index_idr, dev); } -static Sg_device *sg_get_dev(int dev) +static Sg_device * +sg_get_dev(int dev) { struct sg_device *sdp; unsigned long flags; @@ -2192,8 +2280,8 @@ static Sg_device *sg_get_dev(int dev) sdp = sg_lookup_dev(dev); if (!sdp) sdp = ERR_PTR(-ENXIO); - else if (sdp->detached) { - /* If sdp->detached, then the refcount may already be 0, in + else if (atomic_read(&sdp->detaching)) { + /* If sdp->detaching, then the refcount may already be 0, in * which case it would be a bug to do kref_get(). */ sdp = ERR_PTR(-ENODEV); @@ -2204,11 +2292,6 @@ static Sg_device *sg_get_dev(int dev) return sdp; } -static void sg_put_dev(struct sg_device *sdp) -{ - kref_put(&sdp->d_ref, sg_device_destroy); -} - #ifdef CONFIG_SCSI_PROC_FS static struct proc_dir_entry *sg_proc_sgp = NULL; @@ -2425,8 +2508,7 @@ static int sg_proc_single_open_version(struct inode *inode, struct file *file) static int sg_proc_seq_show_devhdr(struct seq_file *s, void *v) { - seq_printf(s, "host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\t" - "online\n"); + seq_puts(s, "host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\tonline\n"); return 0; } @@ -2482,16 +2564,19 @@ static int sg_proc_seq_show_dev(struct seq_file *s, void *v) read_lock_irqsave(&sg_index_lock, iflags); sdp = it ? sg_lookup_dev(it->index) : NULL; - if (sdp && (scsidp = sdp->device) && (!sdp->detached)) - seq_printf(s, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", + if ((NULL == sdp) || (NULL == sdp->device) || + (atomic_read(&sdp->detaching))) + seq_puts(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n"); + else { + scsidp = sdp->device; + seq_printf(s, "%d\t%d\t%d\t%llu\t%d\t%d\t%d\t%d\t%d\n", scsidp->host->host_no, scsidp->channel, scsidp->id, scsidp->lun, (int) scsidp->type, 1, (int) scsidp->queue_depth, - (int) scsidp->device_busy, + (int) atomic_read(&scsidp->device_busy), (int) scsi_device_online(scsidp)); - else - seq_printf(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n"); + } read_unlock_irqrestore(&sg_index_lock, iflags); return 0; } @@ -2510,11 +2595,12 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v) read_lock_irqsave(&sg_index_lock, iflags); sdp = it ? sg_lookup_dev(it->index) : NULL; - if (sdp && (scsidp = sdp->device) && (!sdp->detached)) + scsidp = sdp ? sdp->device : NULL; + if (sdp && scsidp && (!atomic_read(&sdp->detaching))) seq_printf(s, "%8.8s\t%16.16s\t%4.4s\n", scsidp->vendor, scsidp->model, scsidp->rev); else - seq_printf(s, "<no active device>\n"); + seq_puts(s, "<no active device>\n"); read_unlock_irqrestore(&sg_index_lock, iflags); return 0; } @@ -2559,12 +2645,12 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) else cp = " "; } - seq_printf(s, cp); + seq_puts(s, cp); blen = srp->data.bufflen; usg = srp->data.k_use_sg; - seq_printf(s, srp->done ? - ((1 == srp->done) ? "rcv:" : "fin:") - : "act:"); + seq_puts(s, srp->done ? + ((1 == srp->done) ? "rcv:" : "fin:") + : "act:"); seq_printf(s, " id=%d blen=%d", srp->header.pack_id, blen); if (srp->done) @@ -2580,7 +2666,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) (int) srp->data.cmd_opcode); } if (0 == m) - seq_printf(s, " No requests active\n"); + seq_puts(s, " No requests active\n"); read_unlock(&fp->rq_list_lock); } } @@ -2596,31 +2682,34 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v) Sg_device *sdp; unsigned long iflags; - if (it && (0 == it->index)) { - seq_printf(s, "max_active_device=%d(origin 1)\n", - (int)it->max); - seq_printf(s, " def_reserved_size=%d\n", sg_big_buff); - } + if (it && (0 == it->index)) + seq_printf(s, "max_active_device=%d def_reserved_size=%d\n", + (int)it->max, sg_big_buff); read_lock_irqsave(&sg_index_lock, iflags); sdp = it ? sg_lookup_dev(it->index) : NULL; - if (sdp && !list_empty(&sdp->sfds)) { - struct scsi_device *scsidp = sdp->device; - + if (NULL == sdp) + goto skip; + read_lock(&sdp->sfd_lock); + if (!list_empty(&sdp->sfds)) { seq_printf(s, " >>> device=%s ", sdp->disk->disk_name); - if (sdp->detached) - seq_printf(s, "detached pending close "); - else - seq_printf - (s, "scsi%d chan=%d id=%d lun=%d em=%d", - scsidp->host->host_no, - scsidp->channel, scsidp->id, - scsidp->lun, - scsidp->host->hostt->emulated); - seq_printf(s, " sg_tablesize=%d excl=%d\n", - sdp->sg_tablesize, get_exclude(sdp)); + if (atomic_read(&sdp->detaching)) + seq_puts(s, "detaching pending close "); + else if (sdp->device) { + struct scsi_device *scsidp = sdp->device; + + seq_printf(s, "%d:%d:%d:%llu em=%d", + scsidp->host->host_no, + scsidp->channel, scsidp->id, + scsidp->lun, + scsidp->host->hostt->emulated); + } + seq_printf(s, " sg_tablesize=%d excl=%d open_cnt=%d\n", + sdp->sg_tablesize, sdp->exclude, sdp->open_cnt); sg_proc_debug_helper(s, sdp); } + read_unlock(&sdp->sfd_lock); +skip: read_unlock_irqrestore(&sg_index_lock, iflags); return 0; } diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 93cbd36..7eeb936 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -292,8 +292,8 @@ do_tur: if (!cd->tur_changed) { if (cd->get_event_changed) { if (cd->tur_mismatch++ > 8) { - sdev_printk(KERN_WARNING, cd->device, - "GET_EVENT and TUR disagree continuously, suppress GET_EVENT events\n"); + sr_printk(KERN_WARNING, cd, + "GET_EVENT and TUR disagree continuously, suppress GET_EVENT events\n"); cd->ignore_get_event = true; } } else { @@ -322,7 +322,7 @@ static int sr_done(struct scsi_cmnd *SCpnt) struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk); #ifdef DEBUG - printk("sr.c done: %x\n", result); + scmd_printk(KERN_INFO, SCpnt, "done: %x\n", result); #endif /* @@ -385,10 +385,9 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) int block = 0, this_count, s_size; struct scsi_cd *cd; struct request *rq = SCpnt->request; - struct scsi_device *sdp = SCpnt->device; int ret; - ret = scsi_setup_fs_cmnd(sdp, rq); + ret = scsi_init_io(SCpnt, GFP_ATOMIC); if (ret != BLKPREP_OK) goto out; SCpnt = rq->special; @@ -398,13 +397,14 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) * is used for a killable error condition */ ret = BLKPREP_KILL; - SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n", - cd->disk->disk_name, block)); + SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt, + "Doing sr request, block = %d\n", block)); if (!cd->device || !scsi_device_online(cd->device)) { - SCSI_LOG_HLQUEUE(2, printk("Finishing %u sectors\n", - blk_rq_sectors(rq))); - SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + "Finishing %u sectors\n", blk_rq_sectors(rq))); + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + "Retry with 0x%p\n", SCpnt)); goto out; } @@ -425,7 +425,8 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) if (!in_interrupt()) sr_set_blocklength(cd, 2048); else - printk("sr: can't switch blocksize: in interrupt\n"); + scmd_printk(KERN_INFO, SCpnt, + "can't switch blocksize: in interrupt\n"); } if (s_size != 512 && s_size != 1024 && s_size != 2048) { @@ -434,14 +435,12 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) } if (rq_data_dir(rq) == WRITE) { - if (!cd->device->writeable) + if (!cd->writeable) goto out; SCpnt->cmnd[0] = WRITE_10; - SCpnt->sc_data_direction = DMA_TO_DEVICE; - cd->cdi.media_written = 1; + cd->cdi.media_written = 1; } else if (rq_data_dir(rq) == READ) { SCpnt->cmnd[0] = READ_10; - SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { blk_dump_rq_flags(rq, "Unknown sr command"); goto out; @@ -475,11 +474,11 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) this_count = (scsi_bufflen(SCpnt) >> 9) / (s_size >> 9); - SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%u 512 byte blocks.\n", - cd->cdi.name, - (rq_data_dir(rq) == WRITE) ? + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + "%s %d/%u 512 byte blocks.\n", + (rq_data_dir(rq) == WRITE) ? "writing" : "reading", - this_count, blk_rq_sectors(rq))); + this_count, blk_rq_sectors(rq))); SCpnt->cmnd[1] = 0; block = (unsigned int)blk_rq_pos(rq) / (s_size >> 9); @@ -810,8 +809,8 @@ static void get_sectorsize(struct scsi_cd *cd) case 512: break; default: - printk("%s: unsupported sector size %d.\n", - cd->cdi.name, sector_size); + sr_printk(KERN_INFO, cd, + "unsupported sector size %d.", sector_size); cd->capacity = 0; } @@ -853,7 +852,7 @@ static void get_capabilities(struct scsi_cd *cd) /* allocate transfer buffer */ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) { - printk(KERN_ERR "sr: out of memory.\n"); + sr_printk(KERN_ERR, cd, "out of memory.\n"); return; } @@ -872,7 +871,7 @@ static void get_capabilities(struct scsi_cd *cd) CDC_SELECT_DISC | CDC_SELECT_SPEED | CDC_MRW | CDC_MRW_W | CDC_RAM); kfree(buffer); - printk("%s: scsi-1 drive\n", cd->cdi.name); + sr_printk(KERN_INFO, cd, "scsi-1 drive"); return; } @@ -881,22 +880,23 @@ static void get_capabilities(struct scsi_cd *cd) cd->readcd_known = 1; cd->readcd_cdda = buffer[n + 5] & 0x01; /* print some capability bits */ - printk("%s: scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", cd->cdi.name, - ((buffer[n + 14] << 8) + buffer[n + 15]) / 176, - cd->cdi.speed, - buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */ - buffer[n + 3] & 0x20 ? "dvd-ram " : "", - buffer[n + 2] & 0x02 ? "cd/rw " : "", /* can read rewriteable */ - buffer[n + 4] & 0x20 ? "xa/form2 " : "", /* can read xa/from2 */ - buffer[n + 5] & 0x01 ? "cdda " : "", /* can read audio data */ - loadmech[buffer[n + 6] >> 5]); + sr_printk(KERN_INFO, cd, + "scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", + ((buffer[n + 14] << 8) + buffer[n + 15]) / 176, + cd->cdi.speed, + buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */ + buffer[n + 3] & 0x20 ? "dvd-ram " : "", + buffer[n + 2] & 0x02 ? "cd/rw " : "", /* can read rewriteable */ + buffer[n + 4] & 0x20 ? "xa/form2 " : "", /* can read xa/from2 */ + buffer[n + 5] & 0x01 ? "cdda " : "", /* can read audio data */ + loadmech[buffer[n + 6] >> 5]); if ((buffer[n + 6] >> 5) == 0) /* caddy drives can't close tray... */ cd->cdi.mask |= CDC_CLOSE_TRAY; if ((buffer[n + 2] & 0x8) == 0) /* not a DVD drive */ cd->cdi.mask |= CDC_DVD; - if ((buffer[n + 3] & 0x20) == 0) + if ((buffer[n + 3] & 0x20) == 0) /* can't write DVD-RAM media */ cd->cdi.mask |= CDC_DVD_RAM; if ((buffer[n + 3] & 0x10) == 0) @@ -927,7 +927,7 @@ static void get_capabilities(struct scsi_cd *cd) */ if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) != (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) { - cd->device->writeable = 1; + cd->writeable = 1; } kfree(buffer); @@ -935,7 +935,7 @@ static void get_capabilities(struct scsi_cd *cd) /* * sr_packet() is the entry point for the generic commands generated - * by the Uniform CD-ROM layer. + * by the Uniform CD-ROM layer. */ static int sr_packet(struct cdrom_device_info *cdi, struct packet_command *cgc) diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h index 37c8f6b..1d1f6f41 100644 --- a/drivers/scsi/sr.h +++ b/drivers/scsi/sr.h @@ -36,6 +36,7 @@ typedef struct scsi_cd { struct scsi_device *device; unsigned int vendor; /* vendor code, see sr_vendor.c */ unsigned long ms_offset; /* for reading multisession-CD's */ + unsigned writeable : 1; unsigned use:1; /* is this device still supportable */ unsigned xa_flag:1; /* CD has XA sectors ? */ unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */ @@ -55,6 +56,10 @@ typedef struct scsi_cd { struct gendisk *disk; } Scsi_CD; +#define sr_printk(prefix, cd, fmt, a...) \ + sdev_printk(prefix, (cd)->device, "[%s] " fmt, \ + (cd)->cdi.name, ##a) + int sr_do_ioctl(Scsi_CD *, struct packet_command *); int sr_lock_door(struct cdrom_device_info *, int); diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index a3911c3..6389fcf 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -36,7 +36,6 @@ module_param(xa_test, int, S_IRUGO | S_IWUSR); * the status of the unchecked_isa_dma flag in the host structure */ #define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0) - static int sr_read_tochdr(struct cdrom_device_info *cdi, struct cdrom_tochdr *tochdr) { @@ -219,7 +218,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) case UNIT_ATTENTION: SDev->changed = 1; if (!cgc->quiet) - printk(KERN_INFO "%s: disc change detected.\n", cd->cdi.name); + sr_printk(KERN_INFO, cd, + "disc change detected.\n"); if (retries++ < 10) goto retry; err = -ENOMEDIUM; @@ -229,7 +229,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) sshdr.ascq == 0x01) { /* sense: Logical unit is in process of becoming ready */ if (!cgc->quiet) - printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name); + sr_printk(KERN_INFO, cd, + "CDROM not ready yet.\n"); if (retries++ < 10) { /* sleep 2 sec and try again */ ssleep(2); @@ -241,7 +242,9 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) } } if (!cgc->quiet) - printk(KERN_INFO "%s: CDROM not ready. Make sure there is a disc in the drive.\n", cd->cdi.name); + sr_printk(KERN_INFO, cd, + "CDROM not ready. Make sure there " + "is a disc in the drive.\n"); #ifdef DEBUG scsi_print_sense_hdr("sr", &sshdr); #endif @@ -259,7 +262,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) #endif break; default: - printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name); + sr_printk(KERN_ERR, cd, + "CDROM (ioctl) error, command: "); __scsi_print_command(cgc->cmd); scsi_print_sense_hdr("sr", &sshdr); err = -EIO; @@ -491,8 +495,8 @@ static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int struct packet_command cgc; #ifdef DEBUG - printk("%s: sr_read_cd lba=%d format=%d blksize=%d\n", - cd->cdi.name, lba, format, blksize); + sr_printk(KERN_INFO, cd, "sr_read_cd lba=%d format=%d blksize=%d\n", + lba, format, blksize); #endif memset(&cgc, 0, sizeof(struct packet_command)); @@ -539,7 +543,8 @@ static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest if (-EDRIVE_CANT_DO_THIS != rc) return rc; cd->readcd_known = 0; - printk("CDROM does'nt support READ CD (0xbe) command\n"); + sr_printk(KERN_INFO, cd, + "CDROM does'nt support READ CD (0xbe) command\n"); /* fall & retry the other way */ } /* ... if this fails, we switch the blocksize using MODE SELECT */ @@ -548,7 +553,8 @@ static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest return rc; } #ifdef DEBUG - printk("%s: sr_read_sector lba=%d blksize=%d\n", cd->cdi.name, lba, blksize); + sr_printk(KERN_INFO, cd, "sr_read_sector lba=%d blksize=%d\n", + lba, blksize); #endif memset(&cgc, 0, sizeof(struct packet_command)); @@ -592,7 +598,7 @@ int sr_is_xa(Scsi_CD *cd) } kfree(raw_sector); #ifdef DEBUG - printk("%s: sr_is_xa: %d\n", cd->cdi.name, is_xa); + sr_printk(KERN_INFO, cd, "sr_is_xa: %d\n", is_xa); #endif return is_xa; } diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c index 92cc2ef..11a238c 100644 --- a/drivers/scsi/sr_vendor.c +++ b/drivers/scsi/sr_vendor.c @@ -123,7 +123,7 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength) return -ENOMEM; #ifdef DEBUG - printk("%s: MODE SELECT 0x%x/%d\n", cd->cdi.name, density, blocklength); + sr_printk(KERN_INFO, cd, "MODE SELECT 0x%x/%d\n", density, blocklength); #endif memset(&cgc, 0, sizeof(struct packet_command)); cgc.cmd[0] = MODE_SELECT; @@ -144,8 +144,9 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength) } #ifdef DEBUG else - printk("%s: switching blocklength to %d bytes failed\n", - cd->cdi.name, blocklength); + sr_printk(KERN_INFO, cd, + "switching blocklength to %d bytes failed\n", + blocklength); #endif kfree(buffer); return rc; @@ -190,8 +191,8 @@ int sr_cd_check(struct cdrom_device_info *cdi) if (rc != 0) break; if ((buffer[0] << 8) + buffer[1] < 0x0a) { - printk(KERN_INFO "%s: Hmm, seems the drive " - "doesn't support multisession CD's\n", cd->cdi.name); + sr_printk(KERN_INFO, cd, "Hmm, seems the drive " + "doesn't support multisession CD's\n"); no_multi = 1; break; } @@ -218,9 +219,9 @@ int sr_cd_check(struct cdrom_device_info *cdi) if (rc != 0) break; if (buffer[14] != 0 && buffer[14] != 0xb0) { - printk(KERN_INFO "%s: Hmm, seems the cdrom " - "doesn't support multisession CD's\n", - cd->cdi.name); + sr_printk(KERN_INFO, cd, "Hmm, seems the cdrom " + "doesn't support multisession CD's\n"); + no_multi = 1; break; } @@ -245,9 +246,8 @@ int sr_cd_check(struct cdrom_device_info *cdi) cgc.timeout = VENDOR_TIMEOUT; rc = sr_do_ioctl(cd, &cgc); if (rc == -EINVAL) { - printk(KERN_INFO "%s: Hmm, seems the drive " - "doesn't support multisession CD's\n", - cd->cdi.name); + sr_printk(KERN_INFO, cd, "Hmm, seems the drive " + "doesn't support multisession CD's\n"); no_multi = 1; break; } @@ -277,8 +277,8 @@ int sr_cd_check(struct cdrom_device_info *cdi) break; } if ((rc = buffer[2]) == 0) { - printk(KERN_WARNING - "%s: No finished session\n", cd->cdi.name); + sr_printk(KERN_WARNING, cd, + "No finished session\n"); break; } cgc.cmd[0] = READ_TOC; /* Read TOC */ @@ -301,9 +301,9 @@ int sr_cd_check(struct cdrom_device_info *cdi) default: /* should not happen */ - printk(KERN_WARNING - "%s: unknown vendor code (%i), not initialized ?\n", - cd->cdi.name, cd->vendor); + sr_printk(KERN_WARNING, cd, + "unknown vendor code (%i), not initialized ?\n", + cd->vendor); sector = 0; no_multi = 1; break; @@ -321,8 +321,8 @@ int sr_cd_check(struct cdrom_device_info *cdi) #ifdef DEBUG if (sector) - printk(KERN_DEBUG "%s: multisession offset=%lu\n", - cd->cdi.name, sector); + sr_printk(KERN_DEBUG, cd, "multisession offset=%lu\n", + sector); #endif kfree(buffer); return rc; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 14eb4b2..aff9689 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -58,11 +58,11 @@ static const char *verstr = "20101219"; is defined and non-zero. */ #define DEBUG 0 +#define ST_DEB_MSG KERN_NOTICE #if DEBUG /* The message level for the debug messages is currently set to KERN_NOTICE so that people can easily see the messages. Later when the debugging messages in the drivers are more widely classified, this may be changed to KERN_DEBUG. */ -#define ST_DEB_MSG KERN_NOTICE #define DEB(a) a #define DEBC(a) if (debugging) { a ; } #else @@ -305,6 +305,15 @@ static inline char *tape_name(struct scsi_tape *tape) return tape->disk->disk_name; } +#define st_printk(prefix, t, fmt, a...) \ + sdev_printk(prefix, (t)->device, "%s: " fmt, \ + tape_name(t), ##a) +#ifdef DEBUG +#define DEBC_printk(t, fmt, a...) \ + if (debugging) { st_printk(ST_DEB_MSG, t, fmt, ##a ); } +#else +#define DEBC_printk(t, fmt, a...) +#endif static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s) { @@ -358,21 +367,20 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) else scode = 0; - DEB( - if (debugging) { - printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n", - name, result, - SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2], - SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]); + DEB( + if (debugging) { + st_printk(ST_DEB_MSG, STp, + "Error: %x, cmd: %x %x %x %x %x %x\n", result, + SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2], + SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]); if (cmdstatp->have_sense) __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE); } ) /* end DEB */ if (!debugging) { /* Abnormal conditions for tape */ if (!cmdstatp->have_sense) - printk(KERN_WARNING - "%s: Error %x (driver bt 0x%x, host bt 0x%x).\n", - name, result, driver_byte(result), - host_byte(result)); + st_printk(KERN_WARNING, STp, + "Error %x (driver bt 0x%x, host bt 0x%x).\n", + result, driver_byte(result), host_byte(result)); else if (cmdstatp->have_sense && scode != NO_SENSE && scode != RECOVERED_ERROR && @@ -411,7 +419,7 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) STp->recover_count++; STp->recover_reg++; - DEB( + DEB( if (debugging) { if (SRpnt->cmd[0] == READ_6) stp = "read"; @@ -419,8 +427,9 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) stp = "write"; else stp = "ioctl"; - printk(ST_DEB_MSG "%s: Recovered %s error (%d).\n", name, stp, - STp->recover_count); + st_printk(ST_DEB_MSG, STp, + "Recovered %s error (%d).\n", + stp, STp->recover_count); } ) /* end DEB */ if (cmdstatp->flags == 0) @@ -437,8 +446,8 @@ static struct st_request *st_allocate_request(struct scsi_tape *stp) if (streq) streq->stp = stp; else { - DEBC(printk(KERN_ERR "%s: Can't get SCSI request.\n", - tape_name(stp));); + st_printk(KERN_ERR, stp, + "Can't get SCSI request.\n"); if (signal_pending(current)) stp->buffer->syscall_result = -EINTR; else @@ -525,8 +534,8 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd /* if async, make sure there's no command outstanding */ if (!do_wait && ((STp->buffer)->last_SRpnt)) { - printk(KERN_ERR "%s: Async command already active.\n", - tape_name(STp)); + st_printk(KERN_ERR, STp, + "Async command already active.\n"); if (signal_pending(current)) (STp->buffer)->syscall_result = (-EINTR); else @@ -597,12 +606,12 @@ static int write_behind_check(struct scsi_tape * STp) if (!STbuffer->writing) return 0; - DEB( + DEB( if (STp->write_pending) STp->nbr_waits++; else STp->nbr_finished++; - ) /* end DEB */ + ) /* end DEB */ wait_for_completion(&(STp->wait)); SRpnt = STbuffer->last_SRpnt; @@ -639,8 +648,9 @@ static int write_behind_check(struct scsi_tape * STp) STbuffer->writing = 0; DEB(if (debugging && retval) - printk(ST_DEB_MSG "%s: Async write error %x, return value %d.\n", - tape_name(STp), STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */ + st_printk(ST_DEB_MSG, STp, + "Async write error %x, return value %d.\n", + STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */ return retval; } @@ -662,8 +672,8 @@ static int cross_eof(struct scsi_tape * STp, int forward) cmd[2] = cmd[3] = cmd[4] = 0xff; /* -1 filemarks */ cmd[5] = 0; - DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n", - tape_name(STp), forward ? "forward" : "backward")); + DEBC_printk(STp, "Stepping over filemark %s.\n", + forward ? "forward" : "backward"); SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->device->request_queue->rq_timeout, @@ -675,8 +685,9 @@ static int cross_eof(struct scsi_tape * STp, int forward) SRpnt = NULL; if ((STp->buffer)->cmdstat.midlevel_result != 0) - printk(KERN_ERR "%s: Stepping over filemark %s failed.\n", - tape_name(STp), forward ? "forward" : "backward"); + st_printk(KERN_ERR, STp, + "Stepping over filemark %s failed.\n", + forward ? "forward" : "backward"); return (STp->buffer)->syscall_result; } @@ -699,8 +710,7 @@ static int st_flush_write_buffer(struct scsi_tape * STp) if (STp->dirty == 1) { transfer = STp->buffer->buffer_bytes; - DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n", - tape_name(STp), transfer)); + DEBC_printk(STp, "Flushing %d bytes.\n", transfer); memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_6; @@ -732,8 +742,7 @@ static int st_flush_write_buffer(struct scsi_tape * STp) STps->drv_block += blks; result = (-ENOSPC); } else { - printk(KERN_ERR "%s: Error on flush.\n", - tape_name(STp)); + st_printk(KERN_ERR, STp, "Error on flush.\n"); STps->drv_block = (-1); result = (-EIO); } @@ -811,7 +820,6 @@ static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm) { int set_it = 0; unsigned long arg; - char *name = tape_name(STp); if (!STp->density_changed && STm->default_density >= 0 && @@ -830,9 +838,10 @@ static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm) arg |= STp->block_size; if (set_it && st_int_ioctl(STp, SET_DENS_AND_BLK, arg)) { - printk(KERN_WARNING - "%s: Can't set default block size to %d bytes and density %x.\n", - name, STm->default_blksize, STm->default_density); + st_printk(KERN_WARNING, STp, + "Can't set default block size to %d bytes " + "and density %x.\n", + STm->default_blksize, STm->default_density); if (modes_defined) return (-EINVAL); } @@ -844,12 +853,9 @@ static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm) static int do_door_lock(struct scsi_tape * STp, int do_lock) { int retval, cmd; - DEB(char *name = tape_name(STp);) - cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK; - DEBC(printk(ST_DEB_MSG "%s: %socking drive door.\n", name, - do_lock ? "L" : "Unl")); + DEBC_printk(STp, "%socking drive door.\n", do_lock ? "L" : "Unl"); retval = scsi_ioctl(STp->device, cmd, NULL); if (!retval) { STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED; @@ -976,15 +982,14 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) struct st_request *SRpnt = NULL; struct st_modedef *STm; struct st_partstat *STps; - char *name = tape_name(STp); struct inode *inode = file_inode(filp); int mode = TAPE_MODE(inode); STp->ready = ST_READY; if (mode != STp->current_mode) { - DEBC(printk(ST_DEB_MSG "%s: Mode change from %d to %d.\n", - name, STp->current_mode, mode)); + DEBC_printk(STp, "Mode change from %d to %d.\n", + STp->current_mode, mode); new_session = 1; STp->current_mode = mode; } @@ -1055,13 +1060,12 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) STp->min_block = ((STp->buffer)->b_data[4] << 8) | (STp->buffer)->b_data[5]; if ( DEB( debugging || ) !STp->inited) - printk(KERN_INFO - "%s: Block limits %d - %d bytes.\n", name, - STp->min_block, STp->max_block); + st_printk(KERN_INFO, STp, + "Block limits %d - %d bytes.\n", + STp->min_block, STp->max_block); } else { STp->min_block = STp->max_block = (-1); - DEBC(printk(ST_DEB_MSG "%s: Can't read block limits.\n", - name)); + DEBC_printk(STp, "Can't read block limits.\n"); } } @@ -1078,56 +1082,58 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) } if ((STp->buffer)->syscall_result != 0) { - DEBC(printk(ST_DEB_MSG "%s: No Mode Sense.\n", name)); + DEBC_printk(STp, "No Mode Sense.\n"); STp->block_size = ST_DEFAULT_BLOCK; /* Educated guess (?) */ (STp->buffer)->syscall_result = 0; /* Prevent error propagation */ STp->drv_write_prot = 0; } else { - DEBC(printk(ST_DEB_MSG - "%s: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", - name, - (STp->buffer)->b_data[0], (STp->buffer)->b_data[1], - (STp->buffer)->b_data[2], (STp->buffer)->b_data[3])); + DEBC_printk(STp,"Mode sense. Length %d, " + "medium %x, WBS %x, BLL %d\n", + (STp->buffer)->b_data[0], + (STp->buffer)->b_data[1], + (STp->buffer)->b_data[2], + (STp->buffer)->b_data[3]); if ((STp->buffer)->b_data[3] >= 8) { STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7; STp->density = (STp->buffer)->b_data[4]; STp->block_size = (STp->buffer)->b_data[9] * 65536 + (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11]; - DEBC(printk(ST_DEB_MSG - "%s: Density %x, tape length: %x, drv buffer: %d\n", - name, STp->density, (STp->buffer)->b_data[5] * 65536 + - (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7], - STp->drv_buffer)); + DEBC_printk(STp, "Density %x, tape length: %x, " + "drv buffer: %d\n", + STp->density, + (STp->buffer)->b_data[5] * 65536 + + (STp->buffer)->b_data[6] * 256 + + (STp->buffer)->b_data[7], + STp->drv_buffer); } STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0; if (!STp->drv_buffer && STp->immediate_filemark) { - printk(KERN_WARNING - "%s: non-buffered tape: disabling writing immediate filemarks\n", - name); + st_printk(KERN_WARNING, STp, + "non-buffered tape: disabling " + "writing immediate filemarks\n"); STp->immediate_filemark = 0; } } st_release_request(SRpnt); SRpnt = NULL; - STp->inited = 1; + STp->inited = 1; if (STp->block_size > 0) (STp->buffer)->buffer_blocks = - (STp->buffer)->buffer_size / STp->block_size; + (STp->buffer)->buffer_size / STp->block_size; else (STp->buffer)->buffer_blocks = 1; (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0; - DEBC(printk(ST_DEB_MSG - "%s: Block size: %d, buffer size: %d (%d blocks).\n", name, - STp->block_size, (STp->buffer)->buffer_size, - (STp->buffer)->buffer_blocks)); + DEBC_printk(STp, "Block size: %d, buffer size: %d (%d blocks).\n", + STp->block_size, (STp->buffer)->buffer_size, + (STp->buffer)->buffer_blocks); if (STp->drv_write_prot) { STp->write_prot = 1; - DEBC(printk(ST_DEB_MSG "%s: Write protected\n", name)); + DEBC_printk(STp, "Write protected\n"); if (do_wait && ((st_flags & O_ACCMODE) == O_WRONLY || @@ -1141,8 +1147,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) /* This code is reached when the device is opened for the first time after the driver has been initialized with tape in the drive and the partition support has been enabled. */ - DEBC(printk(ST_DEB_MSG - "%s: Updating partition number in status.\n", name)); + DEBC_printk(STp, "Updating partition number in status.\n"); if ((STp->partition = find_partition(STp)) < 0) { retval = STp->partition; goto err_out; @@ -1160,9 +1165,10 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) if (STp->default_drvbuffer != 0xff) { if (st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer)) - printk(KERN_WARNING - "%s: Can't set default drive buffering to %d.\n", - name, STp->default_drvbuffer); + st_printk(KERN_WARNING, STp, + "Can't set default drive " + "buffering to %d.\n", + STp->default_drvbuffer); } } @@ -1182,7 +1188,6 @@ static int st_open(struct inode *inode, struct file *filp) struct scsi_tape *STp; struct st_partstat *STps; int dev = TAPE_NR(inode); - char *name; /* * We really want to do nonseekable_open(inode, filp); here, but some @@ -1196,13 +1201,12 @@ static int st_open(struct inode *inode, struct file *filp) } filp->private_data = STp; - name = tape_name(STp); spin_lock(&st_use_lock); if (STp->in_use) { spin_unlock(&st_use_lock); scsi_tape_put(STp); - DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); ) + DEBC_printk(STp, "Device already in use.\n"); return (-EBUSY); } @@ -1222,8 +1226,8 @@ static int st_open(struct inode *inode, struct file *filp) /* See that we have at least a one page buffer available */ if (!enlarge_buffer(STp->buffer, PAGE_SIZE, STp->restr_dma)) { - printk(KERN_WARNING "%s: Can't allocate one page tape buffer.\n", - name); + st_printk(KERN_WARNING, STp, + "Can't allocate one page tape buffer.\n"); retval = (-EOVERFLOW); goto err_out; } @@ -1279,7 +1283,6 @@ static int st_flush(struct file *filp, fl_owner_t id) struct scsi_tape *STp = filp->private_data; struct st_modedef *STm = &(STp->modes[STp->current_mode]); struct st_partstat *STps = &(STp->ps[STp->partition]); - char *name = tape_name(STp); if (file_count(filp) > 1) return 0; @@ -1292,24 +1295,25 @@ static int st_flush(struct file *filp, fl_owner_t id) if (STp->can_partitions && (result2 = switch_partition(STp)) < 0) { - DEBC(printk(ST_DEB_MSG - "%s: switch_partition at close failed.\n", name)); + DEBC_printk(STp, "switch_partition at close failed.\n"); if (result == 0) result = result2; goto out; } DEBC( if (STp->nbr_requests) - printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d.\n", - name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages)); + st_printk(KERN_DEBUG, STp, + "Number of r/w requests %d, dio used in %d, " + "pages %d.\n", STp->nbr_requests, STp->nbr_dio, + STp->nbr_pages)); if (STps->rw == ST_WRITING && !STp->pos_unknown) { struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; - DEBC(printk(ST_DEB_MSG "%s: Async write waits %d, finished %d.\n", - name, STp->nbr_waits, STp->nbr_finished); - ) - +#if DEBUG + DEBC_printk(STp, "Async write waits %d, finished %d.\n", + STp->nbr_waits, STp->nbr_finished); +#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_FILEMARKS; if (STp->immediate_filemark) @@ -1343,13 +1347,13 @@ static int st_flush(struct file *filp, fl_owner_t id) else { /* Write error */ st_release_request(SRpnt); SRpnt = NULL; - printk(KERN_ERR "%s: Error on write filemark.\n", name); + st_printk(KERN_ERR, STp, + "Error on write filemark.\n"); if (result == 0) result = (-EIO); } - DEBC(printk(ST_DEB_MSG "%s: Buffer flushed, %d EOF(s) written\n", - name, cmd[4])); + DEBC_printk(STp, "Buffer flushed, %d EOF(s) written\n", cmd[4]); } else if (!STp->rew_at_close) { STps = &(STp->ps[STp->partition]); if (!STm->sysv || STps->rw != ST_READING) { @@ -1447,9 +1451,10 @@ static ssize_t rw_checks(struct scsi_tape *STp, struct file *filp, size_t count) if (count == 0) goto out; - DEB( + DEB( if (!STp->in_use) { - printk(ST_DEB_MSG "%s: Incorrect device.\n", tape_name(STp)); + st_printk(ST_DEB_MSG, STp, + "Incorrect device.\n"); retval = (-EIO); goto out; } ) /* end DEB */ @@ -1519,8 +1524,9 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf, if (bufsize > STbp->buffer_size && !enlarge_buffer(STbp, bufsize, STp->restr_dma)) { - printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n", - tape_name(STp), bufsize); + st_printk(KERN_WARNING, STp, + "Can't allocate %d byte tape buffer.\n", + bufsize); retval = (-EOVERFLOW); goto out; } @@ -1563,7 +1569,6 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) struct st_modedef *STm; struct st_partstat *STps; struct st_buffer *STbp; - char *name = tape_name(STp); if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; @@ -1574,8 +1579,8 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) /* Write must be integral number of blocks */ if (STp->block_size != 0 && (count % STp->block_size) != 0) { - printk(KERN_WARNING "%s: Write not multiple of tape block size.\n", - name); + st_printk(KERN_WARNING, STp, + "Write not multiple of tape block size.\n"); retval = (-EINVAL); goto out; } @@ -1601,8 +1606,8 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (STm->default_compression != ST_DONT_TOUCH && !(STp->compression_changed)) { if (st_compression(STp, (STm->default_compression == ST_YES))) { - printk(KERN_WARNING "%s: Can't set default compression.\n", - name); + st_printk(KERN_WARNING, STp, + "Can't set default compression.\n"); if (modes_defined) { retval = (-EINVAL); goto out; @@ -1723,7 +1728,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (STbp->syscall_result != 0) { struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; - DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name)); + DEBC_printk(STp, "Error on write:\n"); if (cmdstatp->have_sense && (cmdstatp->flags & SENSE_EOM)) { scode = cmdstatp->sense_hdr.sense_key; if (cmdstatp->remainder_valid) @@ -1750,9 +1755,9 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (STp->block_size == 0 || undone > 0 || count == 0) retval = (-ENOSPC); /* EOM within current request */ - DEBC(printk(ST_DEB_MSG - "%s: EOM with %d bytes unwritten.\n", - name, (int)count)); + DEBC_printk(STp, "EOM with %d " + "bytes unwritten.\n", + (int)count); } else { /* EOT within data buffered earlier (possible only in fixed block mode without direct i/o) */ @@ -1765,9 +1770,10 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) STp->block_size; } STps->eof = ST_EOM_OK; - DEBC(printk(ST_DEB_MSG - "%s: Retry write of %d bytes at EOM.\n", - name, STp->buffer->buffer_bytes)); + DEBC_printk(STp, "Retry " + "write of %d " + "bytes at EOM.\n", + STp->buffer->buffer_bytes); goto retry_write; } else { @@ -1778,9 +1784,8 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) STps->eof = ST_EOM_ERROR; STps->drv_block = (-1); /* Too cautious? */ retval = (-EIO); /* EOM for old data */ - DEBC(printk(ST_DEB_MSG - "%s: EOM with lost data.\n", - name)); + DEBC_printk(STp, "EOM with " + "lost data.\n"); } } } else { @@ -1839,7 +1844,6 @@ static long read_tape(struct scsi_tape *STp, long count, struct st_partstat *STps; struct st_buffer *STbp; int retval = 0; - char *name = tape_name(STp); if (count == 0) return 0; @@ -1891,12 +1895,12 @@ static long read_tape(struct scsi_tape *STp, long count, struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; retval = 1; - DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", - name, - SRpnt->sense[0], SRpnt->sense[1], - SRpnt->sense[2], SRpnt->sense[3], - SRpnt->sense[4], SRpnt->sense[5], - SRpnt->sense[6], SRpnt->sense[7])); + DEBC_printk(STp, + "Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", + SRpnt->sense[0], SRpnt->sense[1], + SRpnt->sense[2], SRpnt->sense[3], + SRpnt->sense[4], SRpnt->sense[5], + SRpnt->sense[6], SRpnt->sense[7]); if (cmdstatp->have_sense) { if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK) @@ -1913,23 +1917,27 @@ static long read_tape(struct scsi_tape *STp, long count, transfer = bytes; if (cmdstatp->flags & SENSE_ILI) { /* ILI */ - if (STp->block_size == 0) { - if (transfer <= 0) { - if (transfer < 0) - printk(KERN_NOTICE - "%s: Failed to read %d byte block with %d byte transfer.\n", - name, bytes - transfer, bytes); - if (STps->drv_block >= 0) - STps->drv_block += 1; - STbp->buffer_bytes = 0; - return (-ENOMEM); - } + if (STp->block_size == 0 && + transfer < 0) { + st_printk(KERN_NOTICE, STp, + "Failed to read %d " + "byte block with %d " + "byte transfer.\n", + bytes - transfer, + bytes); + if (STps->drv_block >= 0) + STps->drv_block += 1; + STbp->buffer_bytes = 0; + return (-ENOMEM); + } else if (STp->block_size == 0) { STbp->buffer_bytes = bytes - transfer; } else { st_release_request(SRpnt); SRpnt = *aSRpnt = NULL; if (transfer == blks) { /* We did not get anything, error */ - printk(KERN_NOTICE "%s: Incorrect block size.\n", name); + st_printk(KERN_NOTICE, STp, + "Incorrect " + "block size.\n"); if (STps->drv_block >= 0) STps->drv_block += blks - transfer + 1; st_int_ioctl(STp, MTBSR, 1); @@ -1938,9 +1946,11 @@ static long read_tape(struct scsi_tape *STp, long count, /* We have some data, deliver it */ STbp->buffer_bytes = (blks - transfer) * STp->block_size; - DEBC(printk(ST_DEB_MSG - "%s: ILI but enough data received %ld %d.\n", - name, count, STbp->buffer_bytes)); + DEBC_printk(STp, "ILI but " + "enough data " + "received %ld " + "%d.\n", count, + STbp->buffer_bytes); if (STps->drv_block >= 0) STps->drv_block += 1; if (st_int_ioctl(STp, MTBSR, 1)) @@ -1956,9 +1966,9 @@ static long read_tape(struct scsi_tape *STp, long count, else STbp->buffer_bytes = bytes - transfer * STp->block_size; - DEBC(printk(ST_DEB_MSG - "%s: EOF detected (%d bytes read).\n", - name, STbp->buffer_bytes)); + DEBC_printk(STp, "EOF detected (%d " + "bytes read).\n", + STbp->buffer_bytes); } else if (cmdstatp->flags & SENSE_EOM) { if (STps->eof == ST_FM) STps->eof = ST_EOD_1; @@ -1970,20 +1980,20 @@ static long read_tape(struct scsi_tape *STp, long count, STbp->buffer_bytes = bytes - transfer * STp->block_size; - DEBC(printk(ST_DEB_MSG "%s: EOM detected (%d bytes read).\n", - name, STbp->buffer_bytes)); + DEBC_printk(STp, "EOM detected (%d " + "bytes read).\n", + STbp->buffer_bytes); } } - /* end of EOF, EOM, ILI test */ + /* end of EOF, EOM, ILI test */ else { /* nonzero sense key */ - DEBC(printk(ST_DEB_MSG - "%s: Tape error while reading.\n", name)); + DEBC_printk(STp, "Tape error while reading.\n"); STps->drv_block = (-1); if (STps->eof == ST_FM && cmdstatp->sense_hdr.sense_key == BLANK_CHECK) { - DEBC(printk(ST_DEB_MSG - "%s: Zero returned for first BLANK CHECK after EOF.\n", - name)); + DEBC_printk(STp, "Zero returned for " + "first BLANK CHECK " + "after EOF.\n"); STps->eof = ST_EOD_2; /* First BLANK_CHECK after FM */ } else /* Some other extended sense code */ retval = (-EIO); @@ -1992,13 +2002,13 @@ static long read_tape(struct scsi_tape *STp, long count, if (STbp->buffer_bytes < 0) /* Caused by bogus sense data */ STbp->buffer_bytes = 0; } - /* End of extended sense test */ + /* End of extended sense test */ else { /* Non-extended sense */ retval = STbp->syscall_result; } } - /* End of error handling */ + /* End of error handling */ else { /* Read successful */ STbp->buffer_bytes = bytes; if (STp->sili) /* In fixed block mode residual is always zero here */ @@ -2028,7 +2038,6 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) struct st_modedef *STm; struct st_partstat *STps; struct st_buffer *STbp = STp->buffer; - DEB( char *name = tape_name(STp); ) if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; @@ -2053,11 +2062,12 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) goto out; STps->rw = ST_READING; } - DEB( + DEB( if (debugging && STps->eof != ST_NOEOF) - printk(ST_DEB_MSG "%s: EOF/EOM flag up (%d). Bytes %d\n", name, - STps->eof, STbp->buffer_bytes); - ) /* end DEB */ + st_printk(ST_DEB_MSG, STp, + "EOF/EOM flag up (%d). Bytes %d\n", + STps->eof, STbp->buffer_bytes); + ) /* end DEB */ retval = setup_buffering(STp, buf, count, 1); if (retval) @@ -2104,13 +2114,13 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) /* Move the data from driver buffer to user buffer */ if (STbp->buffer_bytes > 0) { - DEB( + DEB( if (debugging && STps->eof != ST_NOEOF) - printk(ST_DEB_MSG - "%s: EOF up (%d). Left %d, needed %d.\n", name, - STps->eof, STbp->buffer_bytes, - (int)(count - total)); - ) /* end DEB */ + st_printk(ST_DEB_MSG, STp, + "EOF up (%d). Left %d, needed %d.\n", + STps->eof, STbp->buffer_bytes, + (int)(count - total)); + ) /* end DEB */ transfer = STbp->buffer_bytes < count - total ? STbp->buffer_bytes : count - total; if (!do_dio) { @@ -2166,26 +2176,30 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) DEB( /* Set the driver options */ -static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char *name) +static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm) { if (debugging) { - printk(KERN_INFO - "%s: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n", - name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes, - STm->do_read_ahead); - printk(KERN_INFO - "%s: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n", - name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock); - printk(KERN_INFO - "%s: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n", - name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions, - STp->scsi2_logical); - printk(KERN_INFO - "%s: sysv: %d nowait: %d sili: %d nowait_filemark: %d\n", - name, STm->sysv, STp->immediate, STp->sili, - STp->immediate_filemark); - printk(KERN_INFO "%s: debugging: %d\n", - name, debugging); + st_printk(KERN_INFO, STp, + "Mode %d options: buffer writes: %d, " + "async writes: %d, read ahead: %d\n", + STp->current_mode, STm->do_buffer_writes, + STm->do_async_writes, STm->do_read_ahead); + st_printk(KERN_INFO, STp, + " can bsr: %d, two FMs: %d, " + "fast mteom: %d, auto lock: %d,\n", + STp->can_bsr, STp->two_fm, STp->fast_mteom, + STp->do_auto_lock); + st_printk(KERN_INFO, STp, + " defs for wr: %d, no block limits: %d, " + "partitions: %d, s2 log: %d\n", + STm->defaults_for_writes, STp->omit_blklims, + STp->can_partitions, STp->scsi2_logical); + st_printk(KERN_INFO, STp, + " sysv: %d nowait: %d sili: %d " + "nowait_filemark: %d\n", + STm->sysv, STp->immediate, STp->sili, + STp->immediate_filemark); + st_printk(KERN_INFO, STp, " debugging: %d\n", debugging); } } ) @@ -2196,7 +2210,6 @@ static int st_set_options(struct scsi_tape *STp, long options) int value; long code; struct st_modedef *STm; - char *name = tape_name(STp); struct cdev *cd0, *cd1; struct device *d0, *d1; @@ -2212,9 +2225,8 @@ static int st_set_options(struct scsi_tape *STp, long options) STm->devs[0] = d0; STm->devs[1] = d1; modes_defined = 1; - DEBC(printk(ST_DEB_MSG - "%s: Initialized mode %d definition from mode 0\n", - name, STp->current_mode)); + DEBC_printk(STp, "Initialized mode %d definition from mode 0\n", + STp->current_mode); } code = options & MT_ST_OPTIONS; @@ -2236,7 +2248,7 @@ static int st_set_options(struct scsi_tape *STp, long options) STm->sysv = (options & MT_ST_SYSV) != 0; STp->sili = (options & MT_ST_SILI) != 0; DEB( debugging = (options & MT_ST_DEBUGGING) != 0; - st_log_options(STp, STm, name); ) + st_log_options(STp, STm); ) } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) { value = (code == MT_ST_SETBOOLEANS); if ((options & MT_ST_BUFFER_WRITES) != 0) @@ -2270,21 +2282,21 @@ static int st_set_options(struct scsi_tape *STp, long options) STm->sysv = value; if ((options & MT_ST_SILI) != 0) STp->sili = value; - DEB( + DEB( if ((options & MT_ST_DEBUGGING) != 0) debugging = value; - st_log_options(STp, STm, name); ) + st_log_options(STp, STm); ) } else if (code == MT_ST_WRITE_THRESHOLD) { /* Retained for compatibility */ } else if (code == MT_ST_DEF_BLKSIZE) { value = (options & ~MT_ST_OPTIONS); if (value == ~MT_ST_OPTIONS) { STm->default_blksize = (-1); - DEBC( printk(KERN_INFO "%s: Default block size disabled.\n", name)); + DEBC_printk(STp, "Default block size disabled.\n"); } else { STm->default_blksize = value; - DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n", - name, STm->default_blksize)); + DEBC_printk(STp,"Default block size set to " + "%d bytes.\n", STm->default_blksize); if (STp->ready == ST_READY) { STp->blksize_changed = 0; set_mode_densblk(STp, STm); @@ -2294,13 +2306,13 @@ static int st_set_options(struct scsi_tape *STp, long options) value = (options & ~MT_ST_OPTIONS); if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) { STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ; - DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name, - (value & ~MT_ST_SET_LONG_TIMEOUT))); + DEBC_printk(STp, "Long timeout set to %d seconds.\n", + (value & ~MT_ST_SET_LONG_TIMEOUT)); } else { blk_queue_rq_timeout(STp->device->request_queue, value * HZ); - DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n", - name, value) ); + DEBC_printk(STp, "Normal timeout set to %d seconds.\n", + value); } } else if (code == MT_ST_SET_CLN) { value = (options & ~MT_ST_OPTIONS) & 0xff; @@ -2311,21 +2323,21 @@ static int st_set_options(struct scsi_tape *STp, long options) STp->cln_mode = value; STp->cln_sense_mask = (options >> 8) & 0xff; STp->cln_sense_value = (options >> 16) & 0xff; - printk(KERN_INFO - "%s: Cleaning request mode %d, mask %02x, value %02x\n", - name, value, STp->cln_sense_mask, STp->cln_sense_value); + st_printk(KERN_INFO, STp, + "Cleaning request mode %d, mask %02x, value %02x\n", + value, STp->cln_sense_mask, STp->cln_sense_value); } else if (code == MT_ST_DEF_OPTIONS) { code = (options & ~MT_ST_CLEAR_DEFAULT); value = (options & MT_ST_CLEAR_DEFAULT); if (code == MT_ST_DEF_DENSITY) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_density = (-1); - DEBC( printk(KERN_INFO "%s: Density default disabled.\n", - name)); + DEBC_printk(STp, + "Density default disabled.\n"); } else { STm->default_density = value & 0xff; - DEBC( printk(KERN_INFO "%s: Density default set to %x\n", - name, STm->default_density)); + DEBC_printk(STp, "Density default set to %x\n", + STm->default_density); if (STp->ready == ST_READY) { STp->density_changed = 0; set_mode_densblk(STp, STm); @@ -2334,31 +2346,33 @@ static int st_set_options(struct scsi_tape *STp, long options) } else if (code == MT_ST_DEF_DRVBUFFER) { if (value == MT_ST_CLEAR_DEFAULT) { STp->default_drvbuffer = 0xff; - DEBC( printk(KERN_INFO - "%s: Drive buffer default disabled.\n", name)); + DEBC_printk(STp, + "Drive buffer default disabled.\n"); } else { STp->default_drvbuffer = value & 7; - DEBC( printk(KERN_INFO - "%s: Drive buffer default set to %x\n", - name, STp->default_drvbuffer)); + DEBC_printk(STp, + "Drive buffer default set to %x\n", + STp->default_drvbuffer); if (STp->ready == ST_READY) st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer); } } else if (code == MT_ST_DEF_COMPRESSION) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_compression = ST_DONT_TOUCH; - DEBC( printk(KERN_INFO - "%s: Compression default disabled.\n", name)); + DEBC_printk(STp, + "Compression default disabled.\n"); } else { if ((value & 0xff00) != 0) { STp->c_algo = (value & 0xff00) >> 8; - DEBC( printk(KERN_INFO "%s: Compression algorithm set to 0x%x.\n", - name, STp->c_algo)); + DEBC_printk(STp, "Compression " + "algorithm set to 0x%x.\n", + STp->c_algo); } if ((value & 0xff) != 0xff) { STm->default_compression = (value & 1 ? ST_YES : ST_NO); - DEBC( printk(KERN_INFO "%s: Compression default set to %x\n", - name, (value & 1))); + DEBC_printk(STp, "Compression default " + "set to %x\n", + (value & 1)); if (STp->ready == ST_READY) { STp->compression_changed = 0; st_compression(STp, (STm->default_compression == ST_YES)); @@ -2473,7 +2487,6 @@ static int st_compression(struct scsi_tape * STp, int state) int retval; int mpoffs; /* Offset to mode page start */ unsigned char *b_data = (STp->buffer)->b_data; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); @@ -2481,18 +2494,17 @@ static int st_compression(struct scsi_tape * STp, int state) /* Read the current page contents */ retval = read_mode_page(STp, COMPRESSION_PAGE, 0); if (retval) { - DEBC(printk(ST_DEB_MSG "%s: Compression mode page not supported.\n", - name)); + DEBC_printk(STp, "Compression mode page not supported.\n"); return (-EIO); } mpoffs = MODE_HEADER_LENGTH + b_data[MH_OFF_BDESCS_LENGTH]; - DEBC(printk(ST_DEB_MSG "%s: Compression state is %d.\n", name, - (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0))); + DEBC_printk(STp, "Compression state is %d.\n", + (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0)); /* Check if compression can be changed */ if ((b_data[mpoffs + CP_OFF_DCE_DCC] & DCC_MASK) == 0) { - DEBC(printk(ST_DEB_MSG "%s: Compression not supported.\n", name)); + DEBC_printk(STp, "Compression not supported.\n"); return (-EIO); } @@ -2510,11 +2522,10 @@ static int st_compression(struct scsi_tape * STp, int state) retval = write_mode_page(STp, COMPRESSION_PAGE, 0); if (retval) { - DEBC(printk(ST_DEB_MSG "%s: Compression change failed.\n", name)); + DEBC_printk(STp, "Compression change failed.\n"); return (-EIO); } - DEBC(printk(ST_DEB_MSG "%s: Compression state changed to %d.\n", - name, state)); + DEBC_printk(STp, "Compression state changed to %d.\n", state); STp->compression_changed = 1; return 0; @@ -2525,7 +2536,6 @@ static int st_compression(struct scsi_tape * STp, int state) static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_code) { int retval = (-EIO), timeout; - DEB( char *name = tape_name(STp); ) unsigned char cmd[MAX_COMMAND_SIZE]; struct st_partstat *STps; struct st_request *SRpnt; @@ -2546,9 +2556,9 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod */ if (load_code >= 1 + MT_ST_HPLOADER_OFFSET && load_code <= 6 + MT_ST_HPLOADER_OFFSET) { - DEBC(printk(ST_DEB_MSG "%s: Enhanced %sload slot %2d.\n", - name, (cmd[4]) ? "" : "un", - load_code - MT_ST_HPLOADER_OFFSET)); + DEBC_printk(STp, " Enhanced %sload slot %2d.\n", + (cmd[4]) ? "" : "un", + load_code - MT_ST_HPLOADER_OFFSET); cmd[3] = load_code - MT_ST_HPLOADER_OFFSET; /* MediaID field of C1553A */ } if (STp->immediate) { @@ -2560,9 +2570,9 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod DEBC( if (!load_code) - printk(ST_DEB_MSG "%s: Unloading tape.\n", name); + st_printk(ST_DEB_MSG, STp, "Unloading tape.\n"); else - printk(ST_DEB_MSG "%s: Loading tape.\n", name); + st_printk(ST_DEB_MSG, STp, "Loading tape.\n"); ); SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, @@ -2597,17 +2607,24 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod #if DEBUG #define ST_DEB_FORWARD 0 #define ST_DEB_BACKWARD 1 -static void deb_space_print(char *name, int direction, char *units, unsigned char *cmd) +static void deb_space_print(struct scsi_tape *STp, int direction, char *units, unsigned char *cmd) { s32 sc; + if (!debugging) + return; + sc = cmd[2] & 0x80 ? 0xff000000 : 0; sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4]; if (direction) sc = -sc; - printk(ST_DEB_MSG "%s: Spacing tape %s over %d %s.\n", name, - direction ? "backward" : "forward", sc, units); + st_printk(ST_DEB_MSG, STp, "Spacing tape %s over %d %s.\n", + direction ? "backward" : "forward", sc, units); } +#else +#define ST_DEB_FORWARD 0 +#define ST_DEB_BACKWARD 1 +static void deb_space_print(struct scsi_tape *STp, int direction, char *units, unsigned char *cmd) {} #endif @@ -2623,7 +2640,6 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon struct st_partstat *STps; int fileno, blkno, at_sm, undone; int datalen = 0, direction = DMA_NONE; - char *name = tape_name(STp); WARN_ON(STp->buffer->do_dio != 0); if (STp->ready != ST_READY) { @@ -2648,7 +2664,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - DEBC(deb_space_print(name, ST_DEB_FORWARD, "filemarks", cmd);) + deb_space_print(STp, ST_DEB_FORWARD, "filemarks", cmd); if (fileno >= 0) fileno += arg; blkno = 0; @@ -2663,7 +2679,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; - DEBC(deb_space_print(name, ST_DEB_BACKWARD, "filemarks", cmd);) + deb_space_print(STp, ST_DEB_BACKWARD, "filemarks", cmd); if (fileno >= 0) fileno -= arg; blkno = (-1); /* We can't know the block number */ @@ -2675,7 +2691,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - DEBC(deb_space_print(name, ST_DEB_FORWARD, "blocks", cmd);) + deb_space_print(STp, ST_DEB_FORWARD, "blocks", cmd); if (blkno >= 0) blkno += arg; at_sm &= (arg == 0); @@ -2687,7 +2703,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; - DEBC(deb_space_print(name, ST_DEB_BACKWARD, "blocks", cmd);) + deb_space_print(STp, ST_DEB_BACKWARD, "blocks", cmd); if (blkno >= 0) blkno -= arg; at_sm &= (arg == 0); @@ -2698,7 +2714,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - DEBC(deb_space_print(name, ST_DEB_FORWARD, "setmarks", cmd);) + deb_space_print(STp, ST_DEB_FORWARD, "setmarks", cmd); if (arg != 0) { blkno = fileno = (-1); at_sm = 1; @@ -2711,7 +2727,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; - DEBC(deb_space_print(name, ST_DEB_BACKWARD, "setmarks", cmd);) + deb_space_print(STp, ST_DEB_BACKWARD, "setmarks", cmd); if (arg != 0) { blkno = fileno = (-1); at_sm = 1; @@ -2732,13 +2748,19 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[3] = (arg >> 8); cmd[4] = arg; timeout = STp->device->request_queue->rq_timeout; - DEBC( - if (cmd_in != MTWSM) - printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name, - cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); - else - printk(ST_DEB_MSG "%s: Writing %d setmarks.\n", name, - cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); + DEBC( + if (cmd_in != MTWSM) + st_printk(ST_DEB_MSG, STp, + "Writing %d filemarks.\n", + cmd[2] * 65536 + + cmd[3] * 256 + + cmd[4]); + else + st_printk(ST_DEB_MSG, STp, + "Writing %d setmarks.\n", + cmd[2] * 65536 + + cmd[3] * 256 + + cmd[4]); ) if (fileno >= 0) fileno += arg; @@ -2751,11 +2773,11 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[1] = 1; /* Don't wait for completion */ timeout = STp->device->request_queue->rq_timeout; } - DEBC(printk(ST_DEB_MSG "%s: Rewinding tape.\n", name)); + DEBC_printk(STp, "Rewinding tape.\n"); fileno = blkno = at_sm = 0; break; case MTNOP: - DEBC(printk(ST_DEB_MSG "%s: No op on tape.\n", name)); + DEBC_printk(STp, "No op on tape.\n"); return 0; /* Should do something ? */ break; case MTRETEN: @@ -2765,7 +2787,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon timeout = STp->device->request_queue->rq_timeout; } cmd[4] = 3; - DEBC(printk(ST_DEB_MSG "%s: Retensioning tape.\n", name)); + DEBC_printk(STp, "Retensioning tape.\n"); fileno = blkno = at_sm = 0; break; case MTEOM: @@ -2783,8 +2805,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon fileno = (-1); cmd[0] = SPACE; cmd[1] = 3; - DEBC(printk(ST_DEB_MSG "%s: Spacing to end of recorded medium.\n", - name)); + DEBC_printk(STp, "Spacing to end of recorded medium.\n"); blkno = -1; at_sm = 0; break; @@ -2800,7 +2821,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon else timeout = STp->long_timeout * 8; - DEBC(printk(ST_DEB_MSG "%s: Erasing tape.\n", name)); + DEBC_printk(STp, "Erasing tape.\n"); fileno = blkno = at_sm = 0; break; case MTSETBLK: /* Set block length */ @@ -2815,7 +2836,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon STp->max_block > 0 && ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block || (arg & MT_ST_BLKSIZE_MASK) > STp->max_block)) { - printk(KERN_WARNING "%s: Illegal block size.\n", name); + st_printk(KERN_WARNING, STp, "Illegal block size.\n"); return (-EINVAL); } cmd[0] = MODE_SELECT; @@ -2848,21 +2869,21 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon (STp->buffer)->b_data[10] = (ltmp >> 8); (STp->buffer)->b_data[11] = ltmp; timeout = STp->device->request_queue->rq_timeout; - DEBC( + DEBC( if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) - printk(ST_DEB_MSG - "%s: Setting block size to %d bytes.\n", name, - (STp->buffer)->b_data[9] * 65536 + - (STp->buffer)->b_data[10] * 256 + - (STp->buffer)->b_data[11]); + st_printk(ST_DEB_MSG, STp, + "Setting block size to %d bytes.\n", + (STp->buffer)->b_data[9] * 65536 + + (STp->buffer)->b_data[10] * 256 + + (STp->buffer)->b_data[11]); if (cmd_in == MTSETDENSITY || cmd_in == SET_DENS_AND_BLK) - printk(ST_DEB_MSG - "%s: Setting density code to %x.\n", name, - (STp->buffer)->b_data[4]); + st_printk(ST_DEB_MSG, STp, + "Setting density code to %x.\n", + (STp->buffer)->b_data[4]); if (cmd_in == MTSETDRVBUFFER) - printk(ST_DEB_MSG - "%s: Setting drive buffer code to %d.\n", name, - ((STp->buffer)->b_data[2] >> 4) & 7); + st_printk(ST_DEB_MSG, STp, + "Setting drive buffer code to %d.\n", + ((STp->buffer)->b_data[2] >> 4) & 7); ) break; default: @@ -3019,7 +3040,6 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti int result; unsigned char scmd[MAX_COMMAND_SIZE]; struct st_request *SRpnt; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); @@ -3043,7 +3063,7 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti (STp->device->scsi_level >= SCSI_2 && ((STp->buffer)->b_data[0] & 4) != 0)) { *block = *partition = 0; - DEBC(printk(ST_DEB_MSG "%s: Can't read tape position.\n", name)); + DEBC_printk(STp, " Can't read tape position.\n"); result = (-EIO); } else { result = 0; @@ -3062,8 +3082,8 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti (STp->buffer)->b_data[1] == 0) /* BOP of partition 0 */ STp->ps[0].drv_block = STp->ps[0].drv_file = 0; } - DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name, - *block, *partition)); + DEBC_printk(STp, "Got tape pos. blk %d part %d.\n", + *block, *partition); } st_release_request(SRpnt); SRpnt = NULL; @@ -3083,15 +3103,14 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition int timeout; unsigned char scmd[MAX_COMMAND_SIZE]; struct st_request *SRpnt; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); timeout = STp->long_timeout; STps = &(STp->ps[STp->partition]); - DEBC(printk(ST_DEB_MSG "%s: Setting block to %d and partition to %d.\n", - name, block, partition)); + DEBC_printk(STp, "Setting block to %d and partition to %d.\n", + block, partition); DEB(if (partition < 0) return (-EIO); ) @@ -3105,9 +3124,9 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition else { STps->last_block_valid = 1; STps->last_block_visited = blk; - DEBC(printk(ST_DEB_MSG - "%s: Visited block %d for partition %d saved.\n", - name, blk, STp->partition)); + DEBC_printk(STp, "Visited block %d for " + "partition %d saved.\n", + blk, STp->partition); } } @@ -3129,9 +3148,9 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition if (STp->partition != partition) { scmd[1] |= 2; scmd[8] = partition; - DEBC(printk(ST_DEB_MSG - "%s: Trying to change partition from %d to %d\n", - name, STp->partition, partition)); + DEBC_printk(STp, "Trying to change partition " + "from %d to %d\n", STp->partition, + partition); } } if (STp->immediate) { @@ -3222,7 +3241,6 @@ static int switch_partition(struct scsi_tape *STp) static int nbr_partitions(struct scsi_tape *STp) { int result; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); @@ -3230,13 +3248,12 @@ static int nbr_partitions(struct scsi_tape *STp) result = read_mode_page(STp, PART_PAGE, 1); if (result) { - DEBC(printk(ST_DEB_MSG "%s: Can't read medium partition page.\n", - name)); + DEBC_printk(STp, "Can't read medium partition page.\n"); result = (-EIO); } else { result = (STp->buffer)->b_data[MODE_HEADER_LENGTH + PP_OFF_NBR_ADD_PARTS] + 1; - DEBC(printk(ST_DEB_MSG "%s: Number of partitions %d.\n", name, result)); + DEBC_printk(STp, "Number of partitions %d.\n", result); } return result; @@ -3264,21 +3281,20 @@ static int nbr_partitions(struct scsi_tape *STp) */ static int partition_tape(struct scsi_tape *STp, int size) { - char *name = tape_name(STp); int result; int pgo, psd_cnt, psdo; unsigned char *bp; result = read_mode_page(STp, PART_PAGE, 0); if (result) { - DEBC(printk(ST_DEB_MSG "%s: Can't read partition mode page.\n", name)); + DEBC_printk(STp, "Can't read partition mode page.\n"); return result; } /* The mode page is in the buffer. Let's modify it and write it. */ bp = (STp->buffer)->b_data; pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH]; - DEBC(printk(ST_DEB_MSG "%s: Partition page length is %d bytes.\n", - name, bp[pgo + MP_OFF_PAGE_LENGTH] + 2)); + DEBC_printk(STp, "Partition page length is %d bytes.\n", + bp[pgo + MP_OFF_PAGE_LENGTH] + 2); psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2; psdo = pgo + PART_PAGE_FIXED_LENGTH; @@ -3288,25 +3304,23 @@ static int partition_tape(struct scsi_tape *STp, int size) } memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2); - DEBC(printk("%s: psd_cnt %d, max.parts %d, nbr_parts %d\n", name, + DEBC_printk(STp, "psd_cnt %d, max.parts %d, nbr_parts %d\n", psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS], - bp[pgo + PP_OFF_NBR_ADD_PARTS])); + bp[pgo + PP_OFF_NBR_ADD_PARTS]); if (size <= 0) { bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0; if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS]) bp[pgo + MP_OFF_PAGE_LENGTH] = 6; - DEBC(printk(ST_DEB_MSG "%s: Formatting tape with one partition.\n", - name)); + DEBC_printk(STp, "Formatting tape with one partition.\n"); } else { bp[psdo] = (size >> 8) & 0xff; bp[psdo + 1] = size & 0xff; bp[pgo + 3] = 1; if (bp[pgo + MP_OFF_PAGE_LENGTH] < 8) bp[pgo + MP_OFF_PAGE_LENGTH] = 8; - DEBC(printk(ST_DEB_MSG - "%s: Formatting tape with two partitions (1 = %d MB).\n", - name, size)); + DEBC_printk(STp, "Formatting tape with two partitions " + "(1 = %d MB).\n", size); } bp[pgo + PP_OFF_PART_UNITS] = 0; bp[pgo + PP_OFF_RESERVED] = 0; @@ -3314,7 +3328,7 @@ static int partition_tape(struct scsi_tape *STp, int size) result = write_mode_page(STp, PART_PAGE, 1); if (result) { - printk(KERN_INFO "%s: Partitioning of tape failed.\n", name); + st_printk(KERN_INFO, STp, "Partitioning of tape failed.\n"); result = (-EIO); } @@ -3332,15 +3346,14 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) struct scsi_tape *STp = file->private_data; struct st_modedef *STm; struct st_partstat *STps; - char *name = tape_name(STp); void __user *p = (void __user *)arg; if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; - DEB( + DEB( if (debugging && !STp->in_use) { - printk(ST_DEB_MSG "%s: Incorrect device.\n", name); + st_printk(ST_DEB_MSG, STp, "Incorrect device.\n"); retval = (-EIO); goto out; } ) /* end DEB */ @@ -3378,8 +3391,8 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) } if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) { - printk(KERN_WARNING - "%s: MTSETDRVBUFFER only allowed for root.\n", name); + st_printk(KERN_WARNING, STp, + "MTSETDRVBUFFER only allowed for root.\n"); retval = (-EPERM); goto out; } @@ -4087,7 +4100,8 @@ static int st_probe(struct device *dev) return -ENODEV; if ((stp = st_incompatible(SDp))) { sdev_printk(KERN_INFO, SDp, "Found incompatible tape\n"); - printk(KERN_INFO "st: The suggested driver is %s.\n", stp); + sdev_printk(KERN_INFO, SDp, + "st: The suggested driver is %s.\n", stp); return -ENODEV; } @@ -4096,20 +4110,23 @@ static int st_probe(struct device *dev) i = st_max_sg_segs; buffer = new_tape_buffer((SDp->host)->unchecked_isa_dma, i); if (buffer == NULL) { - printk(KERN_ERR - "st: Can't allocate new tape buffer. Device not attached.\n"); + sdev_printk(KERN_ERR, SDp, + "st: Can't allocate new tape buffer. " + "Device not attached.\n"); goto out; } disk = alloc_disk(1); if (!disk) { - printk(KERN_ERR "st: out of memory. Device not attached.\n"); + sdev_printk(KERN_ERR, SDp, + "st: out of memory. Device not attached.\n"); goto out_buffer_free; } tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC); if (tpnt == NULL) { - printk(KERN_ERR "st: Can't allocate device descriptor.\n"); + sdev_printk(KERN_ERR, SDp, + "st: Can't allocate device descriptor.\n"); goto out_put_disk; } kref_init(&tpnt->kref); diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 9969fa1..fecac5d0 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -33,6 +33,7 @@ #include <linux/device.h> #include <linux/hyperv.h> #include <linux/mempool.h> +#include <linux/blkdev.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_host.h> @@ -326,21 +327,23 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); */ static int storvsc_timeout = 180; +static int msft_blist_flags = BLIST_TRY_VPD_PAGES; + #define STORVSC_MAX_IO_REQUESTS 200 static void storvsc_on_channel_callback(void *context); -/* - * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In - * reality, the path/target is not used (ie always set to 0) so our - * scsi host adapter essentially has 1 bus with 1 target that contains - * up to 256 luns. - */ -#define STORVSC_MAX_LUNS_PER_TARGET 64 -#define STORVSC_MAX_TARGETS 1 -#define STORVSC_MAX_CHANNELS 1 +#define STORVSC_MAX_LUNS_PER_TARGET 255 +#define STORVSC_MAX_TARGETS 2 +#define STORVSC_MAX_CHANNELS 8 +#define STORVSC_FC_MAX_LUNS_PER_TARGET 255 +#define STORVSC_FC_MAX_TARGETS 128 +#define STORVSC_FC_MAX_CHANNELS 8 +#define STORVSC_IDE_MAX_LUNS_PER_TARGET 64 +#define STORVSC_IDE_MAX_TARGETS 1 +#define STORVSC_IDE_MAX_CHANNELS 1 struct storvsc_cmd_request { struct list_head entry; @@ -1017,6 +1020,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, case ATA_12: set_host_byte(scmnd, DID_PASSTHROUGH); break; + /* + * On Some Windows hosts TEST_UNIT_READY command can return + * SRB_STATUS_ERROR, let the upper level code deal with it + * based on the sense information. + */ + case TEST_UNIT_READY: + break; default: set_host_byte(scmnd, DID_TARGET_FAILURE); } @@ -1441,6 +1451,14 @@ static int storvsc_device_configure(struct scsi_device *sdevice) sdevice->no_write_same = 1; + /* + * Add blist flags to permit the reading of the VPD pages even when + * the target may claim SPC-2 compliance. MSFT targets currently + * claim SPC-2 compliance while they implement post SPC-2 features. + * With this patch we can correctly handle WRITE_SAME_16 issues. + */ + sdevice->sdev_bflags |= msft_blist_flags; + return 0; } @@ -1518,6 +1536,16 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) return SUCCESS; } +/* + * The host guarantees to respond to each command, although I/O latencies might + * be unbounded on Azure. Reset the timer unconditionally to give the host a + * chance to perform EH. + */ +static enum blk_eh_timer_return storvsc_eh_timed_out(struct scsi_cmnd *scmnd) +{ + return BLK_EH_RESET_TIMER; +} + static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd) { bool allowed = true; @@ -1553,9 +1581,19 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) struct vmscsi_request *vm_srb; struct stor_mem_pools *memp = scmnd->device->hostdata; - if (!storvsc_scsi_cmd_ok(scmnd)) { - scmnd->scsi_done(scmnd); - return 0; + if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { + /* + * On legacy hosts filter unimplemented commands. + * Future hosts are expected to correctly handle + * unsupported commands. Furthermore, it is + * possible that some of the currently + * unsupported commands maybe supported in + * future versions of the host. + */ + if (!storvsc_scsi_cmd_ok(scmnd)) { + scmnd->scsi_done(scmnd); + return 0; + } } request_size = sizeof(struct storvsc_cmd_request); @@ -1580,26 +1618,24 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) vm_srb = &cmd_request->vstor_packet.vm_srb; vm_srb->win8_extension.time_out_value = 60; + vm_srb->win8_extension.srb_flags |= + (SRB_FLAGS_QUEUE_ACTION_ENABLE | + SRB_FLAGS_DISABLE_SYNCH_TRANSFER); /* Build the SRB */ switch (scmnd->sc_data_direction) { case DMA_TO_DEVICE: vm_srb->data_in = WRITE_TYPE; vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_OUT; - vm_srb->win8_extension.srb_flags |= - (SRB_FLAGS_QUEUE_ACTION_ENABLE | - SRB_FLAGS_DISABLE_SYNCH_TRANSFER); break; case DMA_FROM_DEVICE: vm_srb->data_in = READ_TYPE; vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN; - vm_srb->win8_extension.srb_flags |= - (SRB_FLAGS_QUEUE_ACTION_ENABLE | - SRB_FLAGS_DISABLE_SYNCH_TRANSFER); break; default: vm_srb->data_in = UNKNOWN_TYPE; - vm_srb->win8_extension.srb_flags = 0; + vm_srb->win8_extension.srb_flags |= (SRB_FLAGS_DATA_IN | + SRB_FLAGS_DATA_OUT); break; } @@ -1687,11 +1723,11 @@ static struct scsi_host_template scsi_driver = { .bios_param = storvsc_get_chs, .queuecommand = storvsc_queuecommand, .eh_host_reset_handler = storvsc_host_reset_handler, + .eh_timed_out = storvsc_eh_timed_out, .slave_alloc = storvsc_device_alloc, .slave_destroy = storvsc_device_destroy, .slave_configure = storvsc_device_configure, - .cmd_per_lun = 1, - /* 64 max_queue * 1 target */ + .cmd_per_lun = 255, .can_queue = STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, .this_id = -1, /* no use setting to 0 since ll_blk_rw reset it to 1 */ @@ -1743,19 +1779,25 @@ static int storvsc_probe(struct hv_device *device, * set state to properly communicate with the host. */ - if (vmbus_proto_version == VERSION_WIN8) { - sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = 0; - vmstor_current_major = VMSTOR_WIN8_MAJOR; - vmstor_current_minor = VMSTOR_WIN8_MINOR; - } else { + switch (vmbus_proto_version) { + case VERSION_WS2008: + case VERSION_WIN7: sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); vmstor_current_major = VMSTOR_WIN7_MAJOR; vmstor_current_minor = VMSTOR_WIN7_MINOR; + break; + default: + sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; + vmscsi_size_delta = 0; + vmstor_current_major = VMSTOR_WIN8_MAJOR; + vmstor_current_minor = VMSTOR_WIN8_MINOR; + break; } - + if (dev_id->driver_data == SFC_GUID) + scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS * + STORVSC_FC_MAX_TARGETS); host = scsi_host_alloc(&scsi_driver, sizeof(struct hv_host_device)); if (!host) @@ -1789,12 +1831,25 @@ static int storvsc_probe(struct hv_device *device, host_dev->path = stor_device->path_id; host_dev->target = stor_device->target_id; - /* max # of devices per target */ - host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; - /* max # of targets per channel */ - host->max_id = STORVSC_MAX_TARGETS; - /* max # of channels */ - host->max_channel = STORVSC_MAX_CHANNELS - 1; + switch (dev_id->driver_data) { + case SFC_GUID: + host->max_lun = STORVSC_FC_MAX_LUNS_PER_TARGET; + host->max_id = STORVSC_FC_MAX_TARGETS; + host->max_channel = STORVSC_FC_MAX_CHANNELS - 1; + break; + + case SCSI_GUID: + host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; + host->max_id = STORVSC_MAX_TARGETS; + host->max_channel = STORVSC_MAX_CHANNELS - 1; + break; + + default: + host->max_lun = STORVSC_IDE_MAX_LUNS_PER_TARGET; + host->max_id = STORVSC_IDE_MAX_TARGETS; + host->max_channel = STORVSC_IDE_MAX_CHANNELS - 1; + break; + } /* max cmd length */ host->max_cmd_len = STORVSC_MAX_CMD_LEN; diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 8822079..1a2367a 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -355,17 +355,18 @@ static void __init init_tags( void ) static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); - if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)) + if (hostdata->busy[cmd->device->id] & (1 << lun)) return( 1 ); if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) return( 0 ); - if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >= - TagAlloc[cmd->device->id][cmd->device->lun].queue_size ) { + if (TagAlloc[cmd->device->id][lun].nr_allocated >= + TagAlloc[cmd->device->id][lun].queue_size ) { dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d: no free tags\n", - H_NO(cmd), cmd->device->id, cmd->device->lun ); + H_NO(cmd), cmd->device->id, lun ); return( 1 ); } return( 0 ); @@ -379,6 +380,7 @@ static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged) static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); /* If we or the target don't support tagged queuing, allocate the LUN for @@ -387,19 +389,19 @@ static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) { cmd->tag = TAG_NONE; - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= (1 << lun); dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d now allocated by untagged " - "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun ); + "command\n", H_NO(cmd), cmd->device->id, lun ); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun]; cmd->tag = find_first_zero_bit( &ta->allocated, MAX_TAGS ); set_bit( cmd->tag, &ta->allocated ); ta->nr_allocated++; dprintk(NDEBUG_TAGS, "scsi%d: using tag %d for target %d lun %d " "(now %d tags in use)\n", - H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun, + H_NO(cmd), cmd->tag, cmd->device->id, lun, ta->nr_allocated ); } } @@ -411,23 +413,24 @@ static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) static void cmd_free_tag(struct scsi_cmnd *cmd) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); if (cmd->tag == TAG_NONE) { - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << lun); dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d untagged cmd finished\n", - H_NO(cmd), cmd->device->id, cmd->device->lun ); + H_NO(cmd), cmd->device->id, lun ); } else if (cmd->tag >= MAX_TAGS) { printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n", H_NO(cmd), cmd->tag ); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun]; clear_bit( cmd->tag, &ta->allocated ); ta->nr_allocated--; dprintk(NDEBUG_TAGS, "scsi%d: freed tag %d for target %d lun %d\n", - H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun ); + H_NO(cmd), cmd->tag, cmd->device->id, lun ); } } @@ -659,7 +662,7 @@ static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd) { int i, s; unsigned char *command; - printk("scsi%d: destination target %d, lun %d\n", + printk("scsi%d: destination target %d, lun %llu\n", H_NO(cmd), cmd->device->id, cmd->device->lun); printk(KERN_CONT " command = "); command = cmd->cmnd; @@ -705,7 +708,7 @@ static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m) { int i, s; unsigned char *command; - seq_printf(m, "scsi%d: destination target %d, lun %d\n", + seq_printf(m, "scsi%d: destination target %d, lun %llu\n", H_NO(cmd), cmd->device->id, cmd->device->lun); seq_printf(m, " command = "); command = cmd->cmnd; @@ -1007,7 +1010,7 @@ static void NCR5380_main (struct work_struct *bl) prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) { if (prev != tmp) - dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun); + dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun); /* When we find one, remove it from the issue queue. */ /* ++guenther: possible race with Falcon locking */ if ( @@ -1038,7 +1041,7 @@ static void NCR5380_main (struct work_struct *bl) * issue queue so we can keep trying. */ dprintk(NDEBUG_MAIN, "scsi%d: main(): command for target %d " - "lun %d removed from issue_queue\n", + "lun %llu removed from issue_queue\n", HOSTNO, tmp->device->id, tmp->device->lun); /* * REQUEST SENSE commands are issued without tagged @@ -2020,7 +2023,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) * accesses to this device will use the * polled-IO. */ printk(KERN_NOTICE "scsi%d: switching target %d " - "lun %d to slow handshake\n", HOSTNO, + "lun %llu to slow handshake\n", HOSTNO, cmd->device->id, cmd->device->lun); cmd->device->borken = 1; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | @@ -2078,7 +2081,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked command " + dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked command " "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun); /* Enable reselect interrupts */ @@ -2090,7 +2093,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) */ if (!cmd->next_link) { - printk(KERN_NOTICE "scsi%d: target %d lun %d " + printk(KERN_NOTICE "scsi%d: target %d lun %llu " "linked command complete, no next_link\n", HOSTNO, cmd->device->id, cmd->device->lun); sink = 1; @@ -2103,7 +2106,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) * and don't free it! */ cmd->next_link->tag = cmd->tag; cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked request " + dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request " "done, calling scsi_done().\n", HOSTNO, cmd->device->id, cmd->device->lun); #ifdef NCR5380_STATS @@ -2118,7 +2121,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); hostdata->connected = NULL; - dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %d " + dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu " "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); #ifdef SUPPORT_TAGS cmd_free_tag( cmd ); @@ -2132,7 +2135,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) /* ++Andreas: the mid level code knows about QUEUE_FULL now. */ TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d returned " + dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned " "QUEUE_FULL after %d commands\n", HOSTNO, cmd->device->id, cmd->device->lun, ta->nr_allocated); @@ -2228,7 +2231,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) cmd->device->tagged_supported = 0; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); cmd->tag = TAG_NONE; - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d rejected " + dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu rejected " "QUEUE_TAG message; tagged queuing " "disabled\n", HOSTNO, cmd->device->id, cmd->device->lun); @@ -2245,7 +2248,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) hostdata->connected = NULL; hostdata->disconnected_queue = cmd; local_irq_restore(flags); - dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %d was " + dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %llu was " "moved from connected to the " "disconnected_queue\n", HOSTNO, cmd->device->id, cmd->device->lun); @@ -2349,12 +2352,12 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) printk("\n"); } else if (tmp != EXTENDED_MESSAGE) printk(KERN_DEBUG "scsi%d: rejecting unknown " - "message %02x from target %d, lun %d\n", + "message %02x from target %d, lun %llu\n", HOSTNO, tmp, cmd->device->id, cmd->device->lun); else printk(KERN_DEBUG "scsi%d: rejecting unknown " "extended message " - "code %02x, length %d from target %d, lun %d\n", + "code %02x, length %d from target %d, lun %llu\n", HOSTNO, extended_msg[1], extended_msg[0], cmd->device->id, cmd->device->lun); @@ -2576,7 +2579,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance) #endif hostdata->connected = tmp; - dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %d, tag = %d\n", + dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n", HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag); } diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 6d3ee1a..e59e6f9 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -851,7 +851,7 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev) * so let's try to stop all on-going I/O. */ starget_printk(KERN_WARNING, tp->starget, - "Removing busy LCB (%d)\n", sdev->lun); + "Removing busy LCB (%d)\n", (u8)sdev->lun); sym_reset_scsi_bus(np, 1); } diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index 5a80cba..a141b17 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -581,7 +581,7 @@ struct sym_pmc { #define sym_lp(tp, lun) (!lun) ? (tp)->lun0p : NULL #else #define sym_lp(tp, lun) \ - (!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[(lun)] : NULL + (!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[((u8)lun)] : NULL #endif /* diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index b006cf7..7645757 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -621,7 +621,7 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr { dc390_freetag (pDCB, pSRB); DEBUG0(printk ("DC390: Interrupt during Start SCSI (target %02i-%02i)\n", - scmd->device->id, scmd->device->lun)); + scmd->device->id, (u8)scmd->device->lun)); pSRB->SRBState = SRB_READY; //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); pACB->SelLost++; @@ -1726,7 +1726,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* } else { SET_RES_DRV(pcmd->result, DRIVER_SENSE); //pSRB->ScsiCmdLen = (u8) (pSRB->Segment1[0] >> 8); - DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun)); pSRB->TotalXferredLen = 0; SET_RES_DID(pcmd->result, DID_SOFT_ERROR); } @@ -1746,7 +1746,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* else if (status == SAM_STAT_TASK_SET_FULL) { scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1); - DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun)); pSRB->TotalXferredLen = 0; SET_RES_DID(pcmd->result, DID_SOFT_ERROR); } diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 5a03bb3..4e76fe8 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -1285,14 +1285,14 @@ static int u14_34f_queuecommand_lck(struct scsi_cmnd *SCpnt, void (*done)(struct cpp->cpp_index = i; SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index; - if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d.\n", + if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%llu.\n", BN(j), i, SCpnt->device->channel, SCpnt->device->id, - SCpnt->device->lun); + (u8)SCpnt->device->lun); cpp->opcode = OP_SCSI; cpp->channel = SCpnt->device->channel; cpp->target = SCpnt->device->id; - cpp->lun = SCpnt->device->lun; + cpp->lun = (u8)SCpnt->device->lun; cpp->SCpnt = SCpnt; cpp->cdb_len = SCpnt->cmd_len; memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len); @@ -1663,10 +1663,10 @@ static int reorder(unsigned int j, unsigned long cursec, if (link_statistics && (overlap || !(flushcount % link_statistics))) for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - printk("%s %d.%d:%d mb %d fc %d nr %d sec %ld ns %u"\ + printk("%s %d.%d:%llu mb %d fc %d nr %d sec %ld ns %u"\ " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, - SCpnt->lun, k, flushcount, n_ready, + (u8)SCpnt->lun, k, flushcount, n_ready, blk_rq_pos(SCpnt->request), blk_rq_sectors(SCpnt->request), cursec, YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), YESNO(overlap), cpp->xdir); diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index f42d1ce..fafcf5e 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -41,7 +41,8 @@ #define MAX_CDB_SIZE 16 #define GENERAL_UPIU_REQUEST_SIZE 32 -#define QUERY_DESC_MAX_SIZE 256 +#define QUERY_DESC_MAX_SIZE 255 +#define QUERY_DESC_MIN_SIZE 2 #define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \ (sizeof(struct utp_upiu_header))) @@ -117,6 +118,41 @@ enum attr_idn { QUERY_ATTR_IDN_EE_STATUS = 0x0E, }; +/* Descriptor idn for Query requests */ +enum desc_idn { + QUERY_DESC_IDN_DEVICE = 0x0, + QUERY_DESC_IDN_CONFIGURAION = 0x1, + QUERY_DESC_IDN_UNIT = 0x2, + QUERY_DESC_IDN_RFU_0 = 0x3, + QUERY_DESC_IDN_INTERCONNECT = 0x4, + QUERY_DESC_IDN_STRING = 0x5, + QUERY_DESC_IDN_RFU_1 = 0x6, + QUERY_DESC_IDN_GEOMETRY = 0x7, + QUERY_DESC_IDN_POWER = 0x8, + QUERY_DESC_IDN_RFU_2 = 0x9, +}; + +#define UNIT_DESC_MAX_SIZE 0x22 +/* Unit descriptor parameters offsets in bytes*/ +enum unit_desc_param { + UNIT_DESC_PARAM_LEN = 0x0, + UNIT_DESC_PARAM_TYPE = 0x1, + UNIT_DESC_PARAM_UNIT_INDEX = 0x2, + UNIT_DESC_PARAM_LU_ENABLE = 0x3, + UNIT_DESC_PARAM_BOOT_LUN_ID = 0x4, + UNIT_DESC_PARAM_LU_WR_PROTECT = 0x5, + UNIT_DESC_PARAM_LU_Q_DEPTH = 0x6, + UNIT_DESC_PARAM_MEM_TYPE = 0x8, + UNIT_DESC_PARAM_DATA_RELIABILITY = 0x9, + UNIT_DESC_PARAM_LOGICAL_BLK_SIZE = 0xA, + UNIT_DESC_PARAM_LOGICAL_BLK_COUNT = 0xB, + UNIT_DESC_PARAM_ERASE_BLK_SIZE = 0x13, + UNIT_DESC_PARAM_PROVISIONING_TYPE = 0x17, + UNIT_DESC_PARAM_PHY_MEM_RSRC_CNT = 0x18, + UNIT_DESC_PARAM_CTX_CAPABILITIES = 0x20, + UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1 = 0x22, +}; + /* Exception event mask values */ enum { MASK_EE_STATUS = 0xFFFF, diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 8b95312..c007a7a 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -135,26 +135,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev) } /** - * ufshcd_set_dma_mask - Set dma mask based on the controller - * addressing capability - * @pdev: PCI device structure - * - * Returns 0 for success, non-zero for failure - */ -static int ufshcd_set_dma_mask(struct pci_dev *pdev) -{ - int err; - - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) - && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) - return 0; - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - return err; -} - -/** * ufshcd_pci_probe - probe routine of the driver * @pdev: pointer to PCI device handle * @id: PCI device id @@ -184,12 +164,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) mmio_base = pcim_iomap_table(pdev)[0]; - err = ufshcd_set_dma_mask(pdev); - if (err) { - dev_err(&pdev->dev, "set dma mask failed\n"); - return err; - } - err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq); if (err) { dev_err(&pdev->dev, "Initialization failed\n"); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 0c28772..ba27215 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -110,6 +110,8 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba); static void ufshcd_async_scan(void *data, async_cookie_t cookie); static int ufshcd_reset_and_restore(struct ufs_hba *hba); static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); +static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba, + struct scsi_device *sdev); /* * ufshcd_wait_for_register - wait for register value to change @@ -446,30 +448,35 @@ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp) * @lrb - pointer to local reference block */ static -void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) +int ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { struct ufs_query_res *query_res = &hba->dev_cmd.query.response; - /* Get the UPIU response */ - query_res->response = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >> - UPIU_RSP_CODE_OFFSET; - memcpy(&query_res->upiu_res, &lrbp->ucd_rsp_ptr->qr, QUERY_OSF_SIZE); - /* Get the descriptor */ if (lrbp->ucd_rsp_ptr->qr.opcode == UPIU_QUERY_OPCODE_READ_DESC) { - u8 *descp = (u8 *)&lrbp->ucd_rsp_ptr + + u8 *descp = (u8 *)lrbp->ucd_rsp_ptr + GENERAL_UPIU_REQUEST_SIZE; - u16 len; + u16 resp_len; + u16 buf_len; /* data segment length */ - len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) & + resp_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) & MASK_QUERY_DATA_SEG_LEN; - - memcpy(hba->dev_cmd.query.descriptor, descp, - min_t(u16, len, QUERY_DESC_MAX_SIZE)); + buf_len = be16_to_cpu( + hba->dev_cmd.query.request.upiu_req.length); + if (likely(buf_len >= resp_len)) { + memcpy(hba->dev_cmd.query.descriptor, descp, resp_len); + } else { + dev_warn(hba->dev, + "%s: Response size is bigger than buffer", + __func__); + return -EINVAL; + } } + + return 0; } /** @@ -797,11 +804,9 @@ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba, QUERY_OSF_SIZE); /* Copy the Descriptor */ - if ((len > 0) && (query->request.upiu_req.opcode == - UPIU_QUERY_OPCODE_WRITE_DESC)) { - memcpy(descp, query->descriptor, - min_t(u16, len, QUERY_DESC_MAX_SIZE)); - } + if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC) + memcpy(descp, query->descriptor, len); + } static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp) @@ -980,6 +985,17 @@ ufshcd_clear_cmd(struct ufs_hba *hba, int tag) return err; } +static int +ufshcd_check_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) +{ + struct ufs_query_res *query_res = &hba->dev_cmd.query.response; + + /* Get the UPIU response */ + query_res->response = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >> + UPIU_RSP_CODE_OFFSET; + return query_res->response; +} + /** * ufshcd_dev_cmd_completion() - handles device management command responses * @hba: per adapter instance @@ -1002,7 +1018,9 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) } break; case UPIU_TRANSACTION_QUERY_RSP: - ufshcd_copy_query_response(hba, lrbp); + err = ufshcd_check_query_response(hba, lrbp); + if (!err) + err = ufshcd_copy_query_response(hba, lrbp); break; case UPIU_TRANSACTION_REJECT_UPIU: /* TODO: handle Reject UPIU Response */ @@ -1134,6 +1152,30 @@ out_put_tag: } /** + * ufshcd_init_query() - init the query response and request parameters + * @hba: per-adapter instance + * @request: address of the request pointer to be initialized + * @response: address of the response pointer to be initialized + * @opcode: operation to perform + * @idn: flag idn to access + * @index: LU number to access + * @selector: query/flag/descriptor further identification + */ +static inline void ufshcd_init_query(struct ufs_hba *hba, + struct ufs_query_req **request, struct ufs_query_res **response, + enum query_opcode opcode, u8 idn, u8 index, u8 selector) +{ + *request = &hba->dev_cmd.query.request; + *response = &hba->dev_cmd.query.response; + memset(*request, 0, sizeof(struct ufs_query_req)); + memset(*response, 0, sizeof(struct ufs_query_res)); + (*request)->upiu_req.opcode = opcode; + (*request)->upiu_req.idn = idn; + (*request)->upiu_req.index = index; + (*request)->upiu_req.selector = selector; +} + +/** * ufshcd_query_flag() - API function for sending flag query requests * hba: per-adapter instance * query_opcode: flag query to perform @@ -1145,17 +1187,15 @@ out_put_tag: static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, bool *flag_res) { - struct ufs_query_req *request; - struct ufs_query_res *response; - int err; + struct ufs_query_req *request = NULL; + struct ufs_query_res *response = NULL; + int err, index = 0, selector = 0; BUG_ON(!hba); mutex_lock(&hba->dev_cmd.lock); - request = &hba->dev_cmd.query.request; - response = &hba->dev_cmd.query.response; - memset(request, 0, sizeof(struct ufs_query_req)); - memset(response, 0, sizeof(struct ufs_query_res)); + ufshcd_init_query(hba, &request, &response, opcode, idn, index, + selector); switch (opcode) { case UPIU_QUERY_OPCODE_SET_FLAG: @@ -1180,12 +1220,8 @@ static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, err = -EINVAL; goto out_unlock; } - request->upiu_req.opcode = opcode; - request->upiu_req.idn = idn; - /* Send query request */ - err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, - QUERY_REQ_TIMEOUT); + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); if (err) { dev_err(hba->dev, @@ -1217,8 +1253,8 @@ out_unlock: static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector, u32 *attr_val) { - struct ufs_query_req *request; - struct ufs_query_res *response; + struct ufs_query_req *request = NULL; + struct ufs_query_res *response = NULL; int err; BUG_ON(!hba); @@ -1231,10 +1267,8 @@ static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, } mutex_lock(&hba->dev_cmd.lock); - request = &hba->dev_cmd.query.request; - response = &hba->dev_cmd.query.response; - memset(request, 0, sizeof(struct ufs_query_req)); - memset(response, 0, sizeof(struct ufs_query_res)); + ufshcd_init_query(hba, &request, &response, opcode, idn, index, + selector); switch (opcode) { case UPIU_QUERY_OPCODE_WRITE_ATTR: @@ -1251,14 +1285,7 @@ static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, goto out_unlock; } - request->upiu_req.opcode = opcode; - request->upiu_req.idn = idn; - request->upiu_req.index = index; - request->upiu_req.selector = selector; - - /* Send query request */ - err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, - QUERY_REQ_TIMEOUT); + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); if (err) { dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n", @@ -1275,6 +1302,82 @@ out: } /** + * ufshcd_query_descriptor - API function for sending descriptor requests + * hba: per-adapter instance + * opcode: attribute opcode + * idn: attribute idn to access + * index: index field + * selector: selector field + * desc_buf: the buffer that contains the descriptor + * buf_len: length parameter passed to the device + * + * Returns 0 for success, non-zero in case of failure. + * The buf_len parameter will contain, on return, the length parameter + * received on the response. + */ +static int ufshcd_query_descriptor(struct ufs_hba *hba, + enum query_opcode opcode, enum desc_idn idn, u8 index, + u8 selector, u8 *desc_buf, int *buf_len) +{ + struct ufs_query_req *request = NULL; + struct ufs_query_res *response = NULL; + int err; + + BUG_ON(!hba); + + if (!desc_buf) { + dev_err(hba->dev, "%s: descriptor buffer required for opcode 0x%x\n", + __func__, opcode); + err = -EINVAL; + goto out; + } + + if (*buf_len <= QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { + dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n", + __func__, *buf_len); + err = -EINVAL; + goto out; + } + + mutex_lock(&hba->dev_cmd.lock); + ufshcd_init_query(hba, &request, &response, opcode, idn, index, + selector); + hba->dev_cmd.query.descriptor = desc_buf; + request->upiu_req.length = cpu_to_be16(*buf_len); + + switch (opcode) { + case UPIU_QUERY_OPCODE_WRITE_DESC: + request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST; + break; + case UPIU_QUERY_OPCODE_READ_DESC: + request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST; + break; + default: + dev_err(hba->dev, + "%s: Expected query descriptor opcode but got = 0x%.2x\n", + __func__, opcode); + err = -EINVAL; + goto out_unlock; + } + + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); + + if (err) { + dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n", + __func__, opcode, idn, err); + goto out_unlock; + } + + hba->dev_cmd.query.descriptor = NULL; + *buf_len = be16_to_cpu(response->upiu_res.length); + +out_unlock: + mutex_unlock(&hba->dev_cmd.lock); +out: + return err; +} + +/** * ufshcd_memory_alloc - allocate memory for host memory space data structures * @hba: per adapter instance * @@ -1878,6 +1981,7 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba) static int ufshcd_slave_alloc(struct scsi_device *sdev) { struct ufs_hba *hba; + int lun_qdepth; hba = shost_priv(sdev->host); sdev->tagged_supported = 1; @@ -1889,14 +1993,68 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev) /* allow SCSI layer to restart the device in case of errors */ sdev->allow_restart = 1; - /* - * Inform SCSI Midlayer that the LUN queue depth is same as the - * controller queue depth. If a LUN queue depth is less than the - * controller queue depth and if the LUN reports - * SAM_STAT_TASK_SET_FULL, the LUN queue depth will be adjusted - * with scsi_adjust_queue_depth. - */ - scsi_activate_tcq(sdev, hba->nutrs); + /* REPORT SUPPORTED OPERATION CODES is not supported */ + sdev->no_report_opcodes = 1; + + lun_qdepth = ufshcd_read_sdev_qdepth(hba, sdev); + if (lun_qdepth <= 0) + /* eventually, we can figure out the real queue depth */ + lun_qdepth = hba->nutrs; + else + lun_qdepth = min_t(int, lun_qdepth, hba->nutrs); + + dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n", + __func__, lun_qdepth); + scsi_activate_tcq(sdev, lun_qdepth); + + return 0; +} + +/** + * ufshcd_change_queue_depth - change queue depth + * @sdev: pointer to SCSI device + * @depth: required depth to set + * @reason: reason for changing the depth + * + * Change queue depth according to the reason and make sure + * the max. limits are not crossed. + */ +static int ufshcd_change_queue_depth(struct scsi_device *sdev, + int depth, int reason) +{ + struct ufs_hba *hba = shost_priv(sdev->host); + + if (depth > hba->nutrs) + depth = hba->nutrs; + + switch (reason) { + case SCSI_QDEPTH_DEFAULT: + case SCSI_QDEPTH_RAMP_UP: + if (!sdev->tagged_supported) + depth = 1; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); + break; + case SCSI_QDEPTH_QFULL: + scsi_track_queue_full(sdev, depth); + break; + default: + return -EOPNOTSUPP; + } + + return depth; +} + +/** + * ufshcd_slave_configure - adjust SCSI device configurations + * @sdev: pointer to SCSI device + */ +static int ufshcd_slave_configure(struct scsi_device *sdev) +{ + struct request_queue *q = sdev->request_queue; + + blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); + blk_queue_max_segment_size(q, PRDT_DATA_BYTE_COUNT_MAX); + return 0; } @@ -1953,42 +2111,6 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp) } /** - * ufshcd_adjust_lun_qdepth - Update LUN queue depth if device responds with - * SAM_STAT_TASK_SET_FULL SCSI command status. - * @cmd: pointer to SCSI command - */ -static void ufshcd_adjust_lun_qdepth(struct scsi_cmnd *cmd) -{ - struct ufs_hba *hba; - int i; - int lun_qdepth = 0; - - hba = shost_priv(cmd->device->host); - - /* - * LUN queue depth can be obtained by counting outstanding commands - * on the LUN. - */ - for (i = 0; i < hba->nutrs; i++) { - if (test_bit(i, &hba->outstanding_reqs)) { - - /* - * Check if the outstanding command belongs - * to the LUN which reported SAM_STAT_TASK_SET_FULL. - */ - if (cmd->device->lun == hba->lrb[i].lun) - lun_qdepth++; - } - } - - /* - * LUN queue depth will be total outstanding commands, except the - * command for which the LUN reported SAM_STAT_TASK_SET_FULL. - */ - scsi_adjust_queue_depth(cmd->device, MSG_SIMPLE_TAG, lun_qdepth - 1); -} - -/** * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status * @lrb: pointer to local reference block of completed command * @scsi_status: SCSI command status @@ -2009,12 +2131,6 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb *lrbp, int scsi_status) scsi_status; break; case SAM_STAT_TASK_SET_FULL: - /* - * If a LUN reports SAM_STAT_TASK_SET_FULL, then the LUN queue - * depth needs to be adjusted to the exact number of - * outstanding commands the LUN can handle at any given time. - */ - ufshcd_adjust_lun_qdepth(lrbp->cmd); case SAM_STAT_BUSY: case SAM_STAT_TASK_ABORTED: ufshcd_copy_sense_data(lrbp); @@ -2134,47 +2250,42 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) u32 tr_doorbell; int result; int index; - bool int_aggr_reset = false; + + /* Resetting interrupt aggregation counters first and reading the + * DOOR_BELL afterward allows us to handle all the completed requests. + * In order to prevent other interrupts starvation the DB is read once + * after reset. The down side of this solution is the possibility of + * false interrupt if device completes another request after resetting + * aggregation and before reading the DB. + */ + ufshcd_reset_intr_aggr(hba); tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); completed_reqs = tr_doorbell ^ hba->outstanding_reqs; - for (index = 0; index < hba->nutrs; index++) { - if (test_bit(index, &completed_reqs)) { - lrbp = &hba->lrb[index]; - cmd = lrbp->cmd; - /* - * Don't skip resetting interrupt aggregation counters - * if a regular command is present. - */ - int_aggr_reset |= !lrbp->intr_cmd; - - if (cmd) { - result = ufshcd_transfer_rsp_status(hba, lrbp); - scsi_dma_unmap(cmd); - cmd->result = result; - /* Mark completed command as NULL in LRB */ - lrbp->cmd = NULL; - clear_bit_unlock(index, &hba->lrb_in_use); - /* Do not touch lrbp after scsi done */ - cmd->scsi_done(cmd); - } else if (lrbp->command_type == - UTP_CMD_TYPE_DEV_MANAGE) { - if (hba->dev_cmd.complete) - complete(hba->dev_cmd.complete); - } - } /* end of if */ - } /* end of for */ + for_each_set_bit(index, &completed_reqs, hba->nutrs) { + lrbp = &hba->lrb[index]; + cmd = lrbp->cmd; + if (cmd) { + result = ufshcd_transfer_rsp_status(hba, lrbp); + scsi_dma_unmap(cmd); + cmd->result = result; + /* Mark completed command as NULL in LRB */ + lrbp->cmd = NULL; + clear_bit_unlock(index, &hba->lrb_in_use); + /* Do not touch lrbp after scsi done */ + cmd->scsi_done(cmd); + } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) { + if (hba->dev_cmd.complete) + complete(hba->dev_cmd.complete); + } + } /* clear corresponding bits of completed commands */ hba->outstanding_reqs ^= completed_reqs; /* we might have free'd some tags above */ wake_up(&hba->dev_cmd.tag_wq); - - /* Reset interrupt aggregation counters */ - if (int_aggr_reset) - ufshcd_reset_intr_aggr(hba); } /** @@ -2779,6 +2890,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) int poll_cnt; u8 resp = 0xF; struct ufshcd_lrb *lrbp; + u32 reg; host = cmd->device->host; hba = shost_priv(host); @@ -2788,6 +2900,13 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) if (!(test_bit(tag, &hba->outstanding_reqs))) goto out; + reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); + if (!(reg & (1 << tag))) { + dev_err(hba->dev, + "%s: cmd was completed, but without a notifying intr, tag = %d", + __func__, tag); + } + lrbp = &hba->lrb[tag]; for (poll_cnt = 100; poll_cnt; poll_cnt--) { err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag, @@ -2796,8 +2915,6 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) /* cmd pending in the device */ break; } else if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_COMPL) { - u32 reg; - /* * cmd not pending in the device, check if it is * in transition. @@ -2971,6 +3088,38 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd) } /** + * ufshcd_read_sdev_qdepth - read the lun command queue depth + * @hba: Pointer to adapter instance + * @sdev: pointer to SCSI device + * + * Return in case of success the lun's queue depth else error. + */ +static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba, + struct scsi_device *sdev) +{ + int ret; + int buff_len = UNIT_DESC_MAX_SIZE; + u8 desc_buf[UNIT_DESC_MAX_SIZE]; + + ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC, + QUERY_DESC_IDN_UNIT, sdev->lun, 0, desc_buf, &buff_len); + + if (ret || (buff_len < UNIT_DESC_PARAM_LU_Q_DEPTH)) { + dev_err(hba->dev, + "%s:Failed reading unit descriptor. len = %d ret = %d" + , __func__, buff_len, ret); + if (!ret) + ret = -EINVAL; + + goto out; + } + + ret = desc_buf[UNIT_DESC_PARAM_LU_Q_DEPTH] & 0xFF; +out: + return ret; +} + +/** * ufshcd_async_scan - asynchronous execution for link startup * @data: data pointer to pass to this function * @cookie: cookie data @@ -3012,7 +3161,9 @@ static struct scsi_host_template ufshcd_driver_template = { .proc_name = UFSHCD, .queuecommand = ufshcd_queuecommand, .slave_alloc = ufshcd_slave_alloc, + .slave_configure = ufshcd_slave_configure, .slave_destroy = ufshcd_slave_destroy, + .change_queue_depth = ufshcd_change_queue_depth, .eh_abort_handler = ufshcd_abort, .eh_device_reset_handler = ufshcd_eh_device_reset_handler, .eh_host_reset_handler = ufshcd_eh_host_reset_handler, @@ -3110,6 +3261,22 @@ void ufshcd_remove(struct ufs_hba *hba) EXPORT_SYMBOL_GPL(ufshcd_remove); /** + * ufshcd_set_dma_mask - Set dma mask based on the controller + * addressing capability + * @hba: per adapter instance + * + * Returns 0 for success, non-zero for failure + */ +static int ufshcd_set_dma_mask(struct ufs_hba *hba) +{ + if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) { + if (!dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(64))) + return 0; + } + return dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(32)); +} + +/** * ufshcd_init - Driver initialization routine * @dev: pointer to device handle * @hba_handle: driver private handle @@ -3160,6 +3327,12 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, /* Get Interrupt bit mask per version */ hba->intr_mask = ufshcd_get_intr_mask(hba); + err = ufshcd_set_dma_mask(hba); + if (err) { + dev_err(hba->dev, "set dma mask failed\n"); + goto out_disable; + } + /* Allocate memory for host memory space */ err = ufshcd_memory_alloc(hba); if (err) { diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index 9abc7e3..e1b844b 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h @@ -296,6 +296,11 @@ enum { MASK_OCS = 0x0F, }; +/* The maximum length of the data byte count field in the PRDT is 256KB */ +#define PRDT_DATA_BYTE_COUNT_MAX (256 * 1024) +/* The granularity of the data byte count field in the PRDT is 32-bit */ +#define PRDT_DATA_BYTE_COUNT_PAD 4 + /** * struct ufshcd_sg_entry - UFSHCI PRD Entry * @base_addr: Lower 32bit physical address DW-0 diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 308256b..eee1bc0 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -27,6 +27,8 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> #include <scsi/scsi_cmnd.h> +#include <scsi/scsi_tcq.h> +#include <linux/seqlock.h> #define VIRTIO_SCSI_MEMPOOL_SZ 64 #define VIRTIO_SCSI_EVENT_LEN 8 @@ -75,18 +77,16 @@ struct virtio_scsi_vq { * queue, and also lets the driver optimize the IRQ affinity for the virtqueues * (each virtqueue's affinity is set to the CPU that "owns" the queue). * - * tgt_lock is held to serialize reading and writing req_vq. Reading req_vq - * could be done locklessly, but we do not do it yet. + * tgt_seq is held to serialize reading and writing req_vq. * * Decrements of reqs are never concurrent with writes of req_vq: before the * decrement reqs will be != 0; after the decrement the virtqueue completion * routine will not use the req_vq so it can be changed by a new request. - * Thus they can happen outside the tgt_lock, provided of course we make reqs + * Thus they can happen outside the tgt_seq, provided of course we make reqs * an atomic_t. */ struct virtio_scsi_target_state { - /* This spinlock never held at the same time as vq_lock. */ - spinlock_t tgt_lock; + seqcount_t tgt_seq; /* Count of outstanding requests. */ atomic_t reqs; @@ -559,19 +559,33 @@ static struct virtio_scsi_vq *virtscsi_pick_vq(struct virtio_scsi *vscsi, unsigned long flags; u32 queue_num; - spin_lock_irqsave(&tgt->tgt_lock, flags); + local_irq_save(flags); + if (atomic_inc_return(&tgt->reqs) > 1) { + unsigned long seq; + + do { + seq = read_seqcount_begin(&tgt->tgt_seq); + vq = tgt->req_vq; + } while (read_seqcount_retry(&tgt->tgt_seq, seq)); + } else { + /* no writes can be concurrent because of atomic_t */ + write_seqcount_begin(&tgt->tgt_seq); + + /* keep previous req_vq if a reader just arrived */ + if (unlikely(atomic_read(&tgt->reqs) > 1)) { + vq = tgt->req_vq; + goto unlock; + } - if (atomic_inc_return(&tgt->reqs) > 1) - vq = tgt->req_vq; - else { queue_num = smp_processor_id(); while (unlikely(queue_num >= vscsi->num_queues)) queue_num -= vscsi->num_queues; - tgt->req_vq = vq = &vscsi->req_vqs[queue_num]; + unlock: + write_seqcount_end(&tgt->tgt_seq); } + local_irq_restore(flags); - spin_unlock_irqrestore(&tgt->tgt_lock, flags); return vq; } @@ -641,6 +655,36 @@ static int virtscsi_device_reset(struct scsi_cmnd *sc) return virtscsi_tmf(vscsi, cmd); } +/** + * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth + * @sdev: Virtscsi target whose queue depth to change + * @qdepth: New queue depth + * @reason: Reason for the queue depth change. + */ +static int virtscsi_change_queue_depth(struct scsi_device *sdev, + int qdepth, + int reason) +{ + struct Scsi_Host *shost = sdev->host; + int max_depth = shost->cmd_per_lun; + + switch (reason) { + case SCSI_QDEPTH_QFULL: /* Drop qdepth in response to BUSY state */ + scsi_track_queue_full(sdev, qdepth); + break; + case SCSI_QDEPTH_RAMP_UP: /* Raise qdepth after BUSY state resolved */ + case SCSI_QDEPTH_DEFAULT: /* Manual change via sysfs */ + scsi_adjust_queue_depth(sdev, + scsi_get_tag_type(sdev), + min(max_depth, qdepth)); + break; + default: + return -EOPNOTSUPP; + } + + return sdev->queue_depth; +} + static int virtscsi_abort(struct scsi_cmnd *sc) { struct virtio_scsi *vscsi = shost_priv(sc->device->host); @@ -667,14 +711,17 @@ static int virtscsi_abort(struct scsi_cmnd *sc) static int virtscsi_target_alloc(struct scsi_target *starget) { + struct Scsi_Host *sh = dev_to_shost(starget->dev.parent); + struct virtio_scsi *vscsi = shost_priv(sh); + struct virtio_scsi_target_state *tgt = kmalloc(sizeof(*tgt), GFP_KERNEL); if (!tgt) return -ENOMEM; - spin_lock_init(&tgt->tgt_lock); + seqcount_init(&tgt->tgt_seq); atomic_set(&tgt->reqs, 0); - tgt->req_vq = NULL; + tgt->req_vq = &vscsi->req_vqs[0]; starget->hostdata = tgt; return 0; @@ -693,6 +740,7 @@ static struct scsi_host_template virtscsi_host_template_single = { .this_id = -1, .cmd_size = sizeof(struct virtio_scsi_cmd), .queuecommand = virtscsi_queuecommand_single, + .change_queue_depth = virtscsi_change_queue_depth, .eh_abort_handler = virtscsi_abort, .eh_device_reset_handler = virtscsi_device_reset, @@ -710,6 +758,7 @@ static struct scsi_host_template virtscsi_host_template_multi = { .this_id = -1, .cmd_size = sizeof(struct virtio_scsi_cmd), .queuecommand = virtscsi_queuecommand_multi, + .change_queue_depth = virtscsi_change_queue_depth, .eh_abort_handler = virtscsi_abort, .eh_device_reset_handler = virtscsi_device_reset, diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index c88e146..598f65e 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c @@ -1194,7 +1194,7 @@ static int pvscsi_setup_msix(const struct pvscsi_adapter *adapter, struct msix_entry entry = { 0, PVSCSI_VECTOR_COMPLETION }; int ret; - ret = pci_enable_msix(adapter->dev, &entry, 1); + ret = pci_enable_msix_exact(adapter->dev, &entry, 1); if (ret) return ret; diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 41883a8..c0506de 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -502,7 +502,8 @@ wd33c93_execute(struct Scsi_Host *instance) cmd = (struct scsi_cmnd *) hostdata->input_Q; prev = NULL; while (cmd) { - if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))) + if (!(hostdata->busy[cmd->device->id] & + (1 << (cmd->device->lun & 0xff)))) break; prev = cmd; cmd = (struct scsi_cmnd *) cmd->host_scribble; @@ -593,10 +594,10 @@ wd33c93_execute(struct Scsi_Host *instance) write_wd33c93(regs, WD_SOURCE_ID, ((cmd->SCp.phase) ? SRCID_ER : 0)); - write_wd33c93(regs, WD_TARGET_LUN, cmd->device->lun); + write_wd33c93(regs, WD_TARGET_LUN, (u8)cmd->device->lun); write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER, hostdata->sync_xfer[cmd->device->id]); - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF)); if ((hostdata->level2 == L2_NONE) || (hostdata->sync_stat[cmd->device->id] == SS_UNSET)) { @@ -862,7 +863,7 @@ wd33c93_intr(struct Scsi_Host *instance) } cmd->result = DID_NO_CONNECT << 16; - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); hostdata->state = S_UNCONNECTED; cmd->scsi_done(cmd); @@ -895,7 +896,7 @@ wd33c93_intr(struct Scsi_Host *instance) /* construct an IDENTIFY message with correct disconnect bit */ - hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->device->lun); + hostdata->outgoing_msg[0] = IDENTIFY(0, cmd->device->lun); if (cmd->SCp.phase) hostdata->outgoing_msg[0] |= 0x40; @@ -1179,7 +1180,7 @@ wd33c93_intr(struct Scsi_Host *instance) lun = read_wd33c93(regs, WD_TARGET_LUN); DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun)) hostdata->connected = NULL; - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); hostdata->state = S_UNCONNECTED; if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE) cmd->SCp.Status = lun; @@ -1268,7 +1269,7 @@ wd33c93_intr(struct Scsi_Host *instance) } DB(DB_INTR, printk("UNEXP_DISC")) hostdata->connected = NULL; - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); hostdata->state = S_UNCONNECTED; if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) cmd->result = @@ -1300,7 +1301,7 @@ wd33c93_intr(struct Scsi_Host *instance) switch (hostdata->state) { case S_PRE_CMP_DISC: hostdata->connected = NULL; - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); hostdata->state = S_UNCONNECTED; DB(DB_INTR, printk(":%d", cmd->SCp.Status)) if (cmd->cmnd[0] == REQUEST_SENSE @@ -1353,7 +1354,7 @@ wd33c93_intr(struct Scsi_Host *instance) if (hostdata->selecting) { cmd = (struct scsi_cmnd *) hostdata->selecting; hostdata->selecting = NULL; - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); cmd->host_scribble = (uchar *) hostdata->input_Q; hostdata->input_Q = cmd; @@ -1365,7 +1366,7 @@ wd33c93_intr(struct Scsi_Host *instance) if (cmd) { if (phs == 0x00) { hostdata->busy[cmd->device->id] &= - ~(1 << cmd->device->lun); + ~(1 << (cmd->device->lun & 0xff)); cmd->host_scribble = (uchar *) hostdata->input_Q; hostdata->input_Q = cmd; @@ -1448,7 +1449,7 @@ wd33c93_intr(struct Scsi_Host *instance) cmd = (struct scsi_cmnd *) hostdata->disconnected_Q; patch = NULL; while (cmd) { - if (id == cmd->device->id && lun == cmd->device->lun) + if (id == cmd->device->id && lun == (u8)cmd->device->lun) break; patch = cmd; cmd = (struct scsi_cmnd *) cmd->host_scribble; @@ -1459,7 +1460,7 @@ wd33c93_intr(struct Scsi_Host *instance) if (!cmd) { printk ("---TROUBLE: target %d.%d not in disconnect queue---", - id, lun); + id, (u8)lun); spin_unlock_irqrestore(&hostdata->lock, flags); return; } @@ -1705,7 +1706,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) sr = read_wd33c93(regs, WD_SCSI_STATUS); printk("asr=%02x, sr=%02x.", asr, sr); - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); hostdata->connected = NULL; hostdata->state = S_UNCONNECTED; cmd->result = DID_ABORT << 16; @@ -2169,7 +2170,7 @@ wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance) seq_printf(m, "\nconnected: "); if (hd->connected) { cmd = (struct scsi_cmnd *) hd->connected; - seq_printf(m, " %d:%d(%02x)", + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); } } @@ -2177,7 +2178,7 @@ wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance) seq_printf(m, "\ninput_Q: "); cmd = (struct scsi_cmnd *) hd->input_Q; while (cmd) { - seq_printf(m, " %d:%d(%02x)", + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); cmd = (struct scsi_cmnd *) cmd->host_scribble; } @@ -2186,7 +2187,7 @@ wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance) seq_printf(m, "\ndisconnected_Q:"); cmd = (struct scsi_cmnd *) hd->disconnected_Q; while (cmd) { - seq_printf(m, " %d:%d(%02x)", + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); cmd = (struct scsi_cmnd *) cmd->host_scribble; } diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index 2029b6f..e7a6ba20 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -463,14 +463,14 @@ static int rtsx_control_thread(void *__dev) else if (chip->srb->device->id) { dev_err(&dev->pci->dev, "Bad target number (%d:%d)\n", chip->srb->device->id, - chip->srb->device->lun); + (u8)chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; } else if (chip->srb->device->lun > chip->max_lun) { dev_err(&dev->pci->dev, "Bad LUN (%d:%d)\n", chip->srb->device->id, - chip->srb->device->lun); + (u8)chip->srb->device->lun); chip->srb->result = DID_BAD_TARGET << 16; } diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 8c64b87..340de9d 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -252,7 +252,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) { struct tcm_loop_cmd *tl_cmd; - pr_debug("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x" + pr_debug("tcm_loop_queuecommand() %d:%d:%d:%llu got CDB: 0x%02x" " scsi_buf_len: %u\n", sc->device->host->host_no, sc->device->id, sc->device->channel, sc->device->lun, sc->cmnd[0], scsi_bufflen(sc)); diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 94d00df..943b1db 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -312,7 +312,7 @@ static int pscsi_add_device_to_list(struct se_device *dev, if (!sd->queue_depth) { sd->queue_depth = PSCSI_DEFAULT_QUEUEDEPTH; - pr_err("Set broken SCSI Device %d:%d:%d" + pr_err("Set broken SCSI Device %d:%d:%llu" " queue_depth to %d\n", sd->channel, sd->id, sd->lun, sd->queue_depth); } @@ -375,7 +375,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd) int ret; if (scsi_device_get(sd)) { - pr_err("scsi_device_get() failed for %d:%d:%d:%d\n", + pr_err("scsi_device_get() failed for %d:%d:%d:%llu\n", sh->host_no, sd->channel, sd->id, sd->lun); spin_unlock_irq(sh->host_lock); return -EIO; @@ -401,7 +401,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd) return ret; } - pr_debug("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d:%d\n", + pr_debug("CORE_PSCSI[%d] - Added TYPE_DISK for %d:%d:%d:%llu\n", phv->phv_host_id, sh->host_no, sd->channel, sd->id, sd->lun); return 0; } @@ -417,7 +417,7 @@ static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd) int ret; if (scsi_device_get(sd)) { - pr_err("scsi_device_get() failed for %d:%d:%d:%d\n", + pr_err("scsi_device_get() failed for %d:%d:%d:%llu\n", sh->host_no, sd->channel, sd->id, sd->lun); spin_unlock_irq(sh->host_lock); return -EIO; @@ -429,7 +429,7 @@ static int pscsi_create_type_rom(struct se_device *dev, struct scsi_device *sd) scsi_device_put(sd); return ret; } - pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n", + pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%llu\n", phv->phv_host_id, scsi_device_type(sd->type), sh->host_no, sd->channel, sd->id, sd->lun); @@ -452,7 +452,7 @@ static int pscsi_create_type_other(struct se_device *dev, if (ret) return ret; - pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%d\n", + pr_debug("CORE_PSCSI[%d] - Added Type: %s for %d:%d:%d:%llu\n", phv->phv_host_id, scsi_device_type(sd->type), sh->host_no, sd->channel, sd->id, sd->lun); return 0; diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 9a26242..715f299 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -18,9 +18,7 @@ config USB_STORAGE This option depends on 'SCSI' support being enabled, but you probably also need 'SCSI device support: SCSI disk support' - (BLK_DEV_SD) for most USB storage devices. Some devices also - will require 'Probe all LUNs on each SCSI device' - (SCSI_MULTI_LUN). + (BLK_DEV_SD) for most USB storage devices. To compile this driver as a module, choose M here: the module will be called usb-storage. diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 073a2c3..38a4504 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -1498,7 +1498,7 @@ static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) { int ret; - usb_stor_dbg(us, "LUN=%d\n", srb->device->lun); + usb_stor_dbg(us, "LUN=%d\n", (u8)srb->device->lun); switch (srb->device->lun) { case 0: @@ -1524,7 +1524,7 @@ static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) break; default: - usb_stor_dbg(us, "Invalid LUN %d\n", srb->device->lun); + usb_stor_dbg(us, "Invalid LUN %d\n", (u8)srb->device->lun); ret = USB_STOR_TRANSPORT_ERROR; break; } diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index f1c9626..cedb292 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -347,14 +347,16 @@ static int usb_stor_control_thread(void * __us) */ else if (us->srb->device->id && !(us->fflags & US_FL_SCM_MULT_TARG)) { - usb_stor_dbg(us, "Bad target number (%d:%d)\n", - us->srb->device->id, us->srb->device->lun); + usb_stor_dbg(us, "Bad target number (%d:%llu)\n", + us->srb->device->id, + us->srb->device->lun); us->srb->result = DID_BAD_TARGET << 16; } else if (us->srb->device->lun > us->max_lun) { - usb_stor_dbg(us, "Bad LUN (%d:%d)\n", - us->srb->device->id, us->srb->device->lun); + usb_stor_dbg(us, "Bad LUN (%d:%llu)\n", + us->srb->device->id, + us->srb->device->lun); us->srb->result = DID_BAD_TARGET << 16; } diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index b1990c5..494f99e 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -381,6 +381,11 @@ extern int param_set_ulong(const char *val, const struct kernel_param *kp); extern int param_get_ulong(char *buffer, const struct kernel_param *kp); #define param_check_ulong(name, p) __param_check(name, p, unsigned long) +extern struct kernel_param_ops param_ops_ullong; +extern int param_set_ullong(const char *val, const struct kernel_param *kp); +extern int param_get_ullong(char *buffer, const struct kernel_param *kp); +#define param_check_ullong(name, p) __param_check(name, p, unsigned long long) + extern struct kernel_param_ops param_ops_charp; extern int param_set_charp(const char *val, const struct kernel_param *kp); extern int param_get_charp(char *buffer, const struct kernel_param *kp); diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index a964f72..f4ec8bb 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -229,10 +229,10 @@ void sg_init_one(struct scatterlist *, const void *, unsigned int); typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t); typedef void (sg_free_fn)(struct scatterlist *, unsigned int); -void __sg_free_table(struct sg_table *, unsigned int, sg_free_fn *); +void __sg_free_table(struct sg_table *, unsigned int, bool, sg_free_fn *); void sg_free_table(struct sg_table *); -int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t, - sg_alloc_fn *); +int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, + struct scatterlist *, gfp_t, sg_alloc_fn *); int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); int sg_alloc_table_from_pages(struct sg_table *sgt, struct page **pages, unsigned int n_pages, diff --git a/include/scsi/libsrp.h b/include/scsi/libsrp.h deleted file mode 100644 index f4105c9..0000000 --- a/include/scsi/libsrp.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef __LIBSRP_H__ -#define __LIBSRP_H__ - -#include <linux/list.h> -#include <linux/kfifo.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_host.h> -#include <scsi/srp.h> - -enum iue_flags { - V_DIOVER, - V_WRITE, - V_LINKED, - V_FLYING, -}; - -struct srp_buf { - dma_addr_t dma; - void *buf; -}; - -struct srp_queue { - void *pool; - void *items; - struct kfifo queue; - spinlock_t lock; -}; - -struct srp_target { - struct Scsi_Host *shost; - struct device *dev; - - spinlock_t lock; - struct list_head cmd_queue; - - size_t srp_iu_size; - struct srp_queue iu_queue; - size_t rx_ring_size; - struct srp_buf **rx_ring; - - void *ldata; -}; - -struct iu_entry { - struct srp_target *target; - - struct list_head ilist; - dma_addr_t remote_token; - unsigned long flags; - - struct srp_buf *sbuf; -}; - -typedef int (srp_rdma_t)(struct scsi_cmnd *, struct scatterlist *, int, - struct srp_direct_buf *, int, - enum dma_data_direction, unsigned int); -extern int srp_target_alloc(struct srp_target *, struct device *, size_t, size_t); -extern void srp_target_free(struct srp_target *); - -extern struct iu_entry *srp_iu_get(struct srp_target *); -extern void srp_iu_put(struct iu_entry *); - -extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64, u64); -extern int srp_transfer_data(struct scsi_cmnd *, struct srp_cmd *, - srp_rdma_t, int, int); - - -static inline struct srp_target *host_to_srp_target(struct Scsi_Host *host) -{ - return (struct srp_target *) host->hostdata; -} - -static inline int srp_cmd_direction(struct srp_cmd *cmd) -{ - return (cmd->buf_fmt >> 4) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; -} - -#endif diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 0a4edfe..e6df23c 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -332,6 +332,7 @@ static inline int scsi_status_is_good(int status) #define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ #define TYPE_RBC 0x0e #define TYPE_OSD 0x11 +#define TYPE_ZBC 0x14 #define TYPE_NO_LUN 0x7f /* SCSI protocols; these are taken from SPC-3 section 7.5 */ @@ -385,7 +386,7 @@ struct scsi_lun { #define SCSI_W_LUN_ACCESS_CONTROL (SCSI_W_LUN_BASE + 2) #define SCSI_W_LUN_TARGET_LOG_PAGE (SCSI_W_LUN_BASE + 3) -static inline int scsi_is_wlun(unsigned int lun) +static inline int scsi_is_wlun(u64 lun) { return (lun & 0xff00) == SCSI_W_LUN_BASE; } diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index e0ae710..73f3490 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -150,9 +150,7 @@ static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) } extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); -extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t); extern void scsi_put_command(struct scsi_cmnd *); -extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *); extern void scsi_finish_command(struct scsi_cmnd *cmd); extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, @@ -160,7 +158,6 @@ extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, extern void scsi_kunmap_atomic_sg(void *virt); extern int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask); -extern void scsi_release_buffers(struct scsi_cmnd *cmd); extern int scsi_dma_map(struct scsi_cmnd *cmd); extern void scsi_dma_unmap(struct scsi_cmnd *cmd); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 27ab310..1a0d184 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -81,9 +81,9 @@ struct scsi_device { struct list_head siblings; /* list of all devices on this host */ struct list_head same_target_siblings; /* just the devices sharing same target id */ - /* this is now protected by the request_queue->queue_lock */ - unsigned int device_busy; /* commands actually active on - * low-level. protected by queue_lock. */ + atomic_t device_busy; /* commands actually active on LLDD */ + 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; @@ -98,8 +98,8 @@ struct scsi_device { unsigned long last_queue_ramp_up; /* last queue ramp up time */ - unsigned int id, lun, channel; - + unsigned int id, channel; + u64 lun; unsigned int manufacturer; /* Manufacturer of device, for using * vendor-specific cmd's */ unsigned sector_size; /* size in bytes */ @@ -127,7 +127,6 @@ struct scsi_device { * pass settings from slave_alloc to scsi * core. */ unsigned int eh_timeout; /* Error handling timeout */ - unsigned writeable:1; unsigned removable:1; unsigned changed:1; /* Data invalid due to media change */ unsigned busy:1; /* Used to prevent races */ @@ -155,6 +154,7 @@ struct scsi_device { unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */ unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */ unsigned skip_vpd_pages:1; /* do not read VPD pages */ + unsigned try_vpd_pages:1; /* attempt to read VPD pages */ unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */ unsigned no_start_on_add:1; /* do not issue start on add */ unsigned allow_restart:1; /* issue START_UNIT in error handler */ @@ -182,8 +182,6 @@ struct scsi_device { struct list_head event_list; /* asserted events */ struct work_struct event_work; - unsigned int device_blocked; /* Device returned QUEUE_FULL. */ - unsigned int max_device_blocked; /* what device_blocked counts down from */ #define SCSI_DEFAULT_DEVICE_BLOCKED 3 @@ -291,14 +289,15 @@ struct scsi_target { unsigned int expecting_lun_change:1; /* A device has reported * a 3F/0E UA, other devices on * the same target will also. */ - /* commands actually active on LLD. protected by host lock. */ - unsigned int target_busy; + /* commands actually active on LLD. */ + atomic_t target_busy; + atomic_t target_blocked; + /* * LLDs should set this in the slave_alloc host template callout. * If set to zero then there is not limit. */ unsigned int can_queue; - unsigned int target_blocked; unsigned int max_target_blocked; #define SCSI_DEFAULT_TARGET_BLOCKED 3 @@ -321,9 +320,9 @@ static inline struct scsi_target *scsi_target(struct scsi_device *sdev) dev_printk(prefix, &(starget)->dev, fmt, ##a) extern struct scsi_device *__scsi_add_device(struct Scsi_Host *, - uint, uint, uint, void *hostdata); + uint, uint, u64, void *hostdata); extern int scsi_add_device(struct Scsi_Host *host, uint channel, - uint target, uint lun); + uint target, u64 lun); extern int scsi_register_device_handler(struct scsi_device_handler *scsi_dh); extern void scsi_remove_device(struct scsi_device *); extern int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh); @@ -332,13 +331,13 @@ void scsi_attach_vpd(struct scsi_device *sdev); extern int scsi_device_get(struct scsi_device *); extern void scsi_device_put(struct scsi_device *); extern struct scsi_device *scsi_device_lookup(struct Scsi_Host *, - uint, uint, uint); + uint, uint, u64); extern struct scsi_device *__scsi_device_lookup(struct Scsi_Host *, - uint, uint, uint); + uint, uint, u64); extern struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *, - uint); + u64); extern struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *, - uint); + u64); extern void starget_for_each_device(struct scsi_target *, void *, void (*fn)(struct scsi_device *, void *)); extern void __starget_for_each_device(struct scsi_target *, void *, @@ -411,13 +410,13 @@ extern void scsi_device_resume(struct scsi_device *sdev); extern void scsi_target_quiesce(struct scsi_target *); extern void scsi_target_resume(struct scsi_target *); extern void scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, unsigned int lun, int rescan); + unsigned int id, u64 lun, int rescan); extern void scsi_target_reap(struct scsi_target *); extern void scsi_target_block(struct device *); extern void scsi_target_unblock(struct device *, enum scsi_device_state); extern void scsi_remove_target(struct device *); -extern void int_to_scsilun(unsigned int, struct scsi_lun *); -extern int scsilun_to_int(struct scsi_lun *); +extern void int_to_scsilun(u64, struct scsi_lun *); +extern u64 scsilun_to_int(struct scsi_lun *); extern const char *scsi_device_state_name(enum scsi_device_state); extern int scsi_is_sdev_device(const struct device *); extern int scsi_is_target_device(const struct device *); diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h index 447d2d7..183eaab 100644 --- a/include/scsi/scsi_devinfo.h +++ b/include/scsi/scsi_devinfo.h @@ -32,4 +32,9 @@ #define BLIST_ATTACH_PQ3 0x1000000 /* Scan: Attach to PQ3 devices */ #define BLIST_NO_DIF 0x2000000 /* Disable T10 PI (DIF) */ #define BLIST_SKIP_VPD_PAGES 0x4000000 /* Ignore SBC-3 VPD pages */ +#define BLIST_SCSI3LUN 0x8000000 /* Scan more than 256 LUNs + for sequential scan */ +#define BLIST_TRY_VPD_PAGES 0x10000000 /* Attempt to read VPD pages */ +#define BLIST_NO_RSOC 0x20000000 /* don't try to issue RSOC */ + #endif diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h index 36c4114..c2b7598 100644 --- a/include/scsi/scsi_driver.h +++ b/include/scsi/scsi_driver.h @@ -29,7 +29,4 @@ extern int scsi_register_interface(struct class_interface *); #define scsi_unregister_interface(intf) \ class_interface_unregister(intf) -int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req); -int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req); - #endif /* _SCSI_SCSI_DRIVER_H */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 94844fc..ba20347 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -7,6 +7,7 @@ #include <linux/workqueue.h> #include <linux/mutex.h> #include <linux/seq_file.h> +#include <linux/blk-mq.h> #include <scsi/scsi.h> struct request_queue; @@ -132,27 +133,6 @@ struct scsi_host_template { int (* queuecommand)(struct Scsi_Host *, struct scsi_cmnd *); /* - * The transfer functions are used to queue a scsi command to - * the LLD. When the driver is finished processing the command - * the done callback is invoked. - * - * This is called to inform the LLD to transfer - * scsi_bufflen(cmd) bytes. scsi_sg_count(cmd) speciefies the - * number of scatterlist entried in the command and - * scsi_sglist(cmd) returns the scatterlist. - * - * return values: see queuecommand - * - * If the LLD accepts the cmd, it should set the result to an - * appropriate value when completed before calling the done function. - * - * STATUS: REQUIRED FOR TARGET DRIVERS - */ - /* TODO: rename */ - int (* transfer_response)(struct scsi_cmnd *, - void (*done)(struct scsi_cmnd *)); - - /* * This is an error handling strategy routine. You don't need to * define one of these if you don't want to - there is a default * routine that is present that should work in most cases. For those @@ -408,7 +388,7 @@ struct scsi_host_template { /* * Set this if the host adapter has limitations beside segment count. */ - unsigned short max_sectors; + unsigned int max_sectors; /* * DMA scatter gather segment boundary limit. A segment crossing this @@ -531,6 +511,9 @@ struct scsi_host_template { */ unsigned int cmd_size; struct scsi_host_cmd_pool *cmd_pool; + + /* temporary flag to disable blk-mq I/O path */ + bool disable_blk_mq; }; /* @@ -601,15 +584,16 @@ struct Scsi_Host { * Area to keep a shared tag map (if needed, will be * NULL if not). */ - struct blk_queue_tag *bqt; + union { + struct blk_queue_tag *bqt; + struct blk_mq_tag_set tag_set; + }; - /* - * The following two fields are protected with host_lock; - * however, eh routines can safely access during eh processing - * without acquiring the lock. - */ - unsigned int host_busy; /* commands actually active on low-level */ - unsigned int host_failed; /* commands that failed. */ + atomic_t host_busy; /* commands actually active on low-level */ + atomic_t host_blocked; + + unsigned int host_failed; /* commands that failed. + protected by host_lock */ unsigned int host_eh_scheduled; /* EH scheduled without command */ unsigned int host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ @@ -623,11 +607,11 @@ struct Scsi_Host { * These three parameters can be used to allow for wide scsi, * and for host adapters that support multiple busses * The first two should be set to 1 more than the actual max id - * or lun (i.e. 8 for normal systems). + * or lun (e.g. 8 for SCSI parallel systems). */ - unsigned int max_id; - unsigned int max_lun; unsigned int max_channel; + unsigned int max_id; + u64 max_lun; /* * This is a unique identifier that must be assigned so that we @@ -652,7 +636,7 @@ struct Scsi_Host { short cmd_per_lun; short unsigned int sg_tablesize; short unsigned int sg_prot_tablesize; - short unsigned int max_sectors; + unsigned int max_sectors; unsigned long dma_boundary; /* * Used to assign serial numbers to the cmds. @@ -695,6 +679,8 @@ struct Scsi_Host { /* The controller does not support WRITE SAME */ unsigned no_write_same:1; + unsigned use_blk_mq:1; + /* * Optional work queue to be utilized by the transport */ @@ -707,11 +693,6 @@ struct Scsi_Host { struct workqueue_struct *tmf_work_q; /* - * Host has rejected a command because it was busy. - */ - unsigned int host_blocked; - - /* * Value host_blocked counts down from */ unsigned int max_host_blocked; @@ -800,6 +781,13 @@ static inline int scsi_host_in_recovery(struct Scsi_Host *shost) shost->tmf_in_progress; } +extern bool scsi_use_blk_mq; + +static inline bool shost_use_blk_mq(struct Scsi_Host *shost) +{ + return shost->use_blk_mq; +} + extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *); extern void scsi_flush_work(struct Scsi_Host *); @@ -816,8 +804,6 @@ extern struct Scsi_Host *scsi_host_lookup(unsigned short); extern const char *scsi_host_state_name(enum scsi_host_state); extern void scsi_cmd_get_serial(struct Scsi_Host *, struct scsi_cmnd *); -extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *); - static inline int __must_check scsi_add_host(struct Scsi_Host *host, struct device *dev) { diff --git a/include/scsi/scsi_tcq.h b/include/scsi/scsi_tcq.h index 81dd12e..cdcc90b 100644 --- a/include/scsi/scsi_tcq.h +++ b/include/scsi/scsi_tcq.h @@ -67,7 +67,8 @@ static inline void scsi_activate_tcq(struct scsi_device *sdev, int depth) if (!sdev->tagged_supported) return; - if (!blk_queue_tagged(sdev->request_queue)) + if (!shost_use_blk_mq(sdev->host) && + blk_queue_tagged(sdev->request_queue)) blk_queue_init_tags(sdev->request_queue, depth, sdev->host->bqt); @@ -80,7 +81,8 @@ static inline void scsi_activate_tcq(struct scsi_device *sdev, int depth) **/ static inline void scsi_deactivate_tcq(struct scsi_device *sdev, int depth) { - if (blk_queue_tagged(sdev->request_queue)) + if (!shost_use_blk_mq(sdev->host) && + blk_queue_tagged(sdev->request_queue)) blk_queue_free_tags(sdev->request_queue); scsi_adjust_queue_depth(sdev, 0, depth); } @@ -108,6 +110,15 @@ static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg) return 0; } +static inline struct scsi_cmnd *scsi_mq_find_tag(struct Scsi_Host *shost, + unsigned int hw_ctx, int tag) +{ + struct request *req; + + req = blk_mq_tag_to_rq(shost->tag_set.tags[hw_ctx], tag); + return req ? (struct scsi_cmnd *)req->special : NULL; +} + /** * scsi_find_tag - find a tagged command by device * @SDpnt: pointer to the ScSI device @@ -118,10 +129,12 @@ static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg) **/ static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag) { - struct request *req; if (tag != SCSI_NO_TAG) { + if (shost_use_blk_mq(sdev->host)) + return scsi_mq_find_tag(sdev->host, 0, tag); + req = blk_queue_find_tag(sdev->request_queue, tag); return req ? (struct scsi_cmnd *)req->special : NULL; } @@ -130,6 +143,7 @@ static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag) return sdev->current_cmnd; } + /** * scsi_init_shared_tag_map - create a shared tag map * @shost: the host to share the tag map among all devices @@ -138,6 +152,12 @@ static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag) static inline int scsi_init_shared_tag_map(struct Scsi_Host *shost, int depth) { /* + * We always have a shared tag map around when using blk-mq. + */ + if (shost_use_blk_mq(shost)) + return 0; + + /* * If the shared tag map isn't already initialized, do it now. * This saves callers from having to check ->bqt when setting up * devices on the shared host (for libata) @@ -165,6 +185,8 @@ static inline struct scsi_cmnd *scsi_host_find_tag(struct Scsi_Host *shost, struct request *req; if (tag != SCSI_NO_TAG) { + if (shost_use_blk_mq(shost)) + return scsi_mq_find_tag(shost, 0, tag); req = blk_map_queue_find_tag(shost->bqt, tag); return req ? (struct scsi_cmnd *)req->special : NULL; } diff --git a/include/scsi/scsi_tgt.h b/include/scsi/scsi_tgt.h deleted file mode 100644 index d0fefb9..0000000 --- a/include/scsi/scsi_tgt.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SCSI target definitions - */ - -#include <linux/dma-mapping.h> - -struct Scsi_Host; -struct scsi_cmnd; -struct scsi_lun; - -extern struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *); -extern int scsi_tgt_alloc_queue(struct Scsi_Host *); -extern void scsi_tgt_free_queue(struct Scsi_Host *); -extern int scsi_tgt_queue_command(struct scsi_cmnd *, u64, struct scsi_lun *, u64); -extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, u64, int, u64, - struct scsi_lun *, void *); -extern struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *, - enum dma_data_direction, gfp_t); -extern void scsi_host_put_command(struct Scsi_Host *, struct scsi_cmnd *); -extern int scsi_tgt_it_nexus_create(struct Scsi_Host *, u64, char *); -extern int scsi_tgt_it_nexus_destroy(struct Scsi_Host *, u64); diff --git a/include/scsi/scsi_tgt_if.h b/include/scsi/scsi_tgt_if.h deleted file mode 100644 index f2ee7c2..0000000 --- a/include/scsi/scsi_tgt_if.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * SCSI target kernel/user interface - * - * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org> - * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ -#ifndef __SCSI_TARGET_IF_H -#define __SCSI_TARGET_IF_H - -/* user -> kernel */ -#define TGT_UEVENT_CMD_RSP 0x0001 -#define TGT_UEVENT_IT_NEXUS_RSP 0x0002 -#define TGT_UEVENT_TSK_MGMT_RSP 0x0003 - -/* kernel -> user */ -#define TGT_KEVENT_CMD_REQ 0x1001 -#define TGT_KEVENT_CMD_DONE 0x1002 -#define TGT_KEVENT_IT_NEXUS_REQ 0x1003 -#define TGT_KEVENT_TSK_MGMT_REQ 0x1004 - -struct tgt_event_hdr { - uint16_t version; - uint16_t status; - uint16_t type; - uint16_t len; -} __attribute__ ((aligned (sizeof(uint64_t)))); - -struct tgt_event { - struct tgt_event_hdr hdr; - - union { - /* user-> kernel */ - struct { - int host_no; - int result; - aligned_u64 itn_id; - aligned_u64 tag; - aligned_u64 uaddr; - aligned_u64 sense_uaddr; - uint32_t len; - uint32_t sense_len; - uint8_t rw; - } cmd_rsp; - struct { - int host_no; - int result; - aligned_u64 itn_id; - aligned_u64 mid; - } tsk_mgmt_rsp; - struct { - __s32 host_no; - __s32 result; - aligned_u64 itn_id; - __u32 function; - } it_nexus_rsp; - - /* kernel -> user */ - struct { - int host_no; - uint32_t data_len; - aligned_u64 itn_id; - uint8_t scb[16]; - uint8_t lun[8]; - int attribute; - aligned_u64 tag; - } cmd_req; - struct { - int host_no; - int result; - aligned_u64 itn_id; - aligned_u64 tag; - } cmd_done; - struct { - int host_no; - int function; - aligned_u64 itn_id; - aligned_u64 tag; - uint8_t lun[8]; - aligned_u64 mid; - } tsk_mgmt_req; - struct { - __s32 host_no; - __u32 function; - aligned_u64 itn_id; - __u32 max_cmds; - __u8 initiator_id[16]; - } it_nexus_req; - } p; -} __attribute__ ((aligned (sizeof(uint64_t)))); - -#define TGT_RING_SIZE (1UL << 16) - -#endif diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index af244f4..8129239 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -35,7 +35,7 @@ struct scsi_transport_template { /* * If set, called from sysfs and legacy procfs rescanning code. */ - int (*user_scan)(struct Scsi_Host *, uint, uint, uint); + int (*user_scan)(struct Scsi_Host *, uint, uint, u64); /* The size of the specific transport attribute structure (a * space of this size will be left at the end of the diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 8c79980..007a0bc 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -131,6 +131,10 @@ enum fc_vport_state { #define FC_PORTSPEED_8GBIT 0x10 #define FC_PORTSPEED_16GBIT 0x20 #define FC_PORTSPEED_32GBIT 0x40 +#define FC_PORTSPEED_20GBIT 0x80 +#define FC_PORTSPEED_40GBIT 0x100 +#define FC_PORTSPEED_50GBIT 0x200 +#define FC_PORTSPEED_100GBIT 0x400 #define FC_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */ /* diff --git a/include/scsi/sg.h b/include/scsi/sg.h index a9f3c6f..9859355 100644 --- a/include/scsi/sg.h +++ b/include/scsi/sg.h @@ -4,77 +4,34 @@ #include <linux/compiler.h> /* - History: - Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user - process control of SCSI devices. - Development Sponsored by Killy Corp. NY NY -Original driver (sg.h): -* Copyright (C) 1992 Lawrence Foard -Version 2 and 3 extensions to driver: -* Copyright (C) 1998 - 2006 Douglas Gilbert - - Version: 3.5.34 (20060920) - This version is for 2.6 series kernels. - - For a full changelog see http://www.torque.net/sg - -Map of SG verions to the Linux kernels in which they appear: - ---------- ---------------------------------- - original all kernels < 2.2.6 - 2.1.40 2.2.20 - 3.0.x optional version 3 sg driver for 2.2 series - 3.1.17++ 2.4.0++ - 3.5.30++ 2.6.0++ - -Major new features in SG 3.x driver (cf SG 2.x drivers) - - SG_IO ioctl() combines function if write() and read() - - new interface (sg_io_hdr_t) but still supports old interface - - scatter/gather in user space, direct IO, and mmap supported - - The normal action of this driver is to use the adapter (HBA) driver to DMA - data into kernel buffers and then use the CPU to copy the data into the - user space (vice versa for writes). That is called "indirect" IO due to - the double handling of data. There are two methods offered to remove the - redundant copy: 1) direct IO and 2) using the mmap() system call to map - the reserve buffer (this driver has one reserve buffer per fd) into the - user space. Both have their advantages. - In terms of absolute speed mmap() is faster. If speed is not a concern, - indirect IO should be fine. Read the documentation for more information. - - ** N.B. To use direct IO 'echo 1 > /proc/scsi/sg/allow_dio' or - 'echo 1 > /sys/module/sg/parameters/allow_dio' is needed. - That attribute is 0 by default. ** - - Historical note: this SCSI pass-through driver has been known as "sg" for - a decade. In broader kernel discussions "sg" is used to refer to scatter - gather techniques. The context should clarify which "sg" is referred to. - - Documentation - ============= - A web site for the SG device driver can be found at: - http://www.torque.net/sg [alternatively check the MAINTAINERS file] - The documentation for the sg version 3 driver can be found at: - http://www.torque.net/sg/p/sg_v3_ho.html - This is a rendering from DocBook source [change the extension to "sgml" - or "xml"]. There are renderings in "ps", "pdf", "rtf" and "txt" (soon). - The SG_IO ioctl is now found in other parts kernel (e.g. the block layer). - For more information see http://www.torque.net/sg/sg_io.html - - The older, version 2 documents discuss the original sg interface in detail: - http://www.torque.net/sg/p/scsi-generic.txt - http://www.torque.net/sg/p/scsi-generic_long.txt - Also available: <kernel_source>/Documentation/scsi/scsi-generic.txt - - Utility and test programs are available at the sg web site. They are - packaged as sg3_utils (for the lk 2.4 and 2.6 series) and sg_utils - (for the lk 2.2 series). -*/ + * History: + * Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user + * process control of SCSI devices. + * Development Sponsored by Killy Corp. NY NY + * + * Original driver (sg.h): + * Copyright (C) 1992 Lawrence Foard + * Version 2 and 3 extensions to driver: + * Copyright (C) 1998 - 2014 Douglas Gilbert + * + * Version: 3.5.36 (20140603) + * This version is for 2.6 and 3 series kernels. + * + * Documentation + * ============= + * A web site for the SG device driver can be found at: + * 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 + * + * For utility and test programs see: http://sg.danny.cz/sg/sg3_utils.html + */ #ifdef __KERNEL__ extern int sg_big_buff; /* for sysctl */ #endif -/* New interface introduced in the 3.x SG drivers follows */ typedef struct sg_iovec /* same structure as used by readv() Linux system */ { /* call. It defines one scatter-gather element. */ @@ -87,7 +44,7 @@ typedef struct sg_io_hdr { int interface_id; /* [i] 'S' for SCSI generic (required) */ int dxfer_direction; /* [i] data transfer direction */ - unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + unsigned char cmd_len; /* [i] SCSI command length */ unsigned char mx_sb_len; /* [i] max length to write to sbp */ unsigned short iovec_count; /* [i] 0 implies no scatter gather */ unsigned int dxfer_len; /* [i] byte count of data transfer */ @@ -129,6 +86,7 @@ typedef struct sg_io_hdr #define SG_FLAG_MMAP_IO 4 /* request memory mapped IO */ #define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */ /* user space (debug indirect IO) */ +#define SG_FLAG_Q_AT_TAIL 0x10 /* default is Q_AT_HEAD */ /* following 'info' values are "or"-ed together */ #define SG_INFO_OK_MASK 0x1 diff --git a/kernel/params.c b/kernel/params.c index 1e52ca2..34f5270 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -256,6 +256,7 @@ STANDARD_PARAM_DEF(int, int, "%i", kstrtoint); STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint); STANDARD_PARAM_DEF(long, long, "%li", kstrtol); STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul); +STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull); int param_set_charp(const char *val, const struct kernel_param *kp) { diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 3a8e8e8..b4415fc 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -165,6 +165,7 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents) * __sg_free_table - Free a previously mapped sg table * @table: The sg table header to use * @max_ents: The maximum number of entries per single scatterlist + * @skip_first_chunk: don't free the (preallocated) first scatterlist chunk * @free_fn: Free function * * Description: @@ -174,7 +175,7 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents) * **/ void __sg_free_table(struct sg_table *table, unsigned int max_ents, - sg_free_fn *free_fn) + bool skip_first_chunk, sg_free_fn *free_fn) { struct scatterlist *sgl, *next; @@ -202,7 +203,10 @@ void __sg_free_table(struct sg_table *table, unsigned int max_ents, } table->orig_nents -= sg_size; - free_fn(sgl, alloc_size); + if (!skip_first_chunk) { + free_fn(sgl, alloc_size); + skip_first_chunk = false; + } sgl = next; } @@ -217,7 +221,7 @@ EXPORT_SYMBOL(__sg_free_table); **/ void sg_free_table(struct sg_table *table) { - __sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree); + __sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree); } EXPORT_SYMBOL(sg_free_table); @@ -241,8 +245,8 @@ EXPORT_SYMBOL(sg_free_table); * **/ int __sg_alloc_table(struct sg_table *table, unsigned int nents, - unsigned int max_ents, gfp_t gfp_mask, - sg_alloc_fn *alloc_fn) + unsigned int max_ents, struct scatterlist *first_chunk, + gfp_t gfp_mask, sg_alloc_fn *alloc_fn) { struct scatterlist *sg, *prv; unsigned int left; @@ -269,7 +273,12 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents, left -= sg_size; - sg = alloc_fn(alloc_size, gfp_mask); + if (first_chunk) { + sg = first_chunk; + first_chunk = NULL; + } else { + sg = alloc_fn(alloc_size, gfp_mask); + } if (unlikely(!sg)) { /* * Adjust entry count to reflect that the last @@ -324,9 +333,9 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask) int ret; ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC, - gfp_mask, sg_kmalloc); + NULL, gfp_mask, sg_kmalloc); if (unlikely(ret)) - __sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree); + __sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree); return ret; } |