xref: /openbmc/linux/drivers/ata/ahci.c (revision a40cf3f38881ce8543ceb9667150b4f2ead4c437)
1c6fd2807SJeff Garzik /*
2c6fd2807SJeff Garzik  *  ahci.c - AHCI SATA support
3c6fd2807SJeff Garzik  *
48c3d3d4bSTejun Heo  *  Maintained by:  Tejun Heo <tj@kernel.org>
5c6fd2807SJeff Garzik  *    		    Please ALWAYS copy linux-ide@vger.kernel.org
6c6fd2807SJeff Garzik  *		    on emails.
7c6fd2807SJeff Garzik  *
8c6fd2807SJeff Garzik  *  Copyright 2004-2005 Red Hat, Inc.
9c6fd2807SJeff Garzik  *
10c6fd2807SJeff Garzik  *
11c6fd2807SJeff Garzik  *  This program is free software; you can redistribute it and/or modify
12c6fd2807SJeff Garzik  *  it under the terms of the GNU General Public License as published by
13c6fd2807SJeff Garzik  *  the Free Software Foundation; either version 2, or (at your option)
14c6fd2807SJeff Garzik  *  any later version.
15c6fd2807SJeff Garzik  *
16c6fd2807SJeff Garzik  *  This program is distributed in the hope that it will be useful,
17c6fd2807SJeff Garzik  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18c6fd2807SJeff Garzik  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19c6fd2807SJeff Garzik  *  GNU General Public License for more details.
20c6fd2807SJeff Garzik  *
21c6fd2807SJeff Garzik  *  You should have received a copy of the GNU General Public License
22c6fd2807SJeff Garzik  *  along with this program; see the file COPYING.  If not, write to
23c6fd2807SJeff Garzik  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24c6fd2807SJeff Garzik  *
25c6fd2807SJeff Garzik  *
26c6fd2807SJeff Garzik  * libata documentation is available via 'make {ps|pdf}docs',
27c6fd2807SJeff Garzik  * as Documentation/DocBook/libata.*
28c6fd2807SJeff Garzik  *
29c6fd2807SJeff Garzik  * AHCI hardware documentation:
30c6fd2807SJeff Garzik  * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
31c6fd2807SJeff Garzik  * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
32c6fd2807SJeff Garzik  *
33c6fd2807SJeff Garzik  */
34c6fd2807SJeff Garzik 
35c6fd2807SJeff Garzik #include <linux/kernel.h>
36c6fd2807SJeff Garzik #include <linux/module.h>
37c6fd2807SJeff Garzik #include <linux/pci.h>
38c6fd2807SJeff Garzik #include <linux/blkdev.h>
39c6fd2807SJeff Garzik #include <linux/delay.h>
40c6fd2807SJeff Garzik #include <linux/interrupt.h>
41c6fd2807SJeff Garzik #include <linux/dma-mapping.h>
42c6fd2807SJeff Garzik #include <linux/device.h>
43edc93052STejun Heo #include <linux/dmi.h>
445a0e3ad6STejun Heo #include <linux/gfp.h>
45ee2aad42SRobert Richter #include <linux/msi.h>
46c6fd2807SJeff Garzik #include <scsi/scsi_host.h>
47c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h>
48c6fd2807SJeff Garzik #include <linux/libata.h>
49365cfa1eSAnton Vorontsov #include "ahci.h"
50c6fd2807SJeff Garzik 
51c6fd2807SJeff Garzik #define DRV_NAME	"ahci"
527d50b60bSTejun Heo #define DRV_VERSION	"3.0"
53c6fd2807SJeff Garzik 
54c6fd2807SJeff Garzik enum {
55318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STA2X11	= 0,
56b7ae128dSRobert Richter 	AHCI_PCI_BAR_CAVIUM	= 0,
577f9c9f8eSHugh Daschbach 	AHCI_PCI_BAR_ENMOTUS	= 2,
58318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STANDARD	= 5,
59441577efSTejun Heo };
60c6fd2807SJeff Garzik 
61441577efSTejun Heo enum board_ids {
62441577efSTejun Heo 	/* board IDs by feature in alphabetical order */
63441577efSTejun Heo 	board_ahci,
64441577efSTejun Heo 	board_ahci_ign_iferr,
6566a7cbc3STejun Heo 	board_ahci_nomsi,
6667809f85SLevente Kurusa 	board_ahci_noncq,
67441577efSTejun Heo 	board_ahci_nosntf,
685f173107STejun Heo 	board_ahci_yes_fbs,
69441577efSTejun Heo 
70441577efSTejun Heo 	/* board IDs for specific chipsets in alphabetical order */
71dbfe8ef5SDan Williams 	board_ahci_avn,
72441577efSTejun Heo 	board_ahci_mcp65,
7383f2b963STejun Heo 	board_ahci_mcp77,
7483f2b963STejun Heo 	board_ahci_mcp89,
75441577efSTejun Heo 	board_ahci_mv,
76441577efSTejun Heo 	board_ahci_sb600,
77441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
78441577efSTejun Heo 	board_ahci_vt8251,
79441577efSTejun Heo 
80441577efSTejun Heo 	/* aliases */
81441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
82441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
83441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
8483f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
85c6fd2807SJeff Garzik };
86c6fd2807SJeff Garzik 
87c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
88a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
89a1efdabaSTejun Heo 				 unsigned long deadline);
90dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
91dbfe8ef5SDan Williams 			      unsigned long deadline);
92cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
93cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev);
94a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
95a1efdabaSTejun Heo 				unsigned long deadline);
96438ac6d5STejun Heo #ifdef CONFIG_PM
97c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
98c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev);
99438ac6d5STejun Heo #endif
100c6fd2807SJeff Garzik 
101fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = {
102fad16e7aSTejun Heo 	AHCI_SHT("ahci"),
103fad16e7aSTejun Heo };
104fad16e7aSTejun Heo 
105029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
106029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
107a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
108ad616ffbSTejun Heo };
109ad616ffbSTejun Heo 
110029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
111029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
112a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
113edc93052STejun Heo };
114edc93052STejun Heo 
115dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = {
116dbfe8ef5SDan Williams 	.inherits		= &ahci_ops,
117dbfe8ef5SDan Williams 	.hardreset		= ahci_avn_hardreset,
118dbfe8ef5SDan Williams };
119dbfe8ef5SDan Williams 
120c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
121441577efSTejun Heo 	/* by features */
122facb8fa6SJeffrin Jose 	[board_ahci] = {
1231188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
12414bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
125469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
126c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
127c6fd2807SJeff Garzik 	},
128facb8fa6SJeffrin Jose 	[board_ahci_ign_iferr] = {
129417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
130417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
13114bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
132469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
13341669553STejun Heo 		.port_ops	= &ahci_ops,
13441669553STejun Heo 	},
13566a7cbc3STejun Heo 	[board_ahci_nomsi] = {
13666a7cbc3STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_MSI),
13766a7cbc3STejun Heo 		.flags		= AHCI_FLAG_COMMON,
13866a7cbc3STejun Heo 		.pio_mask	= ATA_PIO4,
13966a7cbc3STejun Heo 		.udma_mask	= ATA_UDMA6,
14066a7cbc3STejun Heo 		.port_ops	= &ahci_ops,
14166a7cbc3STejun Heo 	},
14267809f85SLevente Kurusa 	[board_ahci_noncq] = {
14367809f85SLevente Kurusa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ),
14467809f85SLevente Kurusa 		.flags		= AHCI_FLAG_COMMON,
14567809f85SLevente Kurusa 		.pio_mask	= ATA_PIO4,
14667809f85SLevente Kurusa 		.udma_mask	= ATA_UDMA6,
14767809f85SLevente Kurusa 		.port_ops	= &ahci_ops,
14867809f85SLevente Kurusa 	},
149facb8fa6SJeffrin Jose 	[board_ahci_nosntf] = {
150441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
151441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
152441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
153441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
154441577efSTejun Heo 		.port_ops	= &ahci_ops,
155441577efSTejun Heo 	},
156facb8fa6SJeffrin Jose 	[board_ahci_yes_fbs] = {
1575f173107STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),
1585f173107STejun Heo 		.flags		= AHCI_FLAG_COMMON,
1595f173107STejun Heo 		.pio_mask	= ATA_PIO4,
1605f173107STejun Heo 		.udma_mask	= ATA_UDMA6,
1615f173107STejun Heo 		.port_ops	= &ahci_ops,
1625f173107STejun Heo 	},
163441577efSTejun Heo 	/* by chipsets */
164dbfe8ef5SDan Williams 	[board_ahci_avn] = {
165dbfe8ef5SDan Williams 		.flags		= AHCI_FLAG_COMMON,
166dbfe8ef5SDan Williams 		.pio_mask	= ATA_PIO4,
167dbfe8ef5SDan Williams 		.udma_mask	= ATA_UDMA6,
168dbfe8ef5SDan Williams 		.port_ops	= &ahci_avn_ops,
169dbfe8ef5SDan Williams 	},
170facb8fa6SJeffrin Jose 	[board_ahci_mcp65] = {
17183f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
17283f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
173ae01b249STejun Heo 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
17483f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
17583f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
17683f2b963STejun Heo 		.port_ops	= &ahci_ops,
17783f2b963STejun Heo 	},
178facb8fa6SJeffrin Jose 	[board_ahci_mcp77] = {
17983f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
18083f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
18183f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
18283f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
18383f2b963STejun Heo 		.port_ops	= &ahci_ops,
18483f2b963STejun Heo 	},
185facb8fa6SJeffrin Jose 	[board_ahci_mcp89] = {
18683f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
187441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
188441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
189441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
190441577efSTejun Heo 		.port_ops	= &ahci_ops,
191441577efSTejun Heo 	},
192facb8fa6SJeffrin Jose 	[board_ahci_mv] = {
193441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
194441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
1959cbe056fSSergei Shtylyov 		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
196441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
197441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
198441577efSTejun Heo 		.port_ops	= &ahci_ops,
199441577efSTejun Heo 	},
200facb8fa6SJeffrin Jose 	[board_ahci_sb600] = {
201417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
2022fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
2032fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
204417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
20514bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
206469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
207345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
20855a61604SConke Hu 	},
209facb8fa6SJeffrin Jose 	[board_ahci_sb700] = {	/* for SB700 and SB800 */
210bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
211e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
21214bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
213e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
214345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
215e39fc8c9SShane Huang 	},
216facb8fa6SJeffrin Jose 	[board_ahci_vt8251] = {
217441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
218e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
21914bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
220e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
221441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
2221b677afdSShaohua Li 	},
223c6fd2807SJeff Garzik };
224c6fd2807SJeff Garzik 
225c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
226c6fd2807SJeff Garzik 	/* Intel */
22754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
22854bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
22954bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
23054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
23154bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
23282490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
23354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
23454bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
23554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
23654bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2377a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2381b677afdSShaohua Li 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
2397a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2407a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2417a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2427a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2437a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2447a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2457a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2467a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
2477a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
2487a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
2497a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
2507a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
2517a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
2527a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
2537a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
254d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
255d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
25616ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
257b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
25816ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
259c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
260c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
261adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
2628e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
263c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
264adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
2658e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
266c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
2675623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
2685623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
2695623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
2705623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
2715623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
2725623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
273992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
274992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
275992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
27664a3903dSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
277a4a461a6SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
278181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
279181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */
280181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
281181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
282181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
283181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
2842cab7a4cSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
285ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
286ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */
287ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
288ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */
289ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
290ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */
291ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
292ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */
29377b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */
29477b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */
29577b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */
29677b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */
29777b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */
29877b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */
29977b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */
30077b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */
30129e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
30229e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
30329e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
30429e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
30529e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
30629e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
30729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
30829e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
309dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */
310dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */
311dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */
312dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */
313dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */
314dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
315dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
316dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
317efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
318efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
319151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
320151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
321151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
322151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
323151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
324151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
325151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
326151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
3271cfc7df3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
3289f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */
3299f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */
3309f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */
3319f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */
3321b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
3331b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */
3341b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
3351b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */
3361b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
3371b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
3381b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
3391b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
340249cd0a1SDevin Ryles 	{ PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */
341249cd0a1SDevin Ryles 	{ PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */
342249cd0a1SDevin Ryles 	{ PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */
343690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
344690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
345690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
346690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
347c6fd2807SJeff Garzik 
348e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
349e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
350e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
3511fefb8fdSBen Hutchings 	/* JMicron 362B and 362C have an AHCI function with IDE class code */
3521fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
3531fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
35491f15fb3SZhang Rui 	/* May need to update quirk_jmicron_async_suspend() for additions */
355c6fd2807SJeff Garzik 
356c6fd2807SJeff Garzik 	/* ATI */
357c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
358e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
359e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
360e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
361e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
362e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
363e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
364c6fd2807SJeff Garzik 
365e2dd90b1SShane Huang 	/* AMD */
3665deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
367fafe5c3dSShane Huang 	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
368e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
369e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
370e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
371e2dd90b1SShane Huang 
372c6fd2807SJeff Garzik 	/* VIA */
37354bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
374bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
375c6fd2807SJeff Garzik 
376c6fd2807SJeff Garzik 	/* NVIDIA */
377e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
378e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
379e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
380e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
381e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
382e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
383e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
384e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
385441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
386441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
387441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
388441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
389441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
390441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
391441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
392441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
393441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
394441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
395441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
396441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
397441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
398441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
399441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
400441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
401441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
402441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
403441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
404441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
405441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
406441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
407441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
408441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
409441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
410441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
411441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
412441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
413441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
414441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
415441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
416441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
417441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
418441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
419441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
420441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
421441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
422441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
423441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
424441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
425441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
426441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
427441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
428441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
429441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
430441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
431441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
432441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
433441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
434441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
435441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
436441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
437441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
438441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
439441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
440441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
441441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
442441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
443441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
444441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
445441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
446441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
447441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
448441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
449441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
450441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
451441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
452441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
453441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
454441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
455441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
456441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
457441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
458441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
459441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
460441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
461c6fd2807SJeff Garzik 
462c6fd2807SJeff Garzik 	/* SiS */
46320e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
46420e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
46520e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
466c6fd2807SJeff Garzik 
467318893e1SAlessandro Rubini 	/* ST Microelectronics */
468318893e1SAlessandro Rubini 	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */
469318893e1SAlessandro Rubini 
470cd70c266SJeff Garzik 	/* Marvell */
471cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
472c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
47369fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
47410aca06cSAnssi Hannula 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
47510aca06cSAnssi Hannula 	  .class_mask = 0xffffff,
4765f173107STejun Heo 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
47769fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
478467b41c6SPer Jessen 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
479e098f5cbSSimon Guinot 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
480e098f5cbSSimon Guinot 			 PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
481e098f5cbSSimon Guinot 	  .driver_data = board_ahci_yes_fbs },			/* 88se9170 */
48269fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
483642d8925SMatt Johnson 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
484fcce9a35SGeorge Spelvin 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
485c5edfff9SMurali Karicheri 	  .driver_data = board_ahci_yes_fbs },			/* 88se9182 */
486c5edfff9SMurali Karicheri 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
487fcce9a35SGeorge Spelvin 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
48869fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
48917c60c6bSAlan Cox 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */
490754a292fSAndreas Schrägle 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0),
491754a292fSAndreas Schrägle 	  .driver_data = board_ahci_yes_fbs },
492*a40cf3f3SJohannes Thumshirn 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), 	/* 88se91a2 */
493*a40cf3f3SJohannes Thumshirn 	  .driver_data = board_ahci_yes_fbs },
49469fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
49550be5e36STejun Heo 	  .driver_data = board_ahci_yes_fbs },
4966d5278a6SSamir Benmendil 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
4976d5278a6SSamir Benmendil 	  .driver_data = board_ahci_yes_fbs },
498d2518365SJérôme Carretero 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642),
499d2518365SJérôme Carretero 	  .driver_data = board_ahci_yes_fbs },
500cd70c266SJeff Garzik 
501c77a036bSMark Nelson 	/* Promise */
502c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
503b32bfc06SRomain Degez 	{ PCI_VDEVICE(PROMISE, 0x3781), board_ahci },   /* FastTrak TX8660 ahci-mode */
504c77a036bSMark Nelson 
505c9703765SKeng-Yu Lin 	/* Asmedia */
5067b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },	/* ASM1060 */
5077b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },	/* ASM1060 */
5087b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */
5097b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */
510c9703765SKeng-Yu Lin 
51167809f85SLevente Kurusa 	/*
51266a7cbc3STejun Heo 	 * Samsung SSDs found on some macbooks.  NCQ times out if MSI is
51366a7cbc3STejun Heo 	 * enabled.  https://bugzilla.kernel.org/show_bug.cgi?id=60731
51467809f85SLevente Kurusa 	 */
51566a7cbc3STejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
5162b21ef0aSTejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi },
51767809f85SLevente Kurusa 
5187f9c9f8eSHugh Daschbach 	/* Enmotus */
5197f9c9f8eSHugh Daschbach 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
5207f9c9f8eSHugh Daschbach 
521415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
522415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
523c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
524415ae2b5SJeff Garzik 
525c6fd2807SJeff Garzik 	{ }	/* terminate list */
526c6fd2807SJeff Garzik };
527c6fd2807SJeff Garzik 
528c6fd2807SJeff Garzik 
529c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
530c6fd2807SJeff Garzik 	.name			= DRV_NAME,
531c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
532c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
53324dc5f33STejun Heo 	.remove			= ata_pci_remove_one,
534438ac6d5STejun Heo #ifdef CONFIG_PM
535c6fd2807SJeff Garzik 	.suspend		= ahci_pci_device_suspend,
536c6fd2807SJeff Garzik 	.resume			= ahci_pci_device_resume,
537438ac6d5STejun Heo #endif
538c6fd2807SJeff Garzik };
539c6fd2807SJeff Garzik 
5405b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
5415b66c829SAlan Cox static int marvell_enable;
5425b66c829SAlan Cox #else
5435b66c829SAlan Cox static int marvell_enable = 1;
5445b66c829SAlan Cox #endif
5455b66c829SAlan Cox module_param(marvell_enable, int, 0644);
5465b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
5475b66c829SAlan Cox 
5485b66c829SAlan Cox 
549394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
550394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
551394d6e53SAnton Vorontsov {
552394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
553394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
5549a23c1d6SAntoine Tenart 		hpriv->force_port_map = 1;
555394d6e53SAnton Vorontsov 	}
556394d6e53SAnton Vorontsov 
557394d6e53SAnton Vorontsov 	/*
558394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
559394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
560394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
561394d6e53SAnton Vorontsov 	 */
562394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
563394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
5649a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0x3;
565394d6e53SAnton Vorontsov 		else
5669a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0xf;
567394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
568394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
569394d6e53SAnton Vorontsov 	}
570394d6e53SAnton Vorontsov 
571725c7b57SAntoine Ténart 	ahci_save_initial_config(&pdev->dev, hpriv);
572394d6e53SAnton Vorontsov }
573394d6e53SAnton Vorontsov 
5743303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host)
5753303040dSAnton Vorontsov {
5763303040dSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
5773303040dSAnton Vorontsov 
5783303040dSAnton Vorontsov 	ahci_reset_controller(host);
5793303040dSAnton Vorontsov 
580c6fd2807SJeff Garzik 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
5813303040dSAnton Vorontsov 		struct ahci_host_priv *hpriv = host->private_data;
582c6fd2807SJeff Garzik 		u16 tmp16;
583c6fd2807SJeff Garzik 
584c6fd2807SJeff Garzik 		/* configure PCS */
585c6fd2807SJeff Garzik 		pci_read_config_word(pdev, 0x92, &tmp16);
58649f29090STejun Heo 		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
58749f29090STejun Heo 			tmp16 |= hpriv->port_map;
588c6fd2807SJeff Garzik 			pci_write_config_word(pdev, 0x92, tmp16);
589c6fd2807SJeff Garzik 		}
59049f29090STejun Heo 	}
591c6fd2807SJeff Garzik 
592c6fd2807SJeff Garzik 	return 0;
593c6fd2807SJeff Garzik }
594c6fd2807SJeff Garzik 
595781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
596781d6550SAnton Vorontsov {
597781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
598781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
599781d6550SAnton Vorontsov 	void __iomem *port_mmio;
600781d6550SAnton Vorontsov 	u32 tmp;
601c40e7cb8SJose Alberto Reguero 	int mv;
6022bcd866bSJeff Garzik 
603417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
604c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
605c40e7cb8SJose Alberto Reguero 			mv = 2;
606c40e7cb8SJose Alberto Reguero 		else
607c40e7cb8SJose Alberto Reguero 			mv = 4;
608c40e7cb8SJose Alberto Reguero 		port_mmio = __ahci_port_base(host, mv);
609cd70c266SJeff Garzik 
610cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
611cd70c266SJeff Garzik 
612cd70c266SJeff Garzik 		/* clear port IRQ */
613cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
614cd70c266SJeff Garzik 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
615cd70c266SJeff Garzik 		if (tmp)
616cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
617cd70c266SJeff Garzik 	}
618cd70c266SJeff Garzik 
619781d6550SAnton Vorontsov 	ahci_init_controller(host);
620c6fd2807SJeff Garzik }
621c6fd2807SJeff Garzik 
622cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
623d4b2bab4STejun Heo 				 unsigned long deadline)
624ad616ffbSTejun Heo {
625cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
626039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
6279dadd45bSTejun Heo 	bool online;
628ad616ffbSTejun Heo 	int rc;
629ad616ffbSTejun Heo 
630ad616ffbSTejun Heo 	DPRINTK("ENTER\n");
631ad616ffbSTejun Heo 
6324447d351STejun Heo 	ahci_stop_engine(ap);
633ad616ffbSTejun Heo 
634cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
6359dadd45bSTejun Heo 				 deadline, &online, NULL);
636ad616ffbSTejun Heo 
637039ece38SHans de Goede 	hpriv->start_engine(ap);
638ad616ffbSTejun Heo 
639ad616ffbSTejun Heo 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
640ad616ffbSTejun Heo 
641ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
642ad616ffbSTejun Heo 	 * request follow-up softreset.
643ad616ffbSTejun Heo 	 */
6449dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
645ad616ffbSTejun Heo }
646ad616ffbSTejun Heo 
647edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
648edc93052STejun Heo 				unsigned long deadline)
649edc93052STejun Heo {
650edc93052STejun Heo 	struct ata_port *ap = link->ap;
651edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
652039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
653edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
654edc93052STejun Heo 	struct ata_taskfile tf;
6559dadd45bSTejun Heo 	bool online;
656edc93052STejun Heo 	int rc;
657edc93052STejun Heo 
658edc93052STejun Heo 	ahci_stop_engine(ap);
659edc93052STejun Heo 
660edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
661edc93052STejun Heo 	ata_tf_init(link->device, &tf);
6629bbb1b0eSSergei Shtylyov 	tf.command = ATA_BUSY;
663edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
664edc93052STejun Heo 
665edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
6669dadd45bSTejun Heo 				 deadline, &online, NULL);
667edc93052STejun Heo 
668039ece38SHans de Goede 	hpriv->start_engine(ap);
669edc93052STejun Heo 
670edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
671edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
672edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
673edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
674edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
675edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
676edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
677edc93052STejun Heo 	 *
678edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
679edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
680edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
681edc93052STejun Heo 	 * suffice while making probing snappish enough.
682edc93052STejun Heo 	 */
6839dadd45bSTejun Heo 	if (online) {
6849dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
6859dadd45bSTejun Heo 					  ahci_check_ready);
686edc93052STejun Heo 		if (rc)
68778d5ae39SShane Huang 			ahci_kick_engine(ap);
6889dadd45bSTejun Heo 	}
6899dadd45bSTejun Heo 	return rc;
690edc93052STejun Heo }
691edc93052STejun Heo 
692dbfe8ef5SDan Williams /*
693dbfe8ef5SDan Williams  * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports.
694dbfe8ef5SDan Williams  *
695dbfe8ef5SDan Williams  * It has been observed with some SSDs that the timing of events in the
696dbfe8ef5SDan Williams  * link synchronization phase can leave the port in a state that can not
697dbfe8ef5SDan Williams  * be recovered by a SATA-hard-reset alone.  The failing signature is
698dbfe8ef5SDan Williams  * SStatus.DET stuck at 1 ("Device presence detected but Phy
699dbfe8ef5SDan Williams  * communication not established").  It was found that unloading and
700dbfe8ef5SDan Williams  * reloading the driver when this problem occurs allows the drive
701dbfe8ef5SDan Williams  * connection to be recovered (DET advanced to 0x3).  The critical
702dbfe8ef5SDan Williams  * component of reloading the driver is that the port state machines are
703dbfe8ef5SDan Williams  * reset by bouncing "port enable" in the AHCI PCS configuration
704dbfe8ef5SDan Williams  * register.  So, reproduce that effect by bouncing a port whenever we
705dbfe8ef5SDan Williams  * see DET==1 after a reset.
706dbfe8ef5SDan Williams  */
707dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
708dbfe8ef5SDan Williams 			      unsigned long deadline)
709dbfe8ef5SDan Williams {
710dbfe8ef5SDan Williams 	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
711dbfe8ef5SDan Williams 	struct ata_port *ap = link->ap;
712dbfe8ef5SDan Williams 	struct ahci_port_priv *pp = ap->private_data;
713dbfe8ef5SDan Williams 	struct ahci_host_priv *hpriv = ap->host->private_data;
714dbfe8ef5SDan Williams 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
715dbfe8ef5SDan Williams 	unsigned long tmo = deadline - jiffies;
716dbfe8ef5SDan Williams 	struct ata_taskfile tf;
717dbfe8ef5SDan Williams 	bool online;
718dbfe8ef5SDan Williams 	int rc, i;
719dbfe8ef5SDan Williams 
720dbfe8ef5SDan Williams 	DPRINTK("ENTER\n");
721dbfe8ef5SDan Williams 
722dbfe8ef5SDan Williams 	ahci_stop_engine(ap);
723dbfe8ef5SDan Williams 
724dbfe8ef5SDan Williams 	for (i = 0; i < 2; i++) {
725dbfe8ef5SDan Williams 		u16 val;
726dbfe8ef5SDan Williams 		u32 sstatus;
727dbfe8ef5SDan Williams 		int port = ap->port_no;
728dbfe8ef5SDan Williams 		struct ata_host *host = ap->host;
729dbfe8ef5SDan Williams 		struct pci_dev *pdev = to_pci_dev(host->dev);
730dbfe8ef5SDan Williams 
731dbfe8ef5SDan Williams 		/* clear D2H reception area to properly wait for D2H FIS */
732dbfe8ef5SDan Williams 		ata_tf_init(link->device, &tf);
733dbfe8ef5SDan Williams 		tf.command = ATA_BUSY;
734dbfe8ef5SDan Williams 		ata_tf_to_fis(&tf, 0, 0, d2h_fis);
735dbfe8ef5SDan Williams 
736dbfe8ef5SDan Williams 		rc = sata_link_hardreset(link, timing, deadline, &online,
737dbfe8ef5SDan Williams 				ahci_check_ready);
738dbfe8ef5SDan Williams 
739dbfe8ef5SDan Williams 		if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 ||
740dbfe8ef5SDan Williams 				(sstatus & 0xf) != 1)
741dbfe8ef5SDan Williams 			break;
742dbfe8ef5SDan Williams 
743dbfe8ef5SDan Williams 		ata_link_printk(link, KERN_INFO, "avn bounce port%d\n",
744dbfe8ef5SDan Williams 				port);
745dbfe8ef5SDan Williams 
746dbfe8ef5SDan Williams 		pci_read_config_word(pdev, 0x92, &val);
747dbfe8ef5SDan Williams 		val &= ~(1 << port);
748dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
749dbfe8ef5SDan Williams 		ata_msleep(ap, 1000);
750dbfe8ef5SDan Williams 		val |= 1 << port;
751dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
752dbfe8ef5SDan Williams 		deadline += tmo;
753dbfe8ef5SDan Williams 	}
754dbfe8ef5SDan Williams 
755dbfe8ef5SDan Williams 	hpriv->start_engine(ap);
756dbfe8ef5SDan Williams 
757dbfe8ef5SDan Williams 	if (online)
758dbfe8ef5SDan Williams 		*class = ahci_dev_classify(ap);
759dbfe8ef5SDan Williams 
760dbfe8ef5SDan Williams 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
761dbfe8ef5SDan Williams 	return rc;
762dbfe8ef5SDan Williams }
763dbfe8ef5SDan Williams 
764dbfe8ef5SDan Williams 
765438ac6d5STejun Heo #ifdef CONFIG_PM
766c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
767c6fd2807SJeff Garzik {
7680a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
7699b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
770d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
771c6fd2807SJeff Garzik 	u32 ctl;
772c6fd2807SJeff Garzik 
7739b10ae86STejun Heo 	if (mesg.event & PM_EVENT_SUSPEND &&
7749b10ae86STejun Heo 	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
775a44fec1fSJoe Perches 		dev_err(&pdev->dev,
7769b10ae86STejun Heo 			"BIOS update required for suspend/resume\n");
7779b10ae86STejun Heo 		return -EIO;
7789b10ae86STejun Heo 	}
7799b10ae86STejun Heo 
7803a2d5b70SRafael J. Wysocki 	if (mesg.event & PM_EVENT_SLEEP) {
781c6fd2807SJeff Garzik 		/* AHCI spec rev1.1 section 8.3.3:
782c6fd2807SJeff Garzik 		 * Software must disable interrupts prior to requesting a
783c6fd2807SJeff Garzik 		 * transition of the HBA to D3 state.
784c6fd2807SJeff Garzik 		 */
785c6fd2807SJeff Garzik 		ctl = readl(mmio + HOST_CTL);
786c6fd2807SJeff Garzik 		ctl &= ~HOST_IRQ_EN;
787c6fd2807SJeff Garzik 		writel(ctl, mmio + HOST_CTL);
788c6fd2807SJeff Garzik 		readl(mmio + HOST_CTL); /* flush */
789c6fd2807SJeff Garzik 	}
790c6fd2807SJeff Garzik 
791c6fd2807SJeff Garzik 	return ata_pci_device_suspend(pdev, mesg);
792c6fd2807SJeff Garzik }
793c6fd2807SJeff Garzik 
794c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev)
795c6fd2807SJeff Garzik {
7960a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
797c6fd2807SJeff Garzik 	int rc;
798c6fd2807SJeff Garzik 
799553c4aa6STejun Heo 	rc = ata_pci_device_do_resume(pdev);
800553c4aa6STejun Heo 	if (rc)
801553c4aa6STejun Heo 		return rc;
802c6fd2807SJeff Garzik 
803cb85696dSJames Laird 	/* Apple BIOS helpfully mangles the registers on resume */
804cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
805cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
806cb85696dSJames Laird 
807c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
8083303040dSAnton Vorontsov 		rc = ahci_pci_reset_controller(host);
809c6fd2807SJeff Garzik 		if (rc)
810c6fd2807SJeff Garzik 			return rc;
811c6fd2807SJeff Garzik 
812781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
813c6fd2807SJeff Garzik 	}
814c6fd2807SJeff Garzik 
815cca3974eSJeff Garzik 	ata_host_resume(host);
816c6fd2807SJeff Garzik 
817c6fd2807SJeff Garzik 	return 0;
818c6fd2807SJeff Garzik }
819438ac6d5STejun Heo #endif
820c6fd2807SJeff Garzik 
8214447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
822c6fd2807SJeff Garzik {
823c6fd2807SJeff Garzik 	int rc;
824c6fd2807SJeff Garzik 
825318893e1SAlessandro Rubini 	/*
826318893e1SAlessandro Rubini 	 * If the device fixup already set the dma_mask to some non-standard
827318893e1SAlessandro Rubini 	 * value, don't extend it here. This happens on STA2X11, for example.
828318893e1SAlessandro Rubini 	 */
829318893e1SAlessandro Rubini 	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
830318893e1SAlessandro Rubini 		return 0;
831318893e1SAlessandro Rubini 
832c6fd2807SJeff Garzik 	if (using_dac &&
833c54c719bSQuentin Lambert 	    !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
834c54c719bSQuentin Lambert 		rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
835c6fd2807SJeff Garzik 		if (rc) {
836c54c719bSQuentin Lambert 			rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
837c6fd2807SJeff Garzik 			if (rc) {
838a44fec1fSJoe Perches 				dev_err(&pdev->dev,
839c6fd2807SJeff Garzik 					"64-bit DMA enable failed\n");
840c6fd2807SJeff Garzik 				return rc;
841c6fd2807SJeff Garzik 			}
842c6fd2807SJeff Garzik 		}
843c6fd2807SJeff Garzik 	} else {
844c54c719bSQuentin Lambert 		rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
845c6fd2807SJeff Garzik 		if (rc) {
846a44fec1fSJoe Perches 			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
847c6fd2807SJeff Garzik 			return rc;
848c6fd2807SJeff Garzik 		}
849c54c719bSQuentin Lambert 		rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
850c6fd2807SJeff Garzik 		if (rc) {
851a44fec1fSJoe Perches 			dev_err(&pdev->dev,
852c6fd2807SJeff Garzik 				"32-bit consistent DMA enable failed\n");
853c6fd2807SJeff Garzik 			return rc;
854c6fd2807SJeff Garzik 		}
855c6fd2807SJeff Garzik 	}
856c6fd2807SJeff Garzik 	return 0;
857c6fd2807SJeff Garzik }
858c6fd2807SJeff Garzik 
859439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
860439fcaecSAnton Vorontsov {
861439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
862439fcaecSAnton Vorontsov 	u16 cc;
863439fcaecSAnton Vorontsov 	const char *scc_s;
864439fcaecSAnton Vorontsov 
865439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
866439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
867439fcaecSAnton Vorontsov 		scc_s = "IDE";
868439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
869439fcaecSAnton Vorontsov 		scc_s = "SATA";
870439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
871439fcaecSAnton Vorontsov 		scc_s = "RAID";
872439fcaecSAnton Vorontsov 	else
873439fcaecSAnton Vorontsov 		scc_s = "unknown";
874439fcaecSAnton Vorontsov 
875439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
876439fcaecSAnton Vorontsov }
877439fcaecSAnton Vorontsov 
878edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
879edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
880edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
881edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
882edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
883edc93052STejun Heo  * other configuration).
884edc93052STejun Heo  *
885edc93052STejun Heo  * When there's no device attached to the first downstream port of the
886edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
887edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
888edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
889edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
890edc93052STejun Heo  *
891edc93052STejun Heo  * The following function works around the problem by always using
892edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
893edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
894edc93052STejun Heo  * assumed without follow-up softreset.
895edc93052STejun Heo  */
896edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
897edc93052STejun Heo {
8981bd06867SMathias Krause 	static const struct dmi_system_id sysids[] = {
899edc93052STejun Heo 		{
900edc93052STejun Heo 			.ident = "P5W DH Deluxe",
901edc93052STejun Heo 			.matches = {
902edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
903edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
904edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
905edc93052STejun Heo 			},
906edc93052STejun Heo 		},
907edc93052STejun Heo 		{ }
908edc93052STejun Heo 	};
909edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
910edc93052STejun Heo 
911edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
912edc93052STejun Heo 	    dmi_check_system(sysids)) {
913edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
914edc93052STejun Heo 
915a44fec1fSJoe Perches 		dev_info(&pdev->dev,
916a44fec1fSJoe Perches 			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
917edc93052STejun Heo 
918edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
919edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
920edc93052STejun Heo 	}
921edc93052STejun Heo }
922edc93052STejun Heo 
923cb85696dSJames Laird /*
924cb85696dSJames Laird  * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
925cb85696dSJames Laird  * booting in BIOS compatibility mode.  We restore the registers but not ID.
926cb85696dSJames Laird  */
927cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
928cb85696dSJames Laird {
929cb85696dSJames Laird 	u32 val;
930cb85696dSJames Laird 
931cb85696dSJames Laird 	printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
932cb85696dSJames Laird 
933cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
934cb85696dSJames Laird 	val |= 1 << 0x1b;
935cb85696dSJames Laird 	/* the following changes the device ID, but appears not to affect function */
936cb85696dSJames Laird 	/* val = (val & ~0xf0000000) | 0x80000000; */
937cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
938cb85696dSJames Laird 
939cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
940cb85696dSJames Laird 	val |= 1 << 0xc;
941cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
942cb85696dSJames Laird 
943cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x4a4, &val);
944cb85696dSJames Laird 	val &= 0xff;
945cb85696dSJames Laird 	val |= 0x01060100;
946cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x4a4, val);
947cb85696dSJames Laird 
948cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
949cb85696dSJames Laird 	val &= ~(1 << 0xc);
950cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
951cb85696dSJames Laird 
952cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
953cb85696dSJames Laird 	val &= ~(1 << 0x1b);
954cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
955cb85696dSJames Laird }
956cb85696dSJames Laird 
957cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev)
958cb85696dSJames Laird {
959cb85696dSJames Laird 	return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
960cb85696dSJames Laird 		pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
961cb85696dSJames Laird 		pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
962cb85696dSJames Laird 		pdev->subsystem_device == 0xcb89;
963cb85696dSJames Laird }
964cb85696dSJames Laird 
9652fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
9662fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
96758a09b38SShane Huang {
96858a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
96903d783bfSTejun Heo 		/*
97003d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
97103d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
9722fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
9732fcad9d2STejun Heo 		 *
97403d783bfSTejun Heo 		 * Please read bko#9412 for more info.
97503d783bfSTejun Heo 		 */
97658a09b38SShane Huang 		{
97758a09b38SShane Huang 			.ident = "ASUS M2A-VM",
97858a09b38SShane Huang 			.matches = {
97958a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
98058a09b38SShane Huang 					  "ASUSTeK Computer INC."),
98158a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
98258a09b38SShane Huang 			},
98303d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
98458a09b38SShane Huang 		},
985e65cc194SMark Nelson 		/*
986e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
987e65cc194SMark Nelson 		 * support 64bit DMA.
988e65cc194SMark Nelson 		 *
989e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
990e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
991e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
992e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
993e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
994e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
995e65cc194SMark Nelson 		 *
996e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
997e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
998e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
999e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
1000e65cc194SMark Nelson 		 */
1001e65cc194SMark Nelson 		{
1002e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
1003e65cc194SMark Nelson 			.matches = {
1004e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1005e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
1006e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
1007e65cc194SMark Nelson 			},
1008e65cc194SMark Nelson 		},
10093c4aa91fSMark Nelson 		/*
1010ff0173c1SMark Nelson 		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support
1011ff0173c1SMark Nelson 		 * 64bit DMA.
1012ff0173c1SMark Nelson 		 *
1013ff0173c1SMark Nelson 		 * This board also had the typo mentioned above in the
1014ff0173c1SMark Nelson 		 * Manufacturer DMI field (fixed in BIOS version 1.5), so
1015ff0173c1SMark Nelson 		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again.
1016ff0173c1SMark Nelson 		 */
1017ff0173c1SMark Nelson 		{
1018ff0173c1SMark Nelson 			.ident = "MSI K9AGM2",
1019ff0173c1SMark Nelson 			.matches = {
1020ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1021ff0173c1SMark Nelson 					  "MICRO-STAR INTER"),
1022ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"),
1023ff0173c1SMark Nelson 			},
1024ff0173c1SMark Nelson 		},
1025ff0173c1SMark Nelson 		/*
10263c4aa91fSMark Nelson 		 * All BIOS versions for the Asus M3A support 64bit DMA.
10273c4aa91fSMark Nelson 		 * (all release versions from 0301 to 1206 were tested)
10283c4aa91fSMark Nelson 		 */
10293c4aa91fSMark Nelson 		{
10303c4aa91fSMark Nelson 			.ident = "ASUS M3A",
10313c4aa91fSMark Nelson 			.matches = {
10323c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
10333c4aa91fSMark Nelson 					  "ASUSTeK Computer INC."),
10343c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
10353c4aa91fSMark Nelson 			},
10363c4aa91fSMark Nelson 		},
103758a09b38SShane Huang 		{ }
103858a09b38SShane Huang 	};
103903d783bfSTejun Heo 	const struct dmi_system_id *match;
10402fcad9d2STejun Heo 	int year, month, date;
10412fcad9d2STejun Heo 	char buf[9];
104258a09b38SShane Huang 
104303d783bfSTejun Heo 	match = dmi_first_match(sysids);
104458a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
104503d783bfSTejun Heo 	    !match)
104658a09b38SShane Huang 		return false;
104758a09b38SShane Huang 
1048e65cc194SMark Nelson 	if (!match->driver_data)
1049e65cc194SMark Nelson 		goto enable_64bit;
1050e65cc194SMark Nelson 
105103d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
105203d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
105303d783bfSTejun Heo 
1054e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
1055e65cc194SMark Nelson 		goto enable_64bit;
1056e65cc194SMark Nelson 	else {
1057a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
1058a44fec1fSJoe Perches 			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
1059a44fec1fSJoe Perches 			 match->ident);
10602fcad9d2STejun Heo 		return false;
10612fcad9d2STejun Heo 	}
1062e65cc194SMark Nelson 
1063e65cc194SMark Nelson enable_64bit:
1064a44fec1fSJoe Perches 	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
1065e65cc194SMark Nelson 	return true;
106658a09b38SShane Huang }
106758a09b38SShane Huang 
10681fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
10691fd68434SRafael J. Wysocki {
10701fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
10711fd68434SRafael J. Wysocki 		{
10721fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
10731fd68434SRafael J. Wysocki 			.matches = {
10741fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
10751fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
10761fd68434SRafael J. Wysocki 			},
10771fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
10781fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
10791fd68434SRafael J. Wysocki 		},
1080d2f9c061SMaciej Rutecki 		{
1081d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
1082d2f9c061SMaciej Rutecki 			.matches = {
1083d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1084d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
1085d2f9c061SMaciej Rutecki 			},
1086d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
1087d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
1088d2f9c061SMaciej Rutecki 		},
10891fd68434SRafael J. Wysocki 
10901fd68434SRafael J. Wysocki 		{ }	/* terminate list */
10911fd68434SRafael J. Wysocki 	};
10921fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
10931fd68434SRafael J. Wysocki 
10941fd68434SRafael J. Wysocki 	if (dmi) {
10951fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
10961fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
10971fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
10981fd68434SRafael J. Wysocki 	}
10991fd68434SRafael J. Wysocki 
11001fd68434SRafael J. Wysocki 	return false;
11011fd68434SRafael J. Wysocki }
11021fd68434SRafael J. Wysocki 
11039b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
11049b10ae86STejun Heo {
11059b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
11069b10ae86STejun Heo 		/*
11079b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
11089b10ae86STejun Heo 		 * to the harddisk doesn't become online after
11099b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
11109deb3431STejun Heo 		 *
11119deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
11129deb3431STejun Heo 		 *
11139deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
11149deb3431STejun Heo 		 * apparently recycling both product and version
11159deb3431STejun Heo 		 * strings.
11169deb3431STejun Heo 		 *
11179deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
11189b10ae86STejun Heo 		 */
11199b10ae86STejun Heo 		{
11209b10ae86STejun Heo 			.ident = "dv4",
11219b10ae86STejun Heo 			.matches = {
11229b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11239b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
11249b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
11259b10ae86STejun Heo 			},
11269deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
11279b10ae86STejun Heo 		},
11289b10ae86STejun Heo 		{
11299b10ae86STejun Heo 			.ident = "dv5",
11309b10ae86STejun Heo 			.matches = {
11319b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11329b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
11339b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
11349b10ae86STejun Heo 			},
11359deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
11369b10ae86STejun Heo 		},
11379b10ae86STejun Heo 		{
11389b10ae86STejun Heo 			.ident = "dv6",
11399b10ae86STejun Heo 			.matches = {
11409b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11419b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
11429b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
11439b10ae86STejun Heo 			},
11449deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
11459b10ae86STejun Heo 		},
11469b10ae86STejun Heo 		{
11479b10ae86STejun Heo 			.ident = "HDX18",
11489b10ae86STejun Heo 			.matches = {
11499b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11509b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
11519b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
11529b10ae86STejun Heo 			},
11539deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
11549b10ae86STejun Heo 		},
1155cedc9bf9STejun Heo 		/*
1156cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
1157cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
115825985edcSLucas De Marchi 		 * work.  Between, there are V1.06, V2.06 and V3.03
1159cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
1160cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
11619deb3431STejun Heo 		 *
11629deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
1163cedc9bf9STejun Heo 		 */
1164cedc9bf9STejun Heo 		{
1165cedc9bf9STejun Heo 			.ident = "G725",
1166cedc9bf9STejun Heo 			.matches = {
1167cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
1168cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
1169cedc9bf9STejun Heo 			},
11709deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
1171cedc9bf9STejun Heo 		},
11729b10ae86STejun Heo 		{ }	/* terminate list */
11739b10ae86STejun Heo 	};
11749b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
11759deb3431STejun Heo 	int year, month, date;
11769deb3431STejun Heo 	char buf[9];
11779b10ae86STejun Heo 
11789b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
11799b10ae86STejun Heo 		return false;
11809b10ae86STejun Heo 
11819deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
11829deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
11839b10ae86STejun Heo 
11849deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
11859b10ae86STejun Heo }
11869b10ae86STejun Heo 
11875594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
11885594639aSTejun Heo {
11895594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
11905594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
11915594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
11925594639aSTejun Heo 		/*
11935594639aSTejun Heo 		 * There are several gigabyte boards which use
11945594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
11955594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
11965594639aSTejun Heo 		 * online but fail to answer properly to SRST or
11975594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
11985594639aSTejun Heo 		 * causing libata to retry quite a few times leading
11995594639aSTejun Heo 		 * to excessive detection delay.
12005594639aSTejun Heo 		 *
12015594639aSTejun Heo 		 * As these firmwares respond to the second reset try
12025594639aSTejun Heo 		 * with invalid device signature, considering unknown
12035594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
12045594639aSTejun Heo 		 */
12055594639aSTejun Heo 		{
12065594639aSTejun Heo 			.ident = "EP45-DQ6",
12075594639aSTejun Heo 			.matches = {
12085594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
12095594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
12105594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
12115594639aSTejun Heo 			},
12125594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
12135594639aSTejun Heo 		},
12145594639aSTejun Heo 		{
12155594639aSTejun Heo 			.ident = "EP45-DS5",
12165594639aSTejun Heo 			.matches = {
12175594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
12185594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
12195594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
12205594639aSTejun Heo 			},
12215594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
12225594639aSTejun Heo 		},
12235594639aSTejun Heo 		{ }	/* terminate list */
12245594639aSTejun Heo 	};
12255594639aSTejun Heo #undef ENCODE_BUSDEVFN
12265594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
12275594639aSTejun Heo 	unsigned int val;
12285594639aSTejun Heo 
12295594639aSTejun Heo 	if (!dmi)
12305594639aSTejun Heo 		return false;
12315594639aSTejun Heo 
12325594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
12335594639aSTejun Heo 
12345594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
12355594639aSTejun Heo }
12365594639aSTejun Heo 
12370cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev)
12380cf4a7d6SJacob Pan {
12390cf4a7d6SJacob Pan 	/* device with broken DEVSLP but still showing SDS capability */
12400cf4a7d6SJacob Pan 	static const struct pci_device_id ids[] = {
12410cf4a7d6SJacob Pan 		{ PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
12420cf4a7d6SJacob Pan 		{}
12430cf4a7d6SJacob Pan 	};
12440cf4a7d6SJacob Pan 
12450cf4a7d6SJacob Pan 	return pci_match_id(ids, pdev);
12460cf4a7d6SJacob Pan }
12470cf4a7d6SJacob Pan 
12488e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
1249f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
1250f80ae7e4STejun Heo {
1251f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
1252f80ae7e4STejun Heo 		/*
1253f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
1254f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
1255f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
1256f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
1257f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
1258f80ae7e4STejun Heo 		 * failures.  Filter it out.
1259f80ae7e4STejun Heo 		 */
1260f80ae7e4STejun Heo 		{
1261f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
1262f80ae7e4STejun Heo 			.matches = {
1263f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1264f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1265f80ae7e4STejun Heo 			},
1266f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1267f80ae7e4STejun Heo 		},
1268f80ae7e4STejun Heo 		{ }
1269f80ae7e4STejun Heo 	};
1270f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1271f80ae7e4STejun Heo 	unsigned int filter;
1272f80ae7e4STejun Heo 	int i;
1273f80ae7e4STejun Heo 
1274f80ae7e4STejun Heo 	if (!dmi)
1275f80ae7e4STejun Heo 		return;
1276f80ae7e4STejun Heo 
1277f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1278a44fec1fSJoe Perches 	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
1279f80ae7e4STejun Heo 		 filter, dmi->ident);
1280f80ae7e4STejun Heo 
1281f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1282f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1283f80ae7e4STejun Heo 		struct ata_link *link;
1284f80ae7e4STejun Heo 		struct ata_device *dev;
1285f80ae7e4STejun Heo 
1286f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1287f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1288f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1289f80ae7e4STejun Heo 	}
1290f80ae7e4STejun Heo }
12918e513217SMarkus Trippelsdorf #else
12928e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
12938e513217SMarkus Trippelsdorf {}
12948e513217SMarkus Trippelsdorf #endif
1295f80ae7e4STejun Heo 
1296ee2aad42SRobert Richter /*
1297ee2aad42SRobert Richter  * ahci_init_msix() only implements single MSI-X support, not multiple
1298ee2aad42SRobert Richter  * MSI-X per-port interrupts. This is needed for host controllers that only
1299ee2aad42SRobert Richter  * have MSI-X support implemented, but no MSI or intx.
1300ee2aad42SRobert Richter  */
1301ee2aad42SRobert Richter static int ahci_init_msix(struct pci_dev *pdev, unsigned int n_ports,
1302ee2aad42SRobert Richter 			  struct ahci_host_priv *hpriv)
1303ee2aad42SRobert Richter {
1304ee2aad42SRobert Richter 	int rc, nvec;
1305ee2aad42SRobert Richter 	struct msix_entry entry = {};
1306ee2aad42SRobert Richter 
1307ee2aad42SRobert Richter 	/* Do not init MSI-X if MSI is disabled for the device */
1308ee2aad42SRobert Richter 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
1309ee2aad42SRobert Richter 		return -ENODEV;
1310ee2aad42SRobert Richter 
1311ee2aad42SRobert Richter 	nvec = pci_msix_vec_count(pdev);
1312ee2aad42SRobert Richter 	if (nvec < 0)
1313ee2aad42SRobert Richter 		return nvec;
1314ee2aad42SRobert Richter 
1315ee2aad42SRobert Richter 	if (!nvec) {
1316ee2aad42SRobert Richter 		rc = -ENODEV;
1317ee2aad42SRobert Richter 		goto fail;
1318ee2aad42SRobert Richter 	}
1319ee2aad42SRobert Richter 
1320ee2aad42SRobert Richter 	/*
1321ee2aad42SRobert Richter 	 * There can be more than one vector (e.g. for error detection or
1322ee2aad42SRobert Richter 	 * hdd hotplug). Only the first vector (entry.entry = 0) is used.
1323ee2aad42SRobert Richter 	 */
1324ee2aad42SRobert Richter 	rc = pci_enable_msix_exact(pdev, &entry, 1);
1325ee2aad42SRobert Richter 	if (rc < 0)
1326ee2aad42SRobert Richter 		goto fail;
1327ee2aad42SRobert Richter 
132834c56932SRobert Richter 	hpriv->irq = entry.vector;
1329ee2aad42SRobert Richter 
1330ee2aad42SRobert Richter 	return 1;
1331ee2aad42SRobert Richter fail:
1332ee2aad42SRobert Richter 	dev_err(&pdev->dev,
1333ee2aad42SRobert Richter 		"failed to enable MSI-X with error %d, # of vectors: %d\n",
1334ee2aad42SRobert Richter 		rc, nvec);
1335ee2aad42SRobert Richter 
1336ee2aad42SRobert Richter 	return rc;
1337ee2aad42SRobert Richter }
1338ee2aad42SRobert Richter 
1339a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
13407b92b4f6SAlexander Gordeev 			struct ahci_host_priv *hpriv)
13415ca72c4fSAlexander Gordeev {
1342ccf8f53cSAlexander Gordeev 	int rc, nvec;
13435ca72c4fSAlexander Gordeev 
13447b92b4f6SAlexander Gordeev 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
1345a1c82311SRobert Richter 		return -ENODEV;
13467b92b4f6SAlexander Gordeev 
1347fc061d96SAlexander Gordeev 	nvec = pci_msi_vec_count(pdev);
1348fc061d96SAlexander Gordeev 	if (nvec < 0)
1349a1c82311SRobert Richter 		return nvec;
13507b92b4f6SAlexander Gordeev 
13515ca72c4fSAlexander Gordeev 	/*
13527b92b4f6SAlexander Gordeev 	 * If number of MSIs is less than number of ports then Sharing Last
13537b92b4f6SAlexander Gordeev 	 * Message mode could be enforced. In this case assume that advantage
13547b92b4f6SAlexander Gordeev 	 * of multipe MSIs is negated and use single MSI mode instead.
13555ca72c4fSAlexander Gordeev 	 */
1356fc061d96SAlexander Gordeev 	if (nvec < n_ports)
13577b92b4f6SAlexander Gordeev 		goto single_msi;
13585ca72c4fSAlexander Gordeev 
1359ccf8f53cSAlexander Gordeev 	rc = pci_enable_msi_exact(pdev, nvec);
1360ccf8f53cSAlexander Gordeev 	if (rc == -ENOSPC)
1361fc40363bSAlexander Gordeev 		goto single_msi;
1362a1c82311SRobert Richter 	if (rc < 0)
1363a1c82311SRobert Richter 		return rc;
1364ab0f9e78SAlexander Gordeev 
1365ab0f9e78SAlexander Gordeev 	/* fallback to single MSI mode if the controller enforced MRSM mode */
1366ab0f9e78SAlexander Gordeev 	if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) {
1367ab0f9e78SAlexander Gordeev 		pci_disable_msi(pdev);
1368ab0f9e78SAlexander Gordeev 		printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
1369ab0f9e78SAlexander Gordeev 		goto single_msi;
1370ab0f9e78SAlexander Gordeev 	}
13717b92b4f6SAlexander Gordeev 
1372c3ebd6a9SAlexander Gordeev 	if (nvec > 1)
1373c3ebd6a9SAlexander Gordeev 		hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
1374c3ebd6a9SAlexander Gordeev 
137521bfd1aaSRobert Richter 	goto out;
13767b92b4f6SAlexander Gordeev 
13777b92b4f6SAlexander Gordeev single_msi:
137821bfd1aaSRobert Richter 	nvec = 1;
13797b92b4f6SAlexander Gordeev 
1380a1c82311SRobert Richter 	rc = pci_enable_msi(pdev);
1381a1c82311SRobert Richter 	if (rc < 0)
1382a1c82311SRobert Richter 		return rc;
138321bfd1aaSRobert Richter out:
138421bfd1aaSRobert Richter 	hpriv->irq = pdev->irq;
13857b92b4f6SAlexander Gordeev 
138621bfd1aaSRobert Richter 	return nvec;
1387a1c82311SRobert Richter }
1388a1c82311SRobert Richter 
1389a1c82311SRobert Richter static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
1390a1c82311SRobert Richter 				struct ahci_host_priv *hpriv)
1391a1c82311SRobert Richter {
1392a1c82311SRobert Richter 	int nvec;
1393a1c82311SRobert Richter 
1394a1c82311SRobert Richter 	nvec = ahci_init_msi(pdev, n_ports, hpriv);
1395a1c82311SRobert Richter 	if (nvec >= 0)
1396a1c82311SRobert Richter 		return nvec;
1397a1c82311SRobert Richter 
1398ee2aad42SRobert Richter 	/*
1399ee2aad42SRobert Richter 	 * Currently, MSI-X support only implements single IRQ mode and
1400ee2aad42SRobert Richter 	 * exists for controllers which can't do other types of IRQ. Only
1401ee2aad42SRobert Richter 	 * set it up if MSI fails.
1402ee2aad42SRobert Richter 	 */
1403ee2aad42SRobert Richter 	nvec = ahci_init_msix(pdev, n_ports, hpriv);
1404ee2aad42SRobert Richter 	if (nvec >= 0)
1405ee2aad42SRobert Richter 		return nvec;
1406ee2aad42SRobert Richter 
1407a1c82311SRobert Richter 	/* lagacy intx interrupts */
14085ca72c4fSAlexander Gordeev 	pci_intx(pdev, 1);
140921bfd1aaSRobert Richter 	hpriv->irq = pdev->irq;
1410a1c82311SRobert Richter 
14115ca72c4fSAlexander Gordeev 	return 0;
14125ca72c4fSAlexander Gordeev }
14135ca72c4fSAlexander Gordeev 
1414c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1415c6fd2807SJeff Garzik {
1416e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1417e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
14184447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
141924dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1420c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
14214447d351STejun Heo 	struct ata_host *host;
1422c3ebd6a9SAlexander Gordeev 	int n_ports, i, rc;
1423318893e1SAlessandro Rubini 	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
1424c6fd2807SJeff Garzik 
1425c6fd2807SJeff Garzik 	VPRINTK("ENTER\n");
1426c6fd2807SJeff Garzik 
1427b429dd59SJustin P. Mattock 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1428c6fd2807SJeff Garzik 
142906296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1430c6fd2807SJeff Garzik 
14315b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
14325b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
14335b66c829SAlan Cox 	   AHCI stays out of the way */
14345b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
14355b66c829SAlan Cox 		return -ENODEV;
14365b66c829SAlan Cox 
1437cb85696dSJames Laird 	/* Apple BIOS on MCP89 prevents us using AHCI */
1438cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
1439cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
1440c6353b45STejun Heo 
14417a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
14427a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
14437a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
14447a02267eSMark Nelson 	 */
14457a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
1446a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1447a44fec1fSJoe Perches 			 "PDC42819 can only drive SATA devices with this driver\n");
14487a02267eSMark Nelson 
1449b7ae128dSRobert Richter 	/* Some devices use non-standard BARs */
1450318893e1SAlessandro Rubini 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
1451318893e1SAlessandro Rubini 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
14527f9c9f8eSHugh Daschbach 	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
14537f9c9f8eSHugh Daschbach 		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
1454b7ae128dSRobert Richter 	else if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
1455b7ae128dSRobert Richter 		ahci_pci_bar = AHCI_PCI_BAR_CAVIUM;
1456318893e1SAlessandro Rubini 
14574447d351STejun Heo 	/* acquire resources */
145824dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1459c6fd2807SJeff Garzik 	if (rc)
1460c6fd2807SJeff Garzik 		return rc;
1461c6fd2807SJeff Garzik 
1462c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1463c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1464c4f7792cSTejun Heo 		u8 map;
1465c4f7792cSTejun Heo 
1466c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1467c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1468c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1469c4f7792cSTejun Heo 		 */
1470c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1471c4f7792cSTejun Heo 		if (map & 0x3) {
1472a44fec1fSJoe Perches 			dev_info(&pdev->dev,
1473a44fec1fSJoe Perches 				 "controller is in combined mode, can't enable AHCI mode\n");
1474c4f7792cSTejun Heo 			return -ENODEV;
1475c4f7792cSTejun Heo 		}
1476c4f7792cSTejun Heo 	}
1477c4f7792cSTejun Heo 
14786fec8871SPaul Bolle 	/* AHCI controllers often implement SFF compatible interface.
14796fec8871SPaul Bolle 	 * Grab all PCI BARs just in case.
14806fec8871SPaul Bolle 	 */
14816fec8871SPaul Bolle 	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
14826fec8871SPaul Bolle 	if (rc == -EBUSY)
14836fec8871SPaul Bolle 		pcim_pin_device(pdev);
14846fec8871SPaul Bolle 	if (rc)
14856fec8871SPaul Bolle 		return rc;
14866fec8871SPaul Bolle 
148724dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
148824dc5f33STejun Heo 	if (!hpriv)
148924dc5f33STejun Heo 		return -ENOMEM;
1490417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1491417a1a6dSTejun Heo 
1492e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1493e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1494e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1495e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1496e297d99eSTejun Heo 
1497e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1498e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1499e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1500e427fe04SShane Huang 
15012fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
15022fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
15032fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
150458a09b38SShane Huang 
1505318893e1SAlessandro Rubini 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
1506d8993349SAnton Vorontsov 
15070cf4a7d6SJacob Pan 	/* must set flag prior to save config in order to take effect */
15080cf4a7d6SJacob Pan 	if (ahci_broken_devslp(pdev))
15090cf4a7d6SJacob Pan 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
15100cf4a7d6SJacob Pan 
15114447d351STejun Heo 	/* save initial config */
1512394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1513c6fd2807SJeff Garzik 
15144447d351STejun Heo 	/* prepare host */
1515453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1516453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
151783f2b963STejun Heo 		/*
151883f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
151983f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
152083f2b963STejun Heo 		 * capability, but it seems to be broken on some
152183f2b963STejun Heo 		 * chipsets including NVIDIAs.
152283f2b963STejun Heo 		 */
152383f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1524453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
152540fb59e7SMarc Carino 
152640fb59e7SMarc Carino 		/*
152740fb59e7SMarc Carino 		 * All AHCI controllers should be forward-compatible
152840fb59e7SMarc Carino 		 * with the new auxiliary field. This code should be
152940fb59e7SMarc Carino 		 * conditionalized if any buggy AHCI controllers are
153040fb59e7SMarc Carino 		 * encountered.
153140fb59e7SMarc Carino 		 */
153240fb59e7SMarc Carino 		pi.flags |= ATA_FLAG_FPDMA_AUX;
1533453d3131SRobert Hancock 	}
15344447d351STejun Heo 
15357d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
15367d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
15377d50b60bSTejun Heo 
15380cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
153918f7ba4cSKristen Carlson Accardi 
15401fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
15411fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
15421fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
15431fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
15441fd68434SRafael J. Wysocki 	}
15451fd68434SRafael J. Wysocki 
15469b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
15479b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
1548a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
15499b10ae86STejun Heo 			 "BIOS update required for suspend/resume\n");
15509b10ae86STejun Heo 	}
15519b10ae86STejun Heo 
15525594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
15535594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
15545594639aSTejun Heo 		dev_info(&pdev->dev,
15555594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
15565594639aSTejun Heo 	}
15575594639aSTejun Heo 
1558837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1559837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1560837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1561837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1562837f5f8fSTejun Heo 	 */
1563837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1564837f5f8fSTejun Heo 
1565837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
15664447d351STejun Heo 	if (!host)
15674447d351STejun Heo 		return -ENOMEM;
15684447d351STejun Heo 	host->private_data = hpriv;
15694447d351STejun Heo 
157021bfd1aaSRobert Richter 	ahci_init_interrupts(pdev, n_ports, hpriv);
157121bfd1aaSRobert Richter 
1572f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1573886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1574f3d7f23fSArjan van de Ven 	else
1575d2782d96SJingoo Han 		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
1576886ad09fSArjan van de Ven 
157718f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
157818f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
157918f7ba4cSKristen Carlson Accardi 
15804447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
15814447d351STejun Heo 		struct ata_port *ap = host->ports[i];
15824447d351STejun Heo 
1583318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
1584318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar,
1585cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
1586cbcdd875STejun Heo 
158718f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
158818f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
1589008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
159018f7ba4cSKristen Carlson Accardi 
159118f7ba4cSKristen Carlson Accardi 
1592dab632e8SJeff Garzik 		/* disabled/not-implemented port */
1593350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
1594dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
15954447d351STejun Heo 	}
1596c6fd2807SJeff Garzik 
1597edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
1598edc93052STejun Heo 	ahci_p5wdh_workaround(host);
1599edc93052STejun Heo 
1600f80ae7e4STejun Heo 	/* apply gtf filter quirk */
1601f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
1602f80ae7e4STejun Heo 
1603c6fd2807SJeff Garzik 	/* initialize adapter */
16044447d351STejun Heo 	rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
1605c6fd2807SJeff Garzik 	if (rc)
160624dc5f33STejun Heo 		return rc;
1607c6fd2807SJeff Garzik 
16083303040dSAnton Vorontsov 	rc = ahci_pci_reset_controller(host);
16094447d351STejun Heo 	if (rc)
16104447d351STejun Heo 		return rc;
1611c6fd2807SJeff Garzik 
1612781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
1613439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
1614c6fd2807SJeff Garzik 
16154447d351STejun Heo 	pci_set_master(pdev);
16165ca72c4fSAlexander Gordeev 
161721bfd1aaSRobert Richter 	return ahci_host_activate(host, &ahci_sht);
1618c6fd2807SJeff Garzik }
1619c6fd2807SJeff Garzik 
16202fc75da0SAxel Lin module_pci_driver(ahci_pci_driver);
1621c6fd2807SJeff Garzik 
1622c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
1623c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
1624c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
1625c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
1626c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
1627