]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - drivers/scsi/aacraid/linit.c
scsi: aacraid: Log count info of scsi cmds before reset
[mirror_ubuntu-zesty-kernel.git] / drivers / scsi / aacraid / linit.c
index 3ecbf20ca29f96b970cd4b14c38eb3fdbb3b1511..0a8d303c8bc98dfc7025031c92326235d2362ece 100644 (file)
@@ -6,7 +6,8 @@
  * Adaptec aacraid device driver for Linux.
  *
  * Copyright (c) 2000-2010 Adaptec, Inc.
- *               2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
+ *               2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
+ *              2016-2017 Microsemi Corp. (aacraid@microsemi.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
@@ -57,7 +58,7 @@
 
 #include "aacraid.h"
 
-#define AAC_DRIVER_VERSION             "1.2-1"
+#define AAC_DRIVER_VERSION             "1.2.1"
 #ifndef AAC_DRIVER_BRANCH
 #define AAC_DRIVER_BRANCH              ""
 #endif
@@ -401,61 +402,112 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev,
 static int aac_slave_configure(struct scsi_device *sdev)
 {
        struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
+       int chn, tid;
+       unsigned int depth = 0;
+       unsigned int set_timeout = 0;
+       bool set_qd_dev_type = false;
+       u8 devtype = 0;
+
+       chn = aac_logical_to_phys(sdev_channel(sdev));
+       tid = sdev_id(sdev);
+       if (chn < AAC_MAX_BUSES && tid < AAC_MAX_TARGETS && aac->sa_firmware) {
+               devtype = aac->hba_map[chn][tid].devtype;
+
+               if (devtype == AAC_DEVTYPE_NATIVE_RAW)
+                       depth = aac->hba_map[chn][tid].qd_limit;
+               else if (devtype == AAC_DEVTYPE_ARC_RAW)
+                       set_qd_dev_type = true;
+
+               set_timeout = 1;
+               goto common_config;
+       }
+
        if (aac->jbod && (sdev->type == TYPE_DISK))
                sdev->removable = 1;
-       if ((sdev->type == TYPE_DISK) &&
-                       (sdev_channel(sdev) != CONTAINER_CHANNEL) &&
-                       (!aac->jbod || sdev->inq_periph_qual) &&
-                       (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))) {
+
+       if (sdev->type == TYPE_DISK
+        && sdev_channel(sdev) != CONTAINER_CHANNEL
+        && (!aac->jbod || sdev->inq_periph_qual)
+        && (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))) {
+
                if (expose_physicals == 0)
                        return -ENXIO;
+
                if (expose_physicals < 0)
                        sdev->no_uld_attach = 1;
        }
-       if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
-                       (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) &&
-                       !sdev->no_uld_attach) {
+
+       if (sdev->tagged_supported
+        &&  sdev->type == TYPE_DISK
+        &&  (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
+        && !sdev->no_uld_attach) {
+
                struct scsi_device * dev;
                struct Scsi_Host *host = sdev->host;
                unsigned num_lsu = 0;
                unsigned num_one = 0;
-               unsigned depth;
                unsigned cid;
 
-               /*
-                * Firmware has an individual device recovery time typically
-                * of 35 seconds, give us a margin.
-                */
-               if (sdev->request_queue->rq_timeout < (45 * HZ))
-                       blk_queue_rq_timeout(sdev->request_queue, 45*HZ);
+               set_timeout = 1;
+
                for (cid = 0; cid < aac->maximum_num_containers; ++cid)
                        if (aac->fsa_dev[cid].valid)
                                ++num_lsu;
+
                __shost_for_each_device(dev, host) {
-                       if (dev->tagged_supported && (dev->type == TYPE_DISK) &&
-                                       (!aac->raid_scsi_mode ||
-                                               (sdev_channel(sdev) != 2)) &&
-                                       !dev->no_uld_attach) {
+                       if (dev->tagged_supported
+                        && dev->type == TYPE_DISK
+                        && (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
+                        && !dev->no_uld_attach) {
                                if ((sdev_channel(dev) != CONTAINER_CHANNEL)
-                                || !aac->fsa_dev[sdev_id(dev)].valid)
+                                || !aac->fsa_dev[sdev_id(dev)].valid) {
                                        ++num_lsu;
-                       } else
+                               }
+                       } else {
                                ++num_one;
+                       }
                }
+
                if (num_lsu == 0)
                        ++num_lsu;
+
                depth = (host->can_queue - num_one) / num_lsu;
-               if (depth > 256)
-                       depth = 256;
-               else if (depth < 2)
-                       depth = 2;
-               scsi_change_queue_depth(sdev, depth);
-       } else {
-               scsi_change_queue_depth(sdev, 1);
 
-               sdev->tagged_supported = 1;
+               if (sdev_channel(sdev) != NATIVE_CHANNEL)
+                       goto common_config;
+
+               set_qd_dev_type = true;
+
        }
 
+common_config:
+
+       /*
+        * Check if SATA drive
+        */
+       if (set_qd_dev_type) {
+               if (strncmp(sdev->vendor, "ATA", 3) == 0)
+                       depth = 32;
+               else
+                       depth = 64;
+       }
+
+       /*
+        * Firmware has an individual device recovery time typically
+        * of 35 seconds, give us a margin.
+        */
+       if (set_timeout && sdev->request_queue->rq_timeout < (45 * HZ))
+               blk_queue_rq_timeout(sdev->request_queue, 45*HZ);
+
+       if (depth > 256)
+               depth = 256;
+       else if (depth < 1)
+               depth = 1;
+
+       scsi_change_queue_depth(sdev, depth);
+
+       sdev->tagged_supported = 1;
+
        return 0;
 }
 
@@ -470,6 +522,15 @@ static int aac_slave_configure(struct scsi_device *sdev)
 
 static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
 {
+       struct aac_dev *aac = (struct aac_dev *)(sdev->host->hostdata);
+       int chn, tid, is_native_device = 0;
+
+       chn = aac_logical_to_phys(sdev_channel(sdev));
+       tid = sdev_id(sdev);
+       if (chn < AAC_MAX_BUSES && tid < AAC_MAX_TARGETS &&
+               aac->hba_map[chn][tid].devtype == AAC_DEVTYPE_NATIVE_RAW)
+               is_native_device = 1;
+
        if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
            (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
                struct scsi_device * dev;
@@ -491,9 +552,12 @@ static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
                else if (depth < 2)
                        depth = 2;
                return scsi_change_queue_depth(sdev, depth);
+       } else if (is_native_device) {
+               scsi_change_queue_depth(sdev, aac->hba_map[chn][tid].qd_limit);
+       } else {
+               scsi_change_queue_depth(sdev, 1);
        }
-
-       return scsi_change_queue_depth(sdev, 1);
+       return sdev->queue_depth;
 }
 
 static ssize_t aac_show_raid_level(struct device *dev, struct device_attribute *attr, char *buf)
@@ -516,8 +580,39 @@ static struct device_attribute aac_raid_level_attr = {
        .show = aac_show_raid_level
 };
 
+static ssize_t aac_show_unique_id(struct device *dev,
+            struct device_attribute *attr, char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct aac_dev *aac = (struct aac_dev *)(sdev->host->hostdata);
+       unsigned char sn[16];
+
+       memset(sn, 0, sizeof(sn));
+
+       if (sdev_channel(sdev) == CONTAINER_CHANNEL)
+               memcpy(sn, aac->fsa_dev[sdev_id(sdev)].identifier, sizeof(sn));
+
+       return snprintf(buf, 16 * 2 + 2,
+               "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
+               sn[0], sn[1], sn[2], sn[3],
+               sn[4], sn[5], sn[6], sn[7],
+               sn[8], sn[9], sn[10], sn[11],
+               sn[12], sn[13], sn[14], sn[15]);
+}
+
+static struct device_attribute aac_unique_id_attr = {
+       .attr = {
+               .name = "unique_id",
+               .mode = 0444,
+       },
+       .show = aac_show_unique_id
+};
+
+
+
 static struct device_attribute *aac_dev_attrs[] = {
        &aac_raid_level_attr,
+       &aac_unique_id_attr,
        NULL,
 };
 
@@ -529,51 +624,191 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg)
        return aac_do_ioctl(dev, cmd, arg);
 }
 
+static int get_num_of_incomplete_fibs(struct aac_dev *aac)
+{
+
+       unsigned long flags;
+       struct scsi_device *sdev = NULL;
+       struct Scsi_Host *shost = aac->scsi_host_ptr;
+       struct scsi_cmnd *scmnd = NULL;
+       struct device *ctrl_dev;
+
+       int mlcnt  = 0;
+       int llcnt  = 0;
+       int ehcnt  = 0;
+       int fwcnt  = 0;
+       int krlcnt = 0;
+
+       __shost_for_each_device(sdev, shost) {
+               spin_lock_irqsave(&sdev->list_lock, flags);
+               list_for_each_entry(scmnd, &sdev->cmd_list, list) {
+                       switch (scmnd->SCp.phase) {
+                       case AAC_OWNER_FIRMWARE:
+                               fwcnt++;
+                               break;
+                       case AAC_OWNER_ERROR_HANDLER:
+                               ehcnt++;
+                               break;
+                       case AAC_OWNER_LOWLEVEL:
+                               llcnt++;
+                               break;
+                       case AAC_OWNER_MIDLEVEL:
+                               mlcnt++;
+                               break;
+                       default:
+                               krlcnt++;
+                               break;
+                       }
+               }
+               spin_unlock_irqrestore(&sdev->list_lock, flags);
+       }
+
+       ctrl_dev = &aac->pdev->dev;
+
+       dev_info(ctrl_dev, "outstanding cmd: midlevel-%d\n", mlcnt);
+       dev_info(ctrl_dev, "outstanding cmd: lowlevel-%d\n", llcnt);
+       dev_info(ctrl_dev, "outstanding cmd: error handler-%d\n", ehcnt);
+       dev_info(ctrl_dev, "outstanding cmd: firmware-%d\n", fwcnt);
+       dev_info(ctrl_dev, "outstanding cmd: kernel-%d\n", krlcnt);
+
+       return mlcnt + llcnt + ehcnt + fwcnt;
+}
+
 static int aac_eh_abort(struct scsi_cmnd* cmd)
 {
        struct scsi_device * dev = cmd->device;
        struct Scsi_Host * host = dev->host;
        struct aac_dev * aac = (struct aac_dev *)host->hostdata;
-       int count;
+       int count, found;
+       u32 bus, cid;
        int ret = FAILED;
 
-       printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%llu)\n",
-               AAC_DRIVERNAME,
-               host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun);
-       switch (cmd->cmnd[0]) {
-       case SERVICE_ACTION_IN_16:
-               if (!(aac->raw_io_interface) ||
-                   !(aac->raw_io_64) ||
-                   ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
-                       break;
-       case INQUIRY:
-       case READ_CAPACITY:
-               /* Mark associated FIB to not complete, eh handler does this */
+       bus = aac_logical_to_phys(scmd_channel(cmd));
+       cid = scmd_id(cmd);
+       if (aac->hba_map[bus][cid].devtype == AAC_DEVTYPE_NATIVE_RAW) {
+               struct fib *fib;
+               struct aac_hba_tm_req *tmf;
+               int status;
+               u64 address;
+               __le32 managed_request_id;
+
+               pr_err("%s: Host adapter abort request (%d,%d,%d,%d)\n",
+                AAC_DRIVERNAME,
+                host->host_no, sdev_channel(dev), sdev_id(dev), (int)dev->lun);
+
+               found = 0;
                for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
-                       struct fib * fib = &aac->fibs[count];
-                       if (fib->hw_fib_va->header.XferState &&
-                         (fib->flags & FIB_CONTEXT_FLAG) &&
-                         (fib->callback_data == cmd)) {
-                               fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
-                               cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+                       fib = &aac->fibs[count];
+                       if (*(u8 *)fib->hw_fib_va != 0 &&
+                               (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) &&
+                               (fib->callback_data == cmd)) {
+                               found = 1;
+                               managed_request_id = ((struct aac_hba_cmd_req *)
+                                       fib->hw_fib_va)->request_id;
+                               break;
+                       }
+               }
+               if (!found)
+                       return ret;
+
+               /* start a HBA_TMF_ABORT_TASK TMF request */
+               fib = aac_fib_alloc(aac);
+               if (!fib)
+                       return ret;
+
+               tmf = (struct aac_hba_tm_req *)fib->hw_fib_va;
+               memset(tmf, 0, sizeof(*tmf));
+               tmf->tmf = HBA_TMF_ABORT_TASK;
+               tmf->it_nexus = aac->hba_map[bus][cid].rmw_nexus;
+               tmf->lun[1] = cmd->device->lun;
+
+               address = (u64)fib->hw_error_pa;
+               tmf->error_ptr_hi = cpu_to_le32((u32)(address >> 32));
+               tmf->error_ptr_lo = cpu_to_le32((u32)(address & 0xffffffff));
+               tmf->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
+
+               fib->hbacmd_size = sizeof(*tmf);
+               cmd->SCp.sent_command = 0;
+
+               status = aac_hba_send(HBA_IU_TYPE_SCSI_TM_REQ, fib,
+                                 (fib_callback) aac_hba_callback,
+                                 (void *) cmd);
+
+               /* Wait up to 15 secs for completion */
+               for (count = 0; count < 15; ++count) {
+                       if (cmd->SCp.sent_command) {
                                ret = SUCCESS;
+                               break;
                        }
+                       msleep(1000);
                }
-               break;
-       case TEST_UNIT_READY:
-               /* Mark associated FIB to not complete, eh handler does this */
-               for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
-                       struct scsi_cmnd * command;
-                       struct fib * fib = &aac->fibs[count];
-                       if ((fib->hw_fib_va->header.XferState & cpu_to_le32(Async | NoResponseExpected)) &&
-                         (fib->flags & FIB_CONTEXT_FLAG) &&
-                         ((command = fib->callback_data)) &&
-                         (command->device == cmd->device)) {
-                               fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
-                               command->SCp.phase = AAC_OWNER_ERROR_HANDLER;
-                               if (command == cmd)
+
+               if (ret != SUCCESS)
+                       pr_err("%s: Host adapter abort request timed out\n",
+                       AAC_DRIVERNAME);
+       } else {
+               pr_err(
+                       "%s: Host adapter abort request.\n"
+                       "%s: Outstanding commands on (%d,%d,%d,%d):\n",
+                       AAC_DRIVERNAME, AAC_DRIVERNAME,
+                       host->host_no, sdev_channel(dev), sdev_id(dev),
+                       (int)dev->lun);
+               switch (cmd->cmnd[0]) {
+               case SERVICE_ACTION_IN_16:
+                       if (!(aac->raw_io_interface) ||
+                           !(aac->raw_io_64) ||
+                           ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
+                               break;
+               case INQUIRY:
+               case READ_CAPACITY:
+                       /*
+                        * Mark associated FIB to not complete,
+                        * eh handler does this
+                        */
+                       for (count = 0;
+                               count < (host->can_queue + AAC_NUM_MGT_FIB);
+                               ++count) {
+                               struct fib *fib = &aac->fibs[count];
+
+                               if (fib->hw_fib_va->header.XferState &&
+                               (fib->flags & FIB_CONTEXT_FLAG) &&
+                               (fib->callback_data == cmd)) {
+                                       fib->flags |=
+                                               FIB_CONTEXT_FLAG_TIMED_OUT;
+                                       cmd->SCp.phase =
+                                               AAC_OWNER_ERROR_HANDLER;
                                        ret = SUCCESS;
+                               }
                        }
+                       break;
+               case TEST_UNIT_READY:
+                       /*
+                        * Mark associated FIB to not complete,
+                        * eh handler does this
+                        */
+                       for (count = 0;
+                               count < (host->can_queue + AAC_NUM_MGT_FIB);
+                               ++count) {
+                               struct scsi_cmnd *command;
+                               struct fib *fib = &aac->fibs[count];
+
+                               command = fib->callback_data;
+
+                               if ((fib->hw_fib_va->header.XferState &
+                                       cpu_to_le32
+                                       (Async | NoResponseExpected)) &&
+                                       (fib->flags & FIB_CONTEXT_FLAG) &&
+                                       ((command)) &&
+                                       (command->device == cmd->device)) {
+                                       fib->flags |=
+                                               FIB_CONTEXT_FLAG_TIMED_OUT;
+                                       command->SCp.phase =
+                                               AAC_OWNER_ERROR_HANDLER;
+                                       if (command == cmd)
+                                               ret = SUCCESS;
+                               }
+                       }
+                       break;
                }
        }
        return ret;
@@ -588,70 +823,131 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
 {
        struct scsi_device * dev = cmd->device;
        struct Scsi_Host * host = dev->host;
-       struct scsi_cmnd * command;
-       int count;
        struct aac_dev * aac = (struct aac_dev *)host->hostdata;
-       unsigned long flags;
+       int count;
+       u32 bus, cid;
+       int ret = FAILED;
 
-       /* Mark the associated FIB to not complete, eh handler does this */
-       for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
-               struct fib * fib = &aac->fibs[count];
-               if (fib->hw_fib_va->header.XferState &&
-                 (fib->flags & FIB_CONTEXT_FLAG) &&
-                 (fib->callback_data == cmd)) {
-                       fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
-                       cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+       bus = aac_logical_to_phys(scmd_channel(cmd));
+       cid = scmd_id(cmd);
+       if (bus < AAC_MAX_BUSES && cid < AAC_MAX_TARGETS &&
+               aac->hba_map[bus][cid].devtype == AAC_DEVTYPE_NATIVE_RAW) {
+               struct fib *fib;
+               int status;
+               u64 address;
+               u8 command;
+
+               pr_err("%s: Host adapter reset request. SCSI hang ?\n",
+                       AAC_DRIVERNAME);
+
+               fib = aac_fib_alloc(aac);
+               if (!fib)
+                       return ret;
+
+
+               if (aac->hba_map[bus][cid].reset_state == 0) {
+                       struct aac_hba_tm_req *tmf;
+
+                       /* start a HBA_TMF_LUN_RESET TMF request */
+                       tmf = (struct aac_hba_tm_req *)fib->hw_fib_va;
+                       memset(tmf, 0, sizeof(*tmf));
+                       tmf->tmf = HBA_TMF_LUN_RESET;
+                       tmf->it_nexus = aac->hba_map[bus][cid].rmw_nexus;
+                       tmf->lun[1] = cmd->device->lun;
+
+                       address = (u64)fib->hw_error_pa;
+                       tmf->error_ptr_hi = cpu_to_le32
+                                       ((u32)(address >> 32));
+                       tmf->error_ptr_lo = cpu_to_le32
+                                       ((u32)(address & 0xffffffff));
+                       tmf->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
+                       fib->hbacmd_size = sizeof(*tmf);
+
+                       command = HBA_IU_TYPE_SCSI_TM_REQ;
+                       aac->hba_map[bus][cid].reset_state++;
+               } else if (aac->hba_map[bus][cid].reset_state >= 1) {
+                       struct aac_hba_reset_req *rst;
+
+                       /* already tried, start a hard reset now */
+                       rst = (struct aac_hba_reset_req *)fib->hw_fib_va;
+                       memset(rst, 0, sizeof(*rst));
+                       /* reset_type is already zero... */
+                       rst->it_nexus = aac->hba_map[bus][cid].rmw_nexus;
+
+                       address = (u64)fib->hw_error_pa;
+                       rst->error_ptr_hi = cpu_to_le32((u32)(address >> 32));
+                       rst->error_ptr_lo = cpu_to_le32
+                               ((u32)(address & 0xffffffff));
+                       rst->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
+                       fib->hbacmd_size = sizeof(*rst);
+
+                       command = HBA_IU_TYPE_SATA_REQ;
+                       aac->hba_map[bus][cid].reset_state = 0;
                }
-       }
-       printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n",
-                                       AAC_DRIVERNAME);
+               cmd->SCp.sent_command = 0;
 
-       if ((count = aac_check_health(aac)))
-               return count;
-       /*
-        * Wait for all commands to complete to this specific
-        * target (block maximum 60 seconds).
-        */
-       for (count = 60; count; --count) {
-               int active = aac->in_reset;
+               status = aac_hba_send(command, fib,
+                                 (fib_callback) aac_hba_callback,
+                                 (void *) cmd);
 
-               if (active == 0)
-               __shost_for_each_device(dev, host) {
-                       spin_lock_irqsave(&dev->list_lock, flags);
-                       list_for_each_entry(command, &dev->cmd_list, list) {
-                               if ((command != cmd) &&
-                                   (command->SCp.phase == AAC_OWNER_FIRMWARE)) {
-                                       active++;
-                                       break;
-                               }
-                       }
-                       spin_unlock_irqrestore(&dev->list_lock, flags);
-                       if (active)
+               /* Wait up to 15 seconds for completion */
+               for (count = 0; count < 15; ++count) {
+                       if (cmd->SCp.sent_command) {
+                               ret = SUCCESS;
                                break;
+                       }
+                       msleep(1000);
+               }
+
+               if (ret != SUCCESS)
+                       pr_err("%s: Host adapter reset request timed out\n",
+                       AAC_DRIVERNAME);
+       } else {
 
+               /* Mark the assoc. FIB to not complete, eh handler does this */
+               for (count = 0;
+                       count < (host->can_queue + AAC_NUM_MGT_FIB);
+                       ++count) {
+                       struct fib *fib = &aac->fibs[count];
+
+                       if (fib->hw_fib_va->header.XferState &&
+                               (fib->flags & FIB_CONTEXT_FLAG) &&
+                               (fib->callback_data == cmd)) {
+                               fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
+                               cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+                       }
                }
+
+               pr_err("%s: Host adapter reset request. SCSI hang ?\n",
+                                       AAC_DRIVERNAME);
+
+               count = get_num_of_incomplete_fibs(aac);
+               if (count == 0)
+                       return SUCCESS;
+
                /*
-                * We can exit If all the commands are complete
+                * This adapter needs a blind reset, only do so for
+                * Adapters that support a register, instead of a commanded,
+                * reset.
                 */
-               if (active == 0)
-                       return SUCCESS;
-               ssleep(1);
+               if (((aac->supplement_adapter_info.supported_options2 &
+                         AAC_OPTION_MU_RESET) ||
+                         (aac->supplement_adapter_info.supported_options2 &
+                         AAC_OPTION_DOORBELL_RESET)) &&
+                         aac_check_reset &&
+                         ((aac_check_reset != 1) ||
+                          !(aac->supplement_adapter_info.supported_options2 &
+                           AAC_OPTION_IGNORE_RESET))) {
+                       /* Bypass wait for command quiesce */
+                       aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET);
+               }
+               ret = SUCCESS;
        }
-       printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
        /*
-        * This adapter needs a blind reset, only do so for Adapters that
-        * support a register, instead of a commanded, reset.
+        * Cause an immediate retry of the command with a ten second delay
+        * after successful tur
         */
-       if (((aac->supplement_adapter_info.SupportedOptions2 &
-         AAC_OPTION_MU_RESET) ||
-         (aac->supplement_adapter_info.SupportedOptions2 &
-         AAC_OPTION_DOORBELL_RESET)) &&
-         aac_check_reset &&
-         ((aac_check_reset != 1) ||
-          !(aac->supplement_adapter_info.SupportedOptions2 &
-           AAC_OPTION_IGNORE_RESET)))
-               aac_reset_adapter(aac, 2); /* Bypass wait for command quiesce */
-       return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
+       return ret;
 }
 
 /**
@@ -772,8 +1068,8 @@ static ssize_t aac_show_model(struct device *device,
        struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
        int len;
 
-       if (dev->supplement_adapter_info.AdapterTypeText[0]) {
-               char * cp = dev->supplement_adapter_info.AdapterTypeText;
+       if (dev->supplement_adapter_info.adapter_type_text[0]) {
+               char *cp = dev->supplement_adapter_info.adapter_type_text;
                while (*cp && *cp != ' ')
                        ++cp;
                while (*cp == ' ')
@@ -789,18 +1085,20 @@ static ssize_t aac_show_vendor(struct device *device,
                               struct device_attribute *attr, char *buf)
 {
        struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+       struct aac_supplement_adapter_info *sup_adap_info;
        int len;
 
-       if (dev->supplement_adapter_info.AdapterTypeText[0]) {
-               char * cp = dev->supplement_adapter_info.AdapterTypeText;
+       sup_adap_info = &dev->supplement_adapter_info;
+       if (sup_adap_info->adapter_type_text[0]) {
+               char *cp = sup_adap_info->adapter_type_text;
                while (*cp && *cp != ' ')
                        ++cp;
                len = snprintf(buf, PAGE_SIZE, "%.*s\n",
-                 (int)(cp - (char *)dev->supplement_adapter_info.AdapterTypeText),
-                 dev->supplement_adapter_info.AdapterTypeText);
+                       (int)(cp - (char *)sup_adap_info->adapter_type_text),
+                                       sup_adap_info->adapter_type_text);
        } else
                len = snprintf(buf, PAGE_SIZE, "%s\n",
-                 aac_drivers[dev->cardtype].vname);
+                       aac_drivers[dev->cardtype].vname);
        return len;
 }
 
@@ -821,7 +1119,7 @@ static ssize_t aac_show_flags(struct device *cdev,
                                "SAI_READ_CAPACITY_16\n");
        if (dev->jbod)
                len += snprintf(buf + len, PAGE_SIZE - len, "SUPPORTED_JBOD\n");
-       if (dev->supplement_adapter_info.SupportedOptions2 &
+       if (dev->supplement_adapter_info.supported_options2 &
                AAC_OPTION_POWER_MANAGEMENT)
                len += snprintf(buf + len, PAGE_SIZE - len,
                                "SUPPORTED_POWER_MANAGEMENT\n");
@@ -872,6 +1170,13 @@ static ssize_t aac_show_bios_version(struct device *device,
        return len;
 }
 
+static ssize_t aac_show_driver_version(struct device *device,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", aac_driver_version);
+}
+
 static ssize_t aac_show_serial_number(struct device *device,
                               struct device_attribute *attr, char *buf)
 {
@@ -882,12 +1187,12 @@ static ssize_t aac_show_serial_number(struct device *device,
                len = snprintf(buf, 16, "%06X\n",
                  le32_to_cpu(dev->adapter_info.serial[0]));
        if (len &&
-         !memcmp(&dev->supplement_adapter_info.MfgPcbaSerialNo[
-           sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)-len],
+         !memcmp(&dev->supplement_adapter_info.mfg_pcba_serial_no[
+           sizeof(dev->supplement_adapter_info.mfg_pcba_serial_no)-len],
          buf, len-1))
                len = snprintf(buf, 16, "%.*s\n",
-                 (int)sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo),
-                 dev->supplement_adapter_info.MfgPcbaSerialNo);
+                 (int)sizeof(dev->supplement_adapter_info.mfg_pcba_serial_no),
+                 dev->supplement_adapter_info.mfg_pcba_serial_no);
 
        return min(len, 16);
 }
@@ -911,10 +1216,16 @@ static ssize_t aac_store_reset_adapter(struct device *device,
                                       const char *buf, size_t count)
 {
        int retval = -EACCES;
+       int bled = 0;
+       struct aac_dev *aac;
+
 
        if (!capable(CAP_SYS_ADMIN))
                return retval;
-       retval = aac_reset_adapter((struct aac_dev*)class_to_shost(device)->hostdata, buf[0] == '!');
+
+       aac = (struct aac_dev *)class_to_shost(device)->hostdata;
+       bled = buf[0] == '!' ? 1:0;
+       retval = aac_reset_adapter(aac, bled, IOP_HWSOFT_RESET);
        if (retval >= 0)
                retval = count;
        return retval;
@@ -976,6 +1287,13 @@ static struct device_attribute aac_bios_version = {
        },
        .show = aac_show_bios_version,
 };
+static struct device_attribute aac_lld_version = {
+       .attr = {
+               .name = "driver_version",
+               .mode = 0444,
+       },
+       .show = aac_show_driver_version,
+};
 static struct device_attribute aac_serial_number = {
        .attr = {
                .name = "serial_number",
@@ -1013,6 +1331,7 @@ static struct device_attribute *aac_attrs[] = {
        &aac_kernel_version,
        &aac_monitor_version,
        &aac_bios_version,
+       &aac_lld_version,
        &aac_serial_number,
        &aac_max_channel,
        &aac_max_id,
@@ -1070,6 +1389,7 @@ static void __aac_shutdown(struct aac_dev * aac)
 {
        int i;
 
+       aac->adapter_shutdown = 1;
        aac_send_shutdown(aac);
 
        if (aac->aif_thread) {
@@ -1122,6 +1442,7 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        int error = -ENODEV;
        int unique_id = 0;
        u64 dmamask;
+       int mask_bits = 0;
        extern int aac_sync_mode;
 
        /*
@@ -1145,18 +1466,32 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                goto out;
        error = -ENODEV;
 
+       if (!(aac_drivers[index].quirks & AAC_QUIRK_SRC)) {
+               error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               if (error) {
+                       dev_err(&pdev->dev, "PCI 32 BIT dma mask set failed");
+                       goto out_disable_pdev;
+               }
+       }
+
        /*
         * If the quirk31 bit is set, the adapter needs adapter
         * to driver communication memory to be allocated below 2gig
         */
-       if (aac_drivers[index].quirks & AAC_QUIRK_31BIT)
+       if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) {
                dmamask = DMA_BIT_MASK(31);
-       else
+               mask_bits = 31;
+       } else {
                dmamask = DMA_BIT_MASK(32);
+               mask_bits = 32;
+       }
 
-       if (pci_set_dma_mask(pdev, dmamask) ||
-                       pci_set_consistent_dma_mask(pdev, dmamask))
+       error = pci_set_consistent_dma_mask(pdev, dmamask);
+       if (error) {
+               dev_err(&pdev->dev, "PCI %d B consistent dma mask set failed\n"
+                               , mask_bits);
                goto out_disable_pdev;
+       }
 
        pci_set_master(pdev);
 
@@ -1220,15 +1555,6 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                goto out_deinit;
        }
 
-       /*
-        * If we had set a smaller DMA mask earlier, set it to 4gig
-        * now since the adapter can dma data to at least a 4gig
-        * address space.
-        */
-       if (aac_drivers[index].quirks & AAC_QUIRK_31BIT)
-               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))
-                       goto out_deinit;
-
        aac->maximum_num_channels = aac_drivers[index].channels;
        error = aac_get_adapter_info(aac);
        if (error < 0)
@@ -1285,7 +1611,7 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        else
                shost->this_id = shost->max_id;
 
-       if (aac_drivers[index].quirks & AAC_QUIRK_SRC)
+       if (!aac->sa_firmware && aac_drivers[index].quirks & AAC_QUIRK_SRC)
                aac_intr_normal(aac, 0, 2, 0, NULL);
 
        /*
@@ -1311,8 +1637,8 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
  out_unmap:
        aac_fib_map_free(aac);
        if (aac->comm_addr)
-               pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
-                 aac->comm_phys);
+               dma_free_coherent(&aac->pdev->dev, aac->comm_size,
+                                 aac->comm_addr, aac->comm_phys);
        kfree(aac->queues);
        aac_adapter_ioremap(aac, 0);
        kfree(aac->fibs);
@@ -1327,35 +1653,12 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
 static void aac_release_resources(struct aac_dev *aac)
 {
-       int i;
-
        aac_adapter_disable_int(aac);
-       if (aac->pdev->device == PMC_DEVICE_S6 ||
-           aac->pdev->device == PMC_DEVICE_S7 ||
-           aac->pdev->device == PMC_DEVICE_S8 ||
-           aac->pdev->device == PMC_DEVICE_S9) {
-               if (aac->max_msix > 1) {
-                       for (i = 0; i < aac->max_msix; i++)
-                               free_irq(pci_irq_vector(aac->pdev, i),
-                                       &(aac->aac_msix[i]));
-               } else {
-                       free_irq(aac->pdev->irq, &(aac->aac_msix[0]));
-               }
-       } else {
-               free_irq(aac->pdev->irq, aac);
-       }
-       if (aac->msi)
-               pci_disable_msi(aac->pdev);
-       else if (aac->max_msix > 1)
-               pci_disable_msix(aac->pdev);
-
+       aac_free_irq(aac);
 }
 
 static int aac_acquire_resources(struct aac_dev *dev)
 {
-       int i, j;
-       int instance = dev->id;
-       const char *name = dev->name;
        unsigned long status;
        /*
         *      First clear out all interrupts.  Then enable the one's that we
@@ -1377,37 +1680,8 @@ static int aac_acquire_resources(struct aac_dev *dev)
        if (dev->msi_enabled)
                aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
 
-       if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
-               for (i = 0; i < dev->max_msix; i++) {
-                       dev->aac_msix[i].vector_no = i;
-                       dev->aac_msix[i].dev = dev;
-
-                       if (request_irq(pci_irq_vector(dev->pdev, i),
-                                       dev->a_ops.adapter_intr,
-                                       0, "aacraid", &(dev->aac_msix[i]))) {
-                               printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
-                                               name, instance, i);
-                               for (j = 0 ; j < i ; j++)
-                                       free_irq(pci_irq_vector(dev->pdev, j),
-                                                &(dev->aac_msix[j]));
-                               pci_disable_msix(dev->pdev);
-                               goto error_iounmap;
-                       }
-               }
-       } else {
-               dev->aac_msix[0].vector_no = 0;
-               dev->aac_msix[0].dev = dev;
-
-               if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
-                       IRQF_SHARED, "aacraid",
-                       &(dev->aac_msix[0])) < 0) {
-                       if (dev->msi)
-                               pci_disable_msi(dev->pdev);
-                       printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
-                                       name, instance);
-                       goto error_iounmap;
-               }
-       }
+       if (aac_acquire_irq(dev))
+               goto error_iounmap;
 
        aac_adapter_enable_int(dev);
 
@@ -1418,9 +1692,9 @@ static int aac_acquire_resources(struct aac_dev *dev)
 
        if (!dev->sync_mode) {
                /* After EEH recovery or suspend resume, max_msix count
-                * may change, therfore updating in init as well.
+                * may change, therefore updating in init as well.
                 */
-               dev->init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix);
+               dev->init->r7.no_of_msix_vectors = cpu_to_le32(dev->max_msix);
                aac_adapter_start(dev);
        }
        return 0;
@@ -1500,8 +1774,8 @@ static void aac_remove_one(struct pci_dev *pdev)
 
        __aac_shutdown(aac);
        aac_fib_map_free(aac);
-       pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
-                       aac->comm_phys);
+       dma_free_coherent(&aac->pdev->dev, aac->comm_size, aac->comm_addr,
+                         aac->comm_phys);
        kfree(aac->queues);
 
        aac_adapter_ioremap(aac, 0);