xref: /openbmc/linux/drivers/ata/ahci.c (revision c6353b4520788e34098bbf61c73fb9618ca7fdd6)
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 {
55c6fd2807SJeff Garzik 	AHCI_PCI_BAR		= 5,
56441577efSTejun Heo };
57c6fd2807SJeff Garzik 
58441577efSTejun Heo enum board_ids {
59441577efSTejun Heo 	/* board IDs by feature in alphabetical order */
60441577efSTejun Heo 	board_ahci,
61441577efSTejun Heo 	board_ahci_ign_iferr,
62441577efSTejun Heo 	board_ahci_nosntf,
63441577efSTejun Heo 
64441577efSTejun Heo 	/* board IDs for specific chipsets in alphabetical order */
65441577efSTejun Heo 	board_ahci_mcp65,
6683f2b963STejun Heo 	board_ahci_mcp77,
6783f2b963STejun Heo 	board_ahci_mcp89,
68441577efSTejun Heo 	board_ahci_mv,
69441577efSTejun Heo 	board_ahci_sb600,
70441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
71441577efSTejun Heo 	board_ahci_vt8251,
72441577efSTejun Heo 
73441577efSTejun Heo 	/* aliases */
74441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
75441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
76441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
7783f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
78c6fd2807SJeff Garzik };
79c6fd2807SJeff Garzik 
80c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
81bd17243aSShane Huang static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
82bd17243aSShane Huang 			  unsigned long deadline);
83a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
84a1efdabaSTejun Heo 				 unsigned long deadline);
85a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
86a1efdabaSTejun Heo 				unsigned long deadline);
87438ac6d5STejun Heo #ifdef CONFIG_PM
88c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
89c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev);
90438ac6d5STejun Heo #endif
91c6fd2807SJeff Garzik 
92029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
93029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
94a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
95ad616ffbSTejun Heo };
96ad616ffbSTejun Heo 
97029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
98029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
99a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
100edc93052STejun Heo };
101edc93052STejun Heo 
102bd17243aSShane Huang static struct ata_port_operations ahci_sb600_ops = {
103bd17243aSShane Huang 	.inherits		= &ahci_ops,
104bd17243aSShane Huang 	.softreset		= ahci_sb600_softreset,
105bd17243aSShane Huang 	.pmp_softreset		= ahci_sb600_softreset,
106bd17243aSShane Huang };
107bd17243aSShane Huang 
108417a1a6dSTejun Heo #define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags)
109417a1a6dSTejun Heo 
110c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
111441577efSTejun Heo 	/* by features */
1124da646b7SJeff Garzik 	[board_ahci] =
113c6fd2807SJeff Garzik 	{
1141188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
11514bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
116469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
117c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
118c6fd2807SJeff Garzik 	},
1194da646b7SJeff Garzik 	[board_ahci_ign_iferr] =
12041669553STejun Heo 	{
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 	},
127441577efSTejun Heo 	[board_ahci_nosntf] =
128441577efSTejun Heo 	{
129441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
130441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
131441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
132441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
133441577efSTejun Heo 		.port_ops	= &ahci_ops,
134441577efSTejun Heo 	},
135441577efSTejun Heo 	/* by chipsets */
136441577efSTejun Heo 	[board_ahci_mcp65] =
137441577efSTejun Heo 	{
13883f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
13983f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
14083f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
14183f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
14283f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
14383f2b963STejun Heo 		.port_ops	= &ahci_ops,
14483f2b963STejun Heo 	},
14583f2b963STejun Heo 	[board_ahci_mcp77] =
14683f2b963STejun Heo 	{
14783f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
14883f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
14983f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
15083f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
15183f2b963STejun Heo 		.port_ops	= &ahci_ops,
15283f2b963STejun Heo 	},
15383f2b963STejun Heo 	[board_ahci_mcp89] =
15483f2b963STejun Heo 	{
15583f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
156441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
157441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
158441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
159441577efSTejun Heo 		.port_ops	= &ahci_ops,
160441577efSTejun Heo 	},
161441577efSTejun Heo 	[board_ahci_mv] =
162441577efSTejun Heo 	{
163441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
164441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
165441577efSTejun Heo 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
166441577efSTejun Heo 				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
167441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
168441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
169441577efSTejun Heo 		.port_ops	= &ahci_ops,
170441577efSTejun Heo 	},
1714da646b7SJeff Garzik 	[board_ahci_sb600] =
17255a61604SConke Hu 	{
173417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
1742fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
1752fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
176417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
17714bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
178469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
179bd17243aSShane Huang 		.port_ops	= &ahci_sb600_ops,
18055a61604SConke Hu 	},
1814da646b7SJeff Garzik 	[board_ahci_sb700] =	/* for SB700 and SB800 */
182e39fc8c9SShane Huang 	{
183bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
184e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
18514bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
186e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
187bd17243aSShane Huang 		.port_ops	= &ahci_sb600_ops,
188e39fc8c9SShane Huang 	},
189441577efSTejun Heo 	[board_ahci_vt8251] =
190e297d99eSTejun Heo 	{
191441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
192e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
19314bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
194e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
195441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
1961b677afdSShaohua Li 	},
197c6fd2807SJeff Garzik };
198c6fd2807SJeff Garzik 
199c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
200c6fd2807SJeff Garzik 	/* Intel */
20154bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
20254bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
20354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
20454bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
20554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
20682490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
20754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
20854bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
20954bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
21054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2117a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2121b677afdSShaohua Li 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
2137a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2147a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2157a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2167a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2177a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2187a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2197a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2207a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
2217a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
2227a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
2237a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
2247a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
2257a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
2267a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
2277a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
228d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
229d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
23016ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
231b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
23216ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
233c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
234c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
235adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
2368e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
237c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
238adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
2398e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
240c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
2415623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
2425623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
2435623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
2445623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
2455623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
2465623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
247c6fd2807SJeff Garzik 
248e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
249e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
250e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
251c6fd2807SJeff Garzik 
252c6fd2807SJeff Garzik 	/* ATI */
253c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
254e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
255e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
256e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
257e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
258e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
259e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
260c6fd2807SJeff Garzik 
261e2dd90b1SShane Huang 	/* AMD */
2625deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
263e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
264e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
265e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
266e2dd90b1SShane Huang 
267c6fd2807SJeff Garzik 	/* VIA */
26854bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
269bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
270c6fd2807SJeff Garzik 
271c6fd2807SJeff Garzik 	/* NVIDIA */
272e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
273e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
274e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
275e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
276e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
277e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
278e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
279e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
280441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
281441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
282441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
283441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
284441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
285441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
286441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
287441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
288441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
289441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
290441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
291441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
292441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
293441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
294441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
295441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
296441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
297441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
298441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
299441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
300441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
301441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
302441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
303441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
304441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
305441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
306441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
307441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
308441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
309441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
310441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
311441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
312441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
313441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
314441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
315441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
316441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
317441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
318441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
319441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
320441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
321441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
322441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
323441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
324441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
325441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
326441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
327441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
328441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
329441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
330441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
331441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
332441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
333441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
334441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
335441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
336441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
337441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
338441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
339441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
340441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
341441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
342441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
343441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
344441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
345441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
346441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
347441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
348441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
349441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
350441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
351441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
352441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
353441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
354441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
355441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
356c6fd2807SJeff Garzik 
357c6fd2807SJeff Garzik 	/* SiS */
35820e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
35920e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
36020e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
361c6fd2807SJeff Garzik 
362cd70c266SJeff Garzik 	/* Marvell */
363cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
364c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
365cd70c266SJeff Garzik 
366c77a036bSMark Nelson 	/* Promise */
367c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
368c77a036bSMark Nelson 
369415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
370415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
371c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
372415ae2b5SJeff Garzik 
373c6fd2807SJeff Garzik 	{ }	/* terminate list */
374c6fd2807SJeff Garzik };
375c6fd2807SJeff Garzik 
376c6fd2807SJeff Garzik 
377c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
378c6fd2807SJeff Garzik 	.name			= DRV_NAME,
379c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
380c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
38124dc5f33STejun Heo 	.remove			= ata_pci_remove_one,
382438ac6d5STejun Heo #ifdef CONFIG_PM
383c6fd2807SJeff Garzik 	.suspend		= ahci_pci_device_suspend,
384c6fd2807SJeff Garzik 	.resume			= ahci_pci_device_resume,
385438ac6d5STejun Heo #endif
386c6fd2807SJeff Garzik };
387c6fd2807SJeff Garzik 
3885b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE)
3895b66c829SAlan Cox static int marvell_enable;
3905b66c829SAlan Cox #else
3915b66c829SAlan Cox static int marvell_enable = 1;
3925b66c829SAlan Cox #endif
3935b66c829SAlan Cox module_param(marvell_enable, int, 0644);
3945b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
3955b66c829SAlan Cox 
3965b66c829SAlan Cox 
397394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
398394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
399394d6e53SAnton Vorontsov {
400394d6e53SAnton Vorontsov 	unsigned int force_port_map = 0;
401394d6e53SAnton Vorontsov 	unsigned int mask_port_map = 0;
402394d6e53SAnton Vorontsov 
403394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
404394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
405394d6e53SAnton Vorontsov 		force_port_map = 1;
406394d6e53SAnton Vorontsov 	}
407394d6e53SAnton Vorontsov 
408394d6e53SAnton Vorontsov 	/*
409394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
410394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
411394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
412394d6e53SAnton Vorontsov 	 */
413394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
414394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
415394d6e53SAnton Vorontsov 			mask_port_map = 0x3;
416394d6e53SAnton Vorontsov 		else
417394d6e53SAnton Vorontsov 			mask_port_map = 0xf;
418394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
419394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
420394d6e53SAnton Vorontsov 	}
421394d6e53SAnton Vorontsov 
4221d513358SAnton Vorontsov 	ahci_save_initial_config(&pdev->dev, hpriv, force_port_map,
4231d513358SAnton Vorontsov 				 mask_port_map);
424394d6e53SAnton Vorontsov }
425394d6e53SAnton Vorontsov 
4263303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host)
4273303040dSAnton Vorontsov {
4283303040dSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
4293303040dSAnton Vorontsov 
4303303040dSAnton Vorontsov 	ahci_reset_controller(host);
4313303040dSAnton Vorontsov 
432c6fd2807SJeff Garzik 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
4333303040dSAnton Vorontsov 		struct ahci_host_priv *hpriv = host->private_data;
434c6fd2807SJeff Garzik 		u16 tmp16;
435c6fd2807SJeff Garzik 
436c6fd2807SJeff Garzik 		/* configure PCS */
437c6fd2807SJeff Garzik 		pci_read_config_word(pdev, 0x92, &tmp16);
43849f29090STejun Heo 		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
43949f29090STejun Heo 			tmp16 |= hpriv->port_map;
440c6fd2807SJeff Garzik 			pci_write_config_word(pdev, 0x92, tmp16);
441c6fd2807SJeff Garzik 		}
44249f29090STejun Heo 	}
443c6fd2807SJeff Garzik 
444c6fd2807SJeff Garzik 	return 0;
445c6fd2807SJeff Garzik }
446c6fd2807SJeff Garzik 
447781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
448781d6550SAnton Vorontsov {
449781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
450781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
451781d6550SAnton Vorontsov 	void __iomem *port_mmio;
452781d6550SAnton Vorontsov 	u32 tmp;
453c40e7cb8SJose Alberto Reguero 	int mv;
4542bcd866bSJeff Garzik 
455417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
456c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
457c40e7cb8SJose Alberto Reguero 			mv = 2;
458c40e7cb8SJose Alberto Reguero 		else
459c40e7cb8SJose Alberto Reguero 			mv = 4;
460c40e7cb8SJose Alberto Reguero 		port_mmio = __ahci_port_base(host, mv);
461cd70c266SJeff Garzik 
462cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
463cd70c266SJeff Garzik 
464cd70c266SJeff Garzik 		/* clear port IRQ */
465cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
466cd70c266SJeff Garzik 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
467cd70c266SJeff Garzik 		if (tmp)
468cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
469cd70c266SJeff Garzik 	}
470cd70c266SJeff Garzik 
471781d6550SAnton Vorontsov 	ahci_init_controller(host);
472c6fd2807SJeff Garzik }
473c6fd2807SJeff Garzik 
474bd17243aSShane Huang static int ahci_sb600_check_ready(struct ata_link *link)
475bd17243aSShane Huang {
476bd17243aSShane Huang 	void __iomem *port_mmio = ahci_port_base(link->ap);
477bd17243aSShane Huang 	u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
478bd17243aSShane Huang 	u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
479bd17243aSShane Huang 
480bd17243aSShane Huang 	/*
481bd17243aSShane Huang 	 * There is no need to check TFDATA if BAD PMP is found due to HW bug,
482bd17243aSShane Huang 	 * which can save timeout delay.
483bd17243aSShane Huang 	 */
484bd17243aSShane Huang 	if (irq_status & PORT_IRQ_BAD_PMP)
485bd17243aSShane Huang 		return -EIO;
486bd17243aSShane Huang 
487bd17243aSShane Huang 	return ata_check_ready(status);
488bd17243aSShane Huang }
489bd17243aSShane Huang 
490bd17243aSShane Huang static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
491bd17243aSShane Huang 				unsigned long deadline)
492bd17243aSShane Huang {
493bd17243aSShane Huang 	struct ata_port *ap = link->ap;
494bd17243aSShane Huang 	void __iomem *port_mmio = ahci_port_base(ap);
495bd17243aSShane Huang 	int pmp = sata_srst_pmp(link);
496bd17243aSShane Huang 	int rc;
497bd17243aSShane Huang 	u32 irq_sts;
498bd17243aSShane Huang 
499bd17243aSShane Huang 	DPRINTK("ENTER\n");
500bd17243aSShane Huang 
501bd17243aSShane Huang 	rc = ahci_do_softreset(link, class, pmp, deadline,
502bd17243aSShane Huang 			       ahci_sb600_check_ready);
503bd17243aSShane Huang 
504bd17243aSShane Huang 	/*
505bd17243aSShane Huang 	 * Soft reset fails on some ATI chips with IPMS set when PMP
506bd17243aSShane Huang 	 * is enabled but SATA HDD/ODD is connected to SATA port,
507bd17243aSShane Huang 	 * do soft reset again to port 0.
508bd17243aSShane Huang 	 */
509bd17243aSShane Huang 	if (rc == -EIO) {
510bd17243aSShane Huang 		irq_sts = readl(port_mmio + PORT_IRQ_STAT);
511bd17243aSShane Huang 		if (irq_sts & PORT_IRQ_BAD_PMP) {
512bd17243aSShane Huang 			ata_link_printk(link, KERN_WARNING,
513b6931c1fSShane Huang 					"applying SB600 PMP SRST workaround "
514b6931c1fSShane Huang 					"and retrying\n");
515bd17243aSShane Huang 			rc = ahci_do_softreset(link, class, 0, deadline,
516bd17243aSShane Huang 					       ahci_check_ready);
517bd17243aSShane Huang 		}
518bd17243aSShane Huang 	}
519bd17243aSShane Huang 
520bd17243aSShane Huang 	return rc;
521bd17243aSShane Huang }
522bd17243aSShane Huang 
523cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
524d4b2bab4STejun Heo 				 unsigned long deadline)
525ad616ffbSTejun Heo {
526cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
5279dadd45bSTejun Heo 	bool online;
528ad616ffbSTejun Heo 	int rc;
529ad616ffbSTejun Heo 
530ad616ffbSTejun Heo 	DPRINTK("ENTER\n");
531ad616ffbSTejun Heo 
5324447d351STejun Heo 	ahci_stop_engine(ap);
533ad616ffbSTejun Heo 
534cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
5359dadd45bSTejun Heo 				 deadline, &online, NULL);
536ad616ffbSTejun Heo 
5374447d351STejun Heo 	ahci_start_engine(ap);
538ad616ffbSTejun Heo 
539ad616ffbSTejun Heo 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
540ad616ffbSTejun Heo 
541ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
542ad616ffbSTejun Heo 	 * request follow-up softreset.
543ad616ffbSTejun Heo 	 */
5449dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
545ad616ffbSTejun Heo }
546ad616ffbSTejun Heo 
547edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
548edc93052STejun Heo 				unsigned long deadline)
549edc93052STejun Heo {
550edc93052STejun Heo 	struct ata_port *ap = link->ap;
551edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
552edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
553edc93052STejun Heo 	struct ata_taskfile tf;
5549dadd45bSTejun Heo 	bool online;
555edc93052STejun Heo 	int rc;
556edc93052STejun Heo 
557edc93052STejun Heo 	ahci_stop_engine(ap);
558edc93052STejun Heo 
559edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
560edc93052STejun Heo 	ata_tf_init(link->device, &tf);
561edc93052STejun Heo 	tf.command = 0x80;
562edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
563edc93052STejun Heo 
564edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
5659dadd45bSTejun Heo 				 deadline, &online, NULL);
566edc93052STejun Heo 
567edc93052STejun Heo 	ahci_start_engine(ap);
568edc93052STejun Heo 
569edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
570edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
571edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
572edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
573edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
574edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
575edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
576edc93052STejun Heo 	 *
577edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
578edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
579edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
580edc93052STejun Heo 	 * suffice while making probing snappish enough.
581edc93052STejun Heo 	 */
5829dadd45bSTejun Heo 	if (online) {
5839dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
5849dadd45bSTejun Heo 					  ahci_check_ready);
585edc93052STejun Heo 		if (rc)
58678d5ae39SShane Huang 			ahci_kick_engine(ap);
5879dadd45bSTejun Heo 	}
5889dadd45bSTejun Heo 	return rc;
589edc93052STejun Heo }
590edc93052STejun Heo 
591438ac6d5STejun Heo #ifdef CONFIG_PM
592c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
593c6fd2807SJeff Garzik {
594cca3974eSJeff Garzik 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
5959b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
596d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
597c6fd2807SJeff Garzik 	u32 ctl;
598c6fd2807SJeff Garzik 
5999b10ae86STejun Heo 	if (mesg.event & PM_EVENT_SUSPEND &&
6009b10ae86STejun Heo 	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
6019b10ae86STejun Heo 		dev_printk(KERN_ERR, &pdev->dev,
6029b10ae86STejun Heo 			   "BIOS update required for suspend/resume\n");
6039b10ae86STejun Heo 		return -EIO;
6049b10ae86STejun Heo 	}
6059b10ae86STejun Heo 
6063a2d5b70SRafael J. Wysocki 	if (mesg.event & PM_EVENT_SLEEP) {
607c6fd2807SJeff Garzik 		/* AHCI spec rev1.1 section 8.3.3:
608c6fd2807SJeff Garzik 		 * Software must disable interrupts prior to requesting a
609c6fd2807SJeff Garzik 		 * transition of the HBA to D3 state.
610c6fd2807SJeff Garzik 		 */
611c6fd2807SJeff Garzik 		ctl = readl(mmio + HOST_CTL);
612c6fd2807SJeff Garzik 		ctl &= ~HOST_IRQ_EN;
613c6fd2807SJeff Garzik 		writel(ctl, mmio + HOST_CTL);
614c6fd2807SJeff Garzik 		readl(mmio + HOST_CTL); /* flush */
615c6fd2807SJeff Garzik 	}
616c6fd2807SJeff Garzik 
617c6fd2807SJeff Garzik 	return ata_pci_device_suspend(pdev, mesg);
618c6fd2807SJeff Garzik }
619c6fd2807SJeff Garzik 
620c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev)
621c6fd2807SJeff Garzik {
622cca3974eSJeff Garzik 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
623c6fd2807SJeff Garzik 	int rc;
624c6fd2807SJeff Garzik 
625553c4aa6STejun Heo 	rc = ata_pci_device_do_resume(pdev);
626553c4aa6STejun Heo 	if (rc)
627553c4aa6STejun Heo 		return rc;
628c6fd2807SJeff Garzik 
629c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
6303303040dSAnton Vorontsov 		rc = ahci_pci_reset_controller(host);
631c6fd2807SJeff Garzik 		if (rc)
632c6fd2807SJeff Garzik 			return rc;
633c6fd2807SJeff Garzik 
634781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
635c6fd2807SJeff Garzik 	}
636c6fd2807SJeff Garzik 
637cca3974eSJeff Garzik 	ata_host_resume(host);
638c6fd2807SJeff Garzik 
639c6fd2807SJeff Garzik 	return 0;
640c6fd2807SJeff Garzik }
641438ac6d5STejun Heo #endif
642c6fd2807SJeff Garzik 
6434447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
644c6fd2807SJeff Garzik {
645c6fd2807SJeff Garzik 	int rc;
646c6fd2807SJeff Garzik 
647c6fd2807SJeff Garzik 	if (using_dac &&
6486a35528aSYang Hongyang 	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
6496a35528aSYang Hongyang 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
650c6fd2807SJeff Garzik 		if (rc) {
651284901a9SYang Hongyang 			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
652c6fd2807SJeff Garzik 			if (rc) {
653c6fd2807SJeff Garzik 				dev_printk(KERN_ERR, &pdev->dev,
654c6fd2807SJeff Garzik 					   "64-bit DMA enable failed\n");
655c6fd2807SJeff Garzik 				return rc;
656c6fd2807SJeff Garzik 			}
657c6fd2807SJeff Garzik 		}
658c6fd2807SJeff Garzik 	} else {
659284901a9SYang Hongyang 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
660c6fd2807SJeff Garzik 		if (rc) {
661c6fd2807SJeff Garzik 			dev_printk(KERN_ERR, &pdev->dev,
662c6fd2807SJeff Garzik 				   "32-bit DMA enable failed\n");
663c6fd2807SJeff Garzik 			return rc;
664c6fd2807SJeff Garzik 		}
665284901a9SYang Hongyang 		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
666c6fd2807SJeff Garzik 		if (rc) {
667c6fd2807SJeff Garzik 			dev_printk(KERN_ERR, &pdev->dev,
668c6fd2807SJeff Garzik 				   "32-bit consistent DMA enable failed\n");
669c6fd2807SJeff Garzik 			return rc;
670c6fd2807SJeff Garzik 		}
671c6fd2807SJeff Garzik 	}
672c6fd2807SJeff Garzik 	return 0;
673c6fd2807SJeff Garzik }
674c6fd2807SJeff Garzik 
675439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
676439fcaecSAnton Vorontsov {
677439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
678439fcaecSAnton Vorontsov 	u16 cc;
679439fcaecSAnton Vorontsov 	const char *scc_s;
680439fcaecSAnton Vorontsov 
681439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
682439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
683439fcaecSAnton Vorontsov 		scc_s = "IDE";
684439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
685439fcaecSAnton Vorontsov 		scc_s = "SATA";
686439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
687439fcaecSAnton Vorontsov 		scc_s = "RAID";
688439fcaecSAnton Vorontsov 	else
689439fcaecSAnton Vorontsov 		scc_s = "unknown";
690439fcaecSAnton Vorontsov 
691439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
692439fcaecSAnton Vorontsov }
693439fcaecSAnton Vorontsov 
694edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
695edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
696edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
697edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
698edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
699edc93052STejun Heo  * other configuration).
700edc93052STejun Heo  *
701edc93052STejun Heo  * When there's no device attached to the first downstream port of the
702edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
703edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
704edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
705edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
706edc93052STejun Heo  *
707edc93052STejun Heo  * The following function works around the problem by always using
708edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
709edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
710edc93052STejun Heo  * assumed without follow-up softreset.
711edc93052STejun Heo  */
712edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
713edc93052STejun Heo {
714edc93052STejun Heo 	static struct dmi_system_id sysids[] = {
715edc93052STejun Heo 		{
716edc93052STejun Heo 			.ident = "P5W DH Deluxe",
717edc93052STejun Heo 			.matches = {
718edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
719edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
720edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
721edc93052STejun Heo 			},
722edc93052STejun Heo 		},
723edc93052STejun Heo 		{ }
724edc93052STejun Heo 	};
725edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
726edc93052STejun Heo 
727edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
728edc93052STejun Heo 	    dmi_check_system(sysids)) {
729edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
730edc93052STejun Heo 
731edc93052STejun Heo 		dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH "
732edc93052STejun Heo 			   "Deluxe on-board SIMG4726 workaround\n");
733edc93052STejun Heo 
734edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
735edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
736edc93052STejun Heo 	}
737edc93052STejun Heo }
738edc93052STejun Heo 
7392fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
7402fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
74158a09b38SShane Huang {
74258a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
74303d783bfSTejun Heo 		/*
74403d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
74503d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
7462fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
7472fcad9d2STejun Heo 		 *
74803d783bfSTejun Heo 		 * Please read bko#9412 for more info.
74903d783bfSTejun Heo 		 */
75058a09b38SShane Huang 		{
75158a09b38SShane Huang 			.ident = "ASUS M2A-VM",
75258a09b38SShane Huang 			.matches = {
75358a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
75458a09b38SShane Huang 					  "ASUSTeK Computer INC."),
75558a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
75658a09b38SShane Huang 			},
75703d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
75858a09b38SShane Huang 		},
759e65cc194SMark Nelson 		/*
760e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
761e65cc194SMark Nelson 		 * support 64bit DMA.
762e65cc194SMark Nelson 		 *
763e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
764e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
765e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
766e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
767e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
768e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
769e65cc194SMark Nelson 		 *
770e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
771e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
772e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
773e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
774e65cc194SMark Nelson 		 */
775e65cc194SMark Nelson 		{
776e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
777e65cc194SMark Nelson 			.matches = {
778e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
779e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
780e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
781e65cc194SMark Nelson 			},
782e65cc194SMark Nelson 		},
78358a09b38SShane Huang 		{ }
78458a09b38SShane Huang 	};
78503d783bfSTejun Heo 	const struct dmi_system_id *match;
7862fcad9d2STejun Heo 	int year, month, date;
7872fcad9d2STejun Heo 	char buf[9];
78858a09b38SShane Huang 
78903d783bfSTejun Heo 	match = dmi_first_match(sysids);
79058a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
79103d783bfSTejun Heo 	    !match)
79258a09b38SShane Huang 		return false;
79358a09b38SShane Huang 
794e65cc194SMark Nelson 	if (!match->driver_data)
795e65cc194SMark Nelson 		goto enable_64bit;
796e65cc194SMark Nelson 
79703d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
79803d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
79903d783bfSTejun Heo 
800e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
801e65cc194SMark Nelson 		goto enable_64bit;
802e65cc194SMark Nelson 	else {
80303d783bfSTejun Heo 		dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, "
80403d783bfSTejun Heo 			   "forcing 32bit DMA, update BIOS\n", match->ident);
8052fcad9d2STejun Heo 		return false;
8062fcad9d2STejun Heo 	}
807e65cc194SMark Nelson 
808e65cc194SMark Nelson enable_64bit:
809e65cc194SMark Nelson 	dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n",
810e65cc194SMark Nelson 		   match->ident);
811e65cc194SMark Nelson 	return true;
81258a09b38SShane Huang }
81358a09b38SShane Huang 
8141fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
8151fd68434SRafael J. Wysocki {
8161fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
8171fd68434SRafael J. Wysocki 		{
8181fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
8191fd68434SRafael J. Wysocki 			.matches = {
8201fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
8211fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
8221fd68434SRafael J. Wysocki 			},
8231fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
8241fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
8251fd68434SRafael J. Wysocki 		},
826d2f9c061SMaciej Rutecki 		{
827d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
828d2f9c061SMaciej Rutecki 			.matches = {
829d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
830d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
831d2f9c061SMaciej Rutecki 			},
832d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
833d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
834d2f9c061SMaciej Rutecki 		},
8351fd68434SRafael J. Wysocki 
8361fd68434SRafael J. Wysocki 		{ }	/* terminate list */
8371fd68434SRafael J. Wysocki 	};
8381fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
8391fd68434SRafael J. Wysocki 
8401fd68434SRafael J. Wysocki 	if (dmi) {
8411fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
8421fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
8431fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
8441fd68434SRafael J. Wysocki 	}
8451fd68434SRafael J. Wysocki 
8461fd68434SRafael J. Wysocki 	return false;
8471fd68434SRafael J. Wysocki }
8481fd68434SRafael J. Wysocki 
8499b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
8509b10ae86STejun Heo {
8519b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
8529b10ae86STejun Heo 		/*
8539b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
8549b10ae86STejun Heo 		 * to the harddisk doesn't become online after
8559b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
8569deb3431STejun Heo 		 *
8579deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
8589deb3431STejun Heo 		 *
8599deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
8609deb3431STejun Heo 		 * apparently recycling both product and version
8619deb3431STejun Heo 		 * strings.
8629deb3431STejun Heo 		 *
8639deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
8649b10ae86STejun Heo 		 */
8659b10ae86STejun Heo 		{
8669b10ae86STejun Heo 			.ident = "dv4",
8679b10ae86STejun Heo 			.matches = {
8689b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
8699b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
8709b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
8719b10ae86STejun Heo 			},
8729deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
8739b10ae86STejun Heo 		},
8749b10ae86STejun Heo 		{
8759b10ae86STejun Heo 			.ident = "dv5",
8769b10ae86STejun Heo 			.matches = {
8779b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
8789b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
8799b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
8809b10ae86STejun Heo 			},
8819deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
8829b10ae86STejun Heo 		},
8839b10ae86STejun Heo 		{
8849b10ae86STejun Heo 			.ident = "dv6",
8859b10ae86STejun Heo 			.matches = {
8869b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
8879b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
8889b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
8899b10ae86STejun Heo 			},
8909deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
8919b10ae86STejun Heo 		},
8929b10ae86STejun Heo 		{
8939b10ae86STejun Heo 			.ident = "HDX18",
8949b10ae86STejun Heo 			.matches = {
8959b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
8969b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
8979b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
8989b10ae86STejun Heo 			},
8999deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
9009b10ae86STejun Heo 		},
901cedc9bf9STejun Heo 		/*
902cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
903cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
904cedc9bf9STejun Heo 		 * work.  Inbetween, there are V1.06, V2.06 and V3.03
905cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
906cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
9079deb3431STejun Heo 		 *
9089deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
909cedc9bf9STejun Heo 		 */
910cedc9bf9STejun Heo 		{
911cedc9bf9STejun Heo 			.ident = "G725",
912cedc9bf9STejun Heo 			.matches = {
913cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
914cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
915cedc9bf9STejun Heo 			},
9169deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
917cedc9bf9STejun Heo 		},
9189b10ae86STejun Heo 		{ }	/* terminate list */
9199b10ae86STejun Heo 	};
9209b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
9219deb3431STejun Heo 	int year, month, date;
9229deb3431STejun Heo 	char buf[9];
9239b10ae86STejun Heo 
9249b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
9259b10ae86STejun Heo 		return false;
9269b10ae86STejun Heo 
9279deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
9289deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
9299b10ae86STejun Heo 
9309deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
9319b10ae86STejun Heo }
9329b10ae86STejun Heo 
9335594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
9345594639aSTejun Heo {
9355594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
9365594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
9375594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
9385594639aSTejun Heo 		/*
9395594639aSTejun Heo 		 * There are several gigabyte boards which use
9405594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
9415594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
9425594639aSTejun Heo 		 * online but fail to answer properly to SRST or
9435594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
9445594639aSTejun Heo 		 * causing libata to retry quite a few times leading
9455594639aSTejun Heo 		 * to excessive detection delay.
9465594639aSTejun Heo 		 *
9475594639aSTejun Heo 		 * As these firmwares respond to the second reset try
9485594639aSTejun Heo 		 * with invalid device signature, considering unknown
9495594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
9505594639aSTejun Heo 		 */
9515594639aSTejun Heo 		{
9525594639aSTejun Heo 			.ident = "EP45-DQ6",
9535594639aSTejun Heo 			.matches = {
9545594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
9555594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
9565594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
9575594639aSTejun Heo 			},
9585594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
9595594639aSTejun Heo 		},
9605594639aSTejun Heo 		{
9615594639aSTejun Heo 			.ident = "EP45-DS5",
9625594639aSTejun Heo 			.matches = {
9635594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
9645594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
9655594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
9665594639aSTejun Heo 			},
9675594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
9685594639aSTejun Heo 		},
9695594639aSTejun Heo 		{ }	/* terminate list */
9705594639aSTejun Heo 	};
9715594639aSTejun Heo #undef ENCODE_BUSDEVFN
9725594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
9735594639aSTejun Heo 	unsigned int val;
9745594639aSTejun Heo 
9755594639aSTejun Heo 	if (!dmi)
9765594639aSTejun Heo 		return false;
9775594639aSTejun Heo 
9785594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
9795594639aSTejun Heo 
9805594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
9815594639aSTejun Heo }
9825594639aSTejun Heo 
9838e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
984f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
985f80ae7e4STejun Heo {
986f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
987f80ae7e4STejun Heo 		/*
988f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
989f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
990f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
991f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
992f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
993f80ae7e4STejun Heo 		 * failures.  Filter it out.
994f80ae7e4STejun Heo 		 */
995f80ae7e4STejun Heo 		{
996f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
997f80ae7e4STejun Heo 			.matches = {
998f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
999f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1000f80ae7e4STejun Heo 			},
1001f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1002f80ae7e4STejun Heo 		},
1003f80ae7e4STejun Heo 		{ }
1004f80ae7e4STejun Heo 	};
1005f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1006f80ae7e4STejun Heo 	unsigned int filter;
1007f80ae7e4STejun Heo 	int i;
1008f80ae7e4STejun Heo 
1009f80ae7e4STejun Heo 	if (!dmi)
1010f80ae7e4STejun Heo 		return;
1011f80ae7e4STejun Heo 
1012f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1013f80ae7e4STejun Heo 	dev_printk(KERN_INFO, host->dev,
1014f80ae7e4STejun Heo 		   "applying extra ACPI _GTF filter 0x%x for %s\n",
1015f80ae7e4STejun Heo 		   filter, dmi->ident);
1016f80ae7e4STejun Heo 
1017f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1018f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1019f80ae7e4STejun Heo 		struct ata_link *link;
1020f80ae7e4STejun Heo 		struct ata_device *dev;
1021f80ae7e4STejun Heo 
1022f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1023f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1024f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1025f80ae7e4STejun Heo 	}
1026f80ae7e4STejun Heo }
10278e513217SMarkus Trippelsdorf #else
10288e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
10298e513217SMarkus Trippelsdorf {}
10308e513217SMarkus Trippelsdorf #endif
1031f80ae7e4STejun Heo 
1032c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1033c6fd2807SJeff Garzik {
1034c6fd2807SJeff Garzik 	static int printed_version;
1035e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1036e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
10374447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
103824dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1039c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
10404447d351STejun Heo 	struct ata_host *host;
1041837f5f8fSTejun Heo 	int n_ports, i, rc;
1042c6fd2807SJeff Garzik 
1043c6fd2807SJeff Garzik 	VPRINTK("ENTER\n");
1044c6fd2807SJeff Garzik 
1045c6fd2807SJeff Garzik 	WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1046c6fd2807SJeff Garzik 
1047c6fd2807SJeff Garzik 	if (!printed_version++)
1048c6fd2807SJeff Garzik 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
1049c6fd2807SJeff Garzik 
10505b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
10515b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
10525b66c829SAlan Cox 	   AHCI stays out of the way */
10535b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
10545b66c829SAlan Cox 		return -ENODEV;
10555b66c829SAlan Cox 
1056*c6353b45STejun Heo 	/*
1057*c6353b45STejun Heo 	 * For some reason, MCP89 on MacBook 7,1 doesn't work with
1058*c6353b45STejun Heo 	 * ahci, use ata_generic instead.
1059*c6353b45STejun Heo 	 */
1060*c6353b45STejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
1061*c6353b45STejun Heo 	    pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
1062*c6353b45STejun Heo 	    pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
1063*c6353b45STejun Heo 	    pdev->subsystem_device == 0xcb89)
1064*c6353b45STejun Heo 		return -ENODEV;
1065*c6353b45STejun Heo 
10667a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
10677a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
10687a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
10697a02267eSMark Nelson 	 */
10707a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
10717a02267eSMark Nelson 		dev_printk(KERN_INFO, &pdev->dev, "PDC42819 "
10727a02267eSMark Nelson 			   "can only drive SATA devices with this driver\n");
10737a02267eSMark Nelson 
10744447d351STejun Heo 	/* acquire resources */
107524dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1076c6fd2807SJeff Garzik 	if (rc)
1077c6fd2807SJeff Garzik 		return rc;
1078c6fd2807SJeff Garzik 
1079dea55137STejun Heo 	/* AHCI controllers often implement SFF compatible interface.
1080dea55137STejun Heo 	 * Grab all PCI BARs just in case.
1081dea55137STejun Heo 	 */
1082dea55137STejun Heo 	rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME);
10830d5ff566STejun Heo 	if (rc == -EBUSY)
108424dc5f33STejun Heo 		pcim_pin_device(pdev);
10850d5ff566STejun Heo 	if (rc)
108624dc5f33STejun Heo 		return rc;
1087c6fd2807SJeff Garzik 
1088c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1089c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1090c4f7792cSTejun Heo 		u8 map;
1091c4f7792cSTejun Heo 
1092c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1093c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1094c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1095c4f7792cSTejun Heo 		 */
1096c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1097c4f7792cSTejun Heo 		if (map & 0x3) {
1098c4f7792cSTejun Heo 			dev_printk(KERN_INFO, &pdev->dev, "controller is in "
1099c4f7792cSTejun Heo 				   "combined mode, can't enable AHCI mode\n");
1100c4f7792cSTejun Heo 			return -ENODEV;
1101c4f7792cSTejun Heo 		}
1102c4f7792cSTejun Heo 	}
1103c4f7792cSTejun Heo 
110424dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
110524dc5f33STejun Heo 	if (!hpriv)
110624dc5f33STejun Heo 		return -ENOMEM;
1107417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1108417a1a6dSTejun Heo 
1109e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1110e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1111e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1112e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1113e297d99eSTejun Heo 
1114e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1115e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1116e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1117e427fe04SShane Huang 
11182fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
11192fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
11202fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
112158a09b38SShane Huang 
112231b239adSTejun Heo 	if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
112331b239adSTejun Heo 		pci_intx(pdev, 1);
1124c6fd2807SJeff Garzik 
1125d8993349SAnton Vorontsov 	hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
1126d8993349SAnton Vorontsov 
11274447d351STejun Heo 	/* save initial config */
1128394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1129c6fd2807SJeff Garzik 
11304447d351STejun Heo 	/* prepare host */
1131453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1132453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
113383f2b963STejun Heo 		/*
113483f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
113583f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
113683f2b963STejun Heo 		 * capability, but it seems to be broken on some
113783f2b963STejun Heo 		 * chipsets including NVIDIAs.
113883f2b963STejun Heo 		 */
113983f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1140453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
1141453d3131SRobert Hancock 	}
11424447d351STejun Heo 
11437d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
11447d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
11457d50b60bSTejun Heo 
11460cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
114718f7ba4cSKristen Carlson Accardi 
11481fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
11491fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
11501fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
11511fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
11521fd68434SRafael J. Wysocki 	}
11531fd68434SRafael J. Wysocki 
11549b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
11559b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
11569b10ae86STejun Heo 		dev_printk(KERN_WARNING, &pdev->dev,
11579b10ae86STejun Heo 			   "BIOS update required for suspend/resume\n");
11589b10ae86STejun Heo 	}
11599b10ae86STejun Heo 
11605594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
11615594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
11625594639aSTejun Heo 		dev_info(&pdev->dev,
11635594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
11645594639aSTejun Heo 	}
11655594639aSTejun Heo 
1166837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1167837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1168837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1169837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1170837f5f8fSTejun Heo 	 */
1171837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1172837f5f8fSTejun Heo 
1173837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
11744447d351STejun Heo 	if (!host)
11754447d351STejun Heo 		return -ENOMEM;
11764447d351STejun Heo 	host->private_data = hpriv;
11774447d351STejun Heo 
1178f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1179886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1180f3d7f23fSArjan van de Ven 	else
1181f3d7f23fSArjan van de Ven 		printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
1182886ad09fSArjan van de Ven 
118318f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
118418f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
118518f7ba4cSKristen Carlson Accardi 
11864447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
11874447d351STejun Heo 		struct ata_port *ap = host->ports[i];
11884447d351STejun Heo 
1189cbcdd875STejun Heo 		ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
1190cbcdd875STejun Heo 		ata_port_pbar_desc(ap, AHCI_PCI_BAR,
1191cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
1192cbcdd875STejun Heo 
119331556594SKristen Carlson Accardi 		/* set initial link pm policy */
119431556594SKristen Carlson Accardi 		ap->pm_policy = NOT_AVAILABLE;
119531556594SKristen Carlson Accardi 
119618f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
119718f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
1198008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
119918f7ba4cSKristen Carlson Accardi 
120018f7ba4cSKristen Carlson Accardi 
1201dab632e8SJeff Garzik 		/* disabled/not-implemented port */
1202350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
1203dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
12044447d351STejun Heo 	}
1205c6fd2807SJeff Garzik 
1206edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
1207edc93052STejun Heo 	ahci_p5wdh_workaround(host);
1208edc93052STejun Heo 
1209f80ae7e4STejun Heo 	/* apply gtf filter quirk */
1210f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
1211f80ae7e4STejun Heo 
1212c6fd2807SJeff Garzik 	/* initialize adapter */
12134447d351STejun Heo 	rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
1214c6fd2807SJeff Garzik 	if (rc)
121524dc5f33STejun Heo 		return rc;
1216c6fd2807SJeff Garzik 
12173303040dSAnton Vorontsov 	rc = ahci_pci_reset_controller(host);
12184447d351STejun Heo 	if (rc)
12194447d351STejun Heo 		return rc;
1220c6fd2807SJeff Garzik 
1221781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
1222439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
1223c6fd2807SJeff Garzik 
12244447d351STejun Heo 	pci_set_master(pdev);
12254447d351STejun Heo 	return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
12264447d351STejun Heo 				 &ahci_sht);
1227c6fd2807SJeff Garzik }
1228c6fd2807SJeff Garzik 
1229c6fd2807SJeff Garzik static int __init ahci_init(void)
1230c6fd2807SJeff Garzik {
1231c6fd2807SJeff Garzik 	return pci_register_driver(&ahci_pci_driver);
1232c6fd2807SJeff Garzik }
1233c6fd2807SJeff Garzik 
1234c6fd2807SJeff Garzik static void __exit ahci_exit(void)
1235c6fd2807SJeff Garzik {
1236c6fd2807SJeff Garzik 	pci_unregister_driver(&ahci_pci_driver);
1237c6fd2807SJeff Garzik }
1238c6fd2807SJeff Garzik 
1239c6fd2807SJeff Garzik 
1240c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
1241c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
1242c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
1243c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
1244c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
1245c6fd2807SJeff Garzik 
1246c6fd2807SJeff Garzik module_init(ahci_init);
1247c6fd2807SJeff Garzik module_exit(ahci_exit);
1248