[SCSI] hpsa: add P2000 to list of shared SAS devices
[linux-2.6-microblaze.git] / drivers / scsi / hpsa.c
index 415ad4f..cffc7bb 100644 (file)
@@ -273,7 +273,7 @@ static ssize_t host_show_transport_mode(struct device *dev,
                        "performant" : "simple");
 }
 
-/* List of controllers which cannot be reset on kexec with reset_devices */
+/* List of controllers which cannot be hard reset on kexec with reset_devices */
 static u32 unresettable_controller[] = {
        0x324a103C, /* Smart Array P712m */
        0x324b103C, /* SmartArray P711m */
@@ -291,16 +291,45 @@ static u32 unresettable_controller[] = {
        0x409D0E11, /* Smart Array 6400 EM */
 };
 
-static int ctlr_is_resettable(struct ctlr_info *h)
+/* List of controllers which cannot even be soft reset */
+static u32 soft_unresettable_controller[] = {
+       /* Exclude 640x boards.  These are two pci devices in one slot
+        * which share a battery backed cache module.  One controls the
+        * cache, the other accesses the cache through the one that controls
+        * it.  If we reset the one controlling the cache, the other will
+        * likely not be happy.  Just forbid resetting this conjoined mess.
+        * The 640x isn't really supported by hpsa anyway.
+        */
+       0x409C0E11, /* Smart Array 6400 */
+       0x409D0E11, /* Smart Array 6400 EM */
+};
+
+static int ctlr_is_hard_resettable(u32 board_id)
 {
        int i;
 
        for (i = 0; i < ARRAY_SIZE(unresettable_controller); i++)
-               if (unresettable_controller[i] == h->board_id)
+               if (unresettable_controller[i] == board_id)
+                       return 0;
+       return 1;
+}
+
+static int ctlr_is_soft_resettable(u32 board_id)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(soft_unresettable_controller); i++)
+               if (soft_unresettable_controller[i] == board_id)
                        return 0;
        return 1;
 }
 
+static int ctlr_is_resettable(u32 board_id)
+{
+       return ctlr_is_hard_resettable(board_id) ||
+               ctlr_is_soft_resettable(board_id);
+}
+
 static ssize_t host_show_resettable(struct device *dev,
        struct device_attribute *attr, char *buf)
 {
@@ -308,7 +337,7 @@ static ssize_t host_show_resettable(struct device *dev,
        struct Scsi_Host *shost = class_to_shost(dev);
 
        h = shost_to_hba(shost);
-       return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h));
+       return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h->board_id));
 }
 
 static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
@@ -929,13 +958,6 @@ static void hpsa_slave_destroy(struct scsi_device *sdev)
        /* nothing to do. */
 }
 
-static void hpsa_scsi_setup(struct ctlr_info *h)
-{
-       h->ndevices = 0;
-       h->scsi_host = NULL;
-       spin_lock_init(&h->devlock);
-}
-
 static void hpsa_free_sg_chain_blocks(struct ctlr_info *h)
 {
        int i;
@@ -1006,8 +1028,7 @@ static void hpsa_unmap_sg_chain_block(struct ctlr_info *h,
        pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE);
 }
 
-static void complete_scsi_command(struct CommandList *cp,
-       int timeout, u32 tag)
+static void complete_scsi_command(struct CommandList *cp)
 {
        struct scsi_cmnd *cmd;
        struct ctlr_info *h;
@@ -1570,6 +1591,7 @@ static unsigned char *msa2xxx_model[] = {
        "MSA2024",
        "MSA2312",
        "MSA2324",
+       "P2000 G3 SAS",
        NULL,
 };
 
@@ -2751,6 +2773,26 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
        }
 }
 
+static int __devinit hpsa_send_host_reset(struct ctlr_info *h,
+       unsigned char *scsi3addr, u8 reset_type)
+{
+       struct CommandList *c;
+
+       c = cmd_alloc(h);
+       if (!c)
+               return -ENOMEM;
+       fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0,
+               RAID_CTLR_LUNID, TYPE_MSG);
+       c->Request.CDB[1] = reset_type; /* fill_cmd defaults to target reset */
+       c->waiting = NULL;
+       enqueue_cmd_and_start_io(h, c);
+       /* Don't wait for completion, the reset won't complete.  Don't free
+        * the command either.  This is the last command we will send before
+        * re-initializing everything, so it doesn't matter and won't leak.
+        */
+       return 0;
+}
+
 static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
        void *buff, size_t size, u8 page_code, unsigned char *scsi3addr,
        int cmd_type)
@@ -2828,7 +2870,8 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                        c->Request.Type.Attribute = ATTR_SIMPLE;
                        c->Request.Type.Direction = XFER_NONE;
                        c->Request.Timeout = 0; /* Don't time out */
-                       c->Request.CDB[0] =  0x01; /* RESET_MSG is 0x01 */
+                       memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
+                       c->Request.CDB[0] =  cmd;
                        c->Request.CDB[1] = 0x03;  /* Reset target above */
                        /* If bytes 4-7 are zero, it means reset the */
                        /* LunID device */
@@ -2936,7 +2979,7 @@ static inline void finish_cmd(struct CommandList *c, u32 raw_tag)
 {
        removeQ(c);
        if (likely(c->cmd_type == CMD_SCSI))
-               complete_scsi_command(c, 0, raw_tag);
+               complete_scsi_command(c);
        else if (c->cmd_type == CMD_IOCTL_PEND)
                complete(c->waiting);
 }
@@ -2994,6 +3037,63 @@ static inline u32 process_nonindexed_cmd(struct ctlr_info *h,
        return next_command(h);
 }
 
+/* Some controllers, like p400, will give us one interrupt
+ * after a soft reset, even if we turned interrupts off.
+ * Only need to check for this in the hpsa_xxx_discard_completions
+ * functions.
+ */
+static int ignore_bogus_interrupt(struct ctlr_info *h)
+{
+       if (likely(!reset_devices))
+               return 0;
+
+       if (likely(h->interrupts_enabled))
+               return 0;
+
+       dev_info(&h->pdev->dev, "Received interrupt while interrupts disabled "
+               "(known firmware bug.)  Ignoring.\n");
+
+       return 1;
+}
+
+static irqreturn_t hpsa_intx_discard_completions(int irq, void *dev_id)
+{
+       struct ctlr_info *h = dev_id;
+       unsigned long flags;
+       u32 raw_tag;
+
+       if (ignore_bogus_interrupt(h))
+               return IRQ_NONE;
+
+       if (interrupt_not_for_us(h))
+               return IRQ_NONE;
+       spin_lock_irqsave(&h->lock, flags);
+       while (interrupt_pending(h)) {
+               raw_tag = get_next_completion(h);
+               while (raw_tag != FIFO_EMPTY)
+                       raw_tag = next_command(h);
+       }
+       spin_unlock_irqrestore(&h->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t hpsa_msix_discard_completions(int irq, void *dev_id)
+{
+       struct ctlr_info *h = dev_id;
+       unsigned long flags;
+       u32 raw_tag;
+
+       if (ignore_bogus_interrupt(h))
+               return IRQ_NONE;
+
+       spin_lock_irqsave(&h->lock, flags);
+       raw_tag = get_next_completion(h);
+       while (raw_tag != FIFO_EMPTY)
+               raw_tag = next_command(h);
+       spin_unlock_irqrestore(&h->lock, flags);
+       return IRQ_HANDLED;
+}
+
 static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id)
 {
        struct ctlr_info *h = dev_id;
@@ -3132,11 +3232,10 @@ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
        return 0;
 }
 
-#define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0)
 #define hpsa_noop(p) hpsa_message(p, 3, 0)
 
 static int hpsa_controller_hard_reset(struct pci_dev *pdev,
-       void * __iomem vaddr, bool use_doorbell)
+       void * __iomem vaddr, u32 use_doorbell)
 {
        u16 pmcsr;
        int pos;
@@ -3147,8 +3246,7 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
                 * other way using the doorbell register.
                 */
                dev_info(&pdev->dev, "using doorbell to reset controller\n");
-               writel(DOORBELL_CTLR_RESET, vaddr + SA5_DOORBELL);
-               msleep(1000);
+               writel(use_doorbell, vaddr + SA5_DOORBELL);
        } else { /* Try to do it the PCI power state way */
 
                /* Quoting from the Open CISS Specification: "The Power
@@ -3179,12 +3277,63 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
                pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
                pmcsr |= PCI_D0;
                pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
-
-               msleep(500);
        }
        return 0;
 }
 
+static __devinit void init_driver_version(char *driver_version, int len)
+{
+       memset(driver_version, 0, len);
+       strncpy(driver_version, "hpsa " HPSA_DRIVER_VERSION, len - 1);
+}
+
+static __devinit int write_driver_ver_to_cfgtable(
+       struct CfgTable __iomem *cfgtable)
+{
+       char *driver_version;
+       int i, size = sizeof(cfgtable->driver_version);
+
+       driver_version = kmalloc(size, GFP_KERNEL);
+       if (!driver_version)
+               return -ENOMEM;
+
+       init_driver_version(driver_version, size);
+       for (i = 0; i < size; i++)
+               writeb(driver_version[i], &cfgtable->driver_version[i]);
+       kfree(driver_version);
+       return 0;
+}
+
+static __devinit void read_driver_ver_from_cfgtable(
+       struct CfgTable __iomem *cfgtable, unsigned char *driver_ver)
+{
+       int i;
+
+       for (i = 0; i < sizeof(cfgtable->driver_version); i++)
+               driver_ver[i] = readb(&cfgtable->driver_version[i]);
+}
+
+static __devinit int controller_reset_failed(
+       struct CfgTable __iomem *cfgtable)
+{
+
+       char *driver_ver, *old_driver_ver;
+       int rc, size = sizeof(cfgtable->driver_version);
+
+       old_driver_ver = kmalloc(2 * size, GFP_KERNEL);
+       if (!old_driver_ver)
+               return -ENOMEM;
+       driver_ver = old_driver_ver + size;
+
+       /* After a reset, the 32 bytes of "driver version" in the cfgtable
+        * should have been changed, otherwise we know the reset failed.
+        */
+       init_driver_version(old_driver_ver, size);
+       read_driver_ver_from_cfgtable(cfgtable, driver_ver);
+       rc = !memcmp(driver_ver, old_driver_ver, size);
+       kfree(old_driver_ver);
+       return rc;
+}
 /* This does a hard reset of the controller using PCI power management
  * states or the using the doorbell register.
  */
@@ -3195,10 +3344,10 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
        u64 cfg_base_addr_index;
        void __iomem *vaddr;
        unsigned long paddr;
-       u32 misc_fw_support, active_transport;
+       u32 misc_fw_support;
        int rc;
        struct CfgTable __iomem *cfgtable;
-       bool use_doorbell;
+       u32 use_doorbell;
        u32 board_id;
        u16 command_register;
 
@@ -3215,20 +3364,15 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
         * using the doorbell register.
         */
 
-       /* Exclude 640x boards.  These are two pci devices in one slot
-        * which share a battery backed cache module.  One controls the
-        * cache, the other accesses the cache through the one that controls
-        * it.  If we reset the one controlling the cache, the other will
-        * likely not be happy.  Just forbid resetting this conjoined mess.
-        * The 640x isn't really supported by hpsa anyway.
-        */
        rc = hpsa_lookup_board_id(pdev, &board_id);
-       if (rc < 0) {
+       if (rc < 0 || !ctlr_is_resettable(board_id)) {
                dev_warn(&pdev->dev, "Not resetting device.\n");
                return -ENODEV;
        }
-       if (board_id == 0x409C0E11 || board_id == 0x409D0E11)
-               return -ENOTSUPP;
+
+       /* if controller is soft- but not hard resettable... */
+       if (!ctlr_is_hard_resettable(board_id))
+               return -ENOTSUPP; /* try soft reset later. */
 
        /* Save the PCI command register */
        pci_read_config_word(pdev, 4, &command_register);
@@ -3257,10 +3401,28 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
                rc = -ENOMEM;
                goto unmap_vaddr;
        }
+       rc = write_driver_ver_to_cfgtable(cfgtable);
+       if (rc)
+               goto unmap_vaddr;
 
-       /* If reset via doorbell register is supported, use that. */
+       /* If reset via doorbell register is supported, use that.
+        * There are two such methods.  Favor the newest method.
+        */
        misc_fw_support = readl(&cfgtable->misc_fw_support);
-       use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
+       use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET2;
+       if (use_doorbell) {
+               use_doorbell = DOORBELL_CTLR_RESET2;
+       } else {
+               use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
+               if (use_doorbell) {
+                       dev_warn(&pdev->dev, "Controller claims that "
+                               "'Bit 2 doorbell reset' is "
+                               "supported, but not 'bit 5 doorbell reset'.  "
+                               "Firmware update is recommended.\n");
+                       rc = -ENOTSUPP; /* try soft reset */
+                       goto unmap_cfgtable;
+               }
+       }
 
        rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell);
        if (rc)
@@ -3279,30 +3441,32 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
        msleep(HPSA_POST_RESET_PAUSE_MSECS);
 
        /* Wait for board to become not ready, then ready. */
-       dev_info(&pdev->dev, "Waiting for board to become ready.\n");
+       dev_info(&pdev->dev, "Waiting for board to reset.\n");
        rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY);
-       if (rc)
+       if (rc) {
                dev_warn(&pdev->dev,
-                       "failed waiting for board to become not ready\n");
+                       "failed waiting for board to reset."
+                       " Will try soft reset.\n");
+               rc = -ENOTSUPP; /* Not expected, but try soft reset later */
+               goto unmap_cfgtable;
+       }
        rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_READY);
        if (rc) {
                dev_warn(&pdev->dev,
-                       "failed waiting for board to become ready\n");
+                       "failed waiting for board to become ready "
+                       "after hard reset\n");
                goto unmap_cfgtable;
        }
-       dev_info(&pdev->dev, "board ready.\n");
 
-       /* Controller should be in simple mode at this point.  If it's not,
-        * It means we're on one of those controllers which doesn't support
-        * the doorbell reset method and on which the PCI power management reset
-        * method doesn't work (P800, for example.)
-        * In those cases, don't try to proceed, as it generally doesn't work.
-        */
-       active_transport = readl(&cfgtable->TransportActive);
-       if (active_transport & PERFORMANT_MODE) {
-               dev_warn(&pdev->dev, "Unable to successfully reset controller,"
-                       " Ignoring controller.\n");
-               rc = -ENODEV;
+       rc = controller_reset_failed(vaddr);
+       if (rc < 0)
+               goto unmap_cfgtable;
+       if (rc) {
+               dev_warn(&pdev->dev, "Unable to successfully reset "
+                       "controller. Will try soft reset.\n");
+               rc = -ENOTSUPP;
+       } else {
+               dev_info(&pdev->dev, "board ready after hard reset.\n");
        }
 
 unmap_cfgtable:
@@ -3543,6 +3707,9 @@ static int __devinit hpsa_find_cfgtables(struct ctlr_info *h)
                       cfg_base_addr_index) + cfg_offset, sizeof(*h->cfgtable));
        if (!h->cfgtable)
                return -ENOMEM;
+       rc = write_driver_ver_to_cfgtable(h->cfgtable);
+       if (rc)
+               return rc;
        /* Find performant mode table. */
        trans_offset = readl(&h->cfgtable->TransMethodOffset);
        h->transtable = remap_pci_mem(pci_resource_start(h->pdev,
@@ -3777,11 +3944,12 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
         * due to concerns about shared bbwc between 6402/6404 pair.
         */
        if (rc == -ENOTSUPP)
-               return 0; /* just try to do the kdump anyhow. */
+               return rc; /* just try to do the kdump anyhow. */
        if (rc)
                return -ENODEV;
 
        /* Now try to get the controller to respond to a no-op */
+       dev_warn(&pdev->dev, "Waiting for controller to respond to no-op\n");
        for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) {
                if (hpsa_noop(pdev) == 0)
                        break;
@@ -3792,18 +3960,133 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
        return 0;
 }
 
+static __devinit int hpsa_allocate_cmd_pool(struct ctlr_info *h)
+{
+       h->cmd_pool_bits = kzalloc(
+               DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) *
+               sizeof(unsigned long), GFP_KERNEL);
+       h->cmd_pool = pci_alloc_consistent(h->pdev,
+                   h->nr_cmds * sizeof(*h->cmd_pool),
+                   &(h->cmd_pool_dhandle));
+       h->errinfo_pool = pci_alloc_consistent(h->pdev,
+                   h->nr_cmds * sizeof(*h->errinfo_pool),
+                   &(h->errinfo_pool_dhandle));
+       if ((h->cmd_pool_bits == NULL)
+           || (h->cmd_pool == NULL)
+           || (h->errinfo_pool == NULL)) {
+               dev_err(&h->pdev->dev, "out of memory in %s", __func__);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static void hpsa_free_cmd_pool(struct ctlr_info *h)
+{
+       kfree(h->cmd_pool_bits);
+       if (h->cmd_pool)
+               pci_free_consistent(h->pdev,
+                           h->nr_cmds * sizeof(struct CommandList),
+                           h->cmd_pool, h->cmd_pool_dhandle);
+       if (h->errinfo_pool)
+               pci_free_consistent(h->pdev,
+                           h->nr_cmds * sizeof(struct ErrorInfo),
+                           h->errinfo_pool,
+                           h->errinfo_pool_dhandle);
+}
+
+static int hpsa_request_irq(struct ctlr_info *h,
+       irqreturn_t (*msixhandler)(int, void *),
+       irqreturn_t (*intxhandler)(int, void *))
+{
+       int rc;
+
+       if (h->msix_vector || h->msi_vector)
+               rc = request_irq(h->intr[h->intr_mode], msixhandler,
+                               IRQF_DISABLED, h->devname, h);
+       else
+               rc = request_irq(h->intr[h->intr_mode], intxhandler,
+                               IRQF_DISABLED, h->devname, h);
+       if (rc) {
+               dev_err(&h->pdev->dev, "unable to get irq %d for %s\n",
+                      h->intr[h->intr_mode], h->devname);
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static int __devinit hpsa_kdump_soft_reset(struct ctlr_info *h)
+{
+       if (hpsa_send_host_reset(h, RAID_CTLR_LUNID,
+               HPSA_RESET_TYPE_CONTROLLER)) {
+               dev_warn(&h->pdev->dev, "Resetting array controller failed.\n");
+               return -EIO;
+       }
+
+       dev_info(&h->pdev->dev, "Waiting for board to soft reset.\n");
+       if (hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_NOT_READY)) {
+               dev_warn(&h->pdev->dev, "Soft reset had no effect.\n");
+               return -1;
+       }
+
+       dev_info(&h->pdev->dev, "Board reset, awaiting READY status.\n");
+       if (hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY)) {
+               dev_warn(&h->pdev->dev, "Board failed to become ready "
+                       "after soft reset.\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
+{
+       free_irq(h->intr[h->intr_mode], h);
+#ifdef CONFIG_PCI_MSI
+       if (h->msix_vector)
+               pci_disable_msix(h->pdev);
+       else if (h->msi_vector)
+               pci_disable_msi(h->pdev);
+#endif /* CONFIG_PCI_MSI */
+       hpsa_free_sg_chain_blocks(h);
+       hpsa_free_cmd_pool(h);
+       kfree(h->blockFetchTable);
+       pci_free_consistent(h->pdev, h->reply_pool_size,
+               h->reply_pool, h->reply_pool_dhandle);
+       if (h->vaddr)
+               iounmap(h->vaddr);
+       if (h->transtable)
+               iounmap(h->transtable);
+       if (h->cfgtable)
+               iounmap(h->cfgtable);
+       pci_release_regions(h->pdev);
+       kfree(h);
+}
+
 static int __devinit hpsa_init_one(struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
 {
        int dac, rc;
        struct ctlr_info *h;
+       int try_soft_reset = 0;
+       unsigned long flags;
 
        if (number_of_controllers == 0)
                printk(KERN_INFO DRIVER_NAME "\n");
 
        rc = hpsa_init_reset_devices(pdev);
-       if (rc)
-               return rc;
+       if (rc) {
+               if (rc != -ENOTSUPP)
+                       return rc;
+               /* If the reset fails in a particular way (it has no way to do
+                * a proper hard reset, so returns -ENOTSUPP) we can try to do
+                * a soft reset once we get the controller configured up to the
+                * point that it can accept a command.
+                */
+               try_soft_reset = 1;
+               rc = 0;
+       }
+
+reinit_after_soft_reset:
 
        /* Command structures must be aligned on a 32-byte boundary because
         * the 5 lower bits of the address are used by the hardware. and by
@@ -3847,54 +4130,82 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
        /* make sure the board interrupts are off */
        h->access.set_intr_mask(h, HPSA_INTR_OFF);
 
-       if (h->msix_vector || h->msi_vector)
-               rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_msi,
-                               IRQF_DISABLED, h->devname, h);
-       else
-               rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_intx,
-                               IRQF_DISABLED, h->devname, h);
-       if (rc) {
-               dev_err(&pdev->dev, "unable to get irq %d for %s\n",
-                      h->intr[h->intr_mode], h->devname);
+       if (hpsa_request_irq(h, do_hpsa_intr_msi, do_hpsa_intr_intx))
                goto clean2;
-       }
-
        dev_info(&pdev->dev, "%s: <0x%x> at IRQ %d%s using DAC\n",
               h->devname, pdev->device,
               h->intr[h->intr_mode], dac ? "" : " not");
-
-       h->cmd_pool_bits =
-           kmalloc(((h->nr_cmds + BITS_PER_LONG -
-                     1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL);
-       h->cmd_pool = pci_alloc_consistent(h->pdev,
-                   h->nr_cmds * sizeof(*h->cmd_pool),
-                   &(h->cmd_pool_dhandle));
-       h->errinfo_pool = pci_alloc_consistent(h->pdev,
-                   h->nr_cmds * sizeof(*h->errinfo_pool),
-                   &(h->errinfo_pool_dhandle));
-       if ((h->cmd_pool_bits == NULL)
-           || (h->cmd_pool == NULL)
-           || (h->errinfo_pool == NULL)) {
-               dev_err(&pdev->dev, "out of memory");
-               rc = -ENOMEM;
+       if (hpsa_allocate_cmd_pool(h))
                goto clean4;
-       }
        if (hpsa_allocate_sg_chain_blocks(h))
                goto clean4;
        init_waitqueue_head(&h->scan_wait_queue);
        h->scan_finished = 1; /* no scan currently in progress */
 
        pci_set_drvdata(pdev, h);
-       memset(h->cmd_pool_bits, 0,
-              ((h->nr_cmds + BITS_PER_LONG -
-                1) / BITS_PER_LONG) * sizeof(unsigned long));
+       h->ndevices = 0;
+       h->scsi_host = NULL;
+       spin_lock_init(&h->devlock);
+       hpsa_put_ctlr_into_performant_mode(h);
+
+       /* At this point, the controller is ready to take commands.
+        * Now, if reset_devices and the hard reset didn't work, try
+        * the soft reset and see if that works.
+        */
+       if (try_soft_reset) {
+
+               /* This is kind of gross.  We may or may not get a completion
+                * from the soft reset command, and if we do, then the value
+                * from the fifo may or may not be valid.  So, we wait 10 secs
+                * after the reset throwing away any completions we get during
+                * that time.  Unregister the interrupt handler and register
+                * fake ones to scoop up any residual completions.
+                */
+               spin_lock_irqsave(&h->lock, flags);
+               h->access.set_intr_mask(h, HPSA_INTR_OFF);
+               spin_unlock_irqrestore(&h->lock, flags);
+               free_irq(h->intr[h->intr_mode], h);
+               rc = hpsa_request_irq(h, hpsa_msix_discard_completions,
+                                       hpsa_intx_discard_completions);
+               if (rc) {
+                       dev_warn(&h->pdev->dev, "Failed to request_irq after "
+                               "soft reset.\n");
+                       goto clean4;
+               }
+
+               rc = hpsa_kdump_soft_reset(h);
+               if (rc)
+                       /* Neither hard nor soft reset worked, we're hosed. */
+                       goto clean4;
+
+               dev_info(&h->pdev->dev, "Board READY.\n");
+               dev_info(&h->pdev->dev,
+                       "Waiting for stale completions to drain.\n");
+               h->access.set_intr_mask(h, HPSA_INTR_ON);
+               msleep(10000);
+               h->access.set_intr_mask(h, HPSA_INTR_OFF);
+
+               rc = controller_reset_failed(h->cfgtable);
+               if (rc)
+                       dev_info(&h->pdev->dev,
+                               "Soft reset appears to have failed.\n");
+
+               /* since the controller's reset, we have to go back and re-init
+                * everything.  Easiest to just forget what we've done and do it
+                * all over again.
+                */
+               hpsa_undo_allocations_after_kdump_soft_reset(h);
+               try_soft_reset = 0;
+               if (rc)
+                       /* don't go to clean4, we already unallocated */
+                       return -ENODEV;
 
-       hpsa_scsi_setup(h);
+               goto reinit_after_soft_reset;
+       }
 
        /* Turn the interrupts on so we can service requests */
        h->access.set_intr_mask(h, HPSA_INTR_ON);
 
-       hpsa_put_ctlr_into_performant_mode(h);
        hpsa_hba_inquiry(h);
        hpsa_register_scsi(h);  /* hook ourselves into SCSI subsystem */
        h->busy_initializing = 0;
@@ -3902,16 +4213,7 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
 
 clean4:
        hpsa_free_sg_chain_blocks(h);
-       kfree(h->cmd_pool_bits);
-       if (h->cmd_pool)
-               pci_free_consistent(h->pdev,
-                           h->nr_cmds * sizeof(struct CommandList),
-                           h->cmd_pool, h->cmd_pool_dhandle);
-       if (h->errinfo_pool)
-               pci_free_consistent(h->pdev,
-                           h->nr_cmds * sizeof(struct ErrorInfo),
-                           h->errinfo_pool,
-                           h->errinfo_pool_dhandle);
+       hpsa_free_cmd_pool(h);
        free_irq(h->intr[h->intr_mode], h);
 clean2:
 clean1: