cciss: use new doorbell-bit-5 reset method
authorStephen M. Cameron <scameron@beardog.cce.hp.com>
Tue, 3 May 2011 19:53:46 +0000 (14:53 -0500)
committerJens Axboe <jaxboe@fusionio.com>
Fri, 6 May 2011 14:23:55 +0000 (08:23 -0600)
The bit-2-doorbell reset method seemed to cause (survivable) NMIs
on some systems and (unsurvivable) IOCK NMIs on some G7 servers.
Firmware guys implemented a new doorbell method to alleviate these
problems triggered by bit 5 of the doorbell register.  We want to
use it if it's available.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
drivers/block/cciss.c
drivers/block/cciss_cmd.h

index b9f8658..df58c59 100644 (file)
@@ -4384,7 +4384,7 @@ static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, u
 #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,7 +4395,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);
+               writel(use_doorbell, vaddr + SA5_DOORBELL);
                msleep(1000);
        } else { /* Try to do it the PCI power state way */
 
@@ -4499,7 +4499,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;
 
@@ -4560,15 +4560,18 @@ 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)
+                       use_doorbell = DOORBELL_CTLR_RESET;
+       }
 
        rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell);
        if (rc)
index 3b20c31..d9be6b4 100644 (file)
@@ -53,6 +53,7 @@
 #define CFGTBL_ChangeReq        0x00000001l
 #define CFGTBL_AccCmds          0x00000001l
 #define DOORBELL_CTLR_RESET     0x00000004l
+#define DOORBELL_CTLR_RESET2    0x00000020l
 
 #define CFGTBL_Trans_Simple     0x00000002l
 #define CFGTBL_Trans_Performant 0x00000004l
@@ -243,6 +244,7 @@ typedef struct _CfgTable_struct {
   u8              reserved[0x78 - 0x58];
   u32             misc_fw_support; /* offset 0x78 */
 #define MISC_FW_DOORBELL_RESET (0x02)
+#define MISC_FW_DOORBELL_RESET2 (0x10)
        u8         driver_version[32];
 } CfgTable_struct;