blob: a6a736a7dbf2ea1bbe09dd5afae1dd37d44ded55 [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,
Shaohua Li1b677af2009-11-16 09:56:05 +0800116 board_ahci_nosntf = 9,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118 /* global controller registers */
119 HOST_CAP = 0x00, /* host capabilities */
120 HOST_CTL = 0x04, /* global host control */
121 HOST_IRQ_STAT = 0x08, /* interrupt status */
122 HOST_PORTS_IMPL = 0x0c, /* bitmap of implemented ports */
123 HOST_VERSION = 0x10, /* AHCI spec. version compliancy */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700124 HOST_EM_LOC = 0x1c, /* Enclosure Management location */
125 HOST_EM_CTL = 0x20, /* Enclosure Management Control */
Robert Hancock4c521c82009-09-20 17:02:31 -0600126 HOST_CAP2 = 0x24, /* host capabilities, extended */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
128 /* HOST_CTL bits */
129 HOST_RESET = (1 << 0), /* reset controller; self-clear */
130 HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
131 HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
132
133 /* HOST_CAP bits */
Robert Hancock4c521c82009-09-20 17:02:31 -0600134 HOST_CAP_SXS = (1 << 5), /* Supports External SATA */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700135 HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */
Robert Hancock4c521c82009-09-20 17:02:31 -0600136 HOST_CAP_CCC = (1 << 7), /* Command Completion Coalescing */
137 HOST_CAP_PART = (1 << 13), /* Partial state capable */
138 HOST_CAP_SSC = (1 << 14), /* Slumber state capable */
139 HOST_CAP_PIO_MULTI = (1 << 15), /* PIO multiple DRQ support */
140 HOST_CAP_FBS = (1 << 16), /* FIS-based switching support */
Tejun Heo7d50b602007-09-23 13:19:54 +0900141 HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
Robert Hancock4c521c82009-09-20 17:02:31 -0600142 HOST_CAP_ONLY = (1 << 18), /* Supports AHCI mode only */
Tejun Heo22b49982006-01-23 21:38:44 +0900143 HOST_CAP_CLO = (1 << 24), /* Command List Override support */
Robert Hancock4c521c82009-09-20 17:02:31 -0600144 HOST_CAP_LED = (1 << 25), /* Supports activity LED */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400145 HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
Tejun Heo0be0aa92006-07-26 15:59:26 +0900146 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
Robert Hancock4c521c82009-09-20 17:02:31 -0600147 HOST_CAP_MPS = (1 << 28), /* Mechanical presence switch */
Tejun Heo203ef6c2007-07-16 14:29:40 +0900148 HOST_CAP_SNTF = (1 << 29), /* SNotification register */
Tejun Heo979db802006-05-15 21:03:52 +0900149 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
Tejun Heodd410ff2006-05-15 21:03:50 +0900150 HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
Robert Hancock4c521c82009-09-20 17:02:31 -0600152 /* HOST_CAP2 bits */
153 HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */
154 HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */
155 HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */
156
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 /* registers for each SATA port */
158 PORT_LST_ADDR = 0x00, /* command list DMA addr */
159 PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */
160 PORT_FIS_ADDR = 0x08, /* FIS rx buf addr */
161 PORT_FIS_ADDR_HI = 0x0c, /* FIS rx buf addr hi */
162 PORT_IRQ_STAT = 0x10, /* interrupt status */
163 PORT_IRQ_MASK = 0x14, /* interrupt enable/disable mask */
164 PORT_CMD = 0x18, /* port command */
165 PORT_TFDATA = 0x20, /* taskfile data */
166 PORT_SIG = 0x24, /* device TF signature */
167 PORT_CMD_ISSUE = 0x38, /* command issue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */
169 PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */
170 PORT_SCR_ERR = 0x30, /* SATA phy register: SError */
171 PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */
Tejun Heo203ef6c2007-07-16 14:29:40 +0900172 PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
174 /* PORT_IRQ_{STAT,MASK} bits */
175 PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
176 PORT_IRQ_TF_ERR = (1 << 30), /* task file error */
177 PORT_IRQ_HBUS_ERR = (1 << 29), /* host bus fatal error */
178 PORT_IRQ_HBUS_DATA_ERR = (1 << 28), /* host bus data error */
179 PORT_IRQ_IF_ERR = (1 << 27), /* interface fatal error */
180 PORT_IRQ_IF_NONFATAL = (1 << 26), /* interface non-fatal error */
181 PORT_IRQ_OVERFLOW = (1 << 24), /* xfer exhausted available S/G */
182 PORT_IRQ_BAD_PMP = (1 << 23), /* incorrect port multiplier */
183
184 PORT_IRQ_PHYRDY = (1 << 22), /* PhyRdy changed */
185 PORT_IRQ_DEV_ILCK = (1 << 7), /* device interlock */
186 PORT_IRQ_CONNECT = (1 << 6), /* port connect change status */
187 PORT_IRQ_SG_DONE = (1 << 5), /* descriptor processed */
188 PORT_IRQ_UNK_FIS = (1 << 4), /* unknown FIS rx'd */
189 PORT_IRQ_SDB_FIS = (1 << 3), /* Set Device Bits FIS rx'd */
190 PORT_IRQ_DMAS_FIS = (1 << 2), /* DMA Setup FIS rx'd */
191 PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */
192 PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */
193
Tejun Heo78cd52d2006-05-15 20:58:29 +0900194 PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR |
195 PORT_IRQ_IF_ERR |
196 PORT_IRQ_CONNECT |
Tejun Heo42969712006-05-31 18:28:18 +0900197 PORT_IRQ_PHYRDY |
Tejun Heo7d50b602007-09-23 13:19:54 +0900198 PORT_IRQ_UNK_FIS |
199 PORT_IRQ_BAD_PMP,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900200 PORT_IRQ_ERROR = PORT_IRQ_FREEZE |
201 PORT_IRQ_TF_ERR |
202 PORT_IRQ_HBUS_DATA_ERR,
203 DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
204 PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
205 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
207 /* PORT_CMD bits */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400208 PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
209 PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
Jeff Garzik02eaa662005-11-12 01:32:19 -0500210 PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
Tejun Heo7d50b602007-09-23 13:19:54 +0900211 PORT_CMD_PMP = (1 << 17), /* PMP attached */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
213 PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
214 PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
Tejun Heo22b49982006-01-23 21:38:44 +0900215 PORT_CMD_CLO = (1 << 3), /* Command list override */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 PORT_CMD_POWER_ON = (1 << 2), /* Power up device */
217 PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
218 PORT_CMD_START = (1 << 0), /* Enable port DMA engine */
219
Tejun Heo0be0aa92006-07-26 15:59:26 +0900220 PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */
222 PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
223 PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
Jeff Garzik4b0060f2005-06-04 00:50:22 -0400224
Tejun Heo417a1a62007-09-23 13:19:55 +0900225 /* hpriv->flags bits */
226 AHCI_HFLAG_NO_NCQ = (1 << 0),
227 AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */
228 AHCI_HFLAG_IGN_SERR_INTERNAL = (1 << 2), /* ignore SERR_INTERNAL */
229 AHCI_HFLAG_32BIT_ONLY = (1 << 3), /* force 32bit */
230 AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
231 AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
Tejun Heo6949b912007-09-23 13:19:55 +0900232 AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400233 AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
Jeff Garzika8785392008-02-28 15:43:48 -0500234 AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
Tejun Heoe297d992008-06-10 00:13:04 +0900235 AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
Tejun Heo9b10ae82009-05-30 20:50:12 +0900236 AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */
Tejun Heo55946392009-08-04 14:30:08 +0900237 AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as
238 link offline */
Shaohua Li1b677af2009-11-16 09:56:05 +0800239 AHCI_HFLAG_NO_SNTF = (1 << 12), /* no sntf */
Tejun Heo417a1a62007-09-23 13:19:55 +0900240
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200241 /* ap->flags bits */
Tejun Heo1188c0d2007-04-23 02:41:05 +0900242
243 AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
244 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400245 ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
246 ATA_FLAG_IPM,
Tejun Heoc4f77922007-12-06 15:09:43 +0900247
248 ICH_MAP = 0x90, /* ICH MAP register */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700249
Tejun Heod50ce072009-05-12 10:57:41 +0900250 /* em constants */
251 EM_MAX_SLOTS = 8,
252 EM_MAX_RETRY = 5,
253
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700254 /* em_ctl bits */
255 EM_CTL_RST = (1 << 9), /* Reset */
256 EM_CTL_TM = (1 << 8), /* Transmit Message */
257 EM_CTL_ALHD = (1 << 26), /* Activity LED */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258};
259
260struct ahci_cmd_hdr {
Al Viro4ca4e432007-12-30 09:32:22 +0000261 __le32 opts;
262 __le32 status;
263 __le32 tbl_addr;
264 __le32 tbl_addr_hi;
265 __le32 reserved[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266};
267
268struct ahci_sg {
Al Viro4ca4e432007-12-30 09:32:22 +0000269 __le32 addr;
270 __le32 addr_hi;
271 __le32 reserved;
272 __le32 flags_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273};
274
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700275struct ahci_em_priv {
276 enum sw_activity blink_policy;
277 struct timer_list timer;
278 unsigned long saved_activity;
279 unsigned long activity;
280 unsigned long led_state;
281};
282
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283struct ahci_host_priv {
Tejun Heo417a1a62007-09-23 13:19:55 +0900284 unsigned int flags; /* AHCI_HFLAG_* */
Tejun Heod447df12007-03-18 22:15:33 +0900285 u32 cap; /* cap to use */
Robert Hancock4c521c82009-09-20 17:02:31 -0600286 u32 cap2; /* cap2 to use */
Tejun Heod447df12007-03-18 22:15:33 +0900287 u32 port_map; /* port map to use */
288 u32 saved_cap; /* saved initial cap */
Robert Hancock4c521c82009-09-20 17:02:31 -0600289 u32 saved_cap2; /* saved initial cap2 */
Tejun Heod447df12007-03-18 22:15:33 +0900290 u32 saved_port_map; /* saved initial port_map */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700291 u32 em_loc; /* enclosure management location */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292};
293
294struct ahci_port_priv {
Tejun Heo7d50b602007-09-23 13:19:54 +0900295 struct ata_link *active_link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 struct ahci_cmd_hdr *cmd_slot;
297 dma_addr_t cmd_slot_dma;
298 void *cmd_tbl;
299 dma_addr_t cmd_tbl_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 void *rx_fis;
301 dma_addr_t rx_fis_dma;
Tejun Heo0291f952007-01-25 19:16:28 +0900302 /* for NCQ spurious interrupt analysis */
Tejun Heo0291f952007-01-25 19:16:28 +0900303 unsigned int ncq_saw_d2h:1;
304 unsigned int ncq_saw_dmas:1;
Tejun Heoafb2d552007-02-27 13:24:19 +0900305 unsigned int ncq_saw_sdb:1;
Kristen Carlson Accardia7384922007-08-09 14:23:41 -0700306 u32 intr_mask; /* interrupts to enable */
Tejun Heod50ce072009-05-12 10:57:41 +0900307 /* enclosure management info per PM slot */
308 struct ahci_em_priv em_priv[EM_MAX_SLOTS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309};
310
Tejun Heo82ef04f2008-07-31 17:02:40 +0900311static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
312static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
Jeff Garzik2dcb4072007-10-19 06:42:56 -0400313static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
Tejun Heo9a3d9eb2006-01-23 13:09:36 +0900314static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
Tejun Heo4c9bf4e2008-04-07 22:47:20 +0900315static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316static int ahci_port_start(struct ata_port *ap);
317static void ahci_port_stop(struct ata_port *ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318static void ahci_qc_prep(struct ata_queued_cmd *qc);
Tejun Heo78cd52d2006-05-15 20:58:29 +0900319static void ahci_freeze(struct ata_port *ap);
320static void ahci_thaw(struct ata_port *ap);
Tejun Heo7d50b602007-09-23 13:19:54 +0900321static void ahci_pmp_attach(struct ata_port *ap);
322static void ahci_pmp_detach(struct ata_port *ap);
Tejun Heoa1efdab2008-03-25 12:22:50 +0900323static int ahci_softreset(struct ata_link *link, unsigned int *class,
324 unsigned long deadline);
Shane Huangbd172432008-06-10 15:52:04 +0800325static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
326 unsigned long deadline);
Tejun Heoa1efdab2008-03-25 12:22:50 +0900327static int ahci_hardreset(struct ata_link *link, unsigned int *class,
328 unsigned long deadline);
329static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
330 unsigned long deadline);
331static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
332 unsigned long deadline);
333static void ahci_postreset(struct ata_link *link, unsigned int *class);
Tejun Heo78cd52d2006-05-15 20:58:29 +0900334static void ahci_error_handler(struct ata_port *ap);
335static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
Jeff Garzikdf69c9c2007-05-26 20:46:51 -0400336static int ahci_port_resume(struct ata_port *ap);
Jeff Garzika8785392008-02-28 15:43:48 -0500337static void ahci_dev_config(struct ata_device *dev);
Jeff Garzikdab632e2007-05-28 08:33:01 -0400338static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
339 u32 opts);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900340#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900341static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
Tejun Heoc1332872006-07-26 15:59:26 +0900342static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
343static int ahci_pci_device_resume(struct pci_dev *pdev);
Tejun Heo438ac6d2007-03-02 17:31:26 +0900344#endif
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700345static ssize_t ahci_activity_show(struct ata_device *dev, char *buf);
346static ssize_t ahci_activity_store(struct ata_device *dev,
347 enum sw_activity val);
348static void ahci_init_sw_activity(struct ata_link *link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
Matthew Garrett77cdec12009-07-17 19:13:47 +0100350static ssize_t ahci_show_host_caps(struct device *dev,
351 struct device_attribute *attr, char *buf);
Robert Hancock4c521c82009-09-20 17:02:31 -0600352static ssize_t ahci_show_host_cap2(struct device *dev,
353 struct device_attribute *attr, char *buf);
Matthew Garrett77cdec12009-07-17 19:13:47 +0100354static ssize_t ahci_show_host_version(struct device *dev,
355 struct device_attribute *attr, char *buf);
356static ssize_t ahci_show_port_cmd(struct device *dev,
357 struct device_attribute *attr, char *buf);
358
359DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
Robert Hancock4c521c82009-09-20 17:02:31 -0600360DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
Matthew Garrett77cdec12009-07-17 19:13:47 +0100361DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
362DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
363
Tony Jonesee959b02008-02-22 00:13:36 +0100364static struct device_attribute *ahci_shost_attrs[] = {
365 &dev_attr_link_power_management_policy,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700366 &dev_attr_em_message_type,
367 &dev_attr_em_message,
Matthew Garrett77cdec12009-07-17 19:13:47 +0100368 &dev_attr_ahci_host_caps,
Robert Hancock4c521c82009-09-20 17:02:31 -0600369 &dev_attr_ahci_host_cap2,
Matthew Garrett77cdec12009-07-17 19:13:47 +0100370 &dev_attr_ahci_host_version,
371 &dev_attr_ahci_port_cmd,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700372 NULL
373};
374
375static struct device_attribute *ahci_sdev_attrs[] = {
376 &dev_attr_sw_activity,
Elias Oltmanns45fabbb2008-09-21 11:54:08 +0200377 &dev_attr_unload_heads,
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400378 NULL
379};
380
Jeff Garzik193515d2005-11-07 00:59:37 -0500381static struct scsi_host_template ahci_sht = {
Tejun Heo68d1d072008-03-25 12:22:49 +0900382 ATA_NCQ_SHT(DRV_NAME),
Tejun Heo12fad3f2006-05-15 21:03:55 +0900383 .can_queue = AHCI_MAX_CMDS - 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 .sg_tablesize = AHCI_MAX_SG,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 .dma_boundary = AHCI_DMA_BOUNDARY,
Kristen Carlson Accardi31556592007-10-25 01:33:26 -0400386 .shost_attrs = ahci_shost_attrs,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700387 .sdev_attrs = ahci_sdev_attrs,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388};
389
Tejun Heo029cfd62008-03-25 12:22:49 +0900390static struct ata_port_operations ahci_ops = {
391 .inherits = &sata_pmp_port_ops,
392
Tejun Heo7d50b602007-09-23 13:19:54 +0900393 .qc_defer = sata_pmp_qc_defer_cmd_switch,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 .qc_prep = ahci_qc_prep,
395 .qc_issue = ahci_qc_issue,
Tejun Heo4c9bf4e2008-04-07 22:47:20 +0900396 .qc_fill_rtf = ahci_qc_fill_rtf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Tejun Heo78cd52d2006-05-15 20:58:29 +0900398 .freeze = ahci_freeze,
399 .thaw = ahci_thaw,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900400 .softreset = ahci_softreset,
401 .hardreset = ahci_hardreset,
402 .postreset = ahci_postreset,
Tejun Heo071f44b2008-04-07 22:47:22 +0900403 .pmp_softreset = ahci_softreset,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900404 .error_handler = ahci_error_handler,
405 .post_internal_cmd = ahci_post_internal_cmd,
Tejun Heo029cfd62008-03-25 12:22:49 +0900406 .dev_config = ahci_dev_config,
Tejun Heo78cd52d2006-05-15 20:58:29 +0900407
Tejun Heo029cfd62008-03-25 12:22:49 +0900408 .scr_read = ahci_scr_read,
409 .scr_write = ahci_scr_write,
Tejun Heo7d50b602007-09-23 13:19:54 +0900410 .pmp_attach = ahci_pmp_attach,
411 .pmp_detach = ahci_pmp_detach,
Tejun Heo7d50b602007-09-23 13:19:54 +0900412
Tejun Heo029cfd62008-03-25 12:22:49 +0900413 .enable_pm = ahci_enable_alpm,
414 .disable_pm = ahci_disable_alpm,
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700415 .em_show = ahci_led_show,
416 .em_store = ahci_led_store,
417 .sw_activity_show = ahci_activity_show,
418 .sw_activity_store = ahci_activity_store,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900419#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900420 .port_suspend = ahci_port_suspend,
421 .port_resume = ahci_port_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900422#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 .port_start = ahci_port_start,
424 .port_stop = ahci_port_stop,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425};
426
Tejun Heo029cfd62008-03-25 12:22:49 +0900427static struct ata_port_operations ahci_vt8251_ops = {
428 .inherits = &ahci_ops,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900429 .hardreset = ahci_vt8251_hardreset,
Tejun Heoad616ff2006-11-01 18:00:24 +0900430};
431
Tejun Heo029cfd62008-03-25 12:22:49 +0900432static struct ata_port_operations ahci_p5wdh_ops = {
433 .inherits = &ahci_ops,
Tejun Heoa1efdab2008-03-25 12:22:50 +0900434 .hardreset = ahci_p5wdh_hardreset,
Tejun Heoedc93052007-10-25 14:59:16 +0900435};
436
Shane Huangbd172432008-06-10 15:52:04 +0800437static struct ata_port_operations ahci_sb600_ops = {
438 .inherits = &ahci_ops,
439 .softreset = ahci_sb600_softreset,
440 .pmp_softreset = ahci_sb600_softreset,
441};
442
Tejun Heo417a1a62007-09-23 13:19:55 +0900443#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
444
Arjan van de Ven98ac62d2005-11-28 10:06:23 +0100445static const struct ata_port_info ahci_port_info[] = {
Jeff Garzik4da646b2009-04-08 02:00:13 -0400446 [board_ahci] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 {
Tejun Heo1188c0d2007-04-23 02:41:05 +0900448 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100449 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400450 .udma_mask = ATA_UDMA6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 .port_ops = &ahci_ops,
452 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400453 [board_ahci_vt8251] =
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200454 {
Tejun Heo6949b912007-09-23 13:19:55 +0900455 AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
Tejun Heo417a1a62007-09-23 13:19:55 +0900456 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100457 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400458 .udma_mask = ATA_UDMA6,
Tejun Heoad616ff2006-11-01 18:00:24 +0900459 .port_ops = &ahci_vt8251_ops,
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +0200460 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400461 [board_ahci_ign_iferr] =
Tejun Heo41669552006-11-29 11:33:14 +0900462 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900463 AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
464 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100465 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400466 .udma_mask = ATA_UDMA6,
Tejun Heo41669552006-11-29 11:33:14 +0900467 .port_ops = &ahci_ops,
468 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400469 [board_ahci_sb600] =
Conke Hu55a61602007-03-27 18:33:05 +0800470 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900471 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
Tejun Heo2fcad9d2009-10-03 18:27:29 +0900472 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
473 AHCI_HFLAG_32BIT_ONLY),
Tejun Heo417a1a62007-09-23 13:19:55 +0900474 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100475 .pio_mask = ATA_PIO4,
Jeff Garzik469248a2007-07-08 01:13:16 -0400476 .udma_mask = ATA_UDMA6,
Shane Huangbd172432008-06-10 15:52:04 +0800477 .port_ops = &ahci_sb600_ops,
Conke Hu55a61602007-03-27 18:33:05 +0800478 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400479 [board_ahci_mv] =
Jeff Garzikcd70c262007-07-08 02:29:42 -0400480 {
Tejun Heo417a1a62007-09-23 13:19:55 +0900481 AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
Tejun Heo17248462008-08-29 16:03:59 +0200482 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
Jeff Garzikcd70c262007-07-08 02:29:42 -0400483 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
Tejun Heo417a1a62007-09-23 13:19:55 +0900484 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100485 .pio_mask = ATA_PIO4,
Jeff Garzikcd70c262007-07-08 02:29:42 -0400486 .udma_mask = ATA_UDMA6,
487 .port_ops = &ahci_ops,
488 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400489 [board_ahci_sb700] = /* for SB700 and SB800 */
Shane Huange39fc8c2008-02-22 05:00:31 -0800490 {
Shane Huangbd172432008-06-10 15:52:04 +0800491 AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
Shane Huange39fc8c2008-02-22 05:00:31 -0800492 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100493 .pio_mask = ATA_PIO4,
Shane Huange39fc8c2008-02-22 05:00:31 -0800494 .udma_mask = ATA_UDMA6,
Shane Huangbd172432008-06-10 15:52:04 +0800495 .port_ops = &ahci_sb600_ops,
Shane Huange39fc8c2008-02-22 05:00:31 -0800496 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400497 [board_ahci_mcp65] =
Tejun Heoe297d992008-06-10 00:13:04 +0900498 {
499 AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
500 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100501 .pio_mask = ATA_PIO4,
Tejun Heoe297d992008-06-10 00:13:04 +0900502 .udma_mask = ATA_UDMA6,
503 .port_ops = &ahci_ops,
504 },
Jeff Garzik4da646b2009-04-08 02:00:13 -0400505 [board_ahci_nopmp] =
Tejun Heo9a3b1032008-06-18 20:56:58 -0400506 {
507 AHCI_HFLAGS (AHCI_HFLAG_NO_PMP),
508 .flags = AHCI_FLAG_COMMON,
Erik Inge Bolsø14bdef92009-03-14 21:38:24 +0100509 .pio_mask = ATA_PIO4,
Tejun Heo9a3b1032008-06-18 20:56:58 -0400510 .udma_mask = ATA_UDMA6,
511 .port_ops = &ahci_ops,
512 },
Shaohua Li1b677af2009-11-16 09:56:05 +0800513 [board_ahci_yesncq] =
Tejun Heoaa431dd2009-04-08 14:25:31 -0700514 {
515 AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ),
516 .flags = AHCI_FLAG_COMMON,
517 .pio_mask = ATA_PIO4,
518 .udma_mask = ATA_UDMA6,
519 .port_ops = &ahci_ops,
520 },
Shaohua Li1b677af2009-11-16 09:56:05 +0800521 [board_ahci_nosntf] =
522 {
523 AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF),
524 .flags = AHCI_FLAG_COMMON,
525 .pio_mask = ATA_PIO4,
526 .udma_mask = ATA_UDMA6,
527 .port_ops = &ahci_ops,
528 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529};
530
Jeff Garzik3b7d6972005-11-10 11:04:11 -0500531static const struct pci_device_id ahci_pci_tbl[] = {
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400532 /* Intel */
Jeff Garzik54bb3a92006-09-27 22:20:11 -0400533 { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
534 { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
535 { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
536 { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
537 { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
Tejun Heo82490c02007-01-23 15:13:39 +0900538 { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
Jeff Garzik54bb3a92006-09-27 22:20:11 -0400539 { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
540 { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
541 { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
542 { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
Tejun Heo7a234af2007-09-03 12:44:57 +0900543 { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
Shaohua Li1b677af2009-11-16 09:56:05 +0800544 { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
Tejun Heo7a234af2007-09-03 12:44:57 +0900545 { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
546 { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
547 { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
548 { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
549 { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
550 { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
551 { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
552 { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
553 { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
554 { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
555 { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
556 { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
557 { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
558 { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
559 { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
Jason Gastond4155e62007-09-20 17:35:00 -0400560 { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
561 { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
Jason Gaston16ad1ad2008-01-28 17:34:14 -0800562 { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
Mark Goodwinb2dde6a2009-06-26 10:44:11 -0500563 { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
Jason Gaston16ad1ad2008-01-28 17:34:14 -0800564 { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
David Milburnc1f57d92009-07-22 15:15:56 -0500565 { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
566 { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
Seth Heasleyadcb5302008-08-11 17:03:09 -0700567 { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
Seth Heasley8e48b6b2008-08-27 16:47:22 -0700568 { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
David Milburnc1f57d92009-07-22 15:15:56 -0500569 { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
Seth Heasleyadcb5302008-08-11 17:03:09 -0700570 { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
Seth Heasley8e48b6b2008-08-27 16:47:22 -0700571 { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
David Milburnc1f57d92009-07-22 15:15:56 -0500572 { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400573
Tejun Heoe34bb372007-02-26 20:24:03 +0900574 /* JMicron 360/1/3/5/6, match class to avoid IDE function */
575 { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
576 PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400577
578 /* ATI */
Conke Huc65ec1c2007-04-11 18:23:14 +0800579 { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
Shane Huange39fc8c2008-02-22 05:00:31 -0800580 { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
581 { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
582 { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
583 { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
584 { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
585 { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400586
Shane Huange2dd90b2009-07-29 11:34:49 +0800587 /* AMD */
Shane Huang5deab532009-10-13 11:14:00 +0800588 { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
Shane Huange2dd90b2009-07-29 11:34:49 +0800589 /* AMD is using RAID class only for ahci controllers */
590 { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
591 PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
592
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400593 /* VIA */
Jeff Garzik54bb3a92006-09-27 22:20:11 -0400594 { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
Tejun Heobf335542007-04-11 17:27:14 +0900595 { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400596
597 /* NVIDIA */
Tejun Heoe297d992008-06-10 00:13:04 +0900598 { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */
599 { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */
600 { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */
601 { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */
602 { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */
603 { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */
604 { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */
605 { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */
Tejun Heoaa431dd2009-04-08 14:25:31 -0700606 { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_yesncq }, /* MCP67 */
607 { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_yesncq }, /* MCP67 */
608 { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_yesncq }, /* MCP67 */
609 { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_yesncq }, /* MCP67 */
610 { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_yesncq }, /* MCP67 */
611 { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_yesncq }, /* MCP67 */
612 { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_yesncq }, /* MCP67 */
613 { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_yesncq }, /* MCP67 */
614 { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_yesncq }, /* MCP67 */
615 { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_yesncq }, /* MCP67 */
616 { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq }, /* MCP67 */
617 { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq }, /* MCP67 */
peer chen726206f2009-10-15 16:34:56 +0800618 { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_yesncq }, /* Linux ID */
Tejun Heoaa431dd2009-04-08 14:25:31 -0700619 { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq }, /* MCP73 */
620 { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq }, /* MCP73 */
621 { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq }, /* MCP73 */
622 { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_yesncq }, /* MCP73 */
623 { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_yesncq }, /* MCP73 */
624 { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_yesncq }, /* MCP73 */
625 { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_yesncq }, /* MCP73 */
626 { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_yesncq }, /* MCP73 */
627 { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_yesncq }, /* MCP73 */
628 { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_yesncq }, /* MCP73 */
629 { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_yesncq }, /* MCP73 */
630 { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_yesncq }, /* MCP73 */
Peer Chen0522b282007-06-07 18:05:12 +0800631 { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */
632 { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */
633 { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */
634 { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci }, /* MCP77 */
635 { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci }, /* MCP77 */
636 { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci }, /* MCP77 */
637 { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci }, /* MCP77 */
638 { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci }, /* MCP77 */
639 { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci }, /* MCP77 */
640 { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
641 { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
642 { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
peerchen6ba86952007-12-03 22:20:37 +0800643 { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci }, /* MCP79 */
644 { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci }, /* MCP79 */
645 { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci }, /* MCP79 */
646 { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci }, /* MCP79 */
Peer Chen71008192007-09-24 10:16:25 +0800647 { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci }, /* MCP79 */
648 { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci }, /* MCP79 */
649 { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci }, /* MCP79 */
650 { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci }, /* MCP79 */
651 { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci }, /* MCP79 */
652 { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */
653 { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */
654 { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */
peerchen7adbe462009-02-27 16:58:41 +0800655 { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci }, /* MCP89 */
656 { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci }, /* MCP89 */
657 { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci }, /* MCP89 */
658 { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci }, /* MCP89 */
659 { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci }, /* MCP89 */
660 { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci }, /* MCP89 */
661 { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci }, /* MCP89 */
662 { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci }, /* MCP89 */
663 { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci }, /* MCP89 */
664 { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci }, /* MCP89 */
665 { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci }, /* MCP89 */
666 { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci }, /* MCP89 */
Jeff Garzikfe7fa312006-06-22 23:05:36 -0400667
Jeff Garzik95916ed2006-07-29 04:10:14 -0400668 /* SiS */
Tejun Heo20e2de42008-08-01 12:51:43 +0900669 { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
670 { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */
671 { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
Jeff Garzik95916ed2006-07-29 04:10:14 -0400672
Jeff Garzikcd70c262007-07-08 02:29:42 -0400673 /* Marvell */
674 { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100675 { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */
Jeff Garzikcd70c262007-07-08 02:29:42 -0400676
Mark Nelsonc77a0362008-10-23 14:08:16 +1100677 /* Promise */
678 { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */
679
Jeff Garzik415ae2b2006-11-01 05:10:42 -0500680 /* Generic, PCI class code for AHCI */
681 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
Conke Huc9f89472007-01-09 05:32:51 -0500682 PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
Jeff Garzik415ae2b2006-11-01 05:10:42 -0500683
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 { } /* terminate list */
685};
686
687
688static struct pci_driver ahci_pci_driver = {
689 .name = DRV_NAME,
690 .id_table = ahci_pci_tbl,
691 .probe = ahci_init_one,
Tejun Heo24dc5f32007-01-20 16:00:28 +0900692 .remove = ata_pci_remove_one,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900693#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +0900694 .suspend = ahci_pci_device_suspend,
695 .resume = ahci_pci_device_resume,
Tejun Heo438ac6d2007-03-02 17:31:26 +0900696#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697};
698
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -0700699static int ahci_em_messages = 1;
700module_param(ahci_em_messages, int, 0444);
701/* add other LED protocol types when they become supported */
702MODULE_PARM_DESC(ahci_em_messages,
703 "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
Alan Cox5b66c822008-09-03 14:48:34 +0100705#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
706static int marvell_enable;
707#else
708static int marvell_enable = 1;
709#endif
710module_param(marvell_enable, int, 0644);
711MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
712
713
Tejun Heo98fa4b62006-11-02 12:17:23 +0900714static inline int ahci_nr_ports(u32 cap)
715{
716 return (cap & 0x1f) + 1;
717}
718
Jeff Garzikdab632e2007-05-28 08:33:01 -0400719static inline void __iomem *__ahci_port_base(struct ata_host *host,
720 unsigned int port_no)
721{
722 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
723
724 return mmio + 0x100 + (port_no * 0x80);
725}
726
Tejun Heo4447d352007-04-17 23:44:08 +0900727static inline void __iomem *ahci_port_base(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728{
Jeff Garzikdab632e2007-05-28 08:33:01 -0400729 return __ahci_port_base(ap->host, ap->port_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730}
731
Tejun Heob710a1f2008-01-05 23:11:57 +0900732static void ahci_enable_ahci(void __iomem *mmio)
733{
Tejun Heo15fe9822008-04-23 20:52:58 +0900734 int i;
Tejun Heob710a1f2008-01-05 23:11:57 +0900735 u32 tmp;
736
737 /* turn on AHCI_EN */
738 tmp = readl(mmio + HOST_CTL);
Tejun Heo15fe9822008-04-23 20:52:58 +0900739 if (tmp & HOST_AHCI_EN)
740 return;
741
742 /* Some controllers need AHCI_EN to be written multiple times.
743 * Try a few times before giving up.
744 */
745 for (i = 0; i < 5; i++) {
Tejun Heob710a1f2008-01-05 23:11:57 +0900746 tmp |= HOST_AHCI_EN;
747 writel(tmp, mmio + HOST_CTL);
748 tmp = readl(mmio + HOST_CTL); /* flush && sanity check */
Tejun Heo15fe9822008-04-23 20:52:58 +0900749 if (tmp & HOST_AHCI_EN)
750 return;
751 msleep(10);
Tejun Heob710a1f2008-01-05 23:11:57 +0900752 }
Tejun Heo15fe9822008-04-23 20:52:58 +0900753
754 WARN_ON(1);
Tejun Heob710a1f2008-01-05 23:11:57 +0900755}
756
Matthew Garrett77cdec12009-07-17 19:13:47 +0100757static ssize_t ahci_show_host_caps(struct device *dev,
758 struct device_attribute *attr, char *buf)
759{
760 struct Scsi_Host *shost = class_to_shost(dev);
761 struct ata_port *ap = ata_shost_to_port(shost);
762 struct ahci_host_priv *hpriv = ap->host->private_data;
763
764 return sprintf(buf, "%x\n", hpriv->cap);
765}
766
Robert Hancock4c521c82009-09-20 17:02:31 -0600767static ssize_t ahci_show_host_cap2(struct device *dev,
768 struct device_attribute *attr, char *buf)
769{
770 struct Scsi_Host *shost = class_to_shost(dev);
771 struct ata_port *ap = ata_shost_to_port(shost);
772 struct ahci_host_priv *hpriv = ap->host->private_data;
773
774 return sprintf(buf, "%x\n", hpriv->cap2);
775}
776
Matthew Garrett77cdec12009-07-17 19:13:47 +0100777static ssize_t ahci_show_host_version(struct device *dev,
778 struct device_attribute *attr, char *buf)
779{
780 struct Scsi_Host *shost = class_to_shost(dev);
781 struct ata_port *ap = ata_shost_to_port(shost);
782 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
783
784 return sprintf(buf, "%x\n", readl(mmio + HOST_VERSION));
785}
786
787static ssize_t ahci_show_port_cmd(struct device *dev,
788 struct device_attribute *attr, char *buf)
789{
790 struct Scsi_Host *shost = class_to_shost(dev);
791 struct ata_port *ap = ata_shost_to_port(shost);
792 void __iomem *port_mmio = ahci_port_base(ap);
793
794 return sprintf(buf, "%x\n", readl(port_mmio + PORT_CMD));
795}
796
Tejun Heod447df12007-03-18 22:15:33 +0900797/**
798 * ahci_save_initial_config - Save and fixup initial config values
Tejun Heo4447d352007-04-17 23:44:08 +0900799 * @pdev: target PCI device
Tejun Heo4447d352007-04-17 23:44:08 +0900800 * @hpriv: host private area to store config values
Tejun Heod447df12007-03-18 22:15:33 +0900801 *
802 * Some registers containing configuration info might be setup by
803 * BIOS and might be cleared on reset. This function saves the
804 * initial values of those registers into @hpriv such that they
805 * can be restored after controller reset.
806 *
807 * If inconsistent, config values are fixed up by this function.
808 *
809 * LOCKING:
810 * None.
811 */
Tejun Heo4447d352007-04-17 23:44:08 +0900812static void ahci_save_initial_config(struct pci_dev *pdev,
Tejun Heo4447d352007-04-17 23:44:08 +0900813 struct ahci_host_priv *hpriv)
Tejun Heod447df12007-03-18 22:15:33 +0900814{
Tejun Heo4447d352007-04-17 23:44:08 +0900815 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
Robert Hancock4c521c82009-09-20 17:02:31 -0600816 u32 cap, cap2, vers, port_map;
Tejun Heo17199b12007-03-18 22:26:53 +0900817 int i;
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100818 int mv;
Tejun Heod447df12007-03-18 22:15:33 +0900819
Tejun Heob710a1f2008-01-05 23:11:57 +0900820 /* make sure AHCI mode is enabled before accessing CAP */
821 ahci_enable_ahci(mmio);
822
Tejun Heod447df12007-03-18 22:15:33 +0900823 /* Values prefixed with saved_ are written back to host after
824 * reset. Values without are used for driver operation.
825 */
826 hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
827 hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
828
Robert Hancock4c521c82009-09-20 17:02:31 -0600829 /* CAP2 register is only defined for AHCI 1.2 and later */
830 vers = readl(mmio + HOST_VERSION);
831 if ((vers >> 16) > 1 ||
832 ((vers >> 16) == 1 && (vers & 0xFFFF) >= 0x200))
833 hpriv->saved_cap2 = cap2 = readl(mmio + HOST_CAP2);
834 else
835 hpriv->saved_cap2 = cap2 = 0;
836
Tejun Heo274c1fd2007-07-16 14:29:40 +0900837 /* some chips have errata preventing 64bit use */
Tejun Heo417a1a62007-09-23 13:19:55 +0900838 if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
Tejun Heoc7a42152007-05-18 16:23:19 +0200839 dev_printk(KERN_INFO, &pdev->dev,
840 "controller can't do 64bit DMA, forcing 32bit\n");
841 cap &= ~HOST_CAP_64;
842 }
843
Tejun Heo417a1a62007-09-23 13:19:55 +0900844 if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
Tejun Heo274c1fd2007-07-16 14:29:40 +0900845 dev_printk(KERN_INFO, &pdev->dev,
846 "controller can't do NCQ, turning off CAP_NCQ\n");
847 cap &= ~HOST_CAP_NCQ;
848 }
849
Tejun Heoe297d992008-06-10 00:13:04 +0900850 if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
851 dev_printk(KERN_INFO, &pdev->dev,
852 "controller can do NCQ, turning on CAP_NCQ\n");
853 cap |= HOST_CAP_NCQ;
854 }
855
Roel Kluin258cd842008-03-09 21:42:40 +0100856 if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
Tejun Heo6949b912007-09-23 13:19:55 +0900857 dev_printk(KERN_INFO, &pdev->dev,
858 "controller can't do PMP, turning off CAP_PMP\n");
859 cap &= ~HOST_CAP_PMP;
860 }
861
Shaohua Li1b677af2009-11-16 09:56:05 +0800862 if ((cap & HOST_CAP_SNTF) && (hpriv->flags & AHCI_HFLAG_NO_SNTF)) {
863 dev_printk(KERN_INFO, &pdev->dev,
864 "controller can't do SNTF, turning off CAP_SNTF\n");
865 cap &= ~HOST_CAP_SNTF;
866 }
867
Tejun Heod799e082008-06-17 12:46:30 +0900868 if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 &&
869 port_map != 1) {
870 dev_printk(KERN_INFO, &pdev->dev,
871 "JMB361 has only one port, port_map 0x%x -> 0x%x\n",
872 port_map, 1);
873 port_map = 1;
874 }
875
Jeff Garzikcd70c262007-07-08 02:29:42 -0400876 /*
877 * Temporary Marvell 6145 hack: PATA port presence
878 * is asserted through the standard AHCI port
879 * presence register, as bit 4 (counting from 0)
880 */
Tejun Heo417a1a62007-09-23 13:19:55 +0900881 if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100882 if (pdev->device == 0x6121)
883 mv = 0x3;
884 else
885 mv = 0xf;
Jeff Garzikcd70c262007-07-08 02:29:42 -0400886 dev_printk(KERN_ERR, &pdev->dev,
887 "MV_AHCI HACK: port_map %x -> %x\n",
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100888 port_map,
889 port_map & mv);
Alan Cox5b66c822008-09-03 14:48:34 +0100890 dev_printk(KERN_ERR, &pdev->dev,
891 "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
Jeff Garzikcd70c262007-07-08 02:29:42 -0400892
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +0100893 port_map &= mv;
Jeff Garzikcd70c262007-07-08 02:29:42 -0400894 }
895
Tejun Heo17199b12007-03-18 22:26:53 +0900896 /* cross check port_map and cap.n_ports */
Tejun Heo7a234af2007-09-03 12:44:57 +0900897 if (port_map) {
Tejun Heo837f5f82008-02-06 15:13:51 +0900898 int map_ports = 0;
Tejun Heo17199b12007-03-18 22:26:53 +0900899
Tejun Heo837f5f82008-02-06 15:13:51 +0900900 for (i = 0; i < AHCI_MAX_PORTS; i++)
901 if (port_map & (1 << i))
902 map_ports++;
Tejun Heo17199b12007-03-18 22:26:53 +0900903
Tejun Heo837f5f82008-02-06 15:13:51 +0900904 /* If PI has more ports than n_ports, whine, clear
905 * port_map and let it be generated from n_ports.
Tejun Heo17199b12007-03-18 22:26:53 +0900906 */
Tejun Heo837f5f82008-02-06 15:13:51 +0900907 if (map_ports > ahci_nr_ports(cap)) {
Tejun Heo4447d352007-04-17 23:44:08 +0900908 dev_printk(KERN_WARNING, &pdev->dev,
Tejun Heo837f5f82008-02-06 15:13:51 +0900909 "implemented port map (0x%x) contains more "
910 "ports than nr_ports (%u), using nr_ports\n",
911 port_map, ahci_nr_ports(cap));
Tejun Heo7a234af2007-09-03 12:44:57 +0900912 port_map = 0;
913 }
914 }
915
916 /* fabricate port_map from cap.nr_ports */
917 if (!port_map) {
Tejun Heo17199b12007-03-18 22:26:53 +0900918 port_map = (1 << ahci_nr_ports(cap)) - 1;
Tejun Heo7a234af2007-09-03 12:44:57 +0900919 dev_printk(KERN_WARNING, &pdev->dev,
920 "forcing PORTS_IMPL to 0x%x\n", port_map);
921
922 /* write the fixed up value to the PI register */
923 hpriv->saved_port_map = port_map;
Tejun Heo17199b12007-03-18 22:26:53 +0900924 }
925
Tejun Heod447df12007-03-18 22:15:33 +0900926 /* record values to use during operation */
927 hpriv->cap = cap;
Robert Hancock4c521c82009-09-20 17:02:31 -0600928 hpriv->cap2 = cap2;
Tejun Heod447df12007-03-18 22:15:33 +0900929 hpriv->port_map = port_map;
930}
931
932/**
933 * ahci_restore_initial_config - Restore initial config
Tejun Heo4447d352007-04-17 23:44:08 +0900934 * @host: target ATA host
Tejun Heod447df12007-03-18 22:15:33 +0900935 *
936 * Restore initial config stored by ahci_save_initial_config().
937 *
938 * LOCKING:
939 * None.
940 */
Tejun Heo4447d352007-04-17 23:44:08 +0900941static void ahci_restore_initial_config(struct ata_host *host)
Tejun Heod447df12007-03-18 22:15:33 +0900942{
Tejun Heo4447d352007-04-17 23:44:08 +0900943 struct ahci_host_priv *hpriv = host->private_data;
944 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
945
Tejun Heod447df12007-03-18 22:15:33 +0900946 writel(hpriv->saved_cap, mmio + HOST_CAP);
Robert Hancock4c521c82009-09-20 17:02:31 -0600947 if (hpriv->saved_cap2)
948 writel(hpriv->saved_cap2, mmio + HOST_CAP2);
Tejun Heod447df12007-03-18 22:15:33 +0900949 writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
950 (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
951}
952
Tejun Heo203ef6c2007-07-16 14:29:40 +0900953static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954{
Tejun Heo203ef6c2007-07-16 14:29:40 +0900955 static const int offset[] = {
956 [SCR_STATUS] = PORT_SCR_STAT,
957 [SCR_CONTROL] = PORT_SCR_CTL,
958 [SCR_ERROR] = PORT_SCR_ERR,
959 [SCR_ACTIVE] = PORT_SCR_ACT,
960 [SCR_NOTIFICATION] = PORT_SCR_NTF,
961 };
962 struct ahci_host_priv *hpriv = ap->host->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963
Tejun Heo203ef6c2007-07-16 14:29:40 +0900964 if (sc_reg < ARRAY_SIZE(offset) &&
965 (sc_reg != SCR_NOTIFICATION || (hpriv->cap & HOST_CAP_SNTF)))
966 return offset[sc_reg];
Tejun Heoda3dbb12007-07-16 14:29:40 +0900967 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968}
969
Tejun Heo82ef04f2008-07-31 17:02:40 +0900970static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971{
Tejun Heo82ef04f2008-07-31 17:02:40 +0900972 void __iomem *port_mmio = ahci_port_base(link->ap);
973 int offset = ahci_scr_offset(link->ap, sc_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
Tejun Heo203ef6c2007-07-16 14:29:40 +0900975 if (offset) {
976 *val = readl(port_mmio + offset);
977 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 }
Tejun Heo203ef6c2007-07-16 14:29:40 +0900979 return -EINVAL;
980}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
Tejun Heo82ef04f2008-07-31 17:02:40 +0900982static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
Tejun Heo203ef6c2007-07-16 14:29:40 +0900983{
Tejun Heo82ef04f2008-07-31 17:02:40 +0900984 void __iomem *port_mmio = ahci_port_base(link->ap);
985 int offset = ahci_scr_offset(link->ap, sc_reg);
Tejun Heo203ef6c2007-07-16 14:29:40 +0900986
987 if (offset) {
988 writel(val, port_mmio + offset);
989 return 0;
990 }
991 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992}
993
Tejun Heo4447d352007-04-17 23:44:08 +0900994static void ahci_start_engine(struct ata_port *ap)
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900995{
Tejun Heo4447d352007-04-17 23:44:08 +0900996 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo7c76d1e2005-12-19 22:36:34 +0900997 u32 tmp;
998
Tejun Heod8fcd112006-07-26 15:59:25 +0900999 /* start DMA */
Tejun Heo9f592052006-07-26 15:59:26 +09001000 tmp = readl(port_mmio + PORT_CMD);
Tejun Heo7c76d1e2005-12-19 22:36:34 +09001001 tmp |= PORT_CMD_START;
1002 writel(tmp, port_mmio + PORT_CMD);
1003 readl(port_mmio + PORT_CMD); /* flush */
1004}
1005
Tejun Heo4447d352007-04-17 23:44:08 +09001006static int ahci_stop_engine(struct ata_port *ap)
Tejun Heo254950c2006-07-26 15:59:25 +09001007{
Tejun Heo4447d352007-04-17 23:44:08 +09001008 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo254950c2006-07-26 15:59:25 +09001009 u32 tmp;
1010
1011 tmp = readl(port_mmio + PORT_CMD);
1012
Tejun Heod8fcd112006-07-26 15:59:25 +09001013 /* check if the HBA is idle */
Tejun Heo254950c2006-07-26 15:59:25 +09001014 if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
1015 return 0;
1016
Tejun Heod8fcd112006-07-26 15:59:25 +09001017 /* setting HBA to idle */
Tejun Heo254950c2006-07-26 15:59:25 +09001018 tmp &= ~PORT_CMD_START;
1019 writel(tmp, port_mmio + PORT_CMD);
1020
Tejun Heod8fcd112006-07-26 15:59:25 +09001021 /* wait for engine to stop. This could be as long as 500 msec */
Tejun Heo254950c2006-07-26 15:59:25 +09001022 tmp = ata_wait_register(port_mmio + PORT_CMD,
Jeff Garzik2dcb4072007-10-19 06:42:56 -04001023 PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
Tejun Heod8fcd112006-07-26 15:59:25 +09001024 if (tmp & PORT_CMD_LIST_ON)
Tejun Heo254950c2006-07-26 15:59:25 +09001025 return -EIO;
1026
1027 return 0;
1028}
1029
Tejun Heo4447d352007-04-17 23:44:08 +09001030static void ahci_start_fis_rx(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001031{
Tejun Heo4447d352007-04-17 23:44:08 +09001032 void __iomem *port_mmio = ahci_port_base(ap);
1033 struct ahci_host_priv *hpriv = ap->host->private_data;
1034 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo0be0aa92006-07-26 15:59:26 +09001035 u32 tmp;
1036
1037 /* set FIS registers */
Tejun Heo4447d352007-04-17 23:44:08 +09001038 if (hpriv->cap & HOST_CAP_64)
1039 writel((pp->cmd_slot_dma >> 16) >> 16,
1040 port_mmio + PORT_LST_ADDR_HI);
1041 writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001042
Tejun Heo4447d352007-04-17 23:44:08 +09001043 if (hpriv->cap & HOST_CAP_64)
1044 writel((pp->rx_fis_dma >> 16) >> 16,
1045 port_mmio + PORT_FIS_ADDR_HI);
1046 writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001047
1048 /* enable FIS reception */
1049 tmp = readl(port_mmio + PORT_CMD);
1050 tmp |= PORT_CMD_FIS_RX;
1051 writel(tmp, port_mmio + PORT_CMD);
1052
1053 /* flush */
1054 readl(port_mmio + PORT_CMD);
1055}
1056
Tejun Heo4447d352007-04-17 23:44:08 +09001057static int ahci_stop_fis_rx(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001058{
Tejun Heo4447d352007-04-17 23:44:08 +09001059 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001060 u32 tmp;
1061
1062 /* disable FIS reception */
1063 tmp = readl(port_mmio + PORT_CMD);
1064 tmp &= ~PORT_CMD_FIS_RX;
1065 writel(tmp, port_mmio + PORT_CMD);
1066
1067 /* wait for completion, spec says 500ms, give it 1000 */
1068 tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
1069 PORT_CMD_FIS_ON, 10, 1000);
1070 if (tmp & PORT_CMD_FIS_ON)
1071 return -EBUSY;
1072
1073 return 0;
1074}
1075
Tejun Heo4447d352007-04-17 23:44:08 +09001076static void ahci_power_up(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001077{
Tejun Heo4447d352007-04-17 23:44:08 +09001078 struct ahci_host_priv *hpriv = ap->host->private_data;
1079 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001080 u32 cmd;
1081
1082 cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
1083
1084 /* spin up device */
Tejun Heo4447d352007-04-17 23:44:08 +09001085 if (hpriv->cap & HOST_CAP_SSS) {
Tejun Heo0be0aa92006-07-26 15:59:26 +09001086 cmd |= PORT_CMD_SPIN_UP;
1087 writel(cmd, port_mmio + PORT_CMD);
1088 }
1089
1090 /* wake up link */
1091 writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
1092}
1093
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04001094static void ahci_disable_alpm(struct ata_port *ap)
1095{
1096 struct ahci_host_priv *hpriv = ap->host->private_data;
1097 void __iomem *port_mmio = ahci_port_base(ap);
1098 u32 cmd;
1099 struct ahci_port_priv *pp = ap->private_data;
1100
1101 /* IPM bits should be disabled by libata-core */
1102 /* get the existing command bits */
1103 cmd = readl(port_mmio + PORT_CMD);
1104
1105 /* disable ALPM and ASP */
1106 cmd &= ~PORT_CMD_ASP;
1107 cmd &= ~PORT_CMD_ALPE;
1108
1109 /* force the interface back to active */
1110 cmd |= PORT_CMD_ICC_ACTIVE;
1111
1112 /* write out new cmd value */
1113 writel(cmd, port_mmio + PORT_CMD);
1114 cmd = readl(port_mmio + PORT_CMD);
1115
1116 /* wait 10ms to be sure we've come out of any low power state */
1117 msleep(10);
1118
1119 /* clear out any PhyRdy stuff from interrupt status */
1120 writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
1121
1122 /* go ahead and clean out PhyRdy Change from Serror too */
Tejun Heo82ef04f2008-07-31 17:02:40 +09001123 ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04001124
1125 /*
1126 * Clear flag to indicate that we should ignore all PhyRdy
1127 * state changes
1128 */
1129 hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
1130
1131 /*
1132 * Enable interrupts on Phy Ready.
1133 */
1134 pp->intr_mask |= PORT_IRQ_PHYRDY;
1135 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
1136
1137 /*
1138 * don't change the link pm policy - we can be called
1139 * just to turn of link pm temporarily
1140 */
1141}
1142
1143static int ahci_enable_alpm(struct ata_port *ap,
1144 enum link_pm policy)
1145{
1146 struct ahci_host_priv *hpriv = ap->host->private_data;
1147 void __iomem *port_mmio = ahci_port_base(ap);
1148 u32 cmd;
1149 struct ahci_port_priv *pp = ap->private_data;
1150 u32 asp;
1151
1152 /* Make sure the host is capable of link power management */
1153 if (!(hpriv->cap & HOST_CAP_ALPM))
1154 return -EINVAL;
1155
1156 switch (policy) {
1157 case MAX_PERFORMANCE:
1158 case NOT_AVAILABLE:
1159 /*
1160 * if we came here with NOT_AVAILABLE,
1161 * it just means this is the first time we
1162 * have tried to enable - default to max performance,
1163 * and let the user go to lower power modes on request.
1164 */
1165 ahci_disable_alpm(ap);
1166 return 0;
1167 case MIN_POWER:
1168 /* configure HBA to enter SLUMBER */
1169 asp = PORT_CMD_ASP;
1170 break;
1171 case MEDIUM_POWER:
1172 /* configure HBA to enter PARTIAL */
1173 asp = 0;
1174 break;
1175 default:
1176 return -EINVAL;
1177 }
1178
1179 /*
1180 * Disable interrupts on Phy Ready. This keeps us from
1181 * getting woken up due to spurious phy ready interrupts
1182 * TBD - Hot plug should be done via polling now, is
1183 * that even supported?
1184 */
1185 pp->intr_mask &= ~PORT_IRQ_PHYRDY;
1186 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
1187
1188 /*
1189 * Set a flag to indicate that we should ignore all PhyRdy
1190 * state changes since these can happen now whenever we
1191 * change link state
1192 */
1193 hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
1194
1195 /* get the existing command bits */
1196 cmd = readl(port_mmio + PORT_CMD);
1197
1198 /*
1199 * Set ASP based on Policy
1200 */
1201 cmd |= asp;
1202
1203 /*
1204 * Setting this bit will instruct the HBA to aggressively
1205 * enter a lower power link state when it's appropriate and
1206 * based on the value set above for ASP
1207 */
1208 cmd |= PORT_CMD_ALPE;
1209
1210 /* write out new cmd value */
1211 writel(cmd, port_mmio + PORT_CMD);
1212 cmd = readl(port_mmio + PORT_CMD);
1213
1214 /* IPM bits should be set by libata-core */
1215 return 0;
1216}
1217
Tejun Heo438ac6d2007-03-02 17:31:26 +09001218#ifdef CONFIG_PM
Tejun Heo4447d352007-04-17 23:44:08 +09001219static void ahci_power_down(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001220{
Tejun Heo4447d352007-04-17 23:44:08 +09001221 struct ahci_host_priv *hpriv = ap->host->private_data;
1222 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001223 u32 cmd, scontrol;
1224
Tejun Heo4447d352007-04-17 23:44:08 +09001225 if (!(hpriv->cap & HOST_CAP_SSS))
Tejun Heo07c53da2007-01-21 02:10:11 +09001226 return;
1227
1228 /* put device into listen mode, first set PxSCTL.DET to 0 */
1229 scontrol = readl(port_mmio + PORT_SCR_CTL);
1230 scontrol &= ~0xf;
1231 writel(scontrol, port_mmio + PORT_SCR_CTL);
1232
1233 /* then set PxCMD.SUD to 0 */
Tejun Heo0be0aa92006-07-26 15:59:26 +09001234 cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
Tejun Heo07c53da2007-01-21 02:10:11 +09001235 cmd &= ~PORT_CMD_SPIN_UP;
1236 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001237}
Tejun Heo438ac6d2007-03-02 17:31:26 +09001238#endif
Tejun Heo0be0aa92006-07-26 15:59:26 +09001239
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04001240static void ahci_start_port(struct ata_port *ap)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001241{
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001242 struct ahci_port_priv *pp = ap->private_data;
1243 struct ata_link *link;
1244 struct ahci_em_priv *emp;
David Milburn4c1e9aa2009-04-03 15:36:41 -05001245 ssize_t rc;
1246 int i;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001247
Tejun Heo0be0aa92006-07-26 15:59:26 +09001248 /* enable FIS reception */
Tejun Heo4447d352007-04-17 23:44:08 +09001249 ahci_start_fis_rx(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001250
1251 /* enable DMA */
Tejun Heo4447d352007-04-17 23:44:08 +09001252 ahci_start_engine(ap);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001253
1254 /* turn on LEDs */
1255 if (ap->flags & ATA_FLAG_EM) {
Tejun Heo1eca4362008-11-03 20:03:17 +09001256 ata_for_each_link(link, ap, EDGE) {
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001257 emp = &pp->em_priv[link->pmp];
David Milburn4c1e9aa2009-04-03 15:36:41 -05001258
1259 /* EM Transmit bit maybe busy during init */
Tejun Heod50ce072009-05-12 10:57:41 +09001260 for (i = 0; i < EM_MAX_RETRY; i++) {
David Milburn4c1e9aa2009-04-03 15:36:41 -05001261 rc = ahci_transmit_led_message(ap,
1262 emp->led_state,
1263 4);
1264 if (rc == -EBUSY)
Tejun Heod50ce072009-05-12 10:57:41 +09001265 msleep(1);
David Milburn4c1e9aa2009-04-03 15:36:41 -05001266 else
1267 break;
1268 }
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001269 }
1270 }
1271
1272 if (ap->flags & ATA_FLAG_SW_ACTIVITY)
Tejun Heo1eca4362008-11-03 20:03:17 +09001273 ata_for_each_link(link, ap, EDGE)
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001274 ahci_init_sw_activity(link);
1275
Tejun Heo0be0aa92006-07-26 15:59:26 +09001276}
1277
Tejun Heo4447d352007-04-17 23:44:08 +09001278static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
Tejun Heo0be0aa92006-07-26 15:59:26 +09001279{
1280 int rc;
1281
1282 /* disable DMA */
Tejun Heo4447d352007-04-17 23:44:08 +09001283 rc = ahci_stop_engine(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001284 if (rc) {
1285 *emsg = "failed to stop engine";
1286 return rc;
1287 }
1288
1289 /* disable FIS reception */
Tejun Heo4447d352007-04-17 23:44:08 +09001290 rc = ahci_stop_fis_rx(ap);
Tejun Heo0be0aa92006-07-26 15:59:26 +09001291 if (rc) {
1292 *emsg = "failed stop FIS RX";
1293 return rc;
1294 }
1295
Tejun Heo0be0aa92006-07-26 15:59:26 +09001296 return 0;
1297}
1298
Tejun Heo4447d352007-04-17 23:44:08 +09001299static int ahci_reset_controller(struct ata_host *host)
Tejun Heod91542c2006-07-26 15:59:26 +09001300{
Tejun Heo4447d352007-04-17 23:44:08 +09001301 struct pci_dev *pdev = to_pci_dev(host->dev);
Tejun Heo49f29092007-11-19 16:03:44 +09001302 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo4447d352007-04-17 23:44:08 +09001303 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Tejun Heod447df12007-03-18 22:15:33 +09001304 u32 tmp;
Tejun Heod91542c2006-07-26 15:59:26 +09001305
Jeff Garzik3cc3eb12007-09-26 00:02:41 -04001306 /* we must be in AHCI mode, before using anything
1307 * AHCI-specific, such as HOST_RESET.
1308 */
Tejun Heob710a1f2008-01-05 23:11:57 +09001309 ahci_enable_ahci(mmio);
Jeff Garzik3cc3eb12007-09-26 00:02:41 -04001310
1311 /* global controller reset */
Tejun Heoa22e6442008-03-10 10:25:25 +09001312 if (!ahci_skip_host_reset) {
1313 tmp = readl(mmio + HOST_CTL);
1314 if ((tmp & HOST_RESET) == 0) {
1315 writel(tmp | HOST_RESET, mmio + HOST_CTL);
1316 readl(mmio + HOST_CTL); /* flush */
1317 }
Tejun Heod91542c2006-07-26 15:59:26 +09001318
Zhang Rui24920c82008-07-04 13:32:17 +08001319 /*
1320 * to perform host reset, OS should set HOST_RESET
1321 * and poll until this bit is read to be "0".
1322 * reset must complete within 1 second, or
Tejun Heoa22e6442008-03-10 10:25:25 +09001323 * the hardware should be considered fried.
1324 */
Zhang Rui24920c82008-07-04 13:32:17 +08001325 tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET,
1326 HOST_RESET, 10, 1000);
Tejun Heod91542c2006-07-26 15:59:26 +09001327
Tejun Heoa22e6442008-03-10 10:25:25 +09001328 if (tmp & HOST_RESET) {
1329 dev_printk(KERN_ERR, host->dev,
1330 "controller reset failed (0x%x)\n", tmp);
1331 return -EIO;
1332 }
Tejun Heod91542c2006-07-26 15:59:26 +09001333
Tejun Heoa22e6442008-03-10 10:25:25 +09001334 /* turn on AHCI mode */
1335 ahci_enable_ahci(mmio);
Tejun Heo98fa4b62006-11-02 12:17:23 +09001336
Tejun Heoa22e6442008-03-10 10:25:25 +09001337 /* Some registers might be cleared on reset. Restore
1338 * initial values.
1339 */
1340 ahci_restore_initial_config(host);
1341 } else
1342 dev_printk(KERN_INFO, host->dev,
1343 "skipping global host reset\n");
Tejun Heod91542c2006-07-26 15:59:26 +09001344
1345 if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
1346 u16 tmp16;
1347
1348 /* configure PCS */
1349 pci_read_config_word(pdev, 0x92, &tmp16);
Tejun Heo49f29092007-11-19 16:03:44 +09001350 if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
1351 tmp16 |= hpriv->port_map;
1352 pci_write_config_word(pdev, 0x92, tmp16);
1353 }
Tejun Heod91542c2006-07-26 15:59:26 +09001354 }
1355
1356 return 0;
1357}
1358
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001359static void ahci_sw_activity(struct ata_link *link)
1360{
1361 struct ata_port *ap = link->ap;
1362 struct ahci_port_priv *pp = ap->private_data;
1363 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1364
1365 if (!(link->flags & ATA_LFLAG_SW_ACTIVITY))
1366 return;
1367
1368 emp->activity++;
1369 if (!timer_pending(&emp->timer))
1370 mod_timer(&emp->timer, jiffies + msecs_to_jiffies(10));
1371}
1372
1373static void ahci_sw_activity_blink(unsigned long arg)
1374{
1375 struct ata_link *link = (struct ata_link *)arg;
1376 struct ata_port *ap = link->ap;
1377 struct ahci_port_priv *pp = ap->private_data;
1378 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1379 unsigned long led_message = emp->led_state;
1380 u32 activity_led_state;
David Milburneb409632008-10-16 09:26:19 -05001381 unsigned long flags;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001382
David Milburn87943ac2008-10-13 14:38:36 -05001383 led_message &= EM_MSG_LED_VALUE;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001384 led_message |= ap->port_no | (link->pmp << 8);
1385
1386 /* check to see if we've had activity. If so,
1387 * toggle state of LED and reset timer. If not,
1388 * turn LED to desired idle state.
1389 */
David Milburneb409632008-10-16 09:26:19 -05001390 spin_lock_irqsave(ap->lock, flags);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001391 if (emp->saved_activity != emp->activity) {
1392 emp->saved_activity = emp->activity;
1393 /* get the current LED state */
David Milburn87943ac2008-10-13 14:38:36 -05001394 activity_led_state = led_message & EM_MSG_LED_VALUE_ON;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001395
1396 if (activity_led_state)
1397 activity_led_state = 0;
1398 else
1399 activity_led_state = 1;
1400
1401 /* clear old state */
David Milburn87943ac2008-10-13 14:38:36 -05001402 led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001403
1404 /* toggle state */
1405 led_message |= (activity_led_state << 16);
1406 mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100));
1407 } else {
1408 /* switch to idle */
David Milburn87943ac2008-10-13 14:38:36 -05001409 led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001410 if (emp->blink_policy == BLINK_OFF)
1411 led_message |= (1 << 16);
1412 }
David Milburneb409632008-10-16 09:26:19 -05001413 spin_unlock_irqrestore(ap->lock, flags);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001414 ahci_transmit_led_message(ap, led_message, 4);
1415}
1416
1417static void ahci_init_sw_activity(struct ata_link *link)
1418{
1419 struct ata_port *ap = link->ap;
1420 struct ahci_port_priv *pp = ap->private_data;
1421 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1422
1423 /* init activity stats, setup timer */
1424 emp->saved_activity = emp->activity = 0;
1425 setup_timer(&emp->timer, ahci_sw_activity_blink, (unsigned long)link);
1426
1427 /* check our blink policy and set flag for link if it's enabled */
1428 if (emp->blink_policy)
1429 link->flags |= ATA_LFLAG_SW_ACTIVITY;
1430}
1431
1432static int ahci_reset_em(struct ata_host *host)
1433{
1434 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
1435 u32 em_ctl;
1436
1437 em_ctl = readl(mmio + HOST_EM_CTL);
1438 if ((em_ctl & EM_CTL_TM) || (em_ctl & EM_CTL_RST))
1439 return -EINVAL;
1440
1441 writel(em_ctl | EM_CTL_RST, mmio + HOST_EM_CTL);
1442 return 0;
1443}
1444
1445static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
1446 ssize_t size)
1447{
1448 struct ahci_host_priv *hpriv = ap->host->private_data;
1449 struct ahci_port_priv *pp = ap->private_data;
1450 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
1451 u32 em_ctl;
1452 u32 message[] = {0, 0};
Linus Torvalds93082f02008-07-25 10:56:36 -07001453 unsigned long flags;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001454 int pmp;
1455 struct ahci_em_priv *emp;
1456
1457 /* get the slot number from the message */
David Milburn87943ac2008-10-13 14:38:36 -05001458 pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
Tejun Heod50ce072009-05-12 10:57:41 +09001459 if (pmp < EM_MAX_SLOTS)
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001460 emp = &pp->em_priv[pmp];
1461 else
1462 return -EINVAL;
1463
1464 spin_lock_irqsave(ap->lock, flags);
1465
1466 /*
1467 * if we are still busy transmitting a previous message,
1468 * do not allow
1469 */
1470 em_ctl = readl(mmio + HOST_EM_CTL);
1471 if (em_ctl & EM_CTL_TM) {
1472 spin_unlock_irqrestore(ap->lock, flags);
David Milburn4c1e9aa2009-04-03 15:36:41 -05001473 return -EBUSY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001474 }
1475
1476 /*
1477 * create message header - this is all zero except for
1478 * the message size, which is 4 bytes.
1479 */
1480 message[0] |= (4 << 8);
1481
1482 /* ignore 0:4 of byte zero, fill in port info yourself */
David Milburn87943ac2008-10-13 14:38:36 -05001483 message[1] = ((state & ~EM_MSG_LED_HBA_PORT) | ap->port_no);
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001484
1485 /* write message to EM_LOC */
1486 writel(message[0], mmio + hpriv->em_loc);
1487 writel(message[1], mmio + hpriv->em_loc+4);
1488
1489 /* save off new led state for port/slot */
David Milburn208f2a82009-03-20 14:14:23 -05001490 emp->led_state = state;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001491
1492 /*
1493 * tell hardware to transmit the message
1494 */
1495 writel(em_ctl | EM_CTL_TM, mmio + HOST_EM_CTL);
1496
1497 spin_unlock_irqrestore(ap->lock, flags);
1498 return size;
1499}
1500
1501static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
1502{
1503 struct ahci_port_priv *pp = ap->private_data;
1504 struct ata_link *link;
1505 struct ahci_em_priv *emp;
1506 int rc = 0;
1507
Tejun Heo1eca4362008-11-03 20:03:17 +09001508 ata_for_each_link(link, ap, EDGE) {
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001509 emp = &pp->em_priv[link->pmp];
1510 rc += sprintf(buf, "%lx\n", emp->led_state);
1511 }
1512 return rc;
1513}
1514
1515static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
1516 size_t size)
1517{
1518 int state;
1519 int pmp;
1520 struct ahci_port_priv *pp = ap->private_data;
1521 struct ahci_em_priv *emp;
1522
1523 state = simple_strtoul(buf, NULL, 0);
1524
1525 /* get the slot number from the message */
David Milburn87943ac2008-10-13 14:38:36 -05001526 pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
Tejun Heod50ce072009-05-12 10:57:41 +09001527 if (pmp < EM_MAX_SLOTS)
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001528 emp = &pp->em_priv[pmp];
1529 else
1530 return -EINVAL;
1531
1532 /* mask off the activity bits if we are in sw_activity
1533 * mode, user should turn off sw_activity before setting
1534 * activity led through em_message
1535 */
1536 if (emp->blink_policy)
David Milburn87943ac2008-10-13 14:38:36 -05001537 state &= ~EM_MSG_LED_VALUE_ACTIVITY;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001538
1539 return ahci_transmit_led_message(ap, state, size);
1540}
1541
1542static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)
1543{
1544 struct ata_link *link = dev->link;
1545 struct ata_port *ap = link->ap;
1546 struct ahci_port_priv *pp = ap->private_data;
1547 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1548 u32 port_led_state = emp->led_state;
1549
1550 /* save the desired Activity LED behavior */
1551 if (val == OFF) {
1552 /* clear LFLAG */
1553 link->flags &= ~(ATA_LFLAG_SW_ACTIVITY);
1554
1555 /* set the LED to OFF */
David Milburn87943ac2008-10-13 14:38:36 -05001556 port_led_state &= EM_MSG_LED_VALUE_OFF;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001557 port_led_state |= (ap->port_no | (link->pmp << 8));
1558 ahci_transmit_led_message(ap, port_led_state, 4);
1559 } else {
1560 link->flags |= ATA_LFLAG_SW_ACTIVITY;
1561 if (val == BLINK_OFF) {
1562 /* set LED to ON for idle */
David Milburn87943ac2008-10-13 14:38:36 -05001563 port_led_state &= EM_MSG_LED_VALUE_OFF;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001564 port_led_state |= (ap->port_no | (link->pmp << 8));
David Milburn87943ac2008-10-13 14:38:36 -05001565 port_led_state |= EM_MSG_LED_VALUE_ON; /* check this */
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07001566 ahci_transmit_led_message(ap, port_led_state, 4);
1567 }
1568 }
1569 emp->blink_policy = val;
1570 return 0;
1571}
1572
1573static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
1574{
1575 struct ata_link *link = dev->link;
1576 struct ata_port *ap = link->ap;
1577 struct ahci_port_priv *pp = ap->private_data;
1578 struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1579
1580 /* display the saved value of activity behavior for this
1581 * disk.
1582 */
1583 return sprintf(buf, "%d\n", emp->blink_policy);
1584}
1585
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001586static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
1587 int port_no, void __iomem *mmio,
1588 void __iomem *port_mmio)
1589{
1590 const char *emsg = NULL;
1591 int rc;
1592 u32 tmp;
1593
1594 /* make sure port is not active */
1595 rc = ahci_deinit_port(ap, &emsg);
1596 if (rc)
1597 dev_printk(KERN_WARNING, &pdev->dev,
1598 "%s (%d)\n", emsg, rc);
1599
1600 /* clear SError */
1601 tmp = readl(port_mmio + PORT_SCR_ERR);
1602 VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
1603 writel(tmp, port_mmio + PORT_SCR_ERR);
1604
1605 /* clear port IRQ */
1606 tmp = readl(port_mmio + PORT_IRQ_STAT);
1607 VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
1608 if (tmp)
1609 writel(tmp, port_mmio + PORT_IRQ_STAT);
1610
1611 writel(1 << port_no, mmio + HOST_IRQ_STAT);
1612}
1613
Tejun Heo4447d352007-04-17 23:44:08 +09001614static void ahci_init_controller(struct ata_host *host)
Tejun Heod91542c2006-07-26 15:59:26 +09001615{
Tejun Heo417a1a62007-09-23 13:19:55 +09001616 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo4447d352007-04-17 23:44:08 +09001617 struct pci_dev *pdev = to_pci_dev(host->dev);
1618 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001619 int i;
Jeff Garzikcd70c262007-07-08 02:29:42 -04001620 void __iomem *port_mmio;
Tejun Heod91542c2006-07-26 15:59:26 +09001621 u32 tmp;
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +01001622 int mv;
Tejun Heod91542c2006-07-26 15:59:26 +09001623
Tejun Heo417a1a62007-09-23 13:19:55 +09001624 if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
Jose Alberto Regueroc40e7cb2008-03-13 23:22:24 +01001625 if (pdev->device == 0x6121)
1626 mv = 2;
1627 else
1628 mv = 4;
1629 port_mmio = __ahci_port_base(host, mv);
Jeff Garzikcd70c262007-07-08 02:29:42 -04001630
1631 writel(0, port_mmio + PORT_IRQ_MASK);
1632
1633 /* clear port IRQ */
1634 tmp = readl(port_mmio + PORT_IRQ_STAT);
1635 VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
1636 if (tmp)
1637 writel(tmp, port_mmio + PORT_IRQ_STAT);
1638 }
1639
Tejun Heo4447d352007-04-17 23:44:08 +09001640 for (i = 0; i < host->n_ports; i++) {
1641 struct ata_port *ap = host->ports[i];
Tejun Heod91542c2006-07-26 15:59:26 +09001642
Jeff Garzikcd70c262007-07-08 02:29:42 -04001643 port_mmio = ahci_port_base(ap);
Tejun Heo4447d352007-04-17 23:44:08 +09001644 if (ata_port_is_dummy(ap))
Tejun Heod91542c2006-07-26 15:59:26 +09001645 continue;
Tejun Heod91542c2006-07-26 15:59:26 +09001646
Jeff Garzik2bcd8662007-05-28 07:45:27 -04001647 ahci_port_init(pdev, ap, i, mmio, port_mmio);
Tejun Heod91542c2006-07-26 15:59:26 +09001648 }
1649
1650 tmp = readl(mmio + HOST_CTL);
1651 VPRINTK("HOST_CTL 0x%x\n", tmp);
1652 writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
1653 tmp = readl(mmio + HOST_CTL);
1654 VPRINTK("HOST_CTL 0x%x\n", tmp);
1655}
1656
Jeff Garzika8785392008-02-28 15:43:48 -05001657static void ahci_dev_config(struct ata_device *dev)
1658{
1659 struct ahci_host_priv *hpriv = dev->link->ap->host->private_data;
1660
Jeff Garzik4cde32f2008-03-24 22:40:40 -04001661 if (hpriv->flags & AHCI_HFLAG_SECT255) {
Jeff Garzika8785392008-02-28 15:43:48 -05001662 dev->max_sectors = 255;
Jeff Garzik4cde32f2008-03-24 22:40:40 -04001663 ata_dev_printk(dev, KERN_INFO,
1664 "SB600 AHCI: limiting to 255 sectors per cmd\n");
1665 }
Jeff Garzika8785392008-02-28 15:43:48 -05001666}
1667
Tejun Heo422b7592005-12-19 22:37:17 +09001668static unsigned int ahci_dev_classify(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669{
Tejun Heo4447d352007-04-17 23:44:08 +09001670 void __iomem *port_mmio = ahci_port_base(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 struct ata_taskfile tf;
Tejun Heo422b7592005-12-19 22:37:17 +09001672 u32 tmp;
1673
1674 tmp = readl(port_mmio + PORT_SIG);
1675 tf.lbah = (tmp >> 24) & 0xff;
1676 tf.lbam = (tmp >> 16) & 0xff;
1677 tf.lbal = (tmp >> 8) & 0xff;
1678 tf.nsect = (tmp) & 0xff;
1679
1680 return ata_dev_classify(&tf);
1681}
1682
Tejun Heo12fad3f2006-05-15 21:03:55 +09001683static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
1684 u32 opts)
Tejun Heocc9278e2006-02-10 17:25:47 +09001685{
Tejun Heo12fad3f2006-05-15 21:03:55 +09001686 dma_addr_t cmd_tbl_dma;
1687
1688 cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
1689
1690 pp->cmd_slot[tag].opts = cpu_to_le32(opts);
1691 pp->cmd_slot[tag].status = 0;
1692 pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
1693 pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
Tejun Heocc9278e2006-02-10 17:25:47 +09001694}
1695
Shane Huang78d5ae32009-08-07 15:05:52 +08001696static int ahci_kick_engine(struct ata_port *ap)
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001697{
Tejun Heo350756f2008-04-07 22:47:21 +09001698 void __iomem *port_mmio = ahci_port_base(ap);
Jeff Garzikcca39742006-08-24 03:19:22 -04001699 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo520d06f2008-04-07 22:47:21 +09001700 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001701 u32 tmp;
Tejun Heod2e75df2007-07-16 14:29:39 +09001702 int busy, rc;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001703
Tejun Heod2e75df2007-07-16 14:29:39 +09001704 /* stop engine */
1705 rc = ahci_stop_engine(ap);
1706 if (rc)
1707 goto out_restart;
1708
Shane Huang78d5ae32009-08-07 15:05:52 +08001709 /* need to do CLO?
1710 * always do CLO if PMP is attached (AHCI-1.3 9.2)
1711 */
1712 busy = status & (ATA_BUSY | ATA_DRQ);
1713 if (!busy && !sata_pmp_attached(ap)) {
Tejun Heod2e75df2007-07-16 14:29:39 +09001714 rc = 0;
1715 goto out_restart;
1716 }
1717
1718 if (!(hpriv->cap & HOST_CAP_CLO)) {
1719 rc = -EOPNOTSUPP;
1720 goto out_restart;
1721 }
1722
1723 /* perform CLO */
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001724 tmp = readl(port_mmio + PORT_CMD);
1725 tmp |= PORT_CMD_CLO;
1726 writel(tmp, port_mmio + PORT_CMD);
1727
Tejun Heod2e75df2007-07-16 14:29:39 +09001728 rc = 0;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001729 tmp = ata_wait_register(port_mmio + PORT_CMD,
1730 PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
1731 if (tmp & PORT_CMD_CLO)
Tejun Heod2e75df2007-07-16 14:29:39 +09001732 rc = -EIO;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001733
Tejun Heod2e75df2007-07-16 14:29:39 +09001734 /* restart engine */
1735 out_restart:
1736 ahci_start_engine(ap);
1737 return rc;
Bastiaan Jacquesbf2af2a2006-04-17 14:17:59 +02001738}
1739
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001740static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
1741 struct ata_taskfile *tf, int is_cmd, u16 flags,
1742 unsigned long timeout_msec)
1743{
1744 const u32 cmd_fis_len = 5; /* five dwords */
1745 struct ahci_port_priv *pp = ap->private_data;
1746 void __iomem *port_mmio = ahci_port_base(ap);
1747 u8 *fis = pp->cmd_tbl;
1748 u32 tmp;
1749
1750 /* prep the command */
1751 ata_tf_to_fis(tf, pmp, is_cmd, fis);
1752 ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12));
1753
1754 /* issue & wait */
1755 writel(1, port_mmio + PORT_CMD_ISSUE);
1756
1757 if (timeout_msec) {
1758 tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1,
1759 1, timeout_msec);
1760 if (tmp & 0x1) {
Shane Huang78d5ae32009-08-07 15:05:52 +08001761 ahci_kick_engine(ap);
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001762 return -EBUSY;
1763 }
1764 } else
1765 readl(port_mmio + PORT_CMD_ISSUE); /* flush */
1766
1767 return 0;
1768}
1769
Shane Huangbd172432008-06-10 15:52:04 +08001770static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
1771 int pmp, unsigned long deadline,
1772 int (*check_ready)(struct ata_link *link))
Tejun Heo4658f792006-03-22 21:07:03 +09001773{
Tejun Heocc0680a2007-08-06 18:36:23 +09001774 struct ata_port *ap = link->ap;
Tejun Heo55946392009-08-04 14:30:08 +09001775 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo4658f792006-03-22 21:07:03 +09001776 const char *reason = NULL;
Tejun Heo2cbb79e2007-07-16 14:29:38 +09001777 unsigned long now, msecs;
Tejun Heo4658f792006-03-22 21:07:03 +09001778 struct ata_taskfile tf;
Tejun Heo4658f792006-03-22 21:07:03 +09001779 int rc;
1780
1781 DPRINTK("ENTER\n");
1782
1783 /* prepare for SRST (AHCI-1.1 10.4.1) */
Shane Huang78d5ae32009-08-07 15:05:52 +08001784 rc = ahci_kick_engine(ap);
Tejun Heo994056d2007-12-06 15:02:48 +09001785 if (rc && rc != -EOPNOTSUPP)
Tejun Heocc0680a2007-08-06 18:36:23 +09001786 ata_link_printk(link, KERN_WARNING,
Tejun Heo994056d2007-12-06 15:02:48 +09001787 "failed to reset engine (errno=%d)\n", rc);
Tejun Heo4658f792006-03-22 21:07:03 +09001788
Tejun Heocc0680a2007-08-06 18:36:23 +09001789 ata_tf_init(link->device, &tf);
Tejun Heo4658f792006-03-22 21:07:03 +09001790
1791 /* issue the first D2H Register FIS */
Tejun Heo2cbb79e2007-07-16 14:29:38 +09001792 msecs = 0;
1793 now = jiffies;
1794 if (time_after(now, deadline))
1795 msecs = jiffies_to_msecs(deadline - now);
1796
Tejun Heo4658f792006-03-22 21:07:03 +09001797 tf.ctl |= ATA_SRST;
Tejun Heoa9cf5e82007-07-16 14:29:39 +09001798 if (ahci_exec_polled_cmd(ap, pmp, &tf, 0,
Tejun Heo91c4a2e2007-07-16 14:29:39 +09001799 AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs)) {
Tejun Heo4658f792006-03-22 21:07:03 +09001800 rc = -EIO;
1801 reason = "1st FIS failed";
1802 goto fail;
1803 }
1804
1805 /* spec says at least 5us, but be generous and sleep for 1ms */
1806 msleep(1);
1807
1808 /* issue the second D2H Register FIS */
Tejun Heo4658f792006-03-22 21:07:03 +09001809 tf.ctl &= ~ATA_SRST;
Tejun Heoa9cf5e82007-07-16 14:29:39 +09001810 ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
Tejun Heo4658f792006-03-22 21:07:03 +09001811
Tejun Heo705e76b2008-04-07 22:47:19 +09001812 /* wait for link to become ready */
Shane Huangbd172432008-06-10 15:52:04 +08001813 rc = ata_wait_after_reset(link, deadline, check_ready);
Tejun Heo55946392009-08-04 14:30:08 +09001814 if (rc == -EBUSY && hpriv->flags & AHCI_HFLAG_SRST_TOUT_IS_OFFLINE) {
1815 /*
1816 * Workaround for cases where link online status can't
1817 * be trusted. Treat device readiness timeout as link
1818 * offline.
1819 */
1820 ata_link_printk(link, KERN_INFO,
1821 "device not ready, treating as offline\n");
1822 *class = ATA_DEV_NONE;
1823 } else if (rc) {
1824 /* link occupied, -ENODEV too is an error */
Tejun Heo9b893912007-02-02 16:50:52 +09001825 reason = "device not ready";
1826 goto fail;
Tejun Heo55946392009-08-04 14:30:08 +09001827 } else
1828 *class = ahci_dev_classify(ap);
Tejun Heo4658f792006-03-22 21:07:03 +09001829
1830 DPRINTK("EXIT, class=%u\n", *class);
1831 return 0;
1832
Tejun Heo4658f792006-03-22 21:07:03 +09001833 fail:
Tejun Heocc0680a2007-08-06 18:36:23 +09001834 ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
Tejun Heo4658f792006-03-22 21:07:03 +09001835 return rc;
1836}
1837
Shane Huangbd172432008-06-10 15:52:04 +08001838static int ahci_check_ready(struct ata_link *link)
1839{
1840 void __iomem *port_mmio = ahci_port_base(link->ap);
1841 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1842
1843 return ata_check_ready(status);
1844}
1845
1846static int ahci_softreset(struct ata_link *link, unsigned int *class,
1847 unsigned long deadline)
1848{
1849 int pmp = sata_srst_pmp(link);
1850
1851 DPRINTK("ENTER\n");
1852
1853 return ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
1854}
1855
1856static int ahci_sb600_check_ready(struct ata_link *link)
1857{
1858 void __iomem *port_mmio = ahci_port_base(link->ap);
1859 u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1860 u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
1861
1862 /*
1863 * There is no need to check TFDATA if BAD PMP is found due to HW bug,
1864 * which can save timeout delay.
1865 */
1866 if (irq_status & PORT_IRQ_BAD_PMP)
1867 return -EIO;
1868
1869 return ata_check_ready(status);
1870}
1871
1872static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
1873 unsigned long deadline)
1874{
1875 struct ata_port *ap = link->ap;
1876 void __iomem *port_mmio = ahci_port_base(ap);
1877 int pmp = sata_srst_pmp(link);
1878 int rc;
1879 u32 irq_sts;
1880
1881 DPRINTK("ENTER\n");
1882
1883 rc = ahci_do_softreset(link, class, pmp, deadline,
1884 ahci_sb600_check_ready);
1885
1886 /*
1887 * Soft reset fails on some ATI chips with IPMS set when PMP
1888 * is enabled but SATA HDD/ODD is connected to SATA port,
1889 * do soft reset again to port 0.
1890 */
1891 if (rc == -EIO) {
1892 irq_sts = readl(port_mmio + PORT_IRQ_STAT);
1893 if (irq_sts & PORT_IRQ_BAD_PMP) {
1894 ata_link_printk(link, KERN_WARNING,
Shane Huangb6931c12009-08-05 10:10:41 +08001895 "applying SB600 PMP SRST workaround "
1896 "and retrying\n");
Shane Huangbd172432008-06-10 15:52:04 +08001897 rc = ahci_do_softreset(link, class, 0, deadline,
1898 ahci_check_ready);
1899 }
1900 }
1901
1902 return rc;
1903}
1904
Tejun Heocc0680a2007-08-06 18:36:23 +09001905static int ahci_hardreset(struct ata_link *link, unsigned int *class,
Tejun Heod4b2bab2007-02-02 16:50:52 +09001906 unsigned long deadline)
Tejun Heo422b7592005-12-19 22:37:17 +09001907{
Tejun Heo9dadd452008-04-07 22:47:19 +09001908 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
Tejun Heocc0680a2007-08-06 18:36:23 +09001909 struct ata_port *ap = link->ap;
Tejun Heo42969712006-05-31 18:28:18 +09001910 struct ahci_port_priv *pp = ap->private_data;
1911 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1912 struct ata_taskfile tf;
Tejun Heo9dadd452008-04-07 22:47:19 +09001913 bool online;
Tejun Heo4bd00f62006-02-11 16:26:02 +09001914 int rc;
1915
1916 DPRINTK("ENTER\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
Tejun Heo4447d352007-04-17 23:44:08 +09001918 ahci_stop_engine(ap);
Tejun Heo42969712006-05-31 18:28:18 +09001919
1920 /* clear D2H reception area to properly wait for D2H FIS */
Tejun Heocc0680a2007-08-06 18:36:23 +09001921 ata_tf_init(link->device, &tf);
Tejun Heodfd7a3d2007-01-26 15:37:20 +09001922 tf.command = 0x80;
Tejun Heo99771262007-07-16 14:29:38 +09001923 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
Tejun Heo42969712006-05-31 18:28:18 +09001924
Tejun Heo9dadd452008-04-07 22:47:19 +09001925 rc = sata_link_hardreset(link, timing, deadline, &online,
1926 ahci_check_ready);
Tejun Heo42969712006-05-31 18:28:18 +09001927
Tejun Heo4447d352007-04-17 23:44:08 +09001928 ahci_start_engine(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929
Tejun Heo9dadd452008-04-07 22:47:19 +09001930 if (online)
Tejun Heo4bd00f62006-02-11 16:26:02 +09001931 *class = ahci_dev_classify(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932
Tejun Heo4bd00f62006-02-11 16:26:02 +09001933 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
1934 return rc;
1935}
1936
Tejun Heocc0680a2007-08-06 18:36:23 +09001937static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
Tejun Heod4b2bab2007-02-02 16:50:52 +09001938 unsigned long deadline)
Tejun Heoad616ff2006-11-01 18:00:24 +09001939{
Tejun Heocc0680a2007-08-06 18:36:23 +09001940 struct ata_port *ap = link->ap;
Tejun Heo9dadd452008-04-07 22:47:19 +09001941 bool online;
Tejun Heoad616ff2006-11-01 18:00:24 +09001942 int rc;
1943
1944 DPRINTK("ENTER\n");
1945
Tejun Heo4447d352007-04-17 23:44:08 +09001946 ahci_stop_engine(ap);
Tejun Heoad616ff2006-11-01 18:00:24 +09001947
Tejun Heocc0680a2007-08-06 18:36:23 +09001948 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
Tejun Heo9dadd452008-04-07 22:47:19 +09001949 deadline, &online, NULL);
Tejun Heoad616ff2006-11-01 18:00:24 +09001950
Tejun Heo4447d352007-04-17 23:44:08 +09001951 ahci_start_engine(ap);
Tejun Heoad616ff2006-11-01 18:00:24 +09001952
1953 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
1954
1955 /* vt8251 doesn't clear BSY on signature FIS reception,
1956 * request follow-up softreset.
1957 */
Tejun Heo9dadd452008-04-07 22:47:19 +09001958 return online ? -EAGAIN : rc;
Tejun Heoad616ff2006-11-01 18:00:24 +09001959}
1960
Tejun Heoedc93052007-10-25 14:59:16 +09001961static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
1962 unsigned long deadline)
1963{
1964 struct ata_port *ap = link->ap;
1965 struct ahci_port_priv *pp = ap->private_data;
1966 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1967 struct ata_taskfile tf;
Tejun Heo9dadd452008-04-07 22:47:19 +09001968 bool online;
Tejun Heoedc93052007-10-25 14:59:16 +09001969 int rc;
1970
1971 ahci_stop_engine(ap);
1972
1973 /* clear D2H reception area to properly wait for D2H FIS */
1974 ata_tf_init(link->device, &tf);
1975 tf.command = 0x80;
1976 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
1977
1978 rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
Tejun Heo9dadd452008-04-07 22:47:19 +09001979 deadline, &online, NULL);
Tejun Heoedc93052007-10-25 14:59:16 +09001980
1981 ahci_start_engine(ap);
1982
Tejun Heoedc93052007-10-25 14:59:16 +09001983 /* The pseudo configuration device on SIMG4726 attached to
1984 * ASUS P5W-DH Deluxe doesn't send signature FIS after
1985 * hardreset if no device is attached to the first downstream
1986 * port && the pseudo device locks up on SRST w/ PMP==0. To
1987 * work around this, wait for !BSY only briefly. If BSY isn't
1988 * cleared, perform CLO and proceed to IDENTIFY (achieved by
1989 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
1990 *
1991 * Wait for two seconds. Devices attached to downstream port
1992 * which can't process the following IDENTIFY after this will
1993 * have to be reset again. For most cases, this should
1994 * suffice while making probing snappish enough.
1995 */
Tejun Heo9dadd452008-04-07 22:47:19 +09001996 if (online) {
1997 rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
1998 ahci_check_ready);
1999 if (rc)
Shane Huang78d5ae32009-08-07 15:05:52 +08002000 ahci_kick_engine(ap);
Tejun Heo9dadd452008-04-07 22:47:19 +09002001 }
Tejun Heo9dadd452008-04-07 22:47:19 +09002002 return rc;
Tejun Heoedc93052007-10-25 14:59:16 +09002003}
2004
Tejun Heocc0680a2007-08-06 18:36:23 +09002005static void ahci_postreset(struct ata_link *link, unsigned int *class)
Tejun Heo4bd00f62006-02-11 16:26:02 +09002006{
Tejun Heocc0680a2007-08-06 18:36:23 +09002007 struct ata_port *ap = link->ap;
Tejun Heo4447d352007-04-17 23:44:08 +09002008 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo4bd00f62006-02-11 16:26:02 +09002009 u32 new_tmp, tmp;
2010
Tejun Heo203c75b2008-04-07 22:47:18 +09002011 ata_std_postreset(link, class);
Jeff Garzik02eaa662005-11-12 01:32:19 -05002012
2013 /* Make sure port's ATAPI bit is set appropriately */
2014 new_tmp = tmp = readl(port_mmio + PORT_CMD);
Tejun Heo4bd00f62006-02-11 16:26:02 +09002015 if (*class == ATA_DEV_ATAPI)
Jeff Garzik02eaa662005-11-12 01:32:19 -05002016 new_tmp |= PORT_CMD_ATAPI;
2017 else
2018 new_tmp &= ~PORT_CMD_ATAPI;
2019 if (new_tmp != tmp) {
2020 writel(new_tmp, port_mmio + PORT_CMD);
2021 readl(port_mmio + PORT_CMD); /* flush */
2022 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023}
2024
Tejun Heo12fad3f2006-05-15 21:03:55 +09002025static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026{
Jeff Garzikcedc9a42005-10-05 07:13:30 -04002027 struct scatterlist *sg;
Tejun Heoff2aeb12007-12-05 16:43:11 +09002028 struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
2029 unsigned int si;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030
2031 VPRINTK("ENTER\n");
2032
2033 /*
2034 * Next, the S/G list.
2035 */
Tejun Heoff2aeb12007-12-05 16:43:11 +09002036 for_each_sg(qc->sg, sg, qc->n_elem, si) {
Jeff Garzikcedc9a42005-10-05 07:13:30 -04002037 dma_addr_t addr = sg_dma_address(sg);
2038 u32 sg_len = sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039
Tejun Heoff2aeb12007-12-05 16:43:11 +09002040 ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
2041 ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
2042 ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 }
Jeff Garzik828d09d2005-11-12 01:27:07 -05002044
Tejun Heoff2aeb12007-12-05 16:43:11 +09002045 return si;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046}
2047
2048static void ahci_qc_prep(struct ata_queued_cmd *qc)
2049{
Jeff Garzika0ea7322005-06-04 01:13:15 -04002050 struct ata_port *ap = qc->ap;
2051 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo405e66b2007-11-27 19:28:53 +09002052 int is_atapi = ata_is_atapi(qc->tf.protocol);
Tejun Heo12fad3f2006-05-15 21:03:55 +09002053 void *cmd_tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 u32 opts;
2055 const u32 cmd_fis_len = 5; /* five dwords */
Jeff Garzik828d09d2005-11-12 01:27:07 -05002056 unsigned int n_elem;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057
2058 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 * Fill in command table information. First, the header,
2060 * a SATA Register - Host to Device command FIS.
2061 */
Tejun Heo12fad3f2006-05-15 21:03:55 +09002062 cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
2063
Tejun Heo7d50b602007-09-23 13:19:54 +09002064 ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl);
Tejun Heocc9278e2006-02-10 17:25:47 +09002065 if (is_atapi) {
Tejun Heo12fad3f2006-05-15 21:03:55 +09002066 memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
2067 memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
Jeff Garzika0ea7322005-06-04 01:13:15 -04002068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
Tejun Heocc9278e2006-02-10 17:25:47 +09002070 n_elem = 0;
2071 if (qc->flags & ATA_QCFLAG_DMAMAP)
Tejun Heo12fad3f2006-05-15 21:03:55 +09002072 n_elem = ahci_fill_sg(qc, cmd_tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073
Tejun Heocc9278e2006-02-10 17:25:47 +09002074 /*
2075 * Fill in command slot information.
2076 */
Tejun Heo7d50b602007-09-23 13:19:54 +09002077 opts = cmd_fis_len | n_elem << 16 | (qc->dev->link->pmp << 12);
Tejun Heocc9278e2006-02-10 17:25:47 +09002078 if (qc->tf.flags & ATA_TFLAG_WRITE)
2079 opts |= AHCI_CMD_WRITE;
2080 if (is_atapi)
Tejun Heo4b10e552006-03-12 11:25:27 +09002081 opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
Jeff Garzik828d09d2005-11-12 01:27:07 -05002082
Tejun Heo12fad3f2006-05-15 21:03:55 +09002083 ahci_fill_cmd_slot(pp, qc->tag, opts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084}
2085
Tejun Heo78cd52d2006-05-15 20:58:29 +09002086static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087{
Tejun Heo417a1a62007-09-23 13:19:55 +09002088 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002089 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002090 struct ata_eh_info *host_ehi = &ap->link.eh_info;
2091 struct ata_link *link = NULL;
2092 struct ata_queued_cmd *active_qc;
2093 struct ata_eh_info *active_ehi;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002094 u32 serror;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095
Tejun Heo7d50b602007-09-23 13:19:54 +09002096 /* determine active link */
Tejun Heo1eca4362008-11-03 20:03:17 +09002097 ata_for_each_link(link, ap, EDGE)
Tejun Heo7d50b602007-09-23 13:19:54 +09002098 if (ata_link_active(link))
2099 break;
2100 if (!link)
2101 link = &ap->link;
2102
2103 active_qc = ata_qc_from_tag(ap, link->active_tag);
2104 active_ehi = &link->eh_info;
2105
2106 /* record irq stat */
2107 ata_ehi_clear_desc(host_ehi);
2108 ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);
Jeff Garzik9f68a242005-11-15 14:03:47 -05002109
Tejun Heo78cd52d2006-05-15 20:58:29 +09002110 /* AHCI needs SError cleared; otherwise, it might lock up */
Tejun Heo82ef04f2008-07-31 17:02:40 +09002111 ahci_scr_read(&ap->link, SCR_ERROR, &serror);
2112 ahci_scr_write(&ap->link, SCR_ERROR, serror);
Tejun Heo7d50b602007-09-23 13:19:54 +09002113 host_ehi->serror |= serror;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114
Tejun Heo41669552006-11-29 11:33:14 +09002115 /* some controllers set IRQ_IF_ERR on device errors, ignore it */
Tejun Heo417a1a62007-09-23 13:19:55 +09002116 if (hpriv->flags & AHCI_HFLAG_IGN_IRQ_IF_ERR)
Tejun Heo41669552006-11-29 11:33:14 +09002117 irq_stat &= ~PORT_IRQ_IF_ERR;
2118
Conke Hu55a61602007-03-27 18:33:05 +08002119 if (irq_stat & PORT_IRQ_TF_ERR) {
Tejun Heo7d50b602007-09-23 13:19:54 +09002120 /* If qc is active, charge it; otherwise, the active
2121 * link. There's no active qc on NCQ errors. It will
2122 * be determined by EH by reading log page 10h.
2123 */
2124 if (active_qc)
2125 active_qc->err_mask |= AC_ERR_DEV;
2126 else
2127 active_ehi->err_mask |= AC_ERR_DEV;
2128
Tejun Heo417a1a62007-09-23 13:19:55 +09002129 if (hpriv->flags & AHCI_HFLAG_IGN_SERR_INTERNAL)
Tejun Heo7d50b602007-09-23 13:19:54 +09002130 host_ehi->serror &= ~SERR_INTERNAL;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002131 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132
Tejun Heo78cd52d2006-05-15 20:58:29 +09002133 if (irq_stat & PORT_IRQ_UNK_FIS) {
2134 u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135
Tejun Heo7d50b602007-09-23 13:19:54 +09002136 active_ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002137 active_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002138 ata_ehi_push_desc(active_ehi,
2139 "unknown FIS %08x %08x %08x %08x" ,
Tejun Heo78cd52d2006-05-15 20:58:29 +09002140 unk[0], unk[1], unk[2], unk[3]);
2141 }
Jeff Garzikb8f61532005-08-25 22:01:20 -04002142
Tejun Heo071f44b2008-04-07 22:47:22 +09002143 if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
Tejun Heo7d50b602007-09-23 13:19:54 +09002144 active_ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002145 active_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002146 ata_ehi_push_desc(active_ehi, "incorrect PMP");
2147 }
Tejun Heo78cd52d2006-05-15 20:58:29 +09002148
Tejun Heo7d50b602007-09-23 13:19:54 +09002149 if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
2150 host_ehi->err_mask |= AC_ERR_HOST_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09002151 host_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002152 ata_ehi_push_desc(host_ehi, "host bus error");
2153 }
2154
2155 if (irq_stat & PORT_IRQ_IF_ERR) {
2156 host_ehi->err_mask |= AC_ERR_ATA_BUS;
Tejun Heocf480622008-01-24 00:05:14 +09002157 host_ehi->action |= ATA_EH_RESET;
Tejun Heo7d50b602007-09-23 13:19:54 +09002158 ata_ehi_push_desc(host_ehi, "interface fatal error");
2159 }
2160
2161 if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
2162 ata_ehi_hotplugged(host_ehi);
2163 ata_ehi_push_desc(host_ehi, "%s",
2164 irq_stat & PORT_IRQ_CONNECT ?
2165 "connection status changed" : "PHY RDY changed");
2166 }
2167
2168 /* okay, let's hand over to EH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
Tejun Heo78cd52d2006-05-15 20:58:29 +09002170 if (irq_stat & PORT_IRQ_FREEZE)
2171 ata_port_freeze(ap);
2172 else
2173 ata_port_abort(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174}
2175
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002176static void ahci_port_intr(struct ata_port *ap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177{
Tejun Heo350756f2008-04-07 22:47:21 +09002178 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo9af5c9c2007-08-06 18:36:22 +09002179 struct ata_eh_info *ehi = &ap->link.eh_info;
Tejun Heo0291f952007-01-25 19:16:28 +09002180 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo5f226c62007-10-09 15:02:23 +09002181 struct ahci_host_priv *hpriv = ap->host->private_data;
Tejun Heob06ce3e2007-10-09 15:06:48 +09002182 int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
Tejun Heo12fad3f2006-05-15 21:03:55 +09002183 u32 status, qc_active;
Tejun Heo459ad682007-12-07 12:46:23 +09002184 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185
2186 status = readl(port_mmio + PORT_IRQ_STAT);
2187 writel(status, port_mmio + PORT_IRQ_STAT);
2188
Tejun Heob06ce3e2007-10-09 15:06:48 +09002189 /* ignore BAD_PMP while resetting */
2190 if (unlikely(resetting))
2191 status &= ~PORT_IRQ_BAD_PMP;
2192
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002193 /* If we are getting PhyRdy, this is
2194 * just a power state change, we should
2195 * clear out this, plus the PhyRdy/Comm
2196 * Wake bits from Serror
2197 */
2198 if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
2199 (status & PORT_IRQ_PHYRDY)) {
2200 status &= ~PORT_IRQ_PHYRDY;
Tejun Heo82ef04f2008-07-31 17:02:40 +09002201 ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04002202 }
2203
Tejun Heo78cd52d2006-05-15 20:58:29 +09002204 if (unlikely(status & PORT_IRQ_ERROR)) {
2205 ahci_error_intr(ap, status);
2206 return;
2207 }
2208
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002209 if (status & PORT_IRQ_SDB_FIS) {
Tejun Heo5f226c62007-10-09 15:02:23 +09002210 /* If SNotification is available, leave notification
2211 * handling to sata_async_notification(). If not,
2212 * emulate it by snooping SDB FIS RX area.
2213 *
2214 * Snooping FIS RX area is probably cheaper than
2215 * poking SNotification but some constrollers which
2216 * implement SNotification, ICH9 for example, don't
2217 * store AN SDB FIS into receive area.
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002218 */
Tejun Heo5f226c62007-10-09 15:02:23 +09002219 if (hpriv->cap & HOST_CAP_SNTF)
Tejun Heo7d77b242007-09-23 13:14:13 +09002220 sata_async_notification(ap);
Tejun Heo5f226c62007-10-09 15:02:23 +09002221 else {
2222 /* If the 'N' bit in word 0 of the FIS is set,
2223 * we just received asynchronous notification.
2224 * Tell libata about it.
2225 */
2226 const __le32 *f = pp->rx_fis + RX_FIS_SDB;
2227 u32 f0 = le32_to_cpu(f[0]);
2228
2229 if (f0 & (1 << 15))
2230 sata_async_notification(ap);
2231 }
Kristen Carlson Accardi2f294962007-08-15 04:11:25 -04002232 }
2233
Tejun Heo7d50b602007-09-23 13:19:54 +09002234 /* pp->active_link is valid iff any command is in flight */
2235 if (ap->qc_active && pp->active_link->sactive)
Tejun Heo12fad3f2006-05-15 21:03:55 +09002236 qc_active = readl(port_mmio + PORT_SCR_ACT);
2237 else
2238 qc_active = readl(port_mmio + PORT_CMD_ISSUE);
2239
Tejun Heo79f97da2008-04-07 22:47:20 +09002240 rc = ata_qc_complete_multiple(ap, qc_active);
Tejun Heob06ce3e2007-10-09 15:06:48 +09002241
Tejun Heo459ad682007-12-07 12:46:23 +09002242 /* while resetting, invalid completions are expected */
2243 if (unlikely(rc < 0 && !resetting)) {
Tejun Heo12fad3f2006-05-15 21:03:55 +09002244 ehi->err_mask |= AC_ERR_HSM;
Tejun Heocf480622008-01-24 00:05:14 +09002245 ehi->action |= ATA_EH_RESET;
Tejun Heo12fad3f2006-05-15 21:03:55 +09002246 ata_port_freeze(ap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248}
2249
David Howells7d12e782006-10-05 14:55:46 +01002250static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251{
Jeff Garzikcca39742006-08-24 03:19:22 -04002252 struct ata_host *host = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 struct ahci_host_priv *hpriv;
2254 unsigned int i, handled = 0;
Jeff Garzikea6ba102005-08-30 05:18:18 -04002255 void __iomem *mmio;
Tejun Heod28f87a2008-07-05 13:10:50 +09002256 u32 irq_stat, irq_masked;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
2258 VPRINTK("ENTER\n");
2259
Jeff Garzikcca39742006-08-24 03:19:22 -04002260 hpriv = host->private_data;
Tejun Heo0d5ff562007-02-01 15:06:36 +09002261 mmio = host->iomap[AHCI_PCI_BAR];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262
2263 /* sigh. 0xffffffff is a valid return from h/w */
2264 irq_stat = readl(mmio + HOST_IRQ_STAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 if (!irq_stat)
2266 return IRQ_NONE;
2267
Tejun Heod28f87a2008-07-05 13:10:50 +09002268 irq_masked = irq_stat & hpriv->port_map;
2269
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002270 spin_lock(&host->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002272 for (i = 0; i < host->n_ports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 struct ata_port *ap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
Tejun Heod28f87a2008-07-05 13:10:50 +09002275 if (!(irq_masked & (1 << i)))
Jeff Garzik67846b32005-10-05 02:58:32 -04002276 continue;
2277
Jeff Garzikcca39742006-08-24 03:19:22 -04002278 ap = host->ports[i];
Jeff Garzik67846b32005-10-05 02:58:32 -04002279 if (ap) {
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002280 ahci_port_intr(ap);
Jeff Garzik67846b32005-10-05 02:58:32 -04002281 VPRINTK("port %u\n", i);
2282 } else {
2283 VPRINTK("port %u (no irq)\n", i);
Tejun Heo6971ed12006-03-11 12:47:54 +09002284 if (ata_ratelimit())
Jeff Garzikcca39742006-08-24 03:19:22 -04002285 dev_printk(KERN_WARNING, host->dev,
Jeff Garzika9524a72005-10-30 14:39:11 -05002286 "interrupt on disabled port %u\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 }
Jeff Garzik67846b32005-10-05 02:58:32 -04002288
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 handled = 1;
2290 }
2291
Tejun Heod28f87a2008-07-05 13:10:50 +09002292 /* HOST_IRQ_STAT behaves as level triggered latch meaning that
2293 * it should be cleared after all the port events are cleared;
2294 * otherwise, it will raise a spurious interrupt after each
2295 * valid one. Please read section 10.6.2 of ahci 1.1 for more
2296 * information.
2297 *
2298 * Also, use the unmasked value to clear interrupt as spurious
2299 * pending event on a dummy port might cause screaming IRQ.
2300 */
Tejun Heoea0c62f2008-06-28 01:49:02 +09002301 writel(irq_stat, mmio + HOST_IRQ_STAT);
2302
Jeff Garzikcca39742006-08-24 03:19:22 -04002303 spin_unlock(&host->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304
2305 VPRINTK("EXIT\n");
2306
2307 return IRQ_RETVAL(handled);
2308}
2309
Tejun Heo9a3d9eb2006-01-23 13:09:36 +09002310static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311{
2312 struct ata_port *ap = qc->ap;
Tejun Heo4447d352007-04-17 23:44:08 +09002313 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo7d50b602007-09-23 13:19:54 +09002314 struct ahci_port_priv *pp = ap->private_data;
2315
2316 /* Keep track of the currently active link. It will be used
2317 * in completion path to determine whether NCQ phase is in
2318 * progress.
2319 */
2320 pp->active_link = qc->dev->link;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321
Tejun Heo12fad3f2006-05-15 21:03:55 +09002322 if (qc->tf.protocol == ATA_PROT_NCQ)
2323 writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
2324 writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002326 ahci_sw_activity(qc->dev->link);
2327
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 return 0;
2329}
2330
Tejun Heo4c9bf4e2008-04-07 22:47:20 +09002331static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
2332{
2333 struct ahci_port_priv *pp = qc->ap->private_data;
2334 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
2335
2336 ata_tf_from_fis(d2h_fis, &qc->result_tf);
2337 return true;
2338}
2339
Tejun Heo78cd52d2006-05-15 20:58:29 +09002340static void ahci_freeze(struct ata_port *ap)
2341{
Tejun Heo4447d352007-04-17 23:44:08 +09002342 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002343
2344 /* turn IRQ off */
2345 writel(0, port_mmio + PORT_IRQ_MASK);
2346}
2347
2348static void ahci_thaw(struct ata_port *ap)
2349{
Tejun Heo0d5ff562007-02-01 15:06:36 +09002350 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
Tejun Heo4447d352007-04-17 23:44:08 +09002351 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002352 u32 tmp;
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002353 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo78cd52d2006-05-15 20:58:29 +09002354
2355 /* clear IRQ */
2356 tmp = readl(port_mmio + PORT_IRQ_STAT);
2357 writel(tmp, port_mmio + PORT_IRQ_STAT);
Tejun Heoa7187282007-01-27 11:04:26 +09002358 writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002359
Tejun Heo1c954a42007-10-09 15:01:37 +09002360 /* turn IRQ back on */
2361 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002362}
2363
2364static void ahci_error_handler(struct ata_port *ap)
2365{
Tejun Heob51e9e52006-06-29 01:29:30 +09002366 if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
Tejun Heo78cd52d2006-05-15 20:58:29 +09002367 /* restart engine */
Tejun Heo4447d352007-04-17 23:44:08 +09002368 ahci_stop_engine(ap);
2369 ahci_start_engine(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002370 }
2371
Tejun Heoa1efdab2008-03-25 12:22:50 +09002372 sata_pmp_error_handler(ap);
Tejun Heoedc93052007-10-25 14:59:16 +09002373}
2374
Tejun Heo78cd52d2006-05-15 20:58:29 +09002375static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
2376{
2377 struct ata_port *ap = qc->ap;
2378
Tejun Heod2e75df2007-07-16 14:29:39 +09002379 /* make DMA engine forget about the failed command */
2380 if (qc->flags & ATA_QCFLAG_FAILED)
Shane Huang78d5ae32009-08-07 15:05:52 +08002381 ahci_kick_engine(ap);
Tejun Heo78cd52d2006-05-15 20:58:29 +09002382}
2383
Tejun Heo7d50b602007-09-23 13:19:54 +09002384static void ahci_pmp_attach(struct ata_port *ap)
2385{
2386 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo1c954a42007-10-09 15:01:37 +09002387 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002388 u32 cmd;
2389
2390 cmd = readl(port_mmio + PORT_CMD);
2391 cmd |= PORT_CMD_PMP;
2392 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo1c954a42007-10-09 15:01:37 +09002393
2394 pp->intr_mask |= PORT_IRQ_BAD_PMP;
2395 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo7d50b602007-09-23 13:19:54 +09002396}
2397
2398static void ahci_pmp_detach(struct ata_port *ap)
2399{
2400 void __iomem *port_mmio = ahci_port_base(ap);
Tejun Heo1c954a42007-10-09 15:01:37 +09002401 struct ahci_port_priv *pp = ap->private_data;
Tejun Heo7d50b602007-09-23 13:19:54 +09002402 u32 cmd;
2403
2404 cmd = readl(port_mmio + PORT_CMD);
2405 cmd &= ~PORT_CMD_PMP;
2406 writel(cmd, port_mmio + PORT_CMD);
Tejun Heo1c954a42007-10-09 15:01:37 +09002407
2408 pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
2409 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
Tejun Heo7d50b602007-09-23 13:19:54 +09002410}
2411
Alexey Dobriyan028a2592007-07-17 23:48:48 +04002412static int ahci_port_resume(struct ata_port *ap)
2413{
2414 ahci_power_up(ap);
2415 ahci_start_port(ap);
2416
Tejun Heo071f44b2008-04-07 22:47:22 +09002417 if (sata_pmp_attached(ap))
Tejun Heo7d50b602007-09-23 13:19:54 +09002418 ahci_pmp_attach(ap);
2419 else
2420 ahci_pmp_detach(ap);
2421
Alexey Dobriyan028a2592007-07-17 23:48:48 +04002422 return 0;
2423}
2424
Tejun Heo438ac6d2007-03-02 17:31:26 +09002425#ifdef CONFIG_PM
Tejun Heoc1332872006-07-26 15:59:26 +09002426static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
2427{
Tejun Heoc1332872006-07-26 15:59:26 +09002428 const char *emsg = NULL;
2429 int rc;
2430
Tejun Heo4447d352007-04-17 23:44:08 +09002431 rc = ahci_deinit_port(ap, &emsg);
Tejun Heo8e16f942006-11-20 15:42:36 +09002432 if (rc == 0)
Tejun Heo4447d352007-04-17 23:44:08 +09002433 ahci_power_down(ap);
Tejun Heo8e16f942006-11-20 15:42:36 +09002434 else {
Tejun Heoc1332872006-07-26 15:59:26 +09002435 ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002436 ahci_start_port(ap);
Tejun Heoc1332872006-07-26 15:59:26 +09002437 }
2438
2439 return rc;
2440}
2441
Tejun Heoc1332872006-07-26 15:59:26 +09002442static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
2443{
Jeff Garzikcca39742006-08-24 03:19:22 -04002444 struct ata_host *host = dev_get_drvdata(&pdev->dev);
Tejun Heo9b10ae82009-05-30 20:50:12 +09002445 struct ahci_host_priv *hpriv = host->private_data;
Tejun Heo0d5ff562007-02-01 15:06:36 +09002446 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Tejun Heoc1332872006-07-26 15:59:26 +09002447 u32 ctl;
2448
Tejun Heo9b10ae82009-05-30 20:50:12 +09002449 if (mesg.event & PM_EVENT_SUSPEND &&
2450 hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
2451 dev_printk(KERN_ERR, &pdev->dev,
2452 "BIOS update required for suspend/resume\n");
2453 return -EIO;
2454 }
2455
Rafael J. Wysocki3a2d5b72008-02-23 19:13:25 +01002456 if (mesg.event & PM_EVENT_SLEEP) {
Tejun Heoc1332872006-07-26 15:59:26 +09002457 /* AHCI spec rev1.1 section 8.3.3:
2458 * Software must disable interrupts prior to requesting a
2459 * transition of the HBA to D3 state.
2460 */
2461 ctl = readl(mmio + HOST_CTL);
2462 ctl &= ~HOST_IRQ_EN;
2463 writel(ctl, mmio + HOST_CTL);
2464 readl(mmio + HOST_CTL); /* flush */
2465 }
2466
2467 return ata_pci_device_suspend(pdev, mesg);
2468}
2469
2470static int ahci_pci_device_resume(struct pci_dev *pdev)
2471{
Jeff Garzikcca39742006-08-24 03:19:22 -04002472 struct ata_host *host = dev_get_drvdata(&pdev->dev);
Tejun Heoc1332872006-07-26 15:59:26 +09002473 int rc;
2474
Tejun Heo553c4aa2006-12-26 19:39:50 +09002475 rc = ata_pci_device_do_resume(pdev);
2476 if (rc)
2477 return rc;
Tejun Heoc1332872006-07-26 15:59:26 +09002478
2479 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
Tejun Heo4447d352007-04-17 23:44:08 +09002480 rc = ahci_reset_controller(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002481 if (rc)
2482 return rc;
2483
Tejun Heo4447d352007-04-17 23:44:08 +09002484 ahci_init_controller(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002485 }
2486
Jeff Garzikcca39742006-08-24 03:19:22 -04002487 ata_host_resume(host);
Tejun Heoc1332872006-07-26 15:59:26 +09002488
2489 return 0;
2490}
Tejun Heo438ac6d2007-03-02 17:31:26 +09002491#endif
Tejun Heoc1332872006-07-26 15:59:26 +09002492
Tejun Heo254950c2006-07-26 15:59:25 +09002493static int ahci_port_start(struct ata_port *ap)
2494{
Jeff Garzikcca39742006-08-24 03:19:22 -04002495 struct device *dev = ap->host->dev;
Tejun Heo254950c2006-07-26 15:59:25 +09002496 struct ahci_port_priv *pp;
Tejun Heo254950c2006-07-26 15:59:25 +09002497 void *mem;
2498 dma_addr_t mem_dma;
Tejun Heo254950c2006-07-26 15:59:25 +09002499
Tejun Heo24dc5f32007-01-20 16:00:28 +09002500 pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
Tejun Heo254950c2006-07-26 15:59:25 +09002501 if (!pp)
2502 return -ENOMEM;
Tejun Heo254950c2006-07-26 15:59:25 +09002503
Tejun Heo24dc5f32007-01-20 16:00:28 +09002504 mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma,
2505 GFP_KERNEL);
2506 if (!mem)
Tejun Heo254950c2006-07-26 15:59:25 +09002507 return -ENOMEM;
Tejun Heo254950c2006-07-26 15:59:25 +09002508 memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
2509
2510 /*
2511 * First item in chunk of DMA memory: 32-slot command table,
2512 * 32 bytes each in size
2513 */
2514 pp->cmd_slot = mem;
2515 pp->cmd_slot_dma = mem_dma;
2516
2517 mem += AHCI_CMD_SLOT_SZ;
2518 mem_dma += AHCI_CMD_SLOT_SZ;
2519
2520 /*
2521 * Second item: Received-FIS area
2522 */
2523 pp->rx_fis = mem;
2524 pp->rx_fis_dma = mem_dma;
2525
2526 mem += AHCI_RX_FIS_SZ;
2527 mem_dma += AHCI_RX_FIS_SZ;
2528
2529 /*
2530 * Third item: data area for storing a single command
2531 * and its scatter-gather table
2532 */
2533 pp->cmd_tbl = mem;
2534 pp->cmd_tbl_dma = mem_dma;
2535
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002536 /*
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002537 * Save off initial list of interrupts to be enabled.
2538 * This could be changed later
2539 */
Kristen Carlson Accardia7384922007-08-09 14:23:41 -07002540 pp->intr_mask = DEF_PORT_IRQ;
2541
Tejun Heo254950c2006-07-26 15:59:25 +09002542 ap->private_data = pp;
2543
Jeff Garzikdf69c9c2007-05-26 20:46:51 -04002544 /* engage engines, captain */
2545 return ahci_port_resume(ap);
Tejun Heo254950c2006-07-26 15:59:25 +09002546}
2547
2548static void ahci_port_stop(struct ata_port *ap)
2549{
Tejun Heo0be0aa92006-07-26 15:59:26 +09002550 const char *emsg = NULL;
2551 int rc;
Tejun Heo254950c2006-07-26 15:59:25 +09002552
Tejun Heo0be0aa92006-07-26 15:59:26 +09002553 /* de-initialize port */
Tejun Heo4447d352007-04-17 23:44:08 +09002554 rc = ahci_deinit_port(ap, &emsg);
Tejun Heo0be0aa92006-07-26 15:59:26 +09002555 if (rc)
2556 ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
Tejun Heo254950c2006-07-26 15:59:25 +09002557}
2558
Tejun Heo4447d352007-04-17 23:44:08 +09002559static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 if (using_dac &&
Yang Hongyang6a355282009-04-06 19:01:13 -07002564 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
2565 rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 if (rc) {
Yang Hongyang284901a2009-04-06 19:01:15 -07002567 rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002569 dev_printk(KERN_ERR, &pdev->dev,
2570 "64-bit DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 return rc;
2572 }
2573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 } else {
Yang Hongyang284901a2009-04-06 19:01:15 -07002575 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002577 dev_printk(KERN_ERR, &pdev->dev,
2578 "32-bit DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 return rc;
2580 }
Yang Hongyang284901a2009-04-06 19:01:15 -07002581 rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 if (rc) {
Jeff Garzika9524a72005-10-30 14:39:11 -05002583 dev_printk(KERN_ERR, &pdev->dev,
2584 "32-bit consistent DMA enable failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 return rc;
2586 }
2587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 return 0;
2589}
2590
Tejun Heo4447d352007-04-17 23:44:08 +09002591static void ahci_print_info(struct ata_host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592{
Tejun Heo4447d352007-04-17 23:44:08 +09002593 struct ahci_host_priv *hpriv = host->private_data;
2594 struct pci_dev *pdev = to_pci_dev(host->dev);
2595 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
Robert Hancock4c521c82009-09-20 17:02:31 -06002596 u32 vers, cap, cap2, impl, speed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597 const char *speed_s;
2598 u16 cc;
2599 const char *scc_s;
2600
2601 vers = readl(mmio + HOST_VERSION);
2602 cap = hpriv->cap;
Robert Hancock4c521c82009-09-20 17:02:31 -06002603 cap2 = hpriv->cap2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 impl = hpriv->port_map;
2605
2606 speed = (cap >> 20) & 0xf;
2607 if (speed == 1)
2608 speed_s = "1.5";
2609 else if (speed == 2)
2610 speed_s = "3";
Shane Huang8522ee22008-12-30 11:00:37 +08002611 else if (speed == 3)
2612 speed_s = "6";
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 else
2614 speed_s = "?";
2615
2616 pci_read_config_word(pdev, 0x0a, &cc);
Conke Huc9f89472007-01-09 05:32:51 -05002617 if (cc == PCI_CLASS_STORAGE_IDE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 scc_s = "IDE";
Conke Huc9f89472007-01-09 05:32:51 -05002619 else if (cc == PCI_CLASS_STORAGE_SATA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 scc_s = "SATA";
Conke Huc9f89472007-01-09 05:32:51 -05002621 else if (cc == PCI_CLASS_STORAGE_RAID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 scc_s = "RAID";
2623 else
2624 scc_s = "unknown";
2625
Jeff Garzika9524a72005-10-30 14:39:11 -05002626 dev_printk(KERN_INFO, &pdev->dev,
2627 "AHCI %02x%02x.%02x%02x "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 "%u slots %u ports %s Gbps 0x%x impl %s mode\n"
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002629 ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002631 (vers >> 24) & 0xff,
2632 (vers >> 16) & 0xff,
2633 (vers >> 8) & 0xff,
2634 vers & 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
2636 ((cap >> 8) & 0x1f) + 1,
2637 (cap & 0x1f) + 1,
2638 speed_s,
2639 impl,
2640 scc_s);
2641
Jeff Garzika9524a72005-10-30 14:39:11 -05002642 dev_printk(KERN_INFO, &pdev->dev,
2643 "flags: "
Tejun Heo203ef6c2007-07-16 14:29:40 +09002644 "%s%s%s%s%s%s%s"
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07002645 "%s%s%s%s%s%s%s"
Robert Hancock4c521c82009-09-20 17:02:31 -06002646 "%s%s%s%s%s%s\n"
Jeff Garzik2dcb4072007-10-19 06:42:56 -04002647 ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648
Robert Hancock4c521c82009-09-20 17:02:31 -06002649 cap & HOST_CAP_64 ? "64bit " : "",
2650 cap & HOST_CAP_NCQ ? "ncq " : "",
2651 cap & HOST_CAP_SNTF ? "sntf " : "",
2652 cap & HOST_CAP_MPS ? "ilck " : "",
2653 cap & HOST_CAP_SSS ? "stag " : "",
2654 cap & HOST_CAP_ALPM ? "pm " : "",
2655 cap & HOST_CAP_LED ? "led " : "",
2656 cap & HOST_CAP_CLO ? "clo " : "",
2657 cap & HOST_CAP_ONLY ? "only " : "",
2658 cap & HOST_CAP_PMP ? "pmp " : "",
2659 cap & HOST_CAP_FBS ? "fbs " : "",
2660 cap & HOST_CAP_PIO_MULTI ? "pio " : "",
2661 cap & HOST_CAP_SSC ? "slum " : "",
2662 cap & HOST_CAP_PART ? "part " : "",
2663 cap & HOST_CAP_CCC ? "ccc " : "",
2664 cap & HOST_CAP_EMS ? "ems " : "",
2665 cap & HOST_CAP_SXS ? "sxs " : "",
2666 cap2 & HOST_CAP2_APST ? "apst " : "",
2667 cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",
2668 cap2 & HOST_CAP2_BOH ? "boh " : ""
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 );
2670}
2671
Tejun Heoedc93052007-10-25 14:59:16 +09002672/* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
2673 * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't
2674 * support PMP and the 4726 either directly exports the device
2675 * attached to the first downstream port or acts as a hardware storage
2676 * controller and emulate a single ATA device (can be RAID 0/1 or some
2677 * other configuration).
2678 *
2679 * When there's no device attached to the first downstream port of the
2680 * 4726, "Config Disk" appears, which is a pseudo ATA device to
2681 * configure the 4726. However, ATA emulation of the device is very
2682 * lame. It doesn't send signature D2H Reg FIS after the initial
2683 * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
2684 *
2685 * The following function works around the problem by always using
2686 * hardreset on the port and not depending on receiving signature FIS
2687 * afterward. If signature FIS isn't received soon, ATA class is
2688 * assumed without follow-up softreset.
2689 */
2690static void ahci_p5wdh_workaround(struct ata_host *host)
2691{
2692 static struct dmi_system_id sysids[] = {
2693 {
2694 .ident = "P5W DH Deluxe",
2695 .matches = {
2696 DMI_MATCH(DMI_SYS_VENDOR,
2697 "ASUSTEK COMPUTER INC"),
2698 DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
2699 },
2700 },
2701 { }
2702 };
2703 struct pci_dev *pdev = to_pci_dev(host->dev);
2704
2705 if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
2706 dmi_check_system(sysids)) {
2707 struct ata_port *ap = host->ports[1];
2708
2709 dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
2710 "Deluxe on-board SIMG4726 workaround\n");
2711
2712 ap->ops = &ahci_p5wdh_ops;
2713 ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
2714 }
2715}
2716
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002717/* only some SB600 ahci controllers can do 64bit DMA */
2718static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
Shane Huang58a09b32009-05-27 15:04:43 +08002719{
2720 static const struct dmi_system_id sysids[] = {
Tejun Heo03d783b2009-08-16 21:04:02 +09002721 /*
2722 * The oldest version known to be broken is 0901 and
2723 * working is 1501 which was released on 2007-10-26.
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002724 * Enable 64bit DMA on 1501 and anything newer.
2725 *
Tejun Heo03d783b2009-08-16 21:04:02 +09002726 * Please read bko#9412 for more info.
2727 */
Shane Huang58a09b32009-05-27 15:04:43 +08002728 {
2729 .ident = "ASUS M2A-VM",
2730 .matches = {
2731 DMI_MATCH(DMI_BOARD_VENDOR,
2732 "ASUSTeK Computer INC."),
2733 DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
2734 },
Tejun Heo03d783b2009-08-16 21:04:02 +09002735 .driver_data = "20071026", /* yyyymmdd */
Shane Huang58a09b32009-05-27 15:04:43 +08002736 },
Mark Nelsone65cc192009-11-03 20:06:48 +11002737 /*
2738 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
2739 * support 64bit DMA.
2740 *
2741 * BIOS versions earlier than 1.5 had the Manufacturer DMI
2742 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
2743 * This spelling mistake was fixed in BIOS version 1.5, so
2744 * 1.5 and later have the Manufacturer as
2745 * "MICRO-STAR INTERNATIONAL CO.,LTD".
2746 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
2747 *
2748 * BIOS versions earlier than 1.9 had a Board Product Name
2749 * DMI field of "MS-7376". This was changed to be
2750 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
2751 * match on DMI_BOARD_NAME of "MS-7376".
2752 */
2753 {
2754 .ident = "MSI K9A2 Platinum",
2755 .matches = {
2756 DMI_MATCH(DMI_BOARD_VENDOR,
2757 "MICRO-STAR INTER"),
2758 DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
2759 },
2760 },
Shane Huang58a09b32009-05-27 15:04:43 +08002761 { }
2762 };
Tejun Heo03d783b2009-08-16 21:04:02 +09002763 const struct dmi_system_id *match;
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002764 int year, month, date;
2765 char buf[9];
Shane Huang58a09b32009-05-27 15:04:43 +08002766
Tejun Heo03d783b2009-08-16 21:04:02 +09002767 match = dmi_first_match(sysids);
Shane Huang58a09b32009-05-27 15:04:43 +08002768 if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
Tejun Heo03d783b2009-08-16 21:04:02 +09002769 !match)
Shane Huang58a09b32009-05-27 15:04:43 +08002770 return false;
2771
Mark Nelsone65cc192009-11-03 20:06:48 +11002772 if (!match->driver_data)
2773 goto enable_64bit;
2774
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002775 dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
2776 snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
Shane Huang58a09b32009-05-27 15:04:43 +08002777
Mark Nelsone65cc192009-11-03 20:06:48 +11002778 if (strcmp(buf, match->driver_data) >= 0)
2779 goto enable_64bit;
2780 else {
Tejun Heo03d783b2009-08-16 21:04:02 +09002781 dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, "
2782 "forcing 32bit DMA, update BIOS\n", match->ident);
Tejun Heo2fcad9d2009-10-03 18:27:29 +09002783 return false;
2784 }
Mark Nelsone65cc192009-11-03 20:06:48 +11002785
2786enable_64bit:
2787 dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n",
2788 match->ident);
2789 return true;
Shane Huang58a09b32009-05-27 15:04:43 +08002790}
2791
Rafael J. Wysocki1fd68432009-01-19 20:57:36 +01002792static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
2793{
2794 static const struct dmi_system_id broken_systems[] = {
2795 {
2796 .ident = "HP Compaq nx6310",
2797 .matches = {
2798 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2799 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
2800 },
2801 /* PCI slot number of the controller */
2802 .driver_data = (void *)0x1FUL,
2803 },
Maciej Ruteckid2f9c062009-03-20 00:06:46 +01002804 {
2805 .ident = "HP Compaq 6720s",
2806 .matches = {
2807 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2808 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
2809 },
2810 /* PCI slot number of the controller */
2811 .driver_data = (void *)0x1FUL,
2812 },
Rafael J. Wysocki1fd68432009-01-19 20:57:36 +01002813
2814 { } /* terminate list */
2815 };
2816 const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
2817
2818 if (dmi) {
2819 unsigned long slot = (unsigned long)dmi->driver_data;
2820 /* apply the quirk only to on-board controllers */
2821 return slot == PCI_SLOT(pdev->devfn);
2822 }
2823
2824 return false;
2825}
2826
Tejun Heo9b10ae82009-05-30 20:50:12 +09002827static bool ahci_broken_suspend(struct pci_dev *pdev)
2828{
2829 static const struct dmi_system_id sysids[] = {
2830 /*
2831 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
2832 * to the harddisk doesn't become online after
2833 * resuming from STR. Warn and fail suspend.
2834 */
2835 {
2836 .ident = "dv4",
2837 .matches = {
2838 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2839 DMI_MATCH(DMI_PRODUCT_NAME,
2840 "HP Pavilion dv4 Notebook PC"),
2841 },
2842 .driver_data = "F.30", /* cutoff BIOS version */
2843 },
2844 {
2845 .ident = "dv5",
2846 .matches = {
2847 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2848 DMI_MATCH(DMI_PRODUCT_NAME,
2849 "HP Pavilion dv5 Notebook PC"),
2850 },
2851 .driver_data = "F.16", /* cutoff BIOS version */
2852 },
2853 {
2854 .ident = "dv6",
2855 .matches = {
2856 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2857 DMI_MATCH(DMI_PRODUCT_NAME,
2858 "HP Pavilion dv6 Notebook PC"),
2859 },
2860 .driver_data = "F.21", /* cutoff BIOS version */
2861 },
2862 {
2863 .ident = "HDX18",
2864 .matches = {
2865 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
2866 DMI_MATCH(DMI_PRODUCT_NAME,
2867 "HP HDX18 Notebook PC"),
2868 },
2869 .driver_data = "F.23", /* cutoff BIOS version */
2870 },
Tejun Heocedc9bf2010-01-28 16:04:15 +09002871 /*
2872 * Acer eMachines G725 has the same problem. BIOS
2873 * V1.03 is known to be broken. V3.04 is known to
2874 * work. Inbetween, there are V1.06, V2.06 and V3.03
2875 * that we don't have much idea about. For now,
2876 * blacklist anything older than V3.04.
2877 */
2878 {
2879 .ident = "G725",
2880 .matches = {
2881 DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
2882 DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
2883 },
2884 .driver_data = "V3.04", /* cutoff BIOS version */
2885 },
Tejun Heo9b10ae82009-05-30 20:50:12 +09002886 { } /* terminate list */
2887 };
2888 const struct dmi_system_id *dmi = dmi_first_match(sysids);
2889 const char *ver;
2890
2891 if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
2892 return false;
2893
2894 ver = dmi_get_system_info(DMI_BIOS_VERSION);
2895
2896 return !ver || strcmp(ver, dmi->driver_data) < 0;
2897}
2898
Tejun Heo55946392009-08-04 14:30:08 +09002899static bool ahci_broken_online(struct pci_dev *pdev)
2900{
2901#define ENCODE_BUSDEVFN(bus, slot, func) \
2902 (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
2903 static const struct dmi_system_id sysids[] = {
2904 /*
2905 * There are several gigabyte boards which use
2906 * SIMG5723s configured as hardware RAID. Certain
2907 * 5723 firmware revisions shipped there keep the link
2908 * online but fail to answer properly to SRST or
2909 * IDENTIFY when no device is attached downstream
2910 * causing libata to retry quite a few times leading
2911 * to excessive detection delay.
2912 *
2913 * As these firmwares respond to the second reset try
2914 * with invalid device signature, considering unknown
2915 * sig as offline works around the problem acceptably.
2916 */
2917 {
2918 .ident = "EP45-DQ6",
2919 .matches = {
2920 DMI_MATCH(DMI_BOARD_VENDOR,
2921 "Gigabyte Technology Co., Ltd."),
2922 DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
2923 },
2924 .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
2925 },
2926 {
2927 .ident = "EP45-DS5",
2928 .matches = {
2929 DMI_MATCH(DMI_BOARD_VENDOR,
2930 "Gigabyte Technology Co., Ltd."),
2931 DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
2932 },
2933 .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
2934 },
2935 { } /* terminate list */
2936 };
2937#undef ENCODE_BUSDEVFN
2938 const struct dmi_system_id *dmi = dmi_first_match(sysids);
2939 unsigned int val;
2940
2941 if (!dmi)
2942 return false;
2943
2944 val = (unsigned long)dmi->driver_data;
2945
2946 return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
2947}
2948
Markus Trippelsdorf8e513212009-10-09 05:41:47 +02002949#ifdef CONFIG_ATA_ACPI
Tejun Heof80ae7e2009-09-16 04:18:03 +09002950static void ahci_gtf_filter_workaround(struct ata_host *host)
2951{
2952 static const struct dmi_system_id sysids[] = {
2953 /*
2954 * Aspire 3810T issues a bunch of SATA enable commands
2955 * via _GTF including an invalid one and one which is
2956 * rejected by the device. Among the successful ones
2957 * is FPDMA non-zero offset enable which when enabled
2958 * only on the drive side leads to NCQ command
2959 * failures. Filter it out.
2960 */
2961 {
2962 .ident = "Aspire 3810T",
2963 .matches = {
2964 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
2965 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
2966 },
2967 .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
2968 },
2969 { }
2970 };
2971 const struct dmi_system_id *dmi = dmi_first_match(sysids);
2972 unsigned int filter;
2973 int i;
2974
2975 if (!dmi)
2976 return;
2977
2978 filter = (unsigned long)dmi->driver_data;
2979 dev_printk(KERN_INFO, host->dev,
2980 "applying extra ACPI _GTF filter 0x%x for %s\n",
2981 filter, dmi->ident);
2982
2983 for (i = 0; i < host->n_ports; i++) {
2984 struct ata_port *ap = host->ports[i];
2985 struct ata_link *link;
2986 struct ata_device *dev;
2987
2988 ata_for_each_link(link, ap, EDGE)
2989 ata_for_each_dev(dev, link, ALL)
2990 dev->gtf_filter |= filter;
2991 }
2992}
Markus Trippelsdorf8e513212009-10-09 05:41:47 +02002993#else
2994static inline void ahci_gtf_filter_workaround(struct ata_host *host)
2995{}
2996#endif
Tejun Heof80ae7e2009-09-16 04:18:03 +09002997
Tejun Heo24dc5f32007-01-20 16:00:28 +09002998static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999{
3000 static int printed_version;
Tejun Heoe297d992008-06-10 00:13:04 +09003001 unsigned int board_id = ent->driver_data;
3002 struct ata_port_info pi = ahci_port_info[board_id];
Tejun Heo4447d352007-04-17 23:44:08 +09003003 const struct ata_port_info *ppi[] = { &pi, NULL };
Tejun Heo24dc5f32007-01-20 16:00:28 +09003004 struct device *dev = &pdev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 struct ahci_host_priv *hpriv;
Tejun Heo4447d352007-04-17 23:44:08 +09003006 struct ata_host *host;
Tejun Heo837f5f82008-02-06 15:13:51 +09003007 int n_ports, i, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008
3009 VPRINTK("ENTER\n");
3010
Tejun Heo12fad3f2006-05-15 21:03:55 +09003011 WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
3012
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 if (!printed_version++)
Jeff Garzika9524a72005-10-30 14:39:11 -05003014 dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015
Alan Cox5b66c822008-09-03 14:48:34 +01003016 /* The AHCI driver can only drive the SATA ports, the PATA driver
3017 can drive them all so if both drivers are selected make sure
3018 AHCI stays out of the way */
3019 if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
3020 return -ENODEV;
3021
Mark Nelson7a022672009-11-22 12:07:41 +11003022 /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
3023 * At the moment, we can only use the AHCI mode. Let the users know
3024 * that for SAS drives they're out of luck.
3025 */
3026 if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
3027 dev_printk(KERN_INFO, &pdev->dev, "PDC42819 "
3028 "can only drive SATA devices with this driver\n");
3029
Tejun Heo4447d352007-04-17 23:44:08 +09003030 /* acquire resources */
Tejun Heo24dc5f32007-01-20 16:00:28 +09003031 rc = pcim_enable_device(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 if (rc)
3033 return rc;
3034
Tejun Heodea55132008-03-11 19:52:31 +09003035 /* AHCI controllers often implement SFF compatible interface.
3036 * Grab all PCI BARs just in case.
3037 */
3038 rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
Tejun Heo0d5ff562007-02-01 15:06:36 +09003039 if (rc == -EBUSY)
Tejun Heo24dc5f32007-01-20 16:00:28 +09003040 pcim_pin_device(pdev);
Tejun Heo0d5ff562007-02-01 15:06:36 +09003041 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09003042 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043
Tejun Heoc4f77922007-12-06 15:09:43 +09003044 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
3045 (pdev->device == 0x2652 || pdev->device == 0x2653)) {
3046 u8 map;
3047
3048 /* ICH6s share the same PCI ID for both piix and ahci
3049 * modes. Enabling ahci mode while MAP indicates
3050 * combined mode is a bad idea. Yield to ata_piix.
3051 */
3052 pci_read_config_byte(pdev, ICH_MAP, &map);
3053 if (map & 0x3) {
3054 dev_printk(KERN_INFO, &pdev->dev, "controller is in "
3055 "combined mode, can't enable AHCI mode\n");
3056 return -ENODEV;
3057 }
3058 }
3059
Tejun Heo24dc5f32007-01-20 16:00:28 +09003060 hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
3061 if (!hpriv)
3062 return -ENOMEM;
Tejun Heo417a1a62007-09-23 13:19:55 +09003063 hpriv->flags |= (unsigned long)pi.private_data;
3064
Tejun Heoe297d992008-06-10 00:13:04 +09003065 /* MCP65 revision A1 and A2 can't do MSI */
3066 if (board_id == board_ahci_mcp65 &&
3067 (pdev->revision == 0xa1 || pdev->revision == 0xa2))
3068 hpriv->flags |= AHCI_HFLAG_NO_MSI;
3069
Shane Huange427fe02008-12-30 10:53:41 +08003070 /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
3071 if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
3072 hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
3073
Tejun Heo2fcad9d2009-10-03 18:27:29 +09003074 /* only some SB600s can do 64bit DMA */
3075 if (ahci_sb600_enable_64bit(pdev))
3076 hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
Shane Huang58a09b32009-05-27 15:04:43 +08003077
Tejun Heo31b239a2009-09-17 00:34:39 +09003078 if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
3079 pci_intx(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080
Tejun Heo4447d352007-04-17 23:44:08 +09003081 /* save initial config */
Tejun Heo417a1a62007-09-23 13:19:55 +09003082 ahci_save_initial_config(pdev, hpriv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083
Tejun Heo4447d352007-04-17 23:44:08 +09003084 /* prepare host */
Robert Hancock453d3132010-01-26 22:33:23 -06003085 if (hpriv->cap & HOST_CAP_NCQ) {
3086 pi.flags |= ATA_FLAG_NCQ;
3087 /* Auto-activate optimization is supposed to be supported on
3088 all AHCI controllers indicating NCQ support, but it seems
3089 to be broken at least on some NVIDIA MCP79 chipsets.
3090 Until we get info on which NVIDIA chipsets don't have this
3091 issue, if any, disable AA on all NVIDIA AHCIs. */
3092 if (pdev->vendor != PCI_VENDOR_ID_NVIDIA)
3093 pi.flags |= ATA_FLAG_FPDMA_AA;
3094 }
Tejun Heo4447d352007-04-17 23:44:08 +09003095
Tejun Heo7d50b602007-09-23 13:19:54 +09003096 if (hpriv->cap & HOST_CAP_PMP)
3097 pi.flags |= ATA_FLAG_PMP;
3098
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07003099 if (ahci_em_messages && (hpriv->cap & HOST_CAP_EMS)) {
3100 u8 messages;
3101 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
3102 u32 em_loc = readl(mmio + HOST_EM_LOC);
3103 u32 em_ctl = readl(mmio + HOST_EM_CTL);
3104
David Milburn87943ac2008-10-13 14:38:36 -05003105 messages = (em_ctl & EM_CTRL_MSG_TYPE) >> 16;
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07003106
3107 /* we only support LED message type right now */
3108 if ((messages & 0x01) && (ahci_em_messages == 1)) {
3109 /* store em_loc */
3110 hpriv->em_loc = ((em_loc >> 16) * 4);
3111 pi.flags |= ATA_FLAG_EM;
3112 if (!(em_ctl & EM_CTL_ALHD))
3113 pi.flags |= ATA_FLAG_SW_ACTIVITY;
3114 }
3115 }
3116
Rafael J. Wysocki1fd68432009-01-19 20:57:36 +01003117 if (ahci_broken_system_poweroff(pdev)) {
3118 pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
3119 dev_info(&pdev->dev,
3120 "quirky BIOS, skipping spindown on poweroff\n");
3121 }
3122
Tejun Heo9b10ae82009-05-30 20:50:12 +09003123 if (ahci_broken_suspend(pdev)) {
3124 hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
3125 dev_printk(KERN_WARNING, &pdev->dev,
3126 "BIOS update required for suspend/resume\n");
3127 }
3128
Tejun Heo55946392009-08-04 14:30:08 +09003129 if (ahci_broken_online(pdev)) {
3130 hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
3131 dev_info(&pdev->dev,
3132 "online status unreliable, applying workaround\n");
3133 }
3134
Tejun Heo837f5f82008-02-06 15:13:51 +09003135 /* CAP.NP sometimes indicate the index of the last enabled
3136 * port, at other times, that of the last possible port, so
3137 * determining the maximum port number requires looking at
3138 * both CAP.NP and port_map.
3139 */
3140 n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
3141
3142 host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
Tejun Heo4447d352007-04-17 23:44:08 +09003143 if (!host)
3144 return -ENOMEM;
3145 host->iomap = pcim_iomap_table(pdev);
3146 host->private_data = hpriv;
3147
Arjan van de Venf3d7f232009-01-26 02:05:44 -08003148 if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
Arjan van de Ven886ad092009-01-09 15:54:07 -08003149 host->flags |= ATA_HOST_PARALLEL_SCAN;
Arjan van de Venf3d7f232009-01-26 02:05:44 -08003150 else
3151 printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
Arjan van de Ven886ad092009-01-09 15:54:07 -08003152
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07003153 if (pi.flags & ATA_FLAG_EM)
3154 ahci_reset_em(host);
3155
Tejun Heo4447d352007-04-17 23:44:08 +09003156 for (i = 0; i < host->n_ports; i++) {
Jeff Garzikdab632e2007-05-28 08:33:01 -04003157 struct ata_port *ap = host->ports[i];
Tejun Heo4447d352007-04-17 23:44:08 +09003158
Tejun Heocbcdd872007-08-18 13:14:55 +09003159 ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
3160 ata_port_pbar_desc(ap, AHCI_PCI_BAR,
3161 0x100 + ap->port_no * 0x80, "port");
3162
Kristen Carlson Accardi31556592007-10-25 01:33:26 -04003163 /* set initial link pm policy */
3164 ap->pm_policy = NOT_AVAILABLE;
3165
Kristen Carlson Accardi18f7ba42008-06-03 10:33:55 -07003166 /* set enclosure management message type */
3167 if (ap->flags & ATA_FLAG_EM)
3168 ap->em_message_type = ahci_em_messages;
3169
3170
Jeff Garzikdab632e2007-05-28 08:33:01 -04003171 /* disabled/not-implemented port */
Tejun Heo350756f2008-04-07 22:47:21 +09003172 if (!(hpriv->port_map & (1 << i)))
Jeff Garzikdab632e2007-05-28 08:33:01 -04003173 ap->ops = &ata_dummy_port_ops;
Tejun Heo4447d352007-04-17 23:44:08 +09003174 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175
Tejun Heoedc93052007-10-25 14:59:16 +09003176 /* apply workaround for ASUS P5W DH Deluxe mainboard */
3177 ahci_p5wdh_workaround(host);
3178
Tejun Heof80ae7e2009-09-16 04:18:03 +09003179 /* apply gtf filter quirk */
3180 ahci_gtf_filter_workaround(host);
3181
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182 /* initialize adapter */
Tejun Heo4447d352007-04-17 23:44:08 +09003183 rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184 if (rc)
Tejun Heo24dc5f32007-01-20 16:00:28 +09003185 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186
Tejun Heo4447d352007-04-17 23:44:08 +09003187 rc = ahci_reset_controller(host);
3188 if (rc)
3189 return rc;
Tejun Heo12fad3f2006-05-15 21:03:55 +09003190
Tejun Heo4447d352007-04-17 23:44:08 +09003191 ahci_init_controller(host);
3192 ahci_print_info(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
Tejun Heo4447d352007-04-17 23:44:08 +09003194 pci_set_master(pdev);
3195 return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
3196 &ahci_sht);
Jeff Garzik907f4672005-05-12 15:03:42 -04003197}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198
3199static int __init ahci_init(void)
3200{
Pavel Roskinb7887192006-08-10 18:13:18 +09003201 return pci_register_driver(&ahci_pci_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202}
3203
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204static void __exit ahci_exit(void)
3205{
3206 pci_unregister_driver(&ahci_pci_driver);
3207}
3208
3209
3210MODULE_AUTHOR("Jeff Garzik");
3211MODULE_DESCRIPTION("AHCI SATA low-level driver");
3212MODULE_LICENSE("GPL");
3213MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
Jeff Garzik68854332005-08-23 02:53:51 -04003214MODULE_VERSION(DRV_VERSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215
3216module_init(ahci_init);
3217module_exit(ahci_exit);