diff options
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r-- | drivers/scsi/hpsa.c | 174 |
1 files changed, 133 insertions, 41 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index b2f478596dfb..f57d533f7475 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
@@ -174,6 +174,11 @@ static void calc_bucket_map(int *bucket, int num_buckets, | |||
174 | int nsgs, int *bucket_map); | 174 | int nsgs, int *bucket_map); |
175 | static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h); | 175 | static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h); |
176 | static inline u32 next_command(struct ctlr_info *h); | 176 | static inline u32 next_command(struct ctlr_info *h); |
177 | static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev, | ||
178 | void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index, | ||
179 | u64 *cfg_offset); | ||
180 | static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev, | ||
181 | unsigned long *memory_bar); | ||
177 | 182 | ||
178 | static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); | 183 | static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL); |
179 | static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); | 184 | static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL); |
@@ -3078,17 +3083,75 @@ static __devinit int hpsa_reset_msi(struct pci_dev *pdev) | |||
3078 | return 0; | 3083 | return 0; |
3079 | } | 3084 | } |
3080 | 3085 | ||
3086 | static int hpsa_controller_hard_reset(struct pci_dev *pdev, | ||
3087 | void * __iomem vaddr, bool use_doorbell) | ||
3088 | { | ||
3089 | u16 pmcsr; | ||
3090 | int pos; | ||
3091 | |||
3092 | if (use_doorbell) { | ||
3093 | /* For everything after the P600, the PCI power state method | ||
3094 | * of resetting the controller doesn't work, so we have this | ||
3095 | * other way using the doorbell register. | ||
3096 | */ | ||
3097 | dev_info(&pdev->dev, "using doorbell to reset controller\n"); | ||
3098 | writel(DOORBELL_CTLR_RESET, vaddr + SA5_DOORBELL); | ||
3099 | msleep(1000); | ||
3100 | } else { /* Try to do it the PCI power state way */ | ||
3101 | |||
3102 | /* Quoting from the Open CISS Specification: "The Power | ||
3103 | * Management Control/Status Register (CSR) controls the power | ||
3104 | * state of the device. The normal operating state is D0, | ||
3105 | * CSR=00h. The software off state is D3, CSR=03h. To reset | ||
3106 | * the controller, place the interface device in D3 then to D0, | ||
3107 | * this causes a secondary PCI reset which will reset the | ||
3108 | * controller." */ | ||
3109 | |||
3110 | pos = pci_find_capability(pdev, PCI_CAP_ID_PM); | ||
3111 | if (pos == 0) { | ||
3112 | dev_err(&pdev->dev, | ||
3113 | "hpsa_reset_controller: " | ||
3114 | "PCI PM not supported\n"); | ||
3115 | return -ENODEV; | ||
3116 | } | ||
3117 | dev_info(&pdev->dev, "using PCI PM to reset controller\n"); | ||
3118 | /* enter the D3hot power management state */ | ||
3119 | pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr); | ||
3120 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; | ||
3121 | pmcsr |= PCI_D3hot; | ||
3122 | pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); | ||
3123 | |||
3124 | msleep(500); | ||
3125 | |||
3126 | /* enter the D0 power management state */ | ||
3127 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; | ||
3128 | pmcsr |= PCI_D0; | ||
3129 | pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); | ||
3130 | |||
3131 | msleep(500); | ||
3132 | } | ||
3133 | return 0; | ||
3134 | } | ||
3135 | |||
3081 | /* This does a hard reset of the controller using PCI power management | 3136 | /* This does a hard reset of the controller using PCI power management |
3082 | * states. | 3137 | * states or the using the doorbell register. |
3083 | */ | 3138 | */ |
3084 | static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev) | 3139 | static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) |
3085 | { | 3140 | { |
3086 | u16 pmcsr, saved_config_space[32]; | 3141 | u16 saved_config_space[32]; |
3087 | int i, pos; | 3142 | u64 cfg_offset; |
3143 | u32 cfg_base_addr; | ||
3144 | u64 cfg_base_addr_index; | ||
3145 | void __iomem *vaddr; | ||
3146 | unsigned long paddr; | ||
3147 | u32 misc_fw_support, active_transport; | ||
3148 | int rc, i; | ||
3149 | struct CfgTable __iomem *cfgtable; | ||
3150 | bool use_doorbell; | ||
3088 | 3151 | ||
3089 | dev_info(&pdev->dev, "using PCI PM to reset controller\n"); | ||
3090 | 3152 | ||
3091 | /* This is very nearly the same thing as | 3153 | /* For controllers as old as the P600, this is very nearly |
3154 | * the same thing as | ||
3092 | * | 3155 | * |
3093 | * pci_save_state(pci_dev); | 3156 | * pci_save_state(pci_dev); |
3094 | * pci_set_power_state(pci_dev, PCI_D3hot); | 3157 | * pci_set_power_state(pci_dev, PCI_D3hot); |
@@ -3102,41 +3165,42 @@ static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev) | |||
3102 | * violate the ordering requirements for restoring the | 3165 | * violate the ordering requirements for restoring the |
3103 | * configuration space from the CCISS document (see the | 3166 | * configuration space from the CCISS document (see the |
3104 | * comment below). So we roll our own .... | 3167 | * comment below). So we roll our own .... |
3168 | * | ||
3169 | * For controllers newer than the P600, the pci power state | ||
3170 | * method of resetting doesn't work so we have another way | ||
3171 | * using the doorbell register. | ||
3105 | */ | 3172 | */ |
3106 | |||
3107 | for (i = 0; i < 32; i++) | 3173 | for (i = 0; i < 32; i++) |
3108 | pci_read_config_word(pdev, 2*i, &saved_config_space[i]); | 3174 | pci_read_config_word(pdev, 2*i, &saved_config_space[i]); |
3109 | 3175 | ||
3110 | pos = pci_find_capability(pdev, PCI_CAP_ID_PM); | ||
3111 | if (pos == 0) { | ||
3112 | dev_err(&pdev->dev, | ||
3113 | "hpsa_reset_controller: PCI PM not supported\n"); | ||
3114 | return -ENODEV; | ||
3115 | } | ||
3116 | |||
3117 | /* Quoting from the Open CISS Specification: "The Power | ||
3118 | * Management Control/Status Register (CSR) controls the power | ||
3119 | * state of the device. The normal operating state is D0, | ||
3120 | * CSR=00h. The software off state is D3, CSR=03h. To reset | ||
3121 | * the controller, place the interface device in D3 then to | ||
3122 | * D0, this causes a secondary PCI reset which will reset the | ||
3123 | * controller." | ||
3124 | */ | ||
3125 | 3176 | ||
3126 | /* enter the D3hot power management state */ | 3177 | /* find the first memory BAR, so we can find the cfg table */ |
3127 | pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr); | 3178 | rc = hpsa_pci_find_memory_BAR(pdev, &paddr); |
3128 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; | 3179 | if (rc) |
3129 | pmcsr |= PCI_D3hot; | 3180 | return rc; |
3130 | pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); | 3181 | vaddr = remap_pci_mem(paddr, 0x250); |
3182 | if (!vaddr) | ||
3183 | return -ENOMEM; | ||
3131 | 3184 | ||
3132 | msleep(500); | 3185 | /* find cfgtable in order to check if reset via doorbell is supported */ |
3186 | rc = hpsa_find_cfg_addrs(pdev, vaddr, &cfg_base_addr, | ||
3187 | &cfg_base_addr_index, &cfg_offset); | ||
3188 | if (rc) | ||
3189 | goto unmap_vaddr; | ||
3190 | cfgtable = remap_pci_mem(pci_resource_start(pdev, | ||
3191 | cfg_base_addr_index) + cfg_offset, sizeof(*cfgtable)); | ||
3192 | if (!cfgtable) { | ||
3193 | rc = -ENOMEM; | ||
3194 | goto unmap_vaddr; | ||
3195 | } | ||
3133 | 3196 | ||
3134 | /* enter the D0 power management state */ | 3197 | /* If reset via doorbell register is supported, use that. */ |
3135 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; | 3198 | misc_fw_support = readl(&cfgtable->misc_fw_support); |
3136 | pmcsr |= PCI_D0; | 3199 | use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; |
3137 | pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr); | ||
3138 | 3200 | ||
3139 | msleep(500); | 3201 | rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell); |
3202 | if (rc) | ||
3203 | goto unmap_cfgtable; | ||
3140 | 3204 | ||
3141 | /* Restore the PCI configuration space. The Open CISS | 3205 | /* Restore the PCI configuration space. The Open CISS |
3142 | * Specification says, "Restore the PCI Configuration | 3206 | * Specification says, "Restore the PCI Configuration |
@@ -3153,7 +3217,29 @@ static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev) | |||
3153 | wmb(); | 3217 | wmb(); |
3154 | pci_write_config_word(pdev, 4, saved_config_space[2]); | 3218 | pci_write_config_word(pdev, 4, saved_config_space[2]); |
3155 | 3219 | ||
3156 | return 0; | 3220 | /* Some devices (notably the HP Smart Array 5i Controller) |
3221 | need a little pause here */ | ||
3222 | msleep(HPSA_POST_RESET_PAUSE_MSECS); | ||
3223 | |||
3224 | /* Controller should be in simple mode at this point. If it's not, | ||
3225 | * It means we're on one of those controllers which doesn't support | ||
3226 | * the doorbell reset method and on which the PCI power management reset | ||
3227 | * method doesn't work (P800, for example.) | ||
3228 | * In those cases, pretend the reset worked and hope for the best. | ||
3229 | */ | ||
3230 | active_transport = readl(&cfgtable->TransportActive); | ||
3231 | if (active_transport & PERFORMANT_MODE) { | ||
3232 | dev_warn(&pdev->dev, "Unable to successfully reset controller," | ||
3233 | " proceeding anyway.\n"); | ||
3234 | rc = -ENOTSUPP; | ||
3235 | } | ||
3236 | |||
3237 | unmap_cfgtable: | ||
3238 | iounmap(cfgtable); | ||
3239 | |||
3240 | unmap_vaddr: | ||
3241 | iounmap(vaddr); | ||
3242 | return rc; | ||
3157 | } | 3243 | } |
3158 | 3244 | ||
3159 | /* | 3245 | /* |
@@ -3573,18 +3659,24 @@ static void __devinit hpsa_hba_inquiry(struct ctlr_info *h) | |||
3573 | 3659 | ||
3574 | static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev) | 3660 | static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev) |
3575 | { | 3661 | { |
3576 | int i; | 3662 | int rc, i; |
3577 | 3663 | ||
3578 | if (!reset_devices) | 3664 | if (!reset_devices) |
3579 | return 0; | 3665 | return 0; |
3580 | 3666 | ||
3581 | /* Reset the controller with a PCI power-cycle */ | 3667 | /* Reset the controller with a PCI power-cycle or via doorbell */ |
3582 | if (hpsa_hard_reset_controller(pdev) || hpsa_reset_msi(pdev)) | 3668 | rc = hpsa_kdump_hard_reset_controller(pdev); |
3583 | return -ENODEV; | ||
3584 | 3669 | ||
3585 | /* Some devices (notably the HP Smart Array 5i Controller) | 3670 | /* -ENOTSUPP here means we cannot reset the controller |
3586 | need a little pause here */ | 3671 | * but it's already (and still) up and running in |
3587 | msleep(HPSA_POST_RESET_PAUSE_MSECS); | 3672 | * "performant mode". |
3673 | */ | ||
3674 | if (rc == -ENOTSUPP) | ||
3675 | return 0; /* just try to do the kdump anyhow. */ | ||
3676 | if (rc) | ||
3677 | return -ENODEV; | ||
3678 | if (hpsa_reset_msi(pdev)) | ||
3679 | return -ENODEV; | ||
3588 | 3680 | ||
3589 | /* Now try to get the controller to respond to a no-op */ | 3681 | /* Now try to get the controller to respond to a no-op */ |
3590 | for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) { | 3682 | for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) { |