xref: /openbmc/linux/drivers/ata/ahci.c (revision fafe5c3d82a470d73de53e6b08eb4e28d974d895)
1c6fd2807SJeff Garzik /*
2c6fd2807SJeff Garzik  *  ahci.c - AHCI SATA support
3c6fd2807SJeff Garzik  *
4c6fd2807SJeff Garzik  *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
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/init.h>
39c6fd2807SJeff Garzik #include <linux/blkdev.h>
40c6fd2807SJeff Garzik #include <linux/delay.h>
41c6fd2807SJeff Garzik #include <linux/interrupt.h>
42c6fd2807SJeff Garzik #include <linux/dma-mapping.h>
43c6fd2807SJeff Garzik #include <linux/device.h>
44edc93052STejun Heo #include <linux/dmi.h>
455a0e3ad6STejun Heo #include <linux/gfp.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,
567f9c9f8eSHugh Daschbach 	AHCI_PCI_BAR_ENMOTUS	= 2,
57318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STANDARD	= 5,
58441577efSTejun Heo };
59c6fd2807SJeff Garzik 
60441577efSTejun Heo enum board_ids {
61441577efSTejun Heo 	/* board IDs by feature in alphabetical order */
62441577efSTejun Heo 	board_ahci,
63441577efSTejun Heo 	board_ahci_ign_iferr,
64441577efSTejun Heo 	board_ahci_nosntf,
655f173107STejun Heo 	board_ahci_yes_fbs,
66441577efSTejun Heo 
67441577efSTejun Heo 	/* board IDs for specific chipsets in alphabetical order */
68441577efSTejun Heo 	board_ahci_mcp65,
6983f2b963STejun Heo 	board_ahci_mcp77,
7083f2b963STejun Heo 	board_ahci_mcp89,
71441577efSTejun Heo 	board_ahci_mv,
72441577efSTejun Heo 	board_ahci_sb600,
73441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
74441577efSTejun Heo 	board_ahci_vt8251,
75441577efSTejun Heo 
76441577efSTejun Heo 	/* aliases */
77441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
78441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
79441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
8083f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
81c6fd2807SJeff Garzik };
82c6fd2807SJeff Garzik 
83c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
84a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
85a1efdabaSTejun Heo 				 unsigned long deadline);
86a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
87a1efdabaSTejun Heo 				unsigned long deadline);
88438ac6d5STejun Heo #ifdef CONFIG_PM
89c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
90c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev);
91438ac6d5STejun Heo #endif
92c6fd2807SJeff Garzik 
93fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = {
94fad16e7aSTejun Heo 	AHCI_SHT("ahci"),
95fad16e7aSTejun Heo };
96fad16e7aSTejun Heo 
97029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
98029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
99a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
100ad616ffbSTejun Heo };
101ad616ffbSTejun Heo 
102029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
103029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
104a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
105edc93052STejun Heo };
106edc93052STejun Heo 
107c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
108441577efSTejun Heo 	/* by features */
109facb8fa6SJeffrin Jose 	[board_ahci] = {
1101188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
11114bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
112469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
113c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
114c6fd2807SJeff Garzik 	},
115facb8fa6SJeffrin Jose 	[board_ahci_ign_iferr] = {
116417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
117417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
11814bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
119469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
12041669553STejun Heo 		.port_ops	= &ahci_ops,
12141669553STejun Heo 	},
122facb8fa6SJeffrin Jose 	[board_ahci_nosntf] = {
123441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
124441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
125441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
126441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
127441577efSTejun Heo 		.port_ops	= &ahci_ops,
128441577efSTejun Heo 	},
129facb8fa6SJeffrin Jose 	[board_ahci_yes_fbs] = {
1305f173107STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),
1315f173107STejun Heo 		.flags		= AHCI_FLAG_COMMON,
1325f173107STejun Heo 		.pio_mask	= ATA_PIO4,
1335f173107STejun Heo 		.udma_mask	= ATA_UDMA6,
1345f173107STejun Heo 		.port_ops	= &ahci_ops,
1355f173107STejun Heo 	},
136441577efSTejun Heo 	/* by chipsets */
137facb8fa6SJeffrin Jose 	[board_ahci_mcp65] = {
13883f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
13983f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
140ae01b249STejun Heo 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
14183f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
14283f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
14383f2b963STejun Heo 		.port_ops	= &ahci_ops,
14483f2b963STejun Heo 	},
145facb8fa6SJeffrin Jose 	[board_ahci_mcp77] = {
14683f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
14783f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
14883f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
14983f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
15083f2b963STejun Heo 		.port_ops	= &ahci_ops,
15183f2b963STejun Heo 	},
152facb8fa6SJeffrin Jose 	[board_ahci_mcp89] = {
15383f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
154441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
155441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
156441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
157441577efSTejun Heo 		.port_ops	= &ahci_ops,
158441577efSTejun Heo 	},
159facb8fa6SJeffrin Jose 	[board_ahci_mv] = {
160441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
161441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
1629cbe056fSSergei Shtylyov 		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
163441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
164441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
165441577efSTejun Heo 		.port_ops	= &ahci_ops,
166441577efSTejun Heo 	},
167facb8fa6SJeffrin Jose 	[board_ahci_sb600] = {
168417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
1692fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
1702fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
171417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
17214bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
173469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
174345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
17555a61604SConke Hu 	},
176facb8fa6SJeffrin Jose 	[board_ahci_sb700] = {	/* for SB700 and SB800 */
177bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
178e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
17914bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
180e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
181345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
182e39fc8c9SShane Huang 	},
183facb8fa6SJeffrin Jose 	[board_ahci_vt8251] = {
184441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
185e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
18614bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
187e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
188441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
1891b677afdSShaohua Li 	},
190c6fd2807SJeff Garzik };
191c6fd2807SJeff Garzik 
192c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
193c6fd2807SJeff Garzik 	/* Intel */
19454bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
19554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
19654bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
19754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
19854bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
19982490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
20054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
20154bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
20254bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
20354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2047a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2051b677afdSShaohua Li 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
2067a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2077a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2087a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2097a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2107a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2117a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2127a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2137a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
2147a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
2157a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
2167a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
2177a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
2187a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
2197a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
2207a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
221d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
222d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
22316ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
224b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
22516ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
226c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
227c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
228adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
2298e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
230c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
231adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
2328e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
233c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
2345623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
2355623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
2365623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
2375623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
2385623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
2395623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
240992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
241992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
242992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
24364a3903dSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
244a4a461a6SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
245181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
246181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */
247181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
248181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
249181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
250181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
2512cab7a4cSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
252ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
253ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */
254ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
255ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */
256ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
257ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */
258ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
259ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */
26077b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */
26177b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */
26277b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */
26377b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */
26477b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */
26577b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */
26677b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */
26777b12bc9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */
26829e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
26929e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
27029e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
27129e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
27229e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
27329e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
27429e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
27529e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
27629e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */
27729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */
27829e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */
27929e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */
28029e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */
28129e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
28229e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
28329e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
284efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
285efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
286151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
287151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
288151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
289151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
290151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
291151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
292151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
293151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
294c6fd2807SJeff Garzik 
295e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
296e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
297e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
2981fefb8fdSBen Hutchings 	/* JMicron 362B and 362C have an AHCI function with IDE class code */
2991fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
3001fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
301c6fd2807SJeff Garzik 
302c6fd2807SJeff Garzik 	/* ATI */
303c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
304e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
305e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
306e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
307e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
308e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
309e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
310c6fd2807SJeff Garzik 
311e2dd90b1SShane Huang 	/* AMD */
3125deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
313*fafe5c3dSShane Huang 	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
314e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
315e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
316e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
317e2dd90b1SShane Huang 
318c6fd2807SJeff Garzik 	/* VIA */
31954bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
320bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
321c6fd2807SJeff Garzik 
322c6fd2807SJeff Garzik 	/* NVIDIA */
323e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
324e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
325e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
326e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
327e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
328e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
329e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
330e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
331441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
332441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
333441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
334441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
335441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
336441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
337441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
338441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
339441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
340441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
341441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
342441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
343441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
344441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
345441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
346441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
347441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
348441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
349441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
350441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
351441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
352441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
353441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
354441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
355441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
356441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
357441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
358441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
359441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
360441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
361441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
362441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
363441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
364441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
365441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
366441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
367441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
368441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
369441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
370441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
371441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
372441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
373441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
374441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
375441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
376441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
377441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
378441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
379441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
380441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
381441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
382441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
383441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
384441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
385441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
386441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
387441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
388441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
389441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
390441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
391441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
392441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
393441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
394441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
395441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
396441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
397441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
398441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
399441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
400441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
401441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
402441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
403441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
404441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
405441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
406441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
407c6fd2807SJeff Garzik 
408c6fd2807SJeff Garzik 	/* SiS */
40920e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
41020e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
41120e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
412c6fd2807SJeff Garzik 
413318893e1SAlessandro Rubini 	/* ST Microelectronics */
414318893e1SAlessandro Rubini 	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */
415318893e1SAlessandro Rubini 
416cd70c266SJeff Garzik 	/* Marvell */
417cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
418c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
41969fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
42010aca06cSAnssi Hannula 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
42110aca06cSAnssi Hannula 	  .class_mask = 0xffffff,
4225f173107STejun Heo 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
42369fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
424467b41c6SPer Jessen 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
42569fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
426642d8925SMatt Johnson 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
42769fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
42817c60c6bSAlan Cox 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */
42969fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
43050be5e36STejun Heo 	  .driver_data = board_ahci_yes_fbs },
431cd70c266SJeff Garzik 
432c77a036bSMark Nelson 	/* Promise */
433c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
434c77a036bSMark Nelson 
435c9703765SKeng-Yu Lin 	/* Asmedia */
4367b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },	/* ASM1060 */
4377b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },	/* ASM1060 */
4387b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */
4397b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */
440c9703765SKeng-Yu Lin 
4417f9c9f8eSHugh Daschbach 	/* Enmotus */
4427f9c9f8eSHugh Daschbach 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
4437f9c9f8eSHugh Daschbach 
444415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
445415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
446c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
447415ae2b5SJeff Garzik 
448c6fd2807SJeff Garzik 	{ }	/* terminate list */
449c6fd2807SJeff Garzik };
450c6fd2807SJeff Garzik 
451c6fd2807SJeff Garzik 
452c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
453c6fd2807SJeff Garzik 	.name			= DRV_NAME,
454c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
455c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
45624dc5f33STejun Heo 	.remove			= ata_pci_remove_one,
457438ac6d5STejun Heo #ifdef CONFIG_PM
458c6fd2807SJeff Garzik 	.suspend		= ahci_pci_device_suspend,
459c6fd2807SJeff Garzik 	.resume			= ahci_pci_device_resume,
460438ac6d5STejun Heo #endif
461c6fd2807SJeff Garzik };
462c6fd2807SJeff Garzik 
4635b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
4645b66c829SAlan Cox static int marvell_enable;
4655b66c829SAlan Cox #else
4665b66c829SAlan Cox static int marvell_enable = 1;
4675b66c829SAlan Cox #endif
4685b66c829SAlan Cox module_param(marvell_enable, int, 0644);
4695b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
4705b66c829SAlan Cox 
4715b66c829SAlan Cox 
472394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
473394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
474394d6e53SAnton Vorontsov {
475394d6e53SAnton Vorontsov 	unsigned int force_port_map = 0;
476394d6e53SAnton Vorontsov 	unsigned int mask_port_map = 0;
477394d6e53SAnton Vorontsov 
478394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
479394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
480394d6e53SAnton Vorontsov 		force_port_map = 1;
481394d6e53SAnton Vorontsov 	}
482394d6e53SAnton Vorontsov 
483394d6e53SAnton Vorontsov 	/*
484394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
485394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
486394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
487394d6e53SAnton Vorontsov 	 */
488394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
489394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
490394d6e53SAnton Vorontsov 			mask_port_map = 0x3;
491394d6e53SAnton Vorontsov 		else
492394d6e53SAnton Vorontsov 			mask_port_map = 0xf;
493394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
494394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
495394d6e53SAnton Vorontsov 	}
496394d6e53SAnton Vorontsov 
4971d513358SAnton Vorontsov 	ahci_save_initial_config(&pdev->dev, hpriv, force_port_map,
4981d513358SAnton Vorontsov 				 mask_port_map);
499394d6e53SAnton Vorontsov }
500394d6e53SAnton Vorontsov 
5013303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host)
5023303040dSAnton Vorontsov {
5033303040dSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
5043303040dSAnton Vorontsov 
5053303040dSAnton Vorontsov 	ahci_reset_controller(host);
5063303040dSAnton Vorontsov 
507c6fd2807SJeff Garzik 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
5083303040dSAnton Vorontsov 		struct ahci_host_priv *hpriv = host->private_data;
509c6fd2807SJeff Garzik 		u16 tmp16;
510c6fd2807SJeff Garzik 
511c6fd2807SJeff Garzik 		/* configure PCS */
512c6fd2807SJeff Garzik 		pci_read_config_word(pdev, 0x92, &tmp16);
51349f29090STejun Heo 		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
51449f29090STejun Heo 			tmp16 |= hpriv->port_map;
515c6fd2807SJeff Garzik 			pci_write_config_word(pdev, 0x92, tmp16);
516c6fd2807SJeff Garzik 		}
51749f29090STejun Heo 	}
518c6fd2807SJeff Garzik 
519c6fd2807SJeff Garzik 	return 0;
520c6fd2807SJeff Garzik }
521c6fd2807SJeff Garzik 
522781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
523781d6550SAnton Vorontsov {
524781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
525781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
526781d6550SAnton Vorontsov 	void __iomem *port_mmio;
527781d6550SAnton Vorontsov 	u32 tmp;
528c40e7cb8SJose Alberto Reguero 	int mv;
5292bcd866bSJeff Garzik 
530417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
531c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
532c40e7cb8SJose Alberto Reguero 			mv = 2;
533c40e7cb8SJose Alberto Reguero 		else
534c40e7cb8SJose Alberto Reguero 			mv = 4;
535c40e7cb8SJose Alberto Reguero 		port_mmio = __ahci_port_base(host, mv);
536cd70c266SJeff Garzik 
537cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
538cd70c266SJeff Garzik 
539cd70c266SJeff Garzik 		/* clear port IRQ */
540cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
541cd70c266SJeff Garzik 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
542cd70c266SJeff Garzik 		if (tmp)
543cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
544cd70c266SJeff Garzik 	}
545cd70c266SJeff Garzik 
546781d6550SAnton Vorontsov 	ahci_init_controller(host);
547c6fd2807SJeff Garzik }
548c6fd2807SJeff Garzik 
549cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
550d4b2bab4STejun Heo 				 unsigned long deadline)
551ad616ffbSTejun Heo {
552cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
5539dadd45bSTejun Heo 	bool online;
554ad616ffbSTejun Heo 	int rc;
555ad616ffbSTejun Heo 
556ad616ffbSTejun Heo 	DPRINTK("ENTER\n");
557ad616ffbSTejun Heo 
5584447d351STejun Heo 	ahci_stop_engine(ap);
559ad616ffbSTejun Heo 
560cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
5619dadd45bSTejun Heo 				 deadline, &online, NULL);
562ad616ffbSTejun Heo 
5634447d351STejun Heo 	ahci_start_engine(ap);
564ad616ffbSTejun Heo 
565ad616ffbSTejun Heo 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
566ad616ffbSTejun Heo 
567ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
568ad616ffbSTejun Heo 	 * request follow-up softreset.
569ad616ffbSTejun Heo 	 */
5709dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
571ad616ffbSTejun Heo }
572ad616ffbSTejun Heo 
573edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
574edc93052STejun Heo 				unsigned long deadline)
575edc93052STejun Heo {
576edc93052STejun Heo 	struct ata_port *ap = link->ap;
577edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
578edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
579edc93052STejun Heo 	struct ata_taskfile tf;
5809dadd45bSTejun Heo 	bool online;
581edc93052STejun Heo 	int rc;
582edc93052STejun Heo 
583edc93052STejun Heo 	ahci_stop_engine(ap);
584edc93052STejun Heo 
585edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
586edc93052STejun Heo 	ata_tf_init(link->device, &tf);
587edc93052STejun Heo 	tf.command = 0x80;
588edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
589edc93052STejun Heo 
590edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
5919dadd45bSTejun Heo 				 deadline, &online, NULL);
592edc93052STejun Heo 
593edc93052STejun Heo 	ahci_start_engine(ap);
594edc93052STejun Heo 
595edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
596edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
597edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
598edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
599edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
600edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
601edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
602edc93052STejun Heo 	 *
603edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
604edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
605edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
606edc93052STejun Heo 	 * suffice while making probing snappish enough.
607edc93052STejun Heo 	 */
6089dadd45bSTejun Heo 	if (online) {
6099dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
6109dadd45bSTejun Heo 					  ahci_check_ready);
611edc93052STejun Heo 		if (rc)
61278d5ae39SShane Huang 			ahci_kick_engine(ap);
6139dadd45bSTejun Heo 	}
6149dadd45bSTejun Heo 	return rc;
615edc93052STejun Heo }
616edc93052STejun Heo 
617438ac6d5STejun Heo #ifdef CONFIG_PM
618c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
619c6fd2807SJeff Garzik {
620cca3974eSJeff Garzik 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
6219b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
622d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
623c6fd2807SJeff Garzik 	u32 ctl;
624c6fd2807SJeff Garzik 
6259b10ae86STejun Heo 	if (mesg.event & PM_EVENT_SUSPEND &&
6269b10ae86STejun Heo 	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
627a44fec1fSJoe Perches 		dev_err(&pdev->dev,
6289b10ae86STejun Heo 			"BIOS update required for suspend/resume\n");
6299b10ae86STejun Heo 		return -EIO;
6309b10ae86STejun Heo 	}
6319b10ae86STejun Heo 
6323a2d5b70SRafael J. Wysocki 	if (mesg.event & PM_EVENT_SLEEP) {
633c6fd2807SJeff Garzik 		/* AHCI spec rev1.1 section 8.3.3:
634c6fd2807SJeff Garzik 		 * Software must disable interrupts prior to requesting a
635c6fd2807SJeff Garzik 		 * transition of the HBA to D3 state.
636c6fd2807SJeff Garzik 		 */
637c6fd2807SJeff Garzik 		ctl = readl(mmio + HOST_CTL);
638c6fd2807SJeff Garzik 		ctl &= ~HOST_IRQ_EN;
639c6fd2807SJeff Garzik 		writel(ctl, mmio + HOST_CTL);
640c6fd2807SJeff Garzik 		readl(mmio + HOST_CTL); /* flush */
641c6fd2807SJeff Garzik 	}
642c6fd2807SJeff Garzik 
643c6fd2807SJeff Garzik 	return ata_pci_device_suspend(pdev, mesg);
644c6fd2807SJeff Garzik }
645c6fd2807SJeff Garzik 
646c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev)
647c6fd2807SJeff Garzik {
648cca3974eSJeff Garzik 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
649c6fd2807SJeff Garzik 	int rc;
650c6fd2807SJeff Garzik 
651553c4aa6STejun Heo 	rc = ata_pci_device_do_resume(pdev);
652553c4aa6STejun Heo 	if (rc)
653553c4aa6STejun Heo 		return rc;
654c6fd2807SJeff Garzik 
655c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
6563303040dSAnton Vorontsov 		rc = ahci_pci_reset_controller(host);
657c6fd2807SJeff Garzik 		if (rc)
658c6fd2807SJeff Garzik 			return rc;
659c6fd2807SJeff Garzik 
660781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
661c6fd2807SJeff Garzik 	}
662c6fd2807SJeff Garzik 
663cca3974eSJeff Garzik 	ata_host_resume(host);
664c6fd2807SJeff Garzik 
665c6fd2807SJeff Garzik 	return 0;
666c6fd2807SJeff Garzik }
667438ac6d5STejun Heo #endif
668c6fd2807SJeff Garzik 
6694447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
670c6fd2807SJeff Garzik {
671c6fd2807SJeff Garzik 	int rc;
672c6fd2807SJeff Garzik 
673318893e1SAlessandro Rubini 	/*
674318893e1SAlessandro Rubini 	 * If the device fixup already set the dma_mask to some non-standard
675318893e1SAlessandro Rubini 	 * value, don't extend it here. This happens on STA2X11, for example.
676318893e1SAlessandro Rubini 	 */
677318893e1SAlessandro Rubini 	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
678318893e1SAlessandro Rubini 		return 0;
679318893e1SAlessandro Rubini 
680c6fd2807SJeff Garzik 	if (using_dac &&
6816a35528aSYang Hongyang 	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
6826a35528aSYang Hongyang 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
683c6fd2807SJeff Garzik 		if (rc) {
684284901a9SYang Hongyang 			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
685c6fd2807SJeff Garzik 			if (rc) {
686a44fec1fSJoe Perches 				dev_err(&pdev->dev,
687c6fd2807SJeff Garzik 					"64-bit DMA enable failed\n");
688c6fd2807SJeff Garzik 				return rc;
689c6fd2807SJeff Garzik 			}
690c6fd2807SJeff Garzik 		}
691c6fd2807SJeff Garzik 	} else {
692284901a9SYang Hongyang 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
693c6fd2807SJeff Garzik 		if (rc) {
694a44fec1fSJoe Perches 			dev_err(&pdev->dev, "32-bit DMA enable failed\n");
695c6fd2807SJeff Garzik 			return rc;
696c6fd2807SJeff Garzik 		}
697284901a9SYang Hongyang 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
698c6fd2807SJeff Garzik 		if (rc) {
699a44fec1fSJoe Perches 			dev_err(&pdev->dev,
700c6fd2807SJeff Garzik 				"32-bit consistent DMA enable failed\n");
701c6fd2807SJeff Garzik 			return rc;
702c6fd2807SJeff Garzik 		}
703c6fd2807SJeff Garzik 	}
704c6fd2807SJeff Garzik 	return 0;
705c6fd2807SJeff Garzik }
706c6fd2807SJeff Garzik 
707439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
708439fcaecSAnton Vorontsov {
709439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
710439fcaecSAnton Vorontsov 	u16 cc;
711439fcaecSAnton Vorontsov 	const char *scc_s;
712439fcaecSAnton Vorontsov 
713439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
714439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
715439fcaecSAnton Vorontsov 		scc_s = "IDE";
716439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
717439fcaecSAnton Vorontsov 		scc_s = "SATA";
718439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
719439fcaecSAnton Vorontsov 		scc_s = "RAID";
720439fcaecSAnton Vorontsov 	else
721439fcaecSAnton Vorontsov 		scc_s = "unknown";
722439fcaecSAnton Vorontsov 
723439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
724439fcaecSAnton Vorontsov }
725439fcaecSAnton Vorontsov 
726edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
727edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
728edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
729edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
730edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
731edc93052STejun Heo  * other configuration).
732edc93052STejun Heo  *
733edc93052STejun Heo  * When there's no device attached to the first downstream port of the
734edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
735edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
736edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
737edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
738edc93052STejun Heo  *
739edc93052STejun Heo  * The following function works around the problem by always using
740edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
741edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
742edc93052STejun Heo  * assumed without follow-up softreset.
743edc93052STejun Heo  */
744edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
745edc93052STejun Heo {
746edc93052STejun Heo 	static struct dmi_system_id sysids[] = {
747edc93052STejun Heo 		{
748edc93052STejun Heo 			.ident = "P5W DH Deluxe",
749edc93052STejun Heo 			.matches = {
750edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
751edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
752edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
753edc93052STejun Heo 			},
754edc93052STejun Heo 		},
755edc93052STejun Heo 		{ }
756edc93052STejun Heo 	};
757edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
758edc93052STejun Heo 
759edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
760edc93052STejun Heo 	    dmi_check_system(sysids)) {
761edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
762edc93052STejun Heo 
763a44fec1fSJoe Perches 		dev_info(&pdev->dev,
764a44fec1fSJoe Perches 			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
765edc93052STejun Heo 
766edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
767edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
768edc93052STejun Heo 	}
769edc93052STejun Heo }
770edc93052STejun Heo 
7712fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
7722fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
77358a09b38SShane Huang {
77458a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
77503d783bfSTejun Heo 		/*
77603d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
77703d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
7782fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
7792fcad9d2STejun Heo 		 *
78003d783bfSTejun Heo 		 * Please read bko#9412 for more info.
78103d783bfSTejun Heo 		 */
78258a09b38SShane Huang 		{
78358a09b38SShane Huang 			.ident = "ASUS M2A-VM",
78458a09b38SShane Huang 			.matches = {
78558a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
78658a09b38SShane Huang 					  "ASUSTeK Computer INC."),
78758a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
78858a09b38SShane Huang 			},
78903d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
79058a09b38SShane Huang 		},
791e65cc194SMark Nelson 		/*
792e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
793e65cc194SMark Nelson 		 * support 64bit DMA.
794e65cc194SMark Nelson 		 *
795e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
796e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
797e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
798e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
799e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
800e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
801e65cc194SMark Nelson 		 *
802e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
803e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
804e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
805e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
806e65cc194SMark Nelson 		 */
807e65cc194SMark Nelson 		{
808e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
809e65cc194SMark Nelson 			.matches = {
810e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
811e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
812e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
813e65cc194SMark Nelson 			},
814e65cc194SMark Nelson 		},
8153c4aa91fSMark Nelson 		/*
816ff0173c1SMark Nelson 		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support
817ff0173c1SMark Nelson 		 * 64bit DMA.
818ff0173c1SMark Nelson 		 *
819ff0173c1SMark Nelson 		 * This board also had the typo mentioned above in the
820ff0173c1SMark Nelson 		 * Manufacturer DMI field (fixed in BIOS version 1.5), so
821ff0173c1SMark Nelson 		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again.
822ff0173c1SMark Nelson 		 */
823ff0173c1SMark Nelson 		{
824ff0173c1SMark Nelson 			.ident = "MSI K9AGM2",
825ff0173c1SMark Nelson 			.matches = {
826ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
827ff0173c1SMark Nelson 					  "MICRO-STAR INTER"),
828ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"),
829ff0173c1SMark Nelson 			},
830ff0173c1SMark Nelson 		},
831ff0173c1SMark Nelson 		/*
8323c4aa91fSMark Nelson 		 * All BIOS versions for the Asus M3A support 64bit DMA.
8333c4aa91fSMark Nelson 		 * (all release versions from 0301 to 1206 were tested)
8343c4aa91fSMark Nelson 		 */
8353c4aa91fSMark Nelson 		{
8363c4aa91fSMark Nelson 			.ident = "ASUS M3A",
8373c4aa91fSMark Nelson 			.matches = {
8383c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
8393c4aa91fSMark Nelson 					  "ASUSTeK Computer INC."),
8403c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
8413c4aa91fSMark Nelson 			},
8423c4aa91fSMark Nelson 		},
84358a09b38SShane Huang 		{ }
84458a09b38SShane Huang 	};
84503d783bfSTejun Heo 	const struct dmi_system_id *match;
8462fcad9d2STejun Heo 	int year, month, date;
8472fcad9d2STejun Heo 	char buf[9];
84858a09b38SShane Huang 
84903d783bfSTejun Heo 	match = dmi_first_match(sysids);
85058a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
85103d783bfSTejun Heo 	    !match)
85258a09b38SShane Huang 		return false;
85358a09b38SShane Huang 
854e65cc194SMark Nelson 	if (!match->driver_data)
855e65cc194SMark Nelson 		goto enable_64bit;
856e65cc194SMark Nelson 
85703d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
85803d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
85903d783bfSTejun Heo 
860e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
861e65cc194SMark Nelson 		goto enable_64bit;
862e65cc194SMark Nelson 	else {
863a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
864a44fec1fSJoe Perches 			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
865a44fec1fSJoe Perches 			 match->ident);
8662fcad9d2STejun Heo 		return false;
8672fcad9d2STejun Heo 	}
868e65cc194SMark Nelson 
869e65cc194SMark Nelson enable_64bit:
870a44fec1fSJoe Perches 	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
871e65cc194SMark Nelson 	return true;
87258a09b38SShane Huang }
87358a09b38SShane Huang 
8741fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
8751fd68434SRafael J. Wysocki {
8761fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
8771fd68434SRafael J. Wysocki 		{
8781fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
8791fd68434SRafael J. Wysocki 			.matches = {
8801fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
8811fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
8821fd68434SRafael J. Wysocki 			},
8831fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
8841fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
8851fd68434SRafael J. Wysocki 		},
886d2f9c061SMaciej Rutecki 		{
887d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
888d2f9c061SMaciej Rutecki 			.matches = {
889d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
890d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
891d2f9c061SMaciej Rutecki 			},
892d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
893d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
894d2f9c061SMaciej Rutecki 		},
8951fd68434SRafael J. Wysocki 
8961fd68434SRafael J. Wysocki 		{ }	/* terminate list */
8971fd68434SRafael J. Wysocki 	};
8981fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
8991fd68434SRafael J. Wysocki 
9001fd68434SRafael J. Wysocki 	if (dmi) {
9011fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
9021fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
9031fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
9041fd68434SRafael J. Wysocki 	}
9051fd68434SRafael J. Wysocki 
9061fd68434SRafael J. Wysocki 	return false;
9071fd68434SRafael J. Wysocki }
9081fd68434SRafael J. Wysocki 
9099b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
9109b10ae86STejun Heo {
9119b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
9129b10ae86STejun Heo 		/*
9139b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
9149b10ae86STejun Heo 		 * to the harddisk doesn't become online after
9159b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
9169deb3431STejun Heo 		 *
9179deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
9189deb3431STejun Heo 		 *
9199deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
9209deb3431STejun Heo 		 * apparently recycling both product and version
9219deb3431STejun Heo 		 * strings.
9229deb3431STejun Heo 		 *
9239deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
9249b10ae86STejun Heo 		 */
9259b10ae86STejun Heo 		{
9269b10ae86STejun Heo 			.ident = "dv4",
9279b10ae86STejun Heo 			.matches = {
9289b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
9299b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
9309b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
9319b10ae86STejun Heo 			},
9329deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
9339b10ae86STejun Heo 		},
9349b10ae86STejun Heo 		{
9359b10ae86STejun Heo 			.ident = "dv5",
9369b10ae86STejun Heo 			.matches = {
9379b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
9389b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
9399b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
9409b10ae86STejun Heo 			},
9419deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
9429b10ae86STejun Heo 		},
9439b10ae86STejun Heo 		{
9449b10ae86STejun Heo 			.ident = "dv6",
9459b10ae86STejun Heo 			.matches = {
9469b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
9479b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
9489b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
9499b10ae86STejun Heo 			},
9509deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
9519b10ae86STejun Heo 		},
9529b10ae86STejun Heo 		{
9539b10ae86STejun Heo 			.ident = "HDX18",
9549b10ae86STejun Heo 			.matches = {
9559b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
9569b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
9579b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
9589b10ae86STejun Heo 			},
9599deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
9609b10ae86STejun Heo 		},
961cedc9bf9STejun Heo 		/*
962cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
963cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
96425985edcSLucas De Marchi 		 * work.  Between, there are V1.06, V2.06 and V3.03
965cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
966cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
9679deb3431STejun Heo 		 *
9689deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
969cedc9bf9STejun Heo 		 */
970cedc9bf9STejun Heo 		{
971cedc9bf9STejun Heo 			.ident = "G725",
972cedc9bf9STejun Heo 			.matches = {
973cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
974cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
975cedc9bf9STejun Heo 			},
9769deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
977cedc9bf9STejun Heo 		},
9789b10ae86STejun Heo 		{ }	/* terminate list */
9799b10ae86STejun Heo 	};
9809b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
9819deb3431STejun Heo 	int year, month, date;
9829deb3431STejun Heo 	char buf[9];
9839b10ae86STejun Heo 
9849b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
9859b10ae86STejun Heo 		return false;
9869b10ae86STejun Heo 
9879deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
9889deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
9899b10ae86STejun Heo 
9909deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
9919b10ae86STejun Heo }
9929b10ae86STejun Heo 
9935594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
9945594639aSTejun Heo {
9955594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
9965594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
9975594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
9985594639aSTejun Heo 		/*
9995594639aSTejun Heo 		 * There are several gigabyte boards which use
10005594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
10015594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
10025594639aSTejun Heo 		 * online but fail to answer properly to SRST or
10035594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
10045594639aSTejun Heo 		 * causing libata to retry quite a few times leading
10055594639aSTejun Heo 		 * to excessive detection delay.
10065594639aSTejun Heo 		 *
10075594639aSTejun Heo 		 * As these firmwares respond to the second reset try
10085594639aSTejun Heo 		 * with invalid device signature, considering unknown
10095594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
10105594639aSTejun Heo 		 */
10115594639aSTejun Heo 		{
10125594639aSTejun Heo 			.ident = "EP45-DQ6",
10135594639aSTejun Heo 			.matches = {
10145594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
10155594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
10165594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
10175594639aSTejun Heo 			},
10185594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
10195594639aSTejun Heo 		},
10205594639aSTejun Heo 		{
10215594639aSTejun Heo 			.ident = "EP45-DS5",
10225594639aSTejun Heo 			.matches = {
10235594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
10245594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
10255594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
10265594639aSTejun Heo 			},
10275594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
10285594639aSTejun Heo 		},
10295594639aSTejun Heo 		{ }	/* terminate list */
10305594639aSTejun Heo 	};
10315594639aSTejun Heo #undef ENCODE_BUSDEVFN
10325594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
10335594639aSTejun Heo 	unsigned int val;
10345594639aSTejun Heo 
10355594639aSTejun Heo 	if (!dmi)
10365594639aSTejun Heo 		return false;
10375594639aSTejun Heo 
10385594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
10395594639aSTejun Heo 
10405594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
10415594639aSTejun Heo }
10425594639aSTejun Heo 
10438e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
1044f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
1045f80ae7e4STejun Heo {
1046f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
1047f80ae7e4STejun Heo 		/*
1048f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
1049f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
1050f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
1051f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
1052f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
1053f80ae7e4STejun Heo 		 * failures.  Filter it out.
1054f80ae7e4STejun Heo 		 */
1055f80ae7e4STejun Heo 		{
1056f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
1057f80ae7e4STejun Heo 			.matches = {
1058f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1059f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1060f80ae7e4STejun Heo 			},
1061f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1062f80ae7e4STejun Heo 		},
1063f80ae7e4STejun Heo 		{ }
1064f80ae7e4STejun Heo 	};
1065f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1066f80ae7e4STejun Heo 	unsigned int filter;
1067f80ae7e4STejun Heo 	int i;
1068f80ae7e4STejun Heo 
1069f80ae7e4STejun Heo 	if (!dmi)
1070f80ae7e4STejun Heo 		return;
1071f80ae7e4STejun Heo 
1072f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1073a44fec1fSJoe Perches 	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
1074f80ae7e4STejun Heo 		 filter, dmi->ident);
1075f80ae7e4STejun Heo 
1076f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1077f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1078f80ae7e4STejun Heo 		struct ata_link *link;
1079f80ae7e4STejun Heo 		struct ata_device *dev;
1080f80ae7e4STejun Heo 
1081f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1082f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1083f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1084f80ae7e4STejun Heo 	}
1085f80ae7e4STejun Heo }
10868e513217SMarkus Trippelsdorf #else
10878e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
10888e513217SMarkus Trippelsdorf {}
10898e513217SMarkus Trippelsdorf #endif
1090f80ae7e4STejun Heo 
10915ca72c4fSAlexander Gordeev int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
10925ca72c4fSAlexander Gordeev {
10935ca72c4fSAlexander Gordeev 	int rc;
10945ca72c4fSAlexander Gordeev 	unsigned int maxvec;
10955ca72c4fSAlexander Gordeev 
10965ca72c4fSAlexander Gordeev 	if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) {
10975ca72c4fSAlexander Gordeev 		rc = pci_enable_msi_block_auto(pdev, &maxvec);
10985ca72c4fSAlexander Gordeev 		if (rc > 0) {
10995ca72c4fSAlexander Gordeev 			if ((rc == maxvec) || (rc == 1))
11005ca72c4fSAlexander Gordeev 				return rc;
11015ca72c4fSAlexander Gordeev 			/*
11025ca72c4fSAlexander Gordeev 			 * Assume that advantage of multipe MSIs is negated,
11035ca72c4fSAlexander Gordeev 			 * so fallback to single MSI mode to save resources
11045ca72c4fSAlexander Gordeev 			 */
11055ca72c4fSAlexander Gordeev 			pci_disable_msi(pdev);
11065ca72c4fSAlexander Gordeev 			if (!pci_enable_msi(pdev))
11075ca72c4fSAlexander Gordeev 				return 1;
11085ca72c4fSAlexander Gordeev 		}
11095ca72c4fSAlexander Gordeev 	}
11105ca72c4fSAlexander Gordeev 
11115ca72c4fSAlexander Gordeev 	pci_intx(pdev, 1);
11125ca72c4fSAlexander Gordeev 	return 0;
11135ca72c4fSAlexander Gordeev }
11145ca72c4fSAlexander Gordeev 
11155ca72c4fSAlexander Gordeev /**
11165ca72c4fSAlexander Gordeev  *	ahci_host_activate - start AHCI host, request IRQs and register it
11175ca72c4fSAlexander Gordeev  *	@host: target ATA host
11185ca72c4fSAlexander Gordeev  *	@irq: base IRQ number to request
11195ca72c4fSAlexander Gordeev  *	@n_msis: number of MSIs allocated for this host
11205ca72c4fSAlexander Gordeev  *	@irq_handler: irq_handler used when requesting IRQs
11215ca72c4fSAlexander Gordeev  *	@irq_flags: irq_flags used when requesting IRQs
11225ca72c4fSAlexander Gordeev  *
11235ca72c4fSAlexander Gordeev  *	Similar to ata_host_activate, but requests IRQs according to AHCI-1.1
11245ca72c4fSAlexander Gordeev  *	when multiple MSIs were allocated. That is one MSI per port, starting
11255ca72c4fSAlexander Gordeev  *	from @irq.
11265ca72c4fSAlexander Gordeev  *
11275ca72c4fSAlexander Gordeev  *	LOCKING:
11285ca72c4fSAlexander Gordeev  *	Inherited from calling layer (may sleep).
11295ca72c4fSAlexander Gordeev  *
11305ca72c4fSAlexander Gordeev  *	RETURNS:
11315ca72c4fSAlexander Gordeev  *	0 on success, -errno otherwise.
11325ca72c4fSAlexander Gordeev  */
11335ca72c4fSAlexander Gordeev int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis)
11345ca72c4fSAlexander Gordeev {
11355ca72c4fSAlexander Gordeev 	int i, rc;
11365ca72c4fSAlexander Gordeev 
11375ca72c4fSAlexander Gordeev 	/* Sharing Last Message among several ports is not supported */
11385ca72c4fSAlexander Gordeev 	if (n_msis < host->n_ports)
11395ca72c4fSAlexander Gordeev 		return -EINVAL;
11405ca72c4fSAlexander Gordeev 
11415ca72c4fSAlexander Gordeev 	rc = ata_host_start(host);
11425ca72c4fSAlexander Gordeev 	if (rc)
11435ca72c4fSAlexander Gordeev 		return rc;
11445ca72c4fSAlexander Gordeev 
11455ca72c4fSAlexander Gordeev 	for (i = 0; i < host->n_ports; i++) {
11465ca72c4fSAlexander Gordeev 		rc = devm_request_threaded_irq(host->dev,
11475ca72c4fSAlexander Gordeev 			irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED,
11485ca72c4fSAlexander Gordeev 			dev_driver_string(host->dev), host->ports[i]);
11495ca72c4fSAlexander Gordeev 		if (rc)
11505ca72c4fSAlexander Gordeev 			goto out_free_irqs;
11515ca72c4fSAlexander Gordeev 	}
11525ca72c4fSAlexander Gordeev 
11535ca72c4fSAlexander Gordeev 	for (i = 0; i < host->n_ports; i++)
11545ca72c4fSAlexander Gordeev 		ata_port_desc(host->ports[i], "irq %d", irq + i);
11555ca72c4fSAlexander Gordeev 
11565ca72c4fSAlexander Gordeev 	rc = ata_host_register(host, &ahci_sht);
11575ca72c4fSAlexander Gordeev 	if (rc)
11585ca72c4fSAlexander Gordeev 		goto out_free_all_irqs;
11595ca72c4fSAlexander Gordeev 
11605ca72c4fSAlexander Gordeev 	return 0;
11615ca72c4fSAlexander Gordeev 
11625ca72c4fSAlexander Gordeev out_free_all_irqs:
11635ca72c4fSAlexander Gordeev 	i = host->n_ports;
11645ca72c4fSAlexander Gordeev out_free_irqs:
11655ca72c4fSAlexander Gordeev 	for (i--; i >= 0; i--)
11665ca72c4fSAlexander Gordeev 		devm_free_irq(host->dev, irq + i, host->ports[i]);
11675ca72c4fSAlexander Gordeev 
11685ca72c4fSAlexander Gordeev 	return rc;
11695ca72c4fSAlexander Gordeev }
11705ca72c4fSAlexander Gordeev 
1171c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1172c6fd2807SJeff Garzik {
1173e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1174e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
11754447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
117624dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1177c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
11784447d351STejun Heo 	struct ata_host *host;
11795ca72c4fSAlexander Gordeev 	int n_ports, n_msis, i, rc;
1180318893e1SAlessandro Rubini 	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
1181c6fd2807SJeff Garzik 
1182c6fd2807SJeff Garzik 	VPRINTK("ENTER\n");
1183c6fd2807SJeff Garzik 
1184b429dd59SJustin P. Mattock 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1185c6fd2807SJeff Garzik 
118606296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1187c6fd2807SJeff Garzik 
11885b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
11895b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
11905b66c829SAlan Cox 	   AHCI stays out of the way */
11915b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
11925b66c829SAlan Cox 		return -ENODEV;
11935b66c829SAlan Cox 
1194c6353b45STejun Heo 	/*
1195c6353b45STejun Heo 	 * For some reason, MCP89 on MacBook 7,1 doesn't work with
1196c6353b45STejun Heo 	 * ahci, use ata_generic instead.
1197c6353b45STejun Heo 	 */
1198c6353b45STejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
1199c6353b45STejun Heo 	    pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
1200c6353b45STejun Heo 	    pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
1201c6353b45STejun Heo 	    pdev->subsystem_device == 0xcb89)
1202c6353b45STejun Heo 		return -ENODEV;
1203c6353b45STejun Heo 
12047a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
12057a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
12067a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
12077a02267eSMark Nelson 	 */
12087a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
1209a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1210a44fec1fSJoe Perches 			 "PDC42819 can only drive SATA devices with this driver\n");
12117a02267eSMark Nelson 
12127f9c9f8eSHugh Daschbach 	/* Both Connext and Enmotus devices use non-standard BARs */
1213318893e1SAlessandro Rubini 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
1214318893e1SAlessandro Rubini 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
12157f9c9f8eSHugh Daschbach 	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
12167f9c9f8eSHugh Daschbach 		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
1217318893e1SAlessandro Rubini 
12184447d351STejun Heo 	/* acquire resources */
121924dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1220c6fd2807SJeff Garzik 	if (rc)
1221c6fd2807SJeff Garzik 		return rc;
1222c6fd2807SJeff Garzik 
1223dea55137STejun Heo 	/* AHCI controllers often implement SFF compatible interface.
1224dea55137STejun Heo 	 * Grab all PCI BARs just in case.
1225dea55137STejun Heo 	 */
1226318893e1SAlessandro Rubini 	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
12270d5ff566STejun Heo 	if (rc == -EBUSY)
122824dc5f33STejun Heo 		pcim_pin_device(pdev);
12290d5ff566STejun Heo 	if (rc)
123024dc5f33STejun Heo 		return rc;
1231c6fd2807SJeff Garzik 
1232c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1233c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1234c4f7792cSTejun Heo 		u8 map;
1235c4f7792cSTejun Heo 
1236c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1237c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1238c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1239c4f7792cSTejun Heo 		 */
1240c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1241c4f7792cSTejun Heo 		if (map & 0x3) {
1242a44fec1fSJoe Perches 			dev_info(&pdev->dev,
1243a44fec1fSJoe Perches 				 "controller is in combined mode, can't enable AHCI mode\n");
1244c4f7792cSTejun Heo 			return -ENODEV;
1245c4f7792cSTejun Heo 		}
1246c4f7792cSTejun Heo 	}
1247c4f7792cSTejun Heo 
124824dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
124924dc5f33STejun Heo 	if (!hpriv)
125024dc5f33STejun Heo 		return -ENOMEM;
1251417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1252417a1a6dSTejun Heo 
1253e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1254e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1255e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1256e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1257e297d99eSTejun Heo 
1258e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1259e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1260e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1261e427fe04SShane Huang 
12622fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
12632fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
12642fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
126558a09b38SShane Huang 
1266318893e1SAlessandro Rubini 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
1267d8993349SAnton Vorontsov 
12685ca72c4fSAlexander Gordeev 	n_msis = ahci_init_interrupts(pdev, hpriv);
12695ca72c4fSAlexander Gordeev 	if (n_msis > 1)
12705ca72c4fSAlexander Gordeev 		hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
12715ca72c4fSAlexander Gordeev 
12724447d351STejun Heo 	/* save initial config */
1273394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1274c6fd2807SJeff Garzik 
12754447d351STejun Heo 	/* prepare host */
1276453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1277453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
127883f2b963STejun Heo 		/*
127983f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
128083f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
128183f2b963STejun Heo 		 * capability, but it seems to be broken on some
128283f2b963STejun Heo 		 * chipsets including NVIDIAs.
128383f2b963STejun Heo 		 */
128483f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1285453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
1286453d3131SRobert Hancock 	}
12874447d351STejun Heo 
12887d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
12897d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
12907d50b60bSTejun Heo 
12910cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
129218f7ba4cSKristen Carlson Accardi 
12931fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
12941fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
12951fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
12961fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
12971fd68434SRafael J. Wysocki 	}
12981fd68434SRafael J. Wysocki 
12999b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
13009b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
1301a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
13029b10ae86STejun Heo 			 "BIOS update required for suspend/resume\n");
13039b10ae86STejun Heo 	}
13049b10ae86STejun Heo 
13055594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
13065594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
13075594639aSTejun Heo 		dev_info(&pdev->dev,
13085594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
13095594639aSTejun Heo 	}
13105594639aSTejun Heo 
1311837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1312837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1313837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1314837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1315837f5f8fSTejun Heo 	 */
1316837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1317837f5f8fSTejun Heo 
1318837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
13194447d351STejun Heo 	if (!host)
13204447d351STejun Heo 		return -ENOMEM;
13214447d351STejun Heo 	host->private_data = hpriv;
13224447d351STejun Heo 
1323f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1324886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1325f3d7f23fSArjan van de Ven 	else
1326f3d7f23fSArjan van de Ven 		printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
1327886ad09fSArjan van de Ven 
132818f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
132918f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
133018f7ba4cSKristen Carlson Accardi 
13314447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
13324447d351STejun Heo 		struct ata_port *ap = host->ports[i];
13334447d351STejun Heo 
1334318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
1335318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar,
1336cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
1337cbcdd875STejun Heo 
133818f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
133918f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
1340008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
134118f7ba4cSKristen Carlson Accardi 
134218f7ba4cSKristen Carlson Accardi 
1343dab632e8SJeff Garzik 		/* disabled/not-implemented port */
1344350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
1345dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
13464447d351STejun Heo 	}
1347c6fd2807SJeff Garzik 
1348edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
1349edc93052STejun Heo 	ahci_p5wdh_workaround(host);
1350edc93052STejun Heo 
1351f80ae7e4STejun Heo 	/* apply gtf filter quirk */
1352f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
1353f80ae7e4STejun Heo 
1354c6fd2807SJeff Garzik 	/* initialize adapter */
13554447d351STejun Heo 	rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
1356c6fd2807SJeff Garzik 	if (rc)
135724dc5f33STejun Heo 		return rc;
1358c6fd2807SJeff Garzik 
13593303040dSAnton Vorontsov 	rc = ahci_pci_reset_controller(host);
13604447d351STejun Heo 	if (rc)
13614447d351STejun Heo 		return rc;
1362c6fd2807SJeff Garzik 
1363781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
1364439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
1365c6fd2807SJeff Garzik 
13664447d351STejun Heo 	pci_set_master(pdev);
13675ca72c4fSAlexander Gordeev 
13685ca72c4fSAlexander Gordeev 	if (hpriv->flags & AHCI_HFLAG_MULTI_MSI)
13695ca72c4fSAlexander Gordeev 		return ahci_host_activate(host, pdev->irq, n_msis);
13705ca72c4fSAlexander Gordeev 
13714447d351STejun Heo 	return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
13724447d351STejun Heo 				 &ahci_sht);
1373c6fd2807SJeff Garzik }
1374c6fd2807SJeff Garzik 
13752fc75da0SAxel Lin module_pci_driver(ahci_pci_driver);
1376c6fd2807SJeff Garzik 
1377c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
1378c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
1379c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
1380c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
1381c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
1382