drbd: Use the correct max_bio_size when creating resync requests
[deliverable/linux.git] / drivers / block / cciss.c
index 23b0ba49300a054defe0a4a913c6769a87b87683..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);
 
@@ -2477,31 +2503,6 @@ static int deregister_disk(ctlr_info_t *h, int drv_index,
        return 0;
 }
 
-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 fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff,
                size_t size, __u8 page_code, unsigned char *scsi3addr,
                int cmd_type)
@@ -2642,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) {
@@ -4199,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.
@@ -4477,7 +4503,6 @@ static int cciss_controller_hard_reset(struct pci_dev *pdev,
                 */
                dev_info(&pdev->dev, "using doorbell to reset controller\n");
                writel(use_doorbell, vaddr + SA5_DOORBELL);
-               msleep(1000);
        } else { /* Try to do it the PCI power state way */
 
                /* Quoting from the Open CISS Specification: "The Power
@@ -4508,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;
 }
@@ -4604,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()
@@ -4650,8 +4677,14 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
                use_doorbell = DOORBELL_CTLR_RESET2;
        } else {
                use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
-               if (use_doorbell)
-                       use_doorbell = DOORBELL_CTLR_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);
@@ -4930,6 +4963,11 @@ reinit_after_soft_reset:
        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))
This page took 0.027506 seconds and 5 git commands to generate.