xref: /openbmc/linux/drivers/ata/ahci.c (revision b7ae128d728c42583dac9db48dce9a44bc0fb900)
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,
56*b7ae128dSRobert 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 */
71441577efSTejun Heo 	board_ahci_mcp65,
7283f2b963STejun Heo 	board_ahci_mcp77,
7383f2b963STejun Heo 	board_ahci_mcp89,
74441577efSTejun Heo 	board_ahci_mv,
75441577efSTejun Heo 	board_ahci_sb600,
76441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
77441577efSTejun Heo 	board_ahci_vt8251,
78441577efSTejun Heo 
79441577efSTejun Heo 	/* aliases */
80441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
81441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
82441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
8383f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
84c6fd2807SJeff Garzik };
85c6fd2807SJeff Garzik 
86c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
87a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
88a1efdabaSTejun Heo 				 unsigned long deadline);
89cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
90cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev);
91a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
92a1efdabaSTejun Heo 				unsigned long deadline);
93438ac6d5STejun Heo #ifdef CONFIG_PM
94c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
95c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev);
96438ac6d5STejun Heo #endif
97c6fd2807SJeff Garzik 
98fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = {
99fad16e7aSTejun Heo 	AHCI_SHT("ahci"),
100fad16e7aSTejun Heo };
101fad16e7aSTejun Heo 
102029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
103029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
104a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
105ad616ffbSTejun Heo };
106ad616ffbSTejun Heo 
107029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
108029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
109a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
110edc93052STejun Heo };
111edc93052STejun Heo 
112c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
113441577efSTejun Heo 	/* by features */
114facb8fa6SJeffrin Jose 	[board_ahci] = {
1151188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
11614bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
117469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
118c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
119c6fd2807SJeff Garzik 	},
120facb8fa6SJeffrin Jose 	[board_ahci_ign_iferr] = {
121417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
122417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
12314bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
124469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
12541669553STejun Heo 		.port_ops	= &ahci_ops,
12641669553STejun Heo 	},
12766a7cbc3STejun Heo 	[board_ahci_nomsi] = {
12866a7cbc3STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_MSI),
12966a7cbc3STejun Heo 		.flags		= AHCI_FLAG_COMMON,
13066a7cbc3STejun Heo 		.pio_mask	= ATA_PIO4,
13166a7cbc3STejun Heo 		.udma_mask	= ATA_UDMA6,
13266a7cbc3STejun Heo 		.port_ops	= &ahci_ops,
13366a7cbc3STejun Heo 	},
13467809f85SLevente Kurusa 	[board_ahci_noncq] = {
13567809f85SLevente Kurusa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ),
13667809f85SLevente Kurusa 		.flags		= AHCI_FLAG_COMMON,
13767809f85SLevente Kurusa 		.pio_mask	= ATA_PIO4,
13867809f85SLevente Kurusa 		.udma_mask	= ATA_UDMA6,
13967809f85SLevente Kurusa 		.port_ops	= &ahci_ops,
14067809f85SLevente Kurusa 	},
141facb8fa6SJeffrin Jose 	[board_ahci_nosntf] = {
142441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
143441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
144441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
145441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
146441577efSTejun Heo 		.port_ops	= &ahci_ops,
147441577efSTejun Heo 	},
148facb8fa6SJeffrin Jose 	[board_ahci_yes_fbs] = {
1495f173107STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),
1505f173107STejun Heo 		.flags		= AHCI_FLAG_COMMON,
1515f173107STejun Heo 		.pio_mask	= ATA_PIO4,
1525f173107STejun Heo 		.udma_mask	= ATA_UDMA6,
1535f173107STejun Heo 		.port_ops	= &ahci_ops,
1545f173107STejun Heo 	},
155441577efSTejun Heo 	/* by chipsets */
156facb8fa6SJeffrin Jose 	[board_ahci_mcp65] = {
15783f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
15883f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
159ae01b249STejun Heo 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
16083f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
16183f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
16283f2b963STejun Heo 		.port_ops	= &ahci_ops,
16383f2b963STejun Heo 	},
164facb8fa6SJeffrin Jose 	[board_ahci_mcp77] = {
16583f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
16683f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
16783f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
16883f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
16983f2b963STejun Heo 		.port_ops	= &ahci_ops,
17083f2b963STejun Heo 	},
171facb8fa6SJeffrin Jose 	[board_ahci_mcp89] = {
17283f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
173441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
174441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
175441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
176441577efSTejun Heo 		.port_ops	= &ahci_ops,
177441577efSTejun Heo 	},
178facb8fa6SJeffrin Jose 	[board_ahci_mv] = {
179441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
180441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
1819cbe056fSSergei Shtylyov 		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
182441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
183441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
184441577efSTejun Heo 		.port_ops	= &ahci_ops,
185441577efSTejun Heo 	},
186facb8fa6SJeffrin Jose 	[board_ahci_sb600] = {
187417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
1882fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
1892fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
190417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
19114bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
192469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
193345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
19455a61604SConke Hu 	},
195facb8fa6SJeffrin Jose 	[board_ahci_sb700] = {	/* for SB700 and SB800 */
196bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
197e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
19814bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
199e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
200345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
201e39fc8c9SShane Huang 	},
202facb8fa6SJeffrin Jose 	[board_ahci_vt8251] = {
203441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
204e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
20514bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
206e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
207441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
2081b677afdSShaohua Li 	},
209c6fd2807SJeff Garzik };
210c6fd2807SJeff Garzik 
211c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
212c6fd2807SJeff Garzik 	/* Intel */
21354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
21454bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
21554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
21654bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
21754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
21882490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
21954bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
22054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
22154bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
22254bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2237a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2241b677afdSShaohua Li 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
2257a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2267a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2277a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2287a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2297a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2307a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2317a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2327a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
2337a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
2347a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
2357a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
2367a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
2377a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
2387a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
2397a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
240d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
241d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
24216ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
243b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
24416ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
245c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
246c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
247adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
2488e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
249c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
250adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
2518e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
252c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
2535623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
2545623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
2555623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
2565623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
2575623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
2585623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
259992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
260992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
261992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
26264a3903dSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
263a4a461a6SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
264181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
265181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */
266181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
267181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
268181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
269181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
2702cab7a4cSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
271ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
272ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */
273ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
274ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */
275ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
276ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */
277ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
278ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */
27977b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */
28077b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */
28177b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */
28277b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */
28377b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */
28477b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */
28577b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */
28677b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */
28729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
28829e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
28929e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
29029e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
29129e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
29229e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
29329e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
29429e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
29529e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */
29629e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */
29729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */
29829e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */
29929e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */
30029e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
30129e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
30229e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
303efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
304efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
305151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
306151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
307151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
308151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
309151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
310151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
311151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
312151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
3131cfc7df3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
3149f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */
3159f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */
3169f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */
3179f961a5fSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */
3181b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
3191b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */
3201b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
3211b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */
3221b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
3231b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
3241b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
3251b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
326249cd0a1SDevin Ryles 	{ PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */
327249cd0a1SDevin Ryles 	{ PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */
328249cd0a1SDevin Ryles 	{ PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */
329690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
330690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
331690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
332690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
333c6fd2807SJeff Garzik 
334e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
335e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
336e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
3371fefb8fdSBen Hutchings 	/* JMicron 362B and 362C have an AHCI function with IDE class code */
3381fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
3391fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
340c6fd2807SJeff Garzik 
341c6fd2807SJeff Garzik 	/* ATI */
342c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
343e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
344e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
345e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
346e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
347e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
348e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
349c6fd2807SJeff Garzik 
350e2dd90b1SShane Huang 	/* AMD */
3515deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
352fafe5c3dSShane Huang 	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
353e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
354e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
355e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
356e2dd90b1SShane Huang 
357c6fd2807SJeff Garzik 	/* VIA */
35854bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
359bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
360c6fd2807SJeff Garzik 
361c6fd2807SJeff Garzik 	/* NVIDIA */
362e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
363e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
364e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
365e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
366e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
367e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
368e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
369e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
370441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
371441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
372441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
373441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
374441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
375441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
376441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
377441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
378441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
379441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
380441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
381441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
382441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
383441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
384441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
385441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
386441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
387441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
388441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
389441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
390441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
391441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
392441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
393441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
394441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
395441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
396441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
397441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
398441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
399441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
400441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
401441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
402441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
403441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
404441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
405441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
406441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
407441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
408441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
409441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
410441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
411441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
412441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
413441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
414441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
415441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
416441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
417441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
418441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
419441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
420441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
421441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
422441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
423441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
424441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
425441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
426441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
427441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
428441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
429441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
430441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
431441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
432441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
433441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
434441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
435441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
436441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
437441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
438441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
439441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
440441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
441441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
442441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
443441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
444441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
445441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
446c6fd2807SJeff Garzik 
447c6fd2807SJeff Garzik 	/* SiS */
44820e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
44920e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
45020e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
451c6fd2807SJeff Garzik 
452318893e1SAlessandro Rubini 	/* ST Microelectronics */
453318893e1SAlessandro Rubini 	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */
454318893e1SAlessandro Rubini 
455cd70c266SJeff Garzik 	/* Marvell */
456cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
457c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
45869fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
45910aca06cSAnssi Hannula 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
46010aca06cSAnssi Hannula 	  .class_mask = 0xffffff,
4615f173107STejun Heo 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
46269fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
463467b41c6SPer Jessen 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
464e098f5cbSSimon Guinot 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
465e098f5cbSSimon Guinot 			 PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
466e098f5cbSSimon Guinot 	  .driver_data = board_ahci_yes_fbs },			/* 88se9170 */
46769fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
468642d8925SMatt Johnson 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
469fcce9a35SGeorge Spelvin 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
470c5edfff9SMurali Karicheri 	  .driver_data = board_ahci_yes_fbs },			/* 88se9182 */
471c5edfff9SMurali Karicheri 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
472fcce9a35SGeorge Spelvin 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
47369fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
47417c60c6bSAlan Cox 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */
475754a292fSAndreas Schrägle 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0),
476754a292fSAndreas Schrägle 	  .driver_data = board_ahci_yes_fbs },
47769fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
47850be5e36STejun Heo 	  .driver_data = board_ahci_yes_fbs },
4796d5278a6SSamir Benmendil 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
4806d5278a6SSamir Benmendil 	  .driver_data = board_ahci_yes_fbs },
481d2518365SJérôme Carretero 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642),
482d2518365SJérôme Carretero 	  .driver_data = board_ahci_yes_fbs },
483cd70c266SJeff Garzik 
484c77a036bSMark Nelson 	/* Promise */
485c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
486b32bfc06SRomain Degez 	{ PCI_VDEVICE(PROMISE, 0x3781), board_ahci },   /* FastTrak TX8660 ahci-mode */
487c77a036bSMark Nelson 
488c9703765SKeng-Yu Lin 	/* Asmedia */
4897b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },	/* ASM1060 */
4907b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },	/* ASM1060 */
4917b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */
4927b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */
493c9703765SKeng-Yu Lin 
49467809f85SLevente Kurusa 	/*
49566a7cbc3STejun Heo 	 * Samsung SSDs found on some macbooks.  NCQ times out if MSI is
49666a7cbc3STejun Heo 	 * enabled.  https://bugzilla.kernel.org/show_bug.cgi?id=60731
49767809f85SLevente Kurusa 	 */
49866a7cbc3STejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
4992b21ef0aSTejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi },
50067809f85SLevente Kurusa 
5017f9c9f8eSHugh Daschbach 	/* Enmotus */
5027f9c9f8eSHugh Daschbach 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
5037f9c9f8eSHugh Daschbach 
504415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
505415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
506c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
507415ae2b5SJeff Garzik 
508c6fd2807SJeff Garzik 	{ }	/* terminate list */
509c6fd2807SJeff Garzik };
510c6fd2807SJeff Garzik 
511c6fd2807SJeff Garzik 
512c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
513c6fd2807SJeff Garzik 	.name			= DRV_NAME,
514c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
515c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
51624dc5f33STejun Heo 	.remove			= ata_pci_remove_one,
517438ac6d5STejun Heo #ifdef CONFIG_PM
518c6fd2807SJeff Garzik 	.suspend		= ahci_pci_device_suspend,
519c6fd2807SJeff Garzik 	.resume			= ahci_pci_device_resume,
520438ac6d5STejun Heo #endif
521c6fd2807SJeff Garzik };
522c6fd2807SJeff Garzik 
5235b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
5245b66c829SAlan Cox static int marvell_enable;
5255b66c829SAlan Cox #else
5265b66c829SAlan Cox static int marvell_enable = 1;
5275b66c829SAlan Cox #endif
5285b66c829SAlan Cox module_param(marvell_enable, int, 0644);
5295b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
5305b66c829SAlan Cox 
5315b66c829SAlan Cox 
532394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
533394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
534394d6e53SAnton Vorontsov {
535394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
536394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
5379a23c1d6SAntoine Tenart 		hpriv->force_port_map = 1;
538394d6e53SAnton Vorontsov 	}
539394d6e53SAnton Vorontsov 
540394d6e53SAnton Vorontsov 	/*
541394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
542394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
543394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
544394d6e53SAnton Vorontsov 	 */
545394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
546394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
5479a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0x3;
548394d6e53SAnton Vorontsov 		else
5499a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0xf;
550394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
551394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
552394d6e53SAnton Vorontsov 	}
553394d6e53SAnton Vorontsov 
554725c7b57SAntoine Ténart 	ahci_save_initial_config(&pdev->dev, hpriv);
555394d6e53SAnton Vorontsov }
556394d6e53SAnton Vorontsov 
5573303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host)
5583303040dSAnton Vorontsov {
5593303040dSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
5603303040dSAnton Vorontsov 
5613303040dSAnton Vorontsov 	ahci_reset_controller(host);
5623303040dSAnton Vorontsov 
563c6fd2807SJeff Garzik 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
5643303040dSAnton Vorontsov 		struct ahci_host_priv *hpriv = host->private_data;
565c6fd2807SJeff Garzik 		u16 tmp16;
566c6fd2807SJeff Garzik 
567c6fd2807SJeff Garzik 		/* configure PCS */
568c6fd2807SJeff Garzik 		pci_read_config_word(pdev, 0x92, &tmp16);
56949f29090STejun Heo 		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
57049f29090STejun Heo 			tmp16 |= hpriv->port_map;
571c6fd2807SJeff Garzik 			pci_write_config_word(pdev, 0x92, tmp16);
572c6fd2807SJeff Garzik 		}
57349f29090STejun Heo 	}
574c6fd2807SJeff Garzik 
575c6fd2807SJeff Garzik 	return 0;
576c6fd2807SJeff Garzik }
577c6fd2807SJeff Garzik 
578781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
579781d6550SAnton Vorontsov {
580781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
581781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
582781d6550SAnton Vorontsov 	void __iomem *port_mmio;
583781d6550SAnton Vorontsov 	u32 tmp;
584c40e7cb8SJose Alberto Reguero 	int mv;
5852bcd866bSJeff Garzik 
586417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
587c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
588c40e7cb8SJose Alberto Reguero 			mv = 2;
589c40e7cb8SJose Alberto Reguero 		else
590c40e7cb8SJose Alberto Reguero 			mv = 4;
591c40e7cb8SJose Alberto Reguero 		port_mmio = __ahci_port_base(host, mv);
592cd70c266SJeff Garzik 
593cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
594cd70c266SJeff Garzik 
595cd70c266SJeff Garzik 		/* clear port IRQ */
596cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
597cd70c266SJeff Garzik 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
598cd70c266SJeff Garzik 		if (tmp)
599cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
600cd70c266SJeff Garzik 	}
601cd70c266SJeff Garzik 
602781d6550SAnton Vorontsov 	ahci_init_controller(host);
603c6fd2807SJeff Garzik }
604c6fd2807SJeff Garzik 
605cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
606d4b2bab4STejun Heo 				 unsigned long deadline)
607ad616ffbSTejun Heo {
608cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
609039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
6109dadd45bSTejun Heo 	bool online;
611ad616ffbSTejun Heo 	int rc;
612ad616ffbSTejun Heo 
613ad616ffbSTejun Heo 	DPRINTK("ENTER\n");
614ad616ffbSTejun Heo 
6154447d351STejun Heo 	ahci_stop_engine(ap);
616ad616ffbSTejun Heo 
617cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
6189dadd45bSTejun Heo 				 deadline, &online, NULL);
619ad616ffbSTejun Heo 
620039ece38SHans de Goede 	hpriv->start_engine(ap);
621ad616ffbSTejun Heo 
622ad616ffbSTejun Heo 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
623ad616ffbSTejun Heo 
624ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
625ad616ffbSTejun Heo 	 * request follow-up softreset.
626ad616ffbSTejun Heo 	 */
6279dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
628ad616ffbSTejun Heo }
629ad616ffbSTejun Heo 
630edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
631edc93052STejun Heo 				unsigned long deadline)
632edc93052STejun Heo {
633edc93052STejun Heo 	struct ata_port *ap = link->ap;
634edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
635039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
636edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
637edc93052STejun Heo 	struct ata_taskfile tf;
6389dadd45bSTejun Heo 	bool online;
639edc93052STejun Heo 	int rc;
640edc93052STejun Heo 
641edc93052STejun Heo 	ahci_stop_engine(ap);
642edc93052STejun Heo 
643edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
644edc93052STejun Heo 	ata_tf_init(link->device, &tf);
6459bbb1b0eSSergei Shtylyov 	tf.command = ATA_BUSY;
646edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
647edc93052STejun Heo 
648edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
6499dadd45bSTejun Heo 				 deadline, &online, NULL);
650edc93052STejun Heo 
651039ece38SHans de Goede 	hpriv->start_engine(ap);
652edc93052STejun Heo 
653edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
654edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
655edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
656edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
657edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
658edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
659edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
660edc93052STejun Heo 	 *
661edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
662edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
663edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
664edc93052STejun Heo 	 * suffice while making probing snappish enough.
665edc93052STejun Heo 	 */
6669dadd45bSTejun Heo 	if (online) {
6679dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
6689dadd45bSTejun Heo 					  ahci_check_ready);
669edc93052STejun Heo 		if (rc)
67078d5ae39SShane Huang 			ahci_kick_engine(ap);
6719dadd45bSTejun Heo 	}
6729dadd45bSTejun Heo 	return rc;
673edc93052STejun Heo }
674edc93052STejun Heo 
675438ac6d5STejun Heo #ifdef CONFIG_PM
676c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
677c6fd2807SJeff Garzik {
6780a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
6799b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
680d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
681c6fd2807SJeff Garzik 	u32 ctl;
682c6fd2807SJeff Garzik 
6839b10ae86STejun Heo 	if (mesg.event & PM_EVENT_SUSPEND &&
6849b10ae86STejun Heo 	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
685a44fec1fSJoe Perches 		dev_err(&pdev->dev,
6869b10ae86STejun Heo 			"BIOS update required for suspend/resume\n");
6879b10ae86STejun Heo 		return -EIO;
6889b10ae86STejun Heo 	}
6899b10ae86STejun Heo 
6903a2d5b70SRafael J. Wysocki 	if (mesg.event & PM_EVENT_SLEEP) {
691c6fd2807SJeff Garzik 		/* AHCI spec rev1.1 section 8.3.3:
692c6fd2807SJeff Garzik 		 * Software must disable interrupts prior to requesting a
693c6fd2807SJeff Garzik 		 * transition of the HBA to D3 state.
694c6fd2807SJeff Garzik 		 */
695c6fd2807SJeff Garzik 		ctl = readl(mmio + HOST_CTL);
696c6fd2807SJeff Garzik 		ctl &= ~HOST_IRQ_EN;
697c6fd2807SJeff Garzik 		writel(ctl, mmio + HOST_CTL);
698c6fd2807SJeff Garzik 		readl(mmio + HOST_CTL); /* flush */
699c6fd2807SJeff Garzik 	}
700c6fd2807SJeff Garzik 
701c6fd2807SJeff Garzik 	return ata_pci_device_suspend(pdev, mesg);
702c6fd2807SJeff Garzik }
703c6fd2807SJeff Garzik 
704c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev)
705c6fd2807SJeff Garzik {
7060a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
707c6fd2807SJeff Garzik 	int rc;
708c6fd2807SJeff Garzik 
709553c4aa6STejun Heo 	rc = ata_pci_device_do_resume(pdev);
710553c4aa6STejun Heo 	if (rc)
711553c4aa6STejun Heo 		return rc;
712c6fd2807SJeff Garzik 
713cb85696dSJames Laird 	/* Apple BIOS helpfully mangles the registers on resume */
714cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
715cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
716cb85696dSJames Laird 
717c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
7183303040dSAnton Vorontsov 		rc = ahci_pci_reset_controller(host);
719c6fd2807SJeff Garzik 		if (rc)
720c6fd2807SJeff Garzik 			return rc;
721c6fd2807SJeff Garzik 
722781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
723c6fd2807SJeff Garzik 	}
724c6fd2807SJeff Garzik 
725cca3974eSJeff Garzik 	ata_host_resume(host);
726c6fd2807SJeff Garzik 
727c6fd2807SJeff Garzik 	return 0;
728c6fd2807SJeff Garzik }
729438ac6d5STejun Heo #endif
730c6fd2807SJeff Garzik 
7314447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
732c6fd2807SJeff Garzik {
733c6fd2807SJeff Garzik 	int rc;
734c6fd2807SJeff Garzik 
735318893e1SAlessandro Rubini 	/*
736318893e1SAlessandro Rubini 	 * If the device fixup already set the dma_mask to some non-standard
737318893e1SAlessandro Rubini 	 * value, don't extend it here. This happens on STA2X11, for example.
738318893e1SAlessandro Rubini 	 */
739318893e1SAlessandro Rubini 	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
740318893e1SAlessandro Rubini 		return 0;
741318893e1SAlessandro Rubini 
742c6fd2807SJeff Garzik 	if (using_dac &&
743c54c719bSQuentin Lambert 	    !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
744c54c719bSQuentin Lambert 		rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
745c6fd2807SJeff Garzik 		if (rc) {
746c54c719bSQuentin Lambert 			rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
747c6fd2807SJeff Garzik 			if (rc) {
748a44fec1fSJoe Perches 				dev_err(&pdev->dev,
749c6fd2807SJeff Garzik 					"64-bit DMA enable failed\n");
750c6fd2807SJeff Garzik 				return rc;
751c6fd2807SJeff Garzik 			}
752c6fd2807SJeff Garzik 		}
753c6fd2807SJeff Garzik 	} else {
754c54c719bSQuentin Lambert 		rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
755c6fd2807SJeff Garzik 		if (rc) {
756a44fec1fSJoe Perches 			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
757c6fd2807SJeff Garzik 			return rc;
758c6fd2807SJeff Garzik 		}
759c54c719bSQuentin Lambert 		rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
760c6fd2807SJeff Garzik 		if (rc) {
761a44fec1fSJoe Perches 			dev_err(&pdev->dev,
762c6fd2807SJeff Garzik 				"32-bit consistent DMA enable failed\n");
763c6fd2807SJeff Garzik 			return rc;
764c6fd2807SJeff Garzik 		}
765c6fd2807SJeff Garzik 	}
766c6fd2807SJeff Garzik 	return 0;
767c6fd2807SJeff Garzik }
768c6fd2807SJeff Garzik 
769439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
770439fcaecSAnton Vorontsov {
771439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
772439fcaecSAnton Vorontsov 	u16 cc;
773439fcaecSAnton Vorontsov 	const char *scc_s;
774439fcaecSAnton Vorontsov 
775439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
776439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
777439fcaecSAnton Vorontsov 		scc_s = "IDE";
778439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
779439fcaecSAnton Vorontsov 		scc_s = "SATA";
780439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
781439fcaecSAnton Vorontsov 		scc_s = "RAID";
782439fcaecSAnton Vorontsov 	else
783439fcaecSAnton Vorontsov 		scc_s = "unknown";
784439fcaecSAnton Vorontsov 
785439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
786439fcaecSAnton Vorontsov }
787439fcaecSAnton Vorontsov 
788edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
789edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
790edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
791edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
792edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
793edc93052STejun Heo  * other configuration).
794edc93052STejun Heo  *
795edc93052STejun Heo  * When there's no device attached to the first downstream port of the
796edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
797edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
798edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
799edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
800edc93052STejun Heo  *
801edc93052STejun Heo  * The following function works around the problem by always using
802edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
803edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
804edc93052STejun Heo  * assumed without follow-up softreset.
805edc93052STejun Heo  */
806edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
807edc93052STejun Heo {
8081bd06867SMathias Krause 	static const struct dmi_system_id sysids[] = {
809edc93052STejun Heo 		{
810edc93052STejun Heo 			.ident = "P5W DH Deluxe",
811edc93052STejun Heo 			.matches = {
812edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
813edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
814edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
815edc93052STejun Heo 			},
816edc93052STejun Heo 		},
817edc93052STejun Heo 		{ }
818edc93052STejun Heo 	};
819edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
820edc93052STejun Heo 
821edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
822edc93052STejun Heo 	    dmi_check_system(sysids)) {
823edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
824edc93052STejun Heo 
825a44fec1fSJoe Perches 		dev_info(&pdev->dev,
826a44fec1fSJoe Perches 			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
827edc93052STejun Heo 
828edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
829edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
830edc93052STejun Heo 	}
831edc93052STejun Heo }
832edc93052STejun Heo 
833cb85696dSJames Laird /*
834cb85696dSJames Laird  * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
835cb85696dSJames Laird  * booting in BIOS compatibility mode.  We restore the registers but not ID.
836cb85696dSJames Laird  */
837cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
838cb85696dSJames Laird {
839cb85696dSJames Laird 	u32 val;
840cb85696dSJames Laird 
841cb85696dSJames Laird 	printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
842cb85696dSJames Laird 
843cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
844cb85696dSJames Laird 	val |= 1 << 0x1b;
845cb85696dSJames Laird 	/* the following changes the device ID, but appears not to affect function */
846cb85696dSJames Laird 	/* val = (val & ~0xf0000000) | 0x80000000; */
847cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
848cb85696dSJames Laird 
849cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
850cb85696dSJames Laird 	val |= 1 << 0xc;
851cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
852cb85696dSJames Laird 
853cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x4a4, &val);
854cb85696dSJames Laird 	val &= 0xff;
855cb85696dSJames Laird 	val |= 0x01060100;
856cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x4a4, val);
857cb85696dSJames Laird 
858cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
859cb85696dSJames Laird 	val &= ~(1 << 0xc);
860cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
861cb85696dSJames Laird 
862cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
863cb85696dSJames Laird 	val &= ~(1 << 0x1b);
864cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
865cb85696dSJames Laird }
866cb85696dSJames Laird 
867cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev)
868cb85696dSJames Laird {
869cb85696dSJames Laird 	return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
870cb85696dSJames Laird 		pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
871cb85696dSJames Laird 		pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
872cb85696dSJames Laird 		pdev->subsystem_device == 0xcb89;
873cb85696dSJames Laird }
874cb85696dSJames Laird 
8752fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
8762fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
87758a09b38SShane Huang {
87858a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
87903d783bfSTejun Heo 		/*
88003d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
88103d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
8822fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
8832fcad9d2STejun Heo 		 *
88403d783bfSTejun Heo 		 * Please read bko#9412 for more info.
88503d783bfSTejun Heo 		 */
88658a09b38SShane Huang 		{
88758a09b38SShane Huang 			.ident = "ASUS M2A-VM",
88858a09b38SShane Huang 			.matches = {
88958a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
89058a09b38SShane Huang 					  "ASUSTeK Computer INC."),
89158a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
89258a09b38SShane Huang 			},
89303d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
89458a09b38SShane Huang 		},
895e65cc194SMark Nelson 		/*
896e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
897e65cc194SMark Nelson 		 * support 64bit DMA.
898e65cc194SMark Nelson 		 *
899e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
900e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
901e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
902e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
903e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
904e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
905e65cc194SMark Nelson 		 *
906e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
907e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
908e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
909e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
910e65cc194SMark Nelson 		 */
911e65cc194SMark Nelson 		{
912e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
913e65cc194SMark Nelson 			.matches = {
914e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
915e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
916e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
917e65cc194SMark Nelson 			},
918e65cc194SMark Nelson 		},
9193c4aa91fSMark Nelson 		/*
920ff0173c1SMark Nelson 		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support
921ff0173c1SMark Nelson 		 * 64bit DMA.
922ff0173c1SMark Nelson 		 *
923ff0173c1SMark Nelson 		 * This board also had the typo mentioned above in the
924ff0173c1SMark Nelson 		 * Manufacturer DMI field (fixed in BIOS version 1.5), so
925ff0173c1SMark Nelson 		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again.
926ff0173c1SMark Nelson 		 */
927ff0173c1SMark Nelson 		{
928ff0173c1SMark Nelson 			.ident = "MSI K9AGM2",
929ff0173c1SMark Nelson 			.matches = {
930ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
931ff0173c1SMark Nelson 					  "MICRO-STAR INTER"),
932ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"),
933ff0173c1SMark Nelson 			},
934ff0173c1SMark Nelson 		},
935ff0173c1SMark Nelson 		/*
9363c4aa91fSMark Nelson 		 * All BIOS versions for the Asus M3A support 64bit DMA.
9373c4aa91fSMark Nelson 		 * (all release versions from 0301 to 1206 were tested)
9383c4aa91fSMark Nelson 		 */
9393c4aa91fSMark Nelson 		{
9403c4aa91fSMark Nelson 			.ident = "ASUS M3A",
9413c4aa91fSMark Nelson 			.matches = {
9423c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
9433c4aa91fSMark Nelson 					  "ASUSTeK Computer INC."),
9443c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
9453c4aa91fSMark Nelson 			},
9463c4aa91fSMark Nelson 		},
94758a09b38SShane Huang 		{ }
94858a09b38SShane Huang 	};
94903d783bfSTejun Heo 	const struct dmi_system_id *match;
9502fcad9d2STejun Heo 	int year, month, date;
9512fcad9d2STejun Heo 	char buf[9];
95258a09b38SShane Huang 
95303d783bfSTejun Heo 	match = dmi_first_match(sysids);
95458a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
95503d783bfSTejun Heo 	    !match)
95658a09b38SShane Huang 		return false;
95758a09b38SShane Huang 
958e65cc194SMark Nelson 	if (!match->driver_data)
959e65cc194SMark Nelson 		goto enable_64bit;
960e65cc194SMark Nelson 
96103d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
96203d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
96303d783bfSTejun Heo 
964e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
965e65cc194SMark Nelson 		goto enable_64bit;
966e65cc194SMark Nelson 	else {
967a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
968a44fec1fSJoe Perches 			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
969a44fec1fSJoe Perches 			 match->ident);
9702fcad9d2STejun Heo 		return false;
9712fcad9d2STejun Heo 	}
972e65cc194SMark Nelson 
973e65cc194SMark Nelson enable_64bit:
974a44fec1fSJoe Perches 	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
975e65cc194SMark Nelson 	return true;
97658a09b38SShane Huang }
97758a09b38SShane Huang 
9781fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
9791fd68434SRafael J. Wysocki {
9801fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
9811fd68434SRafael J. Wysocki 		{
9821fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
9831fd68434SRafael J. Wysocki 			.matches = {
9841fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
9851fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
9861fd68434SRafael J. Wysocki 			},
9871fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
9881fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
9891fd68434SRafael J. Wysocki 		},
990d2f9c061SMaciej Rutecki 		{
991d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
992d2f9c061SMaciej Rutecki 			.matches = {
993d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
994d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
995d2f9c061SMaciej Rutecki 			},
996d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
997d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
998d2f9c061SMaciej Rutecki 		},
9991fd68434SRafael J. Wysocki 
10001fd68434SRafael J. Wysocki 		{ }	/* terminate list */
10011fd68434SRafael J. Wysocki 	};
10021fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
10031fd68434SRafael J. Wysocki 
10041fd68434SRafael J. Wysocki 	if (dmi) {
10051fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
10061fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
10071fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
10081fd68434SRafael J. Wysocki 	}
10091fd68434SRafael J. Wysocki 
10101fd68434SRafael J. Wysocki 	return false;
10111fd68434SRafael J. Wysocki }
10121fd68434SRafael J. Wysocki 
10139b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
10149b10ae86STejun Heo {
10159b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
10169b10ae86STejun Heo 		/*
10179b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
10189b10ae86STejun Heo 		 * to the harddisk doesn't become online after
10199b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
10209deb3431STejun Heo 		 *
10219deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
10229deb3431STejun Heo 		 *
10239deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
10249deb3431STejun Heo 		 * apparently recycling both product and version
10259deb3431STejun Heo 		 * strings.
10269deb3431STejun Heo 		 *
10279deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
10289b10ae86STejun Heo 		 */
10299b10ae86STejun Heo 		{
10309b10ae86STejun Heo 			.ident = "dv4",
10319b10ae86STejun Heo 			.matches = {
10329b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
10339b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
10349b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
10359b10ae86STejun Heo 			},
10369deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
10379b10ae86STejun Heo 		},
10389b10ae86STejun Heo 		{
10399b10ae86STejun Heo 			.ident = "dv5",
10409b10ae86STejun Heo 			.matches = {
10419b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
10429b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
10439b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
10449b10ae86STejun Heo 			},
10459deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
10469b10ae86STejun Heo 		},
10479b10ae86STejun Heo 		{
10489b10ae86STejun Heo 			.ident = "dv6",
10499b10ae86STejun Heo 			.matches = {
10509b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
10519b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
10529b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
10539b10ae86STejun Heo 			},
10549deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
10559b10ae86STejun Heo 		},
10569b10ae86STejun Heo 		{
10579b10ae86STejun Heo 			.ident = "HDX18",
10589b10ae86STejun Heo 			.matches = {
10599b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
10609b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
10619b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
10629b10ae86STejun Heo 			},
10639deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
10649b10ae86STejun Heo 		},
1065cedc9bf9STejun Heo 		/*
1066cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
1067cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
106825985edcSLucas De Marchi 		 * work.  Between, there are V1.06, V2.06 and V3.03
1069cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
1070cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
10719deb3431STejun Heo 		 *
10729deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
1073cedc9bf9STejun Heo 		 */
1074cedc9bf9STejun Heo 		{
1075cedc9bf9STejun Heo 			.ident = "G725",
1076cedc9bf9STejun Heo 			.matches = {
1077cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
1078cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
1079cedc9bf9STejun Heo 			},
10809deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
1081cedc9bf9STejun Heo 		},
10829b10ae86STejun Heo 		{ }	/* terminate list */
10839b10ae86STejun Heo 	};
10849b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
10859deb3431STejun Heo 	int year, month, date;
10869deb3431STejun Heo 	char buf[9];
10879b10ae86STejun Heo 
10889b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
10899b10ae86STejun Heo 		return false;
10909b10ae86STejun Heo 
10919deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
10929deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
10939b10ae86STejun Heo 
10949deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
10959b10ae86STejun Heo }
10969b10ae86STejun Heo 
10975594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
10985594639aSTejun Heo {
10995594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
11005594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
11015594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
11025594639aSTejun Heo 		/*
11035594639aSTejun Heo 		 * There are several gigabyte boards which use
11045594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
11055594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
11065594639aSTejun Heo 		 * online but fail to answer properly to SRST or
11075594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
11085594639aSTejun Heo 		 * causing libata to retry quite a few times leading
11095594639aSTejun Heo 		 * to excessive detection delay.
11105594639aSTejun Heo 		 *
11115594639aSTejun Heo 		 * As these firmwares respond to the second reset try
11125594639aSTejun Heo 		 * with invalid device signature, considering unknown
11135594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
11145594639aSTejun Heo 		 */
11155594639aSTejun Heo 		{
11165594639aSTejun Heo 			.ident = "EP45-DQ6",
11175594639aSTejun Heo 			.matches = {
11185594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
11195594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
11205594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
11215594639aSTejun Heo 			},
11225594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
11235594639aSTejun Heo 		},
11245594639aSTejun Heo 		{
11255594639aSTejun Heo 			.ident = "EP45-DS5",
11265594639aSTejun Heo 			.matches = {
11275594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
11285594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
11295594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
11305594639aSTejun Heo 			},
11315594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
11325594639aSTejun Heo 		},
11335594639aSTejun Heo 		{ }	/* terminate list */
11345594639aSTejun Heo 	};
11355594639aSTejun Heo #undef ENCODE_BUSDEVFN
11365594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
11375594639aSTejun Heo 	unsigned int val;
11385594639aSTejun Heo 
11395594639aSTejun Heo 	if (!dmi)
11405594639aSTejun Heo 		return false;
11415594639aSTejun Heo 
11425594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
11435594639aSTejun Heo 
11445594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
11455594639aSTejun Heo }
11465594639aSTejun Heo 
11470cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev)
11480cf4a7d6SJacob Pan {
11490cf4a7d6SJacob Pan 	/* device with broken DEVSLP but still showing SDS capability */
11500cf4a7d6SJacob Pan 	static const struct pci_device_id ids[] = {
11510cf4a7d6SJacob Pan 		{ PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
11520cf4a7d6SJacob Pan 		{}
11530cf4a7d6SJacob Pan 	};
11540cf4a7d6SJacob Pan 
11550cf4a7d6SJacob Pan 	return pci_match_id(ids, pdev);
11560cf4a7d6SJacob Pan }
11570cf4a7d6SJacob Pan 
11588e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
1159f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
1160f80ae7e4STejun Heo {
1161f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
1162f80ae7e4STejun Heo 		/*
1163f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
1164f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
1165f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
1166f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
1167f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
1168f80ae7e4STejun Heo 		 * failures.  Filter it out.
1169f80ae7e4STejun Heo 		 */
1170f80ae7e4STejun Heo 		{
1171f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
1172f80ae7e4STejun Heo 			.matches = {
1173f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1174f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1175f80ae7e4STejun Heo 			},
1176f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1177f80ae7e4STejun Heo 		},
1178f80ae7e4STejun Heo 		{ }
1179f80ae7e4STejun Heo 	};
1180f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1181f80ae7e4STejun Heo 	unsigned int filter;
1182f80ae7e4STejun Heo 	int i;
1183f80ae7e4STejun Heo 
1184f80ae7e4STejun Heo 	if (!dmi)
1185f80ae7e4STejun Heo 		return;
1186f80ae7e4STejun Heo 
1187f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1188a44fec1fSJoe Perches 	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
1189f80ae7e4STejun Heo 		 filter, dmi->ident);
1190f80ae7e4STejun Heo 
1191f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1192f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1193f80ae7e4STejun Heo 		struct ata_link *link;
1194f80ae7e4STejun Heo 		struct ata_device *dev;
1195f80ae7e4STejun Heo 
1196f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1197f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1198f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1199f80ae7e4STejun Heo 	}
1200f80ae7e4STejun Heo }
12018e513217SMarkus Trippelsdorf #else
12028e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
12038e513217SMarkus Trippelsdorf {}
12048e513217SMarkus Trippelsdorf #endif
1205f80ae7e4STejun Heo 
1206ee2aad42SRobert Richter static struct msi_desc *msix_get_desc(struct pci_dev *dev, u16 entry)
1207ee2aad42SRobert Richter {
1208ee2aad42SRobert Richter 	struct msi_desc *desc;
1209ee2aad42SRobert Richter 
1210ee2aad42SRobert Richter 	list_for_each_entry(desc, &dev->msi_list, list) {
1211ee2aad42SRobert Richter 		if (desc->msi_attrib.entry_nr == entry)
1212ee2aad42SRobert Richter 			return desc;
1213ee2aad42SRobert Richter 	}
1214ee2aad42SRobert Richter 
1215ee2aad42SRobert Richter 	return NULL;
1216ee2aad42SRobert Richter }
1217ee2aad42SRobert Richter 
1218ee2aad42SRobert Richter /*
1219ee2aad42SRobert Richter  * ahci_init_msix() only implements single MSI-X support, not multiple
1220ee2aad42SRobert Richter  * MSI-X per-port interrupts. This is needed for host controllers that only
1221ee2aad42SRobert Richter  * have MSI-X support implemented, but no MSI or intx.
1222ee2aad42SRobert Richter  */
1223ee2aad42SRobert Richter static int ahci_init_msix(struct pci_dev *pdev, unsigned int n_ports,
1224ee2aad42SRobert Richter 			  struct ahci_host_priv *hpriv)
1225ee2aad42SRobert Richter {
1226ee2aad42SRobert Richter 	struct msi_desc *desc;
1227ee2aad42SRobert Richter 	int rc, nvec;
1228ee2aad42SRobert Richter 	struct msix_entry entry = {};
1229ee2aad42SRobert Richter 
1230ee2aad42SRobert Richter 	/* Do not init MSI-X if MSI is disabled for the device */
1231ee2aad42SRobert Richter 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
1232ee2aad42SRobert Richter 		return -ENODEV;
1233ee2aad42SRobert Richter 
1234ee2aad42SRobert Richter 	nvec = pci_msix_vec_count(pdev);
1235ee2aad42SRobert Richter 	if (nvec < 0)
1236ee2aad42SRobert Richter 		return nvec;
1237ee2aad42SRobert Richter 
1238ee2aad42SRobert Richter 	if (!nvec) {
1239ee2aad42SRobert Richter 		rc = -ENODEV;
1240ee2aad42SRobert Richter 		goto fail;
1241ee2aad42SRobert Richter 	}
1242ee2aad42SRobert Richter 
1243ee2aad42SRobert Richter 	/*
1244ee2aad42SRobert Richter 	 * There can be more than one vector (e.g. for error detection or
1245ee2aad42SRobert Richter 	 * hdd hotplug). Only the first vector (entry.entry = 0) is used.
1246ee2aad42SRobert Richter 	 */
1247ee2aad42SRobert Richter 	rc = pci_enable_msix_exact(pdev, &entry, 1);
1248ee2aad42SRobert Richter 	if (rc < 0)
1249ee2aad42SRobert Richter 		goto fail;
1250ee2aad42SRobert Richter 
1251ee2aad42SRobert Richter 	desc = msix_get_desc(pdev, 0);	/* first entry */
1252ee2aad42SRobert Richter 	if (!desc) {
1253ee2aad42SRobert Richter 		rc = -EINVAL;
1254ee2aad42SRobert Richter 		goto fail;
1255ee2aad42SRobert Richter 	}
1256ee2aad42SRobert Richter 
1257ee2aad42SRobert Richter 	hpriv->irq = desc->irq;
1258ee2aad42SRobert Richter 
1259ee2aad42SRobert Richter 	return 1;
1260ee2aad42SRobert Richter fail:
1261ee2aad42SRobert Richter 	dev_err(&pdev->dev,
1262ee2aad42SRobert Richter 		"failed to enable MSI-X with error %d, # of vectors: %d\n",
1263ee2aad42SRobert Richter 		rc, nvec);
1264ee2aad42SRobert Richter 
1265ee2aad42SRobert Richter 	return rc;
1266ee2aad42SRobert Richter }
1267ee2aad42SRobert Richter 
1268a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
12697b92b4f6SAlexander Gordeev 			struct ahci_host_priv *hpriv)
12705ca72c4fSAlexander Gordeev {
1271ccf8f53cSAlexander Gordeev 	int rc, nvec;
12725ca72c4fSAlexander Gordeev 
12737b92b4f6SAlexander Gordeev 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
1274a1c82311SRobert Richter 		return -ENODEV;
12757b92b4f6SAlexander Gordeev 
1276fc061d96SAlexander Gordeev 	nvec = pci_msi_vec_count(pdev);
1277fc061d96SAlexander Gordeev 	if (nvec < 0)
1278a1c82311SRobert Richter 		return nvec;
12797b92b4f6SAlexander Gordeev 
12805ca72c4fSAlexander Gordeev 	/*
12817b92b4f6SAlexander Gordeev 	 * If number of MSIs is less than number of ports then Sharing Last
12827b92b4f6SAlexander Gordeev 	 * Message mode could be enforced. In this case assume that advantage
12837b92b4f6SAlexander Gordeev 	 * of multipe MSIs is negated and use single MSI mode instead.
12845ca72c4fSAlexander Gordeev 	 */
1285fc061d96SAlexander Gordeev 	if (nvec < n_ports)
12867b92b4f6SAlexander Gordeev 		goto single_msi;
12875ca72c4fSAlexander Gordeev 
1288ccf8f53cSAlexander Gordeev 	rc = pci_enable_msi_exact(pdev, nvec);
1289ccf8f53cSAlexander Gordeev 	if (rc == -ENOSPC)
1290fc40363bSAlexander Gordeev 		goto single_msi;
1291a1c82311SRobert Richter 	if (rc < 0)
1292a1c82311SRobert Richter 		return rc;
1293ab0f9e78SAlexander Gordeev 
1294ab0f9e78SAlexander Gordeev 	/* fallback to single MSI mode if the controller enforced MRSM mode */
1295ab0f9e78SAlexander Gordeev 	if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) {
1296ab0f9e78SAlexander Gordeev 		pci_disable_msi(pdev);
1297ab0f9e78SAlexander Gordeev 		printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
1298ab0f9e78SAlexander Gordeev 		goto single_msi;
1299ab0f9e78SAlexander Gordeev 	}
13007b92b4f6SAlexander Gordeev 
1301c3ebd6a9SAlexander Gordeev 	if (nvec > 1)
1302c3ebd6a9SAlexander Gordeev 		hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
1303c3ebd6a9SAlexander Gordeev 
130421bfd1aaSRobert Richter 	goto out;
13057b92b4f6SAlexander Gordeev 
13067b92b4f6SAlexander Gordeev single_msi:
130721bfd1aaSRobert Richter 	nvec = 1;
130821bfd1aaSRobert Richter 
1309a1c82311SRobert Richter 	rc = pci_enable_msi(pdev);
1310a1c82311SRobert Richter 	if (rc < 0)
1311a1c82311SRobert Richter 		return rc;
131221bfd1aaSRobert Richter out:
131321bfd1aaSRobert Richter 	hpriv->irq = pdev->irq;
13147b92b4f6SAlexander Gordeev 
131521bfd1aaSRobert Richter 	return nvec;
1316a1c82311SRobert Richter }
1317a1c82311SRobert Richter 
1318a1c82311SRobert Richter static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
1319a1c82311SRobert Richter 				struct ahci_host_priv *hpriv)
1320a1c82311SRobert Richter {
1321a1c82311SRobert Richter 	int nvec;
1322a1c82311SRobert Richter 
1323a1c82311SRobert Richter 	nvec = ahci_init_msi(pdev, n_ports, hpriv);
1324a1c82311SRobert Richter 	if (nvec >= 0)
1325a1c82311SRobert Richter 		return nvec;
1326a1c82311SRobert Richter 
1327ee2aad42SRobert Richter 	/*
1328ee2aad42SRobert Richter 	 * Currently, MSI-X support only implements single IRQ mode and
1329ee2aad42SRobert Richter 	 * exists for controllers which can't do other types of IRQ. Only
1330ee2aad42SRobert Richter 	 * set it up if MSI fails.
1331ee2aad42SRobert Richter 	 */
1332ee2aad42SRobert Richter 	nvec = ahci_init_msix(pdev, n_ports, hpriv);
1333ee2aad42SRobert Richter 	if (nvec >= 0)
1334ee2aad42SRobert Richter 		return nvec;
1335ee2aad42SRobert Richter 
1336a1c82311SRobert Richter 	/* lagacy intx interrupts */
13375ca72c4fSAlexander Gordeev 	pci_intx(pdev, 1);
133821bfd1aaSRobert Richter 	hpriv->irq = pdev->irq;
1339a1c82311SRobert Richter 
13405ca72c4fSAlexander Gordeev 	return 0;
13415ca72c4fSAlexander Gordeev }
13425ca72c4fSAlexander Gordeev 
1343c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1344c6fd2807SJeff Garzik {
1345e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1346e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
13474447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
134824dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1349c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
13504447d351STejun Heo 	struct ata_host *host;
1351c3ebd6a9SAlexander Gordeev 	int n_ports, i, rc;
1352318893e1SAlessandro Rubini 	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
1353c6fd2807SJeff Garzik 
1354c6fd2807SJeff Garzik 	VPRINTK("ENTER\n");
1355c6fd2807SJeff Garzik 
1356b429dd59SJustin P. Mattock 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1357c6fd2807SJeff Garzik 
135806296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1359c6fd2807SJeff Garzik 
13605b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
13615b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
13625b66c829SAlan Cox 	   AHCI stays out of the way */
13635b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
13645b66c829SAlan Cox 		return -ENODEV;
13655b66c829SAlan Cox 
1366cb85696dSJames Laird 	/* Apple BIOS on MCP89 prevents us using AHCI */
1367cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
1368cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
1369c6353b45STejun Heo 
13707a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
13717a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
13727a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
13737a02267eSMark Nelson 	 */
13747a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
1375a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1376a44fec1fSJoe Perches 			 "PDC42819 can only drive SATA devices with this driver\n");
13777a02267eSMark Nelson 
1378*b7ae128dSRobert Richter 	/* Some devices use non-standard BARs */
1379318893e1SAlessandro Rubini 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
1380318893e1SAlessandro Rubini 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
13817f9c9f8eSHugh Daschbach 	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
13827f9c9f8eSHugh Daschbach 		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
1383*b7ae128dSRobert Richter 	else if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
1384*b7ae128dSRobert Richter 		ahci_pci_bar = AHCI_PCI_BAR_CAVIUM;
1385318893e1SAlessandro Rubini 
1386e6b7e41cSChuansheng Liu 	/*
1387e6b7e41cSChuansheng Liu 	 * The JMicron chip 361/363 contains one SATA controller and one
1388e6b7e41cSChuansheng Liu 	 * PATA controller,for powering on these both controllers, we must
1389e6b7e41cSChuansheng Liu 	 * follow the sequence one by one, otherwise one of them can not be
1390e6b7e41cSChuansheng Liu 	 * powered on successfully, so here we disable the async suspend
1391e6b7e41cSChuansheng Liu 	 * method for these chips.
1392e6b7e41cSChuansheng Liu 	 */
1393e6b7e41cSChuansheng Liu 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON &&
1394e6b7e41cSChuansheng Liu 		(pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 ||
1395e6b7e41cSChuansheng Liu 		pdev->device == PCI_DEVICE_ID_JMICRON_JMB361))
1396e6b7e41cSChuansheng Liu 		device_disable_async_suspend(&pdev->dev);
1397e6b7e41cSChuansheng Liu 
13984447d351STejun Heo 	/* acquire resources */
139924dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1400c6fd2807SJeff Garzik 	if (rc)
1401c6fd2807SJeff Garzik 		return rc;
1402c6fd2807SJeff Garzik 
1403c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1404c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1405c4f7792cSTejun Heo 		u8 map;
1406c4f7792cSTejun Heo 
1407c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1408c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1409c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1410c4f7792cSTejun Heo 		 */
1411c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1412c4f7792cSTejun Heo 		if (map & 0x3) {
1413a44fec1fSJoe Perches 			dev_info(&pdev->dev,
1414a44fec1fSJoe Perches 				 "controller is in combined mode, can't enable AHCI mode\n");
1415c4f7792cSTejun Heo 			return -ENODEV;
1416c4f7792cSTejun Heo 		}
1417c4f7792cSTejun Heo 	}
1418c4f7792cSTejun Heo 
14196fec8871SPaul Bolle 	/* AHCI controllers often implement SFF compatible interface.
14206fec8871SPaul Bolle 	 * Grab all PCI BARs just in case.
14216fec8871SPaul Bolle 	 */
14226fec8871SPaul Bolle 	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
14236fec8871SPaul Bolle 	if (rc == -EBUSY)
14246fec8871SPaul Bolle 		pcim_pin_device(pdev);
14256fec8871SPaul Bolle 	if (rc)
14266fec8871SPaul Bolle 		return rc;
14276fec8871SPaul Bolle 
142824dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
142924dc5f33STejun Heo 	if (!hpriv)
143024dc5f33STejun Heo 		return -ENOMEM;
1431417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1432417a1a6dSTejun Heo 
1433e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1434e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1435e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1436e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1437e297d99eSTejun Heo 
1438e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1439e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1440e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1441e427fe04SShane Huang 
14422fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
14432fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
14442fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
144558a09b38SShane Huang 
1446318893e1SAlessandro Rubini 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
1447d8993349SAnton Vorontsov 
14480cf4a7d6SJacob Pan 	/* must set flag prior to save config in order to take effect */
14490cf4a7d6SJacob Pan 	if (ahci_broken_devslp(pdev))
14500cf4a7d6SJacob Pan 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
14510cf4a7d6SJacob Pan 
14524447d351STejun Heo 	/* save initial config */
1453394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1454c6fd2807SJeff Garzik 
14554447d351STejun Heo 	/* prepare host */
1456453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1457453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
145883f2b963STejun Heo 		/*
145983f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
146083f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
146183f2b963STejun Heo 		 * capability, but it seems to be broken on some
146283f2b963STejun Heo 		 * chipsets including NVIDIAs.
146383f2b963STejun Heo 		 */
146483f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1465453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
146640fb59e7SMarc Carino 
146740fb59e7SMarc Carino 		/*
146840fb59e7SMarc Carino 		 * All AHCI controllers should be forward-compatible
146940fb59e7SMarc Carino 		 * with the new auxiliary field. This code should be
147040fb59e7SMarc Carino 		 * conditionalized if any buggy AHCI controllers are
147140fb59e7SMarc Carino 		 * encountered.
147240fb59e7SMarc Carino 		 */
147340fb59e7SMarc Carino 		pi.flags |= ATA_FLAG_FPDMA_AUX;
1474453d3131SRobert Hancock 	}
14754447d351STejun Heo 
14767d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
14777d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
14787d50b60bSTejun Heo 
14790cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
148018f7ba4cSKristen Carlson Accardi 
14811fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
14821fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
14831fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
14841fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
14851fd68434SRafael J. Wysocki 	}
14861fd68434SRafael J. Wysocki 
14879b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
14889b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
1489a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
14909b10ae86STejun Heo 			 "BIOS update required for suspend/resume\n");
14919b10ae86STejun Heo 	}
14929b10ae86STejun Heo 
14935594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
14945594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
14955594639aSTejun Heo 		dev_info(&pdev->dev,
14965594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
14975594639aSTejun Heo 	}
14985594639aSTejun Heo 
1499837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1500837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1501837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1502837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1503837f5f8fSTejun Heo 	 */
1504837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1505837f5f8fSTejun Heo 
1506837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
15074447d351STejun Heo 	if (!host)
15084447d351STejun Heo 		return -ENOMEM;
15094447d351STejun Heo 	host->private_data = hpriv;
15104447d351STejun Heo 
151121bfd1aaSRobert Richter 	ahci_init_interrupts(pdev, n_ports, hpriv);
151221bfd1aaSRobert Richter 
1513f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1514886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1515f3d7f23fSArjan van de Ven 	else
1516d2782d96SJingoo Han 		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
1517886ad09fSArjan van de Ven 
151818f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
151918f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
152018f7ba4cSKristen Carlson Accardi 
15214447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
15224447d351STejun Heo 		struct ata_port *ap = host->ports[i];
15234447d351STejun Heo 
1524318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
1525318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar,
1526cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
1527cbcdd875STejun Heo 
152818f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
152918f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
1530008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
153118f7ba4cSKristen Carlson Accardi 
153218f7ba4cSKristen Carlson Accardi 
1533dab632e8SJeff Garzik 		/* disabled/not-implemented port */
1534350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
1535dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
15364447d351STejun Heo 	}
1537c6fd2807SJeff Garzik 
1538edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
1539edc93052STejun Heo 	ahci_p5wdh_workaround(host);
1540edc93052STejun Heo 
1541f80ae7e4STejun Heo 	/* apply gtf filter quirk */
1542f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
1543f80ae7e4STejun Heo 
1544c6fd2807SJeff Garzik 	/* initialize adapter */
15454447d351STejun Heo 	rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
1546c6fd2807SJeff Garzik 	if (rc)
154724dc5f33STejun Heo 		return rc;
1548c6fd2807SJeff Garzik 
15493303040dSAnton Vorontsov 	rc = ahci_pci_reset_controller(host);
15504447d351STejun Heo 	if (rc)
15514447d351STejun Heo 		return rc;
1552c6fd2807SJeff Garzik 
1553781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
1554439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
1555c6fd2807SJeff Garzik 
15564447d351STejun Heo 	pci_set_master(pdev);
15575ca72c4fSAlexander Gordeev 
155821bfd1aaSRobert Richter 	return ahci_host_activate(host, &ahci_sht);
1559c6fd2807SJeff Garzik }
1560c6fd2807SJeff Garzik 
15612fc75da0SAxel Lin module_pci_driver(ahci_pci_driver);
1562c6fd2807SJeff Garzik 
1563c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
1564c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
1565c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
1566c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
1567c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
1568