aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cce.hp.com>2011-05-03 15:53:46 -0400
committerJens Axboe <jaxboe@fusionio.com>2011-05-06 10:23:55 -0400
commitbf2e2e6b87ae38fab460a36abfe272d99ae8be49 (patch)
tree4f51b122e44f7ae25bcb6230c17b0cbe33bbfea7
parent3e28601fdfdec75ce8f6aaaf58540fdd0883fb58 (diff)
cciss: use new doorbell-bit-5 reset method
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>
-rw-r--r--drivers/block/cciss.c25
-rw-r--r--drivers/block/cciss_cmd.h2
2 files changed, 16 insertions, 11 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index b9f8658341cc..df58c59d9031 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -4384,7 +4384,7 @@ static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, u
4384#define cciss_noop(p) cciss_message(p, 3, 0) 4384#define cciss_noop(p) cciss_message(p, 3, 0)
4385 4385
4386static int cciss_controller_hard_reset(struct pci_dev *pdev, 4386static int cciss_controller_hard_reset(struct pci_dev *pdev,
4387 void * __iomem vaddr, bool use_doorbell) 4387 void * __iomem vaddr, u32 use_doorbell)
4388{ 4388{
4389 u16 pmcsr; 4389 u16 pmcsr;
4390 int pos; 4390 int pos;
@@ -4395,7 +4395,7 @@ static int cciss_controller_hard_reset(struct pci_dev *pdev,
4395 * other way using the doorbell register. 4395 * other way using the doorbell register.
4396 */ 4396 */
4397 dev_info(&pdev->dev, "using doorbell to reset controller\n"); 4397 dev_info(&pdev->dev, "using doorbell to reset controller\n");
4398 writel(DOORBELL_CTLR_RESET, vaddr + SA5_DOORBELL); 4398 writel(use_doorbell, vaddr + SA5_DOORBELL);
4399 msleep(1000); 4399 msleep(1000);
4400 } else { /* Try to do it the PCI power state way */ 4400 } else { /* Try to do it the PCI power state way */
4401 4401
@@ -4499,7 +4499,7 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
4499 u32 misc_fw_support; 4499 u32 misc_fw_support;
4500 int rc; 4500 int rc;
4501 CfgTable_struct __iomem *cfgtable; 4501 CfgTable_struct __iomem *cfgtable;
4502 bool use_doorbell; 4502 u32 use_doorbell;
4503 u32 board_id; 4503 u32 board_id;
4504 u16 command_register; 4504 u16 command_register;
4505 4505
@@ -4560,15 +4560,18 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
4560 if (rc) 4560 if (rc)
4561 goto unmap_vaddr; 4561 goto unmap_vaddr;
4562 4562
4563 /* If reset via doorbell register is supported, use that. */ 4563 /* If reset via doorbell register is supported, use that.
4564 misc_fw_support = readl(&cfgtable->misc_fw_support); 4564 * There are two such methods. Favor the newest method.
4565 use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
4566
4567 /* The doorbell reset seems to cause lockups on some Smart
4568 * Arrays (e.g. P410, P410i, maybe others). Until this is
4569 * fixed or at least isolated, avoid the doorbell reset.
4570 */ 4565 */
4571 use_doorbell = 0; 4566 misc_fw_support = readl(&cfgtable->misc_fw_support);
4567 use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET2;
4568 if (use_doorbell) {
4569 use_doorbell = DOORBELL_CTLR_RESET2;
4570 } else {
4571 use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
4572 if (use_doorbell)
4573 use_doorbell = DOORBELL_CTLR_RESET;
4574 }
4572 4575
4573 rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell); 4576 rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell);
4574 if (rc) 4577 if (rc)
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index 3b20c31d746d..d9be6b4d49a6 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -53,6 +53,7 @@
53#define CFGTBL_ChangeReq 0x00000001l 53#define CFGTBL_ChangeReq 0x00000001l
54#define CFGTBL_AccCmds 0x00000001l 54#define CFGTBL_AccCmds 0x00000001l
55#define DOORBELL_CTLR_RESET 0x00000004l 55#define DOORBELL_CTLR_RESET 0x00000004l
56#define DOORBELL_CTLR_RESET2 0x00000020l
56 57
57#define CFGTBL_Trans_Simple 0x00000002l 58#define CFGTBL_Trans_Simple 0x00000002l
58#define CFGTBL_Trans_Performant 0x00000004l 59#define CFGTBL_Trans_Performant 0x00000004l
@@ -243,6 +244,7 @@ typedef struct _CfgTable_struct {
243 u8 reserved[0x78 - 0x58]; 244 u8 reserved[0x78 - 0x58];
244 u32 misc_fw_support; /* offset 0x78 */ 245 u32 misc_fw_support; /* offset 0x78 */
245#define MISC_FW_DOORBELL_RESET (0x02) 246#define MISC_FW_DOORBELL_RESET (0x02)
247#define MISC_FW_DOORBELL_RESET2 (0x10)
246 u8 driver_version[32]; 248 u8 driver_version[32];
247} CfgTable_struct; 249} CfgTable_struct;
248 250