[SCSI] libsas, libata: fix start of life for a sas ata_port
[linux-flexiantxendom0-3.2.10.git] / drivers / scsi / ipr.c
index 520461b..467dc38 100644 (file)
@@ -60,6 +60,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
@@ -103,7 +104,9 @@ static DEFINE_SPINLOCK(ipr_driver_lock);
 static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
        { /* Gemstone, Citrine, Obsidian, and Obsidian-E */
                .mailbox = 0x0042C,
+               .max_cmds = 100,
                .cache_line_size = 0x20,
+               .clear_isr = 1,
                {
                        .set_interrupt_mask_reg = 0x0022C,
                        .clr_interrupt_mask_reg = 0x00230,
@@ -125,7 +128,9 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
        },
        { /* Snipe and Scamp */
                .mailbox = 0x0052C,
+               .max_cmds = 100,
                .cache_line_size = 0x20,
+               .clear_isr = 1,
                {
                        .set_interrupt_mask_reg = 0x00288,
                        .clr_interrupt_mask_reg = 0x0028C,
@@ -146,8 +151,10 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
                }
        },
        { /* CRoC */
-               .mailbox = 0x00040,
+               .mailbox = 0x00044,
+               .max_cmds = 1000,
                .cache_line_size = 0x20,
+               .clear_isr = 0,
                {
                        .set_interrupt_mask_reg = 0x00010,
                        .clr_interrupt_mask_reg = 0x00018,
@@ -167,21 +174,22 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
                        .clr_uproc_interrupt_reg32 = 0x0002C,
                        .init_feedback_reg = 0x0005C,
                        .dump_addr_reg = 0x00064,
-                       .dump_data_reg = 0x00068
+                       .dump_data_reg = 0x00068,
+                       .endian_swap_reg = 0x00084
                }
        },
 };
 
 static const struct ipr_chip_t ipr_chip[] = {
-       { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] },
-       { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[0] },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, IPR_USE_MSI, IPR_SIS32, &ipr_chip_cfg[0] },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[1] },
-       { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, IPR_USE_LSI, IPR_SIS32, &ipr_chip_cfg[1] },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, IPR_USE_MSI, IPR_SIS64, &ipr_chip_cfg[2] },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2, IPR_USE_MSI, IPR_SIS64, &ipr_chip_cfg[2] }
+       { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] },
+       { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, IPR_USE_MSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[0] },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] },
+       { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] }
 };
 
 static int ipr_max_bus_speeds [] = {
@@ -567,7 +575,8 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd,
 static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
-       struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+       struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
+       struct ipr_ioasa64 *ioasa64 = &ipr_cmd->s.ioasa64;
        dma_addr_t dma_addr = ipr_cmd->dma_addr;
 
        memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
@@ -576,19 +585,19 @@ static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
        ioarcb->ioadl_len = 0;
        ioarcb->read_ioadl_len = 0;
 
-       if (ipr_cmd->ioa_cfg->sis64)
+       if (ipr_cmd->ioa_cfg->sis64) {
                ioarcb->u.sis64_addr_data.data_ioadl_addr =
                        cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64));
-       else {
+               ioasa64->u.gata.status = 0;
+       } else {
                ioarcb->write_ioadl_addr =
                        cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl));
                ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
+               ioasa->u.gata.status = 0;
        }
 
-       ioasa->ioasc = 0;
-       ioasa->residual_data_len = 0;
-       ioasa->u.gata.status = 0;
-
+       ioasa->hdr.ioasc = 0;
+       ioasa->hdr.residual_data_len = 0;
        ipr_cmd->scsi_cmd = NULL;
        ipr_cmd->qc = NULL;
        ipr_cmd->sense_buffer[0] = 0;
@@ -768,8 +777,8 @@ static void ipr_fail_all_ops(struct ipr_ioa_cfg *ioa_cfg)
        list_for_each_entry_safe(ipr_cmd, temp, &ioa_cfg->pending_q, queue) {
                list_del(&ipr_cmd->queue);
 
-               ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET);
-               ipr_cmd->ioasa.ilid = cpu_to_be32(IPR_DRIVER_ILID);
+               ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET);
+               ipr_cmd->s.ioasa.hdr.ilid = cpu_to_be32(IPR_DRIVER_ILID);
 
                if (ipr_cmd->scsi_cmd)
                        ipr_cmd->done = ipr_scsi_eh_done;
@@ -844,8 +853,6 @@ static void ipr_do_req(struct ipr_cmnd *ipr_cmd,
 
        ipr_trc_hook(ipr_cmd, IPR_TRACE_START, 0);
 
-       mb();
-
        ipr_send_command(ipr_cmd);
 }
 
@@ -979,8 +986,6 @@ static void ipr_send_hcam(struct ipr_ioa_cfg *ioa_cfg, u8 type,
 
                ipr_trc_hook(ipr_cmd, IPR_TRACE_START, IPR_IOA_RES_ADDR);
 
-               mb();
-
                ipr_send_command(ipr_cmd);
        } else {
                list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q);
@@ -1040,12 +1045,14 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res,
                proto = cfgtew->u.cfgte64->proto;
                res->res_flags = cfgtew->u.cfgte64->res_flags;
                res->qmodel = IPR_QUEUEING_MODEL64(res);
-               res->type = cfgtew->u.cfgte64->res_type & 0x0f;
+               res->type = cfgtew->u.cfgte64->res_type;
 
                memcpy(res->res_path, &cfgtew->u.cfgte64->res_path,
                        sizeof(res->res_path));
 
                res->bus = 0;
+               memcpy(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun,
+                       sizeof(res->dev_lun.scsi_lun));
                res->lun = scsilun_to_int(&res->dev_lun);
 
                if (res->type == IPR_RES_TYPE_GENERIC_SCSI) {
@@ -1061,9 +1068,6 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res,
                                                                  ioa_cfg->max_devs_supported);
                                set_bit(res->target, ioa_cfg->target_ids);
                        }
-
-                       memcpy(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun,
-                               sizeof(res->dev_lun.scsi_lun));
                } else if (res->type == IPR_RES_TYPE_IOAFP) {
                        res->bus = IPR_IOAFP_VIRTUAL_BUS;
                        res->target = 0;
@@ -1094,6 +1098,7 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res,
                res->bus = cfgtew->u.cfgte->res_addr.bus;
                res->target = cfgtew->u.cfgte->res_addr.target;
                res->lun = cfgtew->u.cfgte->res_addr.lun;
+               res->lun_wwn = get_unaligned_be64(cfgtew->u.cfgte->lun_wwn);
        }
 
        ipr_update_ata_class(res, proto);
@@ -1113,7 +1118,7 @@ static int ipr_is_same_device(struct ipr_resource_entry *res,
        if (res->ioa_cfg->sis64) {
                if (!memcmp(&res->dev_id, &cfgtew->u.cfgte64->dev_id,
                                        sizeof(cfgtew->u.cfgte64->dev_id)) &&
-                       !memcmp(&res->lun, &cfgtew->u.cfgte64->lun,
+                       !memcmp(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun,
                                        sizeof(cfgtew->u.cfgte64->lun))) {
                        return 1;
                }
@@ -1128,20 +1133,22 @@ static int ipr_is_same_device(struct ipr_resource_entry *res,
 }
 
 /**
- * ipr_format_resource_path - Format the resource path for printing.
+ * ipr_format_res_path - Format the resource path for printing.
  * @res_path:  resource path
  * @buf:       buffer
  *
  * Return value:
  *     pointer to buffer
  **/
-static char *ipr_format_resource_path(u8 *res_path, char *buffer)
+static char *ipr_format_res_path(u8 *res_path, char *buffer, int len)
 {
        int i;
+       char *p = buffer;
 
-       sprintf(buffer, "%02X", res_path[0]);
-       for (i=1; res_path[i] != 0xff; i++)
-               sprintf(buffer, "%s-%02X", buffer, res_path[i]);
+       *p = '\0';
+       p += snprintf(p, buffer + len - p, "%02X", res_path[0]);
+       for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++)
+               p += snprintf(p, buffer + len - p, "-%02X", res_path[i]);
 
        return buffer;
 }
@@ -1164,7 +1171,7 @@ static void ipr_update_res_entry(struct ipr_resource_entry *res,
        if (res->ioa_cfg->sis64) {
                res->flags = cfgtew->u.cfgte64->flags;
                res->res_flags = cfgtew->u.cfgte64->res_flags;
-               res->type = cfgtew->u.cfgte64->res_type & 0x0f;
+               res->type = cfgtew->u.cfgte64->res_type;
 
                memcpy(&res->std_inq_data, &cfgtew->u.cfgte64->std_inq_data,
                        sizeof(struct ipr_std_inq_data));
@@ -1186,7 +1193,8 @@ static void ipr_update_res_entry(struct ipr_resource_entry *res,
 
                if (res->sdev && new_path)
                        sdev_printk(KERN_INFO, res->sdev, "Resource path: %s\n",
-                                   ipr_format_resource_path(&res->res_path[0], &buffer[0]));
+                                   ipr_format_res_path(res->res_path, buffer,
+                                                       sizeof(buffer)));
        } else {
                res->flags = cfgtew->u.cfgte->flags;
                if (res->flags & IPR_IS_IOA_RESOURCE)
@@ -1296,7 +1304,7 @@ static void ipr_handle_config_change(struct ipr_ioa_cfg *ioa_cfg,
                        ipr_clear_res_target(res);
                        list_move_tail(&res->queue, &ioa_cfg->free_res_q);
                }
-       } else if (!res->sdev) {
+       } else if (!res->sdev || res->del_from_ml) {
                res->add_to_ml = 1;
                if (ioa_cfg->allow_ml_add_del)
                        schedule_work(&ioa_cfg->work_q);
@@ -1319,7 +1327,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
        struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
        list_del(&hostrcb->queue);
        list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
@@ -1572,7 +1580,8 @@ static void ipr_log_sis64_config_error(struct ipr_ioa_cfg *ioa_cfg,
                ipr_err_separator;
 
                ipr_err("Device %d : %s", i + 1,
-                        ipr_format_resource_path(&dev_entry->res_path[0], &buffer[0]));
+                        ipr_format_res_path(dev_entry->res_path, buffer,
+                                            sizeof(buffer)));
                ipr_log_ext_vpd(&dev_entry->vpd);
 
                ipr_err("-----New Device Information-----\n");
@@ -1664,7 +1673,7 @@ static void ipr_log_enhanced_array_error(struct ipr_ioa_cfg *ioa_cfg,
 
        array_entry = error->array_member;
        num_entries = min_t(u32, be32_to_cpu(error->num_entries),
-                           sizeof(error->array_member));
+                           ARRAY_SIZE(error->array_member));
 
        for (i = 0; i < num_entries; i++, array_entry++) {
                if (!memcmp(array_entry->vpd.vpd.sn, zero_sn, IPR_SERIAL_NUM_LEN))
@@ -1918,13 +1927,14 @@ static void ipr_log64_fabric_path(struct ipr_hostrcb *hostrcb,
 
                        ipr_hcam_err(hostrcb, "%s %s: Resource Path=%s\n",
                                     path_active_desc[i].desc, path_state_desc[j].desc,
-                                    ipr_format_resource_path(&fabric->res_path[0], &buffer[0]));
+                                    ipr_format_res_path(fabric->res_path, buffer,
+                                                        sizeof(buffer)));
                        return;
                }
        }
 
        ipr_err("Path state=%02X Resource Path=%s\n", path_state,
-               ipr_format_resource_path(&fabric->res_path[0], &buffer[0]));
+               ipr_format_res_path(fabric->res_path, buffer, sizeof(buffer)));
 }
 
 static const struct {
@@ -2065,7 +2075,8 @@ static void ipr_log64_path_elem(struct ipr_hostrcb *hostrcb,
 
                        ipr_hcam_err(hostrcb, "%s %s: Resource Path=%s, Link rate=%s, WWN=%08X%08X\n",
                                     path_status_desc[j].desc, path_type_desc[i].desc,
-                                    ipr_format_resource_path(&cfg->res_path[0], &buffer[0]),
+                                    ipr_format_res_path(cfg->res_path, buffer,
+                                                        sizeof(buffer)),
                                     link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
                                     be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
                        return;
@@ -2073,7 +2084,7 @@ static void ipr_log64_path_elem(struct ipr_hostrcb *hostrcb,
        }
        ipr_hcam_err(hostrcb, "Path element=%02X: Resource Path=%s, Link rate=%s "
                     "WWN=%08X%08X\n", cfg->type_status,
-                    ipr_format_resource_path(&cfg->res_path[0], &buffer[0]),
+                    ipr_format_res_path(cfg->res_path, buffer, sizeof(buffer)),
                     link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
                     be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
 }
@@ -2138,13 +2149,13 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg,
 
        ipr_err("RAID %s Array Configuration: %s\n",
                error->protection_level,
-               ipr_format_resource_path(&error->last_res_path[0], &buffer[0]));
+               ipr_format_res_path(error->last_res_path, buffer, sizeof(buffer)));
 
        ipr_err_separator;
 
        array_entry = error->array_member;
-       num_entries = min_t(u32, be32_to_cpu(error->num_entries),
-                           sizeof(error->array_member));
+       num_entries = min_t(u32, error->num_entries,
+                           ARRAY_SIZE(error->array_member));
 
        for (i = 0; i < num_entries; i++, array_entry++) {
 
@@ -2158,10 +2169,12 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg,
 
                ipr_err("Array Member %d:\n", i);
                ipr_log_ext_vpd(&array_entry->vpd);
-               ipr_err("Current Location: %s",
-                        ipr_format_resource_path(&array_entry->res_path[0], &buffer[0]));
-               ipr_err("Expected Location: %s",
-                        ipr_format_resource_path(&array_entry->expected_res_path[0], &buffer[0]));
+               ipr_err("Current Location: %s\n",
+                        ipr_format_res_path(array_entry->res_path, buffer,
+                                            sizeof(buffer)));
+               ipr_err("Expected Location: %s\n",
+                        ipr_format_res_path(array_entry->expected_res_path,
+                                            buffer, sizeof(buffer)));
 
                ipr_err_separator;
        }
@@ -2354,7 +2367,7 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
        struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
        u32 fd_ioasc;
 
        if (ioa_cfg->sis64)
@@ -2707,13 +2720,18 @@ static int ipr_sdt_copy(struct ipr_ioa_cfg *ioa_cfg,
                        unsigned long pci_address, u32 length)
 {
        int bytes_copied = 0;
-       int cur_len, rc, rem_len, rem_page_len;
+       int cur_len, rc, rem_len, rem_page_len, max_dump_size;
        __be32 *page;
        unsigned long lock_flags = 0;
        struct ipr_ioa_dump *ioa_dump = &ioa_cfg->dump->ioa_dump;
 
+       if (ioa_cfg->sis64)
+               max_dump_size = IPR_FMT3_MAX_IOA_DUMP_SIZE;
+       else
+               max_dump_size = IPR_FMT2_MAX_IOA_DUMP_SIZE;
+
        while (bytes_copied < length &&
-              (ioa_dump->hdr.len + bytes_copied) < IPR_MAX_IOA_DUMP_SIZE) {
+              (ioa_dump->hdr.len + bytes_copied) < max_dump_size) {
                if (ioa_dump->page_offset >= PAGE_SIZE ||
                    ioa_dump->page_offset == 0) {
                        page = (__be32 *)__get_free_page(GFP_ATOMIC);
@@ -2875,8 +2893,8 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
        unsigned long lock_flags = 0;
        struct ipr_driver_dump *driver_dump = &dump->driver_dump;
        struct ipr_ioa_dump *ioa_dump = &dump->ioa_dump;
-       u32 num_entries, start_off, end_off;
-       u32 bytes_to_copy, bytes_copied, rc;
+       u32 num_entries, max_num_entries, start_off, end_off;
+       u32 max_dump_size, bytes_to_copy, bytes_copied, rc;
        struct ipr_sdt *sdt;
        int valid = 1;
        int i;
@@ -2885,11 +2903,17 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
 
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 
-       if (ioa_cfg->sdt_state != GET_DUMP) {
+       if (ioa_cfg->sdt_state != READ_DUMP) {
                spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
                return;
        }
 
+       if (ioa_cfg->sis64) {
+               spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+               ssleep(IPR_DUMP_DELAY_SECONDS);
+               spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       }
+
        start_addr = readl(ioa_cfg->ioa_mailbox);
 
        if (!ioa_cfg->sis64 && !ipr_sdt_is_fmt2(start_addr)) {
@@ -2931,8 +2955,18 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
         on entries in this table */
        sdt = &ioa_dump->sdt;
 
+       if (ioa_cfg->sis64) {
+               max_num_entries = IPR_FMT3_NUM_SDT_ENTRIES;
+               max_dump_size = IPR_FMT3_MAX_IOA_DUMP_SIZE;
+       } else {
+               max_num_entries = IPR_FMT2_NUM_SDT_ENTRIES;
+               max_dump_size = IPR_FMT2_MAX_IOA_DUMP_SIZE;
+       }
+
+       bytes_to_copy = offsetof(struct ipr_sdt, entry) +
+                       (max_num_entries * sizeof(struct ipr_sdt_entry));
        rc = ipr_get_ldump_data_section(ioa_cfg, start_addr, (__be32 *)sdt,
-                                       sizeof(struct ipr_sdt) / sizeof(__be32));
+                                       bytes_to_copy / sizeof(__be32));
 
        /* Smart Dump table is ready to use and the first entry is valid */
        if (rc || ((be32_to_cpu(sdt->hdr.state) != IPR_FMT3_SDT_READY_TO_USE) &&
@@ -2948,13 +2982,20 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
 
        num_entries = be32_to_cpu(sdt->hdr.num_entries_used);
 
-       if (num_entries > IPR_NUM_SDT_ENTRIES)
-               num_entries = IPR_NUM_SDT_ENTRIES;
+       if (num_entries > max_num_entries)
+               num_entries = max_num_entries;
+
+       /* Update dump length to the actual data to be copied */
+       dump->driver_dump.hdr.len += sizeof(struct ipr_sdt_header);
+       if (ioa_cfg->sis64)
+               dump->driver_dump.hdr.len += num_entries * sizeof(struct ipr_sdt_entry);
+       else
+               dump->driver_dump.hdr.len += max_num_entries * sizeof(struct ipr_sdt_entry);
 
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
        for (i = 0; i < num_entries; i++) {
-               if (ioa_dump->hdr.len > IPR_MAX_IOA_DUMP_SIZE) {
+               if (ioa_dump->hdr.len > max_dump_size) {
                        driver_dump->hdr.status = IPR_DUMP_STATUS_QUAL_SUCCESS;
                        break;
                }
@@ -2973,7 +3014,7 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
                                        valid = 0;
                        }
                        if (valid) {
-                               if (bytes_to_copy > IPR_MAX_IOA_DUMP_SIZE) {
+                               if (bytes_to_copy > max_dump_size) {
                                        sdt->entry[i].flags &= ~IPR_SDT_VALID_ENTRY;
                                        continue;
                                }
@@ -3028,6 +3069,7 @@ static void ipr_release_dump(struct kref *kref)
        for (i = 0; i < dump->ioa_dump.next_page_index; i++)
                free_page((unsigned long) dump->ioa_dump.ioa_data[i]);
 
+       vfree(dump->ioa_dump.ioa_data);
        kfree(dump);
        LEAVE;
 }
@@ -3057,7 +3099,7 @@ static void ipr_worker_thread(struct work_struct *work)
        ENTER;
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 
-       if (ioa_cfg->sdt_state == GET_DUMP) {
+       if (ioa_cfg->sdt_state == READ_DUMP) {
                dump = ioa_cfg->dump;
                if (!dump) {
                        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -3069,7 +3111,7 @@ static void ipr_worker_thread(struct work_struct *work)
                kref_put(&dump->kref, ipr_release_dump);
 
                spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
-               if (ioa_cfg->sdt_state == DUMP_OBTAINED)
+               if (ioa_cfg->sdt_state == DUMP_OBTAINED && !ioa_cfg->dump_timeout)
                        ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
                spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
                return;
@@ -3088,7 +3130,10 @@ restart:
                                did_work = 1;
                                sdev = res->sdev;
                                if (!scsi_device_get(sdev)) {
-                                       list_move_tail(&res->queue, &ioa_cfg->free_res_q);
+                                       if (!res->add_to_ml)
+                                               list_move_tail(&res->queue, &ioa_cfg->free_res_q);
+                                       else
+                                               res->del_from_ml = 0;
                                        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
                                        scsi_remove_device(sdev);
                                        scsi_device_put(sdev);
@@ -3120,6 +3165,7 @@ restart:
 #ifdef CONFIG_SCSI_IPR_TRACE
 /**
  * ipr_read_trace - Dump the adapter trace
+ * @filp:              open sysfs file
  * @kobj:              kobject struct
  * @bin_attr:          bin_attribute struct
  * @buf:               buffer
@@ -3129,7 +3175,7 @@ restart:
  * Return value:
  *     number of bytes printed to buffer
  **/
-static ssize_t ipr_read_trace(struct kobject *kobj,
+static ssize_t ipr_read_trace(struct file *filp, struct kobject *kobj,
                              struct bin_attribute *bin_attr,
                              char *buf, loff_t off, size_t count)
 {
@@ -3707,14 +3753,6 @@ static ssize_t ipr_store_update_fw(struct device *dev,
 
        image_hdr = (struct ipr_ucode_image_header *)fw_entry->data;
 
-       if (be32_to_cpu(image_hdr->header_length) > fw_entry->size ||
-           (ioa_cfg->vpd_cbs->page3_data.card_type &&
-            ioa_cfg->vpd_cbs->page3_data.card_type != image_hdr->card_type)) {
-               dev_err(&ioa_cfg->pdev->dev, "Invalid microcode buffer\n");
-               release_firmware(fw_entry);
-               return -EINVAL;
-       }
-
        src = (u8 *)image_hdr + be32_to_cpu(image_hdr->header_length);
        dnld_size = fw_entry->size - be32_to_cpu(image_hdr->header_length);
        sglist = ipr_alloc_ucode_buffer(dnld_size);
@@ -3733,6 +3771,8 @@ static ssize_t ipr_store_update_fw(struct device *dev,
                goto out;
        }
 
+       ipr_info("Updating microcode, please be patient.  This may take up to 30 minutes.\n");
+
        result = ipr_update_ioa_ucode(ioa_cfg, sglist);
 
        if (!result)
@@ -3751,6 +3791,36 @@ static struct device_attribute ipr_update_fw_attr = {
        .store = ipr_store_update_fw
 };
 
+/**
+ * ipr_show_fw_type - Show the adapter's firmware type.
+ * @dev:       class device struct
+ * @buf:       buffer
+ *
+ * Return value:
+ *     number of bytes printed to buffer
+ **/
+static ssize_t ipr_show_fw_type(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+       unsigned long lock_flags = 0;
+       int len;
+
+       spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       len = snprintf(buf, PAGE_SIZE, "%d\n", ioa_cfg->sis64);
+       spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+       return len;
+}
+
+static struct device_attribute ipr_ioa_fw_type_attr = {
+       .attr = {
+               .name =         "fw_type",
+               .mode =         S_IRUGO,
+       },
+       .show = ipr_show_fw_type
+};
+
 static struct device_attribute *ipr_ioa_attrs[] = {
        &ipr_fw_version_attr,
        &ipr_log_level_attr,
@@ -3758,12 +3828,14 @@ static struct device_attribute *ipr_ioa_attrs[] = {
        &ipr_ioa_state_attr,
        &ipr_ioa_reset_attr,
        &ipr_update_fw_attr,
+       &ipr_ioa_fw_type_attr,
        NULL,
 };
 
 #ifdef CONFIG_SCSI_IPR_DUMP
 /**
  * ipr_read_dump - Dump the adapter
+ * @filp:              open sysfs file
  * @kobj:              kobject struct
  * @bin_attr:          bin_attribute struct
  * @buf:               buffer
@@ -3773,7 +3845,7 @@ static struct device_attribute *ipr_ioa_attrs[] = {
  * Return value:
  *     number of bytes printed to buffer
  **/
-static ssize_t ipr_read_dump(struct kobject *kobj,
+static ssize_t ipr_read_dump(struct file *filp, struct kobject *kobj,
                             struct bin_attribute *bin_attr,
                             char *buf, loff_t off, size_t count)
 {
@@ -3783,7 +3855,7 @@ static ssize_t ipr_read_dump(struct kobject *kobj,
        struct ipr_dump *dump;
        unsigned long lock_flags = 0;
        char *src;
-       int len;
+       int len, sdt_end;
        size_t rc = count;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -3823,9 +3895,17 @@ static ssize_t ipr_read_dump(struct kobject *kobj,
 
        off -= sizeof(dump->driver_dump);
 
-       if (count && off < offsetof(struct ipr_ioa_dump, ioa_data)) {
-               if (off + count > offsetof(struct ipr_ioa_dump, ioa_data))
-                       len = offsetof(struct ipr_ioa_dump, ioa_data) - off;
+       if (ioa_cfg->sis64)
+               sdt_end = offsetof(struct ipr_ioa_dump, sdt.entry) +
+                         (be32_to_cpu(dump->ioa_dump.sdt.hdr.num_entries_used) *
+                          sizeof(struct ipr_sdt_entry));
+       else
+               sdt_end = offsetof(struct ipr_ioa_dump, sdt.entry) +
+                         (IPR_FMT2_NUM_SDT_ENTRIES * sizeof(struct ipr_sdt_entry));
+
+       if (count && off < sdt_end) {
+               if (off + count > sdt_end)
+                       len = sdt_end - off;
                else
                        len = count;
                src = (u8 *)&dump->ioa_dump + off;
@@ -3835,7 +3915,7 @@ static ssize_t ipr_read_dump(struct kobject *kobj,
                count -= len;
        }
 
-       off -= offsetof(struct ipr_ioa_dump, ioa_data);
+       off -= sdt_end;
 
        while (count) {
                if ((off & PAGE_MASK) != ((off + count) & PAGE_MASK))
@@ -3864,6 +3944,7 @@ static ssize_t ipr_read_dump(struct kobject *kobj,
 static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
 {
        struct ipr_dump *dump;
+       __be32 **ioa_data;
        unsigned long lock_flags = 0;
 
        dump = kzalloc(sizeof(struct ipr_dump), GFP_KERNEL);
@@ -3873,6 +3954,19 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
                return -ENOMEM;
        }
 
+       if (ioa_cfg->sis64)
+               ioa_data = vmalloc(IPR_FMT3_MAX_NUM_DUMP_PAGES * sizeof(__be32 *));
+       else
+               ioa_data = vmalloc(IPR_FMT2_MAX_NUM_DUMP_PAGES * sizeof(__be32 *));
+
+       if (!ioa_data) {
+               ipr_err("Dump memory allocation failed\n");
+               kfree(dump);
+               return -ENOMEM;
+       }
+
+       dump->ioa_dump.ioa_data = ioa_data;
+
        kref_init(&dump->kref);
        dump->ioa_cfg = ioa_cfg;
 
@@ -3880,6 +3974,7 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
 
        if (INACTIVE != ioa_cfg->sdt_state) {
                spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+               vfree(dump->ioa_dump.ioa_data);
                kfree(dump);
                return 0;
        }
@@ -3927,6 +4022,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg)
 
 /**
  * ipr_write_dump - Setup dump state of adapter
+ * @filp:              open sysfs file
  * @kobj:              kobject struct
  * @bin_attr:          bin_attribute struct
  * @buf:               buffer
@@ -3936,7 +4032,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg)
  * Return value:
  *     number of bytes printed to buffer
  **/
-static ssize_t ipr_write_dump(struct kobject *kobj,
+static ssize_t ipr_write_dump(struct file *filp, struct kobject *kobj,
                              struct bin_attribute *bin_attr,
                              char *buf, loff_t off, size_t count)
 {
@@ -4045,6 +4141,7 @@ static int ipr_change_queue_type(struct scsi_device *sdev, int tag_type)
 /**
  * ipr_show_adapter_handle - Show the adapter's resource handle for this device
  * @dev:       device struct
+ * @attr:      device attribute structure
  * @buf:       buffer
  *
  * Return value:
@@ -4075,8 +4172,10 @@ static struct device_attribute ipr_adapter_handle_attr = {
 };
 
 /**
- * ipr_show_resource_path - Show the resource path for this device.
+ * ipr_show_resource_path - Show the resource path or the resource address for
+ *                         this device.
  * @dev:       device struct
+ * @attr:      device attribute structure
  * @buf:       buffer
  *
  * Return value:
@@ -4093,9 +4192,14 @@ static ssize_t ipr_show_resource_path(struct device *dev, struct device_attribut
 
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
        res = (struct ipr_resource_entry *)sdev->hostdata;
-       if (res)
+       if (res && ioa_cfg->sis64)
                len = snprintf(buf, PAGE_SIZE, "%s\n",
-                              ipr_format_resource_path(&res->res_path[0], &buffer[0]));
+                              ipr_format_res_path(res->res_path, buffer,
+                                                  sizeof(buffer)));
+       else if (res)
+               len = snprintf(buf, PAGE_SIZE, "%d:%d:%d:%d\n", ioa_cfg->host->host_no,
+                              res->bus, res->target, res->lun);
+
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
        return len;
 }
@@ -4103,14 +4207,87 @@ static ssize_t ipr_show_resource_path(struct device *dev, struct device_attribut
 static struct device_attribute ipr_resource_path_attr = {
        .attr = {
                .name =         "resource_path",
-               .mode =         S_IRUSR,
+               .mode =         S_IRUGO,
        },
        .show = ipr_show_resource_path
 };
 
+/**
+ * ipr_show_device_id - Show the device_id for this device.
+ * @dev:       device struct
+ * @attr:      device attribute structure
+ * @buf:       buffer
+ *
+ * Return value:
+ *     number of bytes printed to buffer
+ **/
+static ssize_t ipr_show_device_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
+       struct ipr_resource_entry *res;
+       unsigned long lock_flags = 0;
+       ssize_t len = -ENXIO;
+
+       spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       res = (struct ipr_resource_entry *)sdev->hostdata;
+       if (res && ioa_cfg->sis64)
+               len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->dev_id);
+       else if (res)
+               len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->lun_wwn);
+
+       spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+       return len;
+}
+
+static struct device_attribute ipr_device_id_attr = {
+       .attr = {
+               .name =         "device_id",
+               .mode =         S_IRUGO,
+       },
+       .show = ipr_show_device_id
+};
+
+/**
+ * ipr_show_resource_type - Show the resource type for this device.
+ * @dev:       device struct
+ * @attr:      device attribute structure
+ * @buf:       buffer
+ *
+ * Return value:
+ *     number of bytes printed to buffer
+ **/
+static ssize_t ipr_show_resource_type(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
+       struct ipr_resource_entry *res;
+       unsigned long lock_flags = 0;
+       ssize_t len = -ENXIO;
+
+       spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+       res = (struct ipr_resource_entry *)sdev->hostdata;
+
+       if (res)
+               len = snprintf(buf, PAGE_SIZE, "%x\n", res->type);
+
+       spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+       return len;
+}
+
+static struct device_attribute ipr_resource_type_attr = {
+       .attr = {
+               .name =         "resource_type",
+               .mode =         S_IRUGO,
+       },
+       .show = ipr_show_resource_type
+};
+
 static struct device_attribute *ipr_dev_attrs[] = {
        &ipr_adapter_handle_attr,
        &ipr_resource_path_attr,
+       &ipr_device_id_attr,
+       &ipr_resource_type_attr,
        NULL,
 };
 
@@ -4164,8 +4341,7 @@ static struct ipr_resource_entry *ipr_find_starget(struct scsi_target *starget)
 
        list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
                if ((res->bus == starget->channel) &&
-                   (res->target == starget->id) &&
-                   (res->lun == 0)) {
+                   (res->target == starget->id)) {
                        return res;
                }
        }
@@ -4239,12 +4415,14 @@ static void ipr_target_destroy(struct scsi_target *starget)
        struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *) shost->hostdata;
 
        if (ioa_cfg->sis64) {
-               if (starget->channel == IPR_ARRAY_VIRTUAL_BUS)
-                       clear_bit(starget->id, ioa_cfg->array_ids);
-               else if (starget->channel == IPR_VSET_VIRTUAL_BUS)
-                       clear_bit(starget->id, ioa_cfg->vset_ids);
-               else if (starget->channel == 0)
-                       clear_bit(starget->id, ioa_cfg->target_ids);
+               if (!ipr_find_starget(starget)) {
+                       if (starget->channel == IPR_ARRAY_VIRTUAL_BUS)
+                               clear_bit(starget->id, ioa_cfg->array_ids);
+                       else if (starget->channel == IPR_VSET_VIRTUAL_BUS)
+                               clear_bit(starget->id, ioa_cfg->vset_ids);
+                       else if (starget->channel == 0)
+                               clear_bit(starget->id, ioa_cfg->target_ids);
+               }
        }
 
        if (sata_port) {
@@ -4295,7 +4473,7 @@ static void ipr_slave_destroy(struct scsi_device *sdev)
        res = (struct ipr_resource_entry *) sdev->hostdata;
        if (res) {
                if (res->sata_port)
-                       ata_port_disable(res->sata_port->ap);
+                       res->sata_port->ap->link.device[0].class = ATA_DEV_NONE;
                sdev->hostdata = NULL;
                res->sdev = NULL;
                res->sata_port = NULL;
@@ -4334,8 +4512,6 @@ static int ipr_slave_configure(struct scsi_device *sdev)
                                             IPR_VSET_RW_TIMEOUT);
                        blk_queue_max_hw_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS);
                }
-               if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))
-                       sdev->allow_restart = 1;
                if (ipr_is_gata(res) && res->sata_port)
                        ap = res->sata_port->ap;
                spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -4347,7 +4523,8 @@ static int ipr_slave_configure(struct scsi_device *sdev)
                        scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
                if (ioa_cfg->sis64)
                        sdev_printk(KERN_INFO, sdev, "Resource path: %s\n",
-                                   ipr_format_resource_path(&res->res_path[0], &buffer[0]));
+                                   ipr_format_res_path(res->res_path, buffer,
+                                                       sizeof(buffer)));
                return 0;
        }
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -4372,8 +4549,12 @@ static int ipr_ata_slave_alloc(struct scsi_device *sdev)
        ENTER;
        if (sdev->sdev_target)
                sata_port = sdev->sdev_target->hostdata;
-       if (sata_port)
+       if (sata_port) {
                rc = ata_sas_port_init(sata_port->ap);
+               if (rc == 0)
+                       rc = ata_sas_sync_probe(sata_port->ap);
+       }
+
        if (rc)
                ipr_slave_destroy(sdev);
 
@@ -4439,11 +4620,13 @@ static int __ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd)
        ENTER;
        ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
 
-       dev_err(&ioa_cfg->pdev->dev,
-               "Adapter being reset as a result of error recovery.\n");
+       if (!ioa_cfg->in_reset_reload) {
+               dev_err(&ioa_cfg->pdev->dev,
+                       "Adapter being reset as a result of error recovery.\n");
 
-       if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
-               ioa_cfg->sdt_state = GET_DUMP;
+               if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
+                       ioa_cfg->sdt_state = GET_DUMP;
+       }
 
        rc = ipr_reset_reload(ioa_cfg, IPR_SHUTDOWN_ABBREV);
 
@@ -4506,11 +4689,16 @@ static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg,
        }
 
        ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
-       ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
        list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
-       if (ipr_is_gata(res) && res->sata_port && ioasc != IPR_IOASC_IOA_WAS_RESET)
-               memcpy(&res->sata_port->ioasa, &ipr_cmd->ioasa.u.gata,
-                      sizeof(struct ipr_ioasa_gata));
+       if (ipr_is_gata(res) && res->sata_port && ioasc != IPR_IOASC_IOA_WAS_RESET) {
+               if (ipr_cmd->ioa_cfg->sis64)
+                       memcpy(&res->sata_port->ioasa, &ipr_cmd->s.ioasa64.u.gata,
+                              sizeof(struct ipr_ioasa_gata));
+               else
+                       memcpy(&res->sata_port->ioasa, &ipr_cmd->s.ioasa.u.gata,
+                              sizeof(struct ipr_ioasa_gata));
+       }
 
        LEAVE;
        return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0);
@@ -4728,7 +4916,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
        struct ipr_ioa_cfg *ioa_cfg;
        struct ipr_resource_entry *res;
        struct ipr_cmd_pkt *cmd_pkt;
-       u32 ioasc;
+       u32 ioasc, int_reg;
        int op_found = 0;
 
        ENTER;
@@ -4741,7 +4929,17 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
         */
        if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead)
                return FAILED;
-       if (!res || !ipr_is_gscsi(res))
+       if (!res)
+               return FAILED;
+
+       /*
+        * If we are aborting a timed out op, chances are that the timeout was caused
+        * by a still not detected EEH error. In such cases, reading a register will
+        * trigger the EEH recovery infrastructure.
+        */
+       int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
+
+       if (!ipr_is_gscsi(res))
                return FAILED;
 
        list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
@@ -4765,7 +4963,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
        scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n",
                    scsi_cmd->cmnd[0]);
        ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT);
-       ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
        /*
         * If the abort task timed out and we sent a bus reset, we will get
@@ -4815,9 +5013,35 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd)
  *     IRQ_NONE / IRQ_HANDLED
  **/
 static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
-                                             volatile u32 int_reg)
+                                             u32 int_reg)
 {
        irqreturn_t rc = IRQ_HANDLED;
+       u32 int_mask_reg;
+
+       int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
+       int_reg &= ~int_mask_reg;
+
+       /* If an interrupt on the adapter did not occur, ignore it.
+        * Or in the case of SIS 64, check for a stage change interrupt.
+        */
+       if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) {
+               if (ioa_cfg->sis64) {
+                       int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
+                       int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
+                       if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
+
+                               /* clear stage change */
+                               writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
+                               int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
+                               list_del(&ioa_cfg->reset_cmd->queue);
+                               del_timer(&ioa_cfg->reset_cmd->timer);
+                               ipr_reset_ioa_job(ioa_cfg->reset_cmd);
+                               return IRQ_HANDLED;
+                       }
+               }
+
+               return IRQ_NONE;
+       }
 
        if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
                /* Mask the interrupt */
@@ -4830,6 +5054,15 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
                list_del(&ioa_cfg->reset_cmd->queue);
                del_timer(&ioa_cfg->reset_cmd->timer);
                ipr_reset_ioa_job(ioa_cfg->reset_cmd);
+       } else if ((int_reg & IPR_PCII_HRRQ_UPDATED) == int_reg) {
+               if (ioa_cfg->clear_isr) {
+                       if (ipr_debug && printk_ratelimit())
+                               dev_err(&ioa_cfg->pdev->dev,
+                                       "Spurious interrupt detected. 0x%08X\n", int_reg);
+                       writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
+                       int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
+                       return IRQ_NONE;
+               }
        } else {
                if (int_reg & IPR_PCII_IOA_UNIT_CHECKED)
                        ioa_cfg->ioa_unit_checked = 1;
@@ -4878,10 +5111,11 @@ static irqreturn_t ipr_isr(int irq, void *devp)
 {
        struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
        unsigned long lock_flags = 0;
-       volatile u32 int_reg, int_mask_reg;
+       u32 int_reg = 0;
        u32 ioasc;
        u16 cmd_index;
        int num_hrrq = 0;
+       int irq_none = 0;
        struct ipr_cmnd *ipr_cmd;
        irqreturn_t rc = IRQ_NONE;
 
@@ -4893,33 +5127,6 @@ static irqreturn_t ipr_isr(int irq, void *devp)
                return IRQ_NONE;
        }
 
-       int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
-       int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
-
-       /* If an interrupt on the adapter did not occur, ignore it.
-        * Or in the case of SIS 64, check for a stage change interrupt.
-        */
-       if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) {
-               if (ioa_cfg->sis64) {
-                       int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
-                       int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
-                       if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
-
-                               /* clear stage change */
-                               writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
-                               int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
-                               list_del(&ioa_cfg->reset_cmd->queue);
-                               del_timer(&ioa_cfg->reset_cmd->timer);
-                               ipr_reset_ioa_job(ioa_cfg->reset_cmd);
-                               spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-                               return IRQ_HANDLED;
-                       }
-               }
-
-               spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-               return IRQ_NONE;
-       }
-
        while (1) {
                ipr_cmd = NULL;
 
@@ -4937,7 +5144,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
 
                        ipr_cmd = ioa_cfg->ipr_cmnd_list[cmd_index];
 
-                       ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+                       ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
                        ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc);
 
@@ -4955,20 +5162,26 @@ static irqreturn_t ipr_isr(int irq, void *devp)
                        }
                }
 
+               if (ipr_cmd && !ioa_cfg->clear_isr)
+                       break;
+
                if (ipr_cmd != NULL) {
                        /* Clear the PCI interrupt */
+                       num_hrrq = 0;
                        do {
                                writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
-                               int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
+                               int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
                        } while (int_reg & IPR_PCII_HRRQ_UPDATED &&
                                        num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
 
-                       if (int_reg & IPR_PCII_HRRQ_UPDATED) {
-                               ipr_isr_eh(ioa_cfg, "Error clearing HRRQ");
-                               spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-                               return IRQ_HANDLED;
-                       }
-
+               } else if (rc == IRQ_NONE && irq_none == 0) {
+                       int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
+                       irq_none++;
+               } else if (num_hrrq == IPR_MAX_HRRQ_RETRIES &&
+                          int_reg & IPR_PCII_HRRQ_UPDATED) {
+                       ipr_isr_eh(ioa_cfg, "Error clearing HRRQ");
+                       spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+                       return IRQ_HANDLED;
                } else
                        break;
        }
@@ -5005,12 +5218,17 @@ static int ipr_build_ioadl64(struct ipr_ioa_cfg *ioa_cfg,
 
        nseg = scsi_dma_map(scsi_cmd);
        if (nseg < 0) {
-               dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
+               if (printk_ratelimit())
+                       dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
                return -1;
        }
 
        ipr_cmd->dma_use_sg = nseg;
 
+       ioarcb->data_transfer_length = cpu_to_be32(length);
+       ioarcb->ioadl_len =
+               cpu_to_be32(sizeof(struct ipr_ioadl64_desc) * ipr_cmd->dma_use_sg);
+
        if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
                ioadl_flags = IPR_IOADL_FLAGS_WRITE;
                ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
@@ -5132,7 +5350,7 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
        struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
        struct ipr_resource_entry *res = scsi_cmd->device->hostdata;
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
        if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
                scsi_cmd->result |= (DID_ERROR << 16);
@@ -5163,7 +5381,7 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
 static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
-       struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+       struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
        dma_addr_t dma_addr = ipr_cmd->dma_addr;
 
        memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
@@ -5171,8 +5389,8 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
        ioarcb->read_data_transfer_length = 0;
        ioarcb->ioadl_len = 0;
        ioarcb->read_ioadl_len = 0;
-       ioasa->ioasc = 0;
-       ioasa->residual_data_len = 0;
+       ioasa->hdr.ioasc = 0;
+       ioasa->hdr.residual_data_len = 0;
 
        if (ipr_cmd->ioa_cfg->sis64)
                ioarcb->u.sis64_addr_data.data_ioadl_addr =
@@ -5197,7 +5415,7 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
 static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_cmd_pkt *cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
        if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
                ipr_erp_done(ipr_cmd);
@@ -5274,12 +5492,12 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
        int i;
        u16 data_len;
        u32 ioasc, fd_ioasc;
-       struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+       struct ipr_ioasa *ioasa = &ipr_cmd->s.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;
+       ioasc = be32_to_cpu(ioasa->hdr.ioasc) & IPR_IOASC_IOASC_MASK;
+       fd_ioasc = be32_to_cpu(ioasa->hdr.fd_ioasc) & IPR_IOASC_IOASC_MASK;
 
        if (0 == ioasc)
                return;
@@ -5294,7 +5512,7 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
 
        if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) {
                /* Don't log an error if the IOA already logged one */
-               if (ioasa->ilid != 0)
+               if (ioasa->hdr.ilid != 0)
                        return;
 
                if (!ipr_is_gscsi(res))
@@ -5306,10 +5524,11 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
 
        ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error);
 
-       if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len))
+       data_len = be16_to_cpu(ioasa->hdr.ret_stat_len);
+       if (ioa_cfg->sis64 && sizeof(struct ipr_ioasa64) < data_len)
+               data_len = sizeof(struct ipr_ioasa64);
+       else if (!ioa_cfg->sis64 && sizeof(struct ipr_ioasa) < data_len)
                data_len = sizeof(struct ipr_ioasa);
-       else
-               data_len = be16_to_cpu(ioasa->ret_stat_len);
 
        ipr_err("IOASA Dump:\n");
 
@@ -5335,8 +5554,8 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd)
        u32 failing_lba;
        u8 *sense_buf = ipr_cmd->scsi_cmd->sense_buffer;
        struct ipr_resource_entry *res = ipr_cmd->scsi_cmd->device->hostdata;
-       struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
-       u32 ioasc = be32_to_cpu(ioasa->ioasc);
+       struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
+       u32 ioasc = be32_to_cpu(ioasa->hdr.ioasc);
 
        memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE);
 
@@ -5379,7 +5598,7 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd)
 
                /* Illegal request */
                if ((IPR_IOASC_SENSE_KEY(ioasc) == 0x05) &&
-                   (be32_to_cpu(ioasa->ioasc_specific) & IPR_FIELD_POINTER_VALID)) {
+                   (be32_to_cpu(ioasa->hdr.ioasc_specific) & IPR_FIELD_POINTER_VALID)) {
                        sense_buf[7] = 10;      /* additional length */
 
                        /* IOARCB was in error */
@@ -5390,10 +5609,10 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd)
 
                        sense_buf[16] =
                            ((IPR_FIELD_POINTER_MASK &
-                             be32_to_cpu(ioasa->ioasc_specific)) >> 8) & 0xff;
+                             be32_to_cpu(ioasa->hdr.ioasc_specific)) >> 8) & 0xff;
                        sense_buf[17] =
                            (IPR_FIELD_POINTER_MASK &
-                            be32_to_cpu(ioasa->ioasc_specific)) & 0xff;
+                            be32_to_cpu(ioasa->hdr.ioasc_specific)) & 0xff;
                } else {
                        if (ioasc == IPR_IOASC_MED_DO_NOT_REALLOC) {
                                if (ipr_is_vset_device(res))
@@ -5425,14 +5644,20 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd)
  **/
 static int ipr_get_autosense(struct ipr_cmnd *ipr_cmd)
 {
-       struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+       struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
+       struct ipr_ioasa64 *ioasa64 = &ipr_cmd->s.ioasa64;
 
-       if ((be32_to_cpu(ioasa->ioasc_specific) & IPR_AUTOSENSE_VALID) == 0)
+       if ((be32_to_cpu(ioasa->hdr.ioasc_specific) & IPR_AUTOSENSE_VALID) == 0)
                return 0;
 
-       memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data,
-              min_t(u16, be16_to_cpu(ioasa->auto_sense.auto_sense_len),
-                  SCSI_SENSE_BUFFERSIZE));
+       if (ipr_cmd->ioa_cfg->sis64)
+               memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa64->auto_sense.data,
+                      min_t(u16, be16_to_cpu(ioasa64->auto_sense.auto_sense_len),
+                          SCSI_SENSE_BUFFERSIZE));
+       else
+               memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data,
+                      min_t(u16, be16_to_cpu(ioasa->auto_sense.auto_sense_len),
+                          SCSI_SENSE_BUFFERSIZE));
        return 1;
 }
 
@@ -5452,7 +5677,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
 {
        struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
        struct ipr_resource_entry *res = scsi_cmd->device->hostdata;
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
        u32 masked_ioasc = ioasc & IPR_IOASC_IOASC_MASK;
 
        if (!res) {
@@ -5544,9 +5769,9 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
        struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
-       scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->ioasa.residual_data_len));
+       scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->s.ioasa.hdr.residual_data_len));
 
        if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
                scsi_dma_unmap(ipr_cmd->scsi_cmd);
@@ -5568,7 +5793,7 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd)
  *     SCSI_MLQUEUE_DEVICE_BUSY if device is busy
  *     SCSI_MLQUEUE_HOST_BUSY if host is busy
  **/
-static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
+static int ipr_queuecommand_lck(struct scsi_cmnd *scsi_cmd,
                            void (*done) (struct scsi_cmnd *))
 {
        struct ipr_ioa_cfg *ioa_cfg;
@@ -5602,7 +5827,7 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
        }
 
        if (ipr_is_gata(res) && res->sata_port)
-               return ata_sas_queuecmd(scsi_cmd, done, res->sata_port->ap);
+               return ata_sas_queuecmd(scsi_cmd, res->sata_port->ap);
 
        ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
        ioarcb = &ipr_cmd->ioarcb;
@@ -5624,7 +5849,8 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
                }
 
                ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC;
-               ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST;
+               if (ipr_is_gscsi(res))
+                       ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST;
                ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_ALIGNED_BFR;
                ioarcb->cmd_pkt.flags_lo |= ipr_get_task_attributes(scsi_cmd);
        }
@@ -5640,17 +5866,17 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
                        rc = ipr_build_ioadl(ioa_cfg, ipr_cmd);
        }
 
-       if (likely(rc == 0)) {
-               mb();
-               ipr_send_command(ipr_cmd);
-       } else {
-                list_move_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
-                return SCSI_MLQUEUE_HOST_BUSY;
+       if (unlikely(rc != 0)) {
+               list_move_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+               return SCSI_MLQUEUE_HOST_BUSY;
        }
 
+       ipr_send_command(ipr_cmd);
        return 0;
 }
 
+static DEF_SCSI_QCMD(ipr_queuecommand)
+
 /**
  * ipr_ioctl - IOCTL handler
  * @sdev:      scsi device struct
@@ -5751,13 +5977,13 @@ static void ipr_ata_phy_reset(struct ata_port *ap)
        rc = ipr_device_reset(ioa_cfg, res);
 
        if (rc) {
-               ata_port_disable(ap);
+               ap->link.device[0].class = ATA_DEV_NONE;
                goto out_unlock;
        }
 
        ap->link.device[0].class = res->ata_class;
        if (ap->link.device[0].class == ATA_DEV_UNKNOWN)
-               ata_port_disable(ap);
+               ap->link.device[0].class = ATA_DEV_NONE;
 
 out_unlock:
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
@@ -5836,19 +6062,23 @@ static void ipr_sata_done(struct ipr_cmnd *ipr_cmd)
        struct ata_queued_cmd *qc = ipr_cmd->qc;
        struct ipr_sata_port *sata_port = qc->ap->private_data;
        struct ipr_resource_entry *res = sata_port->res;
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
-       memcpy(&sata_port->ioasa, &ipr_cmd->ioasa.u.gata,
-              sizeof(struct ipr_ioasa_gata));
+       if (ipr_cmd->ioa_cfg->sis64)
+               memcpy(&sata_port->ioasa, &ipr_cmd->s.ioasa64.u.gata,
+                      sizeof(struct ipr_ioasa_gata));
+       else
+               memcpy(&sata_port->ioasa, &ipr_cmd->s.ioasa.u.gata,
+                      sizeof(struct ipr_ioasa_gata));
        ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
 
-       if (be32_to_cpu(ipr_cmd->ioasa.ioasc_specific) & IPR_ATA_DEVICE_WAS_RESET)
+       if (be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc_specific) & IPR_ATA_DEVICE_WAS_RESET)
                scsi_report_device_reset(ioa_cfg->host, res->bus, res->target);
 
        if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR)
-               qc->err_mask |= __ac_err_mask(ipr_cmd->ioasa.u.gata.status);
+               qc->err_mask |= __ac_err_mask(sata_port->ioasa.status);
        else
-               qc->err_mask |= ac_err_mask(ipr_cmd->ioasa.u.gata.status);
+               qc->err_mask |= ac_err_mask(sata_port->ioasa.status);
        list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
        ata_qc_complete(qc);
 }
@@ -6019,8 +6249,6 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
                return AC_ERR_INVALID;
        }
 
-       mb();
-
        ipr_send_command(ipr_cmd);
 
        return 0;
@@ -6067,11 +6295,10 @@ static struct ata_port_operations ipr_sata_ops = {
 };
 
 static struct ata_port_info sata_port_info = {
-       .flags  = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET |
-       ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
-       .pio_mask       = 0x10, /* pio4 */
-       .mwdma_mask = 0x07,
-       .udma_mask      = 0x7f, /* udma0-6 */
+       .flags          = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
+       .pio_mask       = ATA_PIO4_ONLY,
+       .mwdma_mask     = ATA_MWDMA2,
+       .udma_mask      = ATA_UDMA6,
        .port_ops       = &ipr_sata_ops
 };
 
@@ -6517,7 +6744,7 @@ static void ipr_build_mode_sense(struct ipr_cmnd *ipr_cmd,
 static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
        dev_err(&ioa_cfg->pdev->dev,
                "0x%02X failed with IOASC: 0x%08X\n",
@@ -6541,7 +6768,7 @@ static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd)
 static int ipr_reset_mode_sense_failed(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
        if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) {
                ipr_cmd->job_step = ipr_set_supported_devs;
@@ -6631,7 +6858,7 @@ static int ipr_ioafp_mode_select_page24(struct ipr_cmnd *ipr_cmd)
  **/
 static int ipr_reset_mode_sense_page24_failed(struct ipr_cmnd *ipr_cmd)
 {
-       u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
        if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) {
                ipr_cmd->job_step = ipr_ioafp_mode_sense_page28;
@@ -6703,7 +6930,7 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd)
                list_move_tail(&res->queue, &old_res);
 
        if (ioa_cfg->sis64)
-               entries = ioa_cfg->u.cfg_table64->hdr64.num_entries;
+               entries = be16_to_cpu(ioa_cfg->u.cfg_table64->hdr64.num_entries);
        else
                entries = ioa_cfg->u.cfg_table->hdr.num_entries;
 
@@ -6734,7 +6961,8 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd)
                        list_move_tail(&res->queue, &ioa_cfg->used_res_q);
                        ipr_init_res_entry(res, &cfgtew);
                        res->add_to_ml = 1;
-               }
+               } else if (res->sdev && (ipr_is_vset_device(res) || ipr_is_scsi_disk(res)))
+                       res->sdev->allow_restart = 1;
 
                if (found)
                        ipr_update_res_entry(res, &cfgtew);
@@ -6789,6 +7017,7 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd)
        ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE);
 
        ioarcb->cmd_pkt.cdb[0] = IPR_QUERY_IOA_CONFIG;
+       ioarcb->cmd_pkt.cdb[6] = (ioa_cfg->cfg_table_size >> 16) & 0xff;
        ioarcb->cmd_pkt.cdb[7] = (ioa_cfg->cfg_table_size >> 8) & 0xff;
        ioarcb->cmd_pkt.cdb[8] = ioa_cfg->cfg_table_size & 0xff;
 
@@ -7119,7 +7348,9 @@ static int ipr_reset_next_stage(struct ipr_cmnd *ipr_cmd)
        ipr_dbg("IPL stage = 0x%lx, IPL stage time = %ld\n", stage, stage_time);
 
        /* sanity check the stage_time value */
-       if (stage_time < IPR_IPL_INIT_MIN_STAGE_TIME)
+       if (stage_time == 0)
+               stage_time = IPR_IPL_INIT_DEFAULT_STAGE_TIME;
+       else if (stage_time < IPR_IPL_INIT_MIN_STAGE_TIME)
                stage_time = IPR_IPL_INIT_MIN_STAGE_TIME;
        else if (stage_time > IPR_LONG_OPERATIONAL_TIMEOUT)
                stage_time = IPR_LONG_OPERATIONAL_TIMEOUT;
@@ -7130,12 +7361,15 @@ static int ipr_reset_next_stage(struct ipr_cmnd *ipr_cmd)
                stage_time = ioa_cfg->transop_timeout;
                ipr_cmd->job_step = ipr_ioafp_identify_hrrq;
        } else if (stage == IPR_IPL_INIT_STAGE_TRANSOP) {
-               ipr_cmd->job_step = ipr_ioafp_identify_hrrq;
-               maskval = IPR_PCII_IPL_STAGE_CHANGE;
-               maskval = (maskval << 32) | IPR_PCII_IOA_TRANS_TO_OPER;
-               writeq(maskval, ioa_cfg->regs.set_interrupt_mask_reg);
-               int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
-               return IPR_RC_JOB_CONTINUE;
+               int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
+               if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
+                       ipr_cmd->job_step = ipr_ioafp_identify_hrrq;
+                       maskval = IPR_PCII_IPL_STAGE_CHANGE;
+                       maskval = (maskval << 32) | IPR_PCII_IOA_TRANS_TO_OPER;
+                       writeq(maskval, ioa_cfg->regs.set_interrupt_mask_reg);
+                       int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
+                       return IPR_RC_JOB_CONTINUE;
+               }
        }
 
        ipr_cmd->timer.data = (unsigned long) ipr_cmd;
@@ -7162,13 +7396,20 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
        volatile u32 int_reg;
+       volatile u64 maskval;
 
        ENTER;
        ipr_cmd->job_step = ipr_ioafp_identify_hrrq;
        ipr_init_ioa_mem(ioa_cfg);
 
        ioa_cfg->allow_interrupts = 1;
-       int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
+       if (ioa_cfg->sis64) {
+               /* Set the adapter to the correct endian mode. */
+               writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg);
+               int_reg = readl(ioa_cfg->regs.endian_swap_reg);
+       }
+
+       int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
 
        if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
                writel((IPR_PCII_ERROR_INTERRUPTS | IPR_PCII_HRRQ_UPDATED),
@@ -7180,9 +7421,12 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)
        /* Enable destructive diagnostics on IOA */
        writel(ioa_cfg->doorbell, ioa_cfg->regs.set_uproc_interrupt_reg32);
 
-       writel(IPR_PCII_OPER_INTERRUPTS, ioa_cfg->regs.clr_interrupt_mask_reg32);
-       if (ioa_cfg->sis64)
-               writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_mask_reg);
+       if (ioa_cfg->sis64) {
+               maskval = IPR_PCII_IPL_STAGE_CHANGE;
+               maskval = (maskval << 32) | IPR_PCII_OPER_INTERRUPTS;
+               writeq(maskval, ioa_cfg->regs.clr_interrupt_mask_reg);
+       } else
+               writel(IPR_PCII_OPER_INTERRUPTS, ioa_cfg->regs.clr_interrupt_mask_reg32);
 
        int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
 
@@ -7219,8 +7463,11 @@ static int ipr_reset_wait_for_dump(struct ipr_cmnd *ipr_cmd)
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
 
        if (ioa_cfg->sdt_state == GET_DUMP)
+               ioa_cfg->sdt_state = WAIT_FOR_DUMP;
+       else if (ioa_cfg->sdt_state == READ_DUMP)
                ioa_cfg->sdt_state = ABORT_DUMP;
 
+       ioa_cfg->dump_timeout = 1;
        ipr_cmd->job_step = ipr_reset_alert;
 
        return IPR_RC_JOB_CONTINUE;
@@ -7309,6 +7556,29 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
 }
 
 /**
+ * ipr_reset_get_unit_check_job - Call to get the unit check buffer.
+ * @ipr_cmd:   ipr command struct
+ *
+ * Description: This function will call to get the unit check buffer.
+ *
+ * Return value:
+ *     IPR_RC_JOB_RETURN
+ **/
+static int ipr_reset_get_unit_check_job(struct ipr_cmnd *ipr_cmd)
+{
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
+       ENTER;
+       ioa_cfg->ioa_unit_checked = 0;
+       ipr_get_unit_check_buffer(ioa_cfg);
+       ipr_cmd->job_step = ipr_reset_alert;
+       ipr_reset_start_timer(ipr_cmd, 0);
+
+       LEAVE;
+       return IPR_RC_JOB_RETURN;
+}
+
+/**
  * ipr_reset_restore_cfg_space - Restore PCI config space.
  * @ipr_cmd:   ipr command struct
  *
@@ -7322,30 +7592,37 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
 static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
-       int rc;
+       u32 int_reg;
 
        ENTER;
        ioa_cfg->pdev->state_saved = true;
-       rc = pci_restore_state(ioa_cfg->pdev);
-
-       if (rc != PCIBIOS_SUCCESSFUL) {
-               ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
-               return IPR_RC_JOB_CONTINUE;
-       }
+       pci_restore_state(ioa_cfg->pdev);
 
        if (ipr_set_pcix_cmd_reg(ioa_cfg)) {
-               ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
+               ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
                return IPR_RC_JOB_CONTINUE;
        }
 
        ipr_fail_all_ops(ioa_cfg);
 
+       if (ioa_cfg->sis64) {
+               /* Set the adapter to the correct endian mode. */
+               writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg);
+               int_reg = readl(ioa_cfg->regs.endian_swap_reg);
+       }
+
        if (ioa_cfg->ioa_unit_checked) {
-               ioa_cfg->ioa_unit_checked = 0;
-               ipr_get_unit_check_buffer(ioa_cfg);
-               ipr_cmd->job_step = ipr_reset_alert;
-               ipr_reset_start_timer(ipr_cmd, 0);
-               return IPR_RC_JOB_RETURN;
+               if (ioa_cfg->sis64) {
+                       ipr_cmd->job_step = ipr_reset_get_unit_check_job;
+                       ipr_reset_start_timer(ipr_cmd, IPR_DUMP_DELAY_TIMEOUT);
+                       return IPR_RC_JOB_RETURN;
+               } else {
+                       ioa_cfg->ioa_unit_checked = 0;
+                       ipr_get_unit_check_buffer(ioa_cfg);
+                       ipr_cmd->job_step = ipr_reset_alert;
+                       ipr_reset_start_timer(ipr_cmd, 0);
+                       return IPR_RC_JOB_RETURN;
+               }
        }
 
        if (ioa_cfg->in_ioa_bringdown) {
@@ -7354,14 +7631,19 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
                ipr_cmd->job_step = ipr_reset_enable_ioa;
 
                if (GET_DUMP == ioa_cfg->sdt_state) {
-                       ipr_reset_start_timer(ipr_cmd, IPR_DUMP_TIMEOUT);
+                       ioa_cfg->sdt_state = READ_DUMP;
+                       ioa_cfg->dump_timeout = 0;
+                       if (ioa_cfg->sis64)
+                               ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT);
+                       else
+                               ipr_reset_start_timer(ipr_cmd, IPR_SIS32_DUMP_TIMEOUT);
                        ipr_cmd->job_step = ipr_reset_wait_for_dump;
                        schedule_work(&ioa_cfg->work_q);
                        return IPR_RC_JOB_RETURN;
                }
        }
 
-       ENTER;
+       LEAVE;
        return IPR_RC_JOB_CONTINUE;
 }
 
@@ -7376,8 +7658,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
  **/
 static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd)
 {
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
        ENTER;
-       pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
+       if (ioa_cfg->cfg_locked)
+               pci_cfg_access_unlock(ioa_cfg->pdev);
+       ioa_cfg->cfg_locked = 0;
        ipr_cmd->job_step = ipr_reset_restore_cfg_space;
        LEAVE;
        return IPR_RC_JOB_CONTINUE;
@@ -7395,20 +7681,25 @@ static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd)
 static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
-       int rc;
+       int rc = PCIBIOS_SUCCESSFUL;
 
        ENTER;
-       pci_block_user_cfg_access(ioa_cfg->pdev);
-       rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START);
+       if (ioa_cfg->ipr_chip->bist_method == IPR_MMIO)
+               writel(IPR_UPROCI_SIS64_START_BIST,
+                      ioa_cfg->regs.set_uproc_interrupt_reg32);
+       else
+               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 {
+       if (rc == PCIBIOS_SUCCESSFUL) {
                ipr_cmd->job_step = ipr_reset_bist_done;
                ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
                rc = IPR_RC_JOB_RETURN;
+       } else {
+               if (ioa_cfg->cfg_locked)
+                       pci_cfg_access_unlock(ipr_cmd->ioa_cfg->pdev);
+               ioa_cfg->cfg_locked = 0;
+               ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
+               rc = IPR_RC_JOB_CONTINUE;
        }
 
        LEAVE;
@@ -7449,7 +7740,6 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
        struct pci_dev *pdev = ioa_cfg->pdev;
 
        ENTER;
-       pci_block_user_cfg_access(pdev);
        pci_set_pcie_reset_state(pdev, pcie_warm_reset);
        ipr_cmd->job_step = ipr_reset_slot_reset_done;
        ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT);
@@ -7458,6 +7748,56 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
 }
 
 /**
+ * ipr_reset_block_config_access_wait - Wait for permission to block config access
+ * @ipr_cmd:   ipr command struct
+ *
+ * Description: This attempts to block config access to the IOA.
+ *
+ * Return value:
+ *     IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
+ **/
+static int ipr_reset_block_config_access_wait(struct ipr_cmnd *ipr_cmd)
+{
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+       int rc = IPR_RC_JOB_CONTINUE;
+
+       if (pci_cfg_access_trylock(ioa_cfg->pdev)) {
+               ioa_cfg->cfg_locked = 1;
+               ipr_cmd->job_step = ioa_cfg->reset;
+       } else {
+               if (ipr_cmd->u.time_left) {
+                       rc = IPR_RC_JOB_RETURN;
+                       ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
+                       ipr_reset_start_timer(ipr_cmd,
+                                             IPR_CHECK_FOR_RESET_TIMEOUT);
+               } else {
+                       ipr_cmd->job_step = ioa_cfg->reset;
+                       dev_err(&ioa_cfg->pdev->dev,
+                               "Timed out waiting to lock config access. Resetting anyway.\n");
+               }
+       }
+
+       return rc;
+}
+
+/**
+ * ipr_reset_block_config_access - Block config access to the IOA
+ * @ipr_cmd:   ipr command struct
+ *
+ * Description: This attempts to block config access to the IOA
+ *
+ * Return value:
+ *     IPR_RC_JOB_CONTINUE
+ **/
+static int ipr_reset_block_config_access(struct ipr_cmnd *ipr_cmd)
+{
+       ipr_cmd->ioa_cfg->cfg_locked = 0;
+       ipr_cmd->job_step = ipr_reset_block_config_access_wait;
+       ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;
+       return IPR_RC_JOB_CONTINUE;
+}
+
+/**
  * ipr_reset_allowed - Query whether or not IOA can be reset
  * @ioa_cfg:   ioa config struct
  *
@@ -7496,7 +7836,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd)
                ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
                ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT);
        } else {
-               ipr_cmd->job_step = ioa_cfg->reset;
+               ipr_cmd->job_step = ipr_reset_block_config_access;
                rc = IPR_RC_JOB_CONTINUE;
        }
 
@@ -7504,7 +7844,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd)
 }
 
 /**
- * ipr_reset_alert_part2 - Alert the adapter of a pending reset
+ * ipr_reset_alert - Alert the adapter of a pending reset
  * @ipr_cmd:   ipr command struct
  *
  * Description: This function alerts the adapter that it will be reset.
@@ -7529,7 +7869,7 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd)
                writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg32);
                ipr_cmd->job_step = ipr_reset_wait_to_start_bist;
        } else {
-               ipr_cmd->job_step = ioa_cfg->reset;
+               ipr_cmd->job_step = ipr_reset_block_config_access;
        }
 
        ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;
@@ -7662,7 +8002,7 @@ static void ipr_reset_ioa_job(struct ipr_cmnd *ipr_cmd)
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
 
        do {
-               ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+               ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
 
                if (ioa_cfg->reset_cmd != ipr_cmd) {
                        /*
@@ -7735,8 +8075,12 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
        if (ioa_cfg->ioa_is_dead)
                return;
 
-       if (ioa_cfg->in_reset_reload && ioa_cfg->sdt_state == GET_DUMP)
-               ioa_cfg->sdt_state = ABORT_DUMP;
+       if (ioa_cfg->in_reset_reload) {
+               if (ioa_cfg->sdt_state == GET_DUMP)
+                       ioa_cfg->sdt_state = WAIT_FOR_DUMP;
+               else if (ioa_cfg->sdt_state == READ_DUMP)
+                       ioa_cfg->sdt_state = ABORT_DUMP;
+       }
 
        if (ioa_cfg->reset_retries++ >= IPR_NUM_RESET_RELOAD_RETRIES) {
                dev_err(&ioa_cfg->pdev->dev,
@@ -7941,6 +8285,10 @@ static void ipr_free_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
        if (ioa_cfg->ipr_cmd_pool)
                pci_pool_destroy (ioa_cfg->ipr_cmd_pool);
 
+       kfree(ioa_cfg->ipr_cmnd_list);
+       kfree(ioa_cfg->ipr_cmnd_list_dma);
+       ioa_cfg->ipr_cmnd_list = NULL;
+       ioa_cfg->ipr_cmnd_list_dma = NULL;
        ioa_cfg->ipr_cmd_pool = NULL;
 }
 
@@ -8016,11 +8364,19 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
        int i;
 
        ioa_cfg->ipr_cmd_pool = pci_pool_create (IPR_NAME, ioa_cfg->pdev,
-                                                sizeof(struct ipr_cmnd), 16, 0);
+                                                sizeof(struct ipr_cmnd), 512, 0);
 
        if (!ioa_cfg->ipr_cmd_pool)
                return -ENOMEM;
 
+       ioa_cfg->ipr_cmnd_list = kcalloc(IPR_NUM_CMD_BLKS, sizeof(struct ipr_cmnd *), GFP_KERNEL);
+       ioa_cfg->ipr_cmnd_list_dma = kcalloc(IPR_NUM_CMD_BLKS, sizeof(dma_addr_t), GFP_KERNEL);
+
+       if (!ioa_cfg->ipr_cmnd_list || !ioa_cfg->ipr_cmnd_list_dma) {
+               ipr_free_cmd_blks(ioa_cfg);
+               return -ENOMEM;
+       }
+
        for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
                ipr_cmd = pci_pool_alloc (ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
 
@@ -8045,13 +8401,13 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
                        ioarcb->u.sis64_addr_data.data_ioadl_addr =
                                cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64));
                        ioarcb->u.sis64_addr_data.ioasa_host_pci_addr =
-                               cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, ioasa));
+                               cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, s.ioasa64));
                } else {
                        ioarcb->write_ioadl_addr =
                                cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl));
                        ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
                        ioarcb->ioasa_host_pci_addr =
-                               cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioasa));
+                               cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, s.ioasa));
                }
                ioarcb->ioasa_len = cpu_to_be16(sizeof(struct ipr_ioasa));
                ipr_cmd->cmd_index = i;
@@ -8248,6 +8604,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
        host->max_channel = IPR_MAX_BUS_TO_SCAN;
        host->unique_id = host->host_no;
        host->max_cmd_len = IPR_MAX_CDB_LEN;
+       host->can_queue = ioa_cfg->max_cmds;
        pci_set_drvdata(pdev, ioa_cfg);
 
        p = &ioa_cfg->chip_cfg->regs;
@@ -8275,6 +8632,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
                t->init_feedback_reg = base + p->init_feedback_reg;
                t->dump_addr_reg = base + p->dump_addr_reg;
                t->dump_data_reg = base + p->dump_data_reg;
+               t->endian_swap_reg = base + p->endian_swap_reg;
        }
 }
 
@@ -8431,6 +8789,8 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        /* set SIS 32 or SIS 64 */
        ioa_cfg->sis64 = ioa_cfg->ipr_chip->sis_type == IPR_SIS64 ? 1 : 0;
        ioa_cfg->chip_cfg = ioa_cfg->ipr_chip->cfg;
+       ioa_cfg->clear_isr = ioa_cfg->chip_cfg->clear_isr;
+       ioa_cfg->max_cmds = ioa_cfg->chip_cfg->max_cmds;
 
        if (ipr_transop_timeout)
                ioa_cfg->transop_timeout = ipr_transop_timeout;
@@ -8509,14 +8869,14 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        if (rc != PCIBIOS_SUCCESSFUL) {
                dev_err(&pdev->dev, "Failed to save PCI config space\n");
                rc = -EIO;
-               goto cleanup_nomem;
+               goto out_msi_disable;
        }
 
        if ((rc = ipr_save_pcix_cmd_reg(ioa_cfg)))
-               goto cleanup_nomem;
+               goto out_msi_disable;
 
        if ((rc = ipr_set_pcix_cmd_reg(ioa_cfg)))
-               goto cleanup_nomem;
+               goto out_msi_disable;
 
        if (ioa_cfg->sis64)
                ioa_cfg->cfg_table_size = (sizeof(struct ipr_config_table_hdr64)
@@ -8531,7 +8891,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        if (rc < 0) {
                dev_err(&pdev->dev,
                        "Couldn't allocate enough memory for device driver!\n");
-               goto cleanup_nomem;
+               goto out_msi_disable;
        }
 
        /*
@@ -8543,7 +8903,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
        uproc = readl(ioa_cfg->regs.sense_uproc_interrupt_reg32);
        if ((mask & IPR_PCII_HRRQ_UPDATED) == 0 || (uproc & IPR_UPROCI_RESET_ALERT))
                ioa_cfg->needs_hard_reset = 1;
-       if (interrupts & IPR_PCII_ERROR_INTERRUPTS)
+       if ((interrupts & IPR_PCII_ERROR_INTERRUPTS) || reset_devices)
                ioa_cfg->needs_hard_reset = 1;
        if (interrupts & IPR_PCII_IOA_UNIT_CHECKED)
                ioa_cfg->ioa_unit_checked = 1;
@@ -8576,10 +8936,10 @@ out:
 
 cleanup_nolog:
        ipr_free_mem(ioa_cfg);
-cleanup_nomem:
-       iounmap(ipr_regs);
 out_msi_disable:
        pci_disable_msi(pdev);
+cleanup_nomem:
+       iounmap(ipr_regs);
 out_release_regions:
        pci_release_regions(pdev);
 out_scsi_host_put:
@@ -8660,7 +9020,7 @@ static void __ipr_remove(struct pci_dev *pdev)
 
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
        wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
-       flush_scheduled_work();
+       flush_work_sync(&ioa_cfg->work_q);
        spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
 
        spin_lock(&ipr_driver_lock);
@@ -8830,6 +9190,8 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
        { 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_57CC, 0, 0, 0 },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0,
              IPR_USE_LONG_TRANSOP_TIMEOUT | IPR_USE_PCI_WARM_RESET },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
@@ -8848,15 +9210,19 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574D, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B2, 0, 0, 0 },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2,
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2,
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C3, 0, 0, 0 },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2,
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C4, 0, 0, 0 },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B4, 0, 0, 0 },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2,
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B1, 0, 0, 0 },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2,
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C6, 0, 0, 0 },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2,
-               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575D, 0, 0, 0 },
-       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2,
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C8, 0, 0, 0 },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57CE, 0, 0, 0 },
        { }
 };