Commit bf2e2e6b87ae38fab460a36abfe272d99ae8be49

Authored by Stephen M. Cameron
Committed by Jens Axboe
1 parent 3e28601fdf

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>

Showing 2 changed files with 16 additions and 11 deletions Side-by-side Diff

drivers/block/cciss.c
... ... @@ -4384,7 +4384,7 @@
4384 4384 #define cciss_noop(p) cciss_message(p, 3, 0)
4385 4385  
4386 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 4389 u16 pmcsr;
4390 4390 int pos;
... ... @@ -4395,7 +4395,7 @@
4395 4395 * other way using the doorbell register.
4396 4396 */
4397 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 4399 msleep(1000);
4400 4400 } else { /* Try to do it the PCI power state way */
4401 4401  
... ... @@ -4499,7 +4499,7 @@
4499 4499 u32 misc_fw_support;
4500 4500 int rc;
4501 4501 CfgTable_struct __iomem *cfgtable;
4502   - bool use_doorbell;
  4502 + u32 use_doorbell;
4503 4503 u32 board_id;
4504 4504 u16 command_register;
4505 4505  
4506 4506  
... ... @@ -4560,15 +4560,18 @@
4560 4560 if (rc)
4561 4561 goto unmap_vaddr;
4562 4562  
4563   - /* If reset via doorbell register is supported, use that. */
4564   - misc_fw_support = readl(&cfgtable->misc_fw_support);
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.
  4563 + /* If reset via doorbell register is supported, use that.
  4564 + * There are two such methods. Favor the newest method.
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 4576 rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell);
4574 4577 if (rc)
drivers/block/cciss_cmd.h
... ... @@ -53,6 +53,7 @@
53 53 #define CFGTBL_ChangeReq 0x00000001l
54 54 #define CFGTBL_AccCmds 0x00000001l
55 55 #define DOORBELL_CTLR_RESET 0x00000004l
  56 +#define DOORBELL_CTLR_RESET2 0x00000020l
56 57  
57 58 #define CFGTBL_Trans_Simple 0x00000002l
58 59 #define CFGTBL_Trans_Performant 0x00000004l
... ... @@ -243,6 +244,7 @@
243 244 u8 reserved[0x78 - 0x58];
244 245 u32 misc_fw_support; /* offset 0x78 */
245 246 #define MISC_FW_DOORBELL_RESET (0x02)
  247 +#define MISC_FW_DOORBELL_RESET2 (0x10)
246 248 u8 driver_version[32];
247 249 } CfgTable_struct;
248 250