diff options
author | Stephen M. Cameron <scameron@beardog.cce.hp.com> | 2011-05-03 15:53:46 -0400 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2011-05-06 10:23:55 -0400 |
commit | bf2e2e6b87ae38fab460a36abfe272d99ae8be49 (patch) | |
tree | 4f51b122e44f7ae25bcb6230c17b0cbe33bbfea7 | |
parent | 3e28601fdfdec75ce8f6aaaf58540fdd0883fb58 (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.c | 25 | ||||
-rw-r--r-- | drivers/block/cciss_cmd.h | 2 |
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 | ||
4386 | static int cciss_controller_hard_reset(struct pci_dev *pdev, | 4386 | static 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 | ||