diff options
-rw-r--r-- | drivers/scsi/hpsa.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 89744a152427..c1f4a95d5d5d 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
@@ -243,7 +243,7 @@ static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id); | |||
243 | static int hpsa_wait_for_board_state(struct pci_dev *pdev, void __iomem *vaddr, | 243 | static int hpsa_wait_for_board_state(struct pci_dev *pdev, void __iomem *vaddr, |
244 | int wait_for_ready); | 244 | int wait_for_ready); |
245 | static inline void finish_cmd(struct CommandList *c); | 245 | static inline void finish_cmd(struct CommandList *c); |
246 | static void hpsa_wait_for_mode_change_ack(struct ctlr_info *h); | 246 | static int hpsa_wait_for_mode_change_ack(struct ctlr_info *h); |
247 | #define BOARD_NOT_READY 0 | 247 | #define BOARD_NOT_READY 0 |
248 | #define BOARD_READY 1 | 248 | #define BOARD_READY 1 |
249 | static void hpsa_drain_accel_commands(struct ctlr_info *h); | 249 | static void hpsa_drain_accel_commands(struct ctlr_info *h); |
@@ -6191,7 +6191,7 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h) | |||
6191 | writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG); | 6191 | writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG); |
6192 | } | 6192 | } |
6193 | 6193 | ||
6194 | static void hpsa_wait_for_clear_event_notify_ack(struct ctlr_info *h) | 6194 | static int hpsa_wait_for_clear_event_notify_ack(struct ctlr_info *h) |
6195 | { | 6195 | { |
6196 | int i; | 6196 | int i; |
6197 | u32 doorbell_value; | 6197 | u32 doorbell_value; |
@@ -6202,13 +6202,16 @@ static void hpsa_wait_for_clear_event_notify_ack(struct ctlr_info *h) | |||
6202 | doorbell_value = readl(h->vaddr + SA5_DOORBELL); | 6202 | doorbell_value = readl(h->vaddr + SA5_DOORBELL); |
6203 | spin_unlock_irqrestore(&h->lock, flags); | 6203 | spin_unlock_irqrestore(&h->lock, flags); |
6204 | if (!(doorbell_value & DOORBELL_CLEAR_EVENTS)) | 6204 | if (!(doorbell_value & DOORBELL_CLEAR_EVENTS)) |
6205 | break; | 6205 | goto done; |
6206 | /* delay and try again */ | 6206 | /* delay and try again */ |
6207 | msleep(CLEAR_EVENT_WAIT_INTERVAL); | 6207 | msleep(CLEAR_EVENT_WAIT_INTERVAL); |
6208 | } | 6208 | } |
6209 | return -ENODEV; | ||
6210 | done: | ||
6211 | return 0; | ||
6209 | } | 6212 | } |
6210 | 6213 | ||
6211 | static void hpsa_wait_for_mode_change_ack(struct ctlr_info *h) | 6214 | static int hpsa_wait_for_mode_change_ack(struct ctlr_info *h) |
6212 | { | 6215 | { |
6213 | int i; | 6216 | int i; |
6214 | u32 doorbell_value; | 6217 | u32 doorbell_value; |
@@ -6223,12 +6226,16 @@ static void hpsa_wait_for_mode_change_ack(struct ctlr_info *h) | |||
6223 | doorbell_value = readl(h->vaddr + SA5_DOORBELL); | 6226 | doorbell_value = readl(h->vaddr + SA5_DOORBELL); |
6224 | spin_unlock_irqrestore(&h->lock, flags); | 6227 | spin_unlock_irqrestore(&h->lock, flags); |
6225 | if (!(doorbell_value & CFGTBL_ChangeReq)) | 6228 | if (!(doorbell_value & CFGTBL_ChangeReq)) |
6226 | break; | 6229 | goto done; |
6227 | /* delay and try again */ | 6230 | /* delay and try again */ |
6228 | msleep(MODE_CHANGE_WAIT_INTERVAL); | 6231 | msleep(MODE_CHANGE_WAIT_INTERVAL); |
6229 | } | 6232 | } |
6233 | return -ENODEV; | ||
6234 | done: | ||
6235 | return 0; | ||
6230 | } | 6236 | } |
6231 | 6237 | ||
6238 | /* return -ENODEV or other reason on error, 0 on success */ | ||
6232 | static int hpsa_enter_simple_mode(struct ctlr_info *h) | 6239 | static int hpsa_enter_simple_mode(struct ctlr_info *h) |
6233 | { | 6240 | { |
6234 | u32 trans_support; | 6241 | u32 trans_support; |
@@ -6243,7 +6250,8 @@ static int hpsa_enter_simple_mode(struct ctlr_info *h) | |||
6243 | writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); | 6250 | writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest)); |
6244 | writel(0, &h->cfgtable->HostWrite.command_pool_addr_hi); | 6251 | writel(0, &h->cfgtable->HostWrite.command_pool_addr_hi); |
6245 | writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); | 6252 | writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); |
6246 | hpsa_wait_for_mode_change_ack(h); | 6253 | if (hpsa_wait_for_mode_change_ack(h)) |
6254 | goto error; | ||
6247 | print_cfg_table(&h->pdev->dev, h->cfgtable); | 6255 | print_cfg_table(&h->pdev->dev, h->cfgtable); |
6248 | if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) | 6256 | if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) |
6249 | goto error; | 6257 | goto error; |
@@ -7144,7 +7152,8 @@ static void calc_bucket_map(int bucket[], int num_buckets, | |||
7144 | } | 7152 | } |
7145 | } | 7153 | } |
7146 | 7154 | ||
7147 | static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) | 7155 | /* return -ENODEV or other reason on error, 0 on success */ |
7156 | static int hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) | ||
7148 | { | 7157 | { |
7149 | int i; | 7158 | int i; |
7150 | unsigned long register_value; | 7159 | unsigned long register_value; |
@@ -7236,12 +7245,16 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) | |||
7236 | } | 7245 | } |
7237 | } | 7246 | } |
7238 | writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); | 7247 | writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); |
7239 | hpsa_wait_for_mode_change_ack(h); | 7248 | if (hpsa_wait_for_mode_change_ack(h)) { |
7249 | dev_err(&h->pdev->dev, | ||
7250 | "performant mode problem - doorbell timeout\n"); | ||
7251 | return -ENODEV; | ||
7252 | } | ||
7240 | register_value = readl(&(h->cfgtable->TransportActive)); | 7253 | register_value = readl(&(h->cfgtable->TransportActive)); |
7241 | if (!(register_value & CFGTBL_Trans_Performant)) { | 7254 | if (!(register_value & CFGTBL_Trans_Performant)) { |
7242 | dev_err(&h->pdev->dev, | 7255 | dev_err(&h->pdev->dev, |
7243 | "performant mode problem - transport not active\n"); | 7256 | "performant mode problem - transport not active\n"); |
7244 | return; | 7257 | return -ENODEV; |
7245 | } | 7258 | } |
7246 | /* Change the access methods to the performant access methods */ | 7259 | /* Change the access methods to the performant access methods */ |
7247 | h->access = access; | 7260 | h->access = access; |
@@ -7249,7 +7262,7 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) | |||
7249 | 7262 | ||
7250 | if (!((trans_support & CFGTBL_Trans_io_accel1) || | 7263 | if (!((trans_support & CFGTBL_Trans_io_accel1) || |
7251 | (trans_support & CFGTBL_Trans_io_accel2))) | 7264 | (trans_support & CFGTBL_Trans_io_accel2))) |
7252 | return; | 7265 | return 0; |
7253 | 7266 | ||
7254 | if (trans_support & CFGTBL_Trans_io_accel1) { | 7267 | if (trans_support & CFGTBL_Trans_io_accel1) { |
7255 | /* Set up I/O accelerator mode */ | 7268 | /* Set up I/O accelerator mode */ |
@@ -7313,7 +7326,12 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) | |||
7313 | writel(bft2[i], &h->ioaccel2_bft2_regs[i]); | 7326 | writel(bft2[i], &h->ioaccel2_bft2_regs[i]); |
7314 | } | 7327 | } |
7315 | writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); | 7328 | writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); |
7316 | hpsa_wait_for_mode_change_ack(h); | 7329 | if (hpsa_wait_for_mode_change_ack(h)) { |
7330 | dev_err(&h->pdev->dev, | ||
7331 | "performant mode problem - enabling ioaccel mode\n"); | ||
7332 | return -ENODEV; | ||
7333 | } | ||
7334 | return 0; | ||
7317 | } | 7335 | } |
7318 | 7336 | ||
7319 | static int hpsa_alloc_ioaccel_cmd_and_bft(struct ctlr_info *h) | 7337 | static int hpsa_alloc_ioaccel_cmd_and_bft(struct ctlr_info *h) |