GIT b42abb39ca8a5414f039839866f0357725a53618 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git commit b42abb39ca8a5414f039839866f0357725a53618 Author: James Bottomley Date: Sat Feb 2 16:06:23 2008 -0600 [SCSI] sd: handle bad lba in sense information Some devices report medium error locations incorrectly. Add guards to make sure the reported bad lba is actually in the request that caused it. Additionally remove the large case statment for sector sizes and replace it with the proper u64 divisions. Tested-by: Mike Snitzer Cc: Stable Tree Cc: Tony Battersby Signed-off-by: James Bottomley commit 82fa47b17b1b6e7384d2b1a73aa6868d232fd823 Author: Andrew Vasquez Date: Thu Jan 31 12:33:54 2008 -0800 [SCSI] qla2xxx: Update version number to 8.02.00-k8. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit dbfb3e006233d30b5ac6fe40691702326c367981 Author: Andrew Vasquez Date: Thu Jan 31 12:33:53 2008 -0800 [SCSI] qla2xxx: Correct issue where incorrect init-fw mailbox command was used on non-NPIV capable ISPs. BIT_2 of the firmware attributes is only valid on FW-interface-2 type HBAs. Code in commit c48339decceec8e011498b0fc4c7c7d8b2ea06c1 would cause the incorrect initialize-firmware mailbox command to be issued for non-NPIV capable ISPs. Correct this by reverting to previously used (and correct) pre-condition 'if' check. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit b835c75118e35094399a2d3104fe34bbded15729 Author: Seokmann Ju Date: Thu Jan 31 12:33:52 2008 -0800 [SCSI] qla2xxx: Access the proper 'physical' port in FC-transport callbacks. For following fc_host specific attributes, vports rely on the pport. So, this patch changed way to access the data for those attributes so that they can access pport's. - get_host_speed (speed) - get_host_port_state (port_state) - get_host_port_type (port_type) - get_fc_host_stats Also, added PORT_SPEED_8GB case in the speed attribute for 8Gb HBAs. Signed-Off-by: Seokmann Ju Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit f9c15a9d505e96d982549cbbbd9a4f7fcc764404 Author: Seokmann Ju Date: Thu Jan 31 12:33:51 2008 -0800 [SCSI] qla2xxx: Correct issue where vport-state was not updated during an ISP_ABORT_NEEDED requst. While running IO simultaneously through physical port and virtual port, if user changes Data Rate (from scli utility), IO through virtual port fails. It failed because the vport had not received the ISP_ABORT_NEEDED notification. Signed-Off-by: Seokmann Ju Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 828927cfe548a49c52c9d9839ad773ef49c438d8 Author: Andrew Vasquez Date: Thu Jan 31 12:33:50 2008 -0800 [SCSI] qla2xxx: Move RISC-interrupt-register modifications to qla2x00_request_irqs(). There's no functional change involved with this update, instead it simply migrates the "set cleared interrupt state" codes to a more approprate method, qla2x00_request_irqs(), and cleans-up the driver's probe() logic. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit e9949f80902b1afc34cfa625cad08117e60070ef Author: Andrew Vasquez Date: Thu Jan 31 12:33:49 2008 -0800 [SCSI] qla2xxx: Consolidate RISC-parity enablement codes. Collapse duplicate codes called during probe() and RISC-reset into qla2x00_setup_chip(). Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 0fac34ce4d202f2bc94dd5ea75726505dd6e588b Author: Andrew Vasquez Date: Thu Jan 31 12:33:48 2008 -0800 [SCSI] qla2xxx: Cleanse memory allocation logic during probe. - Drop loop-till-allocated structure of code within qla2x00_mem_alloc(). - Properly unwind deallcations of memory during failures. - Drop qla2x00_allocate_sp_pool() and qla2x00_free_sp_pool() functions as their implementations can easily be collapsed into the callers. - Defer DMA pool allocation of SFP data until requested. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 347ca8850c254bf8b8d992021f12c6082b2140ad Author: Andrew Vasquez Date: Thu Jan 31 12:33:47 2008 -0800 [SCSI] qla2xxx: Clear EFT buffer before firmware reinitialization. To insure that there is no stale data present during EFT re-registration. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 081658af61b103a1f01205e0493c8697ecb246d9 Author: Andrew Vasquez Date: Thu Jan 31 12:33:46 2008 -0800 [SCSI] qla2xxx: Cleanup any outstanding SRB resources during shutdown. Refactor SRB-failure completion codes in the process. Also, signal the DPC routine to complete sooner as backend processing at shutdown-time is superflous. [jejb: resolve conflicts with pci_enable_device_bars removal] Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 27d7b1aaf2893ef3cf23518118bf9178ed4b3350 Author: Andrew Vasquez Date: Thu Jan 31 12:33:45 2008 -0800 [SCSI] qla2xxx: Add MODULE_FIRMWARE hint for ISP25XX firmware. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit d688d902fd7d162a5bbffda542bdd75f04d752dc Author: Andrew Vasquez Date: Thu Jan 31 12:33:44 2008 -0800 [SCSI] qla2xxx: Correct resource_size_t usages. Hmm, it looks like the conversion to resource_size_t usage (3776541d8a46347a4924353a192c6ce4a3d04e2e) requires some additional fixups to cleanup the structure-pointer castings used during IO mapped accesses to the chip. There's only a small number of locations, where the driver uses IO mapped accesses to the hardware, the patch below should take care of it without introducing to many structural changes to code flow. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit d7ab64d82a851f5d16ec2e66f4b7032821618892 Author: Mike Christie Date: Thu Jan 31 13:36:54 2008 -0600 [SCSI] iscsi: bump version to 2.0-868 Set iscsi version to 2.0-868 Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit eff2ef2a078c3ca8f97915b92d43e24e815e6b72 Author: Mike Christie Date: Thu Jan 31 13:36:53 2008 -0600 [SCSI] libiscsi: fix session age rollover and remove cid encoding The session age mask is only 4 bits, but session->age is 32. When it gets larger then 15 and we try to or the bits some bits get dropped and the check for session age in iscsi_verify_itt is useless. The ISCSI_CID_MASK related bits are also useless since cid is always one. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 0a49a7b0d300ce73a68f094a5416596102453c86 Author: Mike Christie Date: Thu Jan 31 13:36:52 2008 -0600 [SCSI] iscsi: fix up iscsi printk prefix Some iscsi class messages have the dev_printk prefix and some libiscsi and iscsi_tcp messages have "iscsi" or the module name as a prefix which is normally pretty useless when trying to figure out which session or connection the message is attached to. This patch adds iscsi lib and class dev_printks so all messages have a common prefix that can be used to figure out which object printed it. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit c003045e36c63e28a5d3e9dbdf593dfe17d20923 Author: Mike Christie Date: Thu Jan 31 13:36:51 2008 -0600 [SCSI] iscsi class: fix iscsi conn attr counter There are 13 iscsi conn attrs, but since the IF/OF markers were not being used we did not notice that we forgot to increment the ISCSI_CONN_ATTRS counter. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 5e1d2b2d41f5957fd633c3ae3ab875635c1735cc Author: Mike Christie Date: Thu Jan 31 13:36:50 2008 -0600 [SCSI] libiscsi: fix setting of nop timer If we rollover then we could get a next_timeout of zero, so we need to set the new timer to that value. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 010480d716c0978a39729e0dbc42d59b418c10b0 Author: Mike Christie Date: Thu Jan 31 13:36:49 2008 -0600 [SCSI] qla4xxx: add async scan support qla4xxx has the old school startup/probe where it finds presetup sessions in its flash and then attempts to log into them before returning from the probe. This however, makes it very simple to add a iscsi class scan finished helper which the driver can use. In future patches Dave or I will rip apart the driver to make it more like qla2xxx, but for now this is a very simple two line patch which fixes the problem of trying to figure out when the initial sessions are done being scanned. Signed-off-by: Mike Christie Cc: David Somayajulu Signed-off-by: James Bottomley commit 4d93c49f22f4bda76b84fd2801a14b9de015215f Author: Mike Christie Date: Thu Jan 31 13:36:48 2008 -0600 [SCSI] iscsi class: add async scan helper In qla4xxx's probe it will call the iscsi session setup functions for session that got setup on the initial start. This then makes it easy for the iscsi class to export a helper which indicates when those scans are done. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit a023a6a698bd5a79047d8071001f62de95b80544 Author: Mike Christie Date: Thu Jan 31 13:36:47 2008 -0600 [SCSI] qla4xxx: fix recovery timer and session unblock race If qla4xxx is resetting up a session and the recovery timer fires we do not want to just set it to dead, because the dpc thread could have just set it to online and is in the middle of resetting it up. Signed-off-by: Mike Christie Cc: David Somayajulu Signed-off-by: James Bottomley commit 637b05c316b71017586bf78273ae766f4c3a830c Author: Mike Christie Date: Thu Jan 31 13:36:46 2008 -0600 [SCSI] iscsi class: add session scanning This just adds iscsi session scanning which works like fc rport scanning. The future patches will hook the drivers into Mathew Wilcox's async scanning infrastructure, so userspace does not have to special case iscsi and so userspace does not have to make a extra special case for hardware iscsi root scanning. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 276e911ce5cbba5eff970206286e3c27032f70c1 Author: Mike Christie Date: Thu Jan 31 13:36:45 2008 -0600 [SCSI] qla4xxx: use iscsi class session state check ready This has qla4xxx use the iscsi class's check ready function in the queue command function, so all iscsi drivers return the same error value for common problems. Signed-off-by: Mike Christie Cc: David Somayajulu Signed-off-by: James Bottomley commit ee8cf52943ab000c930732f38eda373a19320ef0 Author: Mike Christie Date: Thu Jan 31 13:36:44 2008 -0600 [SCSI] qla4xxx: directly call iscsi recovery functions Qla4xxx can just call the iscsi recovery functions directly. There is no need for userspace to do this for qla4xxx, because we do not use the mutex to iterate over devices anymore and iscsi_block /unblock_session can be called from interrupt context or the dpc thread. And having userspace do this just creates uneeded headaches for qla4xxx root situations where the session may experience problems. For example during the kernel shutdown the scsi layer wants to send sync caches, but at this time userspace is not up (iscsid is not running), so we cannot recover from the problem. Signed-off-by: Mike Christie Cc: David Somayajulu Signed-off-by: James Bottomley commit 6b382092a7f16f7adb93312bc0ccc835454d61eb Author: Mike Christie Date: Thu Jan 31 13:36:43 2008 -0600 [SCSI] iscsi class, libiscsi: add iscsi sysfs session state file This adds a iscsi session state file which exports the session state for both software and hardware iscsi. It also hooks libiscsi in. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 4e6a046ed27858bf4fef1c836a66cc9489aa2a49 Author: akpm@linux-foundation.org Date: Wed Jan 16 01:31:41 2008 -0800 [SCSI] lpfc: convert pci_enable_device_bars -> pci_enable_device_mem This conversion was missed when the removal of pci_enable_device_bars went in making the driver unbuildable. Signed-off-by: Andrew Morton Cc: James Smart Signed-off-by: James Bottomley commit b68ed815950375a6ca4d897087086dea8e9c9470 Author: Boaz Harrosh Date: Sun Sep 9 21:31:21 2007 +0300 [SCSI] arm: convert to accessors and !use_sg cleanup - convert to accessors and !use_sg cleanup Signed-off-by: Boaz Harrosh Tested-by: Russell King Signed-off-by: James Bottomley commit 7b00a6884ba9d2ac7c6ca1cc1f3770d2e2231c5c Author: James Bottomley Date: Thu Jan 3 12:17:50 2008 -0600 [SCSI] mca_53c9x: remove driver This driver depends on the deprecated NCR53C9X core and needs to be converted to the esp_scsi core. Acked-by: Boaz Harrosh Signed-off-by: James Bottomley commit 5f2046f15981fa415384527d8a290114a8305739 Author: Tony Battersby Date: Tue Nov 6 16:07:04 2007 -0500 [SCSI] sym53c8xx: fix resid calculation This patch fixes the calculation of the data transfer residual for the case of a command that is supposed to transfer an odd number of bytes on a wide bus but transfers nothing instead. Signed-off-by: Tony Battersby Cc: Matthew Wilcox Signed-off-by: James Bottomley commit abf923e7d0c3007adf4fc212ecfb814dbe0a13c6 Author: Aegis Lin Date: Fri Feb 1 17:35:13 2008 +0100 [SCSI] ps3rom: sector size should be 512 bytes It should be desired that 64 KiB is available for ATAPI transferrring. (Historically) in SCSI/block layer sector size is defined as 512 during sector-byte calculation. Originally in ps3rom.c CD_FRAMESIZE (2048) was used, which limited /sys/block/sr0/queue/max_sectors_kb to 16 KiB (32 sectors). Signed-off-by: Aegis Lin Signed-off-by: Geert Uytterhoeven Signed-off-by: James Bottomley commit de40813f156b58d62896679cbc29875f925281f7 Author: Thomas Bogendoerfer Date: Fri Feb 1 00:13:34 2008 +0100 [SCSI] sun3x_esp: convert to esp_scsi Converted sun3x_esp driver to use esp_scsi.c Signed-off-by: Thomas Bogendoerfer Signed-off-by: James Bottomley commit e3e707c0e3850cb42ff2383985b3666f5ac87d05 Author: Adrian Bunk Date: Tue Jan 29 00:11:27 2008 +0200 [SCSI] libiscsi: make __iscsi_complete_pdu() static __iscsi_complete_pdu() can now become static. Signed-off-by: Adrian Bunk Acked-by: Mike Christie Signed-off-by: James Bottomley commit 5d2a24a6406c5fa66e1ce64d0c4d05a0c2ce5841 Author: Salyzyn, Mark Date: Mon Jan 28 12:16:52 2008 -0800 [SCSI] aacraid: fib context lock for management ioctls (take 2) The first patch (a119ee8ee3045bf559d4cf02d72b112f3de2a15b) was a bit too aggressive and nested the locks (!) unit testing was in error. This patch was reverted by 203a512f0976e8ba85df36d76b40af6c80239121. This new patch should fix the locks correctly. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley Signed-off-by: Andrew Morton --- drivers/scsi/Kconfig | 12 drivers/scsi/Makefile | 3 drivers/scsi/aacraid/commctrl.c | 26 - drivers/scsi/arm/acornscsi.c | 14 drivers/scsi/arm/scsi.h | 87 ++-- drivers/scsi/iscsi_tcp.c | 57 +- drivers/scsi/libiscsi.c | 137 +++--- drivers/scsi/mca_53c9x.c | 520 ------------------------ drivers/scsi/ps3rom.c | 2 drivers/scsi/qla2xxx/qla_attr.c | 24 - drivers/scsi/qla2xxx/qla_def.h | 2 drivers/scsi/qla2xxx/qla_gbl.h | 1 drivers/scsi/qla2xxx/qla_init.c | 87 +--- drivers/scsi/qla2xxx/qla_inline.h | 7 drivers/scsi/qla2xxx/qla_isr.c | 27 + drivers/scsi/qla2xxx/qla_mbx.c | 2 drivers/scsi/qla2xxx/qla_os.c | 404 ++++++------------ drivers/scsi/qla2xxx/qla_sup.c | 36 - drivers/scsi/qla2xxx/qla_version.h | 2 drivers/scsi/qla4xxx/ql4_init.c | 1 drivers/scsi/qla4xxx/ql4_os.c | 75 +-- drivers/scsi/scsi_transport_iscsi.c | 238 +++++++++-- drivers/scsi/sd.c | 34 - drivers/scsi/sun3x_esp.c | 560 +++++++++++--------------- drivers/scsi/sym53c8xx_2/sym_hipd.c | 2 include/scsi/iscsi_proto.h | 4 include/scsi/libiscsi.h | 30 + include/scsi/scsi_transport_iscsi.h | 43 + 28 files changed, 953 insertions(+), 1484 deletions(-) diff -puN drivers/scsi/Kconfig~git-scsi-misc drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig~git-scsi-misc +++ a/drivers/scsi/Kconfig @@ -1263,17 +1263,6 @@ config SCSI_NCR53C8XX_NO_DISCONNECT not allow targets to disconnect is not reasonable if there is more than 1 device on a SCSI bus. The normal answer therefore is N. -config SCSI_MCA_53C9X - tristate "NCR MCA 53C9x SCSI support" - depends on MCA_LEGACY && SCSI && BROKEN_ON_SMP - help - Some MicroChannel machines, notably the NCR 35xx line, use a SCSI - controller based on the NCR 53C94. This driver will allow use of - the controller on the 3550, and very possibly others. - - To compile this driver as a module, choose M here: the - module will be called mca_53c9x. - config SCSI_PAS16 tristate "PAS16 SCSI support" depends on ISA && SCSI @@ -1779,6 +1768,7 @@ config SUN3_SCSI config SUN3X_ESP bool "Sun3x ESP SCSI" depends on SUN3X && SCSI=y + select SCSI_SPI_ATTRS help The ESP was an on-board SCSI controller used on Sun 3/80 machines. Say Y here to compile in support for it. diff -puN drivers/scsi/Makefile~git-scsi-misc drivers/scsi/Makefile --- a/drivers/scsi/Makefile~git-scsi-misc +++ a/drivers/scsi/Makefile @@ -95,7 +95,6 @@ obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o obj-$(CONFIG_SCSI_7000FASST) += wd7000.o -obj-$(CONFIG_SCSI_MCA_53C9X) += NCR53C9x.o mca_53c9x.o obj-$(CONFIG_SCSI_IBMMCA) += ibmmca.o obj-$(CONFIG_SCSI_EATA) += eata.o obj-$(CONFIG_SCSI_DC395x) += dc395x.o @@ -118,7 +117,7 @@ obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o obj-$(CONFIG_SCSI_PPA) += ppa.o obj-$(CONFIG_SCSI_IMM) += imm.o obj-$(CONFIG_JAZZ_ESP) += esp_scsi.o jazz_esp.o -obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o +obj-$(CONFIG_SUN3X_ESP) += esp_scsi.o sun3x_esp.o obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o diff -puN drivers/scsi/aacraid/commctrl.c~git-scsi-misc drivers/scsi/aacraid/commctrl.c --- a/drivers/scsi/aacraid/commctrl.c~git-scsi-misc +++ a/drivers/scsi/aacraid/commctrl.c @@ -243,6 +243,7 @@ static int next_getadapter_fib(struct aa * Search the list of AdapterFibContext addresses on the adapter * to be sure this is a valid address */ + spin_lock_irqsave(&dev->fib_lock, flags); entry = dev->fib_list.next; fibctx = NULL; @@ -251,24 +252,25 @@ static int next_getadapter_fib(struct aa /* * Extract the AdapterFibContext from the Input parameters. */ - if (fibctx->unique == f.fibctx) { /* We found a winner */ + if (fibctx->unique == f.fibctx) { /* We found a winner */ break; } entry = entry->next; fibctx = NULL; } if (!fibctx) { + spin_unlock_irqrestore(&dev->fib_lock, flags); dprintk ((KERN_INFO "Fib Context not found\n")); return -EINVAL; } if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) || (fibctx->size != sizeof(struct aac_fib_context))) { + spin_unlock_irqrestore(&dev->fib_lock, flags); dprintk ((KERN_INFO "Fib Context corrupt?\n")); return -EINVAL; } status = 0; - spin_lock_irqsave(&dev->fib_lock, flags); /* * If there are no fibs to send back, then either wait or return * -EAGAIN @@ -414,8 +416,8 @@ static int close_getadapter_fib(struct a * @arg: ioctl arguments * * This routine returns the driver version. - * Under Linux, there have been no version incompatibilities, so this is - * simple! + * Under Linux, there have been no version incompatibilities, so this is + * simple! */ static int check_revision(struct aac_dev *dev, void __user *arg) @@ -463,7 +465,7 @@ static int aac_send_raw_srb(struct aac_d u32 data_dir; void __user *sg_user[32]; void *sg_list[32]; - u32 sg_indx = 0; + u32 sg_indx = 0; u32 byte_count = 0; u32 actual_fibsize64, actual_fibsize = 0; int i; @@ -517,11 +519,11 @@ static int aac_send_raw_srb(struct aac_d // Fix up srb for endian and force some values srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this - srbcmd->channel = cpu_to_le32(user_srbcmd->channel); + srbcmd->channel = cpu_to_le32(user_srbcmd->channel); srbcmd->id = cpu_to_le32(user_srbcmd->id); - srbcmd->lun = cpu_to_le32(user_srbcmd->lun); - srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout); - srbcmd->flags = cpu_to_le32(flags); + srbcmd->lun = cpu_to_le32(user_srbcmd->lun); + srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout); + srbcmd->flags = cpu_to_le32(flags); srbcmd->retry_limit = 0; // Obsolete parameter srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size); memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb)); @@ -786,9 +788,9 @@ static int aac_get_pci_info(struct aac_d pci_info.bus = dev->pdev->bus->number; pci_info.slot = PCI_SLOT(dev->pdev->devfn); - if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) { - dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n")); - return -EFAULT; + if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) { + dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n")); + return -EFAULT; } return 0; } diff -puN drivers/scsi/arm/acornscsi.c~git-scsi-misc drivers/scsi/arm/acornscsi.c --- a/drivers/scsi/arm/acornscsi.c~git-scsi-misc +++ a/drivers/scsi/arm/acornscsi.c @@ -1790,7 +1790,7 @@ int acornscsi_starttransfer(AS_Host *hos return 0; } - residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred; + residual = scsi_bufflen(host->SCpnt) - host->scsi.SCp.scsi_xferred; sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); sbic_arm_writenext(host->scsi.io_port, residual >> 16); @@ -2270,7 +2270,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *h case 0x4b: /* -> PHASE_STATUSIN */ case 0x8b: /* -> PHASE_STATUSIN */ /* DATA IN -> STATUS */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - acornscsi_sbic_xfcount(host); acornscsi_dma_stop(host); acornscsi_readstatusbyte(host); @@ -2281,7 +2281,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *h case 0x4e: /* -> PHASE_MSGOUT */ case 0x8e: /* -> PHASE_MSGOUT */ /* DATA IN -> MESSAGE OUT */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - acornscsi_sbic_xfcount(host); acornscsi_dma_stop(host); acornscsi_sendmessage(host); @@ -2291,7 +2291,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *h case 0x4f: /* message in */ case 0x8f: /* message in */ /* DATA IN -> MESSAGE IN */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - acornscsi_sbic_xfcount(host); acornscsi_dma_stop(host); acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ @@ -2319,7 +2319,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *h case 0x4b: /* -> PHASE_STATUSIN */ case 0x8b: /* -> PHASE_STATUSIN */ /* DATA OUT -> STATUS */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - acornscsi_sbic_xfcount(host); acornscsi_dma_stop(host); acornscsi_dma_adjust(host); @@ -2331,7 +2331,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *h case 0x4e: /* -> PHASE_MSGOUT */ case 0x8e: /* -> PHASE_MSGOUT */ /* DATA OUT -> MESSAGE OUT */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - acornscsi_sbic_xfcount(host); acornscsi_dma_stop(host); acornscsi_dma_adjust(host); @@ -2342,7 +2342,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *h case 0x4f: /* message in */ case 0x8f: /* message in */ /* DATA OUT -> MESSAGE IN */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - + host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - acornscsi_sbic_xfcount(host); acornscsi_dma_stop(host); acornscsi_dma_adjust(host); diff -puN drivers/scsi/arm/scsi.h~git-scsi-misc drivers/scsi/arm/scsi.h --- a/drivers/scsi/arm/scsi.h~git-scsi-misc +++ a/drivers/scsi/arm/scsi.h @@ -18,17 +18,32 @@ * The scatter-gather list handling. This contains all * the yucky stuff that needs to be fixed properly. */ + +/* + * copy_SCp_to_sg() Assumes contiguous allocation at @sg of at-most @max + * entries of uninitialized memory. SCp is from scsi-ml and has a valid + * (possibly chained) sg-list + */ static inline int copy_SCp_to_sg(struct scatterlist *sg, struct scsi_pointer *SCp, int max) { int bufs = SCp->buffers_residual; + /* FIXME: It should be easy for drivers to loop on copy_SCp_to_sg(). + * and to remove this BUG_ON. Use min() in-its-place + */ BUG_ON(bufs + 1 > max); sg_set_buf(sg, SCp->ptr, SCp->this_residual); - if (bufs) - memcpy(sg + 1, SCp->buffer + 1, - sizeof(struct scatterlist) * bufs); + if (bufs) { + struct scatterlist *src_sg; + unsigned i; + + for_each_sg(sg_next(SCp->buffer), src_sg, bufs, i) + *(++sg) = *src_sg; + sg_mark_end(sg); + } + return bufs + 1; } @@ -36,7 +51,7 @@ static inline int next_SCp(struct scsi_p { int ret = SCp->buffers_residual; if (ret) { - SCp->buffer++; + SCp->buffer = sg_next(SCp->buffer); SCp->buffers_residual--; SCp->ptr = sg_virt(SCp->buffer); SCp->this_residual = SCp->buffer->length; @@ -68,46 +83,46 @@ static inline void init_SCp(struct scsi_ { memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer)); - if (SCpnt->use_sg) { + if (scsi_bufflen(SCpnt)) { unsigned long len = 0; - int buf; - SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; - SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; + SCpnt->SCp.buffer = scsi_sglist(SCpnt); + SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1; SCpnt->SCp.ptr = sg_virt(SCpnt->SCp.buffer); SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; - SCpnt->SCp.phase = SCpnt->request_bufflen; + SCpnt->SCp.phase = scsi_bufflen(SCpnt); #ifdef BELT_AND_BRACES - /* - * Calculate correct buffer length. Some commands - * come in with the wrong request_bufflen. - */ - for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++) - len += SCpnt->SCp.buffer[buf].length; - - if (SCpnt->request_bufflen != len) - printk(KERN_WARNING "scsi%d.%c: bad request buffer " - "length %d, should be %ld\n", SCpnt->device->host->host_no, - '0' + SCpnt->device->id, SCpnt->request_bufflen, len); - SCpnt->request_bufflen = len; + { /* + * Calculate correct buffer length. Some commands + * come in with the wrong scsi_bufflen. + */ + struct scatterlist *sg; + unsigned i, sg_count = scsi_sg_count(SCpnt); + + scsi_for_each_sg(SCpnt, sg, sg_count, i) + len += sg->length; + + if (scsi_bufflen(SCpnt) != len) { + printk(KERN_WARNING + "scsi%d.%c: bad request buffer " + "length %d, should be %ld\n", + SCpnt->device->host->host_no, + '0' + SCpnt->device->id, + scsi_bufflen(SCpnt), len); + /* + * FIXME: Totaly naive fixup. We should abort + * with error + */ + SCpnt->SCp.phase = + min_t(unsigned long, len, + scsi_bufflen(SCpnt)); + } + } #endif } else { - SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer; - SCpnt->SCp.this_residual = SCpnt->request_bufflen; - SCpnt->SCp.phase = SCpnt->request_bufflen; - } - - /* - * If the upper SCSI layers pass a buffer, but zero length, - * we aren't interested in the buffer pointer. - */ - if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) { -#if 0 //def BELT_AND_BRACES - printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for " - "command ", SCpnt->host->host_no, '0' + SCpnt->target); - __scsi_print_command(SCpnt->cmnd); -#endif SCpnt->SCp.ptr = NULL; + SCpnt->SCp.this_residual = 0; + SCpnt->SCp.phase = 0; } } diff -puN drivers/scsi/iscsi_tcp.c~git-scsi-misc drivers/scsi/iscsi_tcp.c --- a/drivers/scsi/iscsi_tcp.c~git-scsi-misc +++ a/drivers/scsi/iscsi_tcp.c @@ -629,8 +629,9 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s int rc; if (tcp_conn->in.datalen) { - printk(KERN_ERR "iscsi_tcp: invalid R2t with datalen %d\n", - tcp_conn->in.datalen); + iscsi_conn_printk(KERN_ERR, conn, + "invalid R2t with datalen %d\n", + tcp_conn->in.datalen); return ISCSI_ERR_DATALEN; } @@ -644,8 +645,9 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) { - printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in " - "recovery...\n", ctask->itt); + iscsi_conn_printk(KERN_INFO, conn, + "dropping R2T itt %d in recovery.\n", + ctask->itt); return 0; } @@ -655,7 +657,8 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s r2t->exp_statsn = rhdr->statsn; r2t->data_length = be32_to_cpu(rhdr->data_length); if (r2t->data_length == 0) { - printk(KERN_ERR "iscsi_tcp: invalid R2T with zero data len\n"); + iscsi_conn_printk(KERN_ERR, conn, + "invalid R2T with zero data len\n"); __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); return ISCSI_ERR_DATALEN; @@ -668,9 +671,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s r2t->data_offset = be32_to_cpu(rhdr->data_offset); if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) { - printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at " - "offset %u and total length %d\n", r2t->data_length, - r2t->data_offset, scsi_bufflen(ctask->sc)); + iscsi_conn_printk(KERN_ERR, conn, + "invalid R2T with data len %u at offset %u " + "and total length %d\n", r2t->data_length, + r2t->data_offset, scsi_bufflen(ctask->sc)); __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); return ISCSI_ERR_DATALEN; @@ -736,8 +740,9 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn /* verify PDU length */ tcp_conn->in.datalen = ntoh24(hdr->dlength); if (tcp_conn->in.datalen > conn->max_recv_dlength) { - printk(KERN_ERR "iscsi_tcp: datalen %d > %d\n", - tcp_conn->in.datalen, conn->max_recv_dlength); + iscsi_conn_printk(KERN_ERR, conn, + "iscsi_tcp: datalen %d > %d\n", + tcp_conn->in.datalen, conn->max_recv_dlength); return ISCSI_ERR_DATALEN; } @@ -819,10 +824,12 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn * For now we fail until we find a vendor that needs it */ if (ISCSI_DEF_MAX_RECV_SEG_LEN < tcp_conn->in.datalen) { - printk(KERN_ERR "iscsi_tcp: received buffer of len %u " - "but conn buffer is only %u (opcode %0x)\n", - tcp_conn->in.datalen, - ISCSI_DEF_MAX_RECV_SEG_LEN, opcode); + iscsi_conn_printk(KERN_ERR, conn, + "iscsi_tcp: received buffer of " + "len %u but conn buffer is only %u " + "(opcode %0x)\n", + tcp_conn->in.datalen, + ISCSI_DEF_MAX_RECV_SEG_LEN, opcode); rc = ISCSI_ERR_PROTO; break; } @@ -1496,30 +1503,25 @@ iscsi_tcp_conn_create(struct iscsi_cls_s tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, CRYPTO_ALG_ASYNC); tcp_conn->tx_hash.flags = 0; - if (IS_ERR(tcp_conn->tx_hash.tfm)) { - printk(KERN_ERR "Could not create connection due to crc32c " - "loading error %ld. Make sure the crc32c module is " - "built as a module or into the kernel\n", - PTR_ERR(tcp_conn->tx_hash.tfm)); + if (IS_ERR(tcp_conn->tx_hash.tfm)) goto free_tcp_conn; - } tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, CRYPTO_ALG_ASYNC); tcp_conn->rx_hash.flags = 0; - if (IS_ERR(tcp_conn->rx_hash.tfm)) { - printk(KERN_ERR "Could not create connection due to crc32c " - "loading error %ld. Make sure the crc32c module is " - "built as a module or into the kernel\n", - PTR_ERR(tcp_conn->rx_hash.tfm)); + if (IS_ERR(tcp_conn->rx_hash.tfm)) goto free_tx_tfm; - } return cls_conn; free_tx_tfm: crypto_free_hash(tcp_conn->tx_hash.tfm); free_tcp_conn: + iscsi_conn_printk(KERN_ERR, conn, + "Could not create connection due to crc32c " + "loading error. Make sure the crc32c " + "module is built as a module or into the " + "kernel\n"); kfree(tcp_conn); tcp_conn_alloc_fail: iscsi_conn_teardown(cls_conn); @@ -1627,7 +1629,8 @@ iscsi_tcp_conn_bind(struct iscsi_cls_ses /* lookup for existing socket */ sock = sockfd_lookup((int)transport_eph, &err); if (!sock) { - printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err); + iscsi_conn_printk(KERN_ERR, conn, + "sockfd_lookup failed %d\n", err); return -EEXIST; } /* diff -puN drivers/scsi/libiscsi.c~git-scsi-misc drivers/scsi/libiscsi.c --- a/drivers/scsi/libiscsi.c~git-scsi-misc +++ a/drivers/scsi/libiscsi.c @@ -160,7 +160,7 @@ static int iscsi_prep_scsi_cmd_pdu(struc hdr->opcode = ISCSI_OP_SCSI_CMD; hdr->flags = ISCSI_ATTR_SIMPLE; int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); - hdr->itt = build_itt(ctask->itt, conn->id, session->age); + hdr->itt = build_itt(ctask->itt, session->age); hdr->data_length = cpu_to_be32(scsi_bufflen(sc)); hdr->cmdsn = cpu_to_be32(session->cmdsn); session->cmdsn++; @@ -416,8 +416,9 @@ static void iscsi_scsi_cmd_rsp(struct is if (datalen < 2) { invalid_datalen: - printk(KERN_ERR "iscsi: Got CHECK_CONDITION but " - "invalid data buffer size of %d\n", datalen); + iscsi_conn_printk(KERN_ERR, conn, + "Got CHECK_CONDITION but invalid data " + "buffer size of %d\n", datalen); sc->result = DID_BAD_TARGET << 16; goto out; } @@ -494,7 +495,7 @@ static void iscsi_send_nopout(struct isc mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); if (!mtask) { - printk(KERN_ERR "Could not send nopout\n"); + iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); return; } @@ -522,9 +523,10 @@ static int iscsi_handle_reject(struct is if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) { memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); itt = get_itt(rejected_pdu.itt); - printk(KERN_ERR "itt 0x%x had pdu (op 0x%x) rejected " - "due to DataDigest error.\n", itt, - rejected_pdu.opcode); + iscsi_conn_printk(KERN_ERR, conn, + "itt 0x%x had pdu (op 0x%x) rejected " + "due to DataDigest error.\n", itt, + rejected_pdu.opcode); } } return 0; @@ -541,8 +543,8 @@ static int iscsi_handle_reject(struct is * queuecommand or send generic. session lock must be held and verify * itt must have been called. */ -int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, - char *data, int datalen) +static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + char *data, int datalen) { struct iscsi_session *session = conn->session; int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0; @@ -672,7 +674,6 @@ int __iscsi_complete_pdu(struct iscsi_co return rc; } -EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, char *data, int datalen) @@ -697,18 +698,13 @@ int iscsi_verify_itt(struct iscsi_conn * if (hdr->itt != RESERVED_ITT) { if (((__force u32)hdr->itt & ISCSI_AGE_MASK) != (session->age << ISCSI_AGE_SHIFT)) { - printk(KERN_ERR "iscsi: received itt %x expected " - "session age (%x)\n", (__force u32)hdr->itt, - session->age & ISCSI_AGE_MASK); + iscsi_conn_printk(KERN_ERR, conn, + "received itt %x expected session " + "age (%x)\n", (__force u32)hdr->itt, + session->age & ISCSI_AGE_MASK); return ISCSI_ERR_BAD_ITT; } - if (((__force u32)hdr->itt & ISCSI_CID_MASK) != - (conn->id << ISCSI_CID_SHIFT)) { - printk(KERN_ERR "iscsi: received itt %x, expected " - "CID (%x)\n", (__force u32)hdr->itt, conn->id); - return ISCSI_ERR_BAD_ITT; - } itt = get_itt(hdr->itt); } else itt = ~0U; @@ -717,16 +713,17 @@ int iscsi_verify_itt(struct iscsi_conn * ctask = session->cmds[itt]; if (!ctask->sc) { - printk(KERN_INFO "iscsi: dropping ctask with " - "itt 0x%x\n", ctask->itt); + iscsi_conn_printk(KERN_INFO, conn, "dropping ctask " + "with itt 0x%x\n", ctask->itt); /* force drop */ return ISCSI_ERR_NO_SCSI_CMD; } if (ctask->sc->SCp.phase != session->age) { - printk(KERN_ERR "iscsi: ctask's session age %d, " - "expected %d\n", ctask->sc->SCp.phase, - session->age); + iscsi_conn_printk(KERN_ERR, conn, + "iscsi: ctask's session age %d, " + "expected %d\n", ctask->sc->SCp.phase, + session->age); return ISCSI_ERR_SESSION_FAILED; } } @@ -771,7 +768,7 @@ static void iscsi_prep_mtask(struct iscs */ nop->cmdsn = cpu_to_be32(session->cmdsn); if (hdr->itt != RESERVED_ITT) { - hdr->itt = build_itt(mtask->itt, conn->id, session->age); + hdr->itt = build_itt(mtask->itt, session->age); /* * TODO: We always use immediate, so we never hit this. * If we start to send tmfs or nops as non-immediate then @@ -997,6 +994,7 @@ enum { FAILURE_SESSION_IN_RECOVERY, FAILURE_SESSION_RECOVERY_TIMEOUT, FAILURE_SESSION_LOGGING_OUT, + FAILURE_SESSION_NOT_READY, }; int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) @@ -1017,6 +1015,12 @@ int iscsi_queuecommand(struct scsi_cmnd session = iscsi_hostdata(host->hostdata); spin_lock(&session->lock); + reason = iscsi_session_chkready(session_to_cls(session)); + if (reason) { + sc->result = reason; + goto fault; + } + /* * ISCSI_STATE_FAILED is a temp. state. The recovery * code will decide what is best to do with command queued @@ -1033,18 +1037,23 @@ int iscsi_queuecommand(struct scsi_cmnd switch (session->state) { case ISCSI_STATE_IN_RECOVERY: reason = FAILURE_SESSION_IN_RECOVERY; - goto reject; + sc->result = DID_IMM_RETRY << 16; + break; case ISCSI_STATE_LOGGING_OUT: reason = FAILURE_SESSION_LOGGING_OUT; - goto reject; + sc->result = DID_IMM_RETRY << 16; + break; case ISCSI_STATE_RECOVERY_FAILED: reason = FAILURE_SESSION_RECOVERY_TIMEOUT; + sc->result = DID_NO_CONNECT << 16; break; case ISCSI_STATE_TERMINATE: reason = FAILURE_SESSION_TERMINATE; + sc->result = DID_NO_CONNECT << 16; break; default: reason = FAILURE_SESSION_FREED; + sc->result = DID_NO_CONNECT << 16; } goto fault; } @@ -1052,6 +1061,7 @@ int iscsi_queuecommand(struct scsi_cmnd conn = session->leadconn; if (!conn) { reason = FAILURE_SESSION_FREED; + sc->result = DID_NO_CONNECT << 16; goto fault; } @@ -1091,9 +1101,7 @@ reject: fault: spin_unlock(&session->lock); - printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n", - sc->cmnd[0], reason); - sc->result = (DID_NO_CONNECT << 16); + debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason); scsi_set_resid(sc, scsi_bufflen(sc)); sc->scsi_done(sc); spin_lock(host->host_lock); @@ -1160,7 +1168,8 @@ failed: mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); if (session->state == ISCSI_STATE_LOGGED_IN) - printk(KERN_INFO "iscsi: host reset succeeded\n"); + iscsi_session_printk(KERN_INFO, session, + "host reset succeeded\n"); else goto failed; spin_unlock_bh(&session->lock); @@ -1239,7 +1248,8 @@ static int iscsi_exec_task_mgmt_fn(struc * Fail commands. session lock held and recv side suspended and xmit * thread flushed */ -static void fail_all_commands(struct iscsi_conn *conn, unsigned lun) +static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, + int error) { struct iscsi_cmd_task *ctask, *tmp; @@ -1251,7 +1261,7 @@ static void fail_all_commands(struct isc if (lun == ctask->sc->device->lun || lun == -1) { debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, ctask->itt); - fail_command(conn, ctask, DID_BUS_BUSY << 16); + fail_command(conn, ctask, error << 16); } } @@ -1259,7 +1269,7 @@ static void fail_all_commands(struct isc if (lun == ctask->sc->device->lun || lun == -1) { debug_scsi("failing requeued sc %p itt 0x%x\n", ctask->sc, ctask->itt); - fail_command(conn, ctask, DID_BUS_BUSY << 16); + fail_command(conn, ctask, error << 16); } } @@ -1357,10 +1367,10 @@ static void iscsi_check_transport_timeou last_recv = conn->last_recv; if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ), jiffies)) { - printk(KERN_ERR "ping timeout of %d secs expired, " - "last rx %lu, last ping %lu, now %lu\n", - conn->ping_timeout, last_recv, - conn->last_ping, jiffies); + iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " + "expired, last rx %lu, last ping %lu, " + "now %lu\n", conn->ping_timeout, last_recv, + conn->last_ping, jiffies); spin_unlock(&session->lock); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); return; @@ -1373,14 +1383,11 @@ static void iscsi_check_transport_timeou iscsi_send_nopout(conn, NULL); } next_timeout = last_recv + timeout + (conn->ping_timeout * HZ); - } else { + } else next_timeout = last_recv + timeout; - } - if (next_timeout) { - debug_scsi("Setting next tmo %lu\n", next_timeout); - mod_timer(&conn->transport_timer, next_timeout); - } + debug_scsi("Setting next tmo %lu\n", next_timeout); + mod_timer(&conn->transport_timer, next_timeout); done: spin_unlock(&session->lock); } @@ -1573,7 +1580,7 @@ int iscsi_eh_device_reset(struct scsi_cm /* need to grab the recv lock then session lock */ write_lock_bh(conn->recv_lock); spin_lock(&session->lock); - fail_all_commands(conn, sc->device->lun); + fail_all_commands(conn, sc->device->lun, DID_ERROR); conn->tmf_state = TMF_INITIAL; spin_unlock(&session->lock); write_unlock_bh(conn->recv_lock); @@ -1944,9 +1951,10 @@ void iscsi_conn_teardown(struct iscsi_cl } spin_unlock_irqrestore(session->host->host_lock, flags); msleep_interruptible(500); - printk(KERN_INFO "iscsi: scsi conn_destroy(): host_busy %d " - "host_failed %d\n", session->host->host_busy, - session->host->host_failed); + iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): " + "host_busy %d host_failed %d\n", + session->host->host_busy, + session->host->host_failed); /* * force eh_abort() to unblock */ @@ -1975,27 +1983,28 @@ int iscsi_conn_start(struct iscsi_cls_co struct iscsi_session *session = conn->session; if (!session) { - printk(KERN_ERR "iscsi: can't start unbound connection\n"); + iscsi_conn_printk(KERN_ERR, conn, + "can't start unbound connection\n"); return -EPERM; } if ((session->imm_data_en || !session->initial_r2t_en) && session->first_burst > session->max_burst) { - printk("iscsi: invalid burst lengths: " - "first_burst %d max_burst %d\n", - session->first_burst, session->max_burst); + iscsi_conn_printk(KERN_INFO, conn, "invalid burst lengths: " + "first_burst %d max_burst %d\n", + session->first_burst, session->max_burst); return -EINVAL; } if (conn->ping_timeout && !conn->recv_timeout) { - printk(KERN_ERR "iscsi: invalid recv timeout of zero " - "Using 5 seconds\n."); + iscsi_conn_printk(KERN_ERR, conn, "invalid recv timeout of " + "zero. Using 5 seconds\n."); conn->recv_timeout = 5; } if (conn->recv_timeout && !conn->ping_timeout) { - printk(KERN_ERR "iscsi: invalid ping timeout of zero " - "Using 5 seconds.\n"); + iscsi_conn_printk(KERN_ERR, conn, "invalid ping timeout of " + "zero. Using 5 seconds.\n"); conn->ping_timeout = 5; } @@ -2019,11 +2028,9 @@ int iscsi_conn_start(struct iscsi_cls_co conn->stop_stage = 0; conn->tmf_state = TMF_INITIAL; session->age++; - spin_unlock_bh(&session->lock); - - iscsi_unblock_session(session_to_cls(session)); - wake_up(&conn->ehwait); - return 0; + if (session->age == 16) + session->age = 0; + break; case STOP_CONN_TERM: conn->stop_stage = 0; break; @@ -2032,6 +2039,8 @@ int iscsi_conn_start(struct iscsi_cls_co } spin_unlock_bh(&session->lock); + iscsi_unblock_session(session_to_cls(session)); + wake_up(&conn->ehwait); return 0; } EXPORT_SYMBOL_GPL(iscsi_conn_start); @@ -2123,7 +2132,8 @@ static void iscsi_start_session_recovery * flush queues. */ spin_lock_bh(&session->lock); - fail_all_commands(conn, -1); + fail_all_commands(conn, -1, + STOP_CONN_RECOVER ? DID_BUS_BUSY : DID_ERROR); flush_control_queues(session, conn); spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); @@ -2140,7 +2150,8 @@ void iscsi_conn_stop(struct iscsi_cls_co iscsi_start_session_recovery(session, conn, flag); break; default: - printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag); + iscsi_conn_printk(KERN_ERR, conn, + "invalid stop flag %d\n", flag); } } EXPORT_SYMBOL_GPL(iscsi_conn_stop); diff -puN drivers/scsi/lpfc/lpfc_init.c~git-scsi-misc drivers/scsi/lpfc/lpfc_init.c diff -puN drivers/scsi/mca_53c9x.c~git-scsi-misc /dev/null --- a/drivers/scsi/mca_53c9x.c +++ /dev/null @@ -1,520 +0,0 @@ -/* mca_53c9x.c: Driver for the SCSI adapter found on NCR 35xx - * (and maybe some other) Microchannel machines - * - * Code taken mostly from Cyberstorm SCSI drivers - * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) - * - * Hacked to work with the NCR MCA stuff by Tymm Twillman (tymm@computer.org) - * - * The CyberStorm SCSI driver (and this driver) is based on David S. Miller's - * ESP driver * for the Sparc computers. - * - * Special thanks to Ken Stewart at Symbios (LSI) for helping with info on - * the 86C01. I was on the brink of going ga-ga... - * - * Also thanks to Jesper Skov for helping me with info on how the Amiga - * does things... - */ - -/* - * This is currently only set up to use one 53c9x card at a time; it could be - * changed fairly easily to detect/use more than one, but I'm not too sure how - * many cards that use the 53c9x on MCA systems there are (if, in fact, there - * are cards that use them, other than the one built into some NCR systems)... - * If anyone requests this, I'll throw it in, otherwise it's not worth the - * effort. - */ - -/* - * Info on the 86C01 MCA interface chip at the bottom, if you care enough to - * look. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "scsi.h" -#include -#include "NCR53C9x.h" - -#include -#include -#include -#include - -/* - * From ibmmca.c (IBM scsi controller card driver) -- used for turning PS2 disk - * activity LED on and off - */ - -#define PS2_SYS_CTR 0x92 - -/* Ports the ncr's 53c94 can be put at; indexed by pos register value */ - -#define MCA_53C9X_IO_PORTS { \ - 0x0000, 0x0240, 0x0340, 0x0400, \ - 0x0420, 0x3240, 0x8240, 0xA240, \ - } - -/* - * Supposedly there were some cards put together with the 'c9x and 86c01. If - * they have different ID's from the ones on the 3500 series machines, - * you can add them here and hopefully things will work out. - */ - -#define MCA_53C9X_IDS { \ - 0x7F4C, \ - 0x0000, \ - } - -static int dma_bytes_sent(struct NCR_ESP *, int); -static int dma_can_transfer(struct NCR_ESP *, Scsi_Cmnd *); -static void dma_dump_state(struct NCR_ESP *); -static void dma_init_read(struct NCR_ESP *, __u32, int); -static void dma_init_write(struct NCR_ESP *, __u32, int); -static void dma_ints_off(struct NCR_ESP *); -static void dma_ints_on(struct NCR_ESP *); -static int dma_irq_p(struct NCR_ESP *); -static int dma_ports_p(struct NCR_ESP *); -static void dma_setup(struct NCR_ESP *, __u32, int, int); -static void dma_led_on(struct NCR_ESP *); -static void dma_led_off(struct NCR_ESP *); - -/* This is where all commands are put before they are trasfered to the - * 53c9x via PIO. - */ - -static volatile unsigned char cmd_buffer[16]; - -/* - * We keep the structure that is used to access the registers on the 53c9x - * here. - */ - -static struct ESP_regs eregs; - -/***************************************************************** Detection */ -static int mca_esp_detect(struct scsi_host_template *tpnt) -{ - struct NCR_ESP *esp; - static int io_port_by_pos[] = MCA_53C9X_IO_PORTS; - int mca_53c9x_ids[] = MCA_53C9X_IDS; - int *id_to_check = mca_53c9x_ids; - int slot; - int pos[3]; - unsigned int tmp_io_addr; - unsigned char tmp_byte; - - - if (!MCA_bus) - return 0; - - while (*id_to_check) { - if ((slot = mca_find_adapter(*id_to_check, 0)) != - MCA_NOTFOUND) - { - esp = esp_allocate(tpnt, NULL, 0); - - pos[0] = mca_read_stored_pos(slot, 2); - pos[1] = mca_read_stored_pos(slot, 3); - pos[2] = mca_read_stored_pos(slot, 4); - - esp->eregs = &eregs; - - /* - * IO port base is given in the first (non-ID) pos - * register, like so: - * - * Bits 3 2 1 IO base - * ---------------------------- - * 0 0 0 - * 0 0 1 0x0240 - * 0 1 0 0x0340 - * 0 1 1 0x0400 - * 1 0 0 0x0420 - * 1 0 1 0x3240 - * 1 1 0 0x8240 - * 1 1 1 0xA240 - */ - - tmp_io_addr = - io_port_by_pos[(pos[0] & 0x0E) >> 1]; - - esp->eregs->io_addr = tmp_io_addr + 0x10; - - if (esp->eregs->io_addr == 0x0000) { - printk("Adapter is disabled.\n"); - break; - } - - /* - * IRQ is specified in bits 4 and 5: - * - * Bits 4 5 IRQ - * ----------------------- - * 0 0 3 - * 0 1 5 - * 1 0 7 - * 1 1 9 - */ - - esp->irq = ((pos[0] & 0x30) >> 3) + 3; - - /* - * DMA channel is in the low 3 bits of the second - * POS register - */ - - esp->dma = pos[1] & 7; - esp->slot = slot; - - if (request_irq(esp->irq, esp_intr, 0, - "NCR 53c9x SCSI", esp->ehost)) - { - printk("Unable to request IRQ %d.\n", esp->irq); - esp_deallocate(esp); - scsi_unregister(esp->ehost); - return 0; - } - - if (request_dma(esp->dma, "NCR 53c9x SCSI")) { - printk("Unable to request DMA channel %d.\n", - esp->dma); - free_irq(esp->irq, esp_intr); - esp_deallocate(esp); - scsi_unregister(esp->ehost); - return 0; - } - - request_region(tmp_io_addr, 32, "NCR 53c9x SCSI"); - - /* - * 86C01 handles DMA, IO mode, from address - * (base + 0x0a) - */ - - mca_disable_dma(esp->dma); - mca_set_dma_io(esp->dma, tmp_io_addr + 0x0a); - mca_enable_dma(esp->dma); - - /* Tell the 86C01 to give us interrupts */ - - tmp_byte = inb(tmp_io_addr + 0x02) | 0x40; - outb(tmp_byte, tmp_io_addr + 0x02); - - /* - * Scsi ID -- general purpose register, hi - * 2 bits; add 4 to this number to get the - * ID - */ - - esp->scsi_id = ((pos[2] & 0xC0) >> 6) + 4; - - /* Do command transfer with programmed I/O */ - - esp->do_pio_cmds = 1; - - /* Required functions */ - - esp->dma_bytes_sent = &dma_bytes_sent; - esp->dma_can_transfer = &dma_can_transfer; - esp->dma_dump_state = &dma_dump_state; - esp->dma_init_read = &dma_init_read; - esp->dma_init_write = &dma_init_write; - esp->dma_ints_off = &dma_ints_off; - esp->dma_ints_on = &dma_ints_on; - esp->dma_irq_p = &dma_irq_p; - esp->dma_ports_p = &dma_ports_p; - esp->dma_setup = &dma_setup; - - /* Optional functions */ - - esp->dma_barrier = NULL; - esp->dma_drain = NULL; - esp->dma_invalidate = NULL; - esp->dma_irq_entry = NULL; - esp->dma_irq_exit = NULL; - esp->dma_led_on = dma_led_on; - esp->dma_led_off = dma_led_off; - esp->dma_poll = NULL; - esp->dma_reset = NULL; - - /* Set the command buffer */ - - esp->esp_command = (volatile unsigned char*) - cmd_buffer; - esp->esp_command_dvma = isa_virt_to_bus(cmd_buffer); - - /* SCSI chip speed */ - - esp->cfreq = 25000000; - - /* Differential SCSI? I think not. */ - - esp->diff = 0; - - esp_initialize(esp); - - printk(" Adapter found in slot %2d: io port 0x%x " - "irq %d dma channel %d\n", slot + 1, tmp_io_addr, - esp->irq, esp->dma); - - mca_set_adapter_name(slot, "NCR 53C9X SCSI Adapter"); - mca_mark_as_used(slot); - - break; - } - - id_to_check++; - } - - return esps_in_use; -} - - -/******************************************************************* Release */ - -static int mca_esp_release(struct Scsi_Host *host) -{ - struct NCR_ESP *esp = (struct NCR_ESP *)host->hostdata; - unsigned char tmp_byte; - - esp_deallocate(esp); - /* - * Tell the 86C01 to stop sending interrupts - */ - - tmp_byte = inb(esp->eregs->io_addr - 0x0E); - tmp_byte &= ~0x40; - outb(tmp_byte, esp->eregs->io_addr - 0x0E); - - free_irq(esp->irq, esp_intr); - free_dma(esp->dma); - - mca_mark_as_unused(esp->slot); - - return 0; -} - -/************************************************************* DMA Functions */ -static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) -{ - /* Ask the 53c9x. It knows. */ - - return fifo_count; -} - -static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) -{ - /* - * The MCA dma channels can only do up to 128K bytes at a time. - * (16 bit mode) - */ - - unsigned long sz = sp->SCp.this_residual; - if(sz > 0x20000) - sz = 0x20000; - return sz; -} - -static void dma_dump_state(struct NCR_ESP *esp) -{ - /* - * Doesn't quite match up to the other drivers, but we do what we - * can. - */ - - ESPLOG(("esp%d: dma channel <%d>\n", esp->esp_id, esp->dma)); - ESPLOG(("bytes left to dma: %d\n", mca_get_dma_residue(esp->dma))); -} - -static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) -{ - unsigned long flags; - - - save_flags(flags); - cli(); - - mca_disable_dma(esp->dma); - mca_set_dma_mode(esp->dma, MCA_DMA_MODE_XFER | MCA_DMA_MODE_16 | - MCA_DMA_MODE_IO); - mca_set_dma_addr(esp->dma, addr); - mca_set_dma_count(esp->dma, length / 2); /* !!! */ - mca_enable_dma(esp->dma); - - restore_flags(flags); -} - -static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length) -{ - unsigned long flags; - - - save_flags(flags); - cli(); - - mca_disable_dma(esp->dma); - mca_set_dma_mode(esp->dma, MCA_DMA_MODE_XFER | MCA_DMA_MODE_WRITE | - MCA_DMA_MODE_16 | MCA_DMA_MODE_IO); - mca_set_dma_addr(esp->dma, addr); - mca_set_dma_count(esp->dma, length / 2); /* !!! */ - mca_enable_dma(esp->dma); - - restore_flags(flags); -} - -static void dma_ints_off(struct NCR_ESP *esp) -{ - /* - * Tell the 'C01 to shut up. All interrupts are routed through it. - */ - - outb(inb(esp->eregs->io_addr - 0x0E) & ~0x40, - esp->eregs->io_addr - 0x0E); -} - -static void dma_ints_on(struct NCR_ESP *esp) -{ - /* - * Ok. You can speak again. - */ - - outb(inb(esp->eregs->io_addr - 0x0E) | 0x40, - esp->eregs->io_addr - 0x0E); -} - -static int dma_irq_p(struct NCR_ESP *esp) -{ - /* - * DaveM says that this should return a "yes" if there is an interrupt - * or a DMA error occurred. I copied the Amiga driver's semantics, - * though, because it seems to work and we can't really tell if - * a DMA error happened. This gives the "yes" if the scsi chip - * is sending an interrupt and no DMA activity is taking place - */ - - return (!(inb(esp->eregs->io_addr - 0x04) & 1) && - !(inb(esp->eregs->io_addr - 0x04) & 2) ); -} - -static int dma_ports_p(struct NCR_ESP *esp) -{ - /* - * Check to see if interrupts are enabled on the 'C01 (in case abort - * is entered multiple times, so we only do the abort once) - */ - - return (inb(esp->eregs->io_addr - 0x0E) & 0x40) ? 1:0; -} - -static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) -{ - if(write){ - dma_init_write(esp, addr, count); - } else { - dma_init_read(esp, addr, count); - } -} - -/* - * These will not play nicely with other disk controllers that try to use the - * disk active LED... but what can you do? Don't answer that. - * - * Stolen shamelessly from ibmmca.c -- IBM Microchannel SCSI adapter driver - * - */ - -static void dma_led_on(struct NCR_ESP *esp) -{ - outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); -} - -static void dma_led_off(struct NCR_ESP *esp) -{ - outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); -} - -static struct scsi_host_template driver_template = { - .proc_name = "mca_53c9x", - .name = "NCR 53c9x SCSI", - .detect = mca_esp_detect, - .slave_alloc = esp_slave_alloc, - .slave_destroy = esp_slave_destroy, - .release = mca_esp_release, - .queuecommand = esp_queue, - .eh_abort_handler = esp_abort, - .eh_bus_reset_handler = esp_reset, - .can_queue = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .unchecked_isa_dma = 1, - .use_clustering = DISABLE_CLUSTERING -}; - - -#include "scsi_module.c" - -/* - * OK, here's the goods I promised. The NCR 86C01 is an MCA interface chip - * that handles enabling/diabling IRQ, dma interfacing, IO port selection - * and other fun stuff. It takes up 16 addresses, and the chip it is - * connnected to gets the following 16. Registers are as follows: - * - * Offsets 0-1 : Card ID - * - * Offset 2 : Mode enable register -- - * Bit 7 : Data Word width (1 = 16, 0 = 8) - * Bit 6 : IRQ enable (1 = enabled) - * Bits 5,4 : IRQ select - * 0 0 : IRQ 3 - * 0 1 : IRQ 5 - * 1 0 : IRQ 7 - * 1 1 : IRQ 9 - * Bits 3-1 : Base Address - * 0 0 0 : - * 0 0 1 : 0x0240 - * 0 1 0 : 0x0340 - * 0 1 1 : 0x0400 - * 1 0 0 : 0x0420 - * 1 0 1 : 0x3240 - * 1 1 0 : 0x8240 - * 1 1 1 : 0xA240 - * Bit 0 : Card enable (1 = enabled) - * - * Offset 3 : DMA control register -- - * Bit 7 : DMA enable (1 = enabled) - * Bits 6,5 : Preemt Count Select (transfers to complete after - * 'C01 has been preempted on MCA bus) - * 0 0 : 0 - * 0 1 : 1 - * 1 0 : 3 - * 1 1 : 7 - * (all these wacky numbers; I'm sure there's a reason somewhere) - * Bit 4 : Fairness enable (1 = fair bus priority) - * Bits 3-0 : Arbitration level (0-15 consecutive) - * - * Offset 4 : General purpose register - * Bits 7-3 : User definable (here, 7,6 are SCSI ID) - * Bits 2-0 : reserved - * - * Offset 10 : DMA decode register (used for IO based DMA; also can do - * PIO through this port) - * - * Offset 12 : Status - * Bits 7-2 : reserved - * Bit 1 : DMA pending (1 = pending) - * Bit 0 : IRQ pending (0 = pending) - * - * Exciting, huh? - * - */ diff -puN drivers/scsi/ps3rom.c~git-scsi-misc drivers/scsi/ps3rom.c --- a/drivers/scsi/ps3rom.c~git-scsi-misc +++ a/drivers/scsi/ps3rom.c @@ -35,7 +35,7 @@ #define BOUNCE_SIZE (64*1024) -#define PS3ROM_MAX_SECTORS (BOUNCE_SIZE / CD_FRAMESIZE) +#define PS3ROM_MAX_SECTORS (BOUNCE_SIZE >> 9) struct ps3rom_private { diff -puN drivers/scsi/qla2xxx/qla_attr.c~git-scsi-misc drivers/scsi/qla2xxx/qla_attr.c --- a/drivers/scsi/qla2xxx/qla_attr.c~git-scsi-misc +++ a/drivers/scsi/qla2xxx/qla_attr.c @@ -428,6 +428,19 @@ qla2x00_sysfs_read_sfp(struct kobject *k if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2) return 0; + if (ha->sfp_data) + goto do_read; + + ha->sfp_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, + &ha->sfp_data_dma); + if (!ha->sfp_data) { + qla_printk(KERN_WARNING, ha, + "Unable to allocate memory for SFP read-data.\n"); + return 0; + } + +do_read: + memset(ha->sfp_data, 0, SFP_BLOCK_SIZE); addr = 0xa0; for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE; iter++, offset += SFP_BLOCK_SIZE) { @@ -835,7 +848,7 @@ qla2x00_get_host_port_id(struct Scsi_Hos static void qla2x00_get_host_speed(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost)); uint32_t speed = 0; switch (ha->link_data_rate) { @@ -848,6 +861,9 @@ qla2x00_get_host_speed(struct Scsi_Host case PORT_SPEED_4GB: speed = 4; break; + case PORT_SPEED_8GB: + speed = 8; + break; } fc_host_speed(shost) = speed; } @@ -855,7 +871,7 @@ qla2x00_get_host_speed(struct Scsi_Host static void qla2x00_get_host_port_type(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost)); uint32_t port_type = FC_PORTTYPE_UNKNOWN; switch (ha->current_topology) { @@ -965,7 +981,7 @@ qla2x00_issue_lip(struct Scsi_Host *shos static struct fc_host_statistics * qla2x00_get_fc_host_stats(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost)); int rval; struct link_statistics *stats; dma_addr_t stats_dma; @@ -1049,7 +1065,7 @@ qla2x00_get_host_fabric_name(struct Scsi static void qla2x00_get_host_port_state(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost)); if (!ha->flags.online) fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; diff -puN drivers/scsi/qla2xxx/qla_def.h~git-scsi-misc drivers/scsi/qla2xxx/qla_def.h --- a/drivers/scsi/qla2xxx/qla_def.h~git-scsi-misc +++ a/drivers/scsi/qla2xxx/qla_def.h @@ -2041,8 +2041,6 @@ typedef struct vport_params { #define VP_RET_CODE_NO_MEM 5 #define VP_RET_CODE_NOT_FOUND 6 -#define to_qla_parent(x) (((x)->parent) ? (x)->parent : (x)) - /* * ISP operations */ diff -puN drivers/scsi/qla2xxx/qla_gbl.h~git-scsi-misc drivers/scsi/qla2xxx/qla_gbl.h --- a/drivers/scsi/qla2xxx/qla_gbl.h~git-scsi-misc +++ a/drivers/scsi/qla2xxx/qla_gbl.h @@ -66,6 +66,7 @@ extern int ql2xqfullrampup; extern int num_hosts; extern int qla2x00_loop_reset(scsi_qla_host_t *); +extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); /* * Global Functions in qla_mid.c source file. diff -puN drivers/scsi/qla2xxx/qla_init.c~git-scsi-misc drivers/scsi/qla2xxx/qla_init.c --- a/drivers/scsi/qla2xxx/qla_init.c~git-scsi-misc +++ a/drivers/scsi/qla2xxx/qla_init.c @@ -925,6 +925,16 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) { int rval; uint32_t srisc_address = 0; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + unsigned long flags; + + if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) { + /* Disable SRAM, Instruction RAM and GP RAM parity. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + WRT_REG_WORD(®->hccr, (HCCR_ENABLE_PARITY + 0x0)); + RD_REG_WORD(®->hccr); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + } /* Load firmware sequences */ rval = ha->isp_ops->load_risc(ha, &srisc_address); @@ -968,6 +978,19 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) } } + if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) { + /* Enable proper parity. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + if (IS_QLA2300(ha)) + /* SRAM parity */ + WRT_REG_WORD(®->hccr, HCCR_ENABLE_PARITY + 0x1); + else + /* SRAM, Instruction RAM and GP RAM parity */ + WRT_REG_WORD(®->hccr, HCCR_ENABLE_PARITY + 0x7); + RD_REG_WORD(®->hccr); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + } + if (rval) { DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n", ha->host_no)); @@ -3213,9 +3236,6 @@ int qla2x00_abort_isp(scsi_qla_host_t *ha) { int rval; - unsigned long flags = 0; - uint16_t cnt; - srb_t *sp; uint8_t status = 0; if (ha->flags.online) { @@ -3236,19 +3256,8 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) LOOP_DOWN_TIME); } - spin_lock_irqsave(&ha->hardware_lock, flags); /* Requeue all commands in outstanding command list. */ - for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { - sp = ha->outstanding_cmds[cnt]; - if (sp) { - ha->outstanding_cmds[cnt] = NULL; - sp->flags = 0; - sp->cmd->result = DID_RESET << 16; - sp->cmd->host_scribble = (unsigned char *)NULL; - qla2x00_sp_compl(ha, sp); - } - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); + qla2x00_abort_all_cmds(ha, DID_RESET << 16); ha->isp_ops->get_flash_version(ha, ha->request_ring); @@ -3273,6 +3282,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); if (ha->eft) { + memset(ha->eft, 0, EFT_SIZE); rval = qla2x00_enable_eft_trace(ha, ha->eft_dma, EFT_NUM_BUFFERS); if (rval) { @@ -3357,60 +3367,15 @@ static int qla2x00_restart_isp(scsi_qla_host_t *ha) { uint8_t status = 0; - struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - unsigned long flags = 0; uint32_t wait_time; /* If firmware needs to be loaded */ if (qla2x00_isp_firmware(ha)) { ha->flags.online = 0; - if (!(status = ha->isp_ops->chip_diag(ha))) { - if (IS_QLA2100(ha) || IS_QLA2200(ha)) { - status = qla2x00_setup_chip(ha); - goto done; - } - - spin_lock_irqsave(&ha->hardware_lock, flags); - - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha) && - !IS_QLA25XX(ha)) { - /* - * Disable SRAM, Instruction RAM and GP RAM - * parity. - */ - WRT_REG_WORD(®->hccr, - (HCCR_ENABLE_PARITY + 0x0)); - RD_REG_WORD(®->hccr); - } - - spin_unlock_irqrestore(&ha->hardware_lock, flags); - + if (!(status = ha->isp_ops->chip_diag(ha))) status = qla2x00_setup_chip(ha); - - spin_lock_irqsave(&ha->hardware_lock, flags); - - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha) && - !IS_QLA25XX(ha)) { - /* Enable proper parity */ - if (IS_QLA2300(ha)) - /* SRAM parity */ - WRT_REG_WORD(®->hccr, - (HCCR_ENABLE_PARITY + 0x1)); - else - /* - * SRAM, Instruction RAM and GP RAM - * parity. - */ - WRT_REG_WORD(®->hccr, - (HCCR_ENABLE_PARITY + 0x7)); - RD_REG_WORD(®->hccr); - } - - spin_unlock_irqrestore(&ha->hardware_lock, flags); - } } - done: if (!status && !(status = qla2x00_init_rings(ha))) { clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); if (!(status = qla2x00_fw_ready(ha))) { diff -puN drivers/scsi/qla2xxx/qla_inline.h~git-scsi-misc drivers/scsi/qla2xxx/qla_inline.h --- a/drivers/scsi/qla2xxx/qla_inline.h~git-scsi-misc +++ a/drivers/scsi/qla2xxx/qla_inline.h @@ -119,6 +119,13 @@ static __inline__ void qla2x00_check_fab qla2x00_get_firmware_state(ha, &fw_state); } +static __inline__ scsi_qla_host_t * to_qla_parent(scsi_qla_host_t *); +static __inline__ scsi_qla_host_t * +to_qla_parent(scsi_qla_host_t *ha) +{ + return ha->parent ? ha->parent : ha; +} + /** * qla2x00_issue_marker() - Issue a Marker IOCB if necessary. * @ha: HA context diff -puN drivers/scsi/qla2xxx/qla_isr.c~git-scsi-misc drivers/scsi/qla2xxx/qla_isr.c --- a/drivers/scsi/qla2xxx/qla_isr.c~git-scsi-misc +++ a/drivers/scsi/qla2xxx/qla_isr.c @@ -1815,6 +1815,8 @@ int qla2x00_request_irqs(scsi_qla_host_t *ha) { int ret; + device_reg_t __iomem *reg = ha->iobase; + unsigned long flags; /* If possible, enable MSI-X. */ if (!IS_QLA2432(ha) && !IS_QLA2532(ha)) @@ -1846,7 +1848,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha DEBUG2(qla_printk(KERN_INFO, ha, "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision, ha->fw_attributes)); - return ret; + goto clear_risc_ints; } qla_printk(KERN_WARNING, ha, "MSI-X: Falling back-to INTa mode -- %d.\n", ret); @@ -1864,15 +1866,30 @@ skip_msi: ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); - if (!ret) { - ha->flags.inta_enabled = 1; - ha->host->irq = ha->pdev->irq; - } else { + if (ret) { qla_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d already in use.\n", ha->pdev->irq); + goto fail; + } + ha->flags.inta_enabled = 1; + ha->host->irq = ha->pdev->irq; +clear_risc_ints: + + ha->isp_ops->disable_intrs(ha); + spin_lock_irqsave(&ha->hardware_lock, flags); + if (IS_FWI2_CAPABLE(ha)) { + WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT); + WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT); + } else { + WRT_REG_WORD(®->isp.semaphore, 0); + WRT_REG_WORD(®->isp.hccr, HCCR_CLR_RISC_INT); + WRT_REG_WORD(®->isp.hccr, HCCR_CLR_HOST_INT); } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + ha->isp_ops->enable_intrs(ha); +fail: return ret; } diff -puN drivers/scsi/qla2xxx/qla_mbx.c~git-scsi-misc drivers/scsi/qla2xxx/qla_mbx.c --- a/drivers/scsi/qla2xxx/qla_mbx.c~git-scsi-misc +++ a/drivers/scsi/qla2xxx/qla_mbx.c @@ -980,7 +980,7 @@ qla2x00_init_firmware(scsi_qla_host_t *h DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n", ha->host_no)); - if (ha->fw_attributes & BIT_2) + if (ha->flags.npiv_supported) mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE; else mcp->mb[0] = MBC_INITIALIZE_FIRMWARE; diff -puN drivers/scsi/qla2xxx/qla_os.c~git-scsi-misc drivers/scsi/qla2xxx/qla_os.c --- a/drivers/scsi/qla2xxx/qla_os.c~git-scsi-misc +++ a/drivers/scsi/qla2xxx/qla_os.c @@ -204,10 +204,8 @@ static int qla2x00_do_dpc(void *data); static void qla2x00_rst_aen(scsi_qla_host_t *); -static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); +static int qla2x00_mem_alloc(scsi_qla_host_t *); static void qla2x00_mem_free(scsi_qla_host_t *ha); -static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); -static void qla2x00_free_sp_pool(scsi_qla_host_t *ha); static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *); /* -------------------------------------------------------------------------- */ @@ -1117,6 +1115,27 @@ qla2x00_device_reset(scsi_qla_host_t *ha return ha->isp_ops->abort_target(reset_fcport); } +void +qla2x00_abort_all_cmds(scsi_qla_host_t *ha, int res) +{ + int cnt; + unsigned long flags; + srb_t *sp; + + spin_lock_irqsave(&ha->hardware_lock, flags); + for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + sp = ha->outstanding_cmds[cnt]; + if (sp) { + ha->outstanding_cmds[cnt] = NULL; + sp->flags = 0; + sp->cmd->result = res; + sp->cmd->host_scribble = (unsigned char *)NULL; + qla2x00_sp_compl(ha, sp); + } + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + static int qla2xxx_slave_alloc(struct scsi_device *sdev) { @@ -1557,10 +1576,8 @@ static int __devinit qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { int ret = -ENODEV; - device_reg_t __iomem *reg; struct Scsi_Host *host; scsi_qla_host_t *ha; - unsigned long flags = 0; char pci_info[30]; char fw_str[30]; struct scsi_host_template *sht; @@ -1608,6 +1625,7 @@ qla2x00_probe_one(struct pci_dev *pdev, ha->parent = NULL; ha->bars = bars; ha->mem_only = mem_only; + spin_lock_init(&ha->hardware_lock); /* Set ISP-type information. */ qla2x00_set_isp_flags(ha); @@ -1621,8 +1639,6 @@ qla2x00_probe_one(struct pci_dev *pdev, "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq, ha->iobase); - spin_lock_init(&ha->hardware_lock); - ha->prev_topology = 0; ha->init_cb_size = sizeof(init_cb_t); ha->mgmt_svr_loop_id = MANAGEMENT_SERVER + ha->vp_idx; @@ -1751,34 +1767,6 @@ qla2x00_probe_one(struct pci_dev *pdev, DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", ha->host_no, ha)); - ha->isp_ops->disable_intrs(ha); - - spin_lock_irqsave(&ha->hardware_lock, flags); - reg = ha->iobase; - if (IS_FWI2_CAPABLE(ha)) { - WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT); - WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT); - } else { - WRT_REG_WORD(®->isp.semaphore, 0); - WRT_REG_WORD(®->isp.hccr, HCCR_CLR_RISC_INT); - WRT_REG_WORD(®->isp.hccr, HCCR_CLR_HOST_INT); - - /* Enable proper parity */ - if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) { - if (IS_QLA2300(ha)) - /* SRAM parity */ - WRT_REG_WORD(®->isp.hccr, - (HCCR_ENABLE_PARITY + 0x1)); - else - /* SRAM, Instruction RAM and GP RAM parity */ - WRT_REG_WORD(®->isp.hccr, - (HCCR_ENABLE_PARITY + 0x7)); - } - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - ha->isp_ops->enable_intrs(ha); - pci_set_drvdata(pdev, ha); ha->flags.init_done = 1; @@ -1848,10 +1836,14 @@ qla2x00_remove_one(struct pci_dev *pdev) static void qla2x00_free_device(scsi_qla_host_t *ha) { + qla2x00_abort_all_cmds(ha, DID_NO_CONNECT << 16); + /* Disable timer */ if (ha->timer_active) qla2x00_stop_timer(ha); + ha->flags.online = 0; + /* Kill the kernel thread for this host */ if (ha->dpc_thread) { struct task_struct *t = ha->dpc_thread; @@ -1870,8 +1862,6 @@ qla2x00_free_device(scsi_qla_host_t *ha) if (ha->eft) qla2x00_disable_eft_trace(ha); - ha->flags.online = 0; - /* Stop currently executing firmware. */ qla2x00_try_to_stop_firmware(ha); @@ -2010,196 +2000,109 @@ qla2x00_mark_all_devices_lost(scsi_qla_h * * Returns: * 0 = success. -* 1 = failure. +* !0 = failure. */ -static uint8_t +static int qla2x00_mem_alloc(scsi_qla_host_t *ha) { char name[16]; - uint8_t status = 1; - int retry= 10; - - do { - /* - * This will loop only once if everything goes well, else some - * number of retries will be performed to get around a kernel - * bug where available mem is not allocated until after a - * little delay and a retry. - */ - ha->request_ring = dma_alloc_coherent(&ha->pdev->dev, - (ha->request_q_length + 1) * sizeof(request_t), - &ha->request_dma, GFP_KERNEL); - if (ha->request_ring == NULL) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - request_ring\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - - ha->response_ring = dma_alloc_coherent(&ha->pdev->dev, - (ha->response_q_length + 1) * sizeof(response_t), - &ha->response_dma, GFP_KERNEL); - if (ha->response_ring == NULL) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - response_ring\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - - ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE, - &ha->gid_list_dma, GFP_KERNEL); - if (ha->gid_list == NULL) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - gid_list\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - - /* get consistent memory allocated for init control block */ - ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, - ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL); - if (ha->init_cb == NULL) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - init_cb\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - memset(ha->init_cb, 0, ha->init_cb_size); - - snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, - ha->host_no); - ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, - DMA_POOL_SIZE, 8, 0); - if (ha->s_dma_pool == NULL) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - s_dma_pool\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - - if (qla2x00_allocate_sp_pool(ha)) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - " - "qla2x00_allocate_sp_pool()\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - - /* Allocate memory for SNS commands */ - if (IS_QLA2100(ha) || IS_QLA2200(ha)) { - /* Get consistent memory allocated for SNS commands */ - ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev, - sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, - GFP_KERNEL); - if (ha->sns_cmd == NULL) { - /* error */ - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - sns_cmd\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - memset(ha->sns_cmd, 0, sizeof(struct sns_cmd_pkt)); - } else { - /* Get consistent memory allocated for MS IOCB */ - ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, - &ha->ms_iocb_dma); - if (ha->ms_iocb == NULL) { - /* error */ - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - ms_iocb\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - memset(ha->ms_iocb, 0, sizeof(ms_iocb_entry_t)); - - /* - * Get consistent memory allocated for CT SNS - * commands - */ - ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev, - sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, - GFP_KERNEL); - if (ha->ct_sns == NULL) { - /* error */ - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - ct_sns\n"); - qla2x00_mem_free(ha); - msleep(100); + ha->request_ring = dma_alloc_coherent(&ha->pdev->dev, + (ha->request_q_length + 1) * sizeof(request_t), &ha->request_dma, + GFP_KERNEL); + if (!ha->request_ring) + goto fail; + + ha->response_ring = dma_alloc_coherent(&ha->pdev->dev, + (ha->response_q_length + 1) * sizeof(response_t), + &ha->response_dma, GFP_KERNEL); + if (!ha->response_ring) + goto fail_free_request_ring; + + ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE, + &ha->gid_list_dma, GFP_KERNEL); + if (!ha->gid_list) + goto fail_free_response_ring; + + ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size, + &ha->init_cb_dma, GFP_KERNEL); + if (!ha->init_cb) + goto fail_free_gid_list; + + snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, + ha->host_no); + ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, + DMA_POOL_SIZE, 8, 0); + if (!ha->s_dma_pool) + goto fail_free_init_cb; - continue; - } - memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt)); - - if (IS_FWI2_CAPABLE(ha)) { - /* - * Get consistent memory allocated for SFP - * block. - */ - ha->sfp_data = dma_pool_alloc(ha->s_dma_pool, - GFP_KERNEL, &ha->sfp_data_dma); - if (ha->sfp_data == NULL) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - " - "sfp_data\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - memset(ha->sfp_data, 0, SFP_BLOCK_SIZE); - } - } - - /* Get memory for cached NVRAM */ - ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL); - if (ha->nvram == NULL) { - /* error */ - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - nvram cache\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - - /* Done all allocations without any error. */ - status = 0; - - } while (retry-- && status != 0); + ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep); + if (!ha->srb_mempool) + goto fail_free_s_dma_pool; - if (status) { - printk(KERN_WARNING - "%s(): **** FAILED ****\n", __func__); + /* Get memory for cached NVRAM */ + ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL); + if (!ha->nvram) + goto fail_free_srb_mempool; + + /* Allocate memory for SNS commands */ + if (IS_QLA2100(ha) || IS_QLA2200(ha)) { + /* Get consistent memory allocated for SNS commands */ + ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL); + if (!ha->sns_cmd) + goto fail_free_nvram; + } else { + /* Get consistent memory allocated for MS IOCB */ + ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, + &ha->ms_iocb_dma); + if (!ha->ms_iocb) + goto fail_free_nvram; + + /* Get consistent memory allocated for CT SNS commands */ + ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL); + if (!ha->ct_sns) + goto fail_free_ms_iocb; } - return(status); + return 0; + +fail_free_ms_iocb: + dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); + ha->ms_iocb = NULL; + ha->ms_iocb_dma = 0; +fail_free_nvram: + kfree(ha->nvram); + ha->nvram = NULL; +fail_free_srb_mempool: + mempool_destroy(ha->srb_mempool); + ha->srb_mempool = NULL; +fail_free_s_dma_pool: + dma_pool_destroy(ha->s_dma_pool); + ha->s_dma_pool = NULL; +fail_free_init_cb: + dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb, + ha->init_cb_dma); + ha->init_cb = NULL; + ha->init_cb_dma = 0; +fail_free_gid_list: + dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, + ha->gid_list_dma); + ha->gid_list = NULL; + ha->gid_list_dma = 0; +fail_free_response_ring: + dma_free_coherent(&ha->pdev->dev, (ha->response_q_length + 1) * + sizeof(response_t), ha->response_ring, ha->response_dma); + ha->response_ring = NULL; + ha->response_dma = 0; +fail_free_request_ring: + dma_free_coherent(&ha->pdev->dev, (ha->request_q_length + 1) * + sizeof(request_t), ha->request_ring, ha->request_dma); + ha->request_ring = NULL; + ha->request_dma = 0; +fail: + return -ENOMEM; } /* @@ -2215,14 +2118,8 @@ qla2x00_mem_free(scsi_qla_host_t *ha) struct list_head *fcpl, *fcptemp; fc_port_t *fcport; - if (ha == NULL) { - /* error */ - DEBUG2(printk("%s(): ERROR invalid ha pointer.\n", __func__)); - return; - } - - /* free sp pool */ - qla2x00_free_sp_pool(ha); + if (ha->srb_mempool) + mempool_destroy(ha->srb_mempool); if (ha->fce) dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce, @@ -2270,6 +2167,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha) (ha->request_q_length + 1) * sizeof(request_t), ha->request_ring, ha->request_dma); + ha->srb_mempool = NULL; ha->eft = NULL; ha->eft_dma = 0; ha->sns_cmd = NULL; @@ -2308,44 +2206,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) kfree(ha->nvram); } -/* - * qla2x00_allocate_sp_pool - * This routine is called during initialization to allocate - * memory for local srb_t. - * - * Input: - * ha = adapter block pointer. - * - * Context: - * Kernel context. - */ -static int -qla2x00_allocate_sp_pool(scsi_qla_host_t *ha) -{ - int rval; - - rval = QLA_SUCCESS; - ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep); - if (ha->srb_mempool == NULL) { - qla_printk(KERN_INFO, ha, "Unable to allocate SRB mempool.\n"); - rval = QLA_FUNCTION_FAILED; - } - return (rval); -} - -/* - * This routine frees all adapter allocated memory. - * - */ -static void -qla2x00_free_sp_pool( scsi_qla_host_t *ha) -{ - if (ha->srb_mempool) { - mempool_destroy(ha->srb_mempool); - ha->srb_mempool = NULL; - } -} - /************************************************************************** * qla2x00_do_dpc * This kernel thread is a task that is schedule by the interrupt handler @@ -2367,6 +2227,9 @@ qla2x00_do_dpc(void *data) fc_port_t *fcport; uint8_t status; uint16_t next_loopid; + struct scsi_qla_host *vha; + int i; + ha = (scsi_qla_host_t *)data; @@ -2409,6 +2272,18 @@ qla2x00_do_dpc(void *data) } clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); } + + for_each_mapped_vp_idx(ha, i) { + list_for_each_entry(vha, &ha->vp_list, + vp_list) { + if (i == vha->vp_idx) { + set_bit(ISP_ABORT_NEEDED, + &vha->dpc_flags); + break; + } + } + } + DEBUG(printk("scsi(%ld): dpc: qla2x00_abort_isp end\n", ha->host_no)); } @@ -3029,3 +2904,4 @@ MODULE_FIRMWARE(FW_FILE_ISP22XX); MODULE_FIRMWARE(FW_FILE_ISP2300); MODULE_FIRMWARE(FW_FILE_ISP2322); MODULE_FIRMWARE(FW_FILE_ISP24XX); +MODULE_FIRMWARE(FW_FILE_ISP25XX); diff -puN drivers/scsi/qla2xxx/qla_sup.c~git-scsi-misc drivers/scsi/qla2xxx/qla_sup.c --- a/drivers/scsi/qla2xxx/qla_sup.c~git-scsi-misc +++ a/drivers/scsi/qla2xxx/qla_sup.c @@ -893,6 +893,8 @@ qla2x00_flip_colors(scsi_qla_host_t *ha, } } +#define PIO_REG(h, r) ((h)->pio_address + offsetof(struct device_reg_2xxx, r)) + void qla2x00_beacon_blink(struct scsi_qla_host *ha) { @@ -902,15 +904,12 @@ qla2x00_beacon_blink(struct scsi_qla_hos unsigned long flags; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - if (ha->pio_address) - reg = (struct device_reg_2xxx __iomem *)ha->pio_address; - spin_lock_irqsave(&ha->hardware_lock, flags); /* Save the Original GPIOE. */ if (ha->pio_address) { - gpio_enable = RD_REG_WORD_PIO(®->gpioe); - gpio_data = RD_REG_WORD_PIO(®->gpiod); + gpio_enable = RD_REG_WORD_PIO(PIO_REG(ha, gpioe)); + gpio_data = RD_REG_WORD_PIO(PIO_REG(ha, gpiod)); } else { gpio_enable = RD_REG_WORD(®->gpioe); gpio_data = RD_REG_WORD(®->gpiod); @@ -920,7 +919,7 @@ qla2x00_beacon_blink(struct scsi_qla_hos gpio_enable |= GPIO_LED_MASK; if (ha->pio_address) { - WRT_REG_WORD_PIO(®->gpioe, gpio_enable); + WRT_REG_WORD_PIO(PIO_REG(ha, gpioe), gpio_enable); } else { WRT_REG_WORD(®->gpioe, gpio_enable); RD_REG_WORD(®->gpioe); @@ -936,7 +935,7 @@ qla2x00_beacon_blink(struct scsi_qla_hos /* Set the modified gpio_data values */ if (ha->pio_address) { - WRT_REG_WORD_PIO(®->gpiod, gpio_data); + WRT_REG_WORD_PIO(PIO_REG(ha, gpiod), gpio_data); } else { WRT_REG_WORD(®->gpiod, gpio_data); RD_REG_WORD(®->gpiod); @@ -962,14 +961,11 @@ qla2x00_beacon_on(struct scsi_qla_host * return QLA_FUNCTION_FAILED; } - if (ha->pio_address) - reg = (struct device_reg_2xxx __iomem *)ha->pio_address; - /* Turn off LEDs. */ spin_lock_irqsave(&ha->hardware_lock, flags); if (ha->pio_address) { - gpio_enable = RD_REG_WORD_PIO(®->gpioe); - gpio_data = RD_REG_WORD_PIO(®->gpiod); + gpio_enable = RD_REG_WORD_PIO(PIO_REG(ha, gpioe)); + gpio_data = RD_REG_WORD_PIO(PIO_REG(ha, gpiod)); } else { gpio_enable = RD_REG_WORD(®->gpioe); gpio_data = RD_REG_WORD(®->gpiod); @@ -978,7 +974,7 @@ qla2x00_beacon_on(struct scsi_qla_host * /* Set the modified gpio_enable values. */ if (ha->pio_address) { - WRT_REG_WORD_PIO(®->gpioe, gpio_enable); + WRT_REG_WORD_PIO(PIO_REG(ha, gpioe), gpio_enable); } else { WRT_REG_WORD(®->gpioe, gpio_enable); RD_REG_WORD(®->gpioe); @@ -987,7 +983,7 @@ qla2x00_beacon_on(struct scsi_qla_host * /* Clear out previously set LED colour. */ gpio_data &= ~GPIO_LED_MASK; if (ha->pio_address) { - WRT_REG_WORD_PIO(®->gpiod, gpio_data); + WRT_REG_WORD_PIO(PIO_REG(ha, gpiod), gpio_data); } else { WRT_REG_WORD(®->gpiod, gpio_data); RD_REG_WORD(®->gpiod); @@ -1244,13 +1240,12 @@ qla2x00_read_flash_byte(scsi_qla_host_t if (ha->pio_address) { uint16_t data2; - reg = (struct device_reg_2xxx __iomem *)ha->pio_address; - WRT_REG_WORD_PIO(®->flash_address, (uint16_t)addr); + WRT_REG_WORD_PIO(PIO_REG(ha, flash_address), (uint16_t)addr); do { - data = RD_REG_WORD_PIO(®->flash_data); + data = RD_REG_WORD_PIO(PIO_REG(ha, flash_data)); barrier(); cpu_relax(); - data2 = RD_REG_WORD_PIO(®->flash_data); + data2 = RD_REG_WORD_PIO(PIO_REG(ha, flash_data)); } while (data != data2); } else { WRT_REG_WORD(®->flash_address, (uint16_t)addr); @@ -1304,9 +1299,8 @@ qla2x00_write_flash_byte(scsi_qla_host_t /* Always perform IO mapped accesses to the FLASH registers. */ if (ha->pio_address) { - reg = (struct device_reg_2xxx __iomem *)ha->pio_address; - WRT_REG_WORD_PIO(®->flash_address, (uint16_t)addr); - WRT_REG_WORD_PIO(®->flash_data, (uint16_t)data); + WRT_REG_WORD_PIO(PIO_REG(ha, flash_address), (uint16_t)addr); + WRT_REG_WORD_PIO(PIO_REG(ha, flash_data), (uint16_t)data); } else { WRT_REG_WORD(®->flash_address, (uint16_t)addr); RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ diff -puN drivers/scsi/qla2xxx/qla_version.h~git-scsi-misc drivers/scsi/qla2xxx/qla_version.h --- a/drivers/scsi/qla2xxx/qla_version.h~git-scsi-misc +++ a/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.00-k7" +#define QLA2XXX_VERSION "8.02.00-k8" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 diff -puN drivers/scsi/qla4xxx/ql4_init.c~git-scsi-misc drivers/scsi/qla4xxx/ql4_init.c --- a/drivers/scsi/qla4xxx/ql4_init.c~git-scsi-misc +++ a/drivers/scsi/qla4xxx/ql4_init.c @@ -1306,6 +1306,7 @@ int qla4xxx_process_ddb_changed(struct s atomic_set(&ddb_entry->relogin_timer, 0); clear_bit(DF_RELOGIN, &ddb_entry->flags); clear_bit(DF_NO_RELOGIN, &ddb_entry->flags); + iscsi_unblock_session(ddb_entry->sess); iscsi_session_event(ddb_entry->sess, ISCSI_KEVENT_CREATE_SESSION); /* diff -puN drivers/scsi/qla4xxx/ql4_os.c~git-scsi-misc drivers/scsi/qla4xxx/ql4_os.c --- a/drivers/scsi/qla4xxx/ql4_os.c~git-scsi-misc +++ a/drivers/scsi/qla4xxx/ql4_os.c @@ -63,8 +63,6 @@ static int qla4xxx_sess_get_param(struct enum iscsi_param param, char *buf); static int qla4xxx_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf); -static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag); -static int qla4xxx_conn_start(struct iscsi_cls_conn *conn); static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session); /* @@ -91,6 +89,8 @@ static struct scsi_host_template qla4xxx .slave_alloc = qla4xxx_slave_alloc, .slave_destroy = qla4xxx_slave_destroy, + .scan_finished = iscsi_scan_finished, + .this_id = -1, .cmd_per_lun = 3, .use_clustering = ENABLE_CLUSTERING, @@ -116,8 +116,6 @@ static struct iscsi_transport qla4xxx_is .get_conn_param = qla4xxx_conn_get_param, .get_session_param = qla4xxx_sess_get_param, .get_host_param = qla4xxx_host_get_param, - .start_conn = qla4xxx_conn_start, - .stop_conn = qla4xxx_conn_stop, .session_recovery_timedout = qla4xxx_recovery_timedout, }; @@ -128,48 +126,19 @@ static void qla4xxx_recovery_timedout(st struct ddb_entry *ddb_entry = session->dd_data; struct scsi_qla_host *ha = ddb_entry->ha; - DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count of (%d) " - "secs exhausted, marking device DEAD.\n", ha->host_no, - __func__, ddb_entry->fw_ddb_index, - ha->port_down_retry_count)); - - atomic_set(&ddb_entry->state, DDB_STATE_DEAD); - - DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc flags = " - "0x%lx\n", ha->host_no, __func__, ha->dpc_flags)); - queue_work(ha->dpc_thread, &ha->dpc_work); -} - -static int qla4xxx_conn_start(struct iscsi_cls_conn *conn) -{ - struct iscsi_cls_session *session; - struct ddb_entry *ddb_entry; - - session = iscsi_dev_to_session(conn->dev.parent); - ddb_entry = session->dd_data; - - DEBUG2(printk("scsi%ld: %s: index [%d] starting conn\n", - ddb_entry->ha->host_no, __func__, - ddb_entry->fw_ddb_index)); - iscsi_unblock_session(session); - return 0; -} - -static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag) -{ - struct iscsi_cls_session *session; - struct ddb_entry *ddb_entry; + if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { + atomic_set(&ddb_entry->state, DDB_STATE_DEAD); - session = iscsi_dev_to_session(conn->dev.parent); - ddb_entry = session->dd_data; + DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count " + "of (%d) secs exhausted, marking device DEAD.\n", + ha->host_no, __func__, ddb_entry->fw_ddb_index, + ha->port_down_retry_count)); - DEBUG2(printk("scsi%ld: %s: index [%d] stopping conn\n", - ddb_entry->ha->host_no, __func__, - ddb_entry->fw_ddb_index)); - if (flag == STOP_CONN_RECOVER) - iscsi_block_session(session); - else - printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag); + DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc " + "flags = 0x%lx\n", + ha->host_no, __func__, ha->dpc_flags)); + queue_work(ha->dpc_thread, &ha->dpc_work); + } } static int qla4xxx_host_get_param(struct Scsi_Host *shost, @@ -308,6 +277,9 @@ int qla4xxx_add_sess(struct ddb_entry *d DEBUG2(printk(KERN_ERR "Could not add connection.\n")); return -ENOMEM; } + + /* finally ready to go */ + iscsi_unblock_session(ddb_entry->sess); return 0; } @@ -364,6 +336,7 @@ void qla4xxx_mark_device_missing(struct DEBUG3(printk("scsi%d:%d:%d: index [%d] marked MISSING\n", ha->host_no, ddb_entry->bus, ddb_entry->target, ddb_entry->fw_ddb_index)); + iscsi_block_session(ddb_entry->sess); iscsi_conn_error(ddb_entry->conn, ISCSI_ERR_CONN_FAILED); } @@ -430,9 +403,21 @@ static int qla4xxx_queuecommand(struct s { struct scsi_qla_host *ha = to_qla_host(cmd->device->host); struct ddb_entry *ddb_entry = cmd->device->hostdata; + struct iscsi_cls_session *sess = ddb_entry->sess; struct srb *srb; int rval; + if (!sess) { + cmd->result = DID_IMM_RETRY << 16; + goto qc_fail_command; + } + + rval = iscsi_session_chkready(sess); + if (rval) { + cmd->result = rval; + goto qc_fail_command; + } + if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { if (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) { cmd->result = DID_NO_CONNECT << 16; @@ -1323,7 +1308,7 @@ static int __devinit qla4xxx_probe_adapt qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev), ha->host_no, ha->firmware_version[0], ha->firmware_version[1], ha->patch_number, ha->build_number); - + scsi_scan_host(host); return 0; remove_host: diff -puN drivers/scsi/scsi_transport_iscsi.c~git-scsi-misc drivers/scsi/scsi_transport_iscsi.c --- a/drivers/scsi/scsi_transport_iscsi.c~git-scsi-misc +++ a/drivers/scsi/scsi_transport_iscsi.c @@ -30,10 +30,10 @@ #include #include -#define ISCSI_SESSION_ATTRS 18 -#define ISCSI_CONN_ATTRS 11 +#define ISCSI_SESSION_ATTRS 19 +#define ISCSI_CONN_ATTRS 13 #define ISCSI_HOST_ATTRS 4 -#define ISCSI_TRANSPORT_VERSION "2.0-867" +#define ISCSI_TRANSPORT_VERSION "2.0-868" struct iscsi_internal { int daemon_pid; @@ -127,12 +127,13 @@ static int iscsi_setup_host(struct trans memset(ihost, 0, sizeof(*ihost)); INIT_LIST_HEAD(&ihost->sessions); mutex_init(&ihost->mutex); + atomic_set(&ihost->nr_scans, 0); - snprintf(ihost->unbind_workq_name, KOBJ_NAME_LEN, "iscsi_unbind_%d", + snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d", shost->host_no); - ihost->unbind_workq = create_singlethread_workqueue( - ihost->unbind_workq_name); - if (!ihost->unbind_workq) + ihost->scan_workq = create_singlethread_workqueue( + ihost->scan_workq_name); + if (!ihost->scan_workq) return -ENOMEM; return 0; } @@ -143,7 +144,7 @@ static int iscsi_remove_host(struct tran struct Scsi_Host *shost = dev_to_shost(dev); struct iscsi_host *ihost = shost->shost_data; - destroy_workqueue(ihost->unbind_workq); + destroy_workqueue(ihost->scan_workq); return 0; } @@ -221,6 +222,54 @@ static struct iscsi_cls_conn *iscsi_conn * The following functions can be used by LLDs that allocate * their own scsi_hosts or by software iscsi LLDs */ +static struct { + int value; + char *name; +} iscsi_session_state_names[] = { + { ISCSI_SESSION_LOGGED_IN, "LOGGED_IN" }, + { ISCSI_SESSION_FAILED, "FAILED" }, + { ISCSI_SESSION_FREE, "FREE" }, +}; + +const char *iscsi_session_state_name(int state) +{ + int i; + char *name = NULL; + + for (i = 0; i < ARRAY_SIZE(iscsi_session_state_names); i++) { + if (iscsi_session_state_names[i].value == state) { + name = iscsi_session_state_names[i].name; + break; + } + } + return name; +} + +int iscsi_session_chkready(struct iscsi_cls_session *session) +{ + unsigned long flags; + int err; + + spin_lock_irqsave(&session->lock, flags); + switch (session->state) { + case ISCSI_SESSION_LOGGED_IN: + err = 0; + break; + case ISCSI_SESSION_FAILED: + err = DID_IMM_RETRY << 16; + break; + case ISCSI_SESSION_FREE: + err = DID_NO_CONNECT << 16; + break; + default: + err = DID_NO_CONNECT << 16; + break; + } + spin_unlock_irqrestore(&session->lock, flags); + return err; +} +EXPORT_SYMBOL_GPL(iscsi_session_chkready); + static void iscsi_session_release(struct device *dev) { struct iscsi_cls_session *session = iscsi_dev_to_session(dev); @@ -236,6 +285,25 @@ static int iscsi_is_session_dev(const st return dev->release == iscsi_session_release; } +/** + * iscsi_scan_finished - helper to report when running scans are done + * @shost: scsi host + * @time: scan run time + * + * This function can be used by drives like qla4xxx to report to the scsi + * layer when the scans it kicked off at module load time are done. + */ +int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time) +{ + struct iscsi_host *ihost = shost->shost_data; + /* + * qla4xxx will have kicked off some session unblocks before calling + * scsi_scan_host, so just wait for them to complete. + */ + return !atomic_read(&ihost->nr_scans); +} +EXPORT_SYMBOL_GPL(iscsi_scan_finished); + static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, uint id, uint lun) { @@ -254,14 +322,50 @@ static int iscsi_user_scan(struct Scsi_H return 0; } +static void iscsi_scan_session(struct work_struct *work) +{ + struct iscsi_cls_session *session = + container_of(work, struct iscsi_cls_session, scan_work); + struct Scsi_Host *shost = iscsi_session_to_shost(session); + struct iscsi_host *ihost = shost->shost_data; + unsigned long flags; + + spin_lock_irqsave(&session->lock, flags); + if (session->state != ISCSI_SESSION_LOGGED_IN) { + spin_unlock_irqrestore(&session->lock, flags); + goto done; + } + spin_unlock_irqrestore(&session->lock, flags); + + scsi_scan_target(&session->dev, 0, session->target_id, + SCAN_WILD_CARD, 1); +done: + atomic_dec(&ihost->nr_scans); +} + static void session_recovery_timedout(struct work_struct *work) { struct iscsi_cls_session *session = container_of(work, struct iscsi_cls_session, recovery_work.work); + unsigned long flags; - dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " - "out after %d secs\n", session->recovery_tmo); + iscsi_cls_session_printk(KERN_INFO, session, + "session recovery timed out after %d secs\n", + session->recovery_tmo); + + spin_lock_irqsave(&session->lock, flags); + switch (session->state) { + case ISCSI_SESSION_FAILED: + session->state = ISCSI_SESSION_FREE; + break; + case ISCSI_SESSION_LOGGED_IN: + case ISCSI_SESSION_FREE: + /* we raced with the unblock's flush */ + spin_unlock_irqrestore(&session->lock, flags); + return; + } + spin_unlock_irqrestore(&session->lock, flags); if (session->transport->session_recovery_timedout) session->transport->session_recovery_timedout(session); @@ -269,16 +373,44 @@ static void session_recovery_timedout(st scsi_target_unblock(&session->dev); } -void iscsi_unblock_session(struct iscsi_cls_session *session) +void __iscsi_unblock_session(struct iscsi_cls_session *session) { if (!cancel_delayed_work(&session->recovery_work)) flush_workqueue(iscsi_eh_timer_workq); scsi_target_unblock(&session->dev); } + +void iscsi_unblock_session(struct iscsi_cls_session *session) +{ + struct Scsi_Host *shost = iscsi_session_to_shost(session); + struct iscsi_host *ihost = shost->shost_data; + unsigned long flags; + + spin_lock_irqsave(&session->lock, flags); + session->state = ISCSI_SESSION_LOGGED_IN; + spin_unlock_irqrestore(&session->lock, flags); + + __iscsi_unblock_session(session); + /* + * Only do kernel scanning if the driver is properly hooked into + * the async scanning code (drivers like iscsi_tcp do login and + * scanning from userspace). + */ + if (shost->hostt->scan_finished) { + if (queue_work(ihost->scan_workq, &session->scan_work)) + atomic_inc(&ihost->nr_scans); + } +} EXPORT_SYMBOL_GPL(iscsi_unblock_session); void iscsi_block_session(struct iscsi_cls_session *session) { + unsigned long flags; + + spin_lock_irqsave(&session->lock, flags); + session->state = ISCSI_SESSION_FAILED; + spin_unlock_irqrestore(&session->lock, flags); + scsi_target_block(&session->dev); queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work, session->recovery_tmo * HZ); @@ -311,7 +443,7 @@ static int iscsi_unbind_session(struct i struct Scsi_Host *shost = iscsi_session_to_shost(session); struct iscsi_host *ihost = shost->shost_data; - return queue_work(ihost->unbind_workq, &session->unbind_work); + return queue_work(ihost->scan_workq, &session->unbind_work); } struct iscsi_cls_session * @@ -327,10 +459,13 @@ iscsi_alloc_session(struct Scsi_Host *sh session->transport = transport; session->recovery_tmo = 120; + session->state = ISCSI_SESSION_FREE; INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); INIT_LIST_HEAD(&session->host_list); INIT_LIST_HEAD(&session->sess_list); INIT_WORK(&session->unbind_work, __iscsi_unbind_session); + INIT_WORK(&session->scan_work, iscsi_scan_session); + spin_lock_init(&session->lock); /* this is released in the dev's release function */ scsi_host_get(shost); @@ -358,8 +493,8 @@ int iscsi_add_session(struct iscsi_cls_s session->sid); err = device_add(&session->dev); if (err) { - dev_printk(KERN_ERR, &session->dev, "iscsi: could not " - "register session's dev\n"); + iscsi_cls_session_printk(KERN_ERR, session, + "could not register session's dev\n"); goto release_host; } transport_register_device(&session->dev); @@ -444,22 +579,28 @@ void iscsi_remove_session(struct iscsi_c * If we are blocked let commands flow again. The lld or iscsi * layer should set up the queuecommand to fail commands. */ - iscsi_unblock_session(session); - iscsi_unbind_session(session); + spin_lock_irqsave(&session->lock, flags); + session->state = ISCSI_SESSION_FREE; + spin_unlock_irqrestore(&session->lock, flags); + __iscsi_unblock_session(session); + __iscsi_unbind_session(&session->unbind_work); + + /* flush running scans */ + flush_workqueue(ihost->scan_workq); /* * If the session dropped while removing devices then we need to make * sure it is not blocked */ if (!cancel_delayed_work(&session->recovery_work)) flush_workqueue(iscsi_eh_timer_workq); - flush_workqueue(ihost->unbind_workq); /* hw iscsi may not have removed all connections from session */ err = device_for_each_child(&session->dev, NULL, iscsi_iter_destroy_conn_fn); if (err) - dev_printk(KERN_ERR, &session->dev, "iscsi: Could not delete " - "all connections for session. Error %d.\n", err); + iscsi_cls_session_printk(KERN_ERR, session, + "Could not delete all connections " + "for session. Error %d.\n", err); transport_unregister_device(&session->dev); device_del(&session->dev); @@ -531,8 +672,8 @@ iscsi_create_conn(struct iscsi_cls_sessi conn->dev.release = iscsi_conn_release; err = device_register(&conn->dev); if (err) { - dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register " - "connection's dev\n"); + iscsi_cls_session_printk(KERN_ERR, session, "could not " + "register connection's dev\n"); goto release_parent_ref; } transport_register_device(&conn->dev); @@ -639,8 +780,8 @@ int iscsi_recv_pdu(struct iscsi_cls_conn skb = alloc_skb(len, GFP_ATOMIC); if (!skb) { iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED); - dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver " - "control PDU: OOM\n"); + iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver " + "control PDU: OOM\n"); return -ENOMEM; } @@ -661,20 +802,27 @@ EXPORT_SYMBOL_GPL(iscsi_recv_pdu); void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) { + struct iscsi_cls_session *session = iscsi_conn_to_session(conn); struct nlmsghdr *nlh; struct sk_buff *skb; struct iscsi_uevent *ev; struct iscsi_internal *priv; int len = NLMSG_SPACE(sizeof(*ev)); + unsigned long flags; priv = iscsi_if_transport_lookup(conn->transport); if (!priv) return; + spin_lock_irqsave(&session->lock, flags); + if (session->state == ISCSI_SESSION_LOGGED_IN) + session->state = ISCSI_SESSION_FAILED; + spin_unlock_irqrestore(&session->lock, flags); + skb = alloc_skb(len, GFP_ATOMIC); if (!skb) { - dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored " - "conn error (%d)\n", error); + iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored " + "conn error (%d)\n", error); return; } @@ -688,8 +836,8 @@ void iscsi_conn_error(struct iscsi_cls_c iscsi_broadcast_skb(skb, GFP_ATOMIC); - dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", - error); + iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n", + error); } EXPORT_SYMBOL_GPL(iscsi_conn_error); @@ -744,8 +892,8 @@ iscsi_if_get_stats(struct iscsi_transpor skbstat = alloc_skb(len, GFP_ATOMIC); if (!skbstat) { - dev_printk(KERN_ERR, &conn->dev, "iscsi: can not " - "deliver stats: OOM\n"); + iscsi_cls_conn_printk(KERN_ERR, conn, "can not " + "deliver stats: OOM\n"); return -ENOMEM; } @@ -801,8 +949,9 @@ int iscsi_session_event(struct iscsi_cls skb = alloc_skb(len, GFP_KERNEL); if (!skb) { - dev_printk(KERN_ERR, &session->dev, "Cannot notify userspace " - "of session event %u\n", event); + iscsi_cls_session_printk(KERN_ERR, session, + "Cannot notify userspace of session " + "event %u\n", event); return -ENOMEM; } @@ -825,8 +974,8 @@ int iscsi_session_event(struct iscsi_cls ev->r.unbind_session.sid = session->sid; break; default: - dev_printk(KERN_ERR, &session->dev, "Invalid event %u.\n", - event); + iscsi_cls_session_printk(KERN_ERR, session, "Invalid event " + "%u.\n", event); kfree_skb(skb); return -EINVAL; } @@ -837,8 +986,10 @@ int iscsi_session_event(struct iscsi_cls */ rc = iscsi_broadcast_skb(skb, GFP_KERNEL); if (rc < 0) - dev_printk(KERN_ERR, &session->dev, "Cannot notify userspace " - "of session event %u. Check iscsi daemon\n", event); + iscsi_cls_session_printk(KERN_ERR, session, + "Cannot notify userspace of session " + "event %u. Check iscsi daemon\n", + event); return rc; } EXPORT_SYMBOL_GPL(iscsi_session_event); @@ -871,16 +1022,15 @@ iscsi_if_create_conn(struct iscsi_transp session = iscsi_session_lookup(ev->u.c_conn.sid); if (!session) { - printk(KERN_ERR "iscsi: invalid session %d\n", + printk(KERN_ERR "iscsi: invalid session %d.\n", ev->u.c_conn.sid); return -EINVAL; } conn = transport->create_conn(session, ev->u.c_conn.cid); if (!conn) { - printk(KERN_ERR "iscsi: couldn't create a new " - "connection for session %d\n", - session->sid); + iscsi_cls_session_printk(KERN_ERR, session, + "couldn't create a new connection."); return -ENOMEM; } @@ -1246,6 +1396,15 @@ iscsi_session_attr(fast_abort, ISCSI_PAR iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0); iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0); +static ssize_t +show_priv_session_state(struct class_device *cdev, char *buf) +{ + struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); + return sprintf(buf, "%s\n", iscsi_session_state_name(session->state)); +} +static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state, + NULL); + #define iscsi_priv_session_attr_show(field, format) \ static ssize_t \ show_priv_session_##field(struct class_device *cdev, char *buf) \ @@ -1472,6 +1631,7 @@ iscsi_register_transport(struct iscsi_tr SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO); SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO); SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); + SETUP_PRIV_SESSION_RD_ATTR(state); BUG_ON(count > ISCSI_SESSION_ATTRS); priv->session_attrs[count] = NULL; diff -puN drivers/scsi/sd.c~git-scsi-misc drivers/scsi/sd.c --- a/drivers/scsi/sd.c~git-scsi-misc +++ a/drivers/scsi/sd.c @@ -929,6 +929,7 @@ static int sd_done(struct scsi_cmnd *SCp unsigned int xfer_size = scsi_bufflen(SCpnt); unsigned int good_bytes = result ? 0 : xfer_size; u64 start_lba = SCpnt->request->sector; + u64 end_lba = SCpnt->request->sector + (xfer_size / 512); u64 bad_lba; struct scsi_sense_hdr sshdr; int sense_valid = 0; @@ -967,26 +968,23 @@ static int sd_done(struct scsi_cmnd *SCp goto out; if (xfer_size <= SCpnt->device->sector_size) goto out; - switch (SCpnt->device->sector_size) { - case 256: + if (SCpnt->device->sector_size < 512) { + /* only legitimate sector_size here is 256 */ start_lba <<= 1; - break; - case 512: - break; - case 1024: - start_lba >>= 1; - break; - case 2048: - start_lba >>= 2; - break; - case 4096: - start_lba >>= 3; - break; - default: - /* Print something here with limiting frequency. */ - goto out; - break; + end_lba <<= 1; + } else { + /* be careful ... don't want any overflows */ + u64 factor = SCpnt->device->sector_size / 512; + do_div(start_lba, factor); + do_div(end_lba, factor); } + + if (bad_lba < start_lba || bad_lba >= end_lba) + /* the bad lba was reported incorrectly, we have + * no idea where the error is + */ + goto out; + /* This computation should always be done in terms of * the resolution of the device's medium. */ diff -puN drivers/scsi/sun3x_esp.c~git-scsi-misc drivers/scsi/sun3x_esp.c --- a/drivers/scsi/sun3x_esp.c~git-scsi-misc +++ a/drivers/scsi/sun3x_esp.c @@ -1,392 +1,316 @@ -/* sun3x_esp.c: EnhancedScsiProcessor Sun3x SCSI driver code. +/* sun3x_esp.c: ESP front-end for Sun3x systems. * - * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) - * - * Based on David S. Miller's esp driver + * Copyright (C) 2007,2008 Thomas Bogendoerfer (tsbogend@alpha.franken.de) */ #include #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include -#include "scsi.h" -#include -#include "NCR53C9x.h" - #include +#include +#include #include -#include - -static void dma_barrier(struct NCR_ESP *esp); -static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); -static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp); -static void dma_drain(struct NCR_ESP *esp); -static void dma_invalidate(struct NCR_ESP *esp); -static void dma_dump_state(struct NCR_ESP *esp); -static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length); -static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length); -static void dma_ints_off(struct NCR_ESP *esp); -static void dma_ints_on(struct NCR_ESP *esp); -static int dma_irq_p(struct NCR_ESP *esp); -static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr); -static int dma_ports_p(struct NCR_ESP *esp); -static void dma_reset(struct NCR_ESP *esp); -static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); -static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp); -static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp); -static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp); -static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp); -static void dma_advance_sg (Scsi_Cmnd *sp); - -/* Detecting ESP chips on the machine. This is the simple and easy - * version. - */ -int sun3x_esp_detect(struct scsi_host_template *tpnt) -{ - struct NCR_ESP *esp; - struct ConfigDev *esp_dev; - - esp_dev = 0; - esp = esp_allocate(tpnt, esp_dev, 0); - /* Do command transfer with DMA */ - esp->do_pio_cmds = 0; - - /* Required functions */ - esp->dma_bytes_sent = &dma_bytes_sent; - esp->dma_can_transfer = &dma_can_transfer; - esp->dma_dump_state = &dma_dump_state; - esp->dma_init_read = &dma_init_read; - esp->dma_init_write = &dma_init_write; - esp->dma_ints_off = &dma_ints_off; - esp->dma_ints_on = &dma_ints_on; - esp->dma_irq_p = &dma_irq_p; - esp->dma_ports_p = &dma_ports_p; - esp->dma_setup = &dma_setup; - - /* Optional functions */ - esp->dma_barrier = &dma_barrier; - esp->dma_invalidate = &dma_invalidate; - esp->dma_drain = &dma_drain; - esp->dma_irq_entry = 0; - esp->dma_irq_exit = 0; - esp->dma_led_on = 0; - esp->dma_led_off = 0; - esp->dma_poll = &dma_poll; - esp->dma_reset = &dma_reset; - - /* virtual DMA functions */ - esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one; - esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl; - esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one; - esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl; - esp->dma_advance_sg = &dma_advance_sg; - - /* SCSI chip speed */ - esp->cfreq = 20000000; - esp->eregs = (struct ESP_regs *)(SUN3X_ESP_BASE); - esp->dregs = (void *)SUN3X_ESP_DMA; - - esp->esp_command = (volatile unsigned char *)dvma_malloc(DVMA_PAGE_SIZE); - esp->esp_command_dvma = dvma_vtob((unsigned long)esp->esp_command); +/* DMA controller reg offsets */ +#define DMA_CSR 0x00UL /* rw DMA control/status register 0x00 */ +#define DMA_ADDR 0x04UL /* rw DMA transfer address register 0x04 */ +#define DMA_COUNT 0x08UL /* rw DMA transfer count register 0x08 */ +#define DMA_TEST 0x0cUL /* rw DMA test/debug register 0x0c */ - esp->irq = 2; - if (request_irq(esp->irq, esp_intr, IRQF_DISABLED, - "SUN3X SCSI", esp->ehost)) { - esp_deallocate(esp); - return 0; - } +#include - esp->scsi_id = 7; - esp->diff = 0; +#include "esp_scsi.h" - esp_initialize(esp); +#define DRV_MODULE_NAME "sun3x_esp" +#define PFX DRV_MODULE_NAME ": " +#define DRV_VERSION "1.000" +#define DRV_MODULE_RELDATE "Nov 1, 2007" + +/* + * m68k always assumes readl/writel operate on little endian + * mmio space; this is wrong at least for Sun3x, so we + * need to workaround this until a proper way is found + */ +#if 0 +#define dma_read32(REG) \ + readl(esp->dma_regs + (REG)) +#define dma_write32(VAL, REG) \ + writel((VAL), esp->dma_regs + (REG)) +#else +#define dma_read32(REG) \ + *(volatile u32 *)(esp->dma_regs + (REG)) +#define dma_write32(VAL, REG) \ + do { *(volatile u32 *)(esp->dma_regs + (REG)) = (VAL); } while (0) +#endif - /* for reasons beyond my knowledge (and which should likely be fixed) - sync mode doesn't work on a 3/80 at 5mhz. but it does at 4. */ - esp->sync_defp = 0x3f; - - printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, - esps_in_use); - esps_running = esps_in_use; - return esps_in_use; -} - -static void dma_do_drain(struct NCR_ESP *esp) -{ - struct sparc_dma_registers *dregs = - (struct sparc_dma_registers *) esp->dregs; - - int count = 500000; - - while((dregs->cond_reg & DMA_PEND_READ) && (--count > 0)) - udelay(1); - - if(!count) { - printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg); - } - - dregs->cond_reg |= DMA_FIFO_STDRAIN; - - count = 500000; - - while((dregs->cond_reg & DMA_FIFO_ISDRAIN) && (--count > 0)) - udelay(1); - - if(!count) { - printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg); - } - -} - -static void dma_barrier(struct NCR_ESP *esp) -{ - struct sparc_dma_registers *dregs = - (struct sparc_dma_registers *) esp->dregs; - int count = 500000; - - while((dregs->cond_reg & DMA_PEND_READ) && (--count > 0)) - udelay(1); - - if(!count) { - printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg); - } - - dregs->cond_reg &= ~(DMA_ENABLE); +static void sun3x_esp_write8(struct esp *esp, u8 val, unsigned long reg) +{ + writeb(val, esp->regs + (reg * 4UL)); } -/* This uses various DMA csr fields and the fifo flags count value to - * determine how many bytes were successfully sent/received by the ESP. - */ -static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) +static u8 sun3x_esp_read8(struct esp *esp, unsigned long reg) { - struct sparc_dma_registers *dregs = - (struct sparc_dma_registers *) esp->dregs; - - int rval = dregs->st_addr - esp->esp_command_dvma; - - return rval - fifo_count; + return readb(esp->regs + (reg * 4UL)); } -static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) +static dma_addr_t sun3x_esp_map_single(struct esp *esp, void *buf, + size_t sz, int dir) { - return sp->SCp.this_residual; + return dma_map_single(esp->dev, buf, sz, dir); } -static void dma_drain(struct NCR_ESP *esp) +static int sun3x_esp_map_sg(struct esp *esp, struct scatterlist *sg, + int num_sg, int dir) { - struct sparc_dma_registers *dregs = - (struct sparc_dma_registers *) esp->dregs; - int count = 500000; - - if(dregs->cond_reg & DMA_FIFO_ISDRAIN) { - dregs->cond_reg |= DMA_FIFO_STDRAIN; - while((dregs->cond_reg & DMA_FIFO_ISDRAIN) && (--count > 0)) - udelay(1); - if(!count) { - printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg); - } - - } + return dma_map_sg(esp->dev, sg, num_sg, dir); } -static void dma_invalidate(struct NCR_ESP *esp) +static void sun3x_esp_unmap_single(struct esp *esp, dma_addr_t addr, + size_t sz, int dir) { - struct sparc_dma_registers *dregs = - (struct sparc_dma_registers *) esp->dregs; - - __u32 tmp; - int count = 500000; - - while(((tmp = dregs->cond_reg) & DMA_PEND_READ) && (--count > 0)) - udelay(1); - - if(!count) { - printk("%s:%d timeout CSR %08lx\n", __FILE__, __LINE__, dregs->cond_reg); - } - - dregs->cond_reg = tmp | DMA_FIFO_INV; - dregs->cond_reg &= ~DMA_FIFO_INV; - + dma_unmap_single(esp->dev, addr, sz, dir); } -static void dma_dump_state(struct NCR_ESP *esp) +static void sun3x_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, + int num_sg, int dir) { - struct sparc_dma_registers *dregs = - (struct sparc_dma_registers *) esp->dregs; - - ESPLOG(("esp%d: dma -- cond_reg<%08lx> addr<%08lx>\n", - esp->esp_id, dregs->cond_reg, dregs->st_addr)); + dma_unmap_sg(esp->dev, sg, num_sg, dir); } -static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length) +static int sun3x_esp_irq_pending(struct esp *esp) { - struct sparc_dma_registers *dregs = - (struct sparc_dma_registers *) esp->dregs; - - dregs->st_addr = vaddress; - dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE); + if (dma_read32(DMA_CSR) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)) + return 1; + return 0; } -static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length) +static void sun3x_esp_reset_dma(struct esp *esp) { - struct sparc_dma_registers *dregs = - (struct sparc_dma_registers *) esp->dregs; + u32 val; - /* Set up the DMA counters */ + val = dma_read32(DMA_CSR); + dma_write32(val | DMA_RST_SCSI, DMA_CSR); + dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); - dregs->st_addr = vaddress; - dregs->cond_reg = ((dregs->cond_reg & ~(DMA_ST_WRITE)) | DMA_ENABLE); + /* Enable interrupts. */ + val = dma_read32(DMA_CSR); + dma_write32(val | DMA_INT_ENAB, DMA_CSR); } -static void dma_ints_off(struct NCR_ESP *esp) +static void sun3x_esp_dma_drain(struct esp *esp) { - DMA_INTSOFF((struct sparc_dma_registers *) esp->dregs); -} + u32 csr; + int lim; -static void dma_ints_on(struct NCR_ESP *esp) -{ - DMA_INTSON((struct sparc_dma_registers *) esp->dregs); -} + csr = dma_read32(DMA_CSR); + if (!(csr & DMA_FIFO_ISDRAIN)) + return; -static int dma_irq_p(struct NCR_ESP *esp) -{ - return DMA_IRQ_P((struct sparc_dma_registers *) esp->dregs); + dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR); + + lim = 1000; + while (dma_read32(DMA_CSR) & DMA_FIFO_ISDRAIN) { + if (--lim == 0) { + printk(KERN_ALERT PFX "esp%d: DMA will not drain!\n", + esp->host->unique_id); + break; + } + udelay(1); + } } -static void dma_poll(struct NCR_ESP *esp, unsigned char *vaddr) +static void sun3x_esp_dma_invalidate(struct esp *esp) { - int count = 50; - dma_do_drain(esp); + u32 val; + int lim; - /* Wait till the first bits settle. */ - while((*(volatile unsigned char *)vaddr == 0xff) && (--count > 0)) + lim = 1000; + while ((val = dma_read32(DMA_CSR)) & DMA_PEND_READ) { + if (--lim == 0) { + printk(KERN_ALERT PFX "esp%d: DMA will not " + "invalidate!\n", esp->host->unique_id); + break; + } udelay(1); - - if(!count) { -// printk("%s:%d timeout expire (data %02x)\n", __FILE__, __LINE__, -// esp_read(esp->eregs->esp_fdata)); - //mach_halt(); - vaddr[0] = esp_read(esp->eregs->esp_fdata); - vaddr[1] = esp_read(esp->eregs->esp_fdata); } -} - -static int dma_ports_p(struct NCR_ESP *esp) -{ - return (((struct sparc_dma_registers *) esp->dregs)->cond_reg - & DMA_INT_ENAB); + val &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB); + val |= DMA_FIFO_INV; + dma_write32(val, DMA_CSR); + val &= ~DMA_FIFO_INV; + dma_write32(val, DMA_CSR); } -/* Resetting various pieces of the ESP scsi driver chipset/buses. */ -static void dma_reset(struct NCR_ESP *esp) +static void sun3x_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, + u32 dma_count, int write, u8 cmd) { - struct sparc_dma_registers *dregs = - (struct sparc_dma_registers *)esp->dregs; + u32 csr; + + BUG_ON(!(cmd & ESP_CMD_DMA)); - /* Punt the DVMA into a known state. */ - dregs->cond_reg |= DMA_RST_SCSI; - dregs->cond_reg &= ~(DMA_RST_SCSI); - DMA_INTSON(dregs); + sun3x_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); + sun3x_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); + csr = dma_read32(DMA_CSR); + csr |= DMA_ENABLE; + if (write) + csr |= DMA_ST_WRITE; + else + csr &= ~DMA_ST_WRITE; + dma_write32(csr, DMA_CSR); + dma_write32(addr, DMA_ADDR); + + scsi_esp_cmd(esp, cmd); } -static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) +static int sun3x_esp_dma_error(struct esp *esp) { - struct sparc_dma_registers *dregs = - (struct sparc_dma_registers *) esp->dregs; - unsigned long nreg = dregs->cond_reg; - -// printk("dma_setup %c addr %08x cnt %08x\n", -// write ? 'W' : 'R', addr, count); + u32 csr = dma_read32(DMA_CSR); - dma_do_drain(esp); + if (csr & DMA_HNDL_ERROR) + return 1; - if(write) - nreg |= DMA_ST_WRITE; - else { - nreg &= ~(DMA_ST_WRITE); - } - - nreg |= DMA_ENABLE; - dregs->cond_reg = nreg; - dregs->st_addr = addr; + return 0; } -static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp) -{ - sp->SCp.have_data_in = dvma_map((unsigned long)sp->SCp.buffer, - sp->SCp.this_residual); - sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in); -} +static const struct esp_driver_ops sun3x_esp_ops = { + .esp_write8 = sun3x_esp_write8, + .esp_read8 = sun3x_esp_read8, + .map_single = sun3x_esp_map_single, + .map_sg = sun3x_esp_map_sg, + .unmap_single = sun3x_esp_unmap_single, + .unmap_sg = sun3x_esp_unmap_sg, + .irq_pending = sun3x_esp_irq_pending, + .reset_dma = sun3x_esp_reset_dma, + .dma_drain = sun3x_esp_dma_drain, + .dma_invalidate = sun3x_esp_dma_invalidate, + .send_dma_cmd = sun3x_esp_send_dma_cmd, + .dma_error = sun3x_esp_dma_error, +}; -static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp) +static int __devinit esp_sun3x_probe(struct platform_device *dev) { - int sz = sp->SCp.buffers_residual; - struct scatterlist *sg = sp->SCp.buffer; + struct scsi_host_template *tpnt = &scsi_esp_template; + struct Scsi_Host *host; + struct esp *esp; + struct resource *res; + int err = -ENOMEM; + + host = scsi_host_alloc(tpnt, sizeof(struct esp)); + if (!host) + goto fail; + + host->max_id = 8; + esp = shost_priv(host); + + esp->host = host; + esp->dev = dev; + esp->ops = &sun3x_esp_ops; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!res && !res->start) + goto fail_unlink; + + esp->regs = ioremap_nocache(res->start, 0x20); + if (!esp->regs) + goto fail_unmap_regs; + + res = platform_get_resource(dev, IORESOURCE_MEM, 1); + if (!res && !res->start) + goto fail_unmap_regs; + + esp->dma_regs = ioremap_nocache(res->start, 0x10); + + esp->command_block = dma_alloc_coherent(esp->dev, 16, + &esp->command_block_dma, + GFP_KERNEL); + if (!esp->command_block) + goto fail_unmap_regs_dma; + + host->irq = platform_get_irq(dev, 0); + err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, + "SUN3X ESP", esp); + if (err < 0) + goto fail_unmap_command_block; - while (sz >= 0) { - sg[sz].dma_address = dvma_map((unsigned long)sg_virt(&sg[sz]), - sg[sz].length); - sz--; - } - sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dma_address); -} + esp->scsi_id = 7; + esp->host->this_id = esp->scsi_id; + esp->scsi_id_mask = (1 << esp->scsi_id); + esp->cfreq = 20000000; -static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp) -{ - dvma_unmap((char *)sp->SCp.have_data_in); -} + dev_set_drvdata(&dev->dev, esp); -static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp) -{ - int sz = sp->use_sg - 1; - struct scatterlist *sg = (struct scatterlist *)sp->request_buffer; - - while(sz >= 0) { - dvma_unmap((char *)sg[sz].dma_address); - sz--; - } -} + err = scsi_esp_register(esp, &dev->dev); + if (err) + goto fail_free_irq; + + return 0; + +fail_free_irq: + free_irq(host->irq, esp); +fail_unmap_command_block: + dma_free_coherent(esp->dev, 16, + esp->command_block, + esp->command_block_dma); +fail_unmap_regs_dma: + iounmap(esp->dma_regs); +fail_unmap_regs: + iounmap(esp->regs); +fail_unlink: + scsi_host_put(host); +fail: + return err; +} + +static int __devexit esp_sun3x_remove(struct platform_device *dev) +{ + struct esp *esp = dev_get_drvdata(&dev->dev); + unsigned int irq = esp->host->irq; + u32 val; + + scsi_esp_unregister(esp); + + /* Disable interrupts. */ + val = dma_read32(DMA_CSR); + dma_write32(val & ~DMA_INT_ENAB, DMA_CSR); + + free_irq(irq, esp); + dma_free_coherent(esp->dev, 16, + esp->command_block, + esp->command_block_dma); + + scsi_host_put(esp->host); + + return 0; +} + +static struct platform_driver esp_sun3x_driver = { + .probe = esp_sun3x_probe, + .remove = __devexit_p(esp_sun3x_remove), + .driver = { + .name = "sun3x_esp", + }, +}; -static void dma_advance_sg (Scsi_Cmnd *sp) +static int __init sun3x_esp_init(void) { - sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dma_address); + return platform_driver_register(&esp_sun3x_driver); } -static int sun3x_esp_release(struct Scsi_Host *instance) +static void __exit sun3x_esp_exit(void) { - /* this code does not support being compiled as a module */ - return 1; - + platform_driver_unregister(&esp_sun3x_driver); } -static struct scsi_host_template driver_template = { - .proc_name = "sun3x_esp", - .proc_info = &esp_proc_info, - .name = "Sun ESP 100/100a/200", - .detect = sun3x_esp_detect, - .release = sun3x_esp_release, - .slave_alloc = esp_slave_alloc, - .slave_destroy = esp_slave_destroy, - .info = esp_info, - .queuecommand = esp_queue, - .eh_abort_handler = esp_abort, - .eh_bus_reset_handler = esp_reset, - .can_queue = 7, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .use_clustering = DISABLE_CLUSTERING, -}; - - -#include "scsi_module.c" - +MODULE_DESCRIPTION("Sun3x ESP SCSI driver"); +MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)"); MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(sun3x_esp_init); +module_exit(sun3x_esp_exit); diff -puN drivers/scsi/sym53c8xx_2/sym_hipd.c~git-scsi-misc drivers/scsi/sym53c8xx_2/sym_hipd.c --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c~git-scsi-misc +++ a/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -3842,7 +3842,7 @@ int sym_compute_residual(struct sym_hcb if (cp->startp == cp->phys.head.lastp || sym_evaluate_dp(np, cp, scr_to_cpu(cp->phys.head.lastp), &dp_ofs) < 0) { - return cp->data_len; + return cp->data_len - cp->odd_byte_adjustment; } /* diff -puN include/scsi/iscsi_proto.h~git-scsi-misc include/scsi/iscsi_proto.h --- a/include/scsi/iscsi_proto.h~git-scsi-misc +++ a/include/scsi/iscsi_proto.h @@ -45,8 +45,8 @@ /* initiator tags; opaque for target */ typedef uint32_t __bitwise__ itt_t; /* below makes sense only for initiator that created this tag */ -#define build_itt(itt, id, age) ((__force itt_t)\ - ((itt) | ((id) << ISCSI_CID_SHIFT) | ((age) << ISCSI_AGE_SHIFT))) +#define build_itt(itt, age) ((__force itt_t)\ + ((itt) | ((age) << ISCSI_AGE_SHIFT))) #define get_itt(itt) ((__force uint32_t)(itt_t)(itt) & ISCSI_ITT_MASK) #define RESERVED_ITT ((__force itt_t)0xffffffff) diff -puN include/scsi/libiscsi.h~git-scsi-misc include/scsi/libiscsi.h --- a/include/scsi/libiscsi.h~git-scsi-misc +++ a/include/scsi/libiscsi.h @@ -70,8 +70,6 @@ enum { #define ISCSI_SUSPEND_BIT 1 #define ISCSI_ITT_MASK (0xfff) -#define ISCSI_CID_SHIFT 12 -#define ISCSI_CID_MASK (0xffff << ISCSI_CID_SHIFT) #define ISCSI_AGE_SHIFT 28 #define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) @@ -135,6 +133,14 @@ static inline void* iscsi_next_hdr(struc return (void*)ctask->hdr + ctask->hdr_len; } +/* Connection's states */ +enum { + ISCSI_CONN_INITIAL_STAGE, + ISCSI_CONN_STARTED, + ISCSI_CONN_STOPPED, + ISCSI_CONN_CLEANUP_WAIT, +}; + struct iscsi_conn { struct iscsi_cls_conn *cls_conn; /* ptr to class connection */ void *dd_data; /* iscsi_transport data */ @@ -227,6 +233,17 @@ struct iscsi_pool { int max; /* Max number of elements */ }; +/* Session's states */ +enum { + ISCSI_STATE_FREE = 1, + ISCSI_STATE_LOGGED_IN, + ISCSI_STATE_FAILED, + ISCSI_STATE_TERMINATE, + ISCSI_STATE_IN_RECOVERY, + ISCSI_STATE_RECOVERY_FAILED, + ISCSI_STATE_LOGGING_OUT, +}; + struct iscsi_session { /* * Syncs up the scsi eh thread with the iscsi eh thread when sending @@ -325,6 +342,10 @@ extern int iscsi_session_get_param(struc #define session_to_cls(_sess) \ hostdata_session(_sess->host->hostdata) +#define iscsi_session_printk(prefix, _sess, fmt, a...) \ + iscsi_cls_session_printk(prefix, \ + (struct iscsi_cls_session *)session_to_cls(_sess), fmt, ##a) + /* * connection management */ @@ -339,6 +360,9 @@ extern void iscsi_conn_failure(struct is extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf); +#define iscsi_conn_printk(prefix, _c, fmt, a...) \ + iscsi_cls_conn_printk(prefix, _c->cls_conn, fmt, ##a) + /* * pdu and task processing */ @@ -349,8 +373,6 @@ extern int iscsi_conn_send_pdu(struct is char *, uint32_t); extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, char *, int); -extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, - char *, int); extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *, uint32_t *); extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask); diff -puN include/scsi/scsi_transport_iscsi.h~git-scsi-misc include/scsi/scsi_transport_iscsi.h --- a/include/scsi/scsi_transport_iscsi.h~git-scsi-misc +++ a/include/scsi/scsi_transport_iscsi.h @@ -149,13 +149,6 @@ extern void iscsi_conn_error(struct iscs extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size); - -/* Connection's states */ -#define ISCSI_CONN_INITIAL_STAGE 0 -#define ISCSI_CONN_STARTED 1 -#define ISCSI_CONN_STOPPED 2 -#define ISCSI_CONN_CLEANUP_WAIT 3 - struct iscsi_cls_conn { struct list_head conn_list; /* item in connlist */ void *dd_data; /* LLD private data */ @@ -169,27 +162,31 @@ struct iscsi_cls_conn { #define iscsi_dev_to_conn(_dev) \ container_of(_dev, struct iscsi_cls_conn, dev) -/* Session's states */ -#define ISCSI_STATE_FREE 1 -#define ISCSI_STATE_LOGGED_IN 2 -#define ISCSI_STATE_FAILED 3 -#define ISCSI_STATE_TERMINATE 4 -#define ISCSI_STATE_IN_RECOVERY 5 -#define ISCSI_STATE_RECOVERY_FAILED 6 -#define ISCSI_STATE_LOGGING_OUT 7 +#define iscsi_conn_to_session(_conn) \ + iscsi_dev_to_session(_conn->dev.parent) + +/* iscsi class session state */ +enum { + ISCSI_SESSION_LOGGED_IN, + ISCSI_SESSION_FAILED, + ISCSI_SESSION_FREE, +}; struct iscsi_cls_session { struct list_head sess_list; /* item in session_list */ struct list_head host_list; struct iscsi_transport *transport; + spinlock_t lock; + struct work_struct scan_work; + struct work_struct unbind_work; /* recovery fields */ int recovery_tmo; struct delayed_work recovery_work; - struct work_struct unbind_work; int target_id; + int state; int sid; /* session id */ void *dd_data; /* LLD private data */ struct device dev; /* sysfs transport/container device */ @@ -206,14 +203,22 @@ struct iscsi_cls_session { struct iscsi_host { struct list_head sessions; + atomic_t nr_scans; struct mutex mutex; - struct workqueue_struct *unbind_workq; - char unbind_workq_name[KOBJ_NAME_LEN]; + struct workqueue_struct *scan_workq; + char scan_workq_name[KOBJ_NAME_LEN]; }; /* * session and connection functions that can be used by HW iSCSI LLDs */ +#define iscsi_cls_session_printk(prefix, _cls_session, fmt, a...) \ + dev_printk(prefix, &(_cls_session)->dev, fmt, ##a) + +#define iscsi_cls_conn_printk(prefix, _cls_conn, fmt, a...) \ + dev_printk(prefix, &(_cls_conn)->dev, fmt, ##a) + +extern int iscsi_session_chkready(struct iscsi_cls_session *session); extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport); extern int iscsi_add_session(struct iscsi_cls_session *session, @@ -231,6 +236,6 @@ extern struct iscsi_cls_conn *iscsi_crea extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); extern void iscsi_unblock_session(struct iscsi_cls_session *session); extern void iscsi_block_session(struct iscsi_cls_session *session); - +extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time); #endif _