GIT a6680f71ca27ea78c4c4e577076aecb9ace476f1 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git commit Author: Christof Schmitt Date: Mon Mar 3 12:19:28 2008 +0100 [SCSI] zfcp: convert zfcp to use target reset and device reset handler [based on proposal from Mike Christie , this patch adds some simplifications to the handler functions] With the new target reset handler callback in the SCSI midlayer, the device reset handler in zfcp can be split in two parts. Now, zfcp does not have to track anymore whether the device supports LUN resets, so remove this flag and let the SCSI midlayer decide what to do. The device reset handler simply issues a LUN reset and the target reset handler a target reset. Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley commit 2ba76ffad6d403ac5d0418251161d606ef884b1d Author: Mike Christie Date: Fri Feb 29 18:25:20 2008 -0600 [SCSI] qla4xxx: Add target reset functionality This patch adds target reset functionalty. Signed-off-by: Mike Christie Acked-by: David Somayajulu Signed-off-by: James Bottomley commit 4c6fa944e6312c6ed05005e767a4b51a724d22be Author: Mike Christie Date: Fri Feb 29 18:25:19 2008 -0600 [SCSI] scsi_error: add target reset handler The problem is that serveral drivers are sending a target reset from the device reset handler, and if we have multiple devices a target reset gets sent for each device when only one would be sufficient. And if we do a target reset it affects all the commands on the target so the device reset handler code only cleaning up one devices's commands makes programming the driver a little more difficult than it should be. This patch adds a target reset handler, which drivers can use to send a target reset. If successful it cleans up the commands for a devices accessed through that starget. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit abb1ae734cac6c7a54a8a560db3bae90c652ec1c Author: Geert Uytterhoeven Date: Mon Feb 25 14:24:31 2008 +0100 [SCSI] ps3rom: Simplify fill_from_dev_buffer() As we no longer need to calculate the data length of the whole scatterlist, we can abort the loop earlier and coalesce req_len and act_len into one variable, making fill_from_dev_buffer() more similar to fetch_to_dev_buffer(). Signed-off-by: Geert Uytterhoeven Signed-off-by: James Bottomley commit b3931a2f35f6fcf55bdc8ca6437cd4aee0013960 Author: FUJITA Tomonori Date: Sun Mar 2 18:30:18 2008 +0900 [SCSI] scsi_debug: use shost_priv macro Signed-off-by: FUJITA Tomonori Acked-by: Douglas Gilbert Signed-off-by: James Bottomley commit e7a260a5f68dec7b0b152314a79248495a21856f Author: FUJITA Tomonori Date: Sun Mar 2 18:30:17 2008 +0900 [SCSI] scsi_debug: remove unnecessary checking Signed-off-by: FUJITA Tomonori Acked-by: Douglas Gilbert Signed-off-by: James Bottomley commit 201a489fc0095cd9ce2d4ce50dd03f27d9397007 Author: FUJITA Tomonori Date: Sun Mar 2 18:30:16 2008 +0900 [SCSI] scsi_debug: remove scsi_debug.h scsi_debug.h just incldues some function declarations. This patch removes it with moving the scsi_host_template. Signed-off-by: FUJITA Tomonori Acked-by: Douglas Gilbert Signed-off-by: James Bottomley commit 34a1cb694b3d0539a1eb9e17ec20bc51a384466e Author: FUJITA Tomonori Date: Sun Mar 2 18:30:15 2008 +0900 [SCSI] scsi_debug: stop including drivers/scsi/scsi.h This converts scsi_debug to include header files in include/scsi/ instead of drivers/scsi/scsi.h. Signed-off-by: FUJITA Tomonori Acked-by: Douglas Gilbert Signed-off-by: James Bottomley commit 667a74e35a3188bc7a50add60be03ae861e1cc1a Author: Andi Kleen Date: Mon Feb 25 00:35:21 2008 +0100 [SCSI] Remove random noop unchecked_isa_dma users Lots of drivers set it to 0. Remove that. Patch should be a nop. Signed-off-by: Andi Kleen Signed-off-by: James Bottomley commit 67786c47deb590b4c4ae12f44a7169fe4eaede33 Author: FUJITA Tomonori Date: Sun Feb 24 15:25:23 2008 -0800 [SCSI] aacraid: READ_CAPACITY_16 shouldn't trust allocation length in cdb When aacraid spoofs READ_CAPACITY_16, it assumes that the data length in the sg list is equal to allocation length in cdb. But sg can put any value in scb so the driver needs to check both the data length in the sg list and allocation length in cdb. If allocation length is larger than the response length that the driver expects, it clears the data buffer in the sg list to zero but it doesn't need to do. Just setting resid is fine. Signed-off-by: FUJITA Tomonori Acked-by: Mark Salyzyn Signed-off-by: James Bottomley commit 0b65635a7b2cb942896655ff1bf277e6fe9f765d Author: Kai Makisara Date: Sun Feb 24 22:29:12 2008 +0200 [SCSI] st: show options currently set in sysfs Show the current binary tape driver and mode options is sysfs. A file (options) is created in each directory in /sys/class/scsi_tape. The files contain masks showing the options. The mask bit definitions are the same as used when setting the options using the MTSETDRVBUFFER function in the MTIOCTOP ioctl (defined in include/linux/mtio.h). For example: > cat /sys/class/scsi_tape/nst0/options 0x00000d07 [jejb: updated doc with correction from Randy Dunlap] Signed-off-by: Kai Makisara Signed-off-by: James Bottomley commit 7991d1943581c96d47797ff80b56c997939bfe6f Author: Kai Makisara Date: Sun Feb 24 22:23:24 2008 +0200 [SCSI] st: add option to use SILI in variable block reads Add new option MT_ST_SILI to enable setting the SILI bit in reads in variable block mode. If SILI is set, reading a block shorter than the byte count does not result in CHECK CONDITION. The length of the block is determined using the residual count from the HBA. Avoiding the REQUEST SENSE command for every block speeds up some real applications considerably. Signed-off-by: Kai Makisara Signed-off-by: James Bottomley commit 1634afd1c87a00ca5871ccea19109b89d35a00e0 Author: Boaz Harrosh Date: Wed Feb 27 15:31:20 2008 -0800 [SCSI] gdth: remove command accessors These are no longer necessary. Signed-off-by: Boaz Harrosh Tested-by: Joerg Dorchain: Tested-by: Stefan Priebe Tested-by: Jon Chelton Signed-off-by: James Bottomley commit 3e4f6a6988dc64f241a155c4abd8b9830bb22dc0 Author: Darrick J. Wong Date: Tue Feb 19 10:50:49 2008 -0800 [SCSI] aic94xx: Use sas_request_addr() to provide SAS WWN if the adapter lacks one If the aic94xx chip doesn't have a SAS address in the chip's flash memory, make libsas get one for us. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley commit 4cfca4e6b8d9dc860049872c97909e07b9ce3292 Author: Darrick J. Wong Date: Tue Feb 19 10:49:40 2008 -0800 [SCSI] libsas: Provide a transport-level facility to request SAS addrs Provide a facility to use the request_firmware() interface to get a SAS address from userspace. This can be used by SAS LLDDs that cannot obtain the address from the host adapter. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley commit 80b17c15c1f9eb4d6fdaebe37a7b9605e3899549 Author: FUJITA Tomonori Date: Tue Feb 19 18:41:30 2008 +0900 [SCSI] ips: sg chaining support to the path to non I/O commands I overlooked ips_scmd_buf_write and ips_scmd_buf_read when I converted ips to use the data buffer accessors. ips is unlikely to use sg chaining (especially in this path) since a) this path is used only for non I/O commands (with little data transfer), b) ips's sg_tablesize is set to just 17. Thanks to Tim Pepper for testing this patch. Signed-off-by: FUJITA Tomonori Acked-by: Mark Salyzyn Signed-off-by: James Bottomley commit 7576e4f8ac3d5b6181f8a7138586f6fd006dad05 Author: Jeff Garzik Date: Fri Feb 15 22:20:09 2008 -0500 [SCSI] gdth: convert to PCI hotplug API - remove PCI device sort, which greatly simplifies PCI probe, permitting direct, per-HBA function calls rather than an indirect route to the same end result. - remove need for pcistr[] Signed-off-by: Jeff Garzik Signed-off-by: James Bottomley commit 654a724d1b1f27326bba06b063a736a525e39aa2 Author: Jeff Garzik Date: Fri Feb 15 21:35:26 2008 -0500 [SCSI] gdth: PCI probe cleanups, prep for PCI hotplug API conversion - Reduce uses of gdth_pci_str::pdev, preferring a local variable (or function arg) 'pdev' instead. - Reduce uses of gdth_pcistr array, preferring local variable (or function arg) 'pcistr' instead. - Eliminate lone use of gdth_pci_str::irq, using equivalent pdev->irq instead - Eliminate assign-only gdth_pci_str::io_mm Note: If the indentation seems weird, that's because a line was converted from spaces to tabs, when it was modified. Signed-off-by: Jeff Garzik Signed-off-by: James Bottomley Documentation/scsi/st.txt | 12 ++- drivers/s390/scsi/zfcp_def.h | 1 - drivers/s390/scsi/zfcp_scsi.c | 64 +++----- drivers/scsi/aacraid/aachba.c | 22 ++-- drivers/scsi/aic94xx/aic94xx.h | 16 -- drivers/scsi/aic94xx/aic94xx_hwi.c | 20 +-- drivers/scsi/aic94xx/aic94xx_init.c | 2 - drivers/scsi/arm/acornscsi.c | 1 - drivers/scsi/arm/cumana_1.c | 1 - drivers/scsi/dc395x.c | 1 - drivers/scsi/eata_pio.c | 2 - drivers/scsi/gdth.c | 320 ++++++++++++++-------------------- drivers/scsi/gdth.h | 2 - drivers/scsi/hptiop.c | 1 - drivers/scsi/ips.c | 19 +- drivers/scsi/libsas/sas_scsi_host.c | 41 +++++ drivers/scsi/mac_scsi.c | 1 - drivers/scsi/ps3rom.c | 30 ++-- drivers/scsi/qla4xxx/ql4_fw.h | 1 + drivers/scsi/qla4xxx/ql4_glbl.h | 2 + drivers/scsi/qla4xxx/ql4_mbx.c | 39 +++++ drivers/scsi/qla4xxx/ql4_os.c | 82 +++++++-- drivers/scsi/scsi_debug.c | 72 ++++---- drivers/scsi/scsi_debug.h | 24 --- drivers/scsi/scsi_error.c | 122 +++++++++++-- drivers/scsi/st.c | 83 +++++++++- drivers/scsi/st.h | 3 + drivers/scsi/st_options.h | 6 +- include/linux/mtio.h | 1 + include/scsi/libsas.h | 2 + include/scsi/scsi_eh.h | 1 + include/scsi/scsi_host.h | 1 + 32 files changed, 585 insertions(+), 410 deletions(-) diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt index b7be95b..4075260 100644 --- a/Documentation/scsi/st.txt +++ b/Documentation/scsi/st.txt @@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver. The driver is currently maintained by Kai Mäkisara (email Kai.Makisara@kolumbus.fi) -Last modified: Mon Mar 7 21:14:44 2005 by kai.makisara +Last modified: Sun Feb 24 21:59:07 2008 by kai.makisara BASICS @@ -133,6 +133,11 @@ the defaults set by the user. The value -1 means the default is not set. The file 'dev' contains the device numbers corresponding to this device. The links 'device' and 'driver' point to the SCSI device and driver entries. +Each directory also contains the entry 'options' which shows the currently +enabled driver and mode options. The value in the file is a bit mask where the +bit definitions are the same as those used with MTSETDRVBUFFER in setting the +options. + A link named 'tape' is made from the SCSI device directory to the class directory corresponding to the mode 0 auto-rewind device (e.g., st0). @@ -372,6 +377,11 @@ MTSETDRVBUFFER MT_ST_SYSV sets the SYSV semantics (mode) MT_ST_NOWAIT enables immediate mode (i.e., don't wait for the command to finish) for some commands (e.g., rewind) + MT_ST_SILI enables setting the SILI bit in SCSI commands when + reading in variable block mode to enhance performance when + reading blocks shorter than the byte count; set this only + if you are sure that the drive supports SILI and the HBA + correctly returns transfer residuals MT_ST_DEBUGGING debugging (global; debugging must be compiled into the driver) MT_ST_SETBOOLEANS diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 9e9f6c1..662c70f 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -634,7 +634,6 @@ do { \ ZFCP_STATUS_PORT_NO_SCSI_ID) /* logical unit status */ -#define ZFCP_STATUS_UNIT_NOTSUPPUNITRESET 0x00000001 #define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002 #define ZFCP_STATUS_UNIT_SHARED 0x00000004 #define ZFCP_STATUS_UNIT_READONLY 0x00000008 diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index b9daf5c..ff97a61 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -31,6 +31,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *, void (*done) (struct scsi_cmnd *)); static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); +static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); static int zfcp_task_management_function(struct zfcp_unit *, u8, struct scsi_cmnd *); @@ -51,6 +52,7 @@ struct zfcp_data zfcp_data = { .queuecommand = zfcp_scsi_queuecommand, .eh_abort_handler = zfcp_scsi_eh_abort_handler, .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, + .eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler, .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, .can_queue = 4096, .this_id = -1, @@ -442,58 +444,32 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) return retval; } -static int -zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) +static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { int retval; - struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; + struct zfcp_unit *unit = scpnt->device->hostdata; if (!unit) { - ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n"); - retval = SUCCESS; - goto out; + WARN_ON(1); + return SUCCESS; } - ZFCP_LOG_NORMAL("resetting unit 0x%016Lx on port 0x%016Lx, adapter %s\n", - unit->fcp_lun, unit->port->wwpn, - zfcp_get_busid_by_adapter(unit->port->adapter)); + retval = zfcp_task_management_function(unit, + FCP_LOGICAL_UNIT_RESET, + scpnt); + return retval ? FAILED : SUCCESS; +} - /* - * If we do not know whether the unit supports 'logical unit reset' - * then try 'logical unit reset' and proceed with 'target reset' - * if 'logical unit reset' fails. - * If the unit is known not to support 'logical unit reset' then - * skip 'logical unit reset' and try 'target reset' immediately. - */ - if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, - &unit->status)) { - retval = zfcp_task_management_function(unit, - FCP_LOGICAL_UNIT_RESET, - scpnt); - if (retval) { - ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit); - if (retval == -ENOTSUPP) - atomic_set_mask - (ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, - &unit->status); - /* fall through and try 'target reset' next */ - } else { - ZFCP_LOG_DEBUG("unit reset succeeded (unit=%p)\n", - unit); - /* avoid 'target reset' */ - retval = SUCCESS; - goto out; - } +static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) +{ + int retval; + struct zfcp_unit *unit = scpnt->device->hostdata; + + if (!unit) { + WARN_ON(1); + return SUCCESS; } retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt); - if (retval) { - ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit); - retval = FAILED; - } else { - ZFCP_LOG_DEBUG("target reset succeeded (unit=%p)\n", unit); - retval = SUCCESS; - } - out: - return retval; + return retval ? FAILED : SUCCESS; } static int diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index c05092f..b9fc9b1 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -2047,6 +2047,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) { u64 capacity; char cp[13]; + unsigned int alloc_len; dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n")); capacity = fsa_dev_ptr[cid].size - 1; @@ -2063,18 +2064,17 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) cp[10] = 2; cp[11] = 0; cp[12] = 0; - aac_internal_transfer(scsicmd, cp, 0, - min_t(size_t, scsicmd->cmnd[13], sizeof(cp))); - if (sizeof(cp) < scsicmd->cmnd[13]) { - unsigned int len, offset = sizeof(cp); - memset(cp, 0, offset); - do { - len = min_t(size_t, scsicmd->cmnd[13] - offset, - sizeof(cp)); - aac_internal_transfer(scsicmd, cp, offset, len); - } while ((offset += len) < scsicmd->cmnd[13]); - } + alloc_len = ((scsicmd->cmnd[10] << 24) + + (scsicmd->cmnd[11] << 16) + + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]); + + alloc_len = min_t(size_t, alloc_len, sizeof(cp)); + aac_internal_transfer(scsicmd, cp, 0, alloc_len); + + if (alloc_len < scsi_bufflen(scsicmd)) + scsi_set_resid(scsicmd, + scsi_bufflen(scsicmd) - alloc_len); /* Do not cache partition table for arrays */ scsicmd->device->removable = 1; diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h index eb8efdc..2ef459e 100644 --- a/drivers/scsi/aic94xx/aic94xx.h +++ b/drivers/scsi/aic94xx/aic94xx.h @@ -58,7 +58,6 @@ extern struct kmem_cache *asd_dma_token_cache; extern struct kmem_cache *asd_ascb_cache; -extern char sas_addr_str[2*SAS_ADDR_SIZE + 1]; static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr) { @@ -68,21 +67,6 @@ static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr) *p = '\0'; } -static inline void asd_destringify_sas_addr(u8 *sas_addr, const char *p) -{ - int i; - for (i = 0; i < SAS_ADDR_SIZE; i++) { - u8 h, l; - if (!*p) - break; - h = isdigit(*p) ? *p-'0' : *p-'A'+10; - p++; - l = isdigit(*p) ? *p-'0' : *p-'A'+10; - p++; - sas_addr[i] = (h<<4) | l; - } -} - struct asd_ha_struct; struct asd_ascb; diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index 098b5f3..940a207 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "aic94xx.h" #include "aic94xx_reg.h" @@ -38,16 +39,14 @@ u32 MBAR0_SWB_SIZE; /* ---------- Initialization ---------- */ -static void asd_get_user_sas_addr(struct asd_ha_struct *asd_ha) +static int asd_get_user_sas_addr(struct asd_ha_struct *asd_ha) { - extern char sas_addr_str[]; - /* If the user has specified a WWN it overrides other settings - */ - if (sas_addr_str[0] != '\0') - asd_destringify_sas_addr(asd_ha->hw_prof.sas_addr, - sas_addr_str); - else if (asd_ha->hw_prof.sas_addr[0] != 0) - asd_stringify_sas_addr(sas_addr_str, asd_ha->hw_prof.sas_addr); + /* adapter came with a sas address */ + if (asd_ha->hw_prof.sas_addr[0]) + return 0; + + return sas_request_addr(asd_ha->sas_ha.core.shost, + asd_ha->hw_prof.sas_addr); } static void asd_propagate_sas_addr(struct asd_ha_struct *asd_ha) @@ -657,8 +656,7 @@ int asd_init_hw(struct asd_ha_struct *asd_ha) asd_init_ctxmem(asd_ha); - asd_get_user_sas_addr(asd_ha); - if (!asd_ha->hw_prof.sas_addr[0]) { + if (asd_get_user_sas_addr(asd_ha)) { asd_printk("No SAS Address provided for %s\n", pci_name(asd_ha->pcidev)); err = -ENODEV; diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 88d1e73..806fa4d 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -56,8 +56,6 @@ MODULE_PARM_DESC(collector, "\n" "\tThe aic94xx SAS LLDD supports both modes.\n" "\tDefault: 0 (Direct Mode).\n"); -char sas_addr_str[2*SAS_ADDR_SIZE + 1] = ""; - static struct scsi_transport_template *aic94xx_transport_template; static int asd_scan_finished(struct Scsi_Host *, unsigned long); static void asd_scan_start(struct Scsi_Host *); diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index 3bedf24..8e53f02 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -2983,7 +2983,6 @@ static struct scsi_host_template acornscsi_template = { .this_id = 7, .sg_tablesize = SG_ALL, .cmd_per_lun = 2, - .unchecked_isa_dma = 0, .use_clustering = DISABLE_CLUSTERING, .proc_name = "acornscsi", }; diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 49d838e..a3398fe 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -222,7 +222,6 @@ static struct scsi_host_template cumanascsi_template = { .this_id = 7, .sg_tablesize = SG_ALL, .cmd_per_lun = 2, - .unchecked_isa_dma = 0, .use_clustering = DISABLE_CLUSTERING, .proc_name = "CumanaSCSI-1", }; diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index e351db6..075e239 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -4761,7 +4761,6 @@ static struct scsi_host_template dc395x_driver_template = { .cmd_per_lun = DC395x_MAX_CMD_PER_LUN, .eh_abort_handler = dc395x_eh_abort, .eh_bus_reset_handler = dc395x_eh_bus_reset, - .unchecked_isa_dma = 0, .use_clustering = DISABLE_CLUSTERING, }; diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index b5a6092..952505c 100644 --- a/drivers/scsi/eata_pio.c +++ b/drivers/scsi/eata_pio.c @@ -815,8 +815,6 @@ static int register_pio_HBA(long base, struct get_conf *gc, struct pci_dev *pdev else hd->primary = 1; - sh->unchecked_isa_dma = 0; /* We can only do PIO */ - hd->next = NULL; /* build a linked list of all HBAs */ hd->prev = last_HBA; if (hd->prev != NULL) diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 27ebd33..4560e39 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -85,10 +85,10 @@ /* The meaning of the Scsi_Pointer members in this driver is as follows: * ptr: Chaining - * this_residual: gdth_bufflen - * buffer: gdth_sglist + * this_residual: unused + * buffer: unused * dma_handle: unused - * buffers_residual: gdth_sg_count + * buffers_residual: unused * Status: unused * Message: unused * have_data_in: unused @@ -372,47 +372,6 @@ static const struct file_operations gdth_fops = { .release = gdth_close, }; -/* - * gdth scsi_command access wrappers. - * below 6 functions are used throughout the driver to access scsi_command's - * io parameters. The reason we do not use the regular accessors from - * scsi_cmnd.h is because of gdth_execute(). Since it is unrecommended for - * llds to directly set scsi_cmnd's IO members. This driver will use SCp - * members for IO parameters, and will copy scsi_cmnd's members to Scp - * members in queuecommand. For internal commands through gdth_execute() - * SCp's members will be set directly. - */ -static inline unsigned gdth_bufflen(struct scsi_cmnd *cmd) -{ - return (unsigned)cmd->SCp.this_residual; -} - -static inline void gdth_set_bufflen(struct scsi_cmnd *cmd, unsigned bufflen) -{ - cmd->SCp.this_residual = bufflen; -} - -static inline unsigned gdth_sg_count(struct scsi_cmnd *cmd) -{ - return (unsigned)cmd->SCp.buffers_residual; -} - -static inline void gdth_set_sg_count(struct scsi_cmnd *cmd, unsigned sg_count) -{ - cmd->SCp.buffers_residual = sg_count; -} - -static inline struct scatterlist *gdth_sglist(struct scsi_cmnd *cmd) -{ - return cmd->SCp.buffer; -} - -static inline void gdth_set_sglist(struct scsi_cmnd *cmd, - struct scatterlist *sglist) -{ - cmd->SCp.buffer = sglist; -} - #include "gdth_proc.h" #include "gdth_proc.c" @@ -584,125 +543,111 @@ static int __init gdth_search_isa(ulong32 bios_adr) #endif /* CONFIG_ISA */ #ifdef CONFIG_PCI -static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, - ushort vendor, ushort dev); +static bool gdth_pci_registered; -static int __init gdth_search_pci(gdth_pci_str *pcistr) +static bool gdth_search_vortex(ushort device) { - ushort device, cnt; - - TRACE(("gdth_search_pci()\n")); - - cnt = 0; - for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device) - gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device); - for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP; - device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device) - gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device); - gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, - PCI_DEVICE_ID_VORTEX_GDTNEWRX); - gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, - PCI_DEVICE_ID_VORTEX_GDTNEWRX2); - gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_SRC); - gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_SRC_XSCALE); - return cnt; + if (device <= PCI_DEVICE_ID_VORTEX_GDT6555) + return true; + if (device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP && + device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP) + return true; + if (device == PCI_DEVICE_ID_VORTEX_GDTNEWRX || + device == PCI_DEVICE_ID_VORTEX_GDTNEWRX2) + return true; + return false; } +static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out); +static int gdth_pci_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void gdth_pci_remove_one(struct pci_dev *pdev); +static void gdth_remove_one(gdth_ha_str *ha); + /* Vortex only makes RAID controllers. * We do not really want to specify all 550 ids here, so wildcard match. */ -static struct pci_device_id gdthtable[] __maybe_unused = { - {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID}, - {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, - {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, - {0} +static const struct pci_device_id gdthtable[] = { + { PCI_VDEVICE(VORTEX, PCI_ANY_ID) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC_XSCALE) }, + { } /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, gdthtable); + +static struct pci_driver gdth_pci_driver = { + .name = "gdth", + .id_table = gdthtable, + .probe = gdth_pci_init_one, + .remove = gdth_pci_remove_one, }; -MODULE_DEVICE_TABLE(pci,gdthtable); -static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, - ushort vendor, ushort device) +static void gdth_pci_remove_one(struct pci_dev *pdev) { - ulong base0, base1, base2; - struct pci_dev *pdev; + gdth_ha_str *ha = pci_get_drvdata(pdev); + + pci_set_drvdata(pdev, NULL); + + list_del(&ha->list); + gdth_remove_one(ha); + + pci_disable_device(pdev); +} + +static int gdth_pci_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + ushort vendor = pdev->vendor; + ushort device = pdev->device; + ulong base0, base1, base2; + int rc; + gdth_pci_str gdth_pcistr; + gdth_ha_str *ha = NULL; - TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n", - *cnt, vendor, device)); + TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n", + gdth_ctr_count, vendor, device)); - pdev = NULL; - while ((pdev = pci_get_device(vendor, device, pdev)) - != NULL) { - if (pci_enable_device(pdev)) - continue; - if (*cnt >= MAXHA) { - pci_dev_put(pdev); - return; - } + memset(&gdth_pcistr, 0, sizeof(gdth_pcistr)); + + if (vendor == PCI_VENDOR_ID_VORTEX && !gdth_search_vortex(device)) + return -ENODEV; + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + if (gdth_ctr_count >= MAXHA) + return -EBUSY; /* GDT PCI controller found, resources are already in pdev */ - pcistr[*cnt].pdev = pdev; - pcistr[*cnt].irq = pdev->irq; + gdth_pcistr.pdev = pdev; base0 = pci_resource_flags(pdev, 0); base1 = pci_resource_flags(pdev, 1); base2 = pci_resource_flags(pdev, 2); if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ if (!(base0 & IORESOURCE_MEM)) - continue; - pcistr[*cnt].dpmem = pci_resource_start(pdev, 0); + return -ENODEV; + gdth_pcistr.dpmem = pci_resource_start(pdev, 0); } else { /* GDT6110, GDT6120, .. */ if (!(base0 & IORESOURCE_MEM) || !(base2 & IORESOURCE_MEM) || !(base1 & IORESOURCE_IO)) - continue; - pcistr[*cnt].dpmem = pci_resource_start(pdev, 2); - pcistr[*cnt].io_mm = pci_resource_start(pdev, 0); - pcistr[*cnt].io = pci_resource_start(pdev, 1); + return -ENODEV; + gdth_pcistr.dpmem = pci_resource_start(pdev, 2); + gdth_pcistr.io = pci_resource_start(pdev, 1); } TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", - pcistr[*cnt].pdev->bus->number, - PCI_SLOT(pcistr[*cnt].pdev->devfn), - pcistr[*cnt].irq, pcistr[*cnt].dpmem)); - (*cnt)++; - } -} + gdth_pcistr.pdev->bus->number, + PCI_SLOT(gdth_pcistr.pdev->devfn), + gdth_pcistr.irq, + gdth_pcistr.dpmem)); -static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt) -{ - gdth_pci_str temp; - int i, changed; - - TRACE(("gdth_sort_pci() cnt %d\n",cnt)); - if (cnt == 0) - return; + rc = gdth_pci_probe_one(&gdth_pcistr, &ha); + if (rc) + return rc; - do { - changed = FALSE; - for (i = 0; i < cnt-1; ++i) { - if (!reverse_scan) { - if ((pcistr[i].pdev->bus->number > pcistr[i+1].pdev->bus->number) || - (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number && - PCI_SLOT(pcistr[i].pdev->devfn) > - PCI_SLOT(pcistr[i+1].pdev->devfn))) { - temp = pcistr[i]; - pcistr[i] = pcistr[i+1]; - pcistr[i+1] = temp; - changed = TRUE; - } - } else { - if ((pcistr[i].pdev->bus->number < pcistr[i+1].pdev->bus->number) || - (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number && - PCI_SLOT(pcistr[i].pdev->devfn) < - PCI_SLOT(pcistr[i+1].pdev->devfn))) { - temp = pcistr[i]; - pcistr[i] = pcistr[i+1]; - pcistr[i+1] = temp; - changed = TRUE; - } - } - } - } while (changed); + return 0; } #endif /* CONFIG_PCI */ @@ -902,7 +847,8 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) #endif /* CONFIG_ISA */ #ifdef CONFIG_PCI -static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) +static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr, + gdth_ha_str *ha) { register gdt6_dpram_str __iomem *dp6_ptr; register gdt6c_dpram_str __iomem *dp6c_ptr; @@ -914,14 +860,14 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) TRACE(("gdth_init_pci()\n")); - if (pcistr->pdev->vendor == PCI_VENDOR_ID_INTEL) + if (pdev->vendor == PCI_VENDOR_ID_INTEL) ha->oem_id = OEM_ID_INTEL; else ha->oem_id = OEM_ID_ICP; - ha->brd_phys = (pcistr->pdev->bus->number << 8) | (pcistr->pdev->devfn & 0xf8); - ha->stype = (ulong32)pcistr->pdev->device; - ha->irq = pcistr->irq; - ha->pdev = pcistr->pdev; + ha->brd_phys = (pdev->bus->number << 8) | (pdev->devfn & 0xf8); + ha->stype = (ulong32)pdev->device; + ha->irq = pdev->irq; + ha->pdev = pdev; if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); @@ -949,8 +895,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) continue; } iounmap(ha->brd); - pci_write_config_dword(pcistr->pdev, - PCI_BASE_ADDRESS_0, i); + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i); ha->brd = ioremap(i, sizeof(gdt6_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); @@ -1059,8 +1004,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) continue; } iounmap(ha->brd); - pci_write_config_dword(pcistr->pdev, - PCI_BASE_ADDRESS_2, i); + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_2, i); ha->brd = ioremap(i, sizeof(gdt6c_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); @@ -1152,16 +1096,16 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } /* manipulate config. space to enable DPMEM, start RP controller */ - pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command); + pci_read_config_word(pdev, PCI_COMMAND, &command); command |= 6; - pci_write_config_word(pcistr->pdev, PCI_COMMAND, command); - if (pci_resource_start(pcistr->pdev, 8) == 1UL) - pci_resource_start(pcistr->pdev, 8) = 0UL; + pci_write_config_word(pdev, PCI_COMMAND, command); + if (pci_resource_start(pdev, 8) == 1UL) + pci_resource_start(pdev, 8) = 0UL; i = 0xFEFF0001UL; - pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i); + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, i); gdth_delay(1); - pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, - pci_resource_start(pcistr->pdev, 8)); + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, + pci_resource_start(pdev, 8)); dp6m_ptr = ha->brd; @@ -1188,8 +1132,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) continue; } iounmap(ha->brd); - pci_write_config_dword(pcistr->pdev, - PCI_BASE_ADDRESS_0, i); + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i); ha->brd = ioremap(i, sizeof(gdt6m_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); @@ -2346,12 +2289,12 @@ static void gdth_next(gdth_ha_str *ha) static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, char *buffer, ushort count) { - ushort cpcount,i, max_sg = gdth_sg_count(scp); + ushort cpcount,i, max_sg = scsi_sg_count(scp); ushort cpsum,cpnow; struct scatterlist *sl; char *address; - cpcount = min_t(ushort, count, gdth_bufflen(scp)); + cpcount = min_t(ushort, count, scsi_bufflen(scp)); if (cpcount) { cpsum=0; @@ -2359,7 +2302,7 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, unsigned long flags; cpnow = (ushort)sl->length; TRACE(("copy_internal() now %d sum %d count %d %d\n", - cpnow, cpsum, cpcount, gdth_bufflen(scp))); + cpnow, cpsum, cpcount, scsi_bufflen(scp))); if (cpsum+cpnow > cpcount) cpnow = cpcount - cpsum; cpsum += cpnow; @@ -2582,10 +2525,10 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) cmdp->u.cache.BlockCnt = blockcnt; } - if (gdth_bufflen(scp)) { + if (scsi_bufflen(scp)) { cmndinfo->dma_dir = (read_write == 1 ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp), + sgcnt = pci_map_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp), cmndinfo->dma_dir); if (mode64) { struct scatterlist *sl; @@ -2732,7 +2675,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) cmdp->u.raw64.lun = l; cmdp->u.raw64.bus = b; cmdp->u.raw64.priority = 0; - cmdp->u.raw64.sdlen = gdth_bufflen(scp); + cmdp->u.raw64.sdlen = scsi_bufflen(scp); cmdp->u.raw64.sense_len = 16; cmdp->u.raw64.sense_data = sense_paddr; cmdp->u.raw64.direction = @@ -2749,7 +2692,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) cmdp->u.raw.bus = b; cmdp->u.raw.priority = 0; cmdp->u.raw.link_p = 0; - cmdp->u.raw.sdlen = gdth_bufflen(scp); + cmdp->u.raw.sdlen = scsi_bufflen(scp); cmdp->u.raw.sense_len = 16; cmdp->u.raw.sense_data = sense_paddr; cmdp->u.raw.direction = @@ -2758,9 +2701,9 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) cmdp->u.raw.sg_ranz = 0; } - if (gdth_bufflen(scp)) { + if (scsi_bufflen(scp)) { cmndinfo->dma_dir = PCI_DMA_BIDIRECTIONAL; - sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp), + sgcnt = pci_map_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp), cmndinfo->dma_dir); if (mode64) { struct scatterlist *sl; @@ -3381,8 +3324,8 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, /* retry */ return 2; } - if (gdth_bufflen(scp)) - pci_unmap_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp), + if (scsi_bufflen(scp)) + pci_unmap_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp), cmndinfo->dma_dir); if (cmndinfo->sense_paddr) @@ -4024,10 +3967,6 @@ static int gdth_queuecommand(struct scsi_cmnd *scp, gdth_update_timeout(scp, scp->timeout_per_command * 6); cmndinfo->priority = DEFAULT_PRI; - gdth_set_bufflen(scp, scsi_bufflen(scp)); - gdth_set_sg_count(scp, scsi_sg_count(scp)); - gdth_set_sglist(scp, scsi_sglist(scp)); - return __gdth_queuecommand(ha, scp, cmndinfo); } @@ -4948,12 +4887,16 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot) #endif /* CONFIG_EISA */ #ifdef CONFIG_PCI -static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr) +static int gdth_pci_probe_one(gdth_pci_str *pcistr, + gdth_ha_str **ha_out) { struct Scsi_Host *shp; gdth_ha_str *ha; dma_addr_t scratch_dma_handle = 0; int error, i; + struct pci_dev *pdev = pcistr->pdev; + + *ha_out = NULL; shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str)); if (!shp) @@ -4961,13 +4904,13 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr) ha = shost_priv(shp); error = -ENODEV; - if (!gdth_init_pci(&pcistr[ctr],ha)) + if (!gdth_init_pci(pdev, pcistr, ha)) goto out_host_put; /* controller found and initialized */ printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", - pcistr[ctr].pdev->bus->number, - PCI_SLOT(pcistr[ctr].pdev->devfn), + pdev->bus->number, + PCI_SLOT(pdev->devfn), ha->irq); error = request_irq(ha->irq, gdth_interrupt, @@ -5012,7 +4955,7 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr) ha->scratch_busy = FALSE; ha->req_first = NULL; - ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES; + ha->tid_cnt = pdev->device >= 0x200 ? MAXID : MAX_HDRIVES; if (max_ids > 0 && max_ids < ha->tid_cnt) ha->tid_cnt = max_ids; for (i = 0; i < GDTH_MAXCMDS; ++i) @@ -5032,16 +4975,16 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr) /* 64-bit DMA only supported from FW >= x.43 */ if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) || !ha->dma64_support) { - if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "GDT-PCI %d: " "Unable to set 32-bit DMA\n", ha->hanum); goto out_free_coal_stat; } } else { shp->max_cmd_len = 16; - if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) { + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { printk("GDT-PCI %d: 64-bit DMA enabled\n", ha->hanum); - } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { + } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "GDT-PCI %d: " "Unable to set 64/32-bit DMA\n", ha->hanum); goto out_free_coal_stat; @@ -5055,13 +4998,17 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr) spin_lock_init(&ha->smp_lock); gdth_enable_int(ha); - error = scsi_add_host(shp, &pcistr[ctr].pdev->dev); + error = scsi_add_host(shp, &pdev->dev); if (error) goto out_free_coal_stat; list_add_tail(&ha->list, &gdth_instances); + pci_set_drvdata(ha->pdev, ha); + scsi_scan_host(shp); + *ha_out = ha; + return 0; out_free_coal_stat: @@ -5178,16 +5125,8 @@ static int __init gdth_init(void) #ifdef CONFIG_PCI /* scanning for PCI controllers */ - { - gdth_pci_str pcistr[MAXHA]; - int cnt,ctr; - - cnt = gdth_search_pci(pcistr); - printk("GDT-HA: Found %d PCI Storage RAID Controllers\n", cnt); - gdth_sort_pci(pcistr,cnt); - for (ctr = 0; ctr < cnt; ++ctr) - gdth_pci_probe_one(pcistr, ctr); - } + if (pci_register_driver(&gdth_pci_driver) == 0) + gdth_pci_registered = true; #endif /* CONFIG_PCI */ TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); @@ -5220,6 +5159,11 @@ static void __exit gdth_exit(void) del_timer_sync(&gdth_timer); #endif +#ifdef CONFIG_PCI + if (gdth_pci_registered) + pci_unregister_driver(&gdth_pci_driver); +#endif + list_for_each_entry(ha, &gdth_instances, list) gdth_remove_one(ha); } diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index 26e4e92..ca92476 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -839,8 +839,6 @@ typedef struct { struct pci_dev *pdev; ulong dpmem; /* DPRAM address */ ulong io; /* IO address */ - ulong io_mm; /* IO address mem. mapped */ - unchar irq; /* IRQ */ } gdth_pci_str; diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index ff149ad..44dccf2 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -903,7 +903,6 @@ static struct scsi_host_template driver_template = { .eh_device_reset_handler = hptiop_reset, .eh_bus_reset_handler = hptiop_reset, .info = hptiop_info, - .unchecked_isa_dma = 0, .emulated = 0, .use_clustering = ENABLE_CLUSTERING, .proc_name = driver_name, diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 7ed568f..6264036 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -3510,15 +3510,16 @@ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count) struct scatterlist *sg = scsi_sglist(scmd); for (i = 0, xfer_cnt = 0; - (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) { - min_cnt = min(count - xfer_cnt, sg[i].length); + (i < scsi_sg_count(scmd)) && (xfer_cnt < count); + i++, sg = sg_next(sg)) { + min_cnt = min(count - xfer_cnt, sg->length); /* kmap_atomic() ensures addressability of the data buffer.*/ /* local_irq_save() protects the KM_IRQ0 address slot. */ local_irq_save(flags); - buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset; + buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; memcpy(buffer, &cdata[xfer_cnt], min_cnt); - kunmap_atomic(buffer - sg[i].offset, KM_IRQ0); + kunmap_atomic(buffer - sg->offset, KM_IRQ0); local_irq_restore(flags); xfer_cnt += min_cnt; @@ -3543,15 +3544,16 @@ ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count) struct scatterlist *sg = scsi_sglist(scmd); for (i = 0, xfer_cnt = 0; - (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) { - min_cnt = min(count - xfer_cnt, sg[i].length); + (i < scsi_sg_count(scmd)) && (xfer_cnt < count); + i++, sg = sg_next(sg)) { + min_cnt = min(count - xfer_cnt, sg->length); /* kmap_atomic() ensures addressability of the data buffer.*/ /* local_irq_save() protects the KM_IRQ0 address slot. */ local_irq_save(flags); - buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset; + buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; memcpy(&cdata[xfer_cnt], buffer, min_cnt); - kunmap_atomic(buffer - sg[i].offset, KM_IRQ0); + kunmap_atomic(buffer - sg->offset, KM_IRQ0); local_irq_restore(flags); xfer_cnt += min_cnt; @@ -6842,7 +6844,6 @@ ips_register_scsi(int index) sh->sg_tablesize = sh->hostt->sg_tablesize; sh->can_queue = sh->hostt->can_queue; sh->cmd_per_lun = sh->hostt->cmd_per_lun; - sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma; sh->use_clustering = sh->hostt->use_clustering; sh->max_sectors = 128; diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 1f82415..601ec5b 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -24,6 +24,8 @@ */ #include +#include +#include #include "sas_internal.h" @@ -1064,6 +1066,45 @@ void sas_target_destroy(struct scsi_target *starget) return; } +static void sas_parse_addr(u8 *sas_addr, const char *p) +{ + int i; + for (i = 0; i < SAS_ADDR_SIZE; i++) { + u8 h, l; + if (!*p) + break; + h = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10; + p++; + l = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10; + p++; + sas_addr[i] = (h<<4) | l; + } +} + +#define SAS_STRING_ADDR_SIZE 16 + +int sas_request_addr(struct Scsi_Host *shost, u8 *addr) +{ + int res; + const struct firmware *fw; + + res = request_firmware(&fw, "sas_addr", &shost->shost_gendev); + if (res) + return res; + + if (fw->size < SAS_STRING_ADDR_SIZE) { + res = -ENODEV; + goto out; + } + + sas_parse_addr(addr, fw->data); + +out: + release_firmware(fw); + return res; +} +EXPORT_SYMBOL_GPL(sas_request_addr); + EXPORT_SYMBOL_GPL(sas_queuecommand); EXPORT_SYMBOL_GPL(sas_target_alloc); EXPORT_SYMBOL_GPL(sas_slave_configure); diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 3b09ab2..0248919 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -592,7 +592,6 @@ static struct scsi_host_template driver_template = { .this_id = 7, .sg_tablesize = SG_ALL, .cmd_per_lun = CMD_PER_LUN, - .unchecked_isa_dma = 0, .use_clustering = DISABLE_CLUSTERING }; diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c index fad6cb5..0eed5ca 100644 --- a/drivers/scsi/ps3rom.c +++ b/drivers/scsi/ps3rom.c @@ -95,7 +95,7 @@ static int ps3rom_slave_configure(struct scsi_device *scsi_dev) */ static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf) { - int k, req_len, act_len, len, active; + int k, req_len, len, fin; void *kaddr; struct scatterlist *sgpnt; unsigned int buflen; @@ -107,24 +107,22 @@ static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf) if (!scsi_sglist(cmd)) return -1; - active = 1; - req_len = act_len = 0; + req_len = fin = 0; scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { - if (active) { - kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0); - len = sgpnt->length; - if ((req_len + len) > buflen) { - active = 0; - len = buflen - req_len; - } - memcpy(kaddr + sgpnt->offset, buf + req_len, len); - flush_kernel_dcache_page(sg_page(sgpnt)); - kunmap_atomic(kaddr, KM_IRQ0); - act_len += len; + kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0); + len = sgpnt->length; + if ((req_len + len) > buflen) { + len = buflen - req_len; + fin = 1; } - req_len += sgpnt->length; + memcpy(kaddr + sgpnt->offset, buf + req_len, len); + flush_kernel_dcache_page(sg_page(sgpnt)); + kunmap_atomic(kaddr, KM_IRQ0); + req_len += len; + if (fin) + break; } - scsi_set_resid(cmd, buflen - act_len); + scsi_set_resid(cmd, buflen - req_len); return 0; } diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index fe415ec..ed8ee66 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -216,6 +216,7 @@ union external_hw_config_reg { #define MBOX_CMD_ABOUT_FW 0x0009 #define MBOX_CMD_PING 0x000B #define MBOX_CMD_LUN_RESET 0x0016 +#define MBOX_CMD_TARGET_WARM_RESET 0x0017 #define MBOX_CMD_GET_MANAGEMENT_DATA 0x001E #define MBOX_CMD_GET_FW_STATUS 0x001F #define MBOX_CMD_SET_ISNS_SERVICE 0x0021 diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index a3608e0..b403a17 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -27,6 +27,8 @@ int qla4xxx_relogin_device(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry); int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, int lun); +int qla4xxx_reset_target(struct scsi_qla_host * ha, + struct ddb_entry * ddb_entry); int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, uint32_t offset, uint32_t len); int qla4xxx_get_firmware_status(struct scsi_qla_host * ha); diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 35cd73c..c577d79 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -713,6 +713,45 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, return status; } +/** + * qla4xxx_reset_target - issues target Reset + * @ha: Pointer to host adapter structure. + * @db_entry: Pointer to device database entry + * @un_entry: Pointer to lun entry structure + * + * This routine performs a TARGET RESET on the specified target. + * The caller must ensure that the ddb_entry pointers + * are valid before calling this routine. + **/ +int qla4xxx_reset_target(struct scsi_qla_host *ha, + struct ddb_entry *ddb_entry) +{ + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + int status = QLA_SUCCESS; + + DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no, + ddb_entry->os_target_id)); + + /* + * Send target reset command to ISP, so that the ISP will return all + * outstanding requests with RESET status + */ + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + + mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET; + mbox_cmd[1] = ddb_entry->fw_ddb_index; + mbox_cmd[5] = 0x01; /* Immediate Command Enable */ + + qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], + &mbox_sts[0]); + if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE && + mbox_sts[0] != MBOX_STS_COMMAND_ERROR) + status = QLA_ERROR; + + return status; +} int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, uint32_t offset, uint32_t len) diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 8b92f34..31e605c 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -71,6 +71,7 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session); static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, void (*done) (struct scsi_cmnd *)); static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd); +static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd); static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd); static int qla4xxx_slave_alloc(struct scsi_device *device); static int qla4xxx_slave_configure(struct scsi_device *device); @@ -84,6 +85,7 @@ static struct scsi_host_template qla4xxx_driver_template = { .queuecommand = qla4xxx_queuecommand, .eh_device_reset_handler = qla4xxx_eh_device_reset, + .eh_target_reset_handler = qla4xxx_eh_target_reset, .eh_host_reset_handler = qla4xxx_eh_host_reset, .slave_configure = qla4xxx_slave_configure, @@ -1482,7 +1484,7 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha) } /** - * qla4xxx_eh_wait_for_active_target_commands - wait for active cmds to finish. + * qla4xxx_eh_wait_for_commands - wait for active cmds to finish. * @ha: pointer to to HBA * @t: target id * @l: lun id @@ -1490,20 +1492,22 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha) * This function waits for all outstanding commands to a lun to complete. It * returns 0 if all pending commands are returned and 1 otherwise. **/ -static int qla4xxx_eh_wait_for_active_target_commands(struct scsi_qla_host *ha, - int t, int l) +static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha, + struct scsi_target *stgt, + struct scsi_device *sdev) { int cnt; int status = 0; struct scsi_cmnd *cmd; /* - * Waiting for all commands for the designated target in the active - * array + * Waiting for all commands for the designated target or dev + * in the active array */ for (cnt = 0; cnt < ha->host->can_queue; cnt++) { cmd = scsi_host_find_tag(ha->host, cnt); - if (cmd && cmd->device->id == t && cmd->device->lun == l) { + if (cmd && stgt == scsi_target(cmd->device) && + (!sdev || sdev == cmd->device)) { if (!qla4xxx_eh_wait_on_command(ha, cmd)) { status++; break; @@ -1551,19 +1555,12 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) /* Send marker. */ ha->marker_needed = 1; - /* - * If we are coming down the EH path, wait for all commands to complete - * for the device. - */ - if (cmd->device->host->shost_state == SHOST_RECOVERY) { - if (qla4xxx_eh_wait_for_active_target_commands(ha, - cmd->device->id, - cmd->device->lun)){ - dev_info(&ha->pdev->dev, - "DEVICE RESET FAILED - waiting for " - "commands.\n"); - goto eh_dev_reset_done; - } + if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), + cmd->device)) { + dev_info(&ha->pdev->dev, + "DEVICE RESET FAILED - waiting for " + "commands.\n"); + goto eh_dev_reset_done; } dev_info(&ha->pdev->dev, @@ -1579,6 +1576,53 @@ eh_dev_reset_done: } /** + * qla4xxx_eh_target_reset - callback for target reset. + * @cmd: Pointer to Linux's SCSI command structure + * + * This routine is called by the Linux OS to reset the target. + **/ +static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) +{ + struct scsi_qla_host *ha = to_qla_host(cmd->device->host); + struct ddb_entry *ddb_entry = cmd->device->hostdata; + int stat; + + if (!ddb_entry) + return FAILED; + + starget_printk(KERN_INFO, scsi_target(cmd->device), + "WARM TARGET RESET ISSUED.\n"); + + DEBUG2(printk(KERN_INFO + "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, " + "to=%x,dpc_flags=%lx, status=%x allowed=%d\n", + ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ, + ha->dpc_flags, cmd->result, cmd->allowed)); + + stat = qla4xxx_reset_target(ha, ddb_entry); + if (stat != QLA_SUCCESS) { + starget_printk(KERN_INFO, scsi_target(cmd->device), + "WARM TARGET RESET FAILED.\n"); + return FAILED; + } + + /* Send marker. */ + ha->marker_needed = 1; + + if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), + NULL)) { + starget_printk(KERN_INFO, scsi_target(cmd->device), + "WARM TARGET DEVICE RESET FAILED - " + "waiting for commands.\n"); + return FAILED; + } + + starget_printk(KERN_INFO, scsi_target(cmd->device), + "WARM TARGET RESET SUCCEEDED.\n"); + return SUCCESS; +} + +/** * qla4xxx_eh_host_reset - kernel callback * @cmd: Pointer to Linux's SCSI command structure * diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index d1777a9..3abd286 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -39,16 +39,17 @@ #include #include #include - #include -#include "scsi.h" + +#include +#include +#include #include #include #include #include "scsi_logging.h" -#include "scsi_debug.h" #define SCSI_DEBUG_VERSION "1.81" static const char * scsi_debug_version_date = "20070104"; @@ -165,6 +166,9 @@ static int sdebug_sectors_per; /* sectors per cylinder */ #define SDEBUG_SENSE_LEN 32 +#define SCSI_DEBUG_CANQUEUE 255 +#define SCSI_DEBUG_MAX_CMD_LEN 16 + struct sdebug_dev_info { struct list_head dev_list; unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */ @@ -202,30 +206,6 @@ struct sdebug_queued_cmd { }; static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; -static struct scsi_host_template sdebug_driver_template = { - .proc_info = scsi_debug_proc_info, - .name = "SCSI DEBUG", - .info = scsi_debug_info, - .slave_alloc = scsi_debug_slave_alloc, - .slave_configure = scsi_debug_slave_configure, - .slave_destroy = scsi_debug_slave_destroy, - .ioctl = scsi_debug_ioctl, - .queuecommand = scsi_debug_queuecommand, - .eh_abort_handler = scsi_debug_abort, - .eh_bus_reset_handler = scsi_debug_bus_reset, - .eh_device_reset_handler = scsi_debug_device_reset, - .eh_host_reset_handler = scsi_debug_host_reset, - .bios_param = scsi_debug_biosparam, - .can_queue = SCSI_DEBUG_CANQUEUE, - .this_id = 7, - .sg_tablesize = 256, - .cmd_per_lun = 16, - .max_sectors = 0xffff, - .unchecked_isa_dma = 0, - .use_clustering = DISABLE_CLUSTERING, - .module = THIS_MODULE, -}; - static unsigned char * fake_storep; /* ramdisk storage */ static int num_aborts = 0; @@ -364,9 +344,6 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) int inj_transport = 0; int delay_override = 0; - if (done == NULL) - return 0; /* assume mid level reprocessing command */ - scsi_set_resid(SCpnt, 0); if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) { printk(KERN_INFO "scsi_debug: cmd "); @@ -374,7 +351,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) printk("%02x ", (int)cmd[k]); printk("\n"); } - if(target == sdebug_driver_template.this_id) { + + if (target == SCpnt->device->host->hostt->this_id) { printk(KERN_INFO "scsi_debug: initiator's id used as " "target!\n"); return schedule_resp(SCpnt, NULL, done, @@ -2098,8 +2076,8 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) if (devip) return devip; - sdbg_host = *(struct sdebug_host_info **) sdev->host->hostdata; - if(! sdbg_host) { + sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host); + if (!sdbg_host) { printk(KERN_ERR "Host info NULL\n"); return NULL; } @@ -2226,7 +2204,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) printk(KERN_INFO "scsi_debug: bus_reset\n"); ++num_bus_resets; if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) { - sdbg_host = *(struct sdebug_host_info **) hp->hostdata; + sdbg_host = *(struct sdebug_host_info **)shost_priv(hp); if (sdbg_host) { list_for_each_entry(dev_info, &sdbg_host->dev_info_list, @@ -2922,8 +2900,6 @@ static int __init scsi_debug_init(void) init_all_queued(); - sdebug_driver_template.proc_name = sdebug_proc_name; - host_to_add = scsi_debug_add_host; scsi_debug_add_host = 0; @@ -3083,6 +3059,30 @@ static void sdebug_remove_adapter(void) --scsi_debug_add_host; } +static struct scsi_host_template sdebug_driver_template = { + .proc_info = scsi_debug_proc_info, + .proc_name = sdebug_proc_name, + .name = "SCSI DEBUG", + .info = scsi_debug_info, + .slave_alloc = scsi_debug_slave_alloc, + .slave_configure = scsi_debug_slave_configure, + .slave_destroy = scsi_debug_slave_destroy, + .ioctl = scsi_debug_ioctl, + .queuecommand = scsi_debug_queuecommand, + .eh_abort_handler = scsi_debug_abort, + .eh_bus_reset_handler = scsi_debug_bus_reset, + .eh_device_reset_handler = scsi_debug_device_reset, + .eh_host_reset_handler = scsi_debug_host_reset, + .bios_param = scsi_debug_biosparam, + .can_queue = SCSI_DEBUG_CANQUEUE, + .this_id = 7, + .sg_tablesize = 256, + .cmd_per_lun = 16, + .max_sectors = 0xffff, + .use_clustering = DISABLE_CLUSTERING, + .module = THIS_MODULE, +}; + static int sdebug_driver_probe(struct device * dev) { int error = 0; diff --git a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h deleted file mode 100644 index 965dd5e..0000000 --- a/drivers/scsi/scsi_debug.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _SCSI_DEBUG_H - -#include - -static int scsi_debug_slave_alloc(struct scsi_device *); -static int scsi_debug_slave_configure(struct scsi_device *); -static void scsi_debug_slave_destroy(struct scsi_device *); -static int scsi_debug_queuecommand(struct scsi_cmnd *, - void (*done) (struct scsi_cmnd *)); -static int scsi_debug_ioctl(struct scsi_device *, int, void __user *); -static int scsi_debug_biosparam(struct scsi_device *, struct block_device *, - sector_t, int[]); -static int scsi_debug_abort(struct scsi_cmnd *); -static int scsi_debug_bus_reset(struct scsi_cmnd *); -static int scsi_debug_device_reset(struct scsi_cmnd *); -static int scsi_debug_host_reset(struct scsi_cmnd *); -static int scsi_debug_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int); -static const char * scsi_debug_info(struct Scsi_Host *); - -#define SCSI_DEBUG_CANQUEUE 255 /* needs to be >= 1 */ - -#define SCSI_DEBUG_MAX_CMD_LEN 16 - -#endif diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 045a086..1221d2c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -524,6 +524,41 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd) return rtn; } +static void __scsi_report_device_reset(struct scsi_device *sdev, void *data) +{ + sdev->was_reset = 1; + sdev->expecting_cc_ua = 1; +} + +/** + * scsi_try_target_reset - Ask host to perform a target reset + * @scmd: SCSI cmd used to send a target reset + * + * Notes: + * There is no timeout for this operation. if this operation is + * unreliable for a given host, then the host itself needs to put a + * timer on it, and set the host back to a consistent state prior to + * returning. + */ +static int scsi_try_target_reset(struct scsi_cmnd *scmd) +{ + unsigned long flags; + int rtn; + + if (!scmd->device->host->hostt->eh_target_reset_handler) + return FAILED; + + rtn = scmd->device->host->hostt->eh_target_reset_handler(scmd); + if (rtn == SUCCESS) { + spin_lock_irqsave(scmd->device->host->host_lock, flags); + __starget_for_each_device(scsi_target(scmd->device), NULL, + __scsi_report_device_reset); + spin_unlock_irqrestore(scmd->device->host->host_lock, flags); + } + + return rtn; +} + /** * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev * @scmd: SCSI cmd used to send BDR @@ -542,11 +577,8 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd) return FAILED; rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd); - if (rtn == SUCCESS) { - scmd->device->was_reset = 1; - scmd->device->expecting_cc_ua = 1; - } - + if (rtn == SUCCESS) + __scsi_report_device_reset(scmd->device, NULL); return rtn; } @@ -584,8 +616,9 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) { if (__scsi_try_to_abort_cmd(scmd) != SUCCESS) if (scsi_try_bus_device_reset(scmd) != SUCCESS) - if (scsi_try_bus_reset(scmd) != SUCCESS) - scsi_try_host_reset(scmd); + if (scsi_try_target_reset(scmd) != SUCCESS) + if (scsi_try_bus_reset(scmd) != SUCCESS) + scsi_try_host_reset(scmd); } /** @@ -1060,6 +1093,56 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, } /** + * scsi_eh_target_reset - send target reset if needed + * @shost: scsi host being recovered. + * @work_q: &list_head for pending commands. + * @done_q: &list_head for processed commands. + * + * Notes: + * Try a target reset. + */ +static int scsi_eh_target_reset(struct Scsi_Host *shost, + struct list_head *work_q, + struct list_head *done_q) +{ + struct scsi_cmnd *scmd, *tgtr_scmd, *next; + unsigned int id; + int rtn; + + for (id = 0; id <= shost->max_id; id++) { + tgtr_scmd = NULL; + list_for_each_entry(scmd, work_q, eh_entry) { + if (id == scmd_id(scmd)) { + tgtr_scmd = scmd; + break; + } + } + if (!tgtr_scmd) + continue; + + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset " + "to target %d\n", + current->comm, id)); + rtn = scsi_try_target_reset(tgtr_scmd); + if (rtn == SUCCESS) { + list_for_each_entry_safe(scmd, next, work_q, eh_entry) { + if (id == scmd_id(scmd)) + if (!scsi_device_online(scmd->device) || + !scsi_eh_tur(tgtr_scmd)) + scsi_eh_finish_cmd(scmd, + done_q); + } + } else + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset" + " failed target: " + "%d\n", + current->comm, id)); + } + + return list_empty(work_q); +} + +/** * scsi_eh_bus_reset - send a bus reset * @shost: &scsi host being recovered. * @work_q: &list_head for pending commands. @@ -1447,9 +1530,11 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost, { if (!scsi_eh_stu(shost, work_q, done_q)) if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) - if (!scsi_eh_bus_reset(shost, work_q, done_q)) - if (!scsi_eh_host_reset(work_q, done_q)) - scsi_eh_offline_sdevs(work_q, done_q); + if (!scsi_eh_target_reset(shost, work_q, done_q)) + if (!scsi_eh_bus_reset(shost, work_q, done_q)) + if (!scsi_eh_host_reset(work_q, done_q)) + scsi_eh_offline_sdevs(work_q, + done_q); } EXPORT_SYMBOL_GPL(scsi_eh_ready_devs); @@ -1619,10 +1704,8 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel) struct scsi_device *sdev; __shost_for_each_device(sdev, shost) { - if (channel == sdev_channel(sdev)) { - sdev->was_reset = 1; - sdev->expecting_cc_ua = 1; - } + if (channel == sdev_channel(sdev)) + __scsi_report_device_reset(sdev, NULL); } } EXPORT_SYMBOL(scsi_report_bus_reset); @@ -1655,10 +1738,8 @@ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target) __shost_for_each_device(sdev, shost) { if (channel == sdev_channel(sdev) && - target == sdev_id(sdev)) { - sdev->was_reset = 1; - sdev->expecting_cc_ua = 1; - } + target == sdev_id(sdev)) + __scsi_report_device_reset(sdev, NULL); } } EXPORT_SYMBOL(scsi_report_device_reset); @@ -1714,6 +1795,11 @@ scsi_reset_provider(struct scsi_device *dev, int flag) if (rtn == SUCCESS) break; /* FALLTHROUGH */ + case SCSI_TRY_RESET_TARGET: + rtn = scsi_try_target_reset(scmd); + if (rtn == SUCCESS) + break; + /* FALLTHROUGH */ case SCSI_TRY_RESET_BUS: rtn = scsi_try_bus_reset(scmd); if (rtn == SUCCESS) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 0a52d9d..d204aad 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static const char *verstr = "20080221"; +static const char *verstr = "20080224"; #include @@ -183,6 +183,7 @@ static int modes_defined; static struct st_buffer *new_tape_buffer(int, int, int); static int enlarge_buffer(struct st_buffer *, int, int); +static void clear_buffer(struct st_buffer *); static void normalize_buffer(struct st_buffer *); static int append_to_buffer(const char __user *, struct st_buffer *, int); static int from_buffer(struct st_buffer *, char __user *, int); @@ -442,6 +443,7 @@ static void st_sleep_done(void *data, char *sense, int result, int resid) memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE); (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result; + (STp->buffer)->cmdstat.residual = resid; DEB( STp->write_pending = 0; ) if (SRpnt->waiting) @@ -1159,6 +1161,7 @@ static int st_open(struct inode *inode, struct file *filp) goto err_out; } + (STp->buffer)->cleared = 0; (STp->buffer)->writing = 0; (STp->buffer)->syscall_result = 0; @@ -1432,8 +1435,14 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf, if (STp->block_size) bufsize = STp->block_size > st_fixed_buffer_size ? STp->block_size : st_fixed_buffer_size; - else + else { bufsize = count; + /* Make sure that data from previous user is not leaked even if + HBA does not return correct residual */ + if (is_read && STp->sili && !STbp->cleared) + clear_buffer(STbp); + } + if (bufsize > STbp->buffer_size && !enlarge_buffer(STbp, bufsize, STp->restr_dma)) { printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n", @@ -1783,6 +1792,8 @@ static long read_tape(struct scsi_tape *STp, long count, memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = READ_6; cmd[1] = (STp->block_size != 0); + if (!cmd[1] && STp->sili) + cmd[1] |= 2; cmd[2] = blks >> 16; cmd[3] = blks >> 8; cmd[4] = blks; @@ -1911,8 +1922,11 @@ static long read_tape(struct scsi_tape *STp, long count, } /* End of error handling */ - else /* Read successful */ + else { /* Read successful */ STbp->buffer_bytes = bytes; + if (STp->sili) /* In fixed block mode residual is always zero here */ + STbp->buffer_bytes -= STp->buffer->cmdstat.residual; + } if (STps->drv_block >= 0) { if (STp->block_size == 0) @@ -2090,7 +2104,8 @@ static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions, STp->scsi2_logical); printk(KERN_INFO - "%s: sysv: %d nowait: %d\n", name, STm->sysv, STp->immediate); + "%s: sysv: %d nowait: %d sili: %d\n", name, STm->sysv, STp->immediate, + STp->sili); printk(KERN_INFO "%s: debugging: %d\n", name, debugging); } @@ -2133,6 +2148,7 @@ static int st_set_options(struct scsi_tape *STp, long options) STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0; STp->immediate = (options & MT_ST_NOWAIT) != 0; STm->sysv = (options & MT_ST_SYSV) != 0; + STp->sili = (options & MT_ST_SILI) != 0; DEB( debugging = (options & MT_ST_DEBUGGING) != 0; st_log_options(STp, STm, name); ) } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) { @@ -2164,6 +2180,8 @@ static int st_set_options(struct scsi_tape *STp, long options) STp->immediate = value; if ((options & MT_ST_SYSV) != 0) STm->sysv = value; + if ((options & MT_ST_SILI) != 0) + STp->sili = value; DEB( if ((options & MT_ST_DEBUGGING) != 0) debugging = value; @@ -3655,6 +3673,8 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm STbuffer->frp_segs += 1; got += b_size; STbuffer->buffer_size = got; + if (STbuffer->cleared) + memset(page_address(STbuffer->frp[segs].page), 0, b_size); segs++; } STbuffer->b_data = page_address(STbuffer->frp[0].page); @@ -3663,6 +3683,17 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm } +/* Make sure that no data from previous user is in the internal buffer */ +static void clear_buffer(struct st_buffer * st_bp) +{ + int i; + + for (i=0; i < st_bp->frp_segs; i++) + memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length); + st_bp->cleared = 1; +} + + /* Release the extra buffer */ static void normalize_buffer(struct st_buffer * STbuffer) { @@ -3987,6 +4018,7 @@ static int st_probe(struct device *dev) tpnt->two_fm = ST_TWO_FM; tpnt->fast_mteom = ST_FAST_MTEOM; tpnt->scsi2_logical = ST_SCSI2LOGICAL; + tpnt->sili = ST_SILI; tpnt->immediate = ST_NOWAIT; tpnt->default_drvbuffer = 0xff; /* No forced buffering */ tpnt->partition = 0; @@ -4333,6 +4365,46 @@ static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf) CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL); +static ssize_t st_options_show(struct class_device *class_dev, char *buf) +{ + struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev); + struct scsi_tape *STp; + int i, j, options; + ssize_t l = 0; + + for (i=0; i < st_dev_max; i++) { + for (j=0; j < ST_NBR_MODES; j++) + if (&scsi_tapes[i]->modes[j] == STm) + break; + if (j < ST_NBR_MODES) + break; + } + if (i == st_dev_max) + return 0; /* should never happen */ + + STp = scsi_tapes[i]; + + options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0; + options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0; + options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0; + DEB( options |= debugging ? MT_ST_DEBUGGING : 0 ); + options |= STp->two_fm ? MT_ST_TWO_FM : 0; + options |= STp->fast_mteom ? MT_ST_FAST_MTEOM : 0; + options |= STm->defaults_for_writes ? MT_ST_DEF_WRITES : 0; + options |= STp->can_bsr ? MT_ST_CAN_BSR : 0; + options |= STp->omit_blklims ? MT_ST_NO_BLKLIMS : 0; + options |= STp->can_partitions ? MT_ST_CAN_PARTITIONS : 0; + options |= STp->scsi2_logical ? MT_ST_SCSI2LOGICAL : 0; + options |= STm->sysv ? MT_ST_SYSV : 0; + options |= STp->immediate ? MT_ST_NOWAIT : 0; + options |= STp->sili ? MT_ST_SILI : 0; + + l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options); + return l; +} + +CLASS_DEVICE_ATTR(options, S_IRUGO, st_options_show, NULL); + static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) { int i, rew, error; @@ -4370,6 +4442,9 @@ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) error = class_device_create_file(st_class_member, &class_device_attr_default_compression); if (error) goto out; + error = class_device_create_file(st_class_member, + &class_device_attr_options); + if (error) goto out; if (mode == 0 && rew == 0) { error = sysfs_create_link(&STp->device->sdev_gendev.kobj, diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index 5931726..b92712f 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h @@ -12,6 +12,7 @@ struct st_cmdstatus { int midlevel_result; struct scsi_sense_hdr sense_hdr; int have_sense; + int residual; u64 uremainder64; u8 flags; u8 remainder_valid; @@ -34,6 +35,7 @@ struct st_request { struct st_buffer { unsigned char dma; /* DMA-able buffer */ unsigned char do_dio; /* direct i/o set up? */ + unsigned char cleared; /* internal buffer cleared after open? */ int buffer_size; int buffer_blocks; int buffer_bytes; @@ -122,6 +124,7 @@ struct scsi_tape { unsigned char try_dio_now; /* try direct i/o before next close? */ unsigned char c_algo; /* compression algorithm */ unsigned char pos_unknown; /* after reset position unknown */ + unsigned char sili; /* use SILI when reading in variable b mode */ int tape_type; int long_timeout; /* timeout for commands known to take long time */ diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h index b6b5c9c..d2f9479 100644 --- a/drivers/scsi/st_options.h +++ b/drivers/scsi/st_options.h @@ -3,7 +3,7 @@ Copyright 1995-2003 Kai Makisara. - Last modified: Mon Apr 7 22:49:18 2003 by makisara + Last modified: Thu Feb 21 21:47:07 2008 by kai.makisara */ #ifndef _ST_OPTIONS_H @@ -94,6 +94,10 @@ The default is BSD semantics. */ #define ST_SYSV 0 +/* If ST_SILI is non-zero, the SILI bit is set when reading in variable block + mode and the block size is determined using the residual returned by the HBA. */ +#define ST_SILI 0 + /* Time to wait for the drive to become ready if blocking open */ #define ST_BLOCK_SECONDS 120 diff --git a/include/linux/mtio.h b/include/linux/mtio.h index 6f8d2d4..ef01d6a 100644 --- a/include/linux/mtio.h +++ b/include/linux/mtio.h @@ -192,6 +192,7 @@ struct mtpos { #define MT_ST_SCSI2LOGICAL 0x800 #define MT_ST_SYSV 0x1000 #define MT_ST_NOWAIT 0x2000 +#define MT_ST_SILI 0x4000 /* The mode parameters to be controlled. Parameter chosen with bits 20-28 */ #define MT_ST_CLEAR_DEFAULT 0xfffff diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 39e1cac..98724ba 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -677,4 +677,6 @@ extern void sas_ssp_task_response(struct device *dev, struct sas_task *task, struct ssp_response_iu *iu); struct sas_phy *sas_find_local_phy(struct domain_device *dev); +int sas_request_addr(struct Scsi_Host *shost, u8 *addr); + #endif /* _SASLIB_H_ */ diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 25071d5..37a7614 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -64,6 +64,7 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len, #define SCSI_TRY_RESET_DEVICE 1 #define SCSI_TRY_RESET_BUS 2 #define SCSI_TRY_RESET_HOST 3 +#define SCSI_TRY_RESET_TARGET 4 extern int scsi_reset_provider(struct scsi_device *, int); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 530ff4c..4913286 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -172,6 +172,7 @@ struct scsi_host_template { */ int (* eh_abort_handler)(struct scsi_cmnd *); int (* eh_device_reset_handler)(struct scsi_cmnd *); + int (* eh_target_reset_handler)(struct scsi_cmnd *); int (* eh_bus_reset_handler)(struct scsi_cmnd *); int (* eh_host_reset_handler)(struct scsi_cmnd *);