Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Sat, 5 May 2007 20:30:44 +0000 (13:30 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sat, 5 May 2007 20:30:44 +0000 (13:30 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (87 commits)
  [SCSI] fusion: fix domain validation loops
  [SCSI] qla2xxx: fix regression on sparc64
  [SCSI] modalias for scsi devices
  [SCSI] sg: cap reserved_size values at max_sectors
  [SCSI] BusLogic: stop using check_region
  [SCSI] tgt: fix rdma transfer bugs
  [SCSI] aacraid: fix aacraid not finding device
  [SCSI] aacraid: Correct SMC products in aacraid.txt
  [SCSI] scsi_error.c: Add EH Start Unit retry
  [SCSI] aacraid: [Fastboot] Panics for AACRAID driver during 'insmod' for kexec test.
  [SCSI] ipr: Driver version to 2.3.2
  [SCSI] ipr: Faster sg list fetch
  [SCSI] ipr: Return better qc_issue errors
  [SCSI] ipr: Disrupt device error
  [SCSI] ipr: Improve async error logging level control
  [SCSI] ipr: PCI unblock config access fix
  [SCSI] ipr: Fix for oops following SATA request sense
  [SCSI] ipr: Log error for SAS dual path switch
  [SCSI] ipr: Enable logging of debug error data for all devices
  [SCSI] ipr: Add new PCI-E IDs to device table
  ...

13 files changed:
1  2 
block/ll_rw_blk.c
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/aacraid/dpcsup.c
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/ipr.c
drivers/scsi/libsrp.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_transport_iscsi.c

diff --combined block/ll_rw_blk.c
@@@ -1221,7 -1221,7 +1221,7 @@@ void blk_recount_segments(request_queue
                 * considered part of another segment, since that might
                 * change with the bounce page.
                 */
 -              high = page_to_pfn(bv->bv_page) >= q->bounce_pfn;
 +              high = page_to_pfn(bv->bv_page) > q->bounce_pfn;
                if (high || highprv)
                        goto new_hw_segment;
                if (cluster) {
@@@ -1925,6 -1925,8 +1925,8 @@@ blk_init_queue_node(request_fn_proc *rf
        blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
        blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
  
+       q->sg_reserved_size = INT_MAX;
        /*
         * all done
         */
@@@ -3658,8 -3660,8 +3660,8 @@@ int __init blk_dev_init(void
        open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
        register_hotcpu_notifier(&blk_cpu_notifier);
  
 -      blk_max_low_pfn = max_low_pfn;
 -      blk_max_pfn = max_pfn;
 +      blk_max_low_pfn = max_low_pfn - 1;
 +      blk_max_pfn = max_pfn - 1;
  
        return 0;
  }
@@@ -3741,7 -3743,6 +3743,7 @@@ static struct io_context *current_io_co
                ret->nr_batch_requests = 0; /* because this is 0 */
                ret->aic = NULL;
                ret->cic_root.rb_node = NULL;
 +              ret->ioc_data = NULL;
                /* make sure set_task_ioprio() sees the settings above */
                smp_wmb();
                tsk->io_context = ret;
@@@ -201,7 -201,7 +201,7 @@@ static int iser_post_receive_control(st
         * what's common for both schemes is that the connection is not started
         */
        if (conn->c_stage != ISCSI_CONN_STARTED)
-               rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+               rx_data_size = ISCSI_DEF_MAX_RECV_SEG_LEN;
        else /* FIXME till user space sets conn->max_recv_dlength correctly */
                rx_data_size = 128;
  
@@@ -658,7 -658,6 +658,7 @@@ void iser_ctask_rdma_finalize(struct is
  {
        int deferred;
        int is_rdma_aligned = 1;
 +      struct iser_regd_buf *regd;
  
        /* if we were reading, copy back to unaligned sglist,
         * anyway dma_unmap and free the copy
        }
  
        if (iser_ctask->dir[ISER_DIR_IN]) {
 -              deferred = iser_regd_buff_release
 -                      (&iser_ctask->rdma_regd[ISER_DIR_IN]);
 +              regd = &iser_ctask->rdma_regd[ISER_DIR_IN];
 +              deferred = iser_regd_buff_release(regd);
                if (deferred) {
 -                      iser_err("References remain for BUF-IN rdma reg\n");
 -                      BUG();
 +                      iser_err("%d references remain for BUF-IN rdma reg\n",
 +                               atomic_read(&regd->ref_count));
                }
        }
  
        if (iser_ctask->dir[ISER_DIR_OUT]) {
 -              deferred = iser_regd_buff_release
 -                      (&iser_ctask->rdma_regd[ISER_DIR_OUT]);
 +              regd = &iser_ctask->rdma_regd[ISER_DIR_OUT];
 +              deferred = iser_regd_buff_release(regd);
                if (deferred) {
 -                      iser_err("References remain for BUF-OUT rdma reg\n");
 -                      BUG();
 +                      iser_err("%d references remain for BUF-OUT rdma reg\n",
 +                               atomic_read(&regd->ref_count));
                }
        }
  
diff --combined drivers/scsi/Kconfig
@@@ -241,6 -241,12 +241,12 @@@ config SCSI_SCAN_ASYN
          You can override this choice by specifying "scsi_mod.scan=sync"
          or async on the kernel's command line.
  
+ config SCSI_WAIT_SCAN
+       tristate
+       default m
+       depends on SCSI
+       depends on MODULES
  menu "SCSI Transports"
        depends on SCSI
  
@@@ -1194,17 -1200,6 +1200,6 @@@ config SCSI_NCR53C8XX_SYN
          There is no safe option other than using good cabling, right
          terminations and SCSI conformant devices.
  
- config SCSI_NCR53C8XX_PROFILE
-       bool "enable profiling"
-       depends on SCSI_ZALON || SCSI_NCR_Q720
-       help
-         This option allows you to enable profiling information gathering.
-         These statistics are not very accurate due to the low frequency
-         of the kernel clock (100 Hz on i386) and have performance impact
-         on systems that use very fast devices.
-         The normal answer therefore is N.
  config SCSI_NCR53C8XX_NO_DISCONNECT
        bool "not allow targets to disconnect"
        depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
@@@ -1334,11 -1329,6 +1329,6 @@@ config SCSI_SIM71
  
          It currently supports Compaq EISA cards and NCR MCA cards
  
- config 53C700_IO_MAPPED
-       bool
-       depends on SCSI_SIM710
-       default y
  config SCSI_SYM53C416
        tristate "Symbios 53c416 SCSI support"
        depends on ISA && SCSI
@@@ -1649,7 -1639,7 +1639,7 @@@ config OKTAGON_SCS
  
  config ATARI_SCSI
        tristate "Atari native SCSI support"
 -      depends on ATARI && SCSI && BROKEN
 +      depends on ATARI && SCSI
        select SCSI_SPI_ATTRS
        ---help---
          If you have an Atari with built-in NCR5380 SCSI controller (TT,
@@@ -1763,15 -1753,9 +1753,15 @@@ config SUN3X_ES
          The ESP was an on-board SCSI controller used on Sun 3/80
          machines.  Say Y here to compile in support for it.
  
 +config SCSI_ESP_CORE
 +      tristate "ESP Scsi Driver Core"
 +      depends on SCSI
 +      select SCSI_SPI_ATTRS
 +
  config SCSI_SUNESP
        tristate "Sparc ESP Scsi Driver"
        depends on SBUS && SCSI
 +      select SCSI_ESP_CORE
        help
          This is the driver for the Sun ESP SCSI host adapter. The ESP
          chipset is present in most SPARC SBUS-based computers.
diff --combined drivers/scsi/Makefile
@@@ -106,8 -106,7 +106,8 @@@ obj-$(CONFIG_MEGARAID_LEGACY)      += megara
  obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
  obj-$(CONFIG_MEGARAID_SAS)    += megaraid/
  obj-$(CONFIG_SCSI_ACARD)      += atp870u.o
 -obj-$(CONFIG_SCSI_SUNESP)     += esp.o
 +obj-$(CONFIG_SCSI_ESP_CORE)   += esp_scsi.o
 +obj-$(CONFIG_SCSI_SUNESP)     += sun_esp.o
  obj-$(CONFIG_SCSI_GDTH)               += gdth.o
  obj-$(CONFIG_SCSI_INITIO)     += initio.o
  obj-$(CONFIG_SCSI_INIA100)    += a100u2w.o
@@@ -146,7 -145,7 +146,7 @@@ obj-$(CONFIG_CHR_DEV_SCH)  += ch.
  # This goes last, so that "real" scsi devices probe earlier
  obj-$(CONFIG_SCSI_DEBUG)      += scsi_debug.o
  
- obj-$(CONFIG_SCSI)            += scsi_wait_scan.o
+ obj-$(CONFIG_SCSI_WAIT_SCAN)  += scsi_wait_scan.o
  
  scsi_mod-y                    += scsi.o hosts.o scsi_ioctl.o constants.o \
                                   scsicam.o scsi_error.o scsi_lib.o \
@@@ -5,7 -5,7 +5,7 @@@
   * based on the old aacraid driver that is..
   * Adaptec aacraid device driver for Linux.
   *
-  * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+  * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
@@@ -32,6 -32,7 +32,6 @@@
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/types.h>
 -#include <linux/pci.h>
  #include <linux/spinlock.h>
  #include <linux/slab.h>
  #include <linux/completion.h>
@@@ -72,7 -73,7 +72,7 @@@ unsigned int aac_response_normal(struc
                u32 index = le32_to_cpu(entry->addr);
                fast = index & 0x01;
                fib = &dev->fibs[index >> 2];
-               hwfib = fib->hw_fib;
+               hwfib = fib->hw_fib_va;
                
                aac_consumer_free(dev, q, HostNormRespQueue);
                /*
                 *      continue. The caller has already been notified that
                 *      the fib timed out.
                 */
-               if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
-                       dev->queues->queue[AdapNormCmdQueue].numpending--;
-               else {
-                       printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
-                       printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
+               dev->queues->queue[AdapNormCmdQueue].numpending--;
+               if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
+                       spin_unlock_irqrestore(q->lock, flags);
+                       aac_fib_complete(fib);
+                       aac_fib_free(fib);
+                       spin_lock_irqsave(q->lock, flags);
                        continue;
                }
                spin_unlock_irqrestore(q->lock, flags);
@@@ -192,7 -195,7 +194,7 @@@ unsigned int aac_command_normal(struct 
                INIT_LIST_HEAD(&fib->fiblink);
                fib->type = FSAFS_NTC_FIB_CONTEXT;
                fib->size = sizeof(struct fib);
-               fib->hw_fib = hw_fib;
+               fib->hw_fib_va = hw_fib;
                fib->data = hw_fib->data;
                fib->dev = dev;
                
@@@ -253,12 -256,13 +255,13 @@@ unsigned int aac_intr_normal(struct aac
                        return 1;
                }
                memset(hw_fib, 0, sizeof(struct hw_fib));
-               memcpy(hw_fib, (struct hw_fib *)(((unsigned long)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib));
+               memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) +
+                 (index & ~0x00000002L)), sizeof(struct hw_fib));
                memset(fib, 0, sizeof(struct fib));
                INIT_LIST_HEAD(&fib->fiblink);
                fib->type = FSAFS_NTC_FIB_CONTEXT;
                fib->size = sizeof(struct fib);
-               fib->hw_fib = hw_fib;
+               fib->hw_fib_va = hw_fib;
                fib->data = hw_fib->data;
                fib->dev = dev;
        
        } else {
                int fast = index & 0x01;
                struct fib * fib = &dev->fibs[index >> 2];
-               struct hw_fib * hwfib = fib->hw_fib;
+               struct hw_fib * hwfib = fib->hw_fib_va;
  
                /*
                 *      Remove this fib from the Outstanding I/O queue.
                 *      continue. The caller has already been notified that
                 *      the fib timed out.
                 */
-               if ((fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
-                       printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
-                       printk(KERN_DEBUG"aacraid: hwfib=%p index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
+               dev->queues->queue[AdapNormCmdQueue].numpending--;
+               if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
+                       aac_fib_complete(fib);
+                       aac_fib_free(fib);
                        return 0;
                }
  
-               dev->queues->queue[AdapNormCmdQueue].numpending--;
                if (fast) {
                        /*
                         *      Doctor the fib
@@@ -35,7 -35,7 +35,7 @@@
  #include "ibmvscsi.h"
  
  #define       INITIAL_SRP_LIMIT       16
- #define       DEFAULT_MAX_SECTORS     512
+ #define       DEFAULT_MAX_SECTORS     256
  
  #define       TGT_NAME        "ibmvstgt"
  
@@@ -248,8 -248,8 +248,8 @@@ static int ibmvstgt_rdma(struct scsi_cm
                                                  md[i].va + mdone);
  
                        if (err != H_SUCCESS) {
-                               eprintk("rdma error %d %d\n", dir, slen);
-                               goto out;
+                               eprintk("rdma error %d %d %ld\n", dir, slen, err);
+                               return -EIO;
                        }
  
                        mlen -= slen;
                                if (sidx > nsg) {
                                        eprintk("out of sg %p %d %d\n",
                                                iue, sidx, nsg);
-                                       goto out;
+                                       return -EIO;
                                }
                        }
                };
  
                rest -= mlen;
        }
- out:
        return 0;
  }
  
- static int ibmvstgt_transfer_data(struct scsi_cmnd *sc,
-                                 void (*done)(struct scsi_cmnd *))
- {
-       struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
-       int err;
-       err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
-       done(sc);
-       return err;
- }
  static int ibmvstgt_cmd_done(struct scsi_cmnd *sc,
                             void (*done)(struct scsi_cmnd *))
  {
        unsigned long flags;
        struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
        struct srp_target *target = iue->target;
+       int err = 0;
  
-       dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
+       dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0],
+               cmd->usg_sg);
+       if (sc->use_sg)
+               err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
  
        spin_lock_irqsave(&target->lock, flags);
        list_del(&iue->ilist);
        spin_unlock_irqrestore(&target->lock, flags);
  
-       if (sc->result != SAM_STAT_GOOD) {
+       if (err|| sc->result != SAM_STAT_GOOD) {
                eprintk("operation failed %p %d %x\n",
                        iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]);
                send_rsp(iue, sc, HARDWARE_ERROR, 0x00);
@@@ -503,7 -493,8 +493,8 @@@ static void process_iu(struct viosrp_cr
  {
        struct vio_port *vport = target_to_port(target);
        struct iu_entry *iue;
-       long err, done;
+       long err;
+       int done = 1;
  
        iue = srp_iu_get(target);
        if (!iue) {
  
        if (err != H_SUCCESS) {
                eprintk("%ld transferring data error %p\n", err, iue);
-               done = 1;
                goto out;
        }
  
@@@ -794,7 -784,6 +784,6 @@@ static struct scsi_host_template ibmvst
        .use_clustering         = DISABLE_CLUSTERING,
        .max_sectors            = DEFAULT_MAX_SECTORS,
        .transfer_response      = ibmvstgt_cmd_done,
-       .transfer_data          = ibmvstgt_transfer_data,
        .eh_abort_handler       = ibmvstgt_eh_abort_handler,
        .tsk_mgmt_response      = ibmvstgt_tsk_mgmt_response,
        .shost_attrs            = ibmvstgt_attrs,
@@@ -897,9 -886,9 +886,9 @@@ static int get_system_info(void
  {
        struct device_node *rootdn;
        const char *id, *model, *name;
 -      unsigned int *num;
 +      const unsigned int *num;
  
 -      rootdn = find_path_device("/");
 +      rootdn = of_find_node_by_path("/");
        if (!rootdn)
                return -ENOENT;
  
        if (name)
                strncpy(partition_name, name, sizeof(partition_name));
  
 -      num = (unsigned int *) get_property(rootdn, "ibm,partition-no", NULL);
 +      num = get_property(rootdn, "ibm,partition-no", NULL);
        if (num)
                partition_number = *num;
  
 +      of_node_put(rootdn);
        return 0;
  }
  
diff --combined drivers/scsi/ipr.c
@@@ -89,10 -89,9 +89,9 @@@ static unsigned int ipr_log_level = IPR
  static unsigned int ipr_max_speed = 1;
  static int ipr_testmode = 0;
  static unsigned int ipr_fastfail = 0;
- static unsigned int ipr_transop_timeout = IPR_OPERATIONAL_TIMEOUT;
+ static unsigned int ipr_transop_timeout = 0;
  static unsigned int ipr_enable_cache = 1;
  static unsigned int ipr_debug = 0;
- static int ipr_auto_create = 1;
  static DEFINE_SPINLOCK(ipr_driver_lock);
  
  /* This table describes the differences between DMA controller chips */
@@@ -159,15 -158,13 +158,13 @@@ module_param_named(enable_cache, ipr_en
  MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)");
  module_param_named(debug, ipr_debug, int, 0);
  MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
- module_param_named(auto_create, ipr_auto_create, int, 0);
- MODULE_PARM_DESC(auto_create, "Auto-create single device RAID 0 arrays when initialized (default: 1)");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(IPR_DRIVER_VERSION);
  
  /*  A constant array of IOASCs/URCs/Error Messages */
  static const
  struct ipr_error_table_t ipr_error_table[] = {
-       {0x00000000, 1, 1,
+       {0x00000000, 1, IPR_DEFAULT_LOG_LEVEL,
        "8155: An unknown error was received"},
        {0x00330000, 0, 0,
        "Soft underlength error"},
        "Command to be cancelled not found"},
        {0x00808000, 0, 0,
        "Qualified success"},
-       {0x01080000, 1, 1,
+       {0x01080000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFFE: Soft device bus error recovered by the IOA"},
-       {0x01088100, 0, 1,
+       {0x01088100, 0, IPR_DEFAULT_LOG_LEVEL,
        "4101: Soft device bus fabric error"},
-       {0x01170600, 0, 1,
+       {0x01170600, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF9: Device sector reassign successful"},
-       {0x01170900, 0, 1,
+       {0x01170900, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF7: Media error recovered by device rewrite procedures"},
-       {0x01180200, 0, 1,
+       {0x01180200, 0, IPR_DEFAULT_LOG_LEVEL,
        "7001: IOA sector reassignment successful"},
-       {0x01180500, 0, 1,
+       {0x01180500, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF9: Soft media error. Sector reassignment recommended"},
-       {0x01180600, 0, 1,
+       {0x01180600, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF7: Media error recovered by IOA rewrite procedures"},
-       {0x01418000, 0, 1,
+       {0x01418000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FF3D: Soft PCI bus error recovered by the IOA"},
-       {0x01440000, 1, 1,
+       {0x01440000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFF6: Device hardware error recovered by the IOA"},
-       {0x01448100, 0, 1,
+       {0x01448100, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF6: Device hardware error recovered by the device"},
-       {0x01448200, 1, 1,
+       {0x01448200, 1, IPR_DEFAULT_LOG_LEVEL,
        "FF3D: Soft IOA error recovered by the IOA"},
-       {0x01448300, 0, 1,
+       {0x01448300, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFFA: Undefined device response recovered by the IOA"},
-       {0x014A0000, 1, 1,
+       {0x014A0000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFF6: Device bus error, message or command phase"},
-       {0x014A8000, 0, 1,
+       {0x014A8000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFFE: Task Management Function failed"},
-       {0x015D0000, 0, 1,
+       {0x015D0000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF6: Failure prediction threshold exceeded"},
-       {0x015D9200, 0, 1,
+       {0x015D9200, 0, IPR_DEFAULT_LOG_LEVEL,
        "8009: Impending cache battery pack failure"},
        {0x02040400, 0, 0,
        "34FF: Disk device format in progress"},
        "No ready, IOA shutdown"},
        {0x025A0000, 0, 0,
        "Not ready, IOA has been shutdown"},
-       {0x02670100, 0, 1,
+       {0x02670100, 0, IPR_DEFAULT_LOG_LEVEL,
        "3020: Storage subsystem configuration error"},
        {0x03110B00, 0, 0,
        "FFF5: Medium error, data unreadable, recommend reassign"},
        {0x03110C00, 0, 0,
        "7000: Medium error, data unreadable, do not reassign"},
-       {0x03310000, 0, 1,
+       {0x03310000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF3: Disk media format bad"},
-       {0x04050000, 0, 1,
+       {0x04050000, 0, IPR_DEFAULT_LOG_LEVEL,
        "3002: Addressed device failed to respond to selection"},
-       {0x04080000, 1, 1,
+       {0x04080000, 1, IPR_DEFAULT_LOG_LEVEL,
        "3100: Device bus error"},
-       {0x04080100, 0, 1,
+       {0x04080100, 0, IPR_DEFAULT_LOG_LEVEL,
        "3109: IOA timed out a device command"},
        {0x04088000, 0, 0,
        "3120: SCSI bus is not operational"},
-       {0x04088100, 0, 1,
+       {0x04088100, 0, IPR_DEFAULT_LOG_LEVEL,
        "4100: Hard device bus fabric error"},
-       {0x04118000, 0, 1,
+       {0x04118000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9000: IOA reserved area data check"},
-       {0x04118100, 0, 1,
+       {0x04118100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9001: IOA reserved area invalid data pattern"},
-       {0x04118200, 0, 1,
+       {0x04118200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9002: IOA reserved area LRC error"},
-       {0x04320000, 0, 1,
+       {0x04320000, 0, IPR_DEFAULT_LOG_LEVEL,
        "102E: Out of alternate sectors for disk storage"},
-       {0x04330000, 1, 1,
+       {0x04330000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFF4: Data transfer underlength error"},
-       {0x04338000, 1, 1,
+       {0x04338000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFF4: Data transfer overlength error"},
-       {0x043E0100, 0, 1,
+       {0x043E0100, 0, IPR_DEFAULT_LOG_LEVEL,
        "3400: Logical unit failure"},
-       {0x04408500, 0, 1,
+       {0x04408500, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF4: Device microcode is corrupt"},
-       {0x04418000, 1, 1,
+       {0x04418000, 1, IPR_DEFAULT_LOG_LEVEL,
        "8150: PCI bus error"},
        {0x04430000, 1, 0,
        "Unsupported device bus message received"},
-       {0x04440000, 1, 1,
+       {0x04440000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFF4: Disk device problem"},
-       {0x04448200, 1, 1,
+       {0x04448200, 1, IPR_DEFAULT_LOG_LEVEL,
        "8150: Permanent IOA failure"},
-       {0x04448300, 0, 1,
+       {0x04448300, 0, IPR_DEFAULT_LOG_LEVEL,
        "3010: Disk device returned wrong response to IOA"},
-       {0x04448400, 0, 1,
+       {0x04448400, 0, IPR_DEFAULT_LOG_LEVEL,
        "8151: IOA microcode error"},
        {0x04448500, 0, 0,
        "Device bus status error"},
-       {0x04448600, 0, 1,
+       {0x04448600, 0, IPR_DEFAULT_LOG_LEVEL,
        "8157: IOA error requiring IOA reset to recover"},
        {0x04448700, 0, 0,
        "ATA device status error"},
        {0x04490000, 0, 0,
        "Message reject received from the device"},
-       {0x04449200, 0, 1,
+       {0x04449200, 0, IPR_DEFAULT_LOG_LEVEL,
        "8008: A permanent cache battery pack failure occurred"},
-       {0x0444A000, 0, 1,
+       {0x0444A000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9090: Disk unit has been modified after the last known status"},
-       {0x0444A200, 0, 1,
+       {0x0444A200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9081: IOA detected device error"},
-       {0x0444A300, 0, 1,
+       {0x0444A300, 0, IPR_DEFAULT_LOG_LEVEL,
        "9082: IOA detected device error"},
-       {0x044A0000, 1, 1,
+       {0x044A0000, 1, IPR_DEFAULT_LOG_LEVEL,
        "3110: Device bus error, message or command phase"},
-       {0x044A8000, 1, 1,
+       {0x044A8000, 1, IPR_DEFAULT_LOG_LEVEL,
        "3110: SAS Command / Task Management Function failed"},
-       {0x04670400, 0, 1,
+       {0x04670400, 0, IPR_DEFAULT_LOG_LEVEL,
        "9091: Incorrect hardware configuration change has been detected"},
-       {0x04678000, 0, 1,
+       {0x04678000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9073: Invalid multi-adapter configuration"},
-       {0x04678100, 0, 1,
+       {0x04678100, 0, IPR_DEFAULT_LOG_LEVEL,
        "4010: Incorrect connection between cascaded expanders"},
-       {0x04678200, 0, 1,
+       {0x04678200, 0, IPR_DEFAULT_LOG_LEVEL,
        "4020: Connections exceed IOA design limits"},
-       {0x04678300, 0, 1,
+       {0x04678300, 0, IPR_DEFAULT_LOG_LEVEL,
        "4030: Incorrect multipath connection"},
-       {0x04679000, 0, 1,
+       {0x04679000, 0, IPR_DEFAULT_LOG_LEVEL,
        "4110: Unsupported enclosure function"},
-       {0x046E0000, 0, 1,
+       {0x046E0000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF4: Command to logical unit failed"},
        {0x05240000, 1, 0,
        "Illegal request, invalid request type or request packet"},
        "Illegal request, command sequence error"},
        {0x052C8000, 1, 0,
        "Illegal request, dual adapter support not enabled"},
-       {0x06040500, 0, 1,
+       {0x06040500, 0, IPR_DEFAULT_LOG_LEVEL,
        "9031: Array protection temporarily suspended, protection resuming"},
-       {0x06040600, 0, 1,
+       {0x06040600, 0, IPR_DEFAULT_LOG_LEVEL,
        "9040: Array protection temporarily suspended, protection resuming"},
-       {0x06288000, 0, 1,
+       {0x06288000, 0, IPR_DEFAULT_LOG_LEVEL,
        "3140: Device bus not ready to ready transition"},
-       {0x06290000, 0, 1,
+       {0x06290000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFFB: SCSI bus was reset"},
        {0x06290500, 0, 0,
        "FFFE: SCSI bus transition to single ended"},
        {0x06290600, 0, 0,
        "FFFE: SCSI bus transition to LVD"},
-       {0x06298000, 0, 1,
+       {0x06298000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFFB: SCSI bus was reset by another initiator"},
-       {0x063F0300, 0, 1,
+       {0x063F0300, 0, IPR_DEFAULT_LOG_LEVEL,
        "3029: A device replacement has occurred"},
-       {0x064C8000, 0, 1,
+       {0x064C8000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9051: IOA cache data exists for a missing or failed device"},
-       {0x064C8100, 0, 1,
+       {0x064C8100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9055: Auxiliary cache IOA contains cache data needed by the primary IOA"},
-       {0x06670100, 0, 1,
+       {0x06670100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9025: Disk unit is not supported at its physical location"},
-       {0x06670600, 0, 1,
+       {0x06670600, 0, IPR_DEFAULT_LOG_LEVEL,
        "3020: IOA detected a SCSI bus configuration error"},
-       {0x06678000, 0, 1,
+       {0x06678000, 0, IPR_DEFAULT_LOG_LEVEL,
        "3150: SCSI bus configuration error"},
-       {0x06678100, 0, 1,
+       {0x06678100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9074: Asymmetric advanced function disk configuration"},
-       {0x06678300, 0, 1,
+       {0x06678300, 0, IPR_DEFAULT_LOG_LEVEL,
        "4040: Incomplete multipath connection between IOA and enclosure"},
-       {0x06678400, 0, 1,
+       {0x06678400, 0, IPR_DEFAULT_LOG_LEVEL,
        "4041: Incomplete multipath connection between enclosure and device"},
-       {0x06678500, 0, 1,
+       {0x06678500, 0, IPR_DEFAULT_LOG_LEVEL,
        "9075: Incomplete multipath connection between IOA and remote IOA"},
-       {0x06678600, 0, 1,
+       {0x06678600, 0, IPR_DEFAULT_LOG_LEVEL,
        "9076: Configuration error, missing remote IOA"},
-       {0x06679100, 0, 1,
+       {0x06679100, 0, IPR_DEFAULT_LOG_LEVEL,
        "4050: Enclosure does not support a required multipath function"},
-       {0x06690200, 0, 1,
+       {0x06690200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9041: Array protection temporarily suspended"},
-       {0x06698200, 0, 1,
+       {0x06698200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9042: Corrupt array parity detected on specified device"},
-       {0x066B0200, 0, 1,
+       {0x066B0200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9030: Array no longer protected due to missing or failed disk unit"},
-       {0x066B8000, 0, 1,
+       {0x066B8000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9071: Link operational transition"},
-       {0x066B8100, 0, 1,
+       {0x066B8100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9072: Link not operational transition"},
-       {0x066B8200, 0, 1,
+       {0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9032: Array exposed but still protected"},
-       {0x066B9100, 0, 1,
+       {0x066B8300, 0, IPR_DEFAULT_LOG_LEVEL + 1,
+       "70DD: Device forced failed by disrupt device command"},
+       {0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL,
        "4061: Multipath redundancy level got better"},
-       {0x066B9200, 0, 1,
+       {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL,
        "4060: Multipath redundancy level got worse"},
        {0x07270000, 0, 0,
        "Failure due to other device"},
-       {0x07278000, 0, 1,
+       {0x07278000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9008: IOA does not support functions expected by devices"},
-       {0x07278100, 0, 1,
+       {0x07278100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9010: Cache data associated with attached devices cannot be found"},
-       {0x07278200, 0, 1,
+       {0x07278200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9011: Cache data belongs to devices other than those attached"},
-       {0x07278400, 0, 1,
+       {0x07278400, 0, IPR_DEFAULT_LOG_LEVEL,
        "9020: Array missing 2 or more devices with only 1 device present"},
-       {0x07278500, 0, 1,
+       {0x07278500, 0, IPR_DEFAULT_LOG_LEVEL,
        "9021: Array missing 2 or more devices with 2 or more devices present"},
-       {0x07278600, 0, 1,
+       {0x07278600, 0, IPR_DEFAULT_LOG_LEVEL,
        "9022: Exposed array is missing a required device"},
-       {0x07278700, 0, 1,
+       {0x07278700, 0, IPR_DEFAULT_LOG_LEVEL,
        "9023: Array member(s) not at required physical locations"},
-       {0x07278800, 0, 1,
+       {0x07278800, 0, IPR_DEFAULT_LOG_LEVEL,
        "9024: Array not functional due to present hardware configuration"},
-       {0x07278900, 0, 1,
+       {0x07278900, 0, IPR_DEFAULT_LOG_LEVEL,
        "9026: Array not functional due to present hardware configuration"},
-       {0x07278A00, 0, 1,
+       {0x07278A00, 0, IPR_DEFAULT_LOG_LEVEL,
        "9027: Array is missing a device and parity is out of sync"},
-       {0x07278B00, 0, 1,
+       {0x07278B00, 0, IPR_DEFAULT_LOG_LEVEL,
        "9028: Maximum number of arrays already exist"},
-       {0x07278C00, 0, 1,
+       {0x07278C00, 0, IPR_DEFAULT_LOG_LEVEL,
        "9050: Required cache data cannot be located for a disk unit"},
-       {0x07278D00, 0, 1,
+       {0x07278D00, 0, IPR_DEFAULT_LOG_LEVEL,
        "9052: Cache data exists for a device that has been modified"},
-       {0x07278F00, 0, 1,
+       {0x07278F00, 0, IPR_DEFAULT_LOG_LEVEL,
        "9054: IOA resources not available due to previous problems"},
-       {0x07279100, 0, 1,
+       {0x07279100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9092: Disk unit requires initialization before use"},
-       {0x07279200, 0, 1,
+       {0x07279200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9029: Incorrect hardware configuration change has been detected"},
-       {0x07279600, 0, 1,
+       {0x07279600, 0, IPR_DEFAULT_LOG_LEVEL,
        "9060: One or more disk pairs are missing from an array"},
-       {0x07279700, 0, 1,
+       {0x07279700, 0, IPR_DEFAULT_LOG_LEVEL,
        "9061: One or more disks are missing from an array"},
-       {0x07279800, 0, 1,
+       {0x07279800, 0, IPR_DEFAULT_LOG_LEVEL,
        "9062: One or more disks are missing from an array"},
-       {0x07279900, 0, 1,
+       {0x07279900, 0, IPR_DEFAULT_LOG_LEVEL,
        "9063: Maximum number of functional arrays has been exceeded"},
        {0x0B260000, 0, 0,
        "Aborted command, invalid descriptor"},
@@@ -481,12 -480,16 +480,16 @@@ static void ipr_reinit_ipr_cmnd(struct 
  {
        struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
        struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+       dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr);
  
        memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
        ioarcb->write_data_transfer_length = 0;
        ioarcb->read_data_transfer_length = 0;
        ioarcb->write_ioadl_len = 0;
        ioarcb->read_ioadl_len = 0;
+       ioarcb->write_ioadl_addr =
+               cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl));
+       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
        ioasa->ioasc = 0;
        ioasa->residual_data_len = 0;
        ioasa->u.gata.status = 0;
@@@ -1610,7 -1613,7 +1613,7 @@@ static void ipr_handle_log_data(struct 
        /* Set indication we have logged an error */
        ioa_cfg->errors_logged++;
  
-       if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL)
+       if (ioa_cfg->log_level < ipr_error_table[error_index].log_hcam)
                return;
        if (be32_to_cpu(hostrcb->hcam.length) > sizeof(hostrcb->hcam.u.raw))
                hostrcb->hcam.length = cpu_to_be32(sizeof(hostrcb->hcam.u.raw));
@@@ -3770,8 -3773,7 +3773,8 @@@ static int ipr_device_reset(struct ipr_
   * Return value:
   *    0 on success / non-zero on failure
   **/
 -static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes)
 +static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes,
 +                              unsigned long deadline)
  {
        struct ipr_sata_port *sata_port = ap->private_data;
        struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg;
@@@ -3850,6 -3852,8 +3853,8 @@@ static int __ipr_eh_dev_reset(struct sc
                if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) {
                        if (ipr_cmd->scsi_cmd)
                                ipr_cmd->done = ipr_scsi_eh_done;
+                       if (ipr_cmd->qc)
+                               ipr_cmd->done = ipr_sata_eh_done;
                        if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) {
                                ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
                                ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
@@@ -4230,6 -4234,14 +4235,14 @@@ static int ipr_build_ioadl(struct ipr_i
  
                sglist = scsi_cmd->request_buffer;
  
+               if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
+                       ioadl = ioarcb->add_data.u.ioadl;
+                       ioarcb->write_ioadl_addr =
+                               cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+                                           offsetof(struct ipr_ioarcb, add_data));
+                       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
+               }
                for (i = 0; i < ipr_cmd->dma_use_sg; i++) {
                        ioadl[i].flags_and_data_len =
                                cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i]));
                                                     scsi_cmd->sc_data_direction);
  
                if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) {
+                       ioadl = ioarcb->add_data.u.ioadl;
+                       ioarcb->write_ioadl_addr =
+                               cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+                                           offsetof(struct ipr_ioarcb, add_data));
+                       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
                        ipr_cmd->dma_use_sg = 1;
                        ioadl[0].flags_and_data_len =
                                cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST);
@@@ -4346,11 -4363,9 +4364,9 @@@ static void ipr_erp_done(struct ipr_cmn
   **/
  static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
  {
-       struct ipr_ioarcb *ioarcb;
-       struct ipr_ioasa *ioasa;
-       ioarcb = &ipr_cmd->ioarcb;
-       ioasa = &ipr_cmd->ioasa;
+       struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+       struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+       dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr);
  
        memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
        ioarcb->write_data_transfer_length = 0;
        ioarcb->read_ioadl_len = 0;
        ioasa->ioasc = 0;
        ioasa->residual_data_len = 0;
+       ioarcb->write_ioadl_addr =
+               cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl));
+       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
  }
  
  /**
@@@ -4457,12 -4475,13 +4476,13 @@@ static void ipr_dump_ioasa(struct ipr_i
  {
        int i;
        u16 data_len;
-       u32 ioasc;
+       u32 ioasc, fd_ioasc;
        struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
        __be32 *ioasa_data = (__be32 *)ioasa;
        int error_index;
  
        ioasc = be32_to_cpu(ioasa->ioasc) & IPR_IOASC_IOASC_MASK;
+       fd_ioasc = be32_to_cpu(ioasa->fd_ioasc) & IPR_IOASC_IOASC_MASK;
  
        if (0 == ioasc)
                return;
        if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL)
                return;
  
-       error_index = ipr_get_error(ioasc);
+       if (ioasc == IPR_IOASC_BUS_WAS_RESET && fd_ioasc)
+               error_index = ipr_get_error(fd_ioasc);
+       else
+               error_index = ipr_get_error(ioasc);
  
        if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) {
                /* Don't log an error if the IOA already logged one */
                if (ioasa->ilid != 0)
                        return;
  
+               if (!ipr_is_gscsi(res))
+                       return;
                if (ipr_error_table[error_index].log_ioasa == 0)
                        return;
        }
@@@ -4636,11 -4661,11 +4662,11 @@@ static void ipr_erp_start(struct ipr_io
                return;
        }
  
-       if (ipr_is_gscsi(res))
-               ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
-       else
+       if (!ipr_is_gscsi(res))
                ipr_gen_sense(ipr_cmd);
  
+       ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
        switch (ioasc & IPR_IOASC_IOASC_MASK) {
        case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST:
                if (ipr_is_naca_model(res))
@@@ -5121,7 -5146,7 +5147,7 @@@ static unsigned int ipr_qc_issue(struc
        struct ipr_ioarcb_ata_regs *regs;
  
        if (unlikely(!ioa_cfg->allow_cmds || ioa_cfg->ioa_is_dead))
-               return -EIO;
+               return AC_ERR_SYSTEM;
  
        ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
        ioarcb = &ipr_cmd->ioarcb;
  
        default:
                WARN_ON(1);
-               return -1;
+               return AC_ERR_INVALID;
        }
  
        mb();
@@@ -6188,7 -6213,7 +6214,7 @@@ static int ipr_reset_enable_ioa(struct 
        dev_info(&ioa_cfg->pdev->dev, "Initializing IOA.\n");
  
        ipr_cmd->timer.data = (unsigned long) ipr_cmd;
-       ipr_cmd->timer.expires = jiffies + (ipr_transop_timeout * HZ);
+       ipr_cmd->timer.expires = jiffies + (ioa_cfg->transop_timeout * HZ);
        ipr_cmd->timer.function = (void (*)(unsigned long))ipr_oper_timeout;
        ipr_cmd->done = ipr_reset_ioa_job;
        add_timer(&ipr_cmd->timer);
@@@ -6385,6 -6410,7 +6411,7 @@@ static int ipr_reset_start_bist(struct 
        rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START);
  
        if (rc != PCIBIOS_SUCCESSFUL) {
+               pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
                ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
                rc = IPR_RC_JOB_CONTINUE;
        } else {
@@@ -7117,8 -7143,6 +7144,6 @@@ static void __devinit ipr_init_ioa_cfg(
        ioa_cfg->pdev = pdev;
        ioa_cfg->log_level = ipr_log_level;
        ioa_cfg->doorbell = IPR_DOORBELL;
-       if (!ipr_auto_create)
-               ioa_cfg->doorbell |= IPR_RUNTIME_RESET;
        sprintf(ioa_cfg->eye_catcher, IPR_EYECATCHER);
        sprintf(ioa_cfg->trace_start, IPR_TRACE_START_LABEL);
        sprintf(ioa_cfg->ipr_free_label, IPR_FREEQ_LABEL);
@@@ -7233,6 -7257,13 +7258,13 @@@ static int __devinit ipr_probe_ioa(stru
                goto out_scsi_host_put;
        }
  
+       if (ipr_transop_timeout)
+               ioa_cfg->transop_timeout = ipr_transop_timeout;
+       else if (dev_id->driver_data & IPR_USE_LONG_TRANSOP_TIMEOUT)
+               ioa_cfg->transop_timeout = IPR_LONG_OPERATIONAL_TIMEOUT;
+       else
+               ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT;
        ipr_regs_pci = pci_resource_start(pdev, 0);
  
        rc = pci_request_regions(pdev, IPR_NAME);
@@@ -7540,29 -7571,45 +7572,45 @@@ static struct pci_device_id ipr_pci_tab
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0, 0 },
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0,
+               IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
-             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
-             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0, 0 },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575D, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
-             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, 0 },
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, 0, 0, 0 },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, 0 },
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0,
+               IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, 0 },
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0,
+               IPR_USE_LONG_TRANSOP_TIMEOUT },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SCAMP_E,
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574D, 0, 0,
+               IPR_USE_LONG_TRANSOP_TIMEOUT },
        { }
  };
  MODULE_DEVICE_TABLE(pci, ipr_pci_table);
diff --combined drivers/scsi/libsrp.c
@@@ -22,6 -22,7 +22,6 @@@
  #include <linux/kfifo.h>
  #include <linux/scatterlist.h>
  #include <linux/dma-mapping.h>
 -#include <linux/pci.h>
  #include <scsi/scsi.h>
  #include <scsi/scsi_cmnd.h>
  #include <scsi/scsi_tcq.h>
@@@ -224,8 -225,7 +224,7 @@@ static int srp_indirect_data(struct scs
        struct srp_direct_buf *md = NULL;
        struct scatterlist dummy, *sg = NULL;
        dma_addr_t token = 0;
-       long err;
-       unsigned int done = 0;
+       int err = 0;
        int nmd, nsg = 0, len;
  
        if (dma_map || ext_desc) {
                sg_dma_address(&dummy) = token;
                err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE,
                              id->table_desc.len);
-               if (err < 0) {
-                       eprintk("Error copying indirect table %ld\n", err);
+               if (err) {
+                       eprintk("Error copying indirect table %d\n", err);
                        goto free_mem;
                }
        } else {
@@@ -271,6 -271,7 +270,7 @@@ rdma
                nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg, DMA_BIDIRECTIONAL);
                if (!nsg) {
                        eprintk("fail to map %p %d\n", iue, sc->use_sg);
+                       err = -EIO;
                        goto free_mem;
                }
                len = min(sc->request_bufflen, id->len);
@@@ -286,7 -287,7 +286,7 @@@ free_mem
        if (token && dma_map)
                dma_free_coherent(iue->target->dev, id->table_desc.len, md, token);
  
-       return done;
+       return err;
  }
  
  static int data_out_desc_size(struct srp_cmd *cmd)
@@@ -351,7 -352,7 +351,7 @@@ int srp_transfer_data(struct scsi_cmnd 
                break;
        default:
                eprintk("Unknown format %d %x\n", dir, format);
-               break;
+               err = -EINVAL;
        }
  
        return err;
@@@ -671,7 -671,7 +671,7 @@@ static in
  lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
  {
        uint8_t lenlo, lenhi;
-       uint32_t Length;
+       int Length;
        int i, j;
        int finished = 0;
        int index = 0;
@@@ -1817,9 -1817,10 +1817,9 @@@ static pci_ers_result_t lpfc_io_error_d
        struct lpfc_sli *psli = &phba->sli;
        struct lpfc_sli_ring  *pring;
  
 -      if (state == pci_channel_io_perm_failure) {
 -              lpfc_pci_remove_one(pdev);
 +      if (state == pci_channel_io_perm_failure)
                return PCI_ERS_RESULT_DISCONNECT;
 -      }
 +
        pci_disable_device(pdev);
        /*
         * There may be I/Os dropped by the firmware.
@@@ -184,10 -184,19 +184,19 @@@ int scsi_delete_timer(struct scsi_cmnd 
   **/
  void scsi_times_out(struct scsi_cmnd *scmd)
  {
+       enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
        scsi_log_completion(scmd, TIMEOUT_ERROR);
  
        if (scmd->device->host->transportt->eh_timed_out)
-               switch (scmd->device->host->transportt->eh_timed_out(scmd)) {
+               eh_timed_out = scmd->device->host->transportt->eh_timed_out;
+       else if (scmd->device->host->hostt->eh_timed_out)
+               eh_timed_out = scmd->device->host->hostt->eh_timed_out;
+       else
+               eh_timed_out = NULL;
+       if (eh_timed_out)
+               switch (eh_timed_out(scmd)) {
                case EH_HANDLED:
                        __scsi_done(scmd);
                        return;
@@@ -716,7 -725,7 +725,7 @@@ static int scsi_send_eh_cmnd(struct scs
         */
        if (copy_sense) {
                if (!SCSI_SENSE_VALID(scmd)) {
 -                      memcpy(scmd->sense_buffer, scmd->request_buffer,
 +                      memcpy(scmd->sense_buffer, page_address(sgl.page),
                               sizeof(scmd->sense_buffer));
                }
                __free_page(sgl.page);
@@@ -923,10 -932,12 +932,12 @@@ static int scsi_eh_try_stu(struct scsi_
        static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
  
        if (scmd->device->allow_restart) {
-               int rtn;
+               int i, rtn = NEEDS_RETRY;
+               for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
+                       rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
+                                               START_UNIT_TIMEOUT, 0);
  
-               rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
-                                       START_UNIT_TIMEOUT, 0);
                if (rtn == SUCCESS)
                        return 0;
        }
diff --combined drivers/scsi/scsi_lib.c
@@@ -31,7 -31,7 +31,7 @@@
  
  
  #define SG_MEMPOOL_NR         ARRAY_SIZE(scsi_sg_pools)
 -#define SG_MEMPOOL_SIZE               32
 +#define SG_MEMPOOL_SIZE               2
  
  struct scsi_host_sg_pool {
        size_t          size;
@@@ -848,8 -848,8 +848,8 @@@ void scsi_io_completion(struct scsi_cmn
                                memcpy(req->sense, cmd->sense_buffer,  len);
                                req->sense_len = len;
                        }
-               } else
-                       req->data_len = cmd->resid;
+               }
+               req->data_len = cmd->resid;
        }
  
        /*
        }
        if (result) {
                if (!(req->cmd_flags & REQ_QUIET)) {
-                       scmd_printk(KERN_INFO, cmd,
-                                   "SCSI error: return code = 0x%08x\n",
-                                   result);
+                       scsi_print_result(cmd);
                        if (driver_byte(result) & DRIVER_SENSE)
                                scsi_print_sense("", cmd);
                }
@@@ -276,8 -276,22 +276,22 @@@ static int scsi_bus_match(struct devic
        return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
  }
  
+ static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp,
+                          char *buffer, int buffer_size)
+ {
+       struct scsi_device *sdev = to_scsi_device(dev);
+       int i = 0;
+       int length = 0;
+       add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+                      "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
+       envp[i] = NULL;
+       return 0;
+ }
  static int scsi_bus_suspend(struct device * dev, pm_message_t state)
  {
+       struct device_driver *drv = dev->driver;
        struct scsi_device *sdev = to_scsi_device(dev);
        struct scsi_host_template *sht = sdev->host->hostt;
        int err;
        if (err)
                return err;
  
-       if (sht->suspend)
+       /* call HLD suspend first */
+       if (drv && drv->suspend) {
+               err = drv->suspend(dev, state);
+               if (err)
+                       return err;
+       }
+       /* then, call host suspend */
+       if (sht->suspend) {
                err = sht->suspend(sdev, state);
+               if (err) {
+                       if (drv && drv->resume)
+                               drv->resume(dev);
+                       return err;
+               }
+       }
  
-       return err;
+       return 0;
  }
  
  static int scsi_bus_resume(struct device * dev)
  {
+       struct device_driver *drv = dev->driver;
        struct scsi_device *sdev = to_scsi_device(dev);
        struct scsi_host_template *sht = sdev->host->hostt;
-       int err = 0;
+       int err = 0, err2 = 0;
  
+       /* call host resume first */
        if (sht->resume)
                err = sht->resume(sdev);
  
+       /* then, call HLD resume */
+       if (drv && drv->resume)
+               err2 = drv->resume(dev);
        scsi_device_resume(sdev);
-       return err;
+       /* favor LLD failure */
+       return err ? err : err2;;
  }
  
  struct bus_type scsi_bus_type = {
          .name         = "scsi",
          .match                = scsi_bus_match,
+       .uevent         = scsi_bus_uevent,
        .suspend        = scsi_bus_suspend,
        .resume         = scsi_bus_resume,
  };
@@@ -452,22 -489,10 +489,22 @@@ store_rescan_field (struct device *dev
  }
  static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
  
 +static void sdev_store_delete_callback(struct device *dev)
 +{
 +      scsi_remove_device(to_scsi_device(dev));
 +}
 +
  static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf,
                                 size_t count)
  {
 -      scsi_remove_device(to_scsi_device(dev));
 +      int rc;
 +
 +      /* An attribute cannot be unregistered by one of its own methods,
 +       * so we have to use this roundabout approach.
 +       */
 +      rc = device_schedule_callback(dev, sdev_store_delete_callback);
 +      if (rc)
 +              count = rc;
        return count;
  };
  static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
@@@ -547,6 -572,14 +584,14 @@@ show_sdev_iostat(iorequest_cnt)
  show_sdev_iostat(iodone_cnt);
  show_sdev_iostat(ioerr_cnt);
  
+ static ssize_t
+ sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+       struct scsi_device *sdev;
+       sdev = to_scsi_device(dev);
+       return snprintf (buf, 20, SCSI_DEVICE_MODALIAS_FMT "\n", sdev->type);
+ }
+ static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
  
  /* Default template for device attributes.  May NOT be modified */
  static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
        &dev_attr_iorequest_cnt,
        &dev_attr_iodone_cnt,
        &dev_attr_ioerr_cnt,
+       &dev_attr_modalias,
        NULL
  };
  
@@@ -49,7 -49,7 +49,7 @@@ struct iscsi_internal 
        struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
  };
  
- static int iscsi_session_nr;  /* sysfs session id for next new session */
+ static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
  
  /*
   * list of registered transports and lock that must
@@@ -300,7 -300,7 +300,7 @@@ int iscsi_add_session(struct iscsi_cls_
        int err;
  
        ihost = shost->shost_data;
-       session->sid = iscsi_session_nr++;
+       session->sid = atomic_add_return(1, &iscsi_session_nr);
        session->target_id = target_id;
  
        snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
@@@ -1081,7 -1081,7 +1081,7 @@@ iscsi_if_rx(struct sock *sk, int len
                        struct nlmsghdr *nlh;
                        struct iscsi_uevent *ev;
  
 -                      nlh = (struct nlmsghdr *)skb->data;
 +                      nlh = nlmsg_hdr(skb);
                        if (nlh->nlmsg_len < sizeof(*nlh) ||
                            skb->len < nlh->nlmsg_len) {
                                break;
@@@ -1419,6 -1419,8 +1419,8 @@@ static __init int iscsi_transport_init(
        printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
                ISCSI_TRANSPORT_VERSION);
  
+       atomic_set(&iscsi_session_nr, 0);
        err = class_register(&iscsi_transport_class);
        if (err)
                return err;
        if (err)
                goto unregister_conn_class;
  
 -      nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
 +      nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
                        THIS_MODULE);
        if (!nls) {
                err = -ENOBUFS;