aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBrian King <brking@linux.vnet.ibm.com>2015-03-26 12:23:50 -0400
committerJames Bottomley <JBottomley@Odin.com>2015-04-09 16:42:07 -0400
commit4fdd7c7aabbec3aa9e5dc41c129bc9f6aed7e615 (patch)
tree5bbd1cf3dacd2f7428aa56b04358acaee41e60ec /drivers
parentbe0cf6ca301c61458dc4aa1a37acf4f58d2ed3d6 (diff)
ipr: Reboot speed improvements
Currently when performing a reboot with an ipr adapter, the adapter gets shutdown completely, flushing all write cache, as well as performing a full hardware reset of the card during the shutdown phase of the old kernel. This ensures the adapter is in a fully quiesced state across the reboot. There are scenarios, however, such as when performing kexec, where this full adapter shutdown is not required and not desired, since it can make the reboot process take noticeably longer. This patch adds a module parameter to allow for skipping the full shutdown during reboot. Rather than performing a full adapter shutdown and reset, we simply cancel any outstanding error buffers, place the adapter into a state where it has no memory of any DMA addresses from the old kernel, then disable the device. This significantly speeds up kexec boot, particularly in configurations with multiple ipr adapters. Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Reviewed-by: Wen Xiong <wenxiong@linux.vnet.ibm.com> Reviewed-by: Daniel Kreling <kreling@linux.vnet.ibm.com> Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/ipr.c160
-rw-r--r--drivers/scsi/ipr.h6
2 files changed, 157 insertions, 9 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;
99static unsigned int ipr_max_devs = IPR_DEFAULT_SIS64_DEVS; 99static unsigned int ipr_max_devs = IPR_DEFAULT_SIS64_DEVS;
100static unsigned int ipr_dual_ioa_raid = 1; 100static unsigned int ipr_dual_ioa_raid = 1;
101static unsigned int ipr_number_of_msix = 2; 101static unsigned int ipr_number_of_msix = 2;
102static unsigned int ipr_fast_reboot;
102static DEFINE_SPINLOCK(ipr_driver_lock); 103static 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) "]");
222module_param_named(number_of_msix, ipr_number_of_msix, int, 0); 223module_param_named(number_of_msix, ipr_number_of_msix, int, 0);
223MODULE_PARM_DESC(number_of_msix, "Specify the number of MSIX interrupts to use on capable adapters (1 - 16). (default:2)"); 224MODULE_PARM_DESC(number_of_msix, "Specify the number of MSIX interrupts to use on capable adapters (1 - 16). (default:2)");
225module_param_named(fast_reboot, ipr_fast_reboot, int, S_IRUGO | S_IWUSR);
226MODULE_PARM_DESC(fast_reboot, "Skip adapter shutdown during reboot. Set to 1 to enable. (default: 0)");
224MODULE_LICENSE("GPL"); 227MODULE_LICENSE("GPL");
225MODULE_VERSION(IPR_DRIVER_VERSION); 228MODULE_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 **/
8492static 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 **/
8513static 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 **/
8552static 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
10058static struct pci_device_id ipr_pci_table[] = { 10201static 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 }
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index ec03b42fa2b9..34eec5bcdce0 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -196,6 +196,8 @@
196/* 196/*
197 * Adapter Commands 197 * Adapter Commands
198 */ 198 */
199#define IPR_CANCEL_REQUEST 0xC0
200#define IPR_CANCEL_64BIT_IOARCB 0x01
199#define IPR_QUERY_RSRC_STATE 0xC2 201#define IPR_QUERY_RSRC_STATE 0xC2
200#define IPR_RESET_DEVICE 0xC3 202#define IPR_RESET_DEVICE 0xC3
201#define IPR_RESET_TYPE_SELECT 0x80 203#define IPR_RESET_TYPE_SELECT 0x80
@@ -222,6 +224,7 @@
222#define IPR_ABBREV_SHUTDOWN_TIMEOUT (10 * HZ) 224#define IPR_ABBREV_SHUTDOWN_TIMEOUT (10 * HZ)
223#define IPR_DUAL_IOA_ABBR_SHUTDOWN_TO (2 * 60 * HZ) 225#define IPR_DUAL_IOA_ABBR_SHUTDOWN_TO (2 * 60 * HZ)
224#define IPR_DEVICE_RESET_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) 226#define IPR_DEVICE_RESET_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
227#define IPR_CANCEL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
225#define IPR_CANCEL_ALL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) 228#define IPR_CANCEL_ALL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
226#define IPR_ABORT_TASK_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) 229#define IPR_ABORT_TASK_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
227#define IPR_INTERNAL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) 230#define IPR_INTERNAL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
@@ -1402,7 +1405,8 @@ enum ipr_shutdown_type {
1402 IPR_SHUTDOWN_NORMAL = 0x00, 1405 IPR_SHUTDOWN_NORMAL = 0x00,
1403 IPR_SHUTDOWN_PREPARE_FOR_NORMAL = 0x40, 1406 IPR_SHUTDOWN_PREPARE_FOR_NORMAL = 0x40,
1404 IPR_SHUTDOWN_ABBREV = 0x80, 1407 IPR_SHUTDOWN_ABBREV = 0x80,
1405 IPR_SHUTDOWN_NONE = 0x100 1408 IPR_SHUTDOWN_NONE = 0x100,
1409 IPR_SHUTDOWN_QUIESCE = 0x101,
1406}; 1410};
1407 1411
1408struct ipr_trace_entry { 1412struct ipr_trace_entry {