drbd: Use the correct max_bio_size when creating resync requests
[deliverable/linux.git] / drivers / block / cciss.c
index 63fe05af2c5de75a008d654711e9baafeb905ee1..8f4ef656a1af4ca435ff3ecc5e0d6079e6a1e34d 100644 (file)
@@ -64,6 +64,10 @@ MODULE_DESCRIPTION("Driver for HP Smart Array Controllers");
 MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers");
 MODULE_VERSION("3.6.26");
 MODULE_LICENSE("GPL");
+static int cciss_tape_cmds = 6;
+module_param(cciss_tape_cmds, int, 0644);
+MODULE_PARM_DESC(cciss_tape_cmds,
+       "number of commands to allocate for tape devices (default: 6)");
 
 static DEFINE_MUTEX(cciss_mutex);
 static struct proc_dir_entry *proc_cciss;
@@ -558,7 +562,7 @@ static void __devinit cciss_procinit(ctlr_info_t *h)
 #define to_hba(n) container_of(n, struct ctlr_info, dev)
 #define to_drv(n) container_of(n, drive_info_struct, dev)
 
-/* 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 */
@@ -576,23 +580,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[] = {
+       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)
 {
        struct ctlr_info *h = to_hba(dev);
 
-       return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h));
+       return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h->board_id));
 }
 static DEVICE_ATTR(resettable, S_IRUGO, host_show_resettable, NULL);
 
@@ -2569,7 +2595,7 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff,
                }
        } else if (cmd_type == TYPE_MSG) {
                switch (cmd) {
-               case 0: /* ABORT message */
+               case CCISS_ABORT_MSG:
                        c->Request.CDBLen = 12;
                        c->Request.Type.Attribute = ATTR_SIMPLE;
                        c->Request.Type.Direction = XFER_WRITE;
@@ -2579,16 +2605,16 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff,
                        /* buff contains the tag of the command to abort */
                        memcpy(&c->Request.CDB[4], buff, 8);
                        break;
-               case 1: /* RESET message */
+               case CCISS_RESET_MSG:
                        c->Request.CDBLen = 16;
                        c->Request.Type.Attribute = ATTR_SIMPLE;
                        c->Request.Type.Direction = XFER_NONE;
                        c->Request.Timeout = 0;
                        memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
                        c->Request.CDB[0] = cmd;        /* reset */
-                       c->Request.CDB[1] = 0x03;       /* reset a target */
+                       c->Request.CDB[1] = CCISS_RESET_TYPE_TARGET;
                        break;
-               case 3: /* No-Op message */
+               case CCISS_NOOP_MSG:
                        c->Request.CDBLen = 1;
                        c->Request.Type.Attribute = ATTR_SIMPLE;
                        c->Request.Type.Direction = XFER_WRITE;
@@ -2617,6 +2643,31 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff,
        return status;
 }
 
+static int __devinit cciss_send_reset(ctlr_info_t *h, unsigned char *scsi3addr,
+       u8 reset_type)
+{
+       CommandList_struct *c;
+       int return_status;
+
+       c = cmd_alloc(h);
+       if (!c)
+               return -ENOMEM;
+       return_status = fill_cmd(h, c, CCISS_RESET_MSG, NULL, 0, 0,
+               CTLR_LUNID, TYPE_MSG);
+       c->Request.CDB[1] = reset_type; /* fill_cmd defaults to target reset */
+       if (return_status != IO_OK) {
+               cmd_special_free(h, c);
+               return return_status;
+       }
+       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 int check_target_status(ctlr_info_t *h, CommandList_struct *c)
 {
        switch (c->err_info->ScsiStatus) {
@@ -3463,6 +3514,63 @@ static inline u32 process_nonindexed_cmd(ctlr_info_t *h, u32 raw_tag)
        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 cciss_xxx_discard_completions
+ * functions.
+ */
+static int ignore_bogus_interrupt(ctlr_info_t *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 cciss_intx_discard_completions(int irq, void *dev_id)
+{
+       ctlr_info_t *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 cciss_msix_discard_completions(int irq, void *dev_id)
+{
+       ctlr_info_t *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_cciss_intx(int irq, void *dev_id)
 {
        ctlr_info_t *h = dev_id;
@@ -4117,7 +4225,7 @@ static void __devinit cciss_get_max_perf_mode_cmds(struct ctlr_info *h)
 static void __devinit cciss_find_board_params(ctlr_info_t *h)
 {
        cciss_get_max_perf_mode_cmds(h);
-       h->nr_cmds = h->max_commands - 4; /* Allow room for some ioctls */
+       h->nr_cmds = h->max_commands - 4 - cciss_tape_cmds;
        h->maxsgentries = readl(&(h->cfgtable->MaxSGElements));
        /*
         * Limit in-command s/g elements to 32 save dma'able memory.
@@ -4353,7 +4461,7 @@ static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, u
                tag = readl(vaddr + SA5_REPLY_PORT_OFFSET);
                if ((tag & ~3) == paddr32)
                        break;
-               schedule_timeout_uninterruptible(HZ);
+               msleep(CCISS_POST_RESET_NOOP_TIMEOUT_MSECS);
        }
 
        iounmap(vaddr);
@@ -4380,11 +4488,10 @@ static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, u
        return 0;
 }
 
-#define cciss_soft_reset_controller(p) cciss_message(p, 1, 0)
 #define cciss_noop(p) cciss_message(p, 3, 0)
 
 static int cciss_controller_hard_reset(struct pci_dev *pdev,
-       void * __iomem vaddr, bool use_doorbell)
+       void * __iomem vaddr, u32 use_doorbell)
 {
        u16 pmcsr;
        int pos;
@@ -4395,8 +4502,7 @@ static int cciss_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
@@ -4427,8 +4533,6 @@ static int cciss_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;
 }
@@ -4499,7 +4603,7 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
        u32 misc_fw_support;
        int rc;
        CfgTable_struct __iomem *cfgtable;
-       bool use_doorbell;
+       u32 use_doorbell;
        u32 board_id;
        u16 command_register;
 
@@ -4523,12 +4627,16 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
         * likely not be happy.  Just forbid resetting this conjoined mess.
         */
        cciss_lookup_board_id(pdev, &board_id);
-       if (board_id == 0x409C0E11 || board_id == 0x409D0E11) {
+       if (!ctlr_is_resettable(board_id)) {
                dev_warn(&pdev->dev, "Cannot reset Smart Array 640x "
                                "due to shared cache module.");
                return -ENODEV;
        }
 
+       /* 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);
        /* Turn the board off.  This is so that later pci_restore_state()
@@ -4560,15 +4668,24 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
        if (rc)
                goto unmap_vaddr;
 
-       /* If reset via doorbell register is supported, use that. */
-       misc_fw_support = readl(&cfgtable->misc_fw_support);
-       use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
-
-       /* The doorbell reset seems to cause lockups on some Smart
-        * Arrays (e.g. P410, P410i, maybe others).  Until this is
-        * fixed or at least isolated, avoid the doorbell reset.
+       /* If reset via doorbell register is supported, use that.
+        * There are two such methods.  Favor the newest method.
         */
-       use_doorbell = 0;
+       misc_fw_support = readl(&cfgtable->misc_fw_support);
+       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; /* use the soft reset */
+                       goto unmap_cfgtable;
+               }
+       }
 
        rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell);
        if (rc)
@@ -4586,15 +4703,19 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
        msleep(CCISS_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 = cciss_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY);
-       if (rc) /* Don't bail, might be E500, etc. which can't be reset */
-               dev_warn(&pdev->dev,
-                       "failed waiting for board to become not ready\n");
+       if (rc) {
+               dev_warn(&pdev->dev, "Failed waiting for board to hard reset."
+                               "  Will try soft reset.\n");
+               rc = -ENOTSUPP; /* Not expected, but try soft reset later */
+               goto unmap_cfgtable;
+       }
        rc = cciss_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;
        }
 
@@ -4602,16 +4723,13 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
        if (rc < 0)
                goto unmap_cfgtable;
        if (rc) {
-               dev_warn(&pdev->dev, "Unable to successfully reset controller,"
-                       " Ignoring controller.\n");
-               rc = -ENODEV;
-               goto unmap_cfgtable;
+               dev_warn(&pdev->dev, "Unable to successfully hard reset "
+                       "controller. Will try soft reset.\n");
+               rc = -ENOTSUPP; /* Not expected, but try soft reset later */
        } else {
-               dev_info(&pdev->dev, "board ready.\n");
+               dev_info(&pdev->dev, "Board ready after hard reset.\n");
        }
 
-       dev_info(&pdev->dev, "board ready.\n");
-
 unmap_cfgtable:
        iounmap(cfgtable);
 
@@ -4636,11 +4754,12 @@ static __devinit int cciss_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 < CCISS_POST_RESET_NOOP_RETRIES; i++) {
                if (cciss_noop(pdev) == 0)
                        break;
@@ -4741,6 +4860,60 @@ static int cciss_request_irq(ctlr_info_t *h,
        return -1;
 }
 
+static int __devinit cciss_kdump_soft_reset(ctlr_info_t *h)
+{
+       if (cciss_send_reset(h, CTLR_LUNID, CCISS_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 (cciss_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 (cciss_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 cciss_undo_allocations_after_kdump_soft_reset(ctlr_info_t *h)
+{
+       int ctlr = h->ctlr;
+
+       free_irq(h->intr[PERF_MODE_INT], 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 */
+       cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds);
+       cciss_free_scatterlists(h);
+       cciss_free_cmd_pool(h);
+       kfree(h->blockFetchTable);
+       if (h->reply_pool)
+               pci_free_consistent(h->pdev, h->max_commands * sizeof(__u64),
+                               h->reply_pool, h->reply_pool_dhandle);
+       if (h->transtable)
+               iounmap(h->transtable);
+       if (h->cfgtable)
+               iounmap(h->cfgtable);
+       if (h->vaddr)
+               iounmap(h->vaddr);
+       unregister_blkdev(h->major, h->devname);
+       cciss_destroy_hba_sysfs_entry(h);
+       pci_release_regions(h->pdev);
+       kfree(h);
+       hba[ctlr] = NULL;
+}
+
 /*
  *  This is it.  Find all the controllers and register them.  I really hate
  *  stealing all these major device numbers.
@@ -4752,13 +4925,27 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        int i;
        int j = 0;
        int rc;
+       int try_soft_reset = 0;
        int dac, return_code;
        InquiryData_struct *inq_buff;
        ctlr_info_t *h;
+       unsigned long flags;
 
        rc = cciss_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:
+
        i = alloc_cciss_hba(pdev);
        if (i < 0)
                return -1;
@@ -4776,6 +4963,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        sprintf(h->devname, "cciss%d", i);
        h->ctlr = i;
 
+       if (cciss_tape_cmds < 2)
+               cciss_tape_cmds = 2;
+       if (cciss_tape_cmds > 16)
+               cciss_tape_cmds = 16;
+
        init_completion(&h->scan_wait);
 
        if (cciss_create_hba_sysfs_entry(h))
@@ -4848,6 +5040,62 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
                h->gendisk[j] = NULL;
        }
 
+       /* 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, CCISS_INTR_OFF);
+               spin_unlock_irqrestore(&h->lock, flags);
+               free_irq(h->intr[PERF_MODE_INT], h);
+               rc = cciss_request_irq(h, cciss_msix_discard_completions,
+                                       cciss_intx_discard_completions);
+               if (rc) {
+                       dev_warn(&h->pdev->dev, "Failed to request_irq after "
+                               "soft reset.\n");
+                       goto clean4;
+               }
+
+               rc = cciss_kdump_soft_reset(h);
+               if (rc) {
+                       dev_warn(&h->pdev->dev, "Soft reset failed.\n");
+                       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, CCISS_INTR_ON);
+               msleep(10000);
+               h->access.set_intr_mask(h, CCISS_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.
+                */
+               cciss_undo_allocations_after_kdump_soft_reset(h);
+               try_soft_reset = 0;
+               if (rc)
+                       /* don't go to clean4, we already unallocated */
+                       return -ENODEV;
+
+               goto reinit_after_soft_reset;
+       }
+
        cciss_scsi_setup(h);
 
        /* Turn the interrupts on so we can service requests */
@@ -4988,6 +5236,10 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
                kfree(h->scatter_list[j]);
        kfree(h->scatter_list);
        cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds);
+       kfree(h->blockFetchTable);
+       if (h->reply_pool)
+               pci_free_consistent(h->pdev, h->max_commands * sizeof(__u64),
+                               h->reply_pool, h->reply_pool_dhandle);
        /*
         * Deliberately omit pci_disable_device(): it does something nasty to
         * Smart Array controllers that pci_enable_device does not undo
This page took 0.031614 seconds and 5 git commands to generate.