diff options
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 160 |
1 files changed, 152 insertions, 8 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 9219953ee949..190d0ae0193f 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -99,6 +99,7 @@ static unsigned int ipr_debug = 0; | |||
99 | static unsigned int ipr_max_devs = IPR_DEFAULT_SIS64_DEVS; | 99 | static unsigned int ipr_max_devs = IPR_DEFAULT_SIS64_DEVS; |
100 | static unsigned int ipr_dual_ioa_raid = 1; | 100 | static unsigned int ipr_dual_ioa_raid = 1; |
101 | static unsigned int ipr_number_of_msix = 2; | 101 | static unsigned int ipr_number_of_msix = 2; |
102 | static unsigned int ipr_fast_reboot; | ||
102 | static DEFINE_SPINLOCK(ipr_driver_lock); | 103 | static DEFINE_SPINLOCK(ipr_driver_lock); |
103 | 104 | ||
104 | /* This table describes the differences between DMA controller chips */ | 105 | /* This table describes the differences between DMA controller chips */ |
@@ -221,6 +222,8 @@ MODULE_PARM_DESC(max_devs, "Specify the maximum number of physical devices. " | |||
221 | "[Default=" __stringify(IPR_DEFAULT_SIS64_DEVS) "]"); | 222 | "[Default=" __stringify(IPR_DEFAULT_SIS64_DEVS) "]"); |
222 | module_param_named(number_of_msix, ipr_number_of_msix, int, 0); | 223 | module_param_named(number_of_msix, ipr_number_of_msix, int, 0); |
223 | MODULE_PARM_DESC(number_of_msix, "Specify the number of MSIX interrupts to use on capable adapters (1 - 16). (default:2)"); | 224 | MODULE_PARM_DESC(number_of_msix, "Specify the number of MSIX interrupts to use on capable adapters (1 - 16). (default:2)"); |
225 | module_param_named(fast_reboot, ipr_fast_reboot, int, S_IRUGO | S_IWUSR); | ||
226 | MODULE_PARM_DESC(fast_reboot, "Skip adapter shutdown during reboot. Set to 1 to enable. (default: 0)"); | ||
224 | MODULE_LICENSE("GPL"); | 227 | MODULE_LICENSE("GPL"); |
225 | MODULE_VERSION(IPR_DRIVER_VERSION); | 228 | MODULE_VERSION(IPR_DRIVER_VERSION); |
226 | 229 | ||
@@ -1462,7 +1465,8 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) | |||
1462 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); | 1465 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); |
1463 | 1466 | ||
1464 | if (ioasc) { | 1467 | if (ioasc) { |
1465 | if (ioasc != IPR_IOASC_IOA_WAS_RESET) | 1468 | if (ioasc != IPR_IOASC_IOA_WAS_RESET && |
1469 | ioasc != IPR_IOASC_ABORTED_CMD_TERM_BY_HOST) | ||
1466 | dev_err(&ioa_cfg->pdev->dev, | 1470 | dev_err(&ioa_cfg->pdev->dev, |
1467 | "Host RCB failed with IOASC: 0x%08X\n", ioasc); | 1471 | "Host RCB failed with IOASC: 0x%08X\n", ioasc); |
1468 | 1472 | ||
@@ -2566,7 +2570,8 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) | |||
2566 | ipr_handle_log_data(ioa_cfg, hostrcb); | 2570 | ipr_handle_log_data(ioa_cfg, hostrcb); |
2567 | if (fd_ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED) | 2571 | if (fd_ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED) |
2568 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV); | 2572 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV); |
2569 | } else if (ioasc != IPR_IOASC_IOA_WAS_RESET) { | 2573 | } else if (ioasc != IPR_IOASC_IOA_WAS_RESET && |
2574 | ioasc != IPR_IOASC_ABORTED_CMD_TERM_BY_HOST) { | ||
2570 | dev_err(&ioa_cfg->pdev->dev, | 2575 | dev_err(&ioa_cfg->pdev->dev, |
2571 | "Host RCB failed with IOASC: 0x%08X\n", ioasc); | 2576 | "Host RCB failed with IOASC: 0x%08X\n", ioasc); |
2572 | } | 2577 | } |
@@ -5379,9 +5384,6 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, | |||
5379 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { | 5384 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { |
5380 | /* Mask the interrupt */ | 5385 | /* Mask the interrupt */ |
5381 | writel(IPR_PCII_IOA_TRANS_TO_OPER, ioa_cfg->regs.set_interrupt_mask_reg); | 5386 | writel(IPR_PCII_IOA_TRANS_TO_OPER, ioa_cfg->regs.set_interrupt_mask_reg); |
5382 | |||
5383 | /* Clear the interrupt */ | ||
5384 | writel(IPR_PCII_IOA_TRANS_TO_OPER, ioa_cfg->regs.clr_interrupt_reg); | ||
5385 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); | 5387 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); |
5386 | 5388 | ||
5387 | list_del(&ioa_cfg->reset_cmd->queue); | 5389 | list_del(&ioa_cfg->reset_cmd->queue); |
@@ -8479,6 +8481,122 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd) | |||
8479 | } | 8481 | } |
8480 | 8482 | ||
8481 | /** | 8483 | /** |
8484 | * ipr_reset_quiesce_done - Complete IOA disconnect | ||
8485 | * @ipr_cmd: ipr command struct | ||
8486 | * | ||
8487 | * Description: Freeze the adapter to complete quiesce processing | ||
8488 | * | ||
8489 | * Return value: | ||
8490 | * IPR_RC_JOB_CONTINUE | ||
8491 | **/ | ||
8492 | static int ipr_reset_quiesce_done(struct ipr_cmnd *ipr_cmd) | ||
8493 | { | ||
8494 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
8495 | |||
8496 | ENTER; | ||
8497 | ipr_cmd->job_step = ipr_ioa_bringdown_done; | ||
8498 | ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); | ||
8499 | LEAVE; | ||
8500 | return IPR_RC_JOB_CONTINUE; | ||
8501 | } | ||
8502 | |||
8503 | /** | ||
8504 | * ipr_reset_cancel_hcam_done - Check for outstanding commands | ||
8505 | * @ipr_cmd: ipr command struct | ||
8506 | * | ||
8507 | * Description: Ensure nothing is outstanding to the IOA and | ||
8508 | * proceed with IOA disconnect. Otherwise reset the IOA. | ||
8509 | * | ||
8510 | * Return value: | ||
8511 | * IPR_RC_JOB_RETURN / IPR_RC_JOB_CONTINUE | ||
8512 | **/ | ||
8513 | static int ipr_reset_cancel_hcam_done(struct ipr_cmnd *ipr_cmd) | ||
8514 | { | ||
8515 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
8516 | struct ipr_cmnd *loop_cmd; | ||
8517 | struct ipr_hrr_queue *hrrq; | ||
8518 | int rc = IPR_RC_JOB_CONTINUE; | ||
8519 | int count = 0; | ||
8520 | |||
8521 | ENTER; | ||
8522 | ipr_cmd->job_step = ipr_reset_quiesce_done; | ||
8523 | |||
8524 | for_each_hrrq(hrrq, ioa_cfg) { | ||
8525 | spin_lock(&hrrq->_lock); | ||
8526 | list_for_each_entry(loop_cmd, &hrrq->hrrq_pending_q, queue) { | ||
8527 | count++; | ||
8528 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); | ||
8529 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); | ||
8530 | rc = IPR_RC_JOB_RETURN; | ||
8531 | break; | ||
8532 | } | ||
8533 | spin_unlock(&hrrq->_lock); | ||
8534 | |||
8535 | if (count) | ||
8536 | break; | ||
8537 | } | ||
8538 | |||
8539 | LEAVE; | ||
8540 | return rc; | ||
8541 | } | ||
8542 | |||
8543 | /** | ||
8544 | * ipr_reset_cancel_hcam - Cancel outstanding HCAMs | ||
8545 | * @ipr_cmd: ipr command struct | ||
8546 | * | ||
8547 | * Description: Cancel any oustanding HCAMs to the IOA. | ||
8548 | * | ||
8549 | * Return value: | ||
8550 | * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN | ||
8551 | **/ | ||
8552 | static int ipr_reset_cancel_hcam(struct ipr_cmnd *ipr_cmd) | ||
8553 | { | ||
8554 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
8555 | int rc = IPR_RC_JOB_CONTINUE; | ||
8556 | struct ipr_cmd_pkt *cmd_pkt; | ||
8557 | struct ipr_cmnd *hcam_cmd; | ||
8558 | struct ipr_hrr_queue *hrrq = &ioa_cfg->hrrq[IPR_INIT_HRRQ]; | ||
8559 | |||
8560 | ENTER; | ||
8561 | ipr_cmd->job_step = ipr_reset_cancel_hcam_done; | ||
8562 | |||
8563 | if (!hrrq->ioa_is_dead) { | ||
8564 | if (!list_empty(&ioa_cfg->hostrcb_pending_q)) { | ||
8565 | list_for_each_entry(hcam_cmd, &hrrq->hrrq_pending_q, queue) { | ||
8566 | if (hcam_cmd->ioarcb.cmd_pkt.cdb[0] != IPR_HOST_CONTROLLED_ASYNC) | ||
8567 | continue; | ||
8568 | |||
8569 | ipr_cmd->ioarcb.res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); | ||
8570 | ipr_cmd->ioarcb.cmd_pkt.request_type = IPR_RQTYPE_IOACMD; | ||
8571 | cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; | ||
8572 | cmd_pkt->request_type = IPR_RQTYPE_IOACMD; | ||
8573 | cmd_pkt->cdb[0] = IPR_CANCEL_REQUEST; | ||
8574 | cmd_pkt->cdb[1] = IPR_CANCEL_64BIT_IOARCB; | ||
8575 | cmd_pkt->cdb[10] = ((u64) hcam_cmd->dma_addr >> 56) & 0xff; | ||
8576 | cmd_pkt->cdb[11] = ((u64) hcam_cmd->dma_addr >> 48) & 0xff; | ||
8577 | cmd_pkt->cdb[12] = ((u64) hcam_cmd->dma_addr >> 40) & 0xff; | ||
8578 | cmd_pkt->cdb[13] = ((u64) hcam_cmd->dma_addr >> 32) & 0xff; | ||
8579 | cmd_pkt->cdb[2] = ((u64) hcam_cmd->dma_addr >> 24) & 0xff; | ||
8580 | cmd_pkt->cdb[3] = ((u64) hcam_cmd->dma_addr >> 16) & 0xff; | ||
8581 | cmd_pkt->cdb[4] = ((u64) hcam_cmd->dma_addr >> 8) & 0xff; | ||
8582 | cmd_pkt->cdb[5] = ((u64) hcam_cmd->dma_addr) & 0xff; | ||
8583 | |||
8584 | ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, | ||
8585 | IPR_CANCEL_TIMEOUT); | ||
8586 | |||
8587 | rc = IPR_RC_JOB_RETURN; | ||
8588 | ipr_cmd->job_step = ipr_reset_cancel_hcam; | ||
8589 | break; | ||
8590 | } | ||
8591 | } | ||
8592 | } else | ||
8593 | ipr_cmd->job_step = ipr_reset_alert; | ||
8594 | |||
8595 | LEAVE; | ||
8596 | return rc; | ||
8597 | } | ||
8598 | |||
8599 | /** | ||
8482 | * ipr_reset_ucode_download_done - Microcode download completion | 8600 | * ipr_reset_ucode_download_done - Microcode download completion |
8483 | * @ipr_cmd: ipr command struct | 8601 | * @ipr_cmd: ipr command struct |
8484 | * | 8602 | * |
@@ -8560,7 +8678,9 @@ static int ipr_reset_shutdown_ioa(struct ipr_cmnd *ipr_cmd) | |||
8560 | int rc = IPR_RC_JOB_CONTINUE; | 8678 | int rc = IPR_RC_JOB_CONTINUE; |
8561 | 8679 | ||
8562 | ENTER; | 8680 | ENTER; |
8563 | if (shutdown_type != IPR_SHUTDOWN_NONE && | 8681 | if (shutdown_type == IPR_SHUTDOWN_QUIESCE) |
8682 | ipr_cmd->job_step = ipr_reset_cancel_hcam; | ||
8683 | else if (shutdown_type != IPR_SHUTDOWN_NONE && | ||
8564 | !ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) { | 8684 | !ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) { |
8565 | ipr_cmd->ioarcb.res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); | 8685 | ipr_cmd->ioarcb.res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); |
8566 | ipr_cmd->ioarcb.cmd_pkt.request_type = IPR_RQTYPE_IOACMD; | 8686 | ipr_cmd->ioarcb.cmd_pkt.request_type = IPR_RQTYPE_IOACMD; |
@@ -10035,6 +10155,7 @@ static void ipr_shutdown(struct pci_dev *pdev) | |||
10035 | { | 10155 | { |
10036 | struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); | 10156 | struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); |
10037 | unsigned long lock_flags = 0; | 10157 | unsigned long lock_flags = 0; |
10158 | enum ipr_shutdown_type shutdown_type = IPR_SHUTDOWN_NORMAL; | ||
10038 | int i; | 10159 | int i; |
10039 | 10160 | ||
10040 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | 10161 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); |
@@ -10050,9 +10171,31 @@ static void ipr_shutdown(struct pci_dev *pdev) | |||
10050 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | 10171 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); |
10051 | } | 10172 | } |
10052 | 10173 | ||
10053 | ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL); | 10174 | if (ipr_fast_reboot && system_state == SYSTEM_RESTART && ioa_cfg->sis64) |
10175 | shutdown_type = IPR_SHUTDOWN_QUIESCE; | ||
10176 | |||
10177 | ipr_initiate_ioa_bringdown(ioa_cfg, shutdown_type); | ||
10054 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 10178 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
10055 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | 10179 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); |
10180 | if (ipr_fast_reboot && system_state == SYSTEM_RESTART && ioa_cfg->sis64) { | ||
10181 | if (ioa_cfg->intr_flag == IPR_USE_MSI || | ||
10182 | ioa_cfg->intr_flag == IPR_USE_MSIX) { | ||
10183 | int i; | ||
10184 | for (i = 0; i < ioa_cfg->nvectors; i++) | ||
10185 | free_irq(ioa_cfg->vectors_info[i].vec, | ||
10186 | &ioa_cfg->hrrq[i]); | ||
10187 | } | ||
10188 | |||
10189 | if (ioa_cfg->intr_flag == IPR_USE_MSI) { | ||
10190 | pci_disable_msi(ioa_cfg->pdev); | ||
10191 | ioa_cfg->intr_flag &= ~IPR_USE_MSI; | ||
10192 | } else if (ioa_cfg->intr_flag == IPR_USE_MSIX) { | ||
10193 | pci_disable_msix(ioa_cfg->pdev); | ||
10194 | ioa_cfg->intr_flag &= ~IPR_USE_MSIX; | ||
10195 | } | ||
10196 | |||
10197 | pci_disable_device(ioa_cfg->pdev); | ||
10198 | } | ||
10056 | } | 10199 | } |
10057 | 10200 | ||
10058 | static struct pci_device_id ipr_pci_table[] = { | 10201 | static struct pci_device_id ipr_pci_table[] = { |
@@ -10210,7 +10353,8 @@ static int ipr_halt(struct notifier_block *nb, ulong event, void *buf) | |||
10210 | 10353 | ||
10211 | list_for_each_entry(ioa_cfg, &ipr_ioa_head, queue) { | 10354 | list_for_each_entry(ioa_cfg, &ipr_ioa_head, queue) { |
10212 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | 10355 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); |
10213 | if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) { | 10356 | if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds || |
10357 | (ipr_fast_reboot && event == SYS_RESTART && ioa_cfg->sis64)) { | ||
10214 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); | 10358 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); |
10215 | continue; | 10359 | continue; |
10216 | } | 10360 | } |