aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/hpsa.c
diff options
context:
space:
mode:
authorStephen M. Cameron <scameron@beardog.cce.hp.com>2011-01-06 15:48:08 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-01-24 12:29:46 -0500
commit270d05de2b8d82df4ed19955f6c0c7400f6ffbf5 (patch)
tree8abc541659b5300a32d700205fd88d23e0804987 /drivers/scsi/hpsa.c
parentfe5389c87f13c16cd77d976801c93422d0c05a49 (diff)
[SCSI] hpsa: Use kernel provided PCI state save and restore functions
and use the doorbell reset method if available (which doesn't lock up the controller if you properly save and restore all the PCI registers that you're supposed to.) Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r--drivers/scsi/hpsa.c81
1 files changed, 15 insertions, 66 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index cfd30adc3f18..82b94e2c745b 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3053,38 +3053,6 @@ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
3053#define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0) 3053#define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0)
3054#define hpsa_noop(p) hpsa_message(p, 3, 0) 3054#define hpsa_noop(p) hpsa_message(p, 3, 0)
3055 3055
3056static __devinit int hpsa_reset_msi(struct pci_dev *pdev)
3057{
3058/* the #defines are stolen from drivers/pci/msi.h. */
3059#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
3060#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
3061
3062 int pos;
3063 u16 control = 0;
3064
3065 pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
3066 if (pos) {
3067 pci_read_config_word(pdev, msi_control_reg(pos), &control);
3068 if (control & PCI_MSI_FLAGS_ENABLE) {
3069 dev_info(&pdev->dev, "resetting MSI\n");
3070 pci_write_config_word(pdev, msi_control_reg(pos),
3071 control & ~PCI_MSI_FLAGS_ENABLE);
3072 }
3073 }
3074
3075 pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
3076 if (pos) {
3077 pci_read_config_word(pdev, msi_control_reg(pos), &control);
3078 if (control & PCI_MSIX_FLAGS_ENABLE) {
3079 dev_info(&pdev->dev, "resetting MSI-X\n");
3080 pci_write_config_word(pdev, msi_control_reg(pos),
3081 control & ~PCI_MSIX_FLAGS_ENABLE);
3082 }
3083 }
3084
3085 return 0;
3086}
3087
3088static int hpsa_controller_hard_reset(struct pci_dev *pdev, 3056static int hpsa_controller_hard_reset(struct pci_dev *pdev,
3089 void * __iomem vaddr, bool use_doorbell) 3057 void * __iomem vaddr, bool use_doorbell)
3090{ 3058{
@@ -3140,17 +3108,17 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
3140 */ 3108 */
3141static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) 3109static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
3142{ 3110{
3143 u16 saved_config_space[32];
3144 u64 cfg_offset; 3111 u64 cfg_offset;
3145 u32 cfg_base_addr; 3112 u32 cfg_base_addr;
3146 u64 cfg_base_addr_index; 3113 u64 cfg_base_addr_index;
3147 void __iomem *vaddr; 3114 void __iomem *vaddr;
3148 unsigned long paddr; 3115 unsigned long paddr;
3149 u32 misc_fw_support, active_transport; 3116 u32 misc_fw_support, active_transport;
3150 int rc, i; 3117 int rc;
3151 struct CfgTable __iomem *cfgtable; 3118 struct CfgTable __iomem *cfgtable;
3152 bool use_doorbell; 3119 bool use_doorbell;
3153 u32 board_id; 3120 u32 board_id;
3121 u16 command_register;
3154 3122
3155 /* For controllers as old as the P600, this is very nearly 3123 /* For controllers as old as the P600, this is very nearly
3156 * the same thing as 3124 * the same thing as
@@ -3160,14 +3128,6 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
3160 * pci_set_power_state(pci_dev, PCI_D0); 3128 * pci_set_power_state(pci_dev, PCI_D0);
3161 * pci_restore_state(pci_dev); 3129 * pci_restore_state(pci_dev);
3162 * 3130 *
3163 * but we can't use these nice canned kernel routines on
3164 * kexec, because they also check the MSI/MSI-X state in PCI
3165 * configuration space and do the wrong thing when it is
3166 * set/cleared. Also, the pci_save/restore_state functions
3167 * violate the ordering requirements for restoring the
3168 * configuration space from the CCISS document (see the
3169 * comment below). So we roll our own ....
3170 *
3171 * For controllers newer than the P600, the pci power state 3131 * For controllers newer than the P600, the pci power state
3172 * method of resetting doesn't work so we have another way 3132 * method of resetting doesn't work so we have another way
3173 * using the doorbell register. 3133 * using the doorbell register.
@@ -3184,9 +3144,13 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
3184 if (board_id == 0x409C0E11 || board_id == 0x409D0E11) 3144 if (board_id == 0x409C0E11 || board_id == 0x409D0E11)
3185 return -ENOTSUPP; 3145 return -ENOTSUPP;
3186 3146
3187 for (i = 0; i < 32; i++) 3147 /* Save the PCI command register */
3188 pci_read_config_word(pdev, 2*i, &saved_config_space[i]); 3148 pci_read_config_word(pdev, 4, &command_register);
3189 3149 /* Turn the board off. This is so that later pci_restore_state()
3150 * won't turn the board on before the rest of config space is ready.
3151 */
3152 pci_disable_device(pdev);
3153 pci_save_state(pdev);
3190 3154
3191 /* find the first memory BAR, so we can find the cfg table */ 3155 /* find the first memory BAR, so we can find the cfg table */
3192 rc = hpsa_pci_find_memory_BAR(pdev, &paddr); 3156 rc = hpsa_pci_find_memory_BAR(pdev, &paddr);
@@ -3212,30 +3176,17 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
3212 misc_fw_support = readl(&cfgtable->misc_fw_support); 3176 misc_fw_support = readl(&cfgtable->misc_fw_support);
3213 use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; 3177 use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
3214 3178
3215 /* The doorbell reset seems to cause lockups on some Smart
3216 * Arrays (e.g. P410, P410i, maybe others). Until this is
3217 * fixed or at least isolated, avoid the doorbell reset.
3218 */
3219 use_doorbell = 0;
3220
3221 rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell); 3179 rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell);
3222 if (rc) 3180 if (rc)
3223 goto unmap_cfgtable; 3181 goto unmap_cfgtable;
3224 3182
3225 /* Restore the PCI configuration space. The Open CISS 3183 pci_restore_state(pdev);
3226 * Specification says, "Restore the PCI Configuration 3184 rc = pci_enable_device(pdev);
3227 * Registers, offsets 00h through 60h. It is important to 3185 if (rc) {
3228 * restore the command register, 16-bits at offset 04h, 3186 dev_warn(&pdev->dev, "failed to enable device.\n");
3229 * last. Do not restore the configuration status register, 3187 goto unmap_cfgtable;
3230 * 16-bits at offset 06h." Note that the offset is 2*i.
3231 */
3232 for (i = 0; i < 32; i++) {
3233 if (i == 2 || i == 3)
3234 continue;
3235 pci_write_config_word(pdev, 2*i, saved_config_space[i]);
3236 } 3188 }
3237 wmb(); 3189 pci_write_config_word(pdev, 4, command_register);
3238 pci_write_config_word(pdev, 4, saved_config_space[2]);
3239 3190
3240 /* Some devices (notably the HP Smart Array 5i Controller) 3191 /* Some devices (notably the HP Smart Array 5i Controller)
3241 need a little pause here */ 3192 need a little pause here */
@@ -3732,8 +3683,6 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
3732 return 0; /* just try to do the kdump anyhow. */ 3683 return 0; /* just try to do the kdump anyhow. */
3733 if (rc) 3684 if (rc)
3734 return -ENODEV; 3685 return -ENODEV;
3735 if (hpsa_reset_msi(pdev))
3736 return -ENODEV;
3737 3686
3738 /* Now try to get the controller to respond to a no-op */ 3687 /* Now try to get the controller to respond to a no-op */
3739 for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) { 3688 for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) {