Commit 1df8552abf36519ca8b9e2a8d1e204bac2076d51

Authored by Stephen M. Cameron
Committed by James Bottomley
1 parent 4c2a8c40d8

[SCSI] hpsa: Fix hard reset code.

Smart Array controllers newer than the P600 do not honor the
PCI power state method of resetting the controllers.  Instead,
in these cases we can get them to reset via the "doorbell" register.

This escaped notice until we began using "performant" mode because
the fact that the controllers did not reset did not normally
impede subsequent operation, and so things generally appeared to
"work".  Once the performant mode code was added, if the controller
does not reset, it remains in performant mode.  The code immediately
after the reset presumes the controller is in "simple" mode
(which previously, it had remained in simple mode the whole time).
If the controller remains in performant mode any code which presumes
it is in simple mode will not work.  So the reset needs to be fixed.

Unfortunately there are some controllers which cannot be reset by
either method. (eg. p800).  We detect these cases by noticing that
the controller seems to remain in performant mode even after a
reset has been attempted.  In those case, we proceed anyway,
as if the reset has happened (and skip the step of waiting for
the controller to become ready -- which is expecting it to be in
"simple" mode.)  To sum up, we try to do a better job of resetting
the controller if "reset_devices" is set, and if it doesn't work,
we print a message and try to continue anyway.

Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>

Showing 2 changed files with 137 additions and 41 deletions Side-by-side Diff

... ... @@ -174,6 +174,11 @@
174 174 int nsgs, int *bucket_map);
175 175 static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h);
176 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 183 static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
179 184 static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
180 185  
181 186  
182 187  
183 188  
184 189  
... ... @@ -3078,17 +3083,75 @@
3078 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 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];
3087   - int i, pos;
  3141 + u16 saved_config_space[32];
  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 3156 * pci_save_state(pci_dev);
3094 3157 * pci_set_power_state(pci_dev, PCI_D3hot);
3095 3158  
3096 3159  
3097 3160  
3098 3161  
3099 3162  
3100 3163  
3101 3164  
... ... @@ -3102,42 +3165,43 @@
3102 3165 * violate the ordering requirements for restoring the
3103 3166 * configuration space from the CCISS document (see the
3104 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 3173 for (i = 0; i < 32; i++)
3108 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 3176  
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   - */
  3177 + /* find the first memory BAR, so we can find the cfg table */
  3178 + rc = hpsa_pci_find_memory_BAR(pdev, &paddr);
  3179 + if (rc)
  3180 + return rc;
  3181 + vaddr = remap_pci_mem(paddr, 0x250);
  3182 + if (!vaddr)
  3183 + return -ENOMEM;
3125 3184  
3126   - /* enter the D3hot power management state */
3127   - pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr);
3128   - pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
3129   - pmcsr |= PCI_D3hot;
3130   - pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
  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 + }
3131 3196  
3132   - msleep(500);
  3197 + /* If reset via doorbell register is supported, use that. */
  3198 + misc_fw_support = readl(&cfgtable->misc_fw_support);
  3199 + use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
3133 3200  
3134   - /* enter the D0 power management state */
3135   - pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
3136   - pmcsr |= PCI_D0;
3137   - pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
  3201 + rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell);
  3202 + if (rc)
  3203 + goto unmap_cfgtable;
3138 3204  
3139   - msleep(500);
3140   -
3141 3205 /* Restore the PCI configuration space. The Open CISS
3142 3206 * Specification says, "Restore the PCI Configuration
3143 3207 * Registers, offsets 00h through 60h. It is important to
... ... @@ -3153,7 +3217,29 @@
3153 3217 wmb();
3154 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 /*
3160 3246  
3161 3247  
... ... @@ -3573,18 +3659,24 @@
3573 3659  
3574 3660 static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
3575 3661 {
3576   - int i;
  3662 + int rc, i;
3577 3663  
3578 3664 if (!reset_devices)
3579 3665 return 0;
3580 3666  
3581   - /* Reset the controller with a PCI power-cycle */
3582   - if (hpsa_hard_reset_controller(pdev) || hpsa_reset_msi(pdev))
3583   - return -ENODEV;
  3667 + /* Reset the controller with a PCI power-cycle or via doorbell */
  3668 + rc = hpsa_kdump_hard_reset_controller(pdev);
3584 3669  
3585   - /* Some devices (notably the HP Smart Array 5i Controller)
3586   - need a little pause here */
3587   - msleep(HPSA_POST_RESET_PAUSE_MSECS);
  3670 + /* -ENOTSUPP here means we cannot reset the controller
  3671 + * but it's already (and still) up and running in
  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 3681 /* Now try to get the controller to respond to a no-op */
3590 3682 for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) {
drivers/scsi/hpsa_cmd.h
... ... @@ -100,6 +100,7 @@
100 100 /* Configuration Table */
101 101 #define CFGTBL_ChangeReq 0x00000001l
102 102 #define CFGTBL_AccCmds 0x00000001l
  103 +#define DOORBELL_CTLR_RESET 0x00000004l
103 104  
104 105 #define CFGTBL_Trans_Simple 0x00000002l
105 106 #define CFGTBL_Trans_Performant 0x00000004l
... ... @@ -339,6 +340,9 @@
339 340 u32 MaxPhysicalDevices;
340 341 u32 MaxPhysicalDrivesPerLogicalUnit;
341 342 u32 MaxPerformantModeCommands;
  343 + u8 reserved[0x78 - 0x58];
  344 + u32 misc_fw_support; /* offset 0x78 */
  345 +#define MISC_FW_DOORBELL_RESET (0x02)
342 346 };
343 347  
344 348 #define NUM_BLOCKFETCH_ENTRIES 8