aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2008-03-09 21:25:25 -0400
committerJeff Garzik <jeff@garzik.org>2008-03-17 08:26:50 -0400
commita22e64443f0aa4aa4e3c56a49e5c060e90752c07 (patch)
treecc9db844ba0099aced1ad1faf3859da84ab75a09 /drivers/ata
parentdea55137634226fd74d5187a15dee1244ec252cb (diff)
ahci: implement skip_host_reset parameter
Under certain circumstances (SSP turned off by the BIOS) and for debugging purposes, skipping global controller reset is helpful. Add a kernel parameter for it. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 53f5afd9420c..bbfccdbba3ab 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -49,6 +49,10 @@
49#define DRV_NAME "ahci" 49#define DRV_NAME "ahci"
50#define DRV_VERSION "3.0" 50#define DRV_VERSION "3.0"
51 51
52static int ahci_skip_host_reset;
53module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
54MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
55
52static int ahci_enable_alpm(struct ata_port *ap, 56static int ahci_enable_alpm(struct ata_port *ap,
53 enum link_pm policy); 57 enum link_pm policy);
54static void ahci_disable_alpm(struct ata_port *ap); 58static void ahci_disable_alpm(struct ata_port *ap);
@@ -1088,29 +1092,35 @@ static int ahci_reset_controller(struct ata_host *host)
1088 ahci_enable_ahci(mmio); 1092 ahci_enable_ahci(mmio);
1089 1093
1090 /* global controller reset */ 1094 /* global controller reset */
1091 tmp = readl(mmio + HOST_CTL); 1095 if (!ahci_skip_host_reset) {
1092 if ((tmp & HOST_RESET) == 0) { 1096 tmp = readl(mmio + HOST_CTL);
1093 writel(tmp | HOST_RESET, mmio + HOST_CTL); 1097 if ((tmp & HOST_RESET) == 0) {
1094 readl(mmio + HOST_CTL); /* flush */ 1098 writel(tmp | HOST_RESET, mmio + HOST_CTL);
1095 } 1099 readl(mmio + HOST_CTL); /* flush */
1100 }
1096 1101
1097 /* reset must complete within 1 second, or 1102 /* reset must complete within 1 second, or
1098 * the hardware should be considered fried. 1103 * the hardware should be considered fried.
1099 */ 1104 */
1100 ssleep(1); 1105 ssleep(1);
1101 1106
1102 tmp = readl(mmio + HOST_CTL); 1107 tmp = readl(mmio + HOST_CTL);
1103 if (tmp & HOST_RESET) { 1108 if (tmp & HOST_RESET) {
1104 dev_printk(KERN_ERR, host->dev, 1109 dev_printk(KERN_ERR, host->dev,
1105 "controller reset failed (0x%x)\n", tmp); 1110 "controller reset failed (0x%x)\n", tmp);
1106 return -EIO; 1111 return -EIO;
1107 } 1112 }
1108 1113
1109 /* turn on AHCI mode */ 1114 /* turn on AHCI mode */
1110 ahci_enable_ahci(mmio); 1115 ahci_enable_ahci(mmio);
1111 1116
1112 /* some registers might be cleared on reset. restore initial values */ 1117 /* Some registers might be cleared on reset. Restore
1113 ahci_restore_initial_config(host); 1118 * initial values.
1119 */
1120 ahci_restore_initial_config(host);
1121 } else
1122 dev_printk(KERN_INFO, host->dev,
1123 "skipping global host reset\n");
1114 1124
1115 if (pdev->vendor == PCI_VENDOR_ID_INTEL) { 1125 if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
1116 u16 tmp16; 1126 u16 tmp16;