Commit cf0b08d0cd87ada9d284925834d08fb8026da888
Committed by
James Bottomley
1 parent
9a41338e5b
Exists in
master
and in
39 other branches
[SCSI] hpsa: 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: James Bottomley <jbottomley@parallels.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Showing 2 changed files with 22 additions and 5 deletions Side-by-side Diff
drivers/scsi/hpsa.c
... | ... | @@ -3128,7 +3128,7 @@ |
3128 | 3128 | #define hpsa_noop(p) hpsa_message(p, 3, 0) |
3129 | 3129 | |
3130 | 3130 | static int hpsa_controller_hard_reset(struct pci_dev *pdev, |
3131 | - void * __iomem vaddr, bool use_doorbell) | |
3131 | + void * __iomem vaddr, u32 use_doorbell) | |
3132 | 3132 | { |
3133 | 3133 | u16 pmcsr; |
3134 | 3134 | int pos; |
... | ... | @@ -3139,7 +3139,7 @@ |
3139 | 3139 | * other way using the doorbell register. |
3140 | 3140 | */ |
3141 | 3141 | dev_info(&pdev->dev, "using doorbell to reset controller\n"); |
3142 | - writel(DOORBELL_CTLR_RESET, vaddr + SA5_DOORBELL); | |
3142 | + writel(use_doorbell, vaddr + SA5_DOORBELL); | |
3143 | 3143 | msleep(1000); |
3144 | 3144 | } else { /* Try to do it the PCI power state way */ |
3145 | 3145 | |
... | ... | @@ -3243,7 +3243,7 @@ |
3243 | 3243 | u32 misc_fw_support; |
3244 | 3244 | int rc; |
3245 | 3245 | struct CfgTable __iomem *cfgtable; |
3246 | - bool use_doorbell; | |
3246 | + u32 use_doorbell; | |
3247 | 3247 | u32 board_id; |
3248 | 3248 | u16 command_register; |
3249 | 3249 | |
3250 | 3250 | |
... | ... | @@ -3306,9 +3306,24 @@ |
3306 | 3306 | if (rc) |
3307 | 3307 | goto unmap_vaddr; |
3308 | 3308 | |
3309 | - /* If reset via doorbell register is supported, use that. */ | |
3309 | + /* If reset via doorbell register is supported, use that. | |
3310 | + * There are two such methods. Favor the newest method. | |
3311 | + */ | |
3310 | 3312 | misc_fw_support = readl(&cfgtable->misc_fw_support); |
3311 | - use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; | |
3313 | + use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET2; | |
3314 | + if (use_doorbell) { | |
3315 | + use_doorbell = DOORBELL_CTLR_RESET2; | |
3316 | + } else { | |
3317 | + use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; | |
3318 | + if (use_doorbell) { | |
3319 | + dev_warn(&pdev->dev, "Controller claims that " | |
3320 | + "'Bit 2 doorbell reset' is " | |
3321 | + "supported, but not 'bit 5 doorbell reset'. " | |
3322 | + "Firmware update is recommended.\n"); | |
3323 | + rc = -ENODEV; | |
3324 | + goto unmap_cfgtable; | |
3325 | + } | |
3326 | + } | |
3312 | 3327 | |
3313 | 3328 | rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell); |
3314 | 3329 | if (rc) |
drivers/scsi/hpsa_cmd.h
... | ... | @@ -101,6 +101,7 @@ |
101 | 101 | #define CFGTBL_ChangeReq 0x00000001l |
102 | 102 | #define CFGTBL_AccCmds 0x00000001l |
103 | 103 | #define DOORBELL_CTLR_RESET 0x00000004l |
104 | +#define DOORBELL_CTLR_RESET2 0x00000020l | |
104 | 105 | |
105 | 106 | #define CFGTBL_Trans_Simple 0x00000002l |
106 | 107 | #define CFGTBL_Trans_Performant 0x00000004l |
... | ... | @@ -337,6 +338,7 @@ |
337 | 338 | u8 reserved[0x78 - 0x58]; |
338 | 339 | u32 misc_fw_support; /* offset 0x78 */ |
339 | 340 | #define MISC_FW_DOORBELL_RESET (0x02) |
341 | +#define MISC_FW_DOORBELL_RESET2 (0x010) | |
340 | 342 | u8 driver_version[32]; |
341 | 343 | }; |
342 | 344 |