diff options
author | Brian King <brking@linux.vnet.ibm.com> | 2007-05-07 18:09:05 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-08 12:54:40 -0400 |
commit | 463fc696ed723a9d854113e370cc177b0b63de42 (patch) | |
tree | 5c0743c280e36f06fe7c2596ebd4b5edbb8dfdd2 /drivers/scsi | |
parent | d24f8e8fef43aa9fc98ea7a5ae6eee0eed4cdc06 (diff) |
[SCSI] ipr: Use PCI-E reset API for new ipr adapter
Use a newly added PCI API to issue a PCI Fundamental reset
(warm reset) to a new ipr PCI-E adapter. Typically, the
ipr adapter uses the start BIST bit in config space to reset
an adapter. Issuing start BIST on this particular adapter
results in the PCI-E logic on the card losing sync, which
causes PCI-E errors, making the card unusable. The only reset
mechanism that exists on this hardware that does not have this
problem is PCI Fundamental reset (warm reset).
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/ipr.c | 70 | ||||
-rw-r--r-- | drivers/scsi/ipr.h | 8 |
2 files changed, 72 insertions, 6 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 101e519844df..4baa79e68679 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -6641,6 +6641,48 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) | |||
6641 | } | 6641 | } |
6642 | 6642 | ||
6643 | /** | 6643 | /** |
6644 | * ipr_reset_slot_reset_done - Clear PCI reset to the adapter | ||
6645 | * @ipr_cmd: ipr command struct | ||
6646 | * | ||
6647 | * Description: This clears PCI reset to the adapter and delays two seconds. | ||
6648 | * | ||
6649 | * Return value: | ||
6650 | * IPR_RC_JOB_RETURN | ||
6651 | **/ | ||
6652 | static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd) | ||
6653 | { | ||
6654 | ENTER; | ||
6655 | pci_set_pcie_reset_state(ipr_cmd->ioa_cfg->pdev, pcie_deassert_reset); | ||
6656 | ipr_cmd->job_step = ipr_reset_bist_done; | ||
6657 | ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); | ||
6658 | LEAVE; | ||
6659 | return IPR_RC_JOB_RETURN; | ||
6660 | } | ||
6661 | |||
6662 | /** | ||
6663 | * ipr_reset_slot_reset - Reset the PCI slot of the adapter. | ||
6664 | * @ipr_cmd: ipr command struct | ||
6665 | * | ||
6666 | * Description: This asserts PCI reset to the adapter. | ||
6667 | * | ||
6668 | * Return value: | ||
6669 | * IPR_RC_JOB_RETURN | ||
6670 | **/ | ||
6671 | static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd) | ||
6672 | { | ||
6673 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
6674 | struct pci_dev *pdev = ioa_cfg->pdev; | ||
6675 | |||
6676 | ENTER; | ||
6677 | pci_block_user_cfg_access(pdev); | ||
6678 | pci_set_pcie_reset_state(pdev, pcie_warm_reset); | ||
6679 | ipr_cmd->job_step = ipr_reset_slot_reset_done; | ||
6680 | ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT); | ||
6681 | LEAVE; | ||
6682 | return IPR_RC_JOB_RETURN; | ||
6683 | } | ||
6684 | |||
6685 | /** | ||
6644 | * ipr_reset_allowed - Query whether or not IOA can be reset | 6686 | * ipr_reset_allowed - Query whether or not IOA can be reset |
6645 | * @ioa_cfg: ioa config struct | 6687 | * @ioa_cfg: ioa config struct |
6646 | * | 6688 | * |
@@ -6679,7 +6721,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd) | |||
6679 | ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT; | 6721 | ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT; |
6680 | ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT); | 6722 | ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT); |
6681 | } else { | 6723 | } else { |
6682 | ipr_cmd->job_step = ipr_reset_start_bist; | 6724 | ipr_cmd->job_step = ioa_cfg->reset; |
6683 | rc = IPR_RC_JOB_CONTINUE; | 6725 | rc = IPR_RC_JOB_CONTINUE; |
6684 | } | 6726 | } |
6685 | 6727 | ||
@@ -6712,7 +6754,7 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd) | |||
6712 | writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg); | 6754 | writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg); |
6713 | ipr_cmd->job_step = ipr_reset_wait_to_start_bist; | 6755 | ipr_cmd->job_step = ipr_reset_wait_to_start_bist; |
6714 | } else { | 6756 | } else { |
6715 | ipr_cmd->job_step = ipr_reset_start_bist; | 6757 | ipr_cmd->job_step = ioa_cfg->reset; |
6716 | } | 6758 | } |
6717 | 6759 | ||
6718 | ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT; | 6760 | ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT; |
@@ -6994,8 +7036,11 @@ static pci_ers_result_t ipr_pci_slot_reset(struct pci_dev *pdev) | |||
6994 | struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); | 7036 | struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); |
6995 | 7037 | ||
6996 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | 7038 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); |
6997 | _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space, | 7039 | if (ioa_cfg->needs_warm_reset) |
6998 | IPR_SHUTDOWN_NONE); | 7040 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); |
7041 | else | ||
7042 | _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space, | ||
7043 | IPR_SHUTDOWN_NONE); | ||
6999 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); | 7044 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); |
7000 | return PCI_ERS_RESULT_RECOVERED; | 7045 | return PCI_ERS_RESULT_RECOVERED; |
7001 | } | 7046 | } |
@@ -7483,6 +7528,14 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, | |||
7483 | else | 7528 | else |
7484 | ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT; | 7529 | ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT; |
7485 | 7530 | ||
7531 | rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &ioa_cfg->revid); | ||
7532 | |||
7533 | if (rc != PCIBIOS_SUCCESSFUL) { | ||
7534 | dev_err(&pdev->dev, "Failed to read PCI revision ID\n"); | ||
7535 | rc = -EIO; | ||
7536 | goto out_scsi_host_put; | ||
7537 | } | ||
7538 | |||
7486 | ipr_regs_pci = pci_resource_start(pdev, 0); | 7539 | ipr_regs_pci = pci_resource_start(pdev, 0); |
7487 | 7540 | ||
7488 | rc = pci_request_regions(pdev, IPR_NAME); | 7541 | rc = pci_request_regions(pdev, IPR_NAME); |
@@ -7569,6 +7622,13 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, | |||
7569 | goto cleanup_nolog; | 7622 | goto cleanup_nolog; |
7570 | } | 7623 | } |
7571 | 7624 | ||
7625 | if ((dev_id->driver_data & IPR_USE_PCI_WARM_RESET) || | ||
7626 | (dev_id->device == PCI_DEVICE_ID_IBM_OBSIDIAN_E && !ioa_cfg->revid)) { | ||
7627 | ioa_cfg->needs_warm_reset = 1; | ||
7628 | ioa_cfg->reset = ipr_reset_slot_reset; | ||
7629 | } else | ||
7630 | ioa_cfg->reset = ipr_reset_start_bist; | ||
7631 | |||
7572 | spin_lock(&ipr_driver_lock); | 7632 | spin_lock(&ipr_driver_lock); |
7573 | list_add_tail(&ioa_cfg->queue, &ipr_ioa_head); | 7633 | list_add_tail(&ioa_cfg->queue, &ipr_ioa_head); |
7574 | spin_unlock(&ipr_driver_lock); | 7634 | spin_unlock(&ipr_driver_lock); |
@@ -7835,7 +7895,7 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { | |||
7835 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 }, | 7895 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 }, |
7836 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, | 7896 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, |
7837 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, | 7897 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, |
7838 | IPR_USE_LONG_TRANSOP_TIMEOUT }, | 7898 | IPR_USE_LONG_TRANSOP_TIMEOUT | IPR_USE_PCI_WARM_RESET }, |
7839 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, | 7899 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, |
7840 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 }, | 7900 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 }, |
7841 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, | 7901 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, |
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index daa96ee19d4f..d93156671e93 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
@@ -37,7 +37,7 @@ | |||
37 | /* | 37 | /* |
38 | * Literals | 38 | * Literals |
39 | */ | 39 | */ |
40 | #define IPR_DRIVER_VERSION "2.4.0" | 40 | #define IPR_DRIVER_VERSION "2.4.1" |
41 | #define IPR_DRIVER_DATE "(April 24, 2007)" | 41 | #define IPR_DRIVER_DATE "(April 24, 2007)" |
42 | 42 | ||
43 | /* | 43 | /* |
@@ -112,6 +112,7 @@ | |||
112 | 112 | ||
113 | /* Driver data flags */ | 113 | /* Driver data flags */ |
114 | #define IPR_USE_LONG_TRANSOP_TIMEOUT 0x00000001 | 114 | #define IPR_USE_LONG_TRANSOP_TIMEOUT 0x00000001 |
115 | #define IPR_USE_PCI_WARM_RESET 0x00000002 | ||
115 | 116 | ||
116 | #define IPR_DEFAULT_MAX_ERROR_DUMP 984 | 117 | #define IPR_DEFAULT_MAX_ERROR_DUMP 984 |
117 | #define IPR_NUM_LOG_HCAMS 2 | 118 | #define IPR_NUM_LOG_HCAMS 2 |
@@ -193,6 +194,7 @@ | |||
193 | #define IPR_WAIT_FOR_RESET_TIMEOUT (2 * HZ) | 194 | #define IPR_WAIT_FOR_RESET_TIMEOUT (2 * HZ) |
194 | #define IPR_CHECK_FOR_RESET_TIMEOUT (HZ / 10) | 195 | #define IPR_CHECK_FOR_RESET_TIMEOUT (HZ / 10) |
195 | #define IPR_WAIT_FOR_BIST_TIMEOUT (2 * HZ) | 196 | #define IPR_WAIT_FOR_BIST_TIMEOUT (2 * HZ) |
197 | #define IPR_PCI_RESET_TIMEOUT (HZ / 2) | ||
196 | #define IPR_DUMP_TIMEOUT (15 * HZ) | 198 | #define IPR_DUMP_TIMEOUT (15 * HZ) |
197 | 199 | ||
198 | /* | 200 | /* |
@@ -1091,6 +1093,9 @@ struct ipr_ioa_cfg { | |||
1091 | u8 allow_ml_add_del:1; | 1093 | u8 allow_ml_add_del:1; |
1092 | u8 needs_hard_reset:1; | 1094 | u8 needs_hard_reset:1; |
1093 | u8 dual_raid:1; | 1095 | u8 dual_raid:1; |
1096 | u8 needs_warm_reset:1; | ||
1097 | |||
1098 | u8 revid; | ||
1094 | 1099 | ||
1095 | enum ipr_cache_state cache_state; | 1100 | enum ipr_cache_state cache_state; |
1096 | u16 type; /* CCIN of the card */ | 1101 | u16 type; /* CCIN of the card */ |
@@ -1184,6 +1189,7 @@ struct ipr_ioa_cfg { | |||
1184 | struct pci_pool *ipr_cmd_pool; | 1189 | struct pci_pool *ipr_cmd_pool; |
1185 | 1190 | ||
1186 | struct ipr_cmnd *reset_cmd; | 1191 | struct ipr_cmnd *reset_cmd; |
1192 | int (*reset) (struct ipr_cmnd *); | ||
1187 | 1193 | ||
1188 | struct ata_host ata_host; | 1194 | struct ata_host ata_host; |
1189 | char ipr_cmd_label[8]; | 1195 | char ipr_cmd_label[8]; |