xref: /openbmc/linux/drivers/ata/ahci.c (revision a7ba70f1787f977f970cd116076c6fce4b9e01cc)
1c82ee6d3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2c6fd2807SJeff Garzik /*
3c6fd2807SJeff Garzik  *  ahci.c - AHCI SATA support
4c6fd2807SJeff Garzik  *
58c3d3d4bSTejun Heo  *  Maintained by:  Tejun Heo <tj@kernel.org>
6c6fd2807SJeff Garzik  *    		    Please ALWAYS copy linux-ide@vger.kernel.org
7c6fd2807SJeff Garzik  *		    on emails.
8c6fd2807SJeff Garzik  *
9c6fd2807SJeff Garzik  *  Copyright 2004-2005 Red Hat, Inc.
10c6fd2807SJeff Garzik  *
11c6fd2807SJeff Garzik  * libata documentation is available via 'make {ps|pdf}docs',
1219285f3cSMauro Carvalho Chehab  * as Documentation/driver-api/libata.rst
13c6fd2807SJeff Garzik  *
14c6fd2807SJeff Garzik  * AHCI hardware documentation:
15c6fd2807SJeff Garzik  * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
16c6fd2807SJeff Garzik  * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
17c6fd2807SJeff Garzik  */
18c6fd2807SJeff Garzik 
19c6fd2807SJeff Garzik #include <linux/kernel.h>
20c6fd2807SJeff Garzik #include <linux/module.h>
21c6fd2807SJeff Garzik #include <linux/pci.h>
22c6fd2807SJeff Garzik #include <linux/blkdev.h>
23c6fd2807SJeff Garzik #include <linux/delay.h>
24c6fd2807SJeff Garzik #include <linux/interrupt.h>
25c6fd2807SJeff Garzik #include <linux/dma-mapping.h>
26c6fd2807SJeff Garzik #include <linux/device.h>
27edc93052STejun Heo #include <linux/dmi.h>
285a0e3ad6STejun Heo #include <linux/gfp.h>
29ee2aad42SRobert Richter #include <linux/msi.h>
30c6fd2807SJeff Garzik #include <scsi/scsi_host.h>
31c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h>
32c6fd2807SJeff Garzik #include <linux/libata.h>
33aecec8b6SChristoph Hellwig #include <linux/ahci-remap.h>
34aecec8b6SChristoph Hellwig #include <linux/io-64-nonatomic-lo-hi.h>
35365cfa1eSAnton Vorontsov #include "ahci.h"
36c6fd2807SJeff Garzik 
37c6fd2807SJeff Garzik #define DRV_NAME	"ahci"
387d50b60bSTejun Heo #define DRV_VERSION	"3.0"
39c6fd2807SJeff Garzik 
40c6fd2807SJeff Garzik enum {
41318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STA2X11	= 0,
42b7ae128dSRobert Richter 	AHCI_PCI_BAR_CAVIUM	= 0,
437f9c9f8eSHugh Daschbach 	AHCI_PCI_BAR_ENMOTUS	= 2,
44b1314e3fSRadha Mohan Chintakuntla 	AHCI_PCI_BAR_CAVIUM_GEN5	= 4,
45318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STANDARD	= 5,
46441577efSTejun Heo };
47c6fd2807SJeff Garzik 
48441577efSTejun Heo enum board_ids {
49441577efSTejun Heo 	/* board IDs by feature in alphabetical order */
50441577efSTejun Heo 	board_ahci,
51441577efSTejun Heo 	board_ahci_ign_iferr,
52ebb82e3cSHans de Goede 	board_ahci_mobile,
5366a7cbc3STejun Heo 	board_ahci_nomsi,
5467809f85SLevente Kurusa 	board_ahci_noncq,
55441577efSTejun Heo 	board_ahci_nosntf,
565f173107STejun Heo 	board_ahci_yes_fbs,
57441577efSTejun Heo 
58441577efSTejun Heo 	/* board IDs for specific chipsets in alphabetical order */
59dbfe8ef5SDan Williams 	board_ahci_avn,
60441577efSTejun Heo 	board_ahci_mcp65,
6183f2b963STejun Heo 	board_ahci_mcp77,
6283f2b963STejun Heo 	board_ahci_mcp89,
63441577efSTejun Heo 	board_ahci_mv,
64441577efSTejun Heo 	board_ahci_sb600,
65441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
66441577efSTejun Heo 	board_ahci_vt8251,
67441577efSTejun Heo 
68c312ef17SDan Williams 	/*
69c312ef17SDan Williams 	 * board IDs for Intel chipsets that support more than 6 ports
70c312ef17SDan Williams 	 * *and* end up needing the PCS quirk.
71c312ef17SDan Williams 	 */
72c312ef17SDan Williams 	board_ahci_pcs7,
73c312ef17SDan Williams 
74441577efSTejun Heo 	/* aliases */
75441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
76441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
77441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
7883f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
79c6fd2807SJeff Garzik };
80c6fd2807SJeff Garzik 
81c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
8202e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *dev);
83a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
84a1efdabaSTejun Heo 				 unsigned long deadline);
85dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
86dbfe8ef5SDan Williams 			      unsigned long deadline);
87cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
88cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev);
89a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
90a1efdabaSTejun Heo 				unsigned long deadline);
9102e53293SMika Westerberg #ifdef CONFIG_PM
9202e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev);
9302e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev);
94f1d848f9SMika Westerberg #ifdef CONFIG_PM_SLEEP
95f1d848f9SMika Westerberg static int ahci_pci_device_suspend(struct device *dev);
96f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev);
97438ac6d5STejun Heo #endif
9802e53293SMika Westerberg #endif /* CONFIG_PM */
99c6fd2807SJeff Garzik 
100fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = {
101fad16e7aSTejun Heo 	AHCI_SHT("ahci"),
102fad16e7aSTejun Heo };
103fad16e7aSTejun Heo 
104029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
105029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
106a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
107ad616ffbSTejun Heo };
108ad616ffbSTejun Heo 
109029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
110029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
111a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
112edc93052STejun Heo };
113edc93052STejun Heo 
114dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = {
115dbfe8ef5SDan Williams 	.inherits		= &ahci_ops,
116dbfe8ef5SDan Williams 	.hardreset		= ahci_avn_hardreset,
117dbfe8ef5SDan Williams };
118dbfe8ef5SDan Williams 
119c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
120441577efSTejun Heo 	/* by features */
121facb8fa6SJeffrin Jose 	[board_ahci] = {
1221188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
12314bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
124469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
125c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
126c6fd2807SJeff Garzik 	},
127facb8fa6SJeffrin Jose 	[board_ahci_ign_iferr] = {
128417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
129417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
13014bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
131469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
13241669553STejun Heo 		.port_ops	= &ahci_ops,
13341669553STejun Heo 	},
134ebb82e3cSHans de Goede 	[board_ahci_mobile] = {
135ebb82e3cSHans de Goede 		AHCI_HFLAGS	(AHCI_HFLAG_IS_MOBILE),
136ebb82e3cSHans de Goede 		.flags		= AHCI_FLAG_COMMON,
137ebb82e3cSHans de Goede 		.pio_mask	= ATA_PIO4,
138ebb82e3cSHans de Goede 		.udma_mask	= ATA_UDMA6,
139ebb82e3cSHans de Goede 		.port_ops	= &ahci_ops,
140ebb82e3cSHans de Goede 	},
14166a7cbc3STejun Heo 	[board_ahci_nomsi] = {
14266a7cbc3STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_MSI),
14366a7cbc3STejun Heo 		.flags		= AHCI_FLAG_COMMON,
14466a7cbc3STejun Heo 		.pio_mask	= ATA_PIO4,
14566a7cbc3STejun Heo 		.udma_mask	= ATA_UDMA6,
14666a7cbc3STejun Heo 		.port_ops	= &ahci_ops,
14766a7cbc3STejun Heo 	},
14867809f85SLevente Kurusa 	[board_ahci_noncq] = {
14967809f85SLevente Kurusa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ),
15067809f85SLevente Kurusa 		.flags		= AHCI_FLAG_COMMON,
15167809f85SLevente Kurusa 		.pio_mask	= ATA_PIO4,
15267809f85SLevente Kurusa 		.udma_mask	= ATA_UDMA6,
15367809f85SLevente Kurusa 		.port_ops	= &ahci_ops,
15467809f85SLevente Kurusa 	},
155facb8fa6SJeffrin Jose 	[board_ahci_nosntf] = {
156441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
157441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
158441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
159441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
160441577efSTejun Heo 		.port_ops	= &ahci_ops,
161441577efSTejun Heo 	},
162facb8fa6SJeffrin Jose 	[board_ahci_yes_fbs] = {
1635f173107STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),
1645f173107STejun Heo 		.flags		= AHCI_FLAG_COMMON,
1655f173107STejun Heo 		.pio_mask	= ATA_PIO4,
1665f173107STejun Heo 		.udma_mask	= ATA_UDMA6,
1675f173107STejun Heo 		.port_ops	= &ahci_ops,
1685f173107STejun Heo 	},
169441577efSTejun Heo 	/* by chipsets */
170dbfe8ef5SDan Williams 	[board_ahci_avn] = {
171dbfe8ef5SDan Williams 		.flags		= AHCI_FLAG_COMMON,
172dbfe8ef5SDan Williams 		.pio_mask	= ATA_PIO4,
173dbfe8ef5SDan Williams 		.udma_mask	= ATA_UDMA6,
174dbfe8ef5SDan Williams 		.port_ops	= &ahci_avn_ops,
175dbfe8ef5SDan Williams 	},
176facb8fa6SJeffrin Jose 	[board_ahci_mcp65] = {
17783f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
17883f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
179ae01b249STejun Heo 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
18083f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
18183f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
18283f2b963STejun Heo 		.port_ops	= &ahci_ops,
18383f2b963STejun Heo 	},
184facb8fa6SJeffrin Jose 	[board_ahci_mcp77] = {
18583f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
18683f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
18783f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
18883f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
18983f2b963STejun Heo 		.port_ops	= &ahci_ops,
19083f2b963STejun Heo 	},
191facb8fa6SJeffrin Jose 	[board_ahci_mcp89] = {
19283f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
193441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
194441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
195441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
196441577efSTejun Heo 		.port_ops	= &ahci_ops,
197441577efSTejun Heo 	},
198facb8fa6SJeffrin Jose 	[board_ahci_mv] = {
199441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
200441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
2019cbe056fSSergei Shtylyov 		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
202441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
203441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
204441577efSTejun Heo 		.port_ops	= &ahci_ops,
205441577efSTejun Heo 	},
206facb8fa6SJeffrin Jose 	[board_ahci_sb600] = {
207417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
2082fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
2092fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
210417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
21114bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
212469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
213345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
21455a61604SConke Hu 	},
215facb8fa6SJeffrin Jose 	[board_ahci_sb700] = {	/* for SB700 and SB800 */
216bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
217e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
21814bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
219e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
220345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
221e39fc8c9SShane Huang 	},
222facb8fa6SJeffrin Jose 	[board_ahci_vt8251] = {
223441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
224e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
22514bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
226e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
227441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
2281b677afdSShaohua Li 	},
229c312ef17SDan Williams 	[board_ahci_pcs7] = {
230c312ef17SDan Williams 		.flags		= AHCI_FLAG_COMMON,
231c312ef17SDan Williams 		.pio_mask	= ATA_PIO4,
232c312ef17SDan Williams 		.udma_mask	= ATA_UDMA6,
233c312ef17SDan Williams 		.port_ops	= &ahci_ops,
234c312ef17SDan Williams 	},
235c6fd2807SJeff Garzik };
236c6fd2807SJeff Garzik 
237c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
238c6fd2807SJeff Garzik 	/* Intel */
23954bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
24054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
24154bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
24254bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
24354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
24482490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
24554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
24654bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
24754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
24854bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2497a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2501b677afdSShaohua Li 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
2517a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2527a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2537a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2547a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2557a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2567a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2577a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2587a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
259ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci_mobile }, /* ICH9M */
260ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci_mobile }, /* ICH9M */
261ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci_mobile }, /* ICH9M */
262ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci_mobile }, /* ICH9M */
263ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci_mobile }, /* ICH9M */
2647a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
265ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci_mobile }, /* ICH9M */
266d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
267d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
26816ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
269b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
27016ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
271c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
272c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
273adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
2748e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
275ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci_mobile }, /* PCH M AHCI */
276adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
277ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_mobile }, /* PCH M RAID */
278c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
279c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci_pcs7 }, /* DNV AHCI */
280c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci_pcs7 }, /* DNV AHCI */
281c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b2), board_ahci_pcs7 }, /* DNV AHCI */
282c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b3), board_ahci_pcs7 }, /* DNV AHCI */
283c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b4), board_ahci_pcs7 }, /* DNV AHCI */
284c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b5), board_ahci_pcs7 }, /* DNV AHCI */
285c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b6), board_ahci_pcs7 }, /* DNV AHCI */
286c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b7), board_ahci_pcs7 }, /* DNV AHCI */
287c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19bE), board_ahci_pcs7 }, /* DNV AHCI */
288c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19bF), board_ahci_pcs7 }, /* DNV AHCI */
289c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c0), board_ahci_pcs7 }, /* DNV AHCI */
290c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c1), board_ahci_pcs7 }, /* DNV AHCI */
291c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c2), board_ahci_pcs7 }, /* DNV AHCI */
292c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c3), board_ahci_pcs7 }, /* DNV AHCI */
293c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c4), board_ahci_pcs7 }, /* DNV AHCI */
294c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c5), board_ahci_pcs7 }, /* DNV AHCI */
295c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c6), board_ahci_pcs7 }, /* DNV AHCI */
296c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c7), board_ahci_pcs7 }, /* DNV AHCI */
297c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci_pcs7 }, /* DNV AHCI */
298c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci_pcs7 }, /* DNV AHCI */
2995623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
300ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci_mobile }, /* CPT M AHCI */
3015623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
302ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci_mobile }, /* CPT M RAID */
3035623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
3045623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
305992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
306992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
307992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
30864a3903dSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
309a4a461a6SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
310181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
311ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci_mobile }, /* Panther M AHCI */
312181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
313181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
314181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
315ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci_mobile }, /* Panther M RAID */
3162cab7a4cSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
317ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
318ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci_mobile }, /* Lynx M AHCI */
319ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
320ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci_mobile }, /* Lynx M RAID */
321ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
322ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci_mobile }, /* Lynx M RAID */
323ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
324ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_mobile }, /* Lynx M RAID */
325ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci_mobile }, /* Lynx LP AHCI */
326ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci_mobile }, /* Lynx LP AHCI */
327ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci_mobile }, /* Lynx LP RAID */
328ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c05), board_ahci_mobile }, /* Lynx LP RAID */
329ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c06), board_ahci_mobile }, /* Lynx LP RAID */
330ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci_mobile }, /* Lynx LP RAID */
331ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_mobile }, /* Lynx LP RAID */
332ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_mobile }, /* Lynx LP RAID */
3334544e403SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_mobile }, /* Cannon Lake PCH-LP AHCI */
33429e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
33529e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
33629e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
33729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
33829e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
33929e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
34029e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
34129e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
342dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */
343dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */
344dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */
345dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */
346dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */
347dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
348dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
349dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
350efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
351efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
352151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
353151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
354151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
355151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
356151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
357151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
358151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
359151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
3601cfc7df3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
361ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci_mobile }, /* Wildcat LP AHCI */
362ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci_mobile }, /* Wildcat LP RAID */
363ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci_mobile }, /* Wildcat LP RAID */
364ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_mobile }, /* Wildcat LP RAID */
3651b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
366ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci_mobile }, /* 9 Series M AHCI */
3671b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
368ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci_mobile }, /* 9 Series M RAID */
3691b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
370ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci_mobile }, /* 9 Series M RAID */
3711b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
372ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_mobile }, /* 9 Series M RAID */
373ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9d03), board_ahci_mobile }, /* Sunrise LP AHCI */
374ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9d05), board_ahci_mobile }, /* Sunrise LP RAID */
375ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9d07), board_ahci_mobile }, /* Sunrise LP RAID */
376c5967b79SCharles_Rose@Dell.com 	{ PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */
377ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0xa103), board_ahci_mobile }, /* Sunrise M AHCI */
378690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
379c5967b79SCharles_Rose@Dell.com 	{ PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */
380ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci_mobile }, /* Sunrise M RAID */
381690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
3824d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
383f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
3844d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
385f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
3864d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
3874d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
388f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
389f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
3904d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
3914d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
392f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
393f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
394f919dde0SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */
395ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */
396ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */
397ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */
398ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */
399ba445791SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */
400c6fd2807SJeff Garzik 
401e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
402e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
403e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
4041fefb8fdSBen Hutchings 	/* JMicron 362B and 362C have an AHCI function with IDE class code */
4051fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
4061fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
40791f15fb3SZhang Rui 	/* May need to update quirk_jmicron_async_suspend() for additions */
408c6fd2807SJeff Garzik 
409c6fd2807SJeff Garzik 	/* ATI */
410c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
411e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
412e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
413e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
414e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
415e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
416e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
417c6fd2807SJeff Garzik 
418e2dd90b1SShane Huang 	/* AMD */
4195deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
420fafe5c3dSShane Huang 	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
421e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
422e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
423e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
424e2dd90b1SShane Huang 
425c6fd2807SJeff Garzik 	/* VIA */
42654bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
427bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
428c6fd2807SJeff Garzik 
429c6fd2807SJeff Garzik 	/* NVIDIA */
430e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
431e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
432e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
433e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
434e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
435e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
436e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
437e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
438441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
439441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
440441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
441441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
442441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
443441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
444441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
445441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
446441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
447441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
448441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
449441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
450441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
451441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
452441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
453441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
454441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
455441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
456441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
457441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
458441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
459441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
460441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
461441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
462441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
463441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
464441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
465441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
466441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
467441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
468441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
469441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
470441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
471441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
472441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
473441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
474441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
475441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
476441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
477441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
478441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
479441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
480441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
481441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
482441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
483441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
484441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
485441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
486441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
487441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
488441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
489441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
490441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
491441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
492441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
493441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
494441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
495441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
496441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
497441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
498441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
499441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
500441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
501441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
502441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
503441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
504441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
505441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
506441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
507441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
508441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
509441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
510441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
511441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
512441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
513441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
514c6fd2807SJeff Garzik 
515c6fd2807SJeff Garzik 	/* SiS */
51620e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
51720e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
51820e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
519c6fd2807SJeff Garzik 
520318893e1SAlessandro Rubini 	/* ST Microelectronics */
521318893e1SAlessandro Rubini 	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */
522318893e1SAlessandro Rubini 
523cd70c266SJeff Garzik 	/* Marvell */
524cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
525c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
52669fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
52710aca06cSAnssi Hannula 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
52810aca06cSAnssi Hannula 	  .class_mask = 0xffffff,
5295f173107STejun Heo 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
53069fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
531467b41c6SPer Jessen 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
532e098f5cbSSimon Guinot 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
533e098f5cbSSimon Guinot 			 PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
534e098f5cbSSimon Guinot 	  .driver_data = board_ahci_yes_fbs },			/* 88se9170 */
53569fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
536642d8925SMatt Johnson 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
537fcce9a35SGeorge Spelvin 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
538c5edfff9SMurali Karicheri 	  .driver_data = board_ahci_yes_fbs },			/* 88se9182 */
539c5edfff9SMurali Karicheri 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
540fcce9a35SGeorge Spelvin 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
54169fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
54217c60c6bSAlan Cox 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */
543754a292fSAndreas Schrägle 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0),
544754a292fSAndreas Schrägle 	  .driver_data = board_ahci_yes_fbs },
545a40cf3f3SJohannes Thumshirn 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), 	/* 88se91a2 */
546a40cf3f3SJohannes Thumshirn 	  .driver_data = board_ahci_yes_fbs },
54769fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
54850be5e36STejun Heo 	  .driver_data = board_ahci_yes_fbs },
5496d5278a6SSamir Benmendil 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
5506d5278a6SSamir Benmendil 	  .driver_data = board_ahci_yes_fbs },
55128b2182dSHans de Goede 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */
55228b2182dSHans de Goede 	  .driver_data = board_ahci_yes_fbs },
55328b2182dSHans de Goede 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */
554d2518365SJérôme Carretero 	  .driver_data = board_ahci_yes_fbs },
555cd70c266SJeff Garzik 
556c77a036bSMark Nelson 	/* Promise */
557c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
558b32bfc06SRomain Degez 	{ PCI_VDEVICE(PROMISE, 0x3781), board_ahci },   /* FastTrak TX8660 ahci-mode */
559c77a036bSMark Nelson 
560c9703765SKeng-Yu Lin 	/* Asmedia */
5617b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },	/* ASM1060 */
5627b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },	/* ASM1060 */
5637b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */
5647b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */
5650ce968f3SShawn Lin 	{ PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci },   /* ASM1061R */
5660ce968f3SShawn Lin 	{ PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci },   /* ASM1062R */
567c9703765SKeng-Yu Lin 
56867809f85SLevente Kurusa 	/*
56966a7cbc3STejun Heo 	 * Samsung SSDs found on some macbooks.  NCQ times out if MSI is
57066a7cbc3STejun Heo 	 * enabled.  https://bugzilla.kernel.org/show_bug.cgi?id=60731
57167809f85SLevente Kurusa 	 */
57266a7cbc3STejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
5732b21ef0aSTejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi },
57467809f85SLevente Kurusa 
5757f9c9f8eSHugh Daschbach 	/* Enmotus */
5767f9c9f8eSHugh Daschbach 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
5777f9c9f8eSHugh Daschbach 
578415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
579415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
580c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
581415ae2b5SJeff Garzik 
582c6fd2807SJeff Garzik 	{ }	/* terminate list */
583c6fd2807SJeff Garzik };
584c6fd2807SJeff Garzik 
585f1d848f9SMika Westerberg static const struct dev_pm_ops ahci_pci_pm_ops = {
586f1d848f9SMika Westerberg 	SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume)
58702e53293SMika Westerberg 	SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend,
58802e53293SMika Westerberg 			   ahci_pci_device_runtime_resume, NULL)
589f1d848f9SMika Westerberg };
590c6fd2807SJeff Garzik 
591c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
592c6fd2807SJeff Garzik 	.name			= DRV_NAME,
593c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
594c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
59502e53293SMika Westerberg 	.remove			= ahci_remove_one,
596f1d848f9SMika Westerberg 	.driver = {
597f1d848f9SMika Westerberg 		.pm		= &ahci_pci_pm_ops,
598f1d848f9SMika Westerberg 	},
599c6fd2807SJeff Garzik };
600c6fd2807SJeff Garzik 
6015219d653SJavier Martinez Canillas #if IS_ENABLED(CONFIG_PATA_MARVELL)
6025b66c829SAlan Cox static int marvell_enable;
6035b66c829SAlan Cox #else
6045b66c829SAlan Cox static int marvell_enable = 1;
6055b66c829SAlan Cox #endif
6065b66c829SAlan Cox module_param(marvell_enable, int, 0644);
6075b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
6085b66c829SAlan Cox 
609b1a9585cSSrinivas Pandruvada static int mobile_lpm_policy = -1;
610ebb82e3cSHans de Goede module_param(mobile_lpm_policy, int, 0644);
611ebb82e3cSHans de Goede MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
6125b66c829SAlan Cox 
613394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
614394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
615394d6e53SAnton Vorontsov {
616394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
617394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
6189a23c1d6SAntoine Tenart 		hpriv->force_port_map = 1;
619394d6e53SAnton Vorontsov 	}
620394d6e53SAnton Vorontsov 
621394d6e53SAnton Vorontsov 	/*
622394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
623394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
624394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
625394d6e53SAnton Vorontsov 	 */
626394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
627394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
6289a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0x3;
629394d6e53SAnton Vorontsov 		else
6309a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0xf;
631394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
632394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
633394d6e53SAnton Vorontsov 	}
634394d6e53SAnton Vorontsov 
635725c7b57SAntoine Ténart 	ahci_save_initial_config(&pdev->dev, hpriv);
636394d6e53SAnton Vorontsov }
637394d6e53SAnton Vorontsov 
638781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
639781d6550SAnton Vorontsov {
640781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
641781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
642781d6550SAnton Vorontsov 	void __iomem *port_mmio;
643781d6550SAnton Vorontsov 	u32 tmp;
644c40e7cb8SJose Alberto Reguero 	int mv;
6452bcd866bSJeff Garzik 
646417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
647c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
648c40e7cb8SJose Alberto Reguero 			mv = 2;
649c40e7cb8SJose Alberto Reguero 		else
650c40e7cb8SJose Alberto Reguero 			mv = 4;
651c40e7cb8SJose Alberto Reguero 		port_mmio = __ahci_port_base(host, mv);
652cd70c266SJeff Garzik 
653cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
654cd70c266SJeff Garzik 
655cd70c266SJeff Garzik 		/* clear port IRQ */
656cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
657cd70c266SJeff Garzik 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
658cd70c266SJeff Garzik 		if (tmp)
659cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
660cd70c266SJeff Garzik 	}
661cd70c266SJeff Garzik 
662781d6550SAnton Vorontsov 	ahci_init_controller(host);
663c6fd2807SJeff Garzik }
664c6fd2807SJeff Garzik 
665cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
666d4b2bab4STejun Heo 				 unsigned long deadline)
667ad616ffbSTejun Heo {
668cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
669039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
6709dadd45bSTejun Heo 	bool online;
671ad616ffbSTejun Heo 	int rc;
672ad616ffbSTejun Heo 
673ad616ffbSTejun Heo 	DPRINTK("ENTER\n");
674ad616ffbSTejun Heo 
675fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
676ad616ffbSTejun Heo 
677cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
6789dadd45bSTejun Heo 				 deadline, &online, NULL);
679ad616ffbSTejun Heo 
680039ece38SHans de Goede 	hpriv->start_engine(ap);
681ad616ffbSTejun Heo 
682ad616ffbSTejun Heo 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
683ad616ffbSTejun Heo 
684ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
685ad616ffbSTejun Heo 	 * request follow-up softreset.
686ad616ffbSTejun Heo 	 */
6879dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
688ad616ffbSTejun Heo }
689ad616ffbSTejun Heo 
690edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
691edc93052STejun Heo 				unsigned long deadline)
692edc93052STejun Heo {
693edc93052STejun Heo 	struct ata_port *ap = link->ap;
694edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
695039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
696edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
697edc93052STejun Heo 	struct ata_taskfile tf;
6989dadd45bSTejun Heo 	bool online;
699edc93052STejun Heo 	int rc;
700edc93052STejun Heo 
701fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
702edc93052STejun Heo 
703edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
704edc93052STejun Heo 	ata_tf_init(link->device, &tf);
7059bbb1b0eSSergei Shtylyov 	tf.command = ATA_BUSY;
706edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
707edc93052STejun Heo 
708edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
7099dadd45bSTejun Heo 				 deadline, &online, NULL);
710edc93052STejun Heo 
711039ece38SHans de Goede 	hpriv->start_engine(ap);
712edc93052STejun Heo 
713edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
714edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
715edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
716edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
717edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
718edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
719edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
720edc93052STejun Heo 	 *
721edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
722edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
723edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
724edc93052STejun Heo 	 * suffice while making probing snappish enough.
725edc93052STejun Heo 	 */
7269dadd45bSTejun Heo 	if (online) {
7279dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
7289dadd45bSTejun Heo 					  ahci_check_ready);
729edc93052STejun Heo 		if (rc)
73078d5ae39SShane Huang 			ahci_kick_engine(ap);
7319dadd45bSTejun Heo 	}
7329dadd45bSTejun Heo 	return rc;
733edc93052STejun Heo }
734edc93052STejun Heo 
735dbfe8ef5SDan Williams /*
736dbfe8ef5SDan Williams  * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports.
737dbfe8ef5SDan Williams  *
738dbfe8ef5SDan Williams  * It has been observed with some SSDs that the timing of events in the
739dbfe8ef5SDan Williams  * link synchronization phase can leave the port in a state that can not
740dbfe8ef5SDan Williams  * be recovered by a SATA-hard-reset alone.  The failing signature is
741dbfe8ef5SDan Williams  * SStatus.DET stuck at 1 ("Device presence detected but Phy
742dbfe8ef5SDan Williams  * communication not established").  It was found that unloading and
743dbfe8ef5SDan Williams  * reloading the driver when this problem occurs allows the drive
744dbfe8ef5SDan Williams  * connection to be recovered (DET advanced to 0x3).  The critical
745dbfe8ef5SDan Williams  * component of reloading the driver is that the port state machines are
746dbfe8ef5SDan Williams  * reset by bouncing "port enable" in the AHCI PCS configuration
747dbfe8ef5SDan Williams  * register.  So, reproduce that effect by bouncing a port whenever we
748dbfe8ef5SDan Williams  * see DET==1 after a reset.
749dbfe8ef5SDan Williams  */
750dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
751dbfe8ef5SDan Williams 			      unsigned long deadline)
752dbfe8ef5SDan Williams {
753dbfe8ef5SDan Williams 	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
754dbfe8ef5SDan Williams 	struct ata_port *ap = link->ap;
755dbfe8ef5SDan Williams 	struct ahci_port_priv *pp = ap->private_data;
756dbfe8ef5SDan Williams 	struct ahci_host_priv *hpriv = ap->host->private_data;
757dbfe8ef5SDan Williams 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
758dbfe8ef5SDan Williams 	unsigned long tmo = deadline - jiffies;
759dbfe8ef5SDan Williams 	struct ata_taskfile tf;
760dbfe8ef5SDan Williams 	bool online;
761dbfe8ef5SDan Williams 	int rc, i;
762dbfe8ef5SDan Williams 
763dbfe8ef5SDan Williams 	DPRINTK("ENTER\n");
764dbfe8ef5SDan Williams 
765fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
766dbfe8ef5SDan Williams 
767dbfe8ef5SDan Williams 	for (i = 0; i < 2; i++) {
768dbfe8ef5SDan Williams 		u16 val;
769dbfe8ef5SDan Williams 		u32 sstatus;
770dbfe8ef5SDan Williams 		int port = ap->port_no;
771dbfe8ef5SDan Williams 		struct ata_host *host = ap->host;
772dbfe8ef5SDan Williams 		struct pci_dev *pdev = to_pci_dev(host->dev);
773dbfe8ef5SDan Williams 
774dbfe8ef5SDan Williams 		/* clear D2H reception area to properly wait for D2H FIS */
775dbfe8ef5SDan Williams 		ata_tf_init(link->device, &tf);
776dbfe8ef5SDan Williams 		tf.command = ATA_BUSY;
777dbfe8ef5SDan Williams 		ata_tf_to_fis(&tf, 0, 0, d2h_fis);
778dbfe8ef5SDan Williams 
779dbfe8ef5SDan Williams 		rc = sata_link_hardreset(link, timing, deadline, &online,
780dbfe8ef5SDan Williams 				ahci_check_ready);
781dbfe8ef5SDan Williams 
782dbfe8ef5SDan Williams 		if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 ||
783dbfe8ef5SDan Williams 				(sstatus & 0xf) != 1)
784dbfe8ef5SDan Williams 			break;
785dbfe8ef5SDan Williams 
786dbfe8ef5SDan Williams 		ata_link_printk(link, KERN_INFO, "avn bounce port%d\n",
787dbfe8ef5SDan Williams 				port);
788dbfe8ef5SDan Williams 
789dbfe8ef5SDan Williams 		pci_read_config_word(pdev, 0x92, &val);
790dbfe8ef5SDan Williams 		val &= ~(1 << port);
791dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
792dbfe8ef5SDan Williams 		ata_msleep(ap, 1000);
793dbfe8ef5SDan Williams 		val |= 1 << port;
794dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
795dbfe8ef5SDan Williams 		deadline += tmo;
796dbfe8ef5SDan Williams 	}
797dbfe8ef5SDan Williams 
798dbfe8ef5SDan Williams 	hpriv->start_engine(ap);
799dbfe8ef5SDan Williams 
800dbfe8ef5SDan Williams 	if (online)
801dbfe8ef5SDan Williams 		*class = ahci_dev_classify(ap);
802dbfe8ef5SDan Williams 
803dbfe8ef5SDan Williams 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
804dbfe8ef5SDan Williams 	return rc;
805dbfe8ef5SDan Williams }
806dbfe8ef5SDan Williams 
807dbfe8ef5SDan Williams 
80802e53293SMika Westerberg #ifdef CONFIG_PM
80902e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host)
810c6fd2807SJeff Garzik {
8119b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
812d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
813c6fd2807SJeff Garzik 	u32 ctl;
814c6fd2807SJeff Garzik 
815c6fd2807SJeff Garzik 	/* AHCI spec rev1.1 section 8.3.3:
816c6fd2807SJeff Garzik 	 * Software must disable interrupts prior to requesting a
817c6fd2807SJeff Garzik 	 * transition of the HBA to D3 state.
818c6fd2807SJeff Garzik 	 */
819c6fd2807SJeff Garzik 	ctl = readl(mmio + HOST_CTL);
820c6fd2807SJeff Garzik 	ctl &= ~HOST_IRQ_EN;
821c6fd2807SJeff Garzik 	writel(ctl, mmio + HOST_CTL);
822c6fd2807SJeff Garzik 	readl(mmio + HOST_CTL); /* flush */
82302e53293SMika Westerberg }
824f1d848f9SMika Westerberg 
82502e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev)
82602e53293SMika Westerberg {
82702e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
82802e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
82902e53293SMika Westerberg 
83002e53293SMika Westerberg 	ahci_pci_disable_interrupts(host);
83102e53293SMika Westerberg 	return 0;
83202e53293SMika Westerberg }
83302e53293SMika Westerberg 
83402e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev)
83502e53293SMika Westerberg {
83602e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
83702e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
83802e53293SMika Westerberg 	int rc;
83902e53293SMika Westerberg 
840c312ef17SDan Williams 	rc = ahci_reset_controller(host);
84102e53293SMika Westerberg 	if (rc)
84202e53293SMika Westerberg 		return rc;
84302e53293SMika Westerberg 	ahci_pci_init_controller(host);
84402e53293SMika Westerberg 	return 0;
84502e53293SMika Westerberg }
84602e53293SMika Westerberg 
84702e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP
84802e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev)
84902e53293SMika Westerberg {
85002e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
85102e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
85202e53293SMika Westerberg 	struct ahci_host_priv *hpriv = host->private_data;
85302e53293SMika Westerberg 
85402e53293SMika Westerberg 	if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
85502e53293SMika Westerberg 		dev_err(&pdev->dev,
85602e53293SMika Westerberg 			"BIOS update required for suspend/resume\n");
85702e53293SMika Westerberg 		return -EIO;
85802e53293SMika Westerberg 	}
85902e53293SMika Westerberg 
86002e53293SMika Westerberg 	ahci_pci_disable_interrupts(host);
861f1d848f9SMika Westerberg 	return ata_host_suspend(host, PMSG_SUSPEND);
862c6fd2807SJeff Garzik }
863c6fd2807SJeff Garzik 
864f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev)
865c6fd2807SJeff Garzik {
866f1d848f9SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
8670a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
868c6fd2807SJeff Garzik 	int rc;
869c6fd2807SJeff Garzik 
870cb85696dSJames Laird 	/* Apple BIOS helpfully mangles the registers on resume */
871cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
872cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
873cb85696dSJames Laird 
874c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
875c312ef17SDan Williams 		rc = ahci_reset_controller(host);
876c6fd2807SJeff Garzik 		if (rc)
877c6fd2807SJeff Garzik 			return rc;
878c6fd2807SJeff Garzik 
879781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
880c6fd2807SJeff Garzik 	}
881c6fd2807SJeff Garzik 
882cca3974eSJeff Garzik 	ata_host_resume(host);
883c6fd2807SJeff Garzik 
884c6fd2807SJeff Garzik 	return 0;
885c6fd2807SJeff Garzik }
886438ac6d5STejun Heo #endif
887c6fd2807SJeff Garzik 
88802e53293SMika Westerberg #endif /* CONFIG_PM */
88902e53293SMika Westerberg 
8904447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
891c6fd2807SJeff Garzik {
892b1716871SChristoph Hellwig 	const int dma_bits = using_dac ? 64 : 32;
893c6fd2807SJeff Garzik 	int rc;
894c6fd2807SJeff Garzik 
895318893e1SAlessandro Rubini 	/*
896318893e1SAlessandro Rubini 	 * If the device fixup already set the dma_mask to some non-standard
897318893e1SAlessandro Rubini 	 * value, don't extend it here. This happens on STA2X11, for example.
898b1716871SChristoph Hellwig 	 *
899b1716871SChristoph Hellwig 	 * XXX: manipulating the DMA mask from platform code is completely
900*a7ba70f1SNicolas Saenz Julienne 	 * bogus, platform code should use dev->bus_dma_limit instead..
901318893e1SAlessandro Rubini 	 */
902318893e1SAlessandro Rubini 	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
903318893e1SAlessandro Rubini 		return 0;
904318893e1SAlessandro Rubini 
905b1716871SChristoph Hellwig 	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits));
906b1716871SChristoph Hellwig 	if (rc)
907b1716871SChristoph Hellwig 		dev_err(&pdev->dev, "DMA enable failed\n");
908c6fd2807SJeff Garzik 	return rc;
909c6fd2807SJeff Garzik }
910c6fd2807SJeff Garzik 
911439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
912439fcaecSAnton Vorontsov {
913439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
914439fcaecSAnton Vorontsov 	u16 cc;
915439fcaecSAnton Vorontsov 	const char *scc_s;
916439fcaecSAnton Vorontsov 
917439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
918439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
919439fcaecSAnton Vorontsov 		scc_s = "IDE";
920439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
921439fcaecSAnton Vorontsov 		scc_s = "SATA";
922439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
923439fcaecSAnton Vorontsov 		scc_s = "RAID";
924439fcaecSAnton Vorontsov 	else
925439fcaecSAnton Vorontsov 		scc_s = "unknown";
926439fcaecSAnton Vorontsov 
927439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
928439fcaecSAnton Vorontsov }
929439fcaecSAnton Vorontsov 
930edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
931edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
932edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
933edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
934edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
935edc93052STejun Heo  * other configuration).
936edc93052STejun Heo  *
937edc93052STejun Heo  * When there's no device attached to the first downstream port of the
938edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
939edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
940edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
941edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
942edc93052STejun Heo  *
943edc93052STejun Heo  * The following function works around the problem by always using
944edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
945edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
946edc93052STejun Heo  * assumed without follow-up softreset.
947edc93052STejun Heo  */
948edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
949edc93052STejun Heo {
9501bd06867SMathias Krause 	static const struct dmi_system_id sysids[] = {
951edc93052STejun Heo 		{
952edc93052STejun Heo 			.ident = "P5W DH Deluxe",
953edc93052STejun Heo 			.matches = {
954edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
955edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
956edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
957edc93052STejun Heo 			},
958edc93052STejun Heo 		},
959edc93052STejun Heo 		{ }
960edc93052STejun Heo 	};
961edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
962edc93052STejun Heo 
963edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
964edc93052STejun Heo 	    dmi_check_system(sysids)) {
965edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
966edc93052STejun Heo 
967a44fec1fSJoe Perches 		dev_info(&pdev->dev,
968a44fec1fSJoe Perches 			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
969edc93052STejun Heo 
970edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
971edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
972edc93052STejun Heo 	}
973edc93052STejun Heo }
974edc93052STejun Heo 
975cb85696dSJames Laird /*
976cb85696dSJames Laird  * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
977cb85696dSJames Laird  * booting in BIOS compatibility mode.  We restore the registers but not ID.
978cb85696dSJames Laird  */
979cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
980cb85696dSJames Laird {
981cb85696dSJames Laird 	u32 val;
982cb85696dSJames Laird 
983cb85696dSJames Laird 	printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
984cb85696dSJames Laird 
985cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
986cb85696dSJames Laird 	val |= 1 << 0x1b;
987cb85696dSJames Laird 	/* the following changes the device ID, but appears not to affect function */
988cb85696dSJames Laird 	/* val = (val & ~0xf0000000) | 0x80000000; */
989cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
990cb85696dSJames Laird 
991cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
992cb85696dSJames Laird 	val |= 1 << 0xc;
993cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
994cb85696dSJames Laird 
995cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x4a4, &val);
996cb85696dSJames Laird 	val &= 0xff;
997cb85696dSJames Laird 	val |= 0x01060100;
998cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x4a4, val);
999cb85696dSJames Laird 
1000cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
1001cb85696dSJames Laird 	val &= ~(1 << 0xc);
1002cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
1003cb85696dSJames Laird 
1004cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
1005cb85696dSJames Laird 	val &= ~(1 << 0x1b);
1006cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
1007cb85696dSJames Laird }
1008cb85696dSJames Laird 
1009cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev)
1010cb85696dSJames Laird {
1011cb85696dSJames Laird 	return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
1012cb85696dSJames Laird 		pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
1013cb85696dSJames Laird 		pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
1014cb85696dSJames Laird 		pdev->subsystem_device == 0xcb89;
1015cb85696dSJames Laird }
1016cb85696dSJames Laird 
10172fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
10182fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
101958a09b38SShane Huang {
102058a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
102103d783bfSTejun Heo 		/*
102203d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
102303d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
10242fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
10252fcad9d2STejun Heo 		 *
102603d783bfSTejun Heo 		 * Please read bko#9412 for more info.
102703d783bfSTejun Heo 		 */
102858a09b38SShane Huang 		{
102958a09b38SShane Huang 			.ident = "ASUS M2A-VM",
103058a09b38SShane Huang 			.matches = {
103158a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
103258a09b38SShane Huang 					  "ASUSTeK Computer INC."),
103358a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
103458a09b38SShane Huang 			},
103503d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
103658a09b38SShane Huang 		},
1037e65cc194SMark Nelson 		/*
1038e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
1039e65cc194SMark Nelson 		 * support 64bit DMA.
1040e65cc194SMark Nelson 		 *
1041e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
1042e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
1043e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
1044e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
1045e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
1046e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
1047e65cc194SMark Nelson 		 *
1048e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
1049e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
1050e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
1051e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
1052e65cc194SMark Nelson 		 */
1053e65cc194SMark Nelson 		{
1054e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
1055e65cc194SMark Nelson 			.matches = {
1056e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1057e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
1058e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
1059e65cc194SMark Nelson 			},
1060e65cc194SMark Nelson 		},
10613c4aa91fSMark Nelson 		/*
1062ff0173c1SMark Nelson 		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support
1063ff0173c1SMark Nelson 		 * 64bit DMA.
1064ff0173c1SMark Nelson 		 *
1065ff0173c1SMark Nelson 		 * This board also had the typo mentioned above in the
1066ff0173c1SMark Nelson 		 * Manufacturer DMI field (fixed in BIOS version 1.5), so
1067ff0173c1SMark Nelson 		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again.
1068ff0173c1SMark Nelson 		 */
1069ff0173c1SMark Nelson 		{
1070ff0173c1SMark Nelson 			.ident = "MSI K9AGM2",
1071ff0173c1SMark Nelson 			.matches = {
1072ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1073ff0173c1SMark Nelson 					  "MICRO-STAR INTER"),
1074ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"),
1075ff0173c1SMark Nelson 			},
1076ff0173c1SMark Nelson 		},
1077ff0173c1SMark Nelson 		/*
10783c4aa91fSMark Nelson 		 * All BIOS versions for the Asus M3A support 64bit DMA.
10793c4aa91fSMark Nelson 		 * (all release versions from 0301 to 1206 were tested)
10803c4aa91fSMark Nelson 		 */
10813c4aa91fSMark Nelson 		{
10823c4aa91fSMark Nelson 			.ident = "ASUS M3A",
10833c4aa91fSMark Nelson 			.matches = {
10843c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
10853c4aa91fSMark Nelson 					  "ASUSTeK Computer INC."),
10863c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
10873c4aa91fSMark Nelson 			},
10883c4aa91fSMark Nelson 		},
108958a09b38SShane Huang 		{ }
109058a09b38SShane Huang 	};
109103d783bfSTejun Heo 	const struct dmi_system_id *match;
10922fcad9d2STejun Heo 	int year, month, date;
10932fcad9d2STejun Heo 	char buf[9];
109458a09b38SShane Huang 
109503d783bfSTejun Heo 	match = dmi_first_match(sysids);
109658a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
109703d783bfSTejun Heo 	    !match)
109858a09b38SShane Huang 		return false;
109958a09b38SShane Huang 
1100e65cc194SMark Nelson 	if (!match->driver_data)
1101e65cc194SMark Nelson 		goto enable_64bit;
1102e65cc194SMark Nelson 
110303d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
110403d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
110503d783bfSTejun Heo 
1106e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
1107e65cc194SMark Nelson 		goto enable_64bit;
1108e65cc194SMark Nelson 	else {
1109a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
1110a44fec1fSJoe Perches 			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
1111a44fec1fSJoe Perches 			 match->ident);
11122fcad9d2STejun Heo 		return false;
11132fcad9d2STejun Heo 	}
1114e65cc194SMark Nelson 
1115e65cc194SMark Nelson enable_64bit:
1116a44fec1fSJoe Perches 	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
1117e65cc194SMark Nelson 	return true;
111858a09b38SShane Huang }
111958a09b38SShane Huang 
11201fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
11211fd68434SRafael J. Wysocki {
11221fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
11231fd68434SRafael J. Wysocki 		{
11241fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
11251fd68434SRafael J. Wysocki 			.matches = {
11261fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11271fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
11281fd68434SRafael J. Wysocki 			},
11291fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
11301fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
11311fd68434SRafael J. Wysocki 		},
1132d2f9c061SMaciej Rutecki 		{
1133d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
1134d2f9c061SMaciej Rutecki 			.matches = {
1135d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1136d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
1137d2f9c061SMaciej Rutecki 			},
1138d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
1139d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
1140d2f9c061SMaciej Rutecki 		},
11411fd68434SRafael J. Wysocki 
11421fd68434SRafael J. Wysocki 		{ }	/* terminate list */
11431fd68434SRafael J. Wysocki 	};
11441fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
11451fd68434SRafael J. Wysocki 
11461fd68434SRafael J. Wysocki 	if (dmi) {
11471fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
11481fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
11491fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
11501fd68434SRafael J. Wysocki 	}
11511fd68434SRafael J. Wysocki 
11521fd68434SRafael J. Wysocki 	return false;
11531fd68434SRafael J. Wysocki }
11541fd68434SRafael J. Wysocki 
11559b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
11569b10ae86STejun Heo {
11579b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
11589b10ae86STejun Heo 		/*
11599b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
11609b10ae86STejun Heo 		 * to the harddisk doesn't become online after
11619b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
11629deb3431STejun Heo 		 *
11639deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
11649deb3431STejun Heo 		 *
11659deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
11669deb3431STejun Heo 		 * apparently recycling both product and version
11679deb3431STejun Heo 		 * strings.
11689deb3431STejun Heo 		 *
11699deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
11709b10ae86STejun Heo 		 */
11719b10ae86STejun Heo 		{
11729b10ae86STejun Heo 			.ident = "dv4",
11739b10ae86STejun Heo 			.matches = {
11749b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11759b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
11769b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
11779b10ae86STejun Heo 			},
11789deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
11799b10ae86STejun Heo 		},
11809b10ae86STejun Heo 		{
11819b10ae86STejun Heo 			.ident = "dv5",
11829b10ae86STejun Heo 			.matches = {
11839b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11849b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
11859b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
11869b10ae86STejun Heo 			},
11879deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
11889b10ae86STejun Heo 		},
11899b10ae86STejun Heo 		{
11909b10ae86STejun Heo 			.ident = "dv6",
11919b10ae86STejun Heo 			.matches = {
11929b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11939b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
11949b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
11959b10ae86STejun Heo 			},
11969deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
11979b10ae86STejun Heo 		},
11989b10ae86STejun Heo 		{
11999b10ae86STejun Heo 			.ident = "HDX18",
12009b10ae86STejun Heo 			.matches = {
12019b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12029b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12039b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
12049b10ae86STejun Heo 			},
12059deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
12069b10ae86STejun Heo 		},
1207cedc9bf9STejun Heo 		/*
1208cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
1209cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
121025985edcSLucas De Marchi 		 * work.  Between, there are V1.06, V2.06 and V3.03
1211cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
1212cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
12139deb3431STejun Heo 		 *
12149deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
1215cedc9bf9STejun Heo 		 */
1216cedc9bf9STejun Heo 		{
1217cedc9bf9STejun Heo 			.ident = "G725",
1218cedc9bf9STejun Heo 			.matches = {
1219cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
1220cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
1221cedc9bf9STejun Heo 			},
12229deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
1223cedc9bf9STejun Heo 		},
12249b10ae86STejun Heo 		{ }	/* terminate list */
12259b10ae86STejun Heo 	};
12269b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
12279deb3431STejun Heo 	int year, month, date;
12289deb3431STejun Heo 	char buf[9];
12299b10ae86STejun Heo 
12309b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
12319b10ae86STejun Heo 		return false;
12329b10ae86STejun Heo 
12339deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
12349deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
12359b10ae86STejun Heo 
12369deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
12379b10ae86STejun Heo }
12389b10ae86STejun Heo 
1239240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev)
1240240630e6SHans de Goede {
1241240630e6SHans de Goede 	static const struct dmi_system_id sysids[] = {
1242240630e6SHans de Goede 		/* Various Lenovo 50 series have LPM issues with older BIOSen */
1243240630e6SHans de Goede 		{
1244240630e6SHans de Goede 			.matches = {
1245240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1246240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"),
1247240630e6SHans de Goede 			},
1248240630e6SHans de Goede 			.driver_data = "20180406", /* 1.31 */
1249240630e6SHans de Goede 		},
1250240630e6SHans de Goede 		{
1251240630e6SHans de Goede 			.matches = {
1252240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1253240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"),
1254240630e6SHans de Goede 			},
1255240630e6SHans de Goede 			.driver_data = "20180420", /* 1.28 */
1256240630e6SHans de Goede 		},
1257240630e6SHans de Goede 		{
1258240630e6SHans de Goede 			.matches = {
1259240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1260240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"),
1261240630e6SHans de Goede 			},
1262240630e6SHans de Goede 			.driver_data = "20180315", /* 1.33 */
1263240630e6SHans de Goede 		},
1264240630e6SHans de Goede 		{
1265240630e6SHans de Goede 			.matches = {
1266240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1267240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"),
1268240630e6SHans de Goede 			},
1269240630e6SHans de Goede 			/*
1270240630e6SHans de Goede 			 * Note date based on release notes, 2.35 has been
1271240630e6SHans de Goede 			 * reported to be good, but I've been unable to get
1272240630e6SHans de Goede 			 * a hold of the reporter to get the DMI BIOS date.
1273240630e6SHans de Goede 			 * TODO: fix this.
1274240630e6SHans de Goede 			 */
1275240630e6SHans de Goede 			.driver_data = "20180310", /* 2.35 */
1276240630e6SHans de Goede 		},
1277240630e6SHans de Goede 		{ }	/* terminate list */
1278240630e6SHans de Goede 	};
1279240630e6SHans de Goede 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1280240630e6SHans de Goede 	int year, month, date;
1281240630e6SHans de Goede 	char buf[9];
1282240630e6SHans de Goede 
1283240630e6SHans de Goede 	if (!dmi)
1284240630e6SHans de Goede 		return false;
1285240630e6SHans de Goede 
1286240630e6SHans de Goede 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
1287240630e6SHans de Goede 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
1288240630e6SHans de Goede 
1289240630e6SHans de Goede 	return strcmp(buf, dmi->driver_data) < 0;
1290240630e6SHans de Goede }
1291240630e6SHans de Goede 
12925594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
12935594639aSTejun Heo {
12945594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
12955594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
12965594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
12975594639aSTejun Heo 		/*
12985594639aSTejun Heo 		 * There are several gigabyte boards which use
12995594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
13005594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
13015594639aSTejun Heo 		 * online but fail to answer properly to SRST or
13025594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
13035594639aSTejun Heo 		 * causing libata to retry quite a few times leading
13045594639aSTejun Heo 		 * to excessive detection delay.
13055594639aSTejun Heo 		 *
13065594639aSTejun Heo 		 * As these firmwares respond to the second reset try
13075594639aSTejun Heo 		 * with invalid device signature, considering unknown
13085594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
13095594639aSTejun Heo 		 */
13105594639aSTejun Heo 		{
13115594639aSTejun Heo 			.ident = "EP45-DQ6",
13125594639aSTejun Heo 			.matches = {
13135594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
13145594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
13155594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
13165594639aSTejun Heo 			},
13175594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
13185594639aSTejun Heo 		},
13195594639aSTejun Heo 		{
13205594639aSTejun Heo 			.ident = "EP45-DS5",
13215594639aSTejun Heo 			.matches = {
13225594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
13235594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
13245594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
13255594639aSTejun Heo 			},
13265594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
13275594639aSTejun Heo 		},
13285594639aSTejun Heo 		{ }	/* terminate list */
13295594639aSTejun Heo 	};
13305594639aSTejun Heo #undef ENCODE_BUSDEVFN
13315594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
13325594639aSTejun Heo 	unsigned int val;
13335594639aSTejun Heo 
13345594639aSTejun Heo 	if (!dmi)
13355594639aSTejun Heo 		return false;
13365594639aSTejun Heo 
13375594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
13385594639aSTejun Heo 
13395594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
13405594639aSTejun Heo }
13415594639aSTejun Heo 
13420cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev)
13430cf4a7d6SJacob Pan {
13440cf4a7d6SJacob Pan 	/* device with broken DEVSLP but still showing SDS capability */
13450cf4a7d6SJacob Pan 	static const struct pci_device_id ids[] = {
13460cf4a7d6SJacob Pan 		{ PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
13470cf4a7d6SJacob Pan 		{}
13480cf4a7d6SJacob Pan 	};
13490cf4a7d6SJacob Pan 
13500cf4a7d6SJacob Pan 	return pci_match_id(ids, pdev);
13510cf4a7d6SJacob Pan }
13520cf4a7d6SJacob Pan 
13538e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
1354f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
1355f80ae7e4STejun Heo {
1356f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
1357f80ae7e4STejun Heo 		/*
1358f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
1359f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
1360f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
1361f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
1362f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
1363f80ae7e4STejun Heo 		 * failures.  Filter it out.
1364f80ae7e4STejun Heo 		 */
1365f80ae7e4STejun Heo 		{
1366f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
1367f80ae7e4STejun Heo 			.matches = {
1368f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1369f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1370f80ae7e4STejun Heo 			},
1371f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1372f80ae7e4STejun Heo 		},
1373f80ae7e4STejun Heo 		{ }
1374f80ae7e4STejun Heo 	};
1375f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1376f80ae7e4STejun Heo 	unsigned int filter;
1377f80ae7e4STejun Heo 	int i;
1378f80ae7e4STejun Heo 
1379f80ae7e4STejun Heo 	if (!dmi)
1380f80ae7e4STejun Heo 		return;
1381f80ae7e4STejun Heo 
1382f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1383a44fec1fSJoe Perches 	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
1384f80ae7e4STejun Heo 		 filter, dmi->ident);
1385f80ae7e4STejun Heo 
1386f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1387f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1388f80ae7e4STejun Heo 		struct ata_link *link;
1389f80ae7e4STejun Heo 		struct ata_device *dev;
1390f80ae7e4STejun Heo 
1391f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1392f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1393f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1394f80ae7e4STejun Heo 	}
1395f80ae7e4STejun Heo }
13968e513217SMarkus Trippelsdorf #else
13978e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
13988e513217SMarkus Trippelsdorf {}
13998e513217SMarkus Trippelsdorf #endif
1400f80ae7e4STejun Heo 
14018bfd1743SSui Chen /*
14028bfd1743SSui Chen  * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected
14038bfd1743SSui Chen  * as DUMMY, or detected but eventually get a "link down" and never get up
14048bfd1743SSui Chen  * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the
14058bfd1743SSui Chen  * port_map may hold a value of 0x00.
14068bfd1743SSui Chen  *
14078bfd1743SSui Chen  * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports
14088bfd1743SSui Chen  * and can significantly reduce the occurrence of the problem.
14098bfd1743SSui Chen  *
14108bfd1743SSui Chen  * https://bugzilla.kernel.org/show_bug.cgi?id=189471
14118bfd1743SSui Chen  */
14128bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv,
14138bfd1743SSui Chen 				    struct pci_dev *pdev)
14148bfd1743SSui Chen {
14158bfd1743SSui Chen 	static const struct dmi_system_id sysids[] = {
14168bfd1743SSui Chen 		{
14178bfd1743SSui Chen 			.ident = "Acer Switch Alpha 12",
14188bfd1743SSui Chen 			.matches = {
14198bfd1743SSui Chen 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
14208bfd1743SSui Chen 				DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271")
14218bfd1743SSui Chen 			},
14228bfd1743SSui Chen 		},
14238bfd1743SSui Chen 		{ }
14248bfd1743SSui Chen 	};
14258bfd1743SSui Chen 
14268bfd1743SSui Chen 	if (dmi_check_system(sysids)) {
14278bfd1743SSui Chen 		dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n");
14288bfd1743SSui Chen 		if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) {
14298bfd1743SSui Chen 			hpriv->port_map = 0x7;
14308bfd1743SSui Chen 			hpriv->cap = 0xC734FF02;
14318bfd1743SSui Chen 		}
14328bfd1743SSui Chen 	}
14338bfd1743SSui Chen }
14348bfd1743SSui Chen 
1435d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64
1436d243bed3STirumalesh Chalamarla /*
1437d243bed3STirumalesh Chalamarla  * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
1438d243bed3STirumalesh Chalamarla  * Workaround is to make sure all pending IRQs are served before leaving
1439d243bed3STirumalesh Chalamarla  * handler.
1440d243bed3STirumalesh Chalamarla  */
1441d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
1442d243bed3STirumalesh Chalamarla {
1443d243bed3STirumalesh Chalamarla 	struct ata_host *host = dev_instance;
1444d243bed3STirumalesh Chalamarla 	struct ahci_host_priv *hpriv;
1445d243bed3STirumalesh Chalamarla 	unsigned int rc = 0;
1446d243bed3STirumalesh Chalamarla 	void __iomem *mmio;
1447d243bed3STirumalesh Chalamarla 	u32 irq_stat, irq_masked;
1448d243bed3STirumalesh Chalamarla 	unsigned int handled = 1;
1449d243bed3STirumalesh Chalamarla 
1450d243bed3STirumalesh Chalamarla 	VPRINTK("ENTER\n");
1451d243bed3STirumalesh Chalamarla 	hpriv = host->private_data;
1452d243bed3STirumalesh Chalamarla 	mmio = hpriv->mmio;
1453d243bed3STirumalesh Chalamarla 	irq_stat = readl(mmio + HOST_IRQ_STAT);
1454d243bed3STirumalesh Chalamarla 	if (!irq_stat)
1455d243bed3STirumalesh Chalamarla 		return IRQ_NONE;
1456d243bed3STirumalesh Chalamarla 
1457d243bed3STirumalesh Chalamarla 	do {
1458d243bed3STirumalesh Chalamarla 		irq_masked = irq_stat & hpriv->port_map;
1459d243bed3STirumalesh Chalamarla 		spin_lock(&host->lock);
1460d243bed3STirumalesh Chalamarla 		rc = ahci_handle_port_intr(host, irq_masked);
1461d243bed3STirumalesh Chalamarla 		if (!rc)
1462d243bed3STirumalesh Chalamarla 			handled = 0;
1463d243bed3STirumalesh Chalamarla 		writel(irq_stat, mmio + HOST_IRQ_STAT);
1464d243bed3STirumalesh Chalamarla 		irq_stat = readl(mmio + HOST_IRQ_STAT);
1465d243bed3STirumalesh Chalamarla 		spin_unlock(&host->lock);
1466d243bed3STirumalesh Chalamarla 	} while (irq_stat);
1467d243bed3STirumalesh Chalamarla 	VPRINTK("EXIT\n");
1468d243bed3STirumalesh Chalamarla 
1469d243bed3STirumalesh Chalamarla 	return IRQ_RETVAL(handled);
1470d243bed3STirumalesh Chalamarla }
1471d243bed3STirumalesh Chalamarla #endif
1472d243bed3STirumalesh Chalamarla 
1473aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar,
1474aecec8b6SChristoph Hellwig 		struct ahci_host_priv *hpriv)
1475aecec8b6SChristoph Hellwig {
1476aecec8b6SChristoph Hellwig 	int i, count = 0;
1477aecec8b6SChristoph Hellwig 	u32 cap;
1478aecec8b6SChristoph Hellwig 
1479aecec8b6SChristoph Hellwig 	/*
1480aecec8b6SChristoph Hellwig 	 * Check if this device might have remapped nvme devices.
1481aecec8b6SChristoph Hellwig 	 */
1482aecec8b6SChristoph Hellwig 	if (pdev->vendor != PCI_VENDOR_ID_INTEL ||
1483aecec8b6SChristoph Hellwig 	    pci_resource_len(pdev, bar) < SZ_512K ||
1484aecec8b6SChristoph Hellwig 	    bar != AHCI_PCI_BAR_STANDARD ||
1485aecec8b6SChristoph Hellwig 	    !(readl(hpriv->mmio + AHCI_VSCAP) & 1))
1486aecec8b6SChristoph Hellwig 		return;
1487aecec8b6SChristoph Hellwig 
1488aecec8b6SChristoph Hellwig 	cap = readq(hpriv->mmio + AHCI_REMAP_CAP);
1489aecec8b6SChristoph Hellwig 	for (i = 0; i < AHCI_MAX_REMAP; i++) {
1490aecec8b6SChristoph Hellwig 		if ((cap & (1 << i)) == 0)
1491aecec8b6SChristoph Hellwig 			continue;
1492aecec8b6SChristoph Hellwig 		if (readl(hpriv->mmio + ahci_remap_dcc(i))
1493aecec8b6SChristoph Hellwig 				!= PCI_CLASS_STORAGE_EXPRESS)
1494aecec8b6SChristoph Hellwig 			continue;
1495aecec8b6SChristoph Hellwig 
1496aecec8b6SChristoph Hellwig 		/* We've found a remapped device */
1497aecec8b6SChristoph Hellwig 		count++;
1498aecec8b6SChristoph Hellwig 	}
1499aecec8b6SChristoph Hellwig 
1500aecec8b6SChristoph Hellwig 	if (!count)
1501aecec8b6SChristoph Hellwig 		return;
1502aecec8b6SChristoph Hellwig 
1503aecec8b6SChristoph Hellwig 	dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count);
1504f723fa4eSChristoph Hellwig 	dev_warn(&pdev->dev,
1505f723fa4eSChristoph Hellwig 		 "Switch your BIOS from RAID to AHCI mode to use them.\n");
1506f723fa4eSChristoph Hellwig 
1507f723fa4eSChristoph Hellwig 	/*
1508f723fa4eSChristoph Hellwig 	 * Don't rely on the msi-x capability in the remap case,
1509f723fa4eSChristoph Hellwig 	 * share the legacy interrupt across ahci and remapped devices.
1510f723fa4eSChristoph Hellwig 	 */
1511f723fa4eSChristoph Hellwig 	hpriv->flags |= AHCI_HFLAG_NO_MSI;
1512aecec8b6SChristoph Hellwig }
1513aecec8b6SChristoph Hellwig 
15140b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port)
1515ee2aad42SRobert Richter {
15160b9e2988SChristoph Hellwig 	return pci_irq_vector(to_pci_dev(host->dev), port);
1517ee2aad42SRobert Richter }
1518ee2aad42SRobert Richter 
1519a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
15207b92b4f6SAlexander Gordeev 			struct ahci_host_priv *hpriv)
15215ca72c4fSAlexander Gordeev {
15220b9e2988SChristoph Hellwig 	int nvec;
15235ca72c4fSAlexander Gordeev 
15247b92b4f6SAlexander Gordeev 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
1525a1c82311SRobert Richter 		return -ENODEV;
15267b92b4f6SAlexander Gordeev 
15275ca72c4fSAlexander Gordeev 	/*
15287b92b4f6SAlexander Gordeev 	 * If number of MSIs is less than number of ports then Sharing Last
15297b92b4f6SAlexander Gordeev 	 * Message mode could be enforced. In this case assume that advantage
15307b92b4f6SAlexander Gordeev 	 * of multipe MSIs is negated and use single MSI mode instead.
15315ca72c4fSAlexander Gordeev 	 */
153217a51f12SChristoph Hellwig 	if (n_ports > 1) {
15330b9e2988SChristoph Hellwig 		nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX,
15340b9e2988SChristoph Hellwig 				PCI_IRQ_MSIX | PCI_IRQ_MSI);
15350b9e2988SChristoph Hellwig 		if (nvec > 0) {
15360b9e2988SChristoph Hellwig 			if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) {
15370b9e2988SChristoph Hellwig 				hpriv->get_irq_vector = ahci_get_irq_vector;
1538c3ebd6a9SAlexander Gordeev 				hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
153921bfd1aaSRobert Richter 				return nvec;
1540a1c82311SRobert Richter 			}
1541a1c82311SRobert Richter 
1542d684a90dSDan Williams 			/*
154317a51f12SChristoph Hellwig 			 * Fallback to single MSI mode if the controller
154417a51f12SChristoph Hellwig 			 * enforced MRSM mode.
1545d684a90dSDan Williams 			 */
154617a51f12SChristoph Hellwig 			printk(KERN_INFO
154717a51f12SChristoph Hellwig 				"ahci: MRSM is on, fallback to single MSI\n");
15480b9e2988SChristoph Hellwig 			pci_free_irq_vectors(pdev);
15490b9e2988SChristoph Hellwig 		}
1550a478b097SChristoph Hellwig 	}
1551d684a90dSDan Williams 
15520b9e2988SChristoph Hellwig 	/*
15530b9e2988SChristoph Hellwig 	 * If the host is not capable of supporting per-port vectors, fall
15540b9e2988SChristoph Hellwig 	 * back to single MSI before finally attempting single MSI-X.
15550b9e2988SChristoph Hellwig 	 */
15560b9e2988SChristoph Hellwig 	nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
15570b9e2988SChristoph Hellwig 	if (nvec == 1)
1558a1c82311SRobert Richter 		return nvec;
15590b9e2988SChristoph Hellwig 	return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
15605ca72c4fSAlexander Gordeev }
15615ca72c4fSAlexander Gordeev 
1562b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap,
1563b1a9585cSSrinivas Pandruvada 					   struct ahci_host_priv *hpriv)
1564b1a9585cSSrinivas Pandruvada {
1565b1a9585cSSrinivas Pandruvada 	int policy = CONFIG_SATA_MOBILE_LPM_POLICY;
1566b1a9585cSSrinivas Pandruvada 
1567b1a9585cSSrinivas Pandruvada 
1568b1a9585cSSrinivas Pandruvada 	/* Ignore processing for non mobile platforms */
1569b1a9585cSSrinivas Pandruvada 	if (!(hpriv->flags & AHCI_HFLAG_IS_MOBILE))
1570b1a9585cSSrinivas Pandruvada 		return;
1571b1a9585cSSrinivas Pandruvada 
1572b1a9585cSSrinivas Pandruvada 	/* user modified policy via module param */
1573b1a9585cSSrinivas Pandruvada 	if (mobile_lpm_policy != -1) {
1574b1a9585cSSrinivas Pandruvada 		policy = mobile_lpm_policy;
1575b1a9585cSSrinivas Pandruvada 		goto update_policy;
1576b1a9585cSSrinivas Pandruvada 	}
1577b1a9585cSSrinivas Pandruvada 
1578b1a9585cSSrinivas Pandruvada #ifdef CONFIG_ACPI
1579b1a9585cSSrinivas Pandruvada 	if (policy > ATA_LPM_MED_POWER &&
1580b1a9585cSSrinivas Pandruvada 	    (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) {
1581b1a9585cSSrinivas Pandruvada 		if (hpriv->cap & HOST_CAP_PART)
1582b1a9585cSSrinivas Pandruvada 			policy = ATA_LPM_MIN_POWER_WITH_PARTIAL;
1583b1a9585cSSrinivas Pandruvada 		else if (hpriv->cap & HOST_CAP_SSC)
1584b1a9585cSSrinivas Pandruvada 			policy = ATA_LPM_MIN_POWER;
1585b1a9585cSSrinivas Pandruvada 	}
1586b1a9585cSSrinivas Pandruvada #endif
1587b1a9585cSSrinivas Pandruvada 
1588b1a9585cSSrinivas Pandruvada update_policy:
1589b1a9585cSSrinivas Pandruvada 	if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER)
1590b1a9585cSSrinivas Pandruvada 		ap->target_lpm_policy = policy;
1591b1a9585cSSrinivas Pandruvada }
1592b1a9585cSSrinivas Pandruvada 
1593c312ef17SDan Williams static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
1594c312ef17SDan Williams {
1595c312ef17SDan Williams 	const struct pci_device_id *id = pci_match_id(ahci_pci_tbl, pdev);
1596c312ef17SDan Williams 	u16 tmp16;
1597c312ef17SDan Williams 
1598c312ef17SDan Williams 	/*
1599c312ef17SDan Williams 	 * Only apply the 6-port PCS quirk for known legacy platforms.
1600c312ef17SDan Williams 	 */
1601c312ef17SDan Williams 	if (!id || id->vendor != PCI_VENDOR_ID_INTEL)
1602c312ef17SDan Williams 		return;
160309d6ac8dSDan Williams 
160409d6ac8dSDan Williams 	/* Skip applying the quirk on Denverton and beyond */
160509d6ac8dSDan Williams 	if (((enum board_ids) id->driver_data) >= board_ahci_pcs7)
1606c312ef17SDan Williams 		return;
1607c312ef17SDan Williams 
1608c312ef17SDan Williams 	/*
1609c312ef17SDan Williams 	 * port_map is determined from PORTS_IMPL PCI register which is
1610c312ef17SDan Williams 	 * implemented as write or write-once register.  If the register
1611c312ef17SDan Williams 	 * isn't programmed, ahci automatically generates it from number
1612c312ef17SDan Williams 	 * of ports, which is good enough for PCS programming. It is
1613c312ef17SDan Williams 	 * otherwise expected that platform firmware enables the ports
1614c312ef17SDan Williams 	 * before the OS boots.
1615c312ef17SDan Williams 	 */
1616c312ef17SDan Williams 	pci_read_config_word(pdev, PCS_6, &tmp16);
1617c312ef17SDan Williams 	if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
1618c312ef17SDan Williams 		tmp16 |= hpriv->port_map;
1619c312ef17SDan Williams 		pci_write_config_word(pdev, PCS_6, tmp16);
1620c312ef17SDan Williams 	}
1621c312ef17SDan Williams }
1622c312ef17SDan Williams 
1623c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1624c6fd2807SJeff Garzik {
1625e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1626e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
16274447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
162824dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1629c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
16304447d351STejun Heo 	struct ata_host *host;
1631c3ebd6a9SAlexander Gordeev 	int n_ports, i, rc;
1632318893e1SAlessandro Rubini 	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
1633c6fd2807SJeff Garzik 
1634c6fd2807SJeff Garzik 	VPRINTK("ENTER\n");
1635c6fd2807SJeff Garzik 
1636b429dd59SJustin P. Mattock 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1637c6fd2807SJeff Garzik 
163806296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1639c6fd2807SJeff Garzik 
16405b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
16415b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
16425b66c829SAlan Cox 	   AHCI stays out of the way */
16435b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
16445b66c829SAlan Cox 		return -ENODEV;
16455b66c829SAlan Cox 
1646cb85696dSJames Laird 	/* Apple BIOS on MCP89 prevents us using AHCI */
1647cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
1648cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
1649c6353b45STejun Heo 
16507a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
16517a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
16527a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
16537a02267eSMark Nelson 	 */
16547a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
1655a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1656a44fec1fSJoe Perches 			 "PDC42819 can only drive SATA devices with this driver\n");
16577a02267eSMark Nelson 
1658b7ae128dSRobert Richter 	/* Some devices use non-standard BARs */
1659318893e1SAlessandro Rubini 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
1660318893e1SAlessandro Rubini 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
16617f9c9f8eSHugh Daschbach 	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
16627f9c9f8eSHugh Daschbach 		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
1663b1314e3fSRadha Mohan Chintakuntla 	else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) {
1664b1314e3fSRadha Mohan Chintakuntla 		if (pdev->device == 0xa01c)
1665b7ae128dSRobert Richter 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM;
1666b1314e3fSRadha Mohan Chintakuntla 		if (pdev->device == 0xa084)
1667b1314e3fSRadha Mohan Chintakuntla 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5;
1668b1314e3fSRadha Mohan Chintakuntla 	}
1669318893e1SAlessandro Rubini 
16704447d351STejun Heo 	/* acquire resources */
167124dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1672c6fd2807SJeff Garzik 	if (rc)
1673c6fd2807SJeff Garzik 		return rc;
1674c6fd2807SJeff Garzik 
1675c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1676c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1677c4f7792cSTejun Heo 		u8 map;
1678c4f7792cSTejun Heo 
1679c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1680c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1681c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1682c4f7792cSTejun Heo 		 */
1683c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1684c4f7792cSTejun Heo 		if (map & 0x3) {
1685a44fec1fSJoe Perches 			dev_info(&pdev->dev,
1686a44fec1fSJoe Perches 				 "controller is in combined mode, can't enable AHCI mode\n");
1687c4f7792cSTejun Heo 			return -ENODEV;
1688c4f7792cSTejun Heo 		}
1689c4f7792cSTejun Heo 	}
1690c4f7792cSTejun Heo 
16916fec8871SPaul Bolle 	/* AHCI controllers often implement SFF compatible interface.
16926fec8871SPaul Bolle 	 * Grab all PCI BARs just in case.
16936fec8871SPaul Bolle 	 */
16946fec8871SPaul Bolle 	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
16956fec8871SPaul Bolle 	if (rc == -EBUSY)
16966fec8871SPaul Bolle 		pcim_pin_device(pdev);
16976fec8871SPaul Bolle 	if (rc)
16986fec8871SPaul Bolle 		return rc;
16996fec8871SPaul Bolle 
170024dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
170124dc5f33STejun Heo 	if (!hpriv)
170224dc5f33STejun Heo 		return -ENOMEM;
1703417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1704417a1a6dSTejun Heo 
1705e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1706e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1707e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1708e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1709e297d99eSTejun Heo 
1710e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1711e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1712e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1713e427fe04SShane Huang 
17142fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
17152fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
17162fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
171758a09b38SShane Huang 
1718318893e1SAlessandro Rubini 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
1719d8993349SAnton Vorontsov 
1720aecec8b6SChristoph Hellwig 	/* detect remapped nvme devices */
1721aecec8b6SChristoph Hellwig 	ahci_remap_check(pdev, ahci_pci_bar, hpriv);
1722aecec8b6SChristoph Hellwig 
17230cf4a7d6SJacob Pan 	/* must set flag prior to save config in order to take effect */
17240cf4a7d6SJacob Pan 	if (ahci_broken_devslp(pdev))
17250cf4a7d6SJacob Pan 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
17260cf4a7d6SJacob Pan 
1727d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64
1728d243bed3STirumalesh Chalamarla 	if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
1729d243bed3STirumalesh Chalamarla 		hpriv->irq_handler = ahci_thunderx_irq_handler;
1730d243bed3STirumalesh Chalamarla #endif
1731d243bed3STirumalesh Chalamarla 
17324447d351STejun Heo 	/* save initial config */
1733394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1734c6fd2807SJeff Garzik 
1735c312ef17SDan Williams 	/*
1736c312ef17SDan Williams 	 * If platform firmware failed to enable ports, try to enable
1737c312ef17SDan Williams 	 * them here.
1738c312ef17SDan Williams 	 */
1739c312ef17SDan Williams 	ahci_intel_pcs_quirk(pdev, hpriv);
1740c312ef17SDan Williams 
17414447d351STejun Heo 	/* prepare host */
1742453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1743453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
174483f2b963STejun Heo 		/*
174583f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
174683f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
174783f2b963STejun Heo 		 * capability, but it seems to be broken on some
174883f2b963STejun Heo 		 * chipsets including NVIDIAs.
174983f2b963STejun Heo 		 */
175083f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1751453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
175240fb59e7SMarc Carino 
175340fb59e7SMarc Carino 		/*
175440fb59e7SMarc Carino 		 * All AHCI controllers should be forward-compatible
175540fb59e7SMarc Carino 		 * with the new auxiliary field. This code should be
175640fb59e7SMarc Carino 		 * conditionalized if any buggy AHCI controllers are
175740fb59e7SMarc Carino 		 * encountered.
175840fb59e7SMarc Carino 		 */
175940fb59e7SMarc Carino 		pi.flags |= ATA_FLAG_FPDMA_AUX;
1760453d3131SRobert Hancock 	}
17614447d351STejun Heo 
17627d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
17637d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
17647d50b60bSTejun Heo 
17650cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
176618f7ba4cSKristen Carlson Accardi 
17671fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
17681fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
17691fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
17701fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
17711fd68434SRafael J. Wysocki 	}
17721fd68434SRafael J. Wysocki 
1773240630e6SHans de Goede 	if (ahci_broken_lpm(pdev)) {
1774240630e6SHans de Goede 		pi.flags |= ATA_FLAG_NO_LPM;
1775240630e6SHans de Goede 		dev_warn(&pdev->dev,
1776240630e6SHans de Goede 			 "BIOS update required for Link Power Management support\n");
1777240630e6SHans de Goede 	}
1778240630e6SHans de Goede 
17799b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
17809b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
1781a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
17829b10ae86STejun Heo 			 "BIOS update required for suspend/resume\n");
17839b10ae86STejun Heo 	}
17849b10ae86STejun Heo 
17855594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
17865594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
17875594639aSTejun Heo 		dev_info(&pdev->dev,
17885594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
17895594639aSTejun Heo 	}
17905594639aSTejun Heo 
17918bfd1743SSui Chen 
17928bfd1743SSui Chen 	/* Acer SA5-271 workaround modifies private_data */
17938bfd1743SSui Chen 	acer_sa5_271_workaround(hpriv, pdev);
17948bfd1743SSui Chen 
1795837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1796837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1797837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1798837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1799837f5f8fSTejun Heo 	 */
1800837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1801837f5f8fSTejun Heo 
1802837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
18034447d351STejun Heo 	if (!host)
18044447d351STejun Heo 		return -ENOMEM;
18054447d351STejun Heo 	host->private_data = hpriv;
18060b9e2988SChristoph Hellwig 
18070b9e2988SChristoph Hellwig 	if (ahci_init_msi(pdev, n_ports, hpriv) < 0) {
18080b9e2988SChristoph Hellwig 		/* legacy intx interrupts */
18090b9e2988SChristoph Hellwig 		pci_intx(pdev, 1);
18100b9e2988SChristoph Hellwig 	}
18110ce57f8aSChristoph Hellwig 	hpriv->irq = pci_irq_vector(pdev, 0);
181221bfd1aaSRobert Richter 
1813f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1814886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1815f3d7f23fSArjan van de Ven 	else
1816d2782d96SJingoo Han 		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
1817886ad09fSArjan van de Ven 
181818f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
181918f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
182018f7ba4cSKristen Carlson Accardi 
18214447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
18224447d351STejun Heo 		struct ata_port *ap = host->ports[i];
18234447d351STejun Heo 
1824318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
1825318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar,
1826cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
1827cbcdd875STejun Heo 
182818f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
182918f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
1830008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
183118f7ba4cSKristen Carlson Accardi 
1832b1a9585cSSrinivas Pandruvada 		ahci_update_initial_lpm_policy(ap, hpriv);
183318f7ba4cSKristen Carlson Accardi 
1834dab632e8SJeff Garzik 		/* disabled/not-implemented port */
1835350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
1836dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
18374447d351STejun Heo 	}
1838c6fd2807SJeff Garzik 
1839edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
1840edc93052STejun Heo 	ahci_p5wdh_workaround(host);
1841edc93052STejun Heo 
1842f80ae7e4STejun Heo 	/* apply gtf filter quirk */
1843f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
1844f80ae7e4STejun Heo 
1845c6fd2807SJeff Garzik 	/* initialize adapter */
18464447d351STejun Heo 	rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
1847c6fd2807SJeff Garzik 	if (rc)
184824dc5f33STejun Heo 		return rc;
1849c6fd2807SJeff Garzik 
1850c312ef17SDan Williams 	rc = ahci_reset_controller(host);
18514447d351STejun Heo 	if (rc)
18524447d351STejun Heo 		return rc;
1853c6fd2807SJeff Garzik 
1854781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
1855439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
1856c6fd2807SJeff Garzik 
18574447d351STejun Heo 	pci_set_master(pdev);
18585ca72c4fSAlexander Gordeev 
185902e53293SMika Westerberg 	rc = ahci_host_activate(host, &ahci_sht);
186002e53293SMika Westerberg 	if (rc)
186102e53293SMika Westerberg 		return rc;
186202e53293SMika Westerberg 
186302e53293SMika Westerberg 	pm_runtime_put_noidle(&pdev->dev);
186402e53293SMika Westerberg 	return 0;
186502e53293SMika Westerberg }
186602e53293SMika Westerberg 
186702e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev)
186802e53293SMika Westerberg {
186902e53293SMika Westerberg 	pm_runtime_get_noresume(&pdev->dev);
187002e53293SMika Westerberg 	ata_pci_remove_one(pdev);
1871c6fd2807SJeff Garzik }
1872c6fd2807SJeff Garzik 
18732fc75da0SAxel Lin module_pci_driver(ahci_pci_driver);
1874c6fd2807SJeff Garzik 
1875c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
1876c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
1877c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
1878c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
1879c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
1880