blob: a47d309df2f20bbac7da5f493b2c41422ce1f534 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ahci.c - AHCI SATA support
3 *
Jeff Garzikaf36d7f2005-08-28 20:18:39 -04004 * Maintained by: Jeff Garzik <jgarzik@pobox.com>
5 * Please ALWAYS copy linux-ide@vger.kernel.org
6 * on emails.
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
Jeff Garzikaf36d7f2005-08-28 20:18:39 -04008 * Copyright 2004-2005 Red Hat, Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
Jeff Garzikaf36d7f2005-08-28 20:18:39 -040011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; see the file COPYING. If not, write to
23 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 *
26 * libata documentation is available via 'make {ps|pdf}docs',
27 * as Documentation/DocBook/libata.*
28 *
29 * AHCI hardware documentation:
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
Jeff Garzikaf36d7f2005-08-28 20:18:39 -040031 * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
Linus Torvalds1da177e2005-04-16 15:20:36 -070032 *
33 */
34
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/pci.h>
38#include <linux/init.h>
39#include <linux/blkdev.h>
40#include <linux/delay.h>
41#include <linux/interrupt.h>
domen@coderock.org87507cf2005-04-08 09:53:06 +020042#include <linux/dma-mapping.h>
Jeff Garzika9524a72005-10-30 14:39:11 -050043#include <linux/device.h>
Tejun Heoedc93052007-10-25 14:59:16 +090044#include <linux/dmi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <scsi/scsi_host.h>
Jeff Garzik193515d2005-11-07 00:59:37 -050046#include <scsi/scsi_cmnd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/libata.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49#define DRV_NAME "ahci"
Tejun Heo7d50b602007-09-23 13:19:54 +090050#define DRV_VERSION "3.0"
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
David Milburn87943ac2008-10-13 14:38:36 -050052/* Enclosure Management Control */
53#define EM_CTRL_MSG_TYPE 0x000f0000
54
55/* Enclosure Management LED Message Type */
56#define EM_MSG_LED_HBA_PORT 0x0000000f
57#define EM_MSG_LED_PMP_SLOT 0x0000ff00
58#define EM_MSG_LED_VALUE 0xffff0000
59#define EM_MSG_LED_VALUE_ACTIVITY 0x00070000
60#define EM_MSG_LED_VALUE_OFF 0xfff80000
61#define EM_MSG_LED_VALUE_ON 0x00010000
62
Tejun Heoa22e6442008-03-10 10:25:25 +090063static int ahci_skip_host_reset;
Arjan van de Venf3d7f232009-01-26 02:05:44 -080064static int ahci_ignore_sss;
65
Tejun Heoa22e6442008-03-10 10:25:25 +090066module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
67MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
68
Arjan van de Venf3d7f232009-01-26 02:05:44 -080069module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
70MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
71
Kristen Carlson Accardi31556592007-10-25 01:33:26 -040072static int ahci_enable_alpm(struct ata_port *ap,
73 enum link_pm policy);
74static void ahci_disable_alpm(struct ata_port *ap);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -070075static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
76static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
77 size_t size);
78static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
79 ssize_t size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
81enum {
82 AHCI_PCI_BAR = 5,
Tejun Heo648a88b2006-11-09 15:08:40 +090083 AHCI_MAX_PORTS = 32,
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 AHCI_MAX_SG = 168, /* hardware max is 64K */
85 AHCI_DMA_BOUNDARY = 0xffffffff,
Tejun Heo12fad3f2006-05-15 21:03:55 +090086 AHCI_MAX_CMDS = 32,
Tejun Heodd410ff2006-05-15 21:03:50 +090087 AHCI_CMD_SZ = 32,
Tejun Heo12fad3f2006-05-15 21:03:55 +090088 AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ,
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 AHCI_RX_FIS_SZ = 256,
Jeff Garzika0ea7322005-06-04 01:13:15 -040090 AHCI_CMD_TBL_CDB = 0x40,
Tejun Heodd410ff2006-05-15 21:03:50 +090091 AHCI_CMD_TBL_HDR_SZ = 0x80,
92 AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16),
93 AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
94 AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 AHCI_RX_FIS_SZ,
96 AHCI_IRQ_ON_SG = (1 << 31),
97 AHCI_CMD_ATAPI = (1 << 5),
98 AHCI_CMD_WRITE = (1 << 6),
Tejun Heo4b10e552006-03-12 11:25:27 +090099 AHCI_CMD_PREFETCH = (1 << 7),
Tejun Heo22b49982006-01-23 21:38:44 +0900100 AHCI_CMD_RESET = (1 << 8),
101 AHCI_CMD_CLR_BUSY = (1 << 10),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103 RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
Tejun Heo0291f952007-01-25 19:16:28 +0900104 RX_FIS_SDB = 0x58, /* offset of SDB FIS data */
Tejun Heo78cd52d2006-05-15 20:58:29 +0900105 RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
107 board_ahci = 0,
Tejun Heo7a234af2007-09-03 12:44:57 +0900108 board_ahci_vt8251 = 1,
109 board_ahci_ign_iferr = 2,
110 board_ahci_sb600 = 3,
111 board_ahci_mv = 4,
Shane Huange427fe02008-12-30 10:53:41 +0800112 board_ahci_sb700 = 5, /* for SB700 and SB800 */
Tejun Heoe297d992008-06-10 00:13:04 +0900113 board_ahci_mcp65 = 6,
Tejun Heo9a3b1032008-06-18 20:56:58 -0400114 board_ahci_nopmp = 7,
Tejun Heoaa431dd2009-04-08 14:25:31 -0700115 board_ahci_yesncq = 8,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
117 /* global controller registers */
118 HOST_CAP = 0x00, /* host capabilities */
119 HOST_CTL = 0x04, /* global host control */
120 HOST_IRQ_STAT = 0x08, /* interrupt status */
121 HOST_PORTS_IMPL = 0x0c, /* bitmap of implemented ports */
122 HOST_VERSION = 0x10, /* AHCI spec. version compliancy */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700123 HOST_EM_LOC = 0x1c, /* Enclosure Management location */
124 HOST_EM_CTL = 0x20, /* Enclosure Management Control */
Robert Hancock4c521c82009-09-20 17:02:31 -0600125 HOST_CAP2 = 0x24, /* host capabilities, extended */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127 /* HOST_CTL bits */
128 HOST_RESET = (1 << 0), /* reset controller; self-clear */
129 HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
130 HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
131
132 /* HOST_CAP bits */
Robert Hancock4c521c82009-09-20 17:02:31 -0600133 HOST_CAP_SXS = (1 << 5), /* Supports External SATA */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700134 HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */
Robert Hancock4c521c82009-09-20 17:02:31 -0600135 HOST_CAP_CCC = (1 << 7), /* Command Completion Coalescing */
136 HOST_CAP_PART = (1 << 13), /* Partial state capable */
137 HOST_CAP_SSC = (1 << 14), /* Slumber state capable */
138 HOST_CAP_PIO_MULTI = (1 << 15), /* PIO multiple DRQ support */
139 HOST_CAP_FBS = (1 << 16), /* FIS-based switching support */
Tejun Heo7d50b602007-09-23 13:19:54 +0900140 HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
Robert Hancock4c521c82009-09-20 17:02:31 -0600141 HOST_CAP_ONLY = (1 << 18), /* Supports AHCI mode only */
Tejun Heo22b49982006-01-23 21:38:44 +0900142 HOST_CAP_CLO = (1 << 24), /* Command List Override support */
Robert Hancock4c521c82009-09-20 17:02:31 -0600143 HOST_CAP_LED = (1 << 25), /* Supports activity LED */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400144 HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
Tejun Heo0be0aa92006-07-26 15:59:26 +0900145 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
Robert Hancock4c521c82009-09-20 17:02:31 -0600146 HOST_CAP_MPS = (1 << 28), /* Mechanical presence switch */
Tejun Heo203ef6c2007-07-16 14:29:40 +0900147 HOST_CAP_SNTF = (1 << 29), /* SNotification register */
Tejun Heo979db802006-05-15 21:03:52 +0900148 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
Tejun Heodd410ff2006-05-15 21:03:50 +0900149 HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Robert Hancock4c521c82009-09-20 17:02:31 -0600151 /* HOST_CAP2 bits */
152 HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */
153 HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */
154 HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */
155
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 /* registers for each SATA port */
157 PORT_LST_ADDR = 0x00, /* command list DMA addr */
158 PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */
159 PORT_FIS_ADDR = 0x08, /* FIS rx buf addr */
160 PORT_FIS_ADDR_HI = 0x0c, /* FIS rx buf addr hi */
161 PORT_IRQ_STAT = 0x10, /* interrupt status */
162 PORT_IRQ_MASK = 0x14, /* interrupt enable/disable mask */
163 PORT_CMD = 0x18, /* port command */
164 PORT_TFDATA = 0x20, /* taskfile data */
165 PORT_SIG = 0x24, /* device TF signature */
166 PORT_CMD_ISSUE = 0x38, /* command issue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */
168 PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */
169 PORT_SCR_ERR = 0x30, /* SATA phy register: SError */
170 PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */
Tejun Heo203ef6c2007-07-16 14:29:40 +0900171 PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
173 /* PORT_IRQ_{STAT,MASK} bits */
174 PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
175 PORT_IRQ_TF_ERR = (1 << 30), /* task file error */
176 PORT_IRQ_HBUS_ERR = (1 << 29), /* host bus fatal error */
177 PORT_IRQ_HBUS_DATA_ERR = (1 << 28), /* host bus data error */
178 PORT_IRQ_IF_ERR = (1 << 27), /* interface fatal error */
179 PORT_IRQ_IF_NONFATAL = (1 << 26), /* interface non-fatal error */
180 PORT_IRQ_OVERFLOW = (1 << 24), /* xfer exhausted available S/G */
181 PORT_IRQ_BAD_PMP = (1 << 23), /* incorrect port multiplier */
182
183 PORT_IRQ_PHYRDY = (1 << 22), /* PhyRdy changed */
184 PORT_IRQ_DEV_ILCK = (1 << 7), /* device interlock */
185 PORT_IRQ_CONNECT = (1 << 6), /* port connect change status */
186 PORT_IRQ_SG_DONE = (1 << 5), /* descriptor processed */
187 PORT_IRQ_UNK_FIS = (1 << 4), /* unknown FIS rx'd */
188 PORT_IRQ_SDB_FIS = (1 << 3), /* Set Device Bits FIS rx'd */
189 PORT_IRQ_DMAS_FIS = (1 << 2), /* DMA Setup FIS rx'd */
190 PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */
191 PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */
192
Tejun Heo78cd52d2006-05-15 20:58:29 +0900193 PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR |
194 PORT_IRQ_IF_ERR |
195 PORT_IRQ_CONNECT |
Tejun Heo42969712006-05-31 18:28:18 +0900196 PORT_IRQ_PHYRDY |
Tejun Heo7d50b602007-09-23 13:19:54 +0900197 PORT_IRQ_UNK_FIS |
198 PORT_IRQ_BAD_PMP,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900199 PORT_IRQ_ERROR = PORT_IRQ_FREEZE |
200 PORT_IRQ_TF_ERR |
201 PORT_IRQ_HBUS_DATA_ERR,
202 DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
203 PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
204 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
206 /* PORT_CMD bits */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400207 PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
208 PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
Jeff Garzik02eaa662005-11-12 01:32:19 -0500209 PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
Tejun Heo7d50b602007-09-23 13:19:54 +0900210 PORT_CMD_PMP = (1 << 17), /* PMP attached */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
212 PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
213 PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
Tejun Heo22b49982006-01-23 21:38:44 +0900214 PORT_CMD_CLO = (1 << 3), /* Command list override */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 PORT_CMD_POWER_ON = (1 << 2), /* Power up device */
216 PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
217 PORT_CMD_START = (1 << 0), /* Enable port DMA engine */
218
Tejun Heo0be0aa92006-07-26 15:59:26 +0900219 PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */
221 PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
222 PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
Jeff Garzik4b0060f2005-06-04 00:50:22 -0400223
Tejun Heo417a1a62007-09-23 13:19:55 +0900224 /* hpriv->flags bits */
225 AHCI_HFLAG_NO_NCQ = (1 << 0),
226 AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */
227 AHCI_HFLAG_IGN_SERR_INTERNAL = (1 << 2), /* ignore SERR_INTERNAL */
228 AHCI_HFLAG_32BIT_ONLY = (1 << 3), /* force 32bit */
229 AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
230 AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
Tejun Heo6949b912007-09-23 13:19:55 +0900231 AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400232 AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
Jeff Garzika8785392008-02-28 15:43:48 -0500233 AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
Tejun Heoe297d992008-06-10 00:13:04 +0900234 AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
Tejun Heo9b10ae82009-05-30 20:50:12 +0900235 AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */
Tejun Heo55946392009-08-04 14:30:08 +0900236 AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as
237 link offline */
Tejun Heo417a1a62007-09-23 13:19:55 +0900238
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200239 /* ap->flags bits */
Tejun Heo1188c0d2007-04-23 02:41:05 +0900240
241 AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
242 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400243 ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
244 ATA_FLAG_IPM,
Tejun Heoc4f77922007-12-06 15:09:43 +0900245
246 ICH_MAP = 0x90, /* ICH MAP register */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700247
Tejun Heod50ce072009-05-12 10:57:41 +0900248 /* em constants */
249 EM_MAX_SLOTS = 8,
250 EM_MAX_RETRY = 5,
251
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700252 /* em_ctl bits */
253 EM_CTL_RST = (1 << 9), /* Reset */
254 EM_CTL_TM = (1 << 8), /* Transmit Message */
255 EM_CTL_ALHD = (1 << 26), /* Activity LED */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256};
257
258struct ahci_cmd_hdr {
Al Viro4ca4e432007-12-30 09:32:22 +0000259 __le32 opts;
260 __le32 status;
261 __le32 tbl_addr;
262 __le32 tbl_addr_hi;
263 __le32 reserved[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264};
265
266struct ahci_sg {
Al Viro4ca4e432007-12-30 09:32:22 +0000267 __le32 addr;
268 __le32 addr_hi;
269 __le32 reserved;
270 __le32 flags_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271};
272
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700273struct ahci_em_priv {
274 enum sw_activity blink_policy;
275 struct timer_list timer;
276 unsigned long saved_activity;
277 unsigned long activity;
278 unsigned long led_state;
279};
280
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281struct ahci_host_priv {
Tejun Heo417a1a62007-09-23 13:19:55 +0900282 unsigned int flags; /* AHCI_HFLAG_* */
Tejun Heod447df12007-03-18 22:15:33 +0900283 u32 cap; /* cap to use */
Robert Hancock4c521c82009-09-20 17:02:31 -0600284 u32 cap2; /* cap2 to use */
Tejun Heod447df12007-03-18 22:15:33 +0900285 u32 port_map; /* port map to use */
286 u32 saved_cap; /* saved initial cap */
Robert Hancock4c521c82009-09-20 17:02:31 -0600287 u32 saved_cap2; /* saved initial cap2 */
Tejun Heod447df12007-03-18 22:15:33 +0900288 u32 saved_port_map; /* saved initial port_map */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700289 u32 em_loc; /* enclosure management location */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290};
291
292struct ahci_port_priv {
Tejun Heo7d50b602007-09-23 13:19:54 +0900293 struct ata_link *active_link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 struct ahci_cmd_hdr *cmd_slot;
295 dma_addr_t cmd_slot_dma;
296 void *cmd_tbl;
297 dma_addr_t cmd_tbl_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 void *rx_fis;
299 dma_addr_t rx_fis_dma;
Tejun Heo0291f952007-01-25 19:16:28 +0900300 /* for NCQ spurious interrupt analysis */
Tejun Heo0291f952007-01-25 19:16:28 +0900301 unsigned int ncq_saw_d2h:1;
302 unsigned int ncq_saw_dmas:1;
Tejun Heoafb2d552007-02-27 13:24:19 +0900303 unsigned int ncq_saw_sdb:1;
Kristen Carlson Accardia7384922007-08-09 14:23:41 -0700304 u32 intr_mask; /* interrupts to enable */
Tejun Heod50ce072009-05-12 10:57:41 +0900305 /* enclosure management info per PM slot */
306 struct ahci_em_priv em_priv[EM_MAX_SLOTS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307};
308
Tejun Heo82ef04f2008-07-31 17:02:40 +0900309static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
310static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400311static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
Tejun Heo9a3d9eb2006-01-23 13:09:36 +0900312static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
Tejun Heo4c9bf4e2008-04-07 22:47:20 +0900313static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314static int ahci_port_start(struct ata_port *ap);
315static void ahci_port_stop(struct ata_port *ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316static void ahci_qc_prep(struct ata_queued_cmd *qc);
Tejun Heo78cd52d2006-05-15 20:58:29 +0900317static void ahci_freeze(struct ata_port *ap);
318static void ahci_thaw(struct ata_port *ap);
Tejun Heo7d50b602007-09-23 13:19:54 +0900319static void ahci_pmp_attach(struct ata_port *ap);
320static void ahci_pmp_detach(struct ata_port *ap);
Tejun Heoa1efdab2008-03-25 12:22:50 +0900321static int ahci_softreset(struct ata_link *link, unsigned int *class,
322 unsigned long deadline);
Shane Huangbd172432008-06-10 15:52:04 +0800323static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
324 unsigned long deadline);
Tejun Heoa1efdab2008-03-25 12:22:50 +0900325static int ahci_hardreset(struct ata_link *link, unsigned int *class,
326 unsigned long deadline);
327static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
328 unsigned long deadline);
329static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
330 unsigned long deadline);
331static void ahci_postreset(struct ata_link *link, unsigned int *class);
Tejun Heo78cd52d2006-05-15 20:58:29 +0900332static void ahci_error_handler(struct ata_port *ap);
333static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
Jeff Garzikdf69c9c2007-05-26 20:46:51 -0400334static int ahci_port_resume(struct ata_port *ap);
Jeff Garzika8785392008-02-28 15:43:48 -0500335static void ahci_dev_config(struct ata_device *dev);
Jeff Garzikdab632e2007-05-28 08:33:01 -0400336static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
337 u32 opts);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900338#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900339static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
Tejun Heoc1332872006-07-26 15:59:26 +0900340static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
341static int ahci_pci_device_resume(struct pci_dev *pdev);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900342#endif
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700343static ssize_t ahci_activity_show(struct ata_device *dev, char *buf);
344static ssize_t ahci_activity_store(struct ata_device *dev,
345 enum sw_activity val);
346static void ahci_init_sw_activity(struct ata_link *link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
Matthew Garrett77cdec12009-07-17 19:13:47 +0100348static ssize_t ahci_show_host_caps(struct device *dev,
349 struct device_attribute *attr, char *buf);
Robert Hancock4c521c82009-09-20 17:02:31 -0600350static ssize_t ahci_show_host_cap2(struct device *dev,
351 struct device_attribute *attr, char *buf);
Matthew Garrett77cdec12009-07-17 19:13:47 +0100352static ssize_t ahci_show_host_version(struct device *dev,
353 struct device_attribute *attr, char *buf);
354static ssize_t ahci_show_port_cmd(struct device *dev,
355 struct device_attribute *attr, char *buf);
356
357DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
Robert Hancock4c521c82009-09-20 17:02:31 -0600358DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
Matthew Garrett77cdec12009-07-17 19:13:47 +0100359DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
360DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
361
Tony Jonesee959b02008-02-22 00:13:36 +0100362static struct device_attribute *ahci_shost_attrs[] = {
363 &dev_attr_link_power_management_policy,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700364 &dev_attr_em_message_type,
365 &dev_attr_em_message,
Matthew Garrett77cdec12009-07-17 19:13:47 +0100366 &dev_attr_ahci_host_caps,
Robert Hancock4c521c82009-09-20 17:02:31 -0600367 &dev_attr_ahci_host_cap2,
Matthew Garrett77cdec12009-07-17 19:13:47 +0100368 &dev_attr_ahci_host_version,
369 &dev_attr_ahci_port_cmd,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700370 NULL
371};
372
373static struct device_attribute *ahci_sdev_attrs[] = {
374 &dev_attr_sw_activity,
Elias Oltmanns45fabbb2008-09-21 11:54:08 +0200375 &dev_attr_unload_heads,
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400376 NULL
377};
378
Jeff Garzik193515d2005-11-07 00:59:37 -0500379static struct scsi_host_template ahci_sht = {
Tejun Heo68d1d072008-03-25 12:22:49 +0900380 ATA_NCQ_SHT(DRV_NAME),
Tejun Heo12fad3f2006-05-15 21:03:55 +0900381 .can_queue = AHCI_MAX_CMDS - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 .sg_tablesize = AHCI_MAX_SG,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 .dma_boundary = AHCI_DMA_BOUNDARY,
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400384 .shost_attrs = ahci_shost_attrs,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700385 .sdev_attrs = ahci_sdev_attrs,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386};
387
Tejun Heo029cfd62008-03-25 12:22:49 +0900388static struct ata_port_operations ahci_ops = {
389 .inherits = &sata_pmp_port_ops,
390
Tejun Heo7d50b602007-09-23 13:19:54 +0900391 .qc_defer = sata_pmp_qc_defer_cmd_switch,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 .qc_prep = ahci_qc_prep,
393 .qc_issue = ahci_qc_issue,
Tejun Heo4c9bf4e2008-04-07 22:47:20 +0900394 .qc_fill_rtf = ahci_qc_fill_rtf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Tejun Heo78cd52d2006-05-15 20:58:29 +0900396 .freeze = ahci_freeze,
397 .thaw = ahci_thaw,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900398 .softreset = ahci_softreset,
399 .hardreset = ahci_hardreset,
400 .postreset = ahci_postreset,
Tejun Heo071f44b2008-04-07 22:47:22 +0900401 .pmp_softreset = ahci_softreset,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900402 .error_handler = ahci_error_handler,
403 .post_internal_cmd = ahci_post_internal_cmd,
Tejun Heo029cfd62008-03-25 12:22:49 +0900404 .dev_config = ahci_dev_config,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900405
Tejun Heo029cfd62008-03-25 12:22:49 +0900406 .scr_read = ahci_scr_read,
407 .scr_write = ahci_scr_write,
Tejun Heo7d50b602007-09-23 13:19:54 +0900408 .pmp_attach = ahci_pmp_attach,
409 .pmp_detach = ahci_pmp_detach,
Tejun Heo7d50b602007-09-23 13:19:54 +0900410
Tejun Heo029cfd62008-03-25 12:22:49 +0900411 .enable_pm = ahci_enable_alpm,
412 .disable_pm = ahci_disable_alpm,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700413 .em_show = ahci_led_show,
414 .em_store = ahci_led_store,
415 .sw_activity_show = ahci_activity_show,
416 .sw_activity_store = ahci_activity_store,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900417#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900418 .port_suspend = ahci_port_suspend,
419 .port_resume = ahci_port_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900420#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 .port_start = ahci_port_start,
422 .port_stop = ahci_port_stop,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423};
424
Tejun Heo029cfd62008-03-25 12:22:49 +0900425static struct ata_port_operations ahci_vt8251_ops = {
426 .inherits = &ahci_ops,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900427 .hardreset = ahci_vt8251_hardreset,
Tejun Heoad616ff2006-11-01 18:00:24 +0900428};
429
Tejun Heo029cfd62008-03-25 12:22:49 +0900430static struct ata_port_operations ahci_p5wdh_ops = {
431 .inherits = &ahci_ops,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900432 .hardreset = ahci_p5wdh_hardreset,
Tejun Heoedc93052007-10-25 14:59:16 +0900433};
434
Shane Huangbd172432008-06-10 15:52:04 +0800435static struct ata_port_operations ahci_sb600_ops = {
436 .inherits = &ahci_ops,
437 .softreset = ahci_sb600_softreset,
438 .pmp_softreset = ahci_sb600_softreset,
439};
440
Tejun Heo417a1a62007-09-23 13:19:55 +0900441#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
442
Arjan van de Ven98ac62d2005-11-28 10:06:23 +0100443static const struct ata_port_info ahci_port_info[] = {
Jeff Garzik4da646b2009-04-08 02:00:13 -0400444 [board_ahci] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 {
Tejun Heo1188c0d2007-04-23 02:41:05 +0900446 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100447 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400448 .udma_mask = ATA_UDMA6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 .port_ops = &ahci_ops,
450 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400451 [board_ahci_vt8251] =
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200452 {
Tejun Heo6949b912007-09-23 13:19:55 +0900453 AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
Tejun Heo417a1a62007-09-23 13:19:55 +0900454 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100455 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400456 .udma_mask = ATA_UDMA6,
Tejun Heoad616ff2006-11-01 18:00:24 +0900457 .port_ops = &ahci_vt8251_ops,
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200458 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400459 [board_ahci_ign_iferr] =
Tejun Heo41669552006-11-29 11:33:14 +0900460 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900461 AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
462 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100463 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400464 .udma_mask = ATA_UDMA6,
Tejun Heo41669552006-11-29 11:33:14 +0900465 .port_ops = &ahci_ops,
466 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400467 [board_ahci_sb600] =
Conke Hu55a61602007-03-27 18:33:05 +0800468 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900469 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
Tejun Heo2fcad9d2009-10-03 18:27:29 +0900470 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
471 AHCI_HFLAG_32BIT_ONLY),
Tejun Heo417a1a62007-09-23 13:19:55 +0900472 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100473 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400474 .udma_mask = ATA_UDMA6,
Shane Huangbd172432008-06-10 15:52:04 +0800475 .port_ops = &ahci_sb600_ops,
Conke Hu55a61602007-03-27 18:33:05 +0800476 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400477 [board_ahci_mv] =
Jeff Garzikcd70c262007-07-08 02:29:42 -0400478 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900479 AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
Tejun Heo17248462008-08-29 16:03:59 +0200480 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
Jeff Garzikcd70c262007-07-08 02:29:42 -0400481 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
Tejun Heo417a1a62007-09-23 13:19:55 +0900482 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100483 .pio_mask = ATA_PIO4,
Jeff Garzikcd70c262007-07-08 02:29:42 -0400484 .udma_mask = ATA_UDMA6,
485 .port_ops = &ahci_ops,
486 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400487 [board_ahci_sb700] = /* for SB700 and SB800 */
Shane Huange39fc8c2008-02-22 05:00:31 -0800488 {
Shane Huangbd172432008-06-10 15:52:04 +0800489 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
Shane Huange39fc8c2008-02-22 05:00:31 -0800490 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100491 .pio_mask = ATA_PIO4,
Shane Huange39fc8c2008-02-22 05:00:31 -0800492 .udma_mask = ATA_UDMA6,
Shane Huangbd172432008-06-10 15:52:04 +0800493 .port_ops = &ahci_sb600_ops,
Shane Huange39fc8c2008-02-22 05:00:31 -0800494 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400495 [board_ahci_mcp65] =
Tejun Heoe297d992008-06-10 00:13:04 +0900496 {
497 AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
498 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100499 .pio_mask = ATA_PIO4,
Tejun Heoe297d992008-06-10 00:13:04 +0900500 .udma_mask = ATA_UDMA6,
501 .port_ops = &ahci_ops,
502 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400503 [board_ahci_nopmp] =
Tejun Heo9a3b1032008-06-18 20:56:58 -0400504 {
505 AHCI_HFLAGS (AHCI_HFLAG_NO_PMP),
506 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100507 .pio_mask = ATA_PIO4,
Tejun Heo9a3b1032008-06-18 20:56:58 -0400508 .udma_mask = ATA_UDMA6,
509 .port_ops = &ahci_ops,
510 },
Tejun Heoaa431dd2009-04-08 14:25:31 -0700511 /* board_ahci_yesncq */
512 {
513 AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
514 .flags = AHCI_FLAG_COMMON,
515 .pio_mask = ATA_PIO4,
516 .udma_mask = ATA_UDMA6,
517 .port_ops = &ahci_ops,
518 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519};
520
Jeff Garzik3b7d6972005-11-10 11:04:11 -0500521static const struct pci_device_id ahci_pci_tbl[] = {
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400522 /* Intel */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400523 { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
524 { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
525 { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
526 { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
527 { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
Tejun Heo82490c02007-01-23 15:13:39 +0900528 { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400529 { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
530 { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
531 { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
532 { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
Tejun Heo7a234af2007-09-03 12:44:57 +0900533 { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
534 { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
535 { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
536 { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
537 { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
538 { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
539 { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
540 { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
541 { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
542 { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
543 { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
544 { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
545 { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
546 { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
547 { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
548 { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
549 { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
Jason Gastond4155e62007-09-20 17:35:00 -0400550 { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
551 { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
Jason Gaston16ad1ad2008-01-28 17:34:14 -0800552 { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
Mark Goodwinb2dde6a2009-06-26 10:44:11 -0500553 { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
Jason Gaston16ad1ad2008-01-28 17:34:14 -0800554 { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
David Milburnc1f57d92009-07-22 15:15:56 -0500555 { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
556 { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
Seth Heasleyadcb5302008-08-11 17:03:09 -0700557 { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
Seth Heasley8e48b6b2008-08-27 16:47:22 -0700558 { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
David Milburnc1f57d92009-07-22 15:15:56 -0500559 { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
Seth Heasleyadcb5302008-08-11 17:03:09 -0700560 { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
Seth Heasley8e48b6b2008-08-27 16:47:22 -0700561 { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
David Milburnc1f57d92009-07-22 15:15:56 -0500562 { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400563
Tejun Heoe34bb372007-02-26 20:24:03 +0900564 /* JMicron 360/1/3/5/6, match class to avoid IDE function */
565 { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
566 PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400567
568 /* ATI */
Conke Huc65ec1c2007-04-11 18:23:14 +0800569 { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
Shane Huange39fc8c2008-02-22 05:00:31 -0800570 { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
571 { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
572 { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
573 { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
574 { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
575 { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400576
Shane Huange2dd90b2009-07-29 11:34:49 +0800577 /* AMD */
578 { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD SB900 */
579 /* AMD is using RAID class only for ahci controllers */
580 { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
581 PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
582
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400583 /* VIA */
Jeff Garzik54bb3a942006-09-27 22:20:11 -0400584 { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
Tejun Heobf335542007-04-11 17:27:14 +0900585 { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400586
587 /* NVIDIA */
Tejun Heoe297d992008-06-10 00:13:04 +0900588 { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */
589 { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */
590 { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */
591 { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */
592 { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */
593 { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */
594 { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */
595 { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */
Tejun Heoaa431dd2009-04-08 14:25:31 -0700596 { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_yesncq }, /* MCP67 */
597 { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_yesncq }, /* MCP67 */
598 { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_yesncq }, /* MCP67 */
599 { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_yesncq }, /* MCP67 */
600 { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_yesncq }, /* MCP67 */
601 { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_yesncq }, /* MCP67 */
602 { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_yesncq }, /* MCP67 */
603 { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_yesncq }, /* MCP67 */
604 { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_yesncq }, /* MCP67 */
605 { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_yesncq }, /* MCP67 */
606 { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq }, /* MCP67 */
607 { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq }, /* MCP67 */
608 { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq }, /* MCP73 */
609 { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq }, /* MCP73 */
610 { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq }, /* MCP73 */
611 { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_yesncq }, /* MCP73 */
612 { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_yesncq }, /* MCP73 */
613 { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_yesncq }, /* MCP73 */
614 { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_yesncq }, /* MCP73 */
615 { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_yesncq }, /* MCP73 */
616 { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_yesncq }, /* MCP73 */
617 { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_yesncq }, /* MCP73 */
618 { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_yesncq }, /* MCP73 */
619 { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_yesncq }, /* MCP73 */
Peer Chen0522b282007-06-07 18:05:12 +0800620 { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */
621 { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */
622 { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */
623 { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci }, /* MCP77 */
624 { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci }, /* MCP77 */
625 { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci }, /* MCP77 */
626 { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci }, /* MCP77 */
627 { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci }, /* MCP77 */
628 { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci }, /* MCP77 */
629 { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
630 { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
631 { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
peerchen6ba86952007-12-03 22:20:37 +0800632 { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci }, /* MCP79 */
633 { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci }, /* MCP79 */
634 { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci }, /* MCP79 */
635 { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci }, /* MCP79 */
Peer Chen71008192007-09-24 10:16:25 +0800636 { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci }, /* MCP79 */
637 { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci }, /* MCP79 */
638 { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci }, /* MCP79 */
639 { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci }, /* MCP79 */
640 { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci }, /* MCP79 */
641 { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */
642 { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */
643 { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */
peerchen7adbe462009-02-27 16:58:41 +0800644 { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci }, /* MCP89 */
645 { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci }, /* MCP89 */
646 { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci }, /* MCP89 */
647 { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci }, /* MCP89 */
648 { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci }, /* MCP89 */
649 { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci }, /* MCP89 */
650 { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci }, /* MCP89 */
651 { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci }, /* MCP89 */
652 { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci }, /* MCP89 */
653 { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci }, /* MCP89 */
654 { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci }, /* MCP89 */
655 { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci }, /* MCP89 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400656
Jeff Garzik95916ed2006-07-29 04:10:14 -0400657 /* SiS */
Tejun Heo20e2de42008-08-01 12:51:43 +0900658 { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
659 { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */
660 { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
Jeff Garzik95916ed2006-07-29 04:10:14 -0400661
Jeff Garzikcd70c262007-07-08 02:29:42 -0400662 /* Marvell */
663 { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100664 { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */
Jeff Garzikcd70c262007-07-08 02:29:42 -0400665
Mark Nelsonc77a0362008-10-23 14:08:16 +1100666 /* Promise */
667 { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */
668
Jeff Garzik415ae2b2006-11-01 05:10:42 -0500669 /* Generic, PCI class code for AHCI */
670 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
Conke Huc9f89472007-01-09 05:32:51 -0500671 PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
Jeff Garzik415ae2b2006-11-01 05:10:42 -0500672
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 { } /* terminate list */
674};
675
676
677static struct pci_driver ahci_pci_driver = {
678 .name = DRV_NAME,
679 .id_table = ahci_pci_tbl,
680 .probe = ahci_init_one,
Tejun Heo24dc5f32007-01-20 16:00:28 +0900681 .remove = ata_pci_remove_one,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900682#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900683 .suspend = ahci_pci_device_suspend,
684 .resume = ahci_pci_device_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900685#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686};
687
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700688static int ahci_em_messages = 1;
689module_param(ahci_em_messages, int, 0444);
690/* add other LED protocol types when they become supported */
691MODULE_PARM_DESC(ahci_em_messages,
692 "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Alan Cox5b66c822008-09-03 14:48:34 +0100694#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
695static int marvell_enable;
696#else
697static int marvell_enable = 1;
698#endif
699module_param(marvell_enable, int, 0644);
700MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
701
702
Tejun Heo98fa4b62006-11-02 12:17:23 +0900703static inline int ahci_nr_ports(u32 cap)
704{
705 return (cap & 0x1f) + 1;
706}
707
Jeff Garzikdab632e2007-05-28 08:33:01 -0400708static inline void __iomem *__ahci_port_base(struct ata_host *host,
709 unsigned int port_no)
710{
711 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
712
713 return mmio + 0x100 + (port_no * 0x80);
714}
715
Tejun Heo4447d352007-04-17 23:44:08 +0900716static inline void __iomem *ahci_port_base(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717{
Jeff Garzikdab632e2007-05-28 08:33:01 -0400718 return __ahci_port_base(ap->host, ap->port_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719}
720
Tejun Heob710a1f2008-01-05 23:11:57 +0900721static void ahci_enable_ahci(void __iomem *mmio)
722{
Tejun Heo15fe9822008-04-23 20:52:58 +0900723 int i;
Tejun Heob710a1f2008-01-05 23:11:57 +0900724 u32 tmp;
725
726 /* turn on AHCI_EN */
727 tmp = readl(mmio + HOST_CTL);
Tejun Heo15fe9822008-04-23 20:52:58 +0900728 if (tmp & HOST_AHCI_EN)
729 return;
730
731 /* Some controllers need AHCI_EN to be written multiple times.
732 * Try a few times before giving up.
733 */
734 for (i = 0; i < 5; i++) {
Tejun Heob710a1f2008-01-05 23:11:57 +0900735 tmp |= HOST_AHCI_EN;
736 writel(tmp, mmio + HOST_CTL);
737 tmp = readl(mmio + HOST_CTL); /* flush && sanity check */
Tejun Heo15fe9822008-04-23 20:52:58 +0900738 if (tmp & HOST_AHCI_EN)
739 return;
740 msleep(10);
Tejun Heob710a1f2008-01-05 23:11:57 +0900741 }
Tejun Heo15fe9822008-04-23 20:52:58 +0900742
743 WARN_ON(1);
Tejun Heob710a1f2008-01-05 23:11:57 +0900744}
745
Matthew Garrett77cdec12009-07-17 19:13:47 +0100746static ssize_t ahci_show_host_caps(struct device *dev,
747 struct device_attribute *attr, char *buf)
748{
749 struct Scsi_Host *shost = class_to_shost(dev);
750 struct ata_port *ap = ata_shost_to_port(shost);
751 struct ahci_host_priv *hpriv = ap->host->private_data;
752
753 return sprintf(buf, "%x\n", hpriv->cap);
754}
755
Robert Hancock4c521c82009-09-20 17:02:31 -0600756static ssize_t ahci_show_host_cap2(struct device *dev,
757 struct device_attribute *attr, char *buf)
758{
759 struct Scsi_Host *shost = class_to_shost(dev);
760 struct ata_port *ap = ata_shost_to_port(shost);
761 struct ahci_host_priv *hpriv = ap->host->private_data;
762
763 return sprintf(buf, "%x\n", hpriv->cap2);
764}
765
Matthew Garrett77cdec12009-07-17 19:13:47 +0100766static ssize_t ahci_show_host_version(struct device *dev,
767 struct device_attribute *attr, char *buf)
768{
769 struct Scsi_Host *shost = class_to_shost(dev);
770 struct ata_port *ap = ata_shost_to_port(shost);
771 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
772
773 return sprintf(buf, "%x\n", readl(mmio + HOST_VERSION));
774}
775
776static ssize_t ahci_show_port_cmd(struct device *dev,
777 struct device_attribute *attr, char *buf)
778{
779 struct Scsi_Host *shost = class_to_shost(dev);
780 struct ata_port *ap = ata_shost_to_port(shost);
781 void __iomem *port_mmio = ahci_port_base(ap);
782
783 return sprintf(buf, "%x\n", readl(port_mmio + PORT_CMD));
784}
785
Tejun Heod447df12007-03-18 22:15:33 +0900786/**
787 * ahci_save_initial_config - Save and fixup initial config values
Tejun Heo4447d352007-04-17 23:44:08 +0900788 * @pdev: target PCI device
Tejun Heo4447d352007-04-17 23:44:08 +0900789 * @hpriv: host private area to store config values
Tejun Heod447df12007-03-18 22:15:33 +0900790 *
791 * Some registers containing configuration info might be setup by
792 * BIOS and might be cleared on reset. This function saves the
793 * initial values of those registers into @hpriv such that they
794 * can be restored after controller reset.
795 *
796 * If inconsistent, config values are fixed up by this function.
797 *
798 * LOCKING:
799 * None.
800 */
Tejun Heo4447d352007-04-17 23:44:08 +0900801static void ahci_save_initial_config(struct pci_dev *pdev,
Tejun Heo4447d352007-04-17 23:44:08 +0900802 struct ahci_host_priv *hpriv)
Tejun Heod447df12007-03-18 22:15:33 +0900803{
Tejun Heo4447d352007-04-17 23:44:08 +0900804 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
Robert Hancock4c521c82009-09-20 17:02:31 -0600805 u32 cap, cap2, vers, port_map;
Tejun Heo17199b12007-03-18 22:26:53 +0900806 int i;
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100807 int mv;
Tejun Heod447df12007-03-18 22:15:33 +0900808
Tejun Heob710a1f2008-01-05 23:11:57 +0900809 /* make sure AHCI mode is enabled before accessing CAP */
810 ahci_enable_ahci(mmio);
811
Tejun Heod447df12007-03-18 22:15:33 +0900812 /* Values prefixed with saved_ are written back to host after
813 * reset. Values without are used for driver operation.
814 */
815 hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
816 hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
817
Robert Hancock4c521c82009-09-20 17:02:31 -0600818 /* CAP2 register is only defined for AHCI 1.2 and later */
819 vers = readl(mmio + HOST_VERSION);
820 if ((vers >> 16) > 1 ||
821 ((vers >> 16) == 1 && (vers & 0xFFFF) >= 0x200))
822 hpriv->saved_cap2 = cap2 = readl(mmio + HOST_CAP2);
823 else
824 hpriv->saved_cap2 = cap2 = 0;
825
Tejun Heo274c1fd2007-07-16 14:29:40 +0900826 /* some chips have errata preventing 64bit use */
Tejun Heo417a1a62007-09-23 13:19:55 +0900827 if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
Tejun Heoc7a42152007-05-18 16:23:19 +0200828 dev_printk(KERN_INFO, &pdev->dev,
829 "controller can't do 64bit DMA, forcing 32bit\n");
830 cap &= ~HOST_CAP_64;
831 }
832
Tejun Heo417a1a62007-09-23 13:19:55 +0900833 if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
Tejun Heo274c1fd2007-07-16 14:29:40 +0900834 dev_printk(KERN_INFO, &pdev->dev,
835 "controller can't do NCQ, turning off CAP_NCQ\n");
836 cap &= ~HOST_CAP_NCQ;
837 }
838
Tejun Heoe297d992008-06-10 00:13:04 +0900839 if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
840 dev_printk(KERN_INFO, &pdev->dev,
841 "controller can do NCQ, turning on CAP_NCQ\n");
842 cap |= HOST_CAP_NCQ;
843 }
844
Roel Kluin258cd842008-03-09 21:42:40 +0100845 if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
Tejun Heo6949b912007-09-23 13:19:55 +0900846 dev_printk(KERN_INFO, &pdev->dev,
847 "controller can't do PMP, turning off CAP_PMP\n");
848 cap &= ~HOST_CAP_PMP;
849 }
850
Tejun Heod799e082008-06-17 12:46:30 +0900851 if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 &&
852 port_map != 1) {
853 dev_printk(KERN_INFO, &pdev->dev,
854 "JMB361 has only one port, port_map 0x%x -> 0x%x\n",
855 port_map, 1);
856 port_map = 1;
857 }
858
Jeff Garzikcd70c262007-07-08 02:29:42 -0400859 /*
860 * Temporary Marvell 6145 hack: PATA port presence
861 * is asserted through the standard AHCI port
862 * presence register, as bit 4 (counting from 0)
863 */
Tejun Heo417a1a62007-09-23 13:19:55 +0900864 if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100865 if (pdev->device == 0x6121)
866 mv = 0x3;
867 else
868 mv = 0xf;
Jeff Garzikcd70c262007-07-08 02:29:42 -0400869 dev_printk(KERN_ERR, &pdev->dev,
870 "MV_AHCI HACK: port_map %x -> %x\n",
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100871 port_map,
872 port_map & mv);
Alan Cox5b66c822008-09-03 14:48:34 +0100873 dev_printk(KERN_ERR, &pdev->dev,
874 "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
Jeff Garzikcd70c262007-07-08 02:29:42 -0400875
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100876 port_map &= mv;
Jeff Garzikcd70c262007-07-08 02:29:42 -0400877 }
878
Tejun Heo17199b12007-03-18 22:26:53 +0900879 /* cross check port_map and cap.n_ports */
Tejun Heo7a234af2007-09-03 12:44:57 +0900880 if (port_map) {
Tejun Heo837f5f82008-02-06 15:13:51 +0900881 int map_ports = 0;
Tejun Heo17199b12007-03-18 22:26:53 +0900882
Tejun Heo837f5f82008-02-06 15:13:51 +0900883 for (i = 0; i < AHCI_MAX_PORTS; i++)
884 if (port_map & (1 << i))
885 map_ports++;
Tejun Heo17199b12007-03-18 22:26:53 +0900886
Tejun Heo837f5f82008-02-06 15:13:51 +0900887 /* If PI has more ports than n_ports, whine, clear
888 * port_map and let it be generated from n_ports.
Tejun Heo17199b12007-03-18 22:26:53 +0900889 */
Tejun Heo837f5f82008-02-06 15:13:51 +0900890 if (map_ports > ahci_nr_ports(cap)) {
Tejun Heo4447d352007-04-17 23:44:08 +0900891 dev_printk(KERN_WARNING, &pdev->dev,
Tejun Heo837f5f82008-02-06 15:13:51 +0900892 "implemented port map (0x%x) contains more "
893 "ports than nr_ports (%u), using nr_ports\n",
894 port_map, ahci_nr_ports(cap));
Tejun Heo7a234af2007-09-03 12:44:57 +0900895 port_map = 0;
896 }
897 }
898
899 /* fabricate port_map from cap.nr_ports */
900 if (!port_map) {
Tejun Heo17199b12007-03-18 22:26:53 +0900901 port_map = (1 << ahci_nr_ports(cap)) - 1;
Tejun Heo7a234af2007-09-03 12:44:57 +0900902 dev_printk(KERN_WARNING, &pdev->dev,
903 "forcing PORTS_IMPL to 0x%x\n", port_map);
904
905 /* write the fixed up value to the PI register */
906 hpriv->saved_port_map = port_map;
Tejun Heo17199b12007-03-18 22:26:53 +0900907 }
908
Tejun Heod447df12007-03-18 22:15:33 +0900909 /* record values to use during operation */
910 hpriv->cap = cap;
Robert Hancock4c521c82009-09-20 17:02:31 -0600911 hpriv->cap2 = cap2;
Tejun Heod447df12007-03-18 22:15:33 +0900912 hpriv->port_map = port_map;
913}
914
915/**
916 * ahci_restore_initial_config - Restore initial config
Tejun Heo4447d352007-04-17 23:44:08 +0900917 * @host: target ATA host
Tejun Heod447df12007-03-18 22:15:33 +0900918 *
919 * Restore initial config stored by ahci_save_initial_config().
920 *
921 * LOCKING:
922 * None.
923 */
Tejun Heo4447d352007-04-17 23:44:08 +0900924static void ahci_restore_initial_config(struct ata_host *host)
Tejun Heod447df12007-03-18 22:15:33 +0900925{
Tejun Heo4447d352007-04-17 23:44:08 +0900926 struct ahci_host_priv *hpriv = host->private_data;
927 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
928
Tejun Heod447df12007-03-18 22:15:33 +0900929 writel(hpriv->saved_cap, mmio + HOST_CAP);
Robert Hancock4c521c82009-09-20 17:02:31 -0600930 if (hpriv->saved_cap2)
931 writel(hpriv->saved_cap2, mmio + HOST_CAP2);
Tejun Heod447df12007-03-18 22:15:33 +0900932 writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
933 (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
934}
935
Tejun Heo203ef6c2007-07-16 14:29:40 +0900936static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937{
Tejun Heo203ef6c2007-07-16 14:29:40 +0900938 static const int offset[] = {
939 [SCR_STATUS] = PORT_SCR_STAT,
940 [SCR_CONTROL] = PORT_SCR_CTL,
941 [SCR_ERROR] = PORT_SCR_ERR,
942 [SCR_ACTIVE] = PORT_SCR_ACT,
943 [SCR_NOTIFICATION] = PORT_SCR_NTF,
944 };
945 struct ahci_host_priv *hpriv = ap->host->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
Tejun Heo203ef6c2007-07-16 14:29:40 +0900947 if (sc_reg < ARRAY_SIZE(offset) &&
948 (sc_reg != SCR_NOTIFICATION || (hpriv->cap & HOST_CAP_SNTF)))
949 return offset[sc_reg];
Tejun Heoda3dbb12007-07-16 14:29:40 +0900950 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951}
952
Tejun Heo82ef04f2008-07-31 17:02:40 +0900953static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954{
Tejun Heo82ef04f2008-07-31 17:02:40 +0900955 void __iomem *port_mmio = ahci_port_base(link->ap);
956 int offset = ahci_scr_offset(link->ap, sc_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957
Tejun Heo203ef6c2007-07-16 14:29:40 +0900958 if (offset) {
959 *val = readl(port_mmio + offset);
960 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 }
Tejun Heo203ef6c2007-07-16 14:29:40 +0900962 return -EINVAL;
963}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964
Tejun Heo82ef04f2008-07-31 17:02:40 +0900965static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
Tejun Heo203ef6c2007-07-16 14:29:40 +0900966{
Tejun Heo82ef04f2008-07-31 17:02:40 +0900967 void __iomem *port_mmio = ahci_port_base(link->ap);
968 int offset = ahci_scr_offset(link->ap, sc_reg);
Tejun Heo203ef6c2007-07-16 14:29:40 +0900969
970 if (offset) {
971 writel(val, port_mmio + offset);
972 return 0;
973 }
974 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975}
976
Tejun Heo4447d352007-04-17 23:44:08 +0900977static void ahci_start_engine(struct ata_port *ap)
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900978{
Tejun Heo4447d352007-04-17 23:44:08 +0900979 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900980 u32 tmp;
981
Tejun Heod8fcd112006-07-26 15:59:25 +0900982 /* start DMA */
Tejun Heo9f592052006-07-26 15:59:26 +0900983 tmp = readl(port_mmio + PORT_CMD);
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900984 tmp |= PORT_CMD_START;
985 writel(tmp, port_mmio + PORT_CMD);
986 readl(port_mmio + PORT_CMD); /* flush */
987}
988
Tejun Heo4447d352007-04-17 23:44:08 +0900989static int ahci_stop_engine(struct ata_port *ap)
Tejun Heo254950c2006-07-26 15:59:25 +0900990{
Tejun Heo4447d352007-04-17 23:44:08 +0900991 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo254950c2006-07-26 15:59:25 +0900992 u32 tmp;
993
994 tmp = readl(port_mmio + PORT_CMD);
995
Tejun Heod8fcd112006-07-26 15:59:25 +0900996 /* check if the HBA is idle */
Tejun Heo254950c2006-07-26 15:59:25 +0900997 if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
998 return 0;
999
Tejun Heod8fcd112006-07-26 15:59:25 +09001000 /* setting HBA to idle */
Tejun Heo254950c2006-07-26 15:59:25 +09001001 tmp &= ~PORT_CMD_START;
1002 writel(tmp, port_mmio + PORT_CMD);
1003
Tejun Heod8fcd112006-07-26 15:59:25 +09001004 /* wait for engine to stop. This could be as long as 500 msec */
Tejun Heo254950c2006-07-26 15:59:25 +09001005 tmp = ata_wait_register(port_mmio + PORT_CMD,
Jeff Garzik2dcb4072007-10-19 06:42:56 -04001006 PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
Tejun Heod8fcd112006-07-26 15:59:25 +09001007 if (tmp & PORT_CMD_LIST_ON)
Tejun Heo254950c2006-07-26 15:59:25 +09001008 return -EIO;
1009
1010 return 0;
1011}
1012
Tejun Heo4447d352007-04-17 23:44:08 +09001013static void ahci_start_fis_rx(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001014{
Tejun Heo4447d352007-04-17 23:44:08 +09001015 void __iomem *port_mmio = ahci_port_base(ap);
1016 struct ahci_host_priv *hpriv = ap->host->private_data;
1017 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo0be0aa92006-07-26 15:59:26 +09001018 u32 tmp;
1019
1020 /* set FIS registers */
Tejun Heo4447d352007-04-17 23:44:08 +09001021 if (hpriv->cap & HOST_CAP_64)
1022 writel((pp->cmd_slot_dma >> 16) >> 16,
1023 port_mmio + PORT_LST_ADDR_HI);
1024 writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001025
Tejun Heo4447d352007-04-17 23:44:08 +09001026 if (hpriv->cap & HOST_CAP_64)
1027 writel((pp->rx_fis_dma >> 16) >> 16,
1028 port_mmio + PORT_FIS_ADDR_HI);
1029 writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001030
1031 /* enable FIS reception */
1032 tmp = readl(port_mmio + PORT_CMD);
1033 tmp |= PORT_CMD_FIS_RX;
1034 writel(tmp, port_mmio + PORT_CMD);
1035
1036 /* flush */
1037 readl(port_mmio + PORT_CMD);
1038}
1039
Tejun Heo4447d352007-04-17 23:44:08 +09001040static int ahci_stop_fis_rx(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001041{
Tejun Heo4447d352007-04-17 23:44:08 +09001042 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001043 u32 tmp;
1044
1045 /* disable FIS reception */
1046 tmp = readl(port_mmio + PORT_CMD);
1047 tmp &= ~PORT_CMD_FIS_RX;
1048 writel(tmp, port_mmio + PORT_CMD);
1049
1050 /* wait for completion, spec says 500ms, give it 1000 */
1051 tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
1052 PORT_CMD_FIS_ON, 10, 1000);
1053 if (tmp & PORT_CMD_FIS_ON)
1054 return -EBUSY;
1055
1056 return 0;
1057}
1058
Tejun Heo4447d352007-04-17 23:44:08 +09001059static void ahci_power_up(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001060{
Tejun Heo4447d352007-04-17 23:44:08 +09001061 struct ahci_host_priv *hpriv = ap->host->private_data;
1062 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001063 u32 cmd;
1064
1065 cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
1066
1067 /* spin up device */
Tejun Heo4447d352007-04-17 23:44:08 +09001068 if (hpriv->cap & HOST_CAP_SSS) {
Tejun Heo0be0aa92006-07-26 15:59:26 +09001069 cmd |= PORT_CMD_SPIN_UP;
1070 writel(cmd, port_mmio + PORT_CMD);
1071 }
1072
1073 /* wake up link */
1074 writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
1075}
1076
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04001077static void ahci_disable_alpm(struct ata_port *ap)
1078{
1079 struct ahci_host_priv *hpriv = ap->host->private_data;
1080 void __iomem *port_mmio = ahci_port_base(ap);
1081 u32 cmd;
1082 struct ahci_port_priv *pp = ap->private_data;
1083
1084 /* IPM bits should be disabled by libata-core */
1085 /* get the existing command bits */
1086 cmd = readl(port_mmio + PORT_CMD);
1087
1088 /* disable ALPM and ASP */
1089 cmd &= ~PORT_CMD_ASP;
1090 cmd &= ~PORT_CMD_ALPE;
1091
1092 /* force the interface back to active */
1093 cmd |= PORT_CMD_ICC_ACTIVE;
1094
1095 /* write out new cmd value */
1096 writel(cmd, port_mmio + PORT_CMD);
1097 cmd = readl(port_mmio + PORT_CMD);
1098
1099 /* wait 10ms to be sure we've come out of any low power state */
1100 msleep(10);
1101
1102 /* clear out any PhyRdy stuff from interrupt status */
1103 writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
1104
1105 /* go ahead and clean out PhyRdy Change from Serror too */
Tejun Heo82ef04f2008-07-31 17:02:40 +09001106 ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04001107
1108 /*
1109 * Clear flag to indicate that we should ignore all PhyRdy
1110 * state changes
1111 */
1112 hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
1113
1114 /*
1115 * Enable interrupts on Phy Ready.
1116 */
1117 pp->intr_mask |= PORT_IRQ_PHYRDY;
1118 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
1119
1120 /*
1121 * don't change the link pm policy - we can be called
1122 * just to turn of link pm temporarily
1123 */
1124}
1125
1126static int ahci_enable_alpm(struct ata_port *ap,
1127 enum link_pm policy)
1128{
1129 struct ahci_host_priv *hpriv = ap->host->private_data;
1130 void __iomem *port_mmio = ahci_port_base(ap);
1131 u32 cmd;
1132 struct ahci_port_priv *pp = ap->private_data;
1133 u32 asp;
1134
1135 /* Make sure the host is capable of link power management */
1136 if (!(hpriv->cap & HOST_CAP_ALPM))
1137 return -EINVAL;
1138
1139 switch (policy) {
1140 case MAX_PERFORMANCE:
1141 case NOT_AVAILABLE:
1142 /*
1143 * if we came here with NOT_AVAILABLE,
1144 * it just means this is the first time we
1145 * have tried to enable - default to max performance,
1146 * and let the user go to lower power modes on request.
1147 */
1148 ahci_disable_alpm(ap);
1149 return 0;
1150 case MIN_POWER:
1151 /* configure HBA to enter SLUMBER */
1152 asp = PORT_CMD_ASP;
1153 break;
1154 case MEDIUM_POWER:
1155 /* configure HBA to enter PARTIAL */
1156 asp = 0;
1157 break;
1158 default:
1159 return -EINVAL;
1160 }
1161
1162 /*
1163 * Disable interrupts on Phy Ready. This keeps us from
1164 * getting woken up due to spurious phy ready interrupts
1165 * TBD - Hot plug should be done via polling now, is
1166 * that even supported?
1167 */
1168 pp->intr_mask &= ~PORT_IRQ_PHYRDY;
1169 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
1170
1171 /*
1172 * Set a flag to indicate that we should ignore all PhyRdy
1173 * state changes since these can happen now whenever we
1174 * change link state
1175 */
1176 hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
1177
1178 /* get the existing command bits */
1179 cmd = readl(port_mmio + PORT_CMD);
1180
1181 /*
1182 * Set ASP based on Policy
1183 */
1184 cmd |= asp;
1185
1186 /*
1187 * Setting this bit will instruct the HBA to aggressively
1188 * enter a lower power link state when it's appropriate and
1189 * based on the value set above for ASP
1190 */
1191 cmd |= PORT_CMD_ALPE;
1192
1193 /* write out new cmd value */
1194 writel(cmd, port_mmio + PORT_CMD);
1195 cmd = readl(port_mmio + PORT_CMD);
1196
1197 /* IPM bits should be set by libata-core */
1198 return 0;
1199}
1200
Tejun Heo438ac6d2007-03-02 17:31:26 +09001201#ifdef CONFIG_PM
Tejun Heo4447d352007-04-17 23:44:08 +09001202static void ahci_power_down(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001203{
Tejun Heo4447d352007-04-17 23:44:08 +09001204 struct ahci_host_priv *hpriv = ap->host->private_data;
1205 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001206 u32 cmd, scontrol;
1207
Tejun Heo4447d352007-04-17 23:44:08 +09001208 if (!(hpriv->cap & HOST_CAP_SSS))
Tejun Heo07c53da2007-01-21 02:10:11 +09001209 return;
1210
1211 /* put device into listen mode, first set PxSCTL.DET to 0 */
1212 scontrol = readl(port_mmio + PORT_SCR_CTL);
1213 scontrol &= ~0xf;
1214 writel(scontrol, port_mmio + PORT_SCR_CTL);
1215
1216 /* then set PxCMD.SUD to 0 */
Tejun Heo0be0aa92006-07-26 15:59:26 +09001217 cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
Tejun Heo07c53da2007-01-21 02:10:11 +09001218 cmd &= ~PORT_CMD_SPIN_UP;
1219 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001220}
Tejun Heo438ac6d2007-03-02 17:31:26 +09001221#endif
Tejun Heo0be0aa92006-07-26 15:59:26 +09001222
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04001223static void ahci_start_port(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001224{
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001225 struct ahci_port_priv *pp = ap->private_data;
1226 struct ata_link *link;
1227 struct ahci_em_priv *emp;
David Milburn4c1e9aa2009-04-03 15:36:41 -05001228 ssize_t rc;
1229 int i;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001230
Tejun Heo0be0aa92006-07-26 15:59:26 +09001231 /* enable FIS reception */
Tejun Heo4447d352007-04-17 23:44:08 +09001232 ahci_start_fis_rx(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001233
1234 /* enable DMA */
Tejun Heo4447d352007-04-17 23:44:08 +09001235 ahci_start_engine(ap);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001236
1237 /* turn on LEDs */
1238 if (ap->flags & ATA_FLAG_EM) {
Tejun Heo1eca4362008-11-03 20:03:17 +09001239 ata_for_each_link(link, ap, EDGE) {
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001240 emp = &pp->em_priv[link->pmp];
David Milburn4c1e9aa2009-04-03 15:36:41 -05001241
1242 /* EM Transmit bit maybe busy during init */
Tejun Heod50ce072009-05-12 10:57:41 +09001243 for (i = 0; i < EM_MAX_RETRY; i++) {
David Milburn4c1e9aa2009-04-03 15:36:41 -05001244 rc = ahci_transmit_led_message(ap,
1245 emp->led_state,
1246 4);
1247 if (rc == -EBUSY)
Tejun Heod50ce072009-05-12 10:57:41 +09001248 msleep(1);
David Milburn4c1e9aa2009-04-03 15:36:41 -05001249 else
1250 break;
1251 }
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001252 }
1253 }
1254
1255 if (ap->flags & ATA_FLAG_SW_ACTIVITY)
Tejun Heo1eca4362008-11-03 20:03:17 +09001256 ata_for_each_link(link, ap, EDGE)
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001257 ahci_init_sw_activity(link);
1258
Tejun Heo0be0aa92006-07-26 15:59:26 +09001259}
1260
Tejun Heo4447d352007-04-17 23:44:08 +09001261static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001262{
1263 int rc;
1264
1265 /* disable DMA */
Tejun Heo4447d352007-04-17 23:44:08 +09001266 rc = ahci_stop_engine(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001267 if (rc) {
1268 *emsg = "failed to stop engine";
1269 return rc;
1270 }
1271
1272 /* disable FIS reception */
Tejun Heo4447d352007-04-17 23:44:08 +09001273 rc = ahci_stop_fis_rx(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001274 if (rc) {
1275 *emsg = "failed stop FIS RX";
1276 return rc;
1277 }
1278
Tejun Heo0be0aa92006-07-26 15:59:26 +09001279 return 0;
1280}
1281
Tejun Heo4447d352007-04-17 23:44:08 +09001282static int ahci_reset_controller(struct ata_host *host)
Tejun Heod91542c2006-07-26 15:59:26 +09001283{
Tejun Heo4447d352007-04-17 23:44:08 +09001284 struct pci_dev *pdev = to_pci_dev(host->dev);
Tejun Heo49f29092007-11-19 16:03:44 +09001285 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo4447d352007-04-17 23:44:08 +09001286 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Tejun Heod447df12007-03-18 22:15:33 +09001287 u32 tmp;
Tejun Heod91542c2006-07-26 15:59:26 +09001288
Jeff Garzik3cc3eb12007-09-26 00:02:41 -04001289 /* we must be in AHCI mode, before using anything
1290 * AHCI-specific, such as HOST_RESET.
1291 */
Tejun Heob710a1f2008-01-05 23:11:57 +09001292 ahci_enable_ahci(mmio);
Jeff Garzik3cc3eb12007-09-26 00:02:41 -04001293
1294 /* global controller reset */
Tejun Heoa22e6442008-03-10 10:25:25 +09001295 if (!ahci_skip_host_reset) {
1296 tmp = readl(mmio + HOST_CTL);
1297 if ((tmp & HOST_RESET) == 0) {
1298 writel(tmp | HOST_RESET, mmio + HOST_CTL);
1299 readl(mmio + HOST_CTL); /* flush */
1300 }
Tejun Heod91542c2006-07-26 15:59:26 +09001301
Zhang Rui24920c82008-07-04 13:32:17 +08001302 /*
1303 * to perform host reset, OS should set HOST_RESET
1304 * and poll until this bit is read to be "0".
1305 * reset must complete within 1 second, or
Tejun Heoa22e6442008-03-10 10:25:25 +09001306 * the hardware should be considered fried.
1307 */
Zhang Rui24920c82008-07-04 13:32:17 +08001308 tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET,
1309 HOST_RESET, 10, 1000);
Tejun Heod91542c2006-07-26 15:59:26 +09001310
Tejun Heoa22e6442008-03-10 10:25:25 +09001311 if (tmp & HOST_RESET) {
1312 dev_printk(KERN_ERR, host->dev,
1313 "controller reset failed (0x%x)\n", tmp);
1314 return -EIO;
1315 }
Tejun Heod91542c2006-07-26 15:59:26 +09001316
Tejun Heoa22e6442008-03-10 10:25:25 +09001317 /* turn on AHCI mode */
1318 ahci_enable_ahci(mmio);
Tejun Heo98fa4b62006-11-02 12:17:23 +09001319
Tejun Heoa22e6442008-03-10 10:25:25 +09001320 /* Some registers might be cleared on reset. Restore
1321 * initial values.
1322 */
1323 ahci_restore_initial_config(host);
1324 } else
1325 dev_printk(KERN_INFO, host->dev,
1326 "skipping global host reset\n");
Tejun Heod91542c2006-07-26 15:59:26 +09001327
1328 if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
1329 u16 tmp16;
1330
1331 /* configure PCS */
1332 pci_read_config_word(pdev, 0x92, &tmp16);
Tejun Heo49f29092007-11-19 16:03:44 +09001333 if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
1334 tmp16 |= hpriv->port_map;
1335 pci_write_config_word(pdev, 0x92, tmp16);
1336 }
Tejun Heod91542c2006-07-26 15:59:26 +09001337 }
1338
1339 return 0;
1340}
1341
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001342static void ahci_sw_activity(struct ata_link *link)
1343{
1344 struct ata_port *ap = link->ap;
1345 struct ahci_port_priv *pp = ap->private_data;
1346 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1347
1348 if (!(link->flags & ATA_LFLAG_SW_ACTIVITY))
1349 return;
1350
1351 emp->activity++;
1352 if (!timer_pending(&emp->timer))
1353 mod_timer(&emp->timer, jiffies + msecs_to_jiffies(10));
1354}
1355
1356static void ahci_sw_activity_blink(unsigned long arg)
1357{
1358 struct ata_link *link = (struct ata_link *)arg;
1359 struct ata_port *ap = link->ap;
1360 struct ahci_port_priv *pp = ap->private_data;
1361 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1362 unsigned long led_message = emp->led_state;
1363 u32 activity_led_state;
David Milburneb409632008-10-16 09:26:19 -05001364 unsigned long flags;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001365
David Milburn87943ac2008-10-13 14:38:36 -05001366 led_message &= EM_MSG_LED_VALUE;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001367 led_message |= ap->port_no | (link->pmp << 8);
1368
1369 /* check to see if we've had activity. If so,
1370 * toggle state of LED and reset timer. If not,
1371 * turn LED to desired idle state.
1372 */
David Milburneb409632008-10-16 09:26:19 -05001373 spin_lock_irqsave(ap->lock, flags);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001374 if (emp->saved_activity != emp->activity) {
1375 emp->saved_activity = emp->activity;
1376 /* get the current LED state */
David Milburn87943ac2008-10-13 14:38:36 -05001377 activity_led_state = led_message & EM_MSG_LED_VALUE_ON;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001378
1379 if (activity_led_state)
1380 activity_led_state = 0;
1381 else
1382 activity_led_state = 1;
1383
1384 /* clear old state */
David Milburn87943ac2008-10-13 14:38:36 -05001385 led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001386
1387 /* toggle state */
1388 led_message |= (activity_led_state << 16);
1389 mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100));
1390 } else {
1391 /* switch to idle */
David Milburn87943ac2008-10-13 14:38:36 -05001392 led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001393 if (emp->blink_policy == BLINK_OFF)
1394 led_message |= (1 << 16);
1395 }
David Milburneb409632008-10-16 09:26:19 -05001396 spin_unlock_irqrestore(ap->lock, flags);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001397 ahci_transmit_led_message(ap, led_message, 4);
1398}
1399
1400static void ahci_init_sw_activity(struct ata_link *link)
1401{
1402 struct ata_port *ap = link->ap;
1403 struct ahci_port_priv *pp = ap->private_data;
1404 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1405
1406 /* init activity stats, setup timer */
1407 emp->saved_activity = emp->activity = 0;
1408 setup_timer(&emp->timer, ahci_sw_activity_blink, (unsigned long)link);
1409
1410 /* check our blink policy and set flag for link if it's enabled */
1411 if (emp->blink_policy)
1412 link->flags |= ATA_LFLAG_SW_ACTIVITY;
1413}
1414
1415static int ahci_reset_em(struct ata_host *host)
1416{
1417 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
1418 u32 em_ctl;
1419
1420 em_ctl = readl(mmio + HOST_EM_CTL);
1421 if ((em_ctl & EM_CTL_TM) || (em_ctl & EM_CTL_RST))
1422 return -EINVAL;
1423
1424 writel(em_ctl | EM_CTL_RST, mmio + HOST_EM_CTL);
1425 return 0;
1426}
1427
1428static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
1429 ssize_t size)
1430{
1431 struct ahci_host_priv *hpriv = ap->host->private_data;
1432 struct ahci_port_priv *pp = ap->private_data;
1433 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
1434 u32 em_ctl;
1435 u32 message[] = {0, 0};
Linus Torvalds93082f02008-07-25 10:56:36 -07001436 unsigned long flags;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001437 int pmp;
1438 struct ahci_em_priv *emp;
1439
1440 /* get the slot number from the message */
David Milburn87943ac2008-10-13 14:38:36 -05001441 pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
Tejun Heod50ce072009-05-12 10:57:41 +09001442 if (pmp < EM_MAX_SLOTS)
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001443 emp = &pp->em_priv[pmp];
1444 else
1445 return -EINVAL;
1446
1447 spin_lock_irqsave(ap->lock, flags);
1448
1449 /*
1450 * if we are still busy transmitting a previous message,
1451 * do not allow
1452 */
1453 em_ctl = readl(mmio + HOST_EM_CTL);
1454 if (em_ctl & EM_CTL_TM) {
1455 spin_unlock_irqrestore(ap->lock, flags);
David Milburn4c1e9aa2009-04-03 15:36:41 -05001456 return -EBUSY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001457 }
1458
1459 /*
1460 * create message header - this is all zero except for
1461 * the message size, which is 4 bytes.
1462 */
1463 message[0] |= (4 << 8);
1464
1465 /* ignore 0:4 of byte zero, fill in port info yourself */
David Milburn87943ac2008-10-13 14:38:36 -05001466 message[1] = ((state & ~EM_MSG_LED_HBA_PORT) | ap->port_no);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001467
1468 /* write message to EM_LOC */
1469 writel(message[0], mmio + hpriv->em_loc);
1470 writel(message[1], mmio + hpriv->em_loc+4);
1471
1472 /* save off new led state for port/slot */
David Milburn208f2a82009-03-20 14:14:23 -05001473 emp->led_state = state;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001474
1475 /*
1476 * tell hardware to transmit the message
1477 */
1478 writel(em_ctl | EM_CTL_TM, mmio + HOST_EM_CTL);
1479
1480 spin_unlock_irqrestore(ap->lock, flags);
1481 return size;
1482}
1483
1484static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
1485{
1486 struct ahci_port_priv *pp = ap->private_data;
1487 struct ata_link *link;
1488 struct ahci_em_priv *emp;
1489 int rc = 0;
1490
Tejun Heo1eca4362008-11-03 20:03:17 +09001491 ata_for_each_link(link, ap, EDGE) {
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001492 emp = &pp->em_priv[link->pmp];
1493 rc += sprintf(buf, "%lx\n", emp->led_state);
1494 }
1495 return rc;
1496}
1497
1498static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
1499 size_t size)
1500{
1501 int state;
1502 int pmp;
1503 struct ahci_port_priv *pp = ap->private_data;
1504 struct ahci_em_priv *emp;
1505
1506 state = simple_strtoul(buf, NULL, 0);
1507
1508 /* get the slot number from the message */
David Milburn87943ac2008-10-13 14:38:36 -05001509 pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
Tejun Heod50ce072009-05-12 10:57:41 +09001510 if (pmp < EM_MAX_SLOTS)
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001511 emp = &pp->em_priv[pmp];
1512 else
1513 return -EINVAL;
1514
1515 /* mask off the activity bits if we are in sw_activity
1516 * mode, user should turn off sw_activity before setting
1517 * activity led through em_message
1518 */
1519 if (emp->blink_policy)
David Milburn87943ac2008-10-13 14:38:36 -05001520 state &= ~EM_MSG_LED_VALUE_ACTIVITY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001521
1522 return ahci_transmit_led_message(ap, state, size);
1523}
1524
1525static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)
1526{
1527 struct ata_link *link = dev->link;
1528 struct ata_port *ap = link->ap;
1529 struct ahci_port_priv *pp = ap->private_data;
1530 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1531 u32 port_led_state = emp->led_state;
1532
1533 /* save the desired Activity LED behavior */
1534 if (val == OFF) {
1535 /* clear LFLAG */
1536 link->flags &= ~(ATA_LFLAG_SW_ACTIVITY);
1537
1538 /* set the LED to OFF */
David Milburn87943ac2008-10-13 14:38:36 -05001539 port_led_state &= EM_MSG_LED_VALUE_OFF;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001540 port_led_state |= (ap->port_no | (link->pmp << 8));
1541 ahci_transmit_led_message(ap, port_led_state, 4);
1542 } else {
1543 link->flags |= ATA_LFLAG_SW_ACTIVITY;
1544 if (val == BLINK_OFF) {
1545 /* set LED to ON for idle */
David Milburn87943ac2008-10-13 14:38:36 -05001546 port_led_state &= EM_MSG_LED_VALUE_OFF;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001547 port_led_state |= (ap->port_no | (link->pmp << 8));
David Milburn87943ac2008-10-13 14:38:36 -05001548 port_led_state |= EM_MSG_LED_VALUE_ON; /* check this */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001549 ahci_transmit_led_message(ap, port_led_state, 4);
1550 }
1551 }
1552 emp->blink_policy = val;
1553 return 0;
1554}
1555
1556static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
1557{
1558 struct ata_link *link = dev->link;
1559 struct ata_port *ap = link->ap;
1560 struct ahci_port_priv *pp = ap->private_data;
1561 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1562
1563 /* display the saved value of activity behavior for this
1564 * disk.
1565 */
1566 return sprintf(buf, "%d\n", emp->blink_policy);
1567}
1568
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001569static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
1570 int port_no, void __iomem *mmio,
1571 void __iomem *port_mmio)
1572{
1573 const char *emsg = NULL;
1574 int rc;
1575 u32 tmp;
1576
1577 /* make sure port is not active */
1578 rc = ahci_deinit_port(ap, &emsg);
1579 if (rc)
1580 dev_printk(KERN_WARNING, &pdev->dev,
1581 "%s (%d)\n", emsg, rc);
1582
1583 /* clear SError */
1584 tmp = readl(port_mmio + PORT_SCR_ERR);
1585 VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
1586 writel(tmp, port_mmio + PORT_SCR_ERR);
1587
1588 /* clear port IRQ */
1589 tmp = readl(port_mmio + PORT_IRQ_STAT);
1590 VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
1591 if (tmp)
1592 writel(tmp, port_mmio + PORT_IRQ_STAT);
1593
1594 writel(1 << port_no, mmio + HOST_IRQ_STAT);
1595}
1596
Tejun Heo4447d352007-04-17 23:44:08 +09001597static void ahci_init_controller(struct ata_host *host)
Tejun Heod91542c2006-07-26 15:59:26 +09001598{
Tejun Heo417a1a62007-09-23 13:19:55 +09001599 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo4447d352007-04-17 23:44:08 +09001600 struct pci_dev *pdev = to_pci_dev(host->dev);
1601 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001602 int i;
Jeff Garzikcd70c262007-07-08 02:29:42 -04001603 void __iomem *port_mmio;
Tejun Heod91542c2006-07-26 15:59:26 +09001604 u32 tmp;
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +01001605 int mv;
Tejun Heod91542c2006-07-26 15:59:26 +09001606
Tejun Heo417a1a62007-09-23 13:19:55 +09001607 if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +01001608 if (pdev->device == 0x6121)
1609 mv = 2;
1610 else
1611 mv = 4;
1612 port_mmio = __ahci_port_base(host, mv);
Jeff Garzikcd70c262007-07-08 02:29:42 -04001613
1614 writel(0, port_mmio + PORT_IRQ_MASK);
1615
1616 /* clear port IRQ */
1617 tmp = readl(port_mmio + PORT_IRQ_STAT);
1618 VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
1619 if (tmp)
1620 writel(tmp, port_mmio + PORT_IRQ_STAT);
1621 }
1622
Tejun Heo4447d352007-04-17 23:44:08 +09001623 for (i = 0; i < host->n_ports; i++) {
1624 struct ata_port *ap = host->ports[i];
Tejun Heod91542c2006-07-26 15:59:26 +09001625
Jeff Garzikcd70c262007-07-08 02:29:42 -04001626 port_mmio = ahci_port_base(ap);
Tejun Heo4447d352007-04-17 23:44:08 +09001627 if (ata_port_is_dummy(ap))
Tejun Heod91542c2006-07-26 15:59:26 +09001628 continue;
Tejun Heod91542c2006-07-26 15:59:26 +09001629
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001630 ahci_port_init(pdev, ap, i, mmio, port_mmio);
Tejun Heod91542c2006-07-26 15:59:26 +09001631 }
1632
1633 tmp = readl(mmio + HOST_CTL);
1634 VPRINTK("HOST_CTL 0x%x\n", tmp);
1635 writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
1636 tmp = readl(mmio + HOST_CTL);
1637 VPRINTK("HOST_CTL 0x%x\n", tmp);
1638}
1639
Jeff Garzika8785392008-02-28 15:43:48 -05001640static void ahci_dev_config(struct ata_device *dev)
1641{
1642 struct ahci_host_priv *hpriv = dev->link->ap->host->private_data;
1643
Jeff Garzik4cde32f2008-03-24 22:40:40 -04001644 if (hpriv->flags & AHCI_HFLAG_SECT255) {
Jeff Garzika8785392008-02-28 15:43:48 -05001645 dev->max_sectors = 255;
Jeff Garzik4cde32f2008-03-24 22:40:40 -04001646 ata_dev_printk(dev, KERN_INFO,
1647 "SB600 AHCI: limiting to 255 sectors per cmd\n");
1648 }
Jeff Garzika8785392008-02-28 15:43:48 -05001649}
1650
Tejun Heo422b7592005-12-19 22:37:17 +09001651static unsigned int ahci_dev_classify(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652{
Tejun Heo4447d352007-04-17 23:44:08 +09001653 void __iomem *port_mmio = ahci_port_base(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 struct ata_taskfile tf;
Tejun Heo422b7592005-12-19 22:37:17 +09001655 u32 tmp;
1656
1657 tmp = readl(port_mmio + PORT_SIG);
1658 tf.lbah = (tmp >> 24) & 0xff;
1659 tf.lbam = (tmp >> 16) & 0xff;
1660 tf.lbal = (tmp >> 8) & 0xff;
1661 tf.nsect = (tmp) & 0xff;
1662
1663 return ata_dev_classify(&tf);
1664}
1665
Tejun Heo12fad3f2006-05-15 21:03:55 +09001666static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
1667 u32 opts)
Tejun Heocc9278e2006-02-10 17:25:47 +09001668{
Tejun Heo12fad3f2006-05-15 21:03:55 +09001669 dma_addr_t cmd_tbl_dma;
1670
1671 cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
1672
1673 pp->cmd_slot[tag].opts = cpu_to_le32(opts);
1674 pp->cmd_slot[tag].status = 0;
1675 pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
1676 pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
Tejun Heocc9278e2006-02-10 17:25:47 +09001677}
1678
Shane Huang78d5ae32009-08-07 15:05:52 +08001679static int ahci_kick_engine(struct ata_port *ap)
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001680{
Tejun Heo350756f2008-04-07 22:47:21 +09001681 void __iomem *port_mmio = ahci_port_base(ap);
Jeff Garzikcca39742006-08-24 03:19:22 -04001682 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo520d06f2008-04-07 22:47:21 +09001683 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001684 u32 tmp;
Tejun Heod2e75df2007-07-16 14:29:39 +09001685 int busy, rc;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001686
Tejun Heod2e75df2007-07-16 14:29:39 +09001687 /* stop engine */
1688 rc = ahci_stop_engine(ap);
1689 if (rc)
1690 goto out_restart;
1691
Shane Huang78d5ae32009-08-07 15:05:52 +08001692 /* need to do CLO?
1693 * always do CLO if PMP is attached (AHCI-1.3 9.2)
1694 */
1695 busy = status & (ATA_BUSY | ATA_DRQ);
1696 if (!busy && !sata_pmp_attached(ap)) {
Tejun Heod2e75df2007-07-16 14:29:39 +09001697 rc = 0;
1698 goto out_restart;
1699 }
1700
1701 if (!(hpriv->cap & HOST_CAP_CLO)) {
1702 rc = -EOPNOTSUPP;
1703 goto out_restart;
1704 }
1705
1706 /* perform CLO */
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001707 tmp = readl(port_mmio + PORT_CMD);
1708 tmp |= PORT_CMD_CLO;
1709 writel(tmp, port_mmio + PORT_CMD);
1710
Tejun Heod2e75df2007-07-16 14:29:39 +09001711 rc = 0;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001712 tmp = ata_wait_register(port_mmio + PORT_CMD,
1713 PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
1714 if (tmp & PORT_CMD_CLO)
Tejun Heod2e75df2007-07-16 14:29:39 +09001715 rc = -EIO;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001716
Tejun Heod2e75df2007-07-16 14:29:39 +09001717 /* restart engine */
1718 out_restart:
1719 ahci_start_engine(ap);
1720 return rc;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001721}
1722
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001723static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
1724 struct ata_taskfile *tf, int is_cmd, u16 flags,
1725 unsigned long timeout_msec)
1726{
1727 const u32 cmd_fis_len = 5; /* five dwords */
1728 struct ahci_port_priv *pp = ap->private_data;
1729 void __iomem *port_mmio = ahci_port_base(ap);
1730 u8 *fis = pp->cmd_tbl;
1731 u32 tmp;
1732
1733 /* prep the command */
1734 ata_tf_to_fis(tf, pmp, is_cmd, fis);
1735 ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12));
1736
1737 /* issue & wait */
1738 writel(1, port_mmio + PORT_CMD_ISSUE);
1739
1740 if (timeout_msec) {
1741 tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1,
1742 1, timeout_msec);
1743 if (tmp & 0x1) {
Shane Huang78d5ae32009-08-07 15:05:52 +08001744 ahci_kick_engine(ap);
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001745 return -EBUSY;
1746 }
1747 } else
1748 readl(port_mmio + PORT_CMD_ISSUE); /* flush */
1749
1750 return 0;
1751}
1752
Shane Huangbd172432008-06-10 15:52:04 +08001753static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
1754 int pmp, unsigned long deadline,
1755 int (*check_ready)(struct ata_link *link))
Tejun Heo4658f792006-03-22 21:07:03 +09001756{
Tejun Heocc0680a2007-08-06 18:36:23 +09001757 struct ata_port *ap = link->ap;
Tejun Heo55946392009-08-04 14:30:08 +09001758 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo4658f792006-03-22 21:07:03 +09001759 const char *reason = NULL;
Tejun Heo2cbb79e2007-07-16 14:29:38 +09001760 unsigned long now, msecs;
Tejun Heo4658f792006-03-22 21:07:03 +09001761 struct ata_taskfile tf;
Tejun Heo4658f792006-03-22 21:07:03 +09001762 int rc;
1763
1764 DPRINTK("ENTER\n");
1765
1766 /* prepare for SRST (AHCI-1.1 10.4.1) */
Shane Huang78d5ae32009-08-07 15:05:52 +08001767 rc = ahci_kick_engine(ap);
Tejun Heo994056d2007-12-06 15:02:48 +09001768 if (rc && rc != -EOPNOTSUPP)
Tejun Heocc0680a2007-08-06 18:36:23 +09001769 ata_link_printk(link, KERN_WARNING,
Tejun Heo994056d2007-12-06 15:02:48 +09001770 "failed to reset engine (errno=%d)\n", rc);
Tejun Heo4658f792006-03-22 21:07:03 +09001771
Tejun Heocc0680a2007-08-06 18:36:23 +09001772 ata_tf_init(link->device, &tf);
Tejun Heo4658f792006-03-22 21:07:03 +09001773
1774 /* issue the first D2H Register FIS */
Tejun Heo2cbb79e2007-07-16 14:29:38 +09001775 msecs = 0;
1776 now = jiffies;
1777 if (time_after(now, deadline))
1778 msecs = jiffies_to_msecs(deadline - now);
1779
Tejun Heo4658f792006-03-22 21:07:03 +09001780 tf.ctl |= ATA_SRST;
Tejun Heoa9cf5e82007-07-16 14:29:39 +09001781 if (ahci_exec_polled_cmd(ap, pmp, &tf, 0,
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001782 AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs)) {
Tejun Heo4658f792006-03-22 21:07:03 +09001783 rc = -EIO;
1784 reason = "1st FIS failed";
1785 goto fail;
1786 }
1787
1788 /* spec says at least 5us, but be generous and sleep for 1ms */
1789 msleep(1);
1790
1791 /* issue the second D2H Register FIS */
Tejun Heo4658f792006-03-22 21:07:03 +09001792 tf.ctl &= ~ATA_SRST;
Tejun Heoa9cf5e82007-07-16 14:29:39 +09001793 ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
Tejun Heo4658f792006-03-22 21:07:03 +09001794
Tejun Heo705e76b2008-04-07 22:47:19 +09001795 /* wait for link to become ready */
Shane Huangbd172432008-06-10 15:52:04 +08001796 rc = ata_wait_after_reset(link, deadline, check_ready);
Tejun Heo55946392009-08-04 14:30:08 +09001797 if (rc == -EBUSY && hpriv->flags & AHCI_HFLAG_SRST_TOUT_IS_OFFLINE) {
1798 /*
1799 * Workaround for cases where link online status can't
1800 * be trusted. Treat device readiness timeout as link
1801 * offline.
1802 */
1803 ata_link_printk(link, KERN_INFO,
1804 "device not ready, treating as offline\n");
1805 *class = ATA_DEV_NONE;
1806 } else if (rc) {
1807 /* link occupied, -ENODEV too is an error */
Tejun Heo9b893912007-02-02 16:50:52 +09001808 reason = "device not ready";
1809 goto fail;
Tejun Heo55946392009-08-04 14:30:08 +09001810 } else
1811 *class = ahci_dev_classify(ap);
Tejun Heo4658f792006-03-22 21:07:03 +09001812
1813 DPRINTK("EXIT, class=%u\n", *class);
1814 return 0;
1815
Tejun Heo4658f792006-03-22 21:07:03 +09001816 fail:
Tejun Heocc0680a2007-08-06 18:36:23 +09001817 ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
Tejun Heo4658f792006-03-22 21:07:03 +09001818 return rc;
1819}
1820
Shane Huangbd172432008-06-10 15:52:04 +08001821static int ahci_check_ready(struct ata_link *link)
1822{
1823 void __iomem *port_mmio = ahci_port_base(link->ap);
1824 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1825
1826 return ata_check_ready(status);
1827}
1828
1829static int ahci_softreset(struct ata_link *link, unsigned int *class,
1830 unsigned long deadline)
1831{
1832 int pmp = sata_srst_pmp(link);
1833
1834 DPRINTK("ENTER\n");
1835
1836 return ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
1837}
1838
1839static int ahci_sb600_check_ready(struct ata_link *link)
1840{
1841 void __iomem *port_mmio = ahci_port_base(link->ap);
1842 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1843 u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
1844
1845 /*
1846 * There is no need to check TFDATA if BAD PMP is found due to HW bug,
1847 * which can save timeout delay.
1848 */
1849 if (irq_status & PORT_IRQ_BAD_PMP)
1850 return -EIO;
1851
1852 return ata_check_ready(status);
1853}
1854
1855static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
1856 unsigned long deadline)
1857{
1858 struct ata_port *ap = link->ap;
1859 void __iomem *port_mmio = ahci_port_base(ap);
1860 int pmp = sata_srst_pmp(link);
1861 int rc;
1862 u32 irq_sts;
1863
1864 DPRINTK("ENTER\n");
1865
1866 rc = ahci_do_softreset(link, class, pmp, deadline,
1867 ahci_sb600_check_ready);
1868
1869 /*
1870 * Soft reset fails on some ATI chips with IPMS set when PMP
1871 * is enabled but SATA HDD/ODD is connected to SATA port,
1872 * do soft reset again to port 0.
1873 */
1874 if (rc == -EIO) {
1875 irq_sts = readl(port_mmio + PORT_IRQ_STAT);
1876 if (irq_sts & PORT_IRQ_BAD_PMP) {
1877 ata_link_printk(link, KERN_WARNING,
Shane Huangb6931c12009-08-05 10:10:41 +08001878 "applying SB600 PMP SRST workaround "
1879 "and retrying\n");
Shane Huangbd172432008-06-10 15:52:04 +08001880 rc = ahci_do_softreset(link, class, 0, deadline,
1881 ahci_check_ready);
1882 }
1883 }
1884
1885 return rc;
1886}
1887
Tejun Heocc0680a2007-08-06 18:36:23 +09001888static int ahci_hardreset(struct ata_link *link, unsigned int *class,
Tejun Heod4b2bab2007-02-02 16:50:52 +09001889 unsigned long deadline)
Tejun Heo422b7592005-12-19 22:37:17 +09001890{
Tejun Heo9dadd452008-04-07 22:47:19 +09001891 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
Tejun Heocc0680a2007-08-06 18:36:23 +09001892 struct ata_port *ap = link->ap;
Tejun Heo42969712006-05-31 18:28:18 +09001893 struct ahci_port_priv *pp = ap->private_data;
1894 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1895 struct ata_taskfile tf;
Tejun Heo9dadd452008-04-07 22:47:19 +09001896 bool online;
Tejun Heo4bd00f62006-02-11 16:26:02 +09001897 int rc;
1898
1899 DPRINTK("ENTER\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900
Tejun Heo4447d352007-04-17 23:44:08 +09001901 ahci_stop_engine(ap);
Tejun Heo42969712006-05-31 18:28:18 +09001902
1903 /* clear D2H reception area to properly wait for D2H FIS */
Tejun Heocc0680a2007-08-06 18:36:23 +09001904 ata_tf_init(link->device, &tf);
Tejun Heodfd7a3d2007-01-26 15:37:20 +09001905 tf.command = 0x80;
Tejun Heo99771262007-07-16 14:29:38 +09001906 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
Tejun Heo42969712006-05-31 18:28:18 +09001907
Tejun Heo9dadd452008-04-07 22:47:19 +09001908 rc = sata_link_hardreset(link, timing, deadline, &online,
1909 ahci_check_ready);
Tejun Heo42969712006-05-31 18:28:18 +09001910
Tejun Heo4447d352007-04-17 23:44:08 +09001911 ahci_start_engine(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
Tejun Heo9dadd452008-04-07 22:47:19 +09001913 if (online)
Tejun Heo4bd00f62006-02-11 16:26:02 +09001914 *class = ahci_dev_classify(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915
Tejun Heo4bd00f62006-02-11 16:26:02 +09001916 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
1917 return rc;
1918}
1919
Tejun Heocc0680a2007-08-06 18:36:23 +09001920static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
Tejun Heod4b2bab2007-02-02 16:50:52 +09001921 unsigned long deadline)
Tejun Heoad616ff2006-11-01 18:00:24 +09001922{
Tejun Heocc0680a2007-08-06 18:36:23 +09001923 struct ata_port *ap = link->ap;
Tejun Heo9dadd452008-04-07 22:47:19 +09001924 bool online;
Tejun Heoad616ff2006-11-01 18:00:24 +09001925 int rc;
1926
1927 DPRINTK("ENTER\n");
1928
Tejun Heo4447d352007-04-17 23:44:08 +09001929 ahci_stop_engine(ap);
Tejun Heoad616ff2006-11-01 18:00:24 +09001930
Tejun Heocc0680a2007-08-06 18:36:23 +09001931 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
Tejun Heo9dadd452008-04-07 22:47:19 +09001932 deadline, &online, NULL);
Tejun Heoad616ff2006-11-01 18:00:24 +09001933
Tejun Heo4447d352007-04-17 23:44:08 +09001934 ahci_start_engine(ap);
Tejun Heoad616ff2006-11-01 18:00:24 +09001935
1936 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
1937
1938 /* vt8251 doesn't clear BSY on signature FIS reception,
1939 * request follow-up softreset.
1940 */
Tejun Heo9dadd452008-04-07 22:47:19 +09001941 return online ? -EAGAIN : rc;
Tejun Heoad616ff2006-11-01 18:00:24 +09001942}
1943
Tejun Heoedc93052007-10-25 14:59:16 +09001944static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
1945 unsigned long deadline)
1946{
1947 struct ata_port *ap = link->ap;
1948 struct ahci_port_priv *pp = ap->private_data;
1949 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1950 struct ata_taskfile tf;
Tejun Heo9dadd452008-04-07 22:47:19 +09001951 bool online;
Tejun Heoedc93052007-10-25 14:59:16 +09001952 int rc;
1953
1954 ahci_stop_engine(ap);
1955
1956 /* clear D2H reception area to properly wait for D2H FIS */
1957 ata_tf_init(link->device, &tf);
1958 tf.command = 0x80;
1959 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
1960
1961 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
Tejun Heo9dadd452008-04-07 22:47:19 +09001962 deadline, &online, NULL);
Tejun Heoedc93052007-10-25 14:59:16 +09001963
1964 ahci_start_engine(ap);
1965
Tejun Heoedc93052007-10-25 14:59:16 +09001966 /* The pseudo configuration device on SIMG4726 attached to
1967 * ASUS P5W-DH Deluxe doesn't send signature FIS after
1968 * hardreset if no device is attached to the first downstream
1969 * port && the pseudo device locks up on SRST w/ PMP==0. To
1970 * work around this, wait for !BSY only briefly. If BSY isn't
1971 * cleared, perform CLO and proceed to IDENTIFY (achieved by
1972 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
1973 *
1974 * Wait for two seconds. Devices attached to downstream port
1975 * which can't process the following IDENTIFY after this will
1976 * have to be reset again. For most cases, this should
1977 * suffice while making probing snappish enough.
1978 */
Tejun Heo9dadd452008-04-07 22:47:19 +09001979 if (online) {
1980 rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
1981 ahci_check_ready);
1982 if (rc)
Shane Huang78d5ae32009-08-07 15:05:52 +08001983 ahci_kick_engine(ap);
Tejun Heo9dadd452008-04-07 22:47:19 +09001984 }
Tejun Heo9dadd452008-04-07 22:47:19 +09001985 return rc;
Tejun Heoedc93052007-10-25 14:59:16 +09001986}
1987
Tejun Heocc0680a2007-08-06 18:36:23 +09001988static void ahci_postreset(struct ata_link *link, unsigned int *class)
Tejun Heo4bd00f62006-02-11 16:26:02 +09001989{
Tejun Heocc0680a2007-08-06 18:36:23 +09001990 struct ata_port *ap = link->ap;
Tejun Heo4447d352007-04-17 23:44:08 +09001991 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo4bd00f62006-02-11 16:26:02 +09001992 u32 new_tmp, tmp;
1993
Tejun Heo203c75b2008-04-07 22:47:18 +09001994 ata_std_postreset(link, class);
Jeff Garzik02eaa662005-11-12 01:32:19 -05001995
1996 /* Make sure port's ATAPI bit is set appropriately */
1997 new_tmp = tmp = readl(port_mmio + PORT_CMD);
Tejun Heo4bd00f62006-02-11 16:26:02 +09001998 if (*class == ATA_DEV_ATAPI)
Jeff Garzik02eaa662005-11-12 01:32:19 -05001999 new_tmp |= PORT_CMD_ATAPI;
2000 else
2001 new_tmp &= ~PORT_CMD_ATAPI;
2002 if (new_tmp != tmp) {
2003 writel(new_tmp, port_mmio + PORT_CMD);
2004 readl(port_mmio + PORT_CMD); /* flush */
2005 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006}
2007
Tejun Heo12fad3f2006-05-15 21:03:55 +09002008static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009{
Jeff Garzikcedc9a42005-10-05 07:13:30 -04002010 struct scatterlist *sg;
Tejun Heoff2aeb12007-12-05 16:43:11 +09002011 struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
2012 unsigned int si;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
2014 VPRINTK("ENTER\n");
2015
2016 /*
2017 * Next, the S/G list.
2018 */
Tejun Heoff2aeb12007-12-05 16:43:11 +09002019 for_each_sg(qc->sg, sg, qc->n_elem, si) {
Jeff Garzikcedc9a42005-10-05 07:13:30 -04002020 dma_addr_t addr = sg_dma_address(sg);
2021 u32 sg_len = sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022
Tejun Heoff2aeb12007-12-05 16:43:11 +09002023 ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
2024 ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
2025 ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 }
Jeff Garzik828d09d2005-11-12 01:27:07 -05002027
Tejun Heoff2aeb12007-12-05 16:43:11 +09002028 return si;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029}
2030
2031static void ahci_qc_prep(struct ata_queued_cmd *qc)
2032{
Jeff Garzika0ea7322005-06-04 01:13:15 -04002033 struct ata_port *ap = qc->ap;
2034 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo405e66b2007-11-27 19:28:53 +09002035 int is_atapi = ata_is_atapi(qc->tf.protocol);
Tejun Heo12fad3f2006-05-15 21:03:55 +09002036 void *cmd_tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 u32 opts;
2038 const u32 cmd_fis_len = 5; /* five dwords */
Jeff Garzik828d09d2005-11-12 01:27:07 -05002039 unsigned int n_elem;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040
2041 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 * Fill in command table information. First, the header,
2043 * a SATA Register - Host to Device command FIS.
2044 */
Tejun Heo12fad3f2006-05-15 21:03:55 +09002045 cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
2046
Tejun Heo7d50b602007-09-23 13:19:54 +09002047 ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl);
Tejun Heocc9278e2006-02-10 17:25:47 +09002048 if (is_atapi) {
Tejun Heo12fad3f2006-05-15 21:03:55 +09002049 memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
2050 memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
Jeff Garzika0ea7322005-06-04 01:13:15 -04002051 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052
Tejun Heocc9278e2006-02-10 17:25:47 +09002053 n_elem = 0;
2054 if (qc->flags & ATA_QCFLAG_DMAMAP)
Tejun Heo12fad3f2006-05-15 21:03:55 +09002055 n_elem = ahci_fill_sg(qc, cmd_tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056
Tejun Heocc9278e2006-02-10 17:25:47 +09002057 /*
2058 * Fill in command slot information.
2059 */
Tejun Heo7d50b602007-09-23 13:19:54 +09002060 opts = cmd_fis_len | n_elem << 16 | (qc->dev->link->pmp << 12);
Tejun Heocc9278e2006-02-10 17:25:47 +09002061 if (qc->tf.flags & ATA_TFLAG_WRITE)
2062 opts |= AHCI_CMD_WRITE;
2063 if (is_atapi)
Tejun Heo4b10e552006-03-12 11:25:27 +09002064 opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
Jeff Garzik828d09d2005-11-12 01:27:07 -05002065
Tejun Heo12fad3f2006-05-15 21:03:55 +09002066 ahci_fill_cmd_slot(pp, qc->tag, opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067}
2068
Tejun Heo78cd52d2006-05-15 20:58:29 +09002069static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070{
Tejun Heo417a1a62007-09-23 13:19:55 +09002071 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002072 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002073 struct ata_eh_info *host_ehi = &ap->link.eh_info;
2074 struct ata_link *link = NULL;
2075 struct ata_queued_cmd *active_qc;
2076 struct ata_eh_info *active_ehi;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002077 u32 serror;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078
Tejun Heo7d50b602007-09-23 13:19:54 +09002079 /* determine active link */
Tejun Heo1eca4362008-11-03 20:03:17 +09002080 ata_for_each_link(link, ap, EDGE)
Tejun Heo7d50b602007-09-23 13:19:54 +09002081 if (ata_link_active(link))
2082 break;
2083 if (!link)
2084 link = &ap->link;
2085
2086 active_qc = ata_qc_from_tag(ap, link->active_tag);
2087 active_ehi = &link->eh_info;
2088
2089 /* record irq stat */
2090 ata_ehi_clear_desc(host_ehi);
2091 ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);
Jeff Garzik9f68a242005-11-15 14:03:47 -05002092
Tejun Heo78cd52d2006-05-15 20:58:29 +09002093 /* AHCI needs SError cleared; otherwise, it might lock up */
Tejun Heo82ef04f2008-07-31 17:02:40 +09002094 ahci_scr_read(&ap->link, SCR_ERROR, &serror);
2095 ahci_scr_write(&ap->link, SCR_ERROR, serror);
Tejun Heo7d50b602007-09-23 13:19:54 +09002096 host_ehi->serror |= serror;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
Tejun Heo41669552006-11-29 11:33:14 +09002098 /* some controllers set IRQ_IF_ERR on device errors, ignore it */
Tejun Heo417a1a62007-09-23 13:19:55 +09002099 if (hpriv->flags & AHCI_HFLAG_IGN_IRQ_IF_ERR)
Tejun Heo41669552006-11-29 11:33:14 +09002100 irq_stat &= ~PORT_IRQ_IF_ERR;
2101
Conke Hu55a61602007-03-27 18:33:05 +08002102 if (irq_stat & PORT_IRQ_TF_ERR) {
Tejun Heo7d50b602007-09-23 13:19:54 +09002103 /* If qc is active, charge it; otherwise, the active
2104 * link. There's no active qc on NCQ errors. It will
2105 * be determined by EH by reading log page 10h.
2106 */
2107 if (active_qc)
2108 active_qc->err_mask |= AC_ERR_DEV;
2109 else
2110 active_ehi->err_mask |= AC_ERR_DEV;
2111
Tejun Heo417a1a62007-09-23 13:19:55 +09002112 if (hpriv->flags & AHCI_HFLAG_IGN_SERR_INTERNAL)
Tejun Heo7d50b602007-09-23 13:19:54 +09002113 host_ehi->serror &= ~SERR_INTERNAL;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115
Tejun Heo78cd52d2006-05-15 20:58:29 +09002116 if (irq_stat & PORT_IRQ_UNK_FIS) {
2117 u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118
Tejun Heo7d50b602007-09-23 13:19:54 +09002119 active_ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002120 active_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002121 ata_ehi_push_desc(active_ehi,
2122 "unknown FIS %08x %08x %08x %08x" ,
Tejun Heo78cd52d2006-05-15 20:58:29 +09002123 unk[0], unk[1], unk[2], unk[3]);
2124 }
Jeff Garzikb8f61532005-08-25 22:01:20 -04002125
Tejun Heo071f44b2008-04-07 22:47:22 +09002126 if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
Tejun Heo7d50b602007-09-23 13:19:54 +09002127 active_ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002128 active_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002129 ata_ehi_push_desc(active_ehi, "incorrect PMP");
2130 }
Tejun Heo78cd52d2006-05-15 20:58:29 +09002131
Tejun Heo7d50b602007-09-23 13:19:54 +09002132 if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
2133 host_ehi->err_mask |= AC_ERR_HOST_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09002134 host_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002135 ata_ehi_push_desc(host_ehi, "host bus error");
2136 }
2137
2138 if (irq_stat & PORT_IRQ_IF_ERR) {
2139 host_ehi->err_mask |= AC_ERR_ATA_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09002140 host_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002141 ata_ehi_push_desc(host_ehi, "interface fatal error");
2142 }
2143
2144 if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
2145 ata_ehi_hotplugged(host_ehi);
2146 ata_ehi_push_desc(host_ehi, "%s",
2147 irq_stat & PORT_IRQ_CONNECT ?
2148 "connection status changed" : "PHY RDY changed");
2149 }
2150
2151 /* okay, let's hand over to EH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152
Tejun Heo78cd52d2006-05-15 20:58:29 +09002153 if (irq_stat & PORT_IRQ_FREEZE)
2154 ata_port_freeze(ap);
2155 else
2156 ata_port_abort(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157}
2158
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002159static void ahci_port_intr(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160{
Tejun Heo350756f2008-04-07 22:47:21 +09002161 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo9af5c9c2007-08-06 18:36:22 +09002162 struct ata_eh_info *ehi = &ap->link.eh_info;
Tejun Heo0291f952007-01-25 19:16:28 +09002163 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo5f226c62007-10-09 15:02:23 +09002164 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heob06ce3e2007-10-09 15:06:48 +09002165 int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
Tejun Heo12fad3f2006-05-15 21:03:55 +09002166 u32 status, qc_active;
Tejun Heo459ad682007-12-07 12:46:23 +09002167 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
2169 status = readl(port_mmio + PORT_IRQ_STAT);
2170 writel(status, port_mmio + PORT_IRQ_STAT);
2171
Tejun Heob06ce3e2007-10-09 15:06:48 +09002172 /* ignore BAD_PMP while resetting */
2173 if (unlikely(resetting))
2174 status &= ~PORT_IRQ_BAD_PMP;
2175
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002176 /* If we are getting PhyRdy, this is
2177 * just a power state change, we should
2178 * clear out this, plus the PhyRdy/Comm
2179 * Wake bits from Serror
2180 */
2181 if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
2182 (status & PORT_IRQ_PHYRDY)) {
2183 status &= ~PORT_IRQ_PHYRDY;
Tejun Heo82ef04f2008-07-31 17:02:40 +09002184 ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002185 }
2186
Tejun Heo78cd52d2006-05-15 20:58:29 +09002187 if (unlikely(status & PORT_IRQ_ERROR)) {
2188 ahci_error_intr(ap, status);
2189 return;
2190 }
2191
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002192 if (status & PORT_IRQ_SDB_FIS) {
Tejun Heo5f226c62007-10-09 15:02:23 +09002193 /* If SNotification is available, leave notification
2194 * handling to sata_async_notification(). If not,
2195 * emulate it by snooping SDB FIS RX area.
2196 *
2197 * Snooping FIS RX area is probably cheaper than
2198 * poking SNotification but some constrollers which
2199 * implement SNotification, ICH9 for example, don't
2200 * store AN SDB FIS into receive area.
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002201 */
Tejun Heo5f226c62007-10-09 15:02:23 +09002202 if (hpriv->cap & HOST_CAP_SNTF)
Tejun Heo7d77b242007-09-23 13:14:13 +09002203 sata_async_notification(ap);
Tejun Heo5f226c62007-10-09 15:02:23 +09002204 else {
2205 /* If the 'N' bit in word 0 of the FIS is set,
2206 * we just received asynchronous notification.
2207 * Tell libata about it.
2208 */
2209 const __le32 *f = pp->rx_fis + RX_FIS_SDB;
2210 u32 f0 = le32_to_cpu(f[0]);
2211
2212 if (f0 & (1 << 15))
2213 sata_async_notification(ap);
2214 }
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002215 }
2216
Tejun Heo7d50b602007-09-23 13:19:54 +09002217 /* pp->active_link is valid iff any command is in flight */
2218 if (ap->qc_active && pp->active_link->sactive)
Tejun Heo12fad3f2006-05-15 21:03:55 +09002219 qc_active = readl(port_mmio + PORT_SCR_ACT);
2220 else
2221 qc_active = readl(port_mmio + PORT_CMD_ISSUE);
2222
Tejun Heo79f97da2008-04-07 22:47:20 +09002223 rc = ata_qc_complete_multiple(ap, qc_active);
Tejun Heob06ce3e2007-10-09 15:06:48 +09002224
Tejun Heo459ad682007-12-07 12:46:23 +09002225 /* while resetting, invalid completions are expected */
2226 if (unlikely(rc < 0 && !resetting)) {
Tejun Heo12fad3f2006-05-15 21:03:55 +09002227 ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002228 ehi->action |= ATA_EH_RESET;
Tejun Heo12fad3f2006-05-15 21:03:55 +09002229 ata_port_freeze(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231}
2232
David Howells7d12e782006-10-05 14:55:46 +01002233static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234{
Jeff Garzikcca39742006-08-24 03:19:22 -04002235 struct ata_host *host = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 struct ahci_host_priv *hpriv;
2237 unsigned int i, handled = 0;
Jeff Garzikea6ba102005-08-30 05:18:18 -04002238 void __iomem *mmio;
Tejun Heod28f87a2008-07-05 13:10:50 +09002239 u32 irq_stat, irq_masked;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
2241 VPRINTK("ENTER\n");
2242
Jeff Garzikcca39742006-08-24 03:19:22 -04002243 hpriv = host->private_data;
Tejun Heo0d5ff562007-02-01 15:06:36 +09002244 mmio = host->iomap[AHCI_PCI_BAR];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
2246 /* sigh. 0xffffffff is a valid return from h/w */
2247 irq_stat = readl(mmio + HOST_IRQ_STAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 if (!irq_stat)
2249 return IRQ_NONE;
2250
Tejun Heod28f87a2008-07-05 13:10:50 +09002251 irq_masked = irq_stat & hpriv->port_map;
2252
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002253 spin_lock(&host->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002255 for (i = 0; i < host->n_ports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 struct ata_port *ap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
Tejun Heod28f87a2008-07-05 13:10:50 +09002258 if (!(irq_masked & (1 << i)))
Jeff Garzik67846b32005-10-05 02:58:32 -04002259 continue;
2260
Jeff Garzikcca39742006-08-24 03:19:22 -04002261 ap = host->ports[i];
Jeff Garzik67846b32005-10-05 02:58:32 -04002262 if (ap) {
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002263 ahci_port_intr(ap);
Jeff Garzik67846b32005-10-05 02:58:32 -04002264 VPRINTK("port %u\n", i);
2265 } else {
2266 VPRINTK("port %u (no irq)\n", i);
Tejun Heo6971ed12006-03-11 12:47:54 +09002267 if (ata_ratelimit())
Jeff Garzikcca39742006-08-24 03:19:22 -04002268 dev_printk(KERN_WARNING, host->dev,
Jeff Garzika9524a72005-10-30 14:39:11 -05002269 "interrupt on disabled port %u\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 }
Jeff Garzik67846b32005-10-05 02:58:32 -04002271
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 handled = 1;
2273 }
2274
Tejun Heod28f87a2008-07-05 13:10:50 +09002275 /* HOST_IRQ_STAT behaves as level triggered latch meaning that
2276 * it should be cleared after all the port events are cleared;
2277 * otherwise, it will raise a spurious interrupt after each
2278 * valid one. Please read section 10.6.2 of ahci 1.1 for more
2279 * information.
2280 *
2281 * Also, use the unmasked value to clear interrupt as spurious
2282 * pending event on a dummy port might cause screaming IRQ.
2283 */
Tejun Heoea0c62f2008-06-28 01:49:02 +09002284 writel(irq_stat, mmio + HOST_IRQ_STAT);
2285
Jeff Garzikcca39742006-08-24 03:19:22 -04002286 spin_unlock(&host->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287
2288 VPRINTK("EXIT\n");
2289
2290 return IRQ_RETVAL(handled);
2291}
2292
Tejun Heo9a3d9eb2006-01-23 13:09:36 +09002293static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294{
2295 struct ata_port *ap = qc->ap;
Tejun Heo4447d352007-04-17 23:44:08 +09002296 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo7d50b602007-09-23 13:19:54 +09002297 struct ahci_port_priv *pp = ap->private_data;
2298
2299 /* Keep track of the currently active link. It will be used
2300 * in completion path to determine whether NCQ phase is in
2301 * progress.
2302 */
2303 pp->active_link = qc->dev->link;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304
Tejun Heo12fad3f2006-05-15 21:03:55 +09002305 if (qc->tf.protocol == ATA_PROT_NCQ)
2306 writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
2307 writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002309 ahci_sw_activity(qc->dev->link);
2310
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 return 0;
2312}
2313
Tejun Heo4c9bf4e2008-04-07 22:47:20 +09002314static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
2315{
2316 struct ahci_port_priv *pp = qc->ap->private_data;
2317 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
2318
2319 ata_tf_from_fis(d2h_fis, &qc->result_tf);
2320 return true;
2321}
2322
Tejun Heo78cd52d2006-05-15 20:58:29 +09002323static void ahci_freeze(struct ata_port *ap)
2324{
Tejun Heo4447d352007-04-17 23:44:08 +09002325 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002326
2327 /* turn IRQ off */
2328 writel(0, port_mmio + PORT_IRQ_MASK);
2329}
2330
2331static void ahci_thaw(struct ata_port *ap)
2332{
Tejun Heo0d5ff562007-02-01 15:06:36 +09002333 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
Tejun Heo4447d352007-04-17 23:44:08 +09002334 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002335 u32 tmp;
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002336 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002337
2338 /* clear IRQ */
2339 tmp = readl(port_mmio + PORT_IRQ_STAT);
2340 writel(tmp, port_mmio + PORT_IRQ_STAT);
Tejun Heoa7187282007-01-27 11:04:26 +09002341 writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002342
Tejun Heo1c954a42007-10-09 15:01:37 +09002343 /* turn IRQ back on */
2344 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002345}
2346
2347static void ahci_error_handler(struct ata_port *ap)
2348{
Tejun Heob51e9e52006-06-29 01:29:30 +09002349 if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
Tejun Heo78cd52d2006-05-15 20:58:29 +09002350 /* restart engine */
Tejun Heo4447d352007-04-17 23:44:08 +09002351 ahci_stop_engine(ap);
2352 ahci_start_engine(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002353 }
2354
Tejun Heoa1efdab2008-03-25 12:22:50 +09002355 sata_pmp_error_handler(ap);
Tejun Heoedc93052007-10-25 14:59:16 +09002356}
2357
Tejun Heo78cd52d2006-05-15 20:58:29 +09002358static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
2359{
2360 struct ata_port *ap = qc->ap;
2361
Tejun Heod2e75df2007-07-16 14:29:39 +09002362 /* make DMA engine forget about the failed command */
2363 if (qc->flags & ATA_QCFLAG_FAILED)
Shane Huang78d5ae32009-08-07 15:05:52 +08002364 ahci_kick_engine(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002365}
2366
Tejun Heo7d50b602007-09-23 13:19:54 +09002367static void ahci_pmp_attach(struct ata_port *ap)
2368{
2369 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo1c954a42007-10-09 15:01:37 +09002370 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002371 u32 cmd;
2372
2373 cmd = readl(port_mmio + PORT_CMD);
2374 cmd |= PORT_CMD_PMP;
2375 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo1c954a42007-10-09 15:01:37 +09002376
2377 pp->intr_mask |= PORT_IRQ_BAD_PMP;
2378 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo7d50b602007-09-23 13:19:54 +09002379}
2380
2381static void ahci_pmp_detach(struct ata_port *ap)
2382{
2383 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo1c954a42007-10-09 15:01:37 +09002384 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002385 u32 cmd;
2386
2387 cmd = readl(port_mmio + PORT_CMD);
2388 cmd &= ~PORT_CMD_PMP;
2389 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo1c954a42007-10-09 15:01:37 +09002390
2391 pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
2392 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo7d50b602007-09-23 13:19:54 +09002393}
2394
Alexey Dobriyan028a2592007-07-17 23:48:48 +04002395static int ahci_port_resume(struct ata_port *ap)
2396{
2397 ahci_power_up(ap);
2398 ahci_start_port(ap);
2399
Tejun Heo071f44b2008-04-07 22:47:22 +09002400 if (sata_pmp_attached(ap))
Tejun Heo7d50b602007-09-23 13:19:54 +09002401 ahci_pmp_attach(ap);
2402 else
2403 ahci_pmp_detach(ap);
2404
Alexey Dobriyan028a2592007-07-17 23:48:48 +04002405 return 0;
2406}
2407
Tejun Heo438ac6d2007-03-02 17:31:26 +09002408#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +09002409static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
2410{
Tejun Heoc1332872006-07-26 15:59:26 +09002411 const char *emsg = NULL;
2412 int rc;
2413
Tejun Heo4447d352007-04-17 23:44:08 +09002414 rc = ahci_deinit_port(ap, &emsg);
Tejun Heo8e16f942006-11-20 15:42:36 +09002415 if (rc == 0)
Tejun Heo4447d352007-04-17 23:44:08 +09002416 ahci_power_down(ap);
Tejun Heo8e16f942006-11-20 15:42:36 +09002417 else {
Tejun Heoc1332872006-07-26 15:59:26 +09002418 ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002419 ahci_start_port(ap);
Tejun Heoc1332872006-07-26 15:59:26 +09002420 }
2421
2422 return rc;
2423}
2424
Tejun Heoc1332872006-07-26 15:59:26 +09002425static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
2426{
Jeff Garzikcca39742006-08-24 03:19:22 -04002427 struct ata_host *host = dev_get_drvdata(&pdev->dev);
Tejun Heo9b10ae82009-05-30 20:50:12 +09002428 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo0d5ff562007-02-01 15:06:36 +09002429 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Tejun Heoc1332872006-07-26 15:59:26 +09002430 u32 ctl;
2431
Tejun Heo9b10ae82009-05-30 20:50:12 +09002432 if (mesg.event & PM_EVENT_SUSPEND &&
2433 hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
2434 dev_printk(KERN_ERR, &pdev->dev,
2435 "BIOS update required for suspend/resume\n");
2436 return -EIO;
2437 }
2438
Rafael J. Wysocki3a2d5b72008-02-23 19:13:25 +01002439 if (mesg.event & PM_EVENT_SLEEP) {
Tejun Heoc1332872006-07-26 15:59:26 +09002440 /* AHCI spec rev1.1 section 8.3.3:
2441 * Software must disable interrupts prior to requesting a
2442 * transition of the HBA to D3 state.
2443 */
2444 ctl = readl(mmio + HOST_CTL);
2445 ctl &= ~HOST_IRQ_EN;
2446 writel(ctl, mmio + HOST_CTL);
2447 readl(mmio + HOST_CTL); /* flush */
2448 }
2449
2450 return ata_pci_device_suspend(pdev, mesg);
2451}
2452
2453static int ahci_pci_device_resume(struct pci_dev *pdev)
2454{
Jeff Garzikcca39742006-08-24 03:19:22 -04002455 struct ata_host *host = dev_get_drvdata(&pdev->dev);
Tejun Heoc1332872006-07-26 15:59:26 +09002456 int rc;
2457
Tejun Heo553c4aa2006-12-26 19:39:50 +09002458 rc = ata_pci_device_do_resume(pdev);
2459 if (rc)
2460 return rc;
Tejun Heoc1332872006-07-26 15:59:26 +09002461
2462 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
Tejun Heo4447d352007-04-17 23:44:08 +09002463 rc = ahci_reset_controller(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002464 if (rc)
2465 return rc;
2466
Tejun Heo4447d352007-04-17 23:44:08 +09002467 ahci_init_controller(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002468 }
2469
Jeff Garzikcca39742006-08-24 03:19:22 -04002470 ata_host_resume(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002471
2472 return 0;
2473}
Tejun Heo438ac6d2007-03-02 17:31:26 +09002474#endif
Tejun Heoc1332872006-07-26 15:59:26 +09002475
Tejun Heo254950c2006-07-26 15:59:25 +09002476static int ahci_port_start(struct ata_port *ap)
2477{
Jeff Garzikcca39742006-08-24 03:19:22 -04002478 struct device *dev = ap->host->dev;
Tejun Heo254950c2006-07-26 15:59:25 +09002479 struct ahci_port_priv *pp;
Tejun Heo254950c2006-07-26 15:59:25 +09002480 void *mem;
2481 dma_addr_t mem_dma;
Tejun Heo254950c2006-07-26 15:59:25 +09002482
Tejun Heo24dc5f32007-01-20 16:00:28 +09002483 pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
Tejun Heo254950c2006-07-26 15:59:25 +09002484 if (!pp)
2485 return -ENOMEM;
Tejun Heo254950c2006-07-26 15:59:25 +09002486
Tejun Heo24dc5f32007-01-20 16:00:28 +09002487 mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
2488 GFP_KERNEL);
2489 if (!mem)
Tejun Heo254950c2006-07-26 15:59:25 +09002490 return -ENOMEM;
Tejun Heo254950c2006-07-26 15:59:25 +09002491 memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
2492
2493 /*
2494 * First item in chunk of DMA memory: 32-slot command table,
2495 * 32 bytes each in size
2496 */
2497 pp->cmd_slot = mem;
2498 pp->cmd_slot_dma = mem_dma;
2499
2500 mem += AHCI_CMD_SLOT_SZ;
2501 mem_dma += AHCI_CMD_SLOT_SZ;
2502
2503 /*
2504 * Second item: Received-FIS area
2505 */
2506 pp->rx_fis = mem;
2507 pp->rx_fis_dma = mem_dma;
2508
2509 mem += AHCI_RX_FIS_SZ;
2510 mem_dma += AHCI_RX_FIS_SZ;
2511
2512 /*
2513 * Third item: data area for storing a single command
2514 * and its scatter-gather table
2515 */
2516 pp->cmd_tbl = mem;
2517 pp->cmd_tbl_dma = mem_dma;
2518
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002519 /*
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002520 * Save off initial list of interrupts to be enabled.
2521 * This could be changed later
2522 */
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002523 pp->intr_mask = DEF_PORT_IRQ;
2524
Tejun Heo254950c2006-07-26 15:59:25 +09002525 ap->private_data = pp;
2526
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002527 /* engage engines, captain */
2528 return ahci_port_resume(ap);
Tejun Heo254950c2006-07-26 15:59:25 +09002529}
2530
2531static void ahci_port_stop(struct ata_port *ap)
2532{
Tejun Heo0be0aa92006-07-26 15:59:26 +09002533 const char *emsg = NULL;
2534 int rc;
Tejun Heo254950c2006-07-26 15:59:25 +09002535
Tejun Heo0be0aa92006-07-26 15:59:26 +09002536 /* de-initialize port */
Tejun Heo4447d352007-04-17 23:44:08 +09002537 rc = ahci_deinit_port(ap, &emsg);
Tejun Heo0be0aa92006-07-26 15:59:26 +09002538 if (rc)
2539 ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
Tejun Heo254950c2006-07-26 15:59:25 +09002540}
2541
Tejun Heo4447d352007-04-17 23:44:08 +09002542static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 if (using_dac &&
Yang Hongyang6a355282009-04-06 19:01:13 -07002547 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
2548 rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 if (rc) {
Yang Hongyang284901a2009-04-06 19:01:15 -07002550 rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002552 dev_printk(KERN_ERR, &pdev->dev,
2553 "64-bit DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 return rc;
2555 }
2556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 } else {
Yang Hongyang284901a2009-04-06 19:01:15 -07002558 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002560 dev_printk(KERN_ERR, &pdev->dev,
2561 "32-bit DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 return rc;
2563 }
Yang Hongyang284901a2009-04-06 19:01:15 -07002564 rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002566 dev_printk(KERN_ERR, &pdev->dev,
2567 "32-bit consistent DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 return rc;
2569 }
2570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 return 0;
2572}
2573
Tejun Heo4447d352007-04-17 23:44:08 +09002574static void ahci_print_info(struct ata_host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575{
Tejun Heo4447d352007-04-17 23:44:08 +09002576 struct ahci_host_priv *hpriv = host->private_data;
2577 struct pci_dev *pdev = to_pci_dev(host->dev);
2578 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Robert Hancock4c521c82009-09-20 17:02:31 -06002579 u32 vers, cap, cap2, impl, speed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 const char *speed_s;
2581 u16 cc;
2582 const char *scc_s;
2583
2584 vers = readl(mmio + HOST_VERSION);
2585 cap = hpriv->cap;
Robert Hancock4c521c82009-09-20 17:02:31 -06002586 cap2 = hpriv->cap2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 impl = hpriv->port_map;
2588
2589 speed = (cap >> 20) & 0xf;
2590 if (speed == 1)
2591 speed_s = "1.5";
2592 else if (speed == 2)
2593 speed_s = "3";
Shane Huang8522ee22008-12-30 11:00:37 +08002594 else if (speed == 3)
2595 speed_s = "6";
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 else
2597 speed_s = "?";
2598
2599 pci_read_config_word(pdev, 0x0a, &cc);
Conke Huc9f89472007-01-09 05:32:51 -05002600 if (cc == PCI_CLASS_STORAGE_IDE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 scc_s = "IDE";
Conke Huc9f89472007-01-09 05:32:51 -05002602 else if (cc == PCI_CLASS_STORAGE_SATA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 scc_s = "SATA";
Conke Huc9f89472007-01-09 05:32:51 -05002604 else if (cc == PCI_CLASS_STORAGE_RAID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 scc_s = "RAID";
2606 else
2607 scc_s = "unknown";
2608
Jeff Garzika9524a72005-10-30 14:39:11 -05002609 dev_printk(KERN_INFO, &pdev->dev,
2610 "AHCI %02x%02x.%02x%02x "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 "%u slots %u ports %s Gbps 0x%x impl %s mode\n"
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002612 ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002614 (vers >> 24) & 0xff,
2615 (vers >> 16) & 0xff,
2616 (vers >> 8) & 0xff,
2617 vers & 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618
2619 ((cap >> 8) & 0x1f) + 1,
2620 (cap & 0x1f) + 1,
2621 speed_s,
2622 impl,
2623 scc_s);
2624
Jeff Garzika9524a72005-10-30 14:39:11 -05002625 dev_printk(KERN_INFO, &pdev->dev,
2626 "flags: "
Tejun Heo203ef6c2007-07-16 14:29:40 +09002627 "%s%s%s%s%s%s%s"
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002628 "%s%s%s%s%s%s%s"
Robert Hancock4c521c82009-09-20 17:02:31 -06002629 "%s%s%s%s%s%s\n"
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002630 ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631
Robert Hancock4c521c82009-09-20 17:02:31 -06002632 cap & HOST_CAP_64 ? "64bit " : "",
2633 cap & HOST_CAP_NCQ ? "ncq " : "",
2634 cap & HOST_CAP_SNTF ? "sntf " : "",
2635 cap & HOST_CAP_MPS ? "ilck " : "",
2636 cap & HOST_CAP_SSS ? "stag " : "",
2637 cap & HOST_CAP_ALPM ? "pm " : "",
2638 cap & HOST_CAP_LED ? "led " : "",
2639 cap & HOST_CAP_CLO ? "clo " : "",
2640 cap & HOST_CAP_ONLY ? "only " : "",
2641 cap & HOST_CAP_PMP ? "pmp " : "",
2642 cap & HOST_CAP_FBS ? "fbs " : "",
2643 cap & HOST_CAP_PIO_MULTI ? "pio " : "",
2644 cap & HOST_CAP_SSC ? "slum " : "",
2645 cap & HOST_CAP_PART ? "part " : "",
2646 cap & HOST_CAP_CCC ? "ccc " : "",
2647 cap & HOST_CAP_EMS ? "ems " : "",
2648 cap & HOST_CAP_SXS ? "sxs " : "",
2649 cap2 & HOST_CAP2_APST ? "apst " : "",
2650 cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",
2651 cap2 & HOST_CAP2_BOH ? "boh " : ""
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 );
2653}
2654
Tejun Heoedc93052007-10-25 14:59:16 +09002655/* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
2656 * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't
2657 * support PMP and the 4726 either directly exports the device
2658 * attached to the first downstream port or acts as a hardware storage
2659 * controller and emulate a single ATA device (can be RAID 0/1 or some
2660 * other configuration).
2661 *
2662 * When there's no device attached to the first downstream port of the
2663 * 4726, "Config Disk" appears, which is a pseudo ATA device to
2664 * configure the 4726. However, ATA emulation of the device is very
2665 * lame. It doesn't send signature D2H Reg FIS after the initial
2666 * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
2667 *
2668 * The following function works around the problem by always using
2669 * hardreset on the port and not depending on receiving signature FIS
2670 * afterward. If signature FIS isn't received soon, ATA class is
2671 * assumed without follow-up softreset.
2672 */
2673static void ahci_p5wdh_workaround(struct ata_host *host)
2674{
2675 static struct dmi_system_id sysids[] = {
2676 {
2677 .ident = "P5W DH Deluxe",
2678 .matches = {
2679 DMI_MATCH(DMI_SYS_VENDOR,
2680 "ASUSTEK COMPUTER INC"),
2681 DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
2682 },
2683 },
2684 { }
2685 };
2686 struct pci_dev *pdev = to_pci_dev(host->dev);
2687
2688 if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
2689 dmi_check_system(sysids)) {
2690 struct ata_port *ap = host->ports[1];
2691
2692 dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
2693 "Deluxe on-board SIMG4726 workaround\n");
2694
2695 ap->ops = &ahci_p5wdh_ops;
2696 ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
2697 }
2698}
2699
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002700/* only some SB600 ahci controllers can do 64bit DMA */
2701static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
Shane Huang58a09b32009-05-27 15:04:43 +08002702{
2703 static const struct dmi_system_id sysids[] = {
Tejun Heo03d783b2009-08-16 21:04:02 +09002704 /*
2705 * The oldest version known to be broken is 0901 and
2706 * working is 1501 which was released on 2007-10-26.
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002707 * Enable 64bit DMA on 1501 and anything newer.
2708 *
Tejun Heo03d783b2009-08-16 21:04:02 +09002709 * Please read bko#9412 for more info.
2710 */
Shane Huang58a09b32009-05-27 15:04:43 +08002711 {
2712 .ident = "ASUS M2A-VM",
2713 .matches = {
2714 DMI_MATCH(DMI_BOARD_VENDOR,
2715 "ASUSTeK Computer INC."),
2716 DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
2717 },
Tejun Heo03d783b2009-08-16 21:04:02 +09002718 .driver_data = "20071026", /* yyyymmdd */
Shane Huang58a09b32009-05-27 15:04:43 +08002719 },
2720 { }
2721 };
Tejun Heo03d783b2009-08-16 21:04:02 +09002722 const struct dmi_system_id *match;
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002723 int year, month, date;
2724 char buf[9];
Shane Huang58a09b32009-05-27 15:04:43 +08002725
Tejun Heo03d783b2009-08-16 21:04:02 +09002726 match = dmi_first_match(sysids);
Shane Huang58a09b32009-05-27 15:04:43 +08002727 if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
Tejun Heo03d783b2009-08-16 21:04:02 +09002728 !match)
Shane Huang58a09b32009-05-27 15:04:43 +08002729 return false;
2730
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002731 dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
2732 snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
Shane Huang58a09b32009-05-27 15:04:43 +08002733
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002734 if (strcmp(buf, match->driver_data) >= 0) {
2735 dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n",
2736 match->ident);
2737 return true;
2738 } else {
Tejun Heo03d783b2009-08-16 21:04:02 +09002739 dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, "
2740 "forcing 32bit DMA, update BIOS\n", match->ident);
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002741 return false;
2742 }
Shane Huang58a09b32009-05-27 15:04:43 +08002743}
2744
Rafael J. Wysocki1fd68432009-01-19 20:57:36 +01002745static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
2746{
2747 static const struct dmi_system_id broken_systems[] = {
2748 {
2749 .ident = "HP Compaq nx6310",
2750 .matches = {
2751 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2752 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
2753 },
2754 /* PCI slot number of the controller */
2755 .driver_data = (void *)0x1FUL,
2756 },
Maciej Ruteckid2f9c062009-03-20 00:06:46 +01002757 {
2758 .ident = "HP Compaq 6720s",
2759 .matches = {
2760 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2761 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
2762 },
2763 /* PCI slot number of the controller */
2764 .driver_data = (void *)0x1FUL,
2765 },
Rafael J. Wysocki1fd68432009-01-19 20:57:36 +01002766
2767 { } /* terminate list */
2768 };
2769 const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
2770
2771 if (dmi) {
2772 unsigned long slot = (unsigned long)dmi->driver_data;
2773 /* apply the quirk only to on-board controllers */
2774 return slot == PCI_SLOT(pdev->devfn);
2775 }
2776
2777 return false;
2778}
2779
Tejun Heo9b10ae82009-05-30 20:50:12 +09002780static bool ahci_broken_suspend(struct pci_dev *pdev)
2781{
2782 static const struct dmi_system_id sysids[] = {
2783 /*
2784 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
2785 * to the harddisk doesn't become online after
2786 * resuming from STR. Warn and fail suspend.
2787 */
2788 {
2789 .ident = "dv4",
2790 .matches = {
2791 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2792 DMI_MATCH(DMI_PRODUCT_NAME,
2793 "HP Pavilion dv4 Notebook PC"),
2794 },
2795 .driver_data = "F.30", /* cutoff BIOS version */
2796 },
2797 {
2798 .ident = "dv5",
2799 .matches = {
2800 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2801 DMI_MATCH(DMI_PRODUCT_NAME,
2802 "HP Pavilion dv5 Notebook PC"),
2803 },
2804 .driver_data = "F.16", /* cutoff BIOS version */
2805 },
2806 {
2807 .ident = "dv6",
2808 .matches = {
2809 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2810 DMI_MATCH(DMI_PRODUCT_NAME,
2811 "HP Pavilion dv6 Notebook PC"),
2812 },
2813 .driver_data = "F.21", /* cutoff BIOS version */
2814 },
2815 {
2816 .ident = "HDX18",
2817 .matches = {
2818 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2819 DMI_MATCH(DMI_PRODUCT_NAME,
2820 "HP HDX18 Notebook PC"),
2821 },
2822 .driver_data = "F.23", /* cutoff BIOS version */
2823 },
2824 { } /* terminate list */
2825 };
2826 const struct dmi_system_id *dmi = dmi_first_match(sysids);
2827 const char *ver;
2828
2829 if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
2830 return false;
2831
2832 ver = dmi_get_system_info(DMI_BIOS_VERSION);
2833
2834 return !ver || strcmp(ver, dmi->driver_data) < 0;
2835}
2836
Tejun Heo55946392009-08-04 14:30:08 +09002837static bool ahci_broken_online(struct pci_dev *pdev)
2838{
2839#define ENCODE_BUSDEVFN(bus, slot, func) \
2840 (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
2841 static const struct dmi_system_id sysids[] = {
2842 /*
2843 * There are several gigabyte boards which use
2844 * SIMG5723s configured as hardware RAID. Certain
2845 * 5723 firmware revisions shipped there keep the link
2846 * online but fail to answer properly to SRST or
2847 * IDENTIFY when no device is attached downstream
2848 * causing libata to retry quite a few times leading
2849 * to excessive detection delay.
2850 *
2851 * As these firmwares respond to the second reset try
2852 * with invalid device signature, considering unknown
2853 * sig as offline works around the problem acceptably.
2854 */
2855 {
2856 .ident = "EP45-DQ6",
2857 .matches = {
2858 DMI_MATCH(DMI_BOARD_VENDOR,
2859 "Gigabyte Technology Co., Ltd."),
2860 DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
2861 },
2862 .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
2863 },
2864 {
2865 .ident = "EP45-DS5",
2866 .matches = {
2867 DMI_MATCH(DMI_BOARD_VENDOR,
2868 "Gigabyte Technology Co., Ltd."),
2869 DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
2870 },
2871 .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
2872 },
2873 { } /* terminate list */
2874 };
2875#undef ENCODE_BUSDEVFN
2876 const struct dmi_system_id *dmi = dmi_first_match(sysids);
2877 unsigned int val;
2878
2879 if (!dmi)
2880 return false;
2881
2882 val = (unsigned long)dmi->driver_data;
2883
2884 return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
2885}
2886
Tejun Heo24dc5f32007-01-20 16:00:28 +09002887static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888{
2889 static int printed_version;
Tejun Heoe297d992008-06-10 00:13:04 +09002890 unsigned int board_id = ent->driver_data;
2891 struct ata_port_info pi = ahci_port_info[board_id];
Tejun Heo4447d352007-04-17 23:44:08 +09002892 const struct ata_port_info *ppi[] = { &pi, NULL };
Tejun Heo24dc5f32007-01-20 16:00:28 +09002893 struct device *dev = &pdev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894 struct ahci_host_priv *hpriv;
Tejun Heo4447d352007-04-17 23:44:08 +09002895 struct ata_host *host;
Tejun Heo837f5f82008-02-06 15:13:51 +09002896 int n_ports, i, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897
2898 VPRINTK("ENTER\n");
2899
Tejun Heo12fad3f2006-05-15 21:03:55 +09002900 WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
2901
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 if (!printed_version++)
Jeff Garzika9524a72005-10-30 14:39:11 -05002903 dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904
Alan Cox5b66c822008-09-03 14:48:34 +01002905 /* The AHCI driver can only drive the SATA ports, the PATA driver
2906 can drive them all so if both drivers are selected make sure
2907 AHCI stays out of the way */
2908 if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
2909 return -ENODEV;
2910
Tejun Heo4447d352007-04-17 23:44:08 +09002911 /* acquire resources */
Tejun Heo24dc5f32007-01-20 16:00:28 +09002912 rc = pcim_enable_device(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913 if (rc)
2914 return rc;
2915
Tejun Heodea55132008-03-11 19:52:31 +09002916 /* AHCI controllers often implement SFF compatible interface.
2917 * Grab all PCI BARs just in case.
2918 */
2919 rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002920 if (rc == -EBUSY)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002921 pcim_pin_device(pdev);
Tejun Heo0d5ff562007-02-01 15:06:36 +09002922 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09002923 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924
Tejun Heoc4f77922007-12-06 15:09:43 +09002925 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
2926 (pdev->device == 0x2652 || pdev->device == 0x2653)) {
2927 u8 map;
2928
2929 /* ICH6s share the same PCI ID for both piix and ahci
2930 * modes. Enabling ahci mode while MAP indicates
2931 * combined mode is a bad idea. Yield to ata_piix.
2932 */
2933 pci_read_config_byte(pdev, ICH_MAP, &map);
2934 if (map & 0x3) {
2935 dev_printk(KERN_INFO, &pdev->dev, "controller is in "
2936 "combined mode, can't enable AHCI mode\n");
2937 return -ENODEV;
2938 }
2939 }
2940
Tejun Heo24dc5f32007-01-20 16:00:28 +09002941 hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
2942 if (!hpriv)
2943 return -ENOMEM;
Tejun Heo417a1a62007-09-23 13:19:55 +09002944 hpriv->flags |= (unsigned long)pi.private_data;
2945
Tejun Heoe297d992008-06-10 00:13:04 +09002946 /* MCP65 revision A1 and A2 can't do MSI */
2947 if (board_id == board_ahci_mcp65 &&
2948 (pdev->revision == 0xa1 || pdev->revision == 0xa2))
2949 hpriv->flags |= AHCI_HFLAG_NO_MSI;
2950
Shane Huange427fe02008-12-30 10:53:41 +08002951 /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
2952 if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
2953 hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
2954
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002955 /* only some SB600s can do 64bit DMA */
2956 if (ahci_sb600_enable_64bit(pdev))
2957 hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
Shane Huang58a09b32009-05-27 15:04:43 +08002958
Tejun Heo31b239a2009-09-17 00:34:39 +09002959 if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
2960 pci_intx(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961
Tejun Heo4447d352007-04-17 23:44:08 +09002962 /* save initial config */
Tejun Heo417a1a62007-09-23 13:19:55 +09002963 ahci_save_initial_config(pdev, hpriv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964
Tejun Heo4447d352007-04-17 23:44:08 +09002965 /* prepare host */
Tejun Heo274c1fd2007-07-16 14:29:40 +09002966 if (hpriv->cap & HOST_CAP_NCQ)
Shaohua Li388539f2009-07-27 09:24:35 +08002967 pi.flags |= ATA_FLAG_NCQ | ATA_FLAG_FPDMA_AA;
Tejun Heo4447d352007-04-17 23:44:08 +09002968
Tejun Heo7d50b602007-09-23 13:19:54 +09002969 if (hpriv->cap & HOST_CAP_PMP)
2970 pi.flags |= ATA_FLAG_PMP;
2971
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002972 if (ahci_em_messages && (hpriv->cap & HOST_CAP_EMS)) {
2973 u8 messages;
2974 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
2975 u32 em_loc = readl(mmio + HOST_EM_LOC);
2976 u32 em_ctl = readl(mmio + HOST_EM_CTL);
2977
David Milburn87943ac2008-10-13 14:38:36 -05002978 messages = (em_ctl & EM_CTRL_MSG_TYPE) >> 16;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002979
2980 /* we only support LED message type right now */
2981 if ((messages & 0x01) && (ahci_em_messages == 1)) {
2982 /* store em_loc */
2983 hpriv->em_loc = ((em_loc >> 16) * 4);
2984 pi.flags |= ATA_FLAG_EM;
2985 if (!(em_ctl & EM_CTL_ALHD))
2986 pi.flags |= ATA_FLAG_SW_ACTIVITY;
2987 }
2988 }
2989
Rafael J. Wysocki1fd68432009-01-19 20:57:36 +01002990 if (ahci_broken_system_poweroff(pdev)) {
2991 pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
2992 dev_info(&pdev->dev,
2993 "quirky BIOS, skipping spindown on poweroff\n");
2994 }
2995
Tejun Heo9b10ae82009-05-30 20:50:12 +09002996 if (ahci_broken_suspend(pdev)) {
2997 hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
2998 dev_printk(KERN_WARNING, &pdev->dev,
2999 "BIOS update required for suspend/resume\n");
3000 }
3001
Tejun Heo55946392009-08-04 14:30:08 +09003002 if (ahci_broken_online(pdev)) {
3003 hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
3004 dev_info(&pdev->dev,
3005 "online status unreliable, applying workaround\n");
3006 }
3007
Tejun Heo837f5f82008-02-06 15:13:51 +09003008 /* CAP.NP sometimes indicate the index of the last enabled
3009 * port, at other times, that of the last possible port, so
3010 * determining the maximum port number requires looking at
3011 * both CAP.NP and port_map.
3012 */
3013 n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
3014
3015 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
Tejun Heo4447d352007-04-17 23:44:08 +09003016 if (!host)
3017 return -ENOMEM;
3018 host->iomap = pcim_iomap_table(pdev);
3019 host->private_data = hpriv;
3020
Arjan van de Venf3d7f232009-01-26 02:05:44 -08003021 if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
Arjan van de Ven886ad092009-01-09 15:54:07 -08003022 host->flags |= ATA_HOST_PARALLEL_SCAN;
Arjan van de Venf3d7f232009-01-26 02:05:44 -08003023 else
3024 printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
Arjan van de Ven886ad092009-01-09 15:54:07 -08003025
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07003026 if (pi.flags & ATA_FLAG_EM)
3027 ahci_reset_em(host);
3028
Tejun Heo4447d352007-04-17 23:44:08 +09003029 for (i = 0; i < host->n_ports; i++) {
Jeff Garzikdab632e2007-05-28 08:33:01 -04003030 struct ata_port *ap = host->ports[i];
Tejun Heo4447d352007-04-17 23:44:08 +09003031
Tejun Heocbcdd872007-08-18 13:14:55 +09003032 ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
3033 ata_port_pbar_desc(ap, AHCI_PCI_BAR,
3034 0x100 + ap->port_no * 0x80, "port");
3035
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04003036 /* set initial link pm policy */
3037 ap->pm_policy = NOT_AVAILABLE;
3038
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07003039 /* set enclosure management message type */
3040 if (ap->flags & ATA_FLAG_EM)
3041 ap->em_message_type = ahci_em_messages;
3042
3043
Jeff Garzikdab632e2007-05-28 08:33:01 -04003044 /* disabled/not-implemented port */
Tejun Heo350756f2008-04-07 22:47:21 +09003045 if (!(hpriv->port_map & (1 << i)))
Jeff Garzikdab632e2007-05-28 08:33:01 -04003046 ap->ops = &ata_dummy_port_ops;
Tejun Heo4447d352007-04-17 23:44:08 +09003047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048
Tejun Heoedc93052007-10-25 14:59:16 +09003049 /* apply workaround for ASUS P5W DH Deluxe mainboard */
3050 ahci_p5wdh_workaround(host);
3051
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 /* initialize adapter */
Tejun Heo4447d352007-04-17 23:44:08 +09003053 rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09003055 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056
Tejun Heo4447d352007-04-17 23:44:08 +09003057 rc = ahci_reset_controller(host);
3058 if (rc)
3059 return rc;
Tejun Heo12fad3f2006-05-15 21:03:55 +09003060
Tejun Heo4447d352007-04-17 23:44:08 +09003061 ahci_init_controller(host);
3062 ahci_print_info(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
Tejun Heo4447d352007-04-17 23:44:08 +09003064 pci_set_master(pdev);
3065 return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
3066 &ahci_sht);
Jeff Garzik907f4672005-05-12 15:03:42 -04003067}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068
3069static int __init ahci_init(void)
3070{
Pavel Roskinb7887192006-08-10 18:13:18 +09003071 return pci_register_driver(&ahci_pci_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072}
3073
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074static void __exit ahci_exit(void)
3075{
3076 pci_unregister_driver(&ahci_pci_driver);
3077}
3078
3079
3080MODULE_AUTHOR("Jeff Garzik");
3081MODULE_DESCRIPTION("AHCI SATA low-level driver");
3082MODULE_LICENSE("GPL");
3083MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
Jeff Garzik68854332005-08-23 02:53:51 -04003084MODULE_VERSION(DRV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085
3086module_init(ahci_init);
3087module_exit(ahci_exit);