xref: /openbmc/linux/drivers/ata/ahci.c (revision 7d523bdc303afbdddff48df6770866118fe19309)
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 */
59*7d523bdcSHanna Hawa 	board_ahci_al,
60dbfe8ef5SDan Williams 	board_ahci_avn,
61441577efSTejun Heo 	board_ahci_mcp65,
6283f2b963STejun Heo 	board_ahci_mcp77,
6383f2b963STejun Heo 	board_ahci_mcp89,
64441577efSTejun Heo 	board_ahci_mv,
65441577efSTejun Heo 	board_ahci_sb600,
66441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
67441577efSTejun Heo 	board_ahci_vt8251,
68441577efSTejun Heo 
69c312ef17SDan Williams 	/*
70c312ef17SDan Williams 	 * board IDs for Intel chipsets that support more than 6 ports
71c312ef17SDan Williams 	 * *and* end up needing the PCS quirk.
72c312ef17SDan Williams 	 */
73c312ef17SDan Williams 	board_ahci_pcs7,
74c312ef17SDan Williams 
75441577efSTejun Heo 	/* aliases */
76441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
77441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
78441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
7983f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
80c6fd2807SJeff Garzik };
81c6fd2807SJeff Garzik 
82c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
8302e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *dev);
84a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
85a1efdabaSTejun Heo 				 unsigned long deadline);
86dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
87dbfe8ef5SDan Williams 			      unsigned long deadline);
88cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
89cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev);
90a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
91a1efdabaSTejun Heo 				unsigned long deadline);
9202e53293SMika Westerberg #ifdef CONFIG_PM
9302e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev);
9402e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev);
95f1d848f9SMika Westerberg #ifdef CONFIG_PM_SLEEP
96f1d848f9SMika Westerberg static int ahci_pci_device_suspend(struct device *dev);
97f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev);
98438ac6d5STejun Heo #endif
9902e53293SMika Westerberg #endif /* CONFIG_PM */
100c6fd2807SJeff Garzik 
101fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = {
102fad16e7aSTejun Heo 	AHCI_SHT("ahci"),
103fad16e7aSTejun Heo };
104fad16e7aSTejun Heo 
105029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
106029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
107a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
108ad616ffbSTejun Heo };
109ad616ffbSTejun Heo 
110029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
111029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
112a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
113edc93052STejun Heo };
114edc93052STejun Heo 
115dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = {
116dbfe8ef5SDan Williams 	.inherits		= &ahci_ops,
117dbfe8ef5SDan Williams 	.hardreset		= ahci_avn_hardreset,
118dbfe8ef5SDan Williams };
119dbfe8ef5SDan Williams 
120c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
121441577efSTejun Heo 	/* by features */
122facb8fa6SJeffrin Jose 	[board_ahci] = {
1231188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
12414bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
125469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
126c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
127c6fd2807SJeff Garzik 	},
128facb8fa6SJeffrin Jose 	[board_ahci_ign_iferr] = {
129417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
130417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
13114bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
132469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
13341669553STejun Heo 		.port_ops	= &ahci_ops,
13441669553STejun Heo 	},
135ebb82e3cSHans de Goede 	[board_ahci_mobile] = {
136ebb82e3cSHans de Goede 		AHCI_HFLAGS	(AHCI_HFLAG_IS_MOBILE),
137ebb82e3cSHans de Goede 		.flags		= AHCI_FLAG_COMMON,
138ebb82e3cSHans de Goede 		.pio_mask	= ATA_PIO4,
139ebb82e3cSHans de Goede 		.udma_mask	= ATA_UDMA6,
140ebb82e3cSHans de Goede 		.port_ops	= &ahci_ops,
141ebb82e3cSHans de Goede 	},
14266a7cbc3STejun Heo 	[board_ahci_nomsi] = {
14366a7cbc3STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_MSI),
14466a7cbc3STejun Heo 		.flags		= AHCI_FLAG_COMMON,
14566a7cbc3STejun Heo 		.pio_mask	= ATA_PIO4,
14666a7cbc3STejun Heo 		.udma_mask	= ATA_UDMA6,
14766a7cbc3STejun Heo 		.port_ops	= &ahci_ops,
14866a7cbc3STejun Heo 	},
14967809f85SLevente Kurusa 	[board_ahci_noncq] = {
15067809f85SLevente Kurusa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ),
15167809f85SLevente Kurusa 		.flags		= AHCI_FLAG_COMMON,
15267809f85SLevente Kurusa 		.pio_mask	= ATA_PIO4,
15367809f85SLevente Kurusa 		.udma_mask	= ATA_UDMA6,
15467809f85SLevente Kurusa 		.port_ops	= &ahci_ops,
15567809f85SLevente Kurusa 	},
156facb8fa6SJeffrin Jose 	[board_ahci_nosntf] = {
157441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
158441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
159441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
160441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
161441577efSTejun Heo 		.port_ops	= &ahci_ops,
162441577efSTejun Heo 	},
163facb8fa6SJeffrin Jose 	[board_ahci_yes_fbs] = {
1645f173107STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),
1655f173107STejun Heo 		.flags		= AHCI_FLAG_COMMON,
1665f173107STejun Heo 		.pio_mask	= ATA_PIO4,
1675f173107STejun Heo 		.udma_mask	= ATA_UDMA6,
1685f173107STejun Heo 		.port_ops	= &ahci_ops,
1695f173107STejun Heo 	},
170441577efSTejun Heo 	/* by chipsets */
171*7d523bdcSHanna Hawa 	[board_ahci_al] = {
172*7d523bdcSHanna Hawa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_MSI),
173*7d523bdcSHanna Hawa 		.flags		= AHCI_FLAG_COMMON,
174*7d523bdcSHanna Hawa 		.pio_mask	= ATA_PIO4,
175*7d523bdcSHanna Hawa 		.udma_mask	= ATA_UDMA6,
176*7d523bdcSHanna Hawa 		.port_ops	= &ahci_ops,
177*7d523bdcSHanna Hawa 	},
178dbfe8ef5SDan Williams 	[board_ahci_avn] = {
179dbfe8ef5SDan Williams 		.flags		= AHCI_FLAG_COMMON,
180dbfe8ef5SDan Williams 		.pio_mask	= ATA_PIO4,
181dbfe8ef5SDan Williams 		.udma_mask	= ATA_UDMA6,
182dbfe8ef5SDan Williams 		.port_ops	= &ahci_avn_ops,
183dbfe8ef5SDan Williams 	},
184facb8fa6SJeffrin Jose 	[board_ahci_mcp65] = {
18583f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
18683f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
187ae01b249STejun Heo 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
18883f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
18983f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
19083f2b963STejun Heo 		.port_ops	= &ahci_ops,
19183f2b963STejun Heo 	},
192facb8fa6SJeffrin Jose 	[board_ahci_mcp77] = {
19383f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
19483f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
19583f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
19683f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
19783f2b963STejun Heo 		.port_ops	= &ahci_ops,
19883f2b963STejun Heo 	},
199facb8fa6SJeffrin Jose 	[board_ahci_mcp89] = {
20083f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
201441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
202441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
203441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
204441577efSTejun Heo 		.port_ops	= &ahci_ops,
205441577efSTejun Heo 	},
206facb8fa6SJeffrin Jose 	[board_ahci_mv] = {
207441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
208441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
2099cbe056fSSergei Shtylyov 		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
210441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
211441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
212441577efSTejun Heo 		.port_ops	= &ahci_ops,
213441577efSTejun Heo 	},
214facb8fa6SJeffrin Jose 	[board_ahci_sb600] = {
215417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
2162fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
2172fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
218417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
21914bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
220469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
221345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
22255a61604SConke Hu 	},
223facb8fa6SJeffrin Jose 	[board_ahci_sb700] = {	/* for SB700 and SB800 */
224bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
225e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
22614bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
227e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
228345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
229e39fc8c9SShane Huang 	},
230facb8fa6SJeffrin Jose 	[board_ahci_vt8251] = {
231441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
232e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
23314bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
234e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
235441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
2361b677afdSShaohua Li 	},
237c312ef17SDan Williams 	[board_ahci_pcs7] = {
238c312ef17SDan Williams 		.flags		= AHCI_FLAG_COMMON,
239c312ef17SDan Williams 		.pio_mask	= ATA_PIO4,
240c312ef17SDan Williams 		.udma_mask	= ATA_UDMA6,
241c312ef17SDan Williams 		.port_ops	= &ahci_ops,
242c312ef17SDan Williams 	},
243c6fd2807SJeff Garzik };
244c6fd2807SJeff Garzik 
245c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
246c6fd2807SJeff Garzik 	/* Intel */
24754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
24854bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
24954bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
25054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
25154bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
25282490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
25354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
25454bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
25554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
25654bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2577a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2581b677afdSShaohua Li 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
2597a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2607a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2617a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2627a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2637a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2647a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2657a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2667a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
267ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci_mobile }, /* ICH9M */
268ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci_mobile }, /* ICH9M */
269ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci_mobile }, /* ICH9M */
270ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci_mobile }, /* ICH9M */
271ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci_mobile }, /* ICH9M */
2727a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
273ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci_mobile }, /* ICH9M */
274d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
275d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
27616ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
277b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
27816ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
279c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
280c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
281adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
2828e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
283ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci_mobile }, /* PCH M AHCI */
284adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
285ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_mobile }, /* PCH M RAID */
286c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
287c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci_pcs7 }, /* DNV AHCI */
288c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci_pcs7 }, /* DNV AHCI */
289c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b2), board_ahci_pcs7 }, /* DNV AHCI */
290c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b3), board_ahci_pcs7 }, /* DNV AHCI */
291c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b4), board_ahci_pcs7 }, /* DNV AHCI */
292c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b5), board_ahci_pcs7 }, /* DNV AHCI */
293c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b6), board_ahci_pcs7 }, /* DNV AHCI */
294c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b7), board_ahci_pcs7 }, /* DNV AHCI */
295c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19bE), board_ahci_pcs7 }, /* DNV AHCI */
296c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19bF), board_ahci_pcs7 }, /* DNV AHCI */
297c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c0), board_ahci_pcs7 }, /* DNV AHCI */
298c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c1), board_ahci_pcs7 }, /* DNV AHCI */
299c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c2), board_ahci_pcs7 }, /* DNV AHCI */
300c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c3), board_ahci_pcs7 }, /* DNV AHCI */
301c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c4), board_ahci_pcs7 }, /* DNV AHCI */
302c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c5), board_ahci_pcs7 }, /* DNV AHCI */
303c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c6), board_ahci_pcs7 }, /* DNV AHCI */
304c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c7), board_ahci_pcs7 }, /* DNV AHCI */
305c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci_pcs7 }, /* DNV AHCI */
306c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci_pcs7 }, /* DNV AHCI */
3075623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
308ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci_mobile }, /* CPT M AHCI */
3095623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
310ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci_mobile }, /* CPT M RAID */
3115623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
3125623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
313992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
314992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
315992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
31664a3903dSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
317a4a461a6SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
318181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
319ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci_mobile }, /* Panther M AHCI */
320181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
321181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
322181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
323ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci_mobile }, /* Panther M RAID */
3242cab7a4cSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
325ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
326ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci_mobile }, /* Lynx M AHCI */
327ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
328ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci_mobile }, /* Lynx M RAID */
329ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
330ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci_mobile }, /* Lynx M RAID */
331ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
332ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_mobile }, /* Lynx M RAID */
333ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci_mobile }, /* Lynx LP AHCI */
334ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci_mobile }, /* Lynx LP AHCI */
335ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci_mobile }, /* Lynx LP RAID */
336ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c05), board_ahci_mobile }, /* Lynx LP RAID */
337ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c06), board_ahci_mobile }, /* Lynx LP RAID */
338ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci_mobile }, /* Lynx LP RAID */
339ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_mobile }, /* Lynx LP RAID */
340ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_mobile }, /* Lynx LP RAID */
3414544e403SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_mobile }, /* Cannon Lake PCH-LP AHCI */
34229e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
34329e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
34429e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
34529e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
34629e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
34729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
34829e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
34929e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
350dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */
351dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */
352dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */
353dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */
354dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */
355dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
356dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
357dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
358efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
359efda332cSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
360151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
361151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
362151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
363151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
364151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
365151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
366151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
367151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
3681cfc7df3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
369ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci_mobile }, /* Wildcat LP AHCI */
370ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci_mobile }, /* Wildcat LP RAID */
371ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci_mobile }, /* Wildcat LP RAID */
372ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_mobile }, /* Wildcat LP RAID */
3731b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
374ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci_mobile }, /* 9 Series M AHCI */
3751b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
376ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci_mobile }, /* 9 Series M RAID */
3771b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
378ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci_mobile }, /* 9 Series M RAID */
3791b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
380ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_mobile }, /* 9 Series M RAID */
381ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9d03), board_ahci_mobile }, /* Sunrise LP AHCI */
382ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9d05), board_ahci_mobile }, /* Sunrise LP RAID */
383ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x9d07), board_ahci_mobile }, /* Sunrise LP RAID */
384c5967b79SCharles_Rose@Dell.com 	{ PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */
385ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0xa103), board_ahci_mobile }, /* Sunrise M AHCI */
386690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
387c5967b79SCharles_Rose@Dell.com 	{ PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */
388ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci_mobile }, /* Sunrise M RAID */
389690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
3904d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
391f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
3924d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
393f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
3944d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
3954d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
396f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
397f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
3984d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
3994d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
400f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
401f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
402f919dde0SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */
403ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */
404ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */
405ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */
406ebb82e3cSHans de Goede 	{ PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */
407ba445791SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */
408c6fd2807SJeff Garzik 
409e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
410e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
411e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
4121fefb8fdSBen Hutchings 	/* JMicron 362B and 362C have an AHCI function with IDE class code */
4131fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
4141fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
41591f15fb3SZhang Rui 	/* May need to update quirk_jmicron_async_suspend() for additions */
416c6fd2807SJeff Garzik 
417c6fd2807SJeff Garzik 	/* ATI */
418c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
419e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
420e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
421e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
422e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
423e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
424e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
425c6fd2807SJeff Garzik 
426*7d523bdcSHanna Hawa 	/* Amazon's Annapurna Labs support */
427*7d523bdcSHanna Hawa 	{ PCI_DEVICE(PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031),
428*7d523bdcSHanna Hawa 		.class = PCI_CLASS_STORAGE_SATA_AHCI,
429*7d523bdcSHanna Hawa 		.class_mask = 0xffffff,
430*7d523bdcSHanna Hawa 		board_ahci_al },
431e2dd90b1SShane Huang 	/* AMD */
4325deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
433fafe5c3dSShane Huang 	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
434e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
435e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
436e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
437e2dd90b1SShane Huang 
438c6fd2807SJeff Garzik 	/* VIA */
43954bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
440bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
441c6fd2807SJeff Garzik 
442c6fd2807SJeff Garzik 	/* NVIDIA */
443e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
444e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
445e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
446e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
447e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
448e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
449e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
450e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
451441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
452441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
453441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
454441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
455441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
456441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
457441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
458441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
459441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
460441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
461441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
462441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
463441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
464441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
465441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
466441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
467441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
468441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
469441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
470441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
471441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
472441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
473441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
474441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
475441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
476441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
477441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
478441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
479441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
480441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
481441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
482441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
483441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
484441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
485441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
486441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
487441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
488441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
489441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
490441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
491441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
492441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
493441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
494441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
495441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
496441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
497441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
498441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
499441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
500441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
501441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
502441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
503441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
504441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
505441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
506441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
507441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
508441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
509441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
510441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
511441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
512441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
513441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
514441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
515441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
516441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
517441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
518441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
519441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
520441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
521441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
522441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
523441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
524441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
525441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
526441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
527c6fd2807SJeff Garzik 
528c6fd2807SJeff Garzik 	/* SiS */
52920e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
53020e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
53120e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
532c6fd2807SJeff Garzik 
533318893e1SAlessandro Rubini 	/* ST Microelectronics */
534318893e1SAlessandro Rubini 	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */
535318893e1SAlessandro Rubini 
536cd70c266SJeff Garzik 	/* Marvell */
537cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
538c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
53969fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
54010aca06cSAnssi Hannula 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
54110aca06cSAnssi Hannula 	  .class_mask = 0xffffff,
5425f173107STejun Heo 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
54369fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
544467b41c6SPer Jessen 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
545e098f5cbSSimon Guinot 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
546e098f5cbSSimon Guinot 			 PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
547e098f5cbSSimon Guinot 	  .driver_data = board_ahci_yes_fbs },			/* 88se9170 */
54869fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
549642d8925SMatt Johnson 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
550fcce9a35SGeorge Spelvin 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
551c5edfff9SMurali Karicheri 	  .driver_data = board_ahci_yes_fbs },			/* 88se9182 */
552c5edfff9SMurali Karicheri 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
553fcce9a35SGeorge Spelvin 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
55469fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
55517c60c6bSAlan Cox 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */
556754a292fSAndreas Schrägle 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0),
557754a292fSAndreas Schrägle 	  .driver_data = board_ahci_yes_fbs },
558a40cf3f3SJohannes Thumshirn 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), 	/* 88se91a2 */
559a40cf3f3SJohannes Thumshirn 	  .driver_data = board_ahci_yes_fbs },
56069fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
56150be5e36STejun Heo 	  .driver_data = board_ahci_yes_fbs },
5626d5278a6SSamir Benmendil 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
5636d5278a6SSamir Benmendil 	  .driver_data = board_ahci_yes_fbs },
56428b2182dSHans de Goede 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */
56528b2182dSHans de Goede 	  .driver_data = board_ahci_yes_fbs },
56628b2182dSHans de Goede 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */
567d2518365SJérôme Carretero 	  .driver_data = board_ahci_yes_fbs },
568cd70c266SJeff Garzik 
569c77a036bSMark Nelson 	/* Promise */
570c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
571b32bfc06SRomain Degez 	{ PCI_VDEVICE(PROMISE, 0x3781), board_ahci },   /* FastTrak TX8660 ahci-mode */
572c77a036bSMark Nelson 
573c9703765SKeng-Yu Lin 	/* Asmedia */
5747b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },	/* ASM1060 */
5757b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },	/* ASM1060 */
5767b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */
5777b4f6ecaSAlan Cox 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */
5780ce968f3SShawn Lin 	{ PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci },   /* ASM1061R */
5790ce968f3SShawn Lin 	{ PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci },   /* ASM1062R */
580c9703765SKeng-Yu Lin 
58167809f85SLevente Kurusa 	/*
58266a7cbc3STejun Heo 	 * Samsung SSDs found on some macbooks.  NCQ times out if MSI is
58366a7cbc3STejun Heo 	 * enabled.  https://bugzilla.kernel.org/show_bug.cgi?id=60731
58467809f85SLevente Kurusa 	 */
58566a7cbc3STejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
5862b21ef0aSTejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi },
58767809f85SLevente Kurusa 
5887f9c9f8eSHugh Daschbach 	/* Enmotus */
5897f9c9f8eSHugh Daschbach 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
5907f9c9f8eSHugh Daschbach 
591415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
592415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
593c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
594415ae2b5SJeff Garzik 
595c6fd2807SJeff Garzik 	{ }	/* terminate list */
596c6fd2807SJeff Garzik };
597c6fd2807SJeff Garzik 
598f1d848f9SMika Westerberg static const struct dev_pm_ops ahci_pci_pm_ops = {
599f1d848f9SMika Westerberg 	SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume)
60002e53293SMika Westerberg 	SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend,
60102e53293SMika Westerberg 			   ahci_pci_device_runtime_resume, NULL)
602f1d848f9SMika Westerberg };
603c6fd2807SJeff Garzik 
604c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
605c6fd2807SJeff Garzik 	.name			= DRV_NAME,
606c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
607c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
60802e53293SMika Westerberg 	.remove			= ahci_remove_one,
609f1d848f9SMika Westerberg 	.driver = {
610f1d848f9SMika Westerberg 		.pm		= &ahci_pci_pm_ops,
611f1d848f9SMika Westerberg 	},
612c6fd2807SJeff Garzik };
613c6fd2807SJeff Garzik 
6145219d653SJavier Martinez Canillas #if IS_ENABLED(CONFIG_PATA_MARVELL)
6155b66c829SAlan Cox static int marvell_enable;
6165b66c829SAlan Cox #else
6175b66c829SAlan Cox static int marvell_enable = 1;
6185b66c829SAlan Cox #endif
6195b66c829SAlan Cox module_param(marvell_enable, int, 0644);
6205b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
6215b66c829SAlan Cox 
622b1a9585cSSrinivas Pandruvada static int mobile_lpm_policy = -1;
623ebb82e3cSHans de Goede module_param(mobile_lpm_policy, int, 0644);
624ebb82e3cSHans de Goede MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
6255b66c829SAlan Cox 
626394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
627394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
628394d6e53SAnton Vorontsov {
629394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
630394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
6319a23c1d6SAntoine Tenart 		hpriv->force_port_map = 1;
632394d6e53SAnton Vorontsov 	}
633394d6e53SAnton Vorontsov 
634394d6e53SAnton Vorontsov 	/*
635394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
636394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
637394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
638394d6e53SAnton Vorontsov 	 */
639394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
640394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
6419a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0x3;
642394d6e53SAnton Vorontsov 		else
6439a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0xf;
644394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
645394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
646394d6e53SAnton Vorontsov 	}
647394d6e53SAnton Vorontsov 
648725c7b57SAntoine Ténart 	ahci_save_initial_config(&pdev->dev, hpriv);
649394d6e53SAnton Vorontsov }
650394d6e53SAnton Vorontsov 
651781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
652781d6550SAnton Vorontsov {
653781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
654781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
655781d6550SAnton Vorontsov 	void __iomem *port_mmio;
656781d6550SAnton Vorontsov 	u32 tmp;
657c40e7cb8SJose Alberto Reguero 	int mv;
6582bcd866bSJeff Garzik 
659417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
660c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
661c40e7cb8SJose Alberto Reguero 			mv = 2;
662c40e7cb8SJose Alberto Reguero 		else
663c40e7cb8SJose Alberto Reguero 			mv = 4;
664c40e7cb8SJose Alberto Reguero 		port_mmio = __ahci_port_base(host, mv);
665cd70c266SJeff Garzik 
666cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
667cd70c266SJeff Garzik 
668cd70c266SJeff Garzik 		/* clear port IRQ */
669cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
670cd70c266SJeff Garzik 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
671cd70c266SJeff Garzik 		if (tmp)
672cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
673cd70c266SJeff Garzik 	}
674cd70c266SJeff Garzik 
675781d6550SAnton Vorontsov 	ahci_init_controller(host);
676c6fd2807SJeff Garzik }
677c6fd2807SJeff Garzik 
678cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
679d4b2bab4STejun Heo 				 unsigned long deadline)
680ad616ffbSTejun Heo {
681cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
682039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
6839dadd45bSTejun Heo 	bool online;
684ad616ffbSTejun Heo 	int rc;
685ad616ffbSTejun Heo 
686ad616ffbSTejun Heo 	DPRINTK("ENTER\n");
687ad616ffbSTejun Heo 
688fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
689ad616ffbSTejun Heo 
690cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
6919dadd45bSTejun Heo 				 deadline, &online, NULL);
692ad616ffbSTejun Heo 
693039ece38SHans de Goede 	hpriv->start_engine(ap);
694ad616ffbSTejun Heo 
695ad616ffbSTejun Heo 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
696ad616ffbSTejun Heo 
697ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
698ad616ffbSTejun Heo 	 * request follow-up softreset.
699ad616ffbSTejun Heo 	 */
7009dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
701ad616ffbSTejun Heo }
702ad616ffbSTejun Heo 
703edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
704edc93052STejun Heo 				unsigned long deadline)
705edc93052STejun Heo {
706edc93052STejun Heo 	struct ata_port *ap = link->ap;
707edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
708039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
709edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
710edc93052STejun Heo 	struct ata_taskfile tf;
7119dadd45bSTejun Heo 	bool online;
712edc93052STejun Heo 	int rc;
713edc93052STejun Heo 
714fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
715edc93052STejun Heo 
716edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
717edc93052STejun Heo 	ata_tf_init(link->device, &tf);
7189bbb1b0eSSergei Shtylyov 	tf.command = ATA_BUSY;
719edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
720edc93052STejun Heo 
721edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
7229dadd45bSTejun Heo 				 deadline, &online, NULL);
723edc93052STejun Heo 
724039ece38SHans de Goede 	hpriv->start_engine(ap);
725edc93052STejun Heo 
726edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
727edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
728edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
729edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
730edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
731edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
732edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
733edc93052STejun Heo 	 *
734edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
735edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
736edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
737edc93052STejun Heo 	 * suffice while making probing snappish enough.
738edc93052STejun Heo 	 */
7399dadd45bSTejun Heo 	if (online) {
7409dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
7419dadd45bSTejun Heo 					  ahci_check_ready);
742edc93052STejun Heo 		if (rc)
74378d5ae39SShane Huang 			ahci_kick_engine(ap);
7449dadd45bSTejun Heo 	}
7459dadd45bSTejun Heo 	return rc;
746edc93052STejun Heo }
747edc93052STejun Heo 
748dbfe8ef5SDan Williams /*
749dbfe8ef5SDan Williams  * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports.
750dbfe8ef5SDan Williams  *
751dbfe8ef5SDan Williams  * It has been observed with some SSDs that the timing of events in the
752dbfe8ef5SDan Williams  * link synchronization phase can leave the port in a state that can not
753dbfe8ef5SDan Williams  * be recovered by a SATA-hard-reset alone.  The failing signature is
754dbfe8ef5SDan Williams  * SStatus.DET stuck at 1 ("Device presence detected but Phy
755dbfe8ef5SDan Williams  * communication not established").  It was found that unloading and
756dbfe8ef5SDan Williams  * reloading the driver when this problem occurs allows the drive
757dbfe8ef5SDan Williams  * connection to be recovered (DET advanced to 0x3).  The critical
758dbfe8ef5SDan Williams  * component of reloading the driver is that the port state machines are
759dbfe8ef5SDan Williams  * reset by bouncing "port enable" in the AHCI PCS configuration
760dbfe8ef5SDan Williams  * register.  So, reproduce that effect by bouncing a port whenever we
761dbfe8ef5SDan Williams  * see DET==1 after a reset.
762dbfe8ef5SDan Williams  */
763dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
764dbfe8ef5SDan Williams 			      unsigned long deadline)
765dbfe8ef5SDan Williams {
766dbfe8ef5SDan Williams 	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
767dbfe8ef5SDan Williams 	struct ata_port *ap = link->ap;
768dbfe8ef5SDan Williams 	struct ahci_port_priv *pp = ap->private_data;
769dbfe8ef5SDan Williams 	struct ahci_host_priv *hpriv = ap->host->private_data;
770dbfe8ef5SDan Williams 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
771dbfe8ef5SDan Williams 	unsigned long tmo = deadline - jiffies;
772dbfe8ef5SDan Williams 	struct ata_taskfile tf;
773dbfe8ef5SDan Williams 	bool online;
774dbfe8ef5SDan Williams 	int rc, i;
775dbfe8ef5SDan Williams 
776dbfe8ef5SDan Williams 	DPRINTK("ENTER\n");
777dbfe8ef5SDan Williams 
778fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
779dbfe8ef5SDan Williams 
780dbfe8ef5SDan Williams 	for (i = 0; i < 2; i++) {
781dbfe8ef5SDan Williams 		u16 val;
782dbfe8ef5SDan Williams 		u32 sstatus;
783dbfe8ef5SDan Williams 		int port = ap->port_no;
784dbfe8ef5SDan Williams 		struct ata_host *host = ap->host;
785dbfe8ef5SDan Williams 		struct pci_dev *pdev = to_pci_dev(host->dev);
786dbfe8ef5SDan Williams 
787dbfe8ef5SDan Williams 		/* clear D2H reception area to properly wait for D2H FIS */
788dbfe8ef5SDan Williams 		ata_tf_init(link->device, &tf);
789dbfe8ef5SDan Williams 		tf.command = ATA_BUSY;
790dbfe8ef5SDan Williams 		ata_tf_to_fis(&tf, 0, 0, d2h_fis);
791dbfe8ef5SDan Williams 
792dbfe8ef5SDan Williams 		rc = sata_link_hardreset(link, timing, deadline, &online,
793dbfe8ef5SDan Williams 				ahci_check_ready);
794dbfe8ef5SDan Williams 
795dbfe8ef5SDan Williams 		if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 ||
796dbfe8ef5SDan Williams 				(sstatus & 0xf) != 1)
797dbfe8ef5SDan Williams 			break;
798dbfe8ef5SDan Williams 
799dbfe8ef5SDan Williams 		ata_link_printk(link, KERN_INFO, "avn bounce port%d\n",
800dbfe8ef5SDan Williams 				port);
801dbfe8ef5SDan Williams 
802dbfe8ef5SDan Williams 		pci_read_config_word(pdev, 0x92, &val);
803dbfe8ef5SDan Williams 		val &= ~(1 << port);
804dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
805dbfe8ef5SDan Williams 		ata_msleep(ap, 1000);
806dbfe8ef5SDan Williams 		val |= 1 << port;
807dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
808dbfe8ef5SDan Williams 		deadline += tmo;
809dbfe8ef5SDan Williams 	}
810dbfe8ef5SDan Williams 
811dbfe8ef5SDan Williams 	hpriv->start_engine(ap);
812dbfe8ef5SDan Williams 
813dbfe8ef5SDan Williams 	if (online)
814dbfe8ef5SDan Williams 		*class = ahci_dev_classify(ap);
815dbfe8ef5SDan Williams 
816dbfe8ef5SDan Williams 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
817dbfe8ef5SDan Williams 	return rc;
818dbfe8ef5SDan Williams }
819dbfe8ef5SDan Williams 
820dbfe8ef5SDan Williams 
82102e53293SMika Westerberg #ifdef CONFIG_PM
82202e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host)
823c6fd2807SJeff Garzik {
8249b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
825d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
826c6fd2807SJeff Garzik 	u32 ctl;
827c6fd2807SJeff Garzik 
828c6fd2807SJeff Garzik 	/* AHCI spec rev1.1 section 8.3.3:
829c6fd2807SJeff Garzik 	 * Software must disable interrupts prior to requesting a
830c6fd2807SJeff Garzik 	 * transition of the HBA to D3 state.
831c6fd2807SJeff Garzik 	 */
832c6fd2807SJeff Garzik 	ctl = readl(mmio + HOST_CTL);
833c6fd2807SJeff Garzik 	ctl &= ~HOST_IRQ_EN;
834c6fd2807SJeff Garzik 	writel(ctl, mmio + HOST_CTL);
835c6fd2807SJeff Garzik 	readl(mmio + HOST_CTL); /* flush */
83602e53293SMika Westerberg }
837f1d848f9SMika Westerberg 
83802e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev)
83902e53293SMika Westerberg {
84002e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
84102e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
84202e53293SMika Westerberg 
84302e53293SMika Westerberg 	ahci_pci_disable_interrupts(host);
84402e53293SMika Westerberg 	return 0;
84502e53293SMika Westerberg }
84602e53293SMika Westerberg 
84702e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev)
84802e53293SMika Westerberg {
84902e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
85002e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
85102e53293SMika Westerberg 	int rc;
85202e53293SMika Westerberg 
853c312ef17SDan Williams 	rc = ahci_reset_controller(host);
85402e53293SMika Westerberg 	if (rc)
85502e53293SMika Westerberg 		return rc;
85602e53293SMika Westerberg 	ahci_pci_init_controller(host);
85702e53293SMika Westerberg 	return 0;
85802e53293SMika Westerberg }
85902e53293SMika Westerberg 
86002e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP
86102e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev)
86202e53293SMika Westerberg {
86302e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
86402e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
86502e53293SMika Westerberg 	struct ahci_host_priv *hpriv = host->private_data;
86602e53293SMika Westerberg 
86702e53293SMika Westerberg 	if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
86802e53293SMika Westerberg 		dev_err(&pdev->dev,
86902e53293SMika Westerberg 			"BIOS update required for suspend/resume\n");
87002e53293SMika Westerberg 		return -EIO;
87102e53293SMika Westerberg 	}
87202e53293SMika Westerberg 
87302e53293SMika Westerberg 	ahci_pci_disable_interrupts(host);
874f1d848f9SMika Westerberg 	return ata_host_suspend(host, PMSG_SUSPEND);
875c6fd2807SJeff Garzik }
876c6fd2807SJeff Garzik 
877f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev)
878c6fd2807SJeff Garzik {
879f1d848f9SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
8800a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
881c6fd2807SJeff Garzik 	int rc;
882c6fd2807SJeff Garzik 
883cb85696dSJames Laird 	/* Apple BIOS helpfully mangles the registers on resume */
884cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
885cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
886cb85696dSJames Laird 
887c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
888c312ef17SDan Williams 		rc = ahci_reset_controller(host);
889c6fd2807SJeff Garzik 		if (rc)
890c6fd2807SJeff Garzik 			return rc;
891c6fd2807SJeff Garzik 
892781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
893c6fd2807SJeff Garzik 	}
894c6fd2807SJeff Garzik 
895cca3974eSJeff Garzik 	ata_host_resume(host);
896c6fd2807SJeff Garzik 
897c6fd2807SJeff Garzik 	return 0;
898c6fd2807SJeff Garzik }
899438ac6d5STejun Heo #endif
900c6fd2807SJeff Garzik 
90102e53293SMika Westerberg #endif /* CONFIG_PM */
90202e53293SMika Westerberg 
9034447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
904c6fd2807SJeff Garzik {
905b1716871SChristoph Hellwig 	const int dma_bits = using_dac ? 64 : 32;
906c6fd2807SJeff Garzik 	int rc;
907c6fd2807SJeff Garzik 
908318893e1SAlessandro Rubini 	/*
909318893e1SAlessandro Rubini 	 * If the device fixup already set the dma_mask to some non-standard
910318893e1SAlessandro Rubini 	 * value, don't extend it here. This happens on STA2X11, for example.
911b1716871SChristoph Hellwig 	 *
912b1716871SChristoph Hellwig 	 * XXX: manipulating the DMA mask from platform code is completely
913b1716871SChristoph Hellwig 	 * bogus, platform code should use dev->bus_dma_mask instead..
914318893e1SAlessandro Rubini 	 */
915318893e1SAlessandro Rubini 	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
916318893e1SAlessandro Rubini 		return 0;
917318893e1SAlessandro Rubini 
918b1716871SChristoph Hellwig 	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits));
919b1716871SChristoph Hellwig 	if (rc)
920b1716871SChristoph Hellwig 		dev_err(&pdev->dev, "DMA enable failed\n");
921c6fd2807SJeff Garzik 	return rc;
922c6fd2807SJeff Garzik }
923c6fd2807SJeff Garzik 
924439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
925439fcaecSAnton Vorontsov {
926439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
927439fcaecSAnton Vorontsov 	u16 cc;
928439fcaecSAnton Vorontsov 	const char *scc_s;
929439fcaecSAnton Vorontsov 
930439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
931439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
932439fcaecSAnton Vorontsov 		scc_s = "IDE";
933439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
934439fcaecSAnton Vorontsov 		scc_s = "SATA";
935439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
936439fcaecSAnton Vorontsov 		scc_s = "RAID";
937439fcaecSAnton Vorontsov 	else
938439fcaecSAnton Vorontsov 		scc_s = "unknown";
939439fcaecSAnton Vorontsov 
940439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
941439fcaecSAnton Vorontsov }
942439fcaecSAnton Vorontsov 
943edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
944edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
945edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
946edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
947edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
948edc93052STejun Heo  * other configuration).
949edc93052STejun Heo  *
950edc93052STejun Heo  * When there's no device attached to the first downstream port of the
951edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
952edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
953edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
954edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
955edc93052STejun Heo  *
956edc93052STejun Heo  * The following function works around the problem by always using
957edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
958edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
959edc93052STejun Heo  * assumed without follow-up softreset.
960edc93052STejun Heo  */
961edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
962edc93052STejun Heo {
9631bd06867SMathias Krause 	static const struct dmi_system_id sysids[] = {
964edc93052STejun Heo 		{
965edc93052STejun Heo 			.ident = "P5W DH Deluxe",
966edc93052STejun Heo 			.matches = {
967edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
968edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
969edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
970edc93052STejun Heo 			},
971edc93052STejun Heo 		},
972edc93052STejun Heo 		{ }
973edc93052STejun Heo 	};
974edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
975edc93052STejun Heo 
976edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
977edc93052STejun Heo 	    dmi_check_system(sysids)) {
978edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
979edc93052STejun Heo 
980a44fec1fSJoe Perches 		dev_info(&pdev->dev,
981a44fec1fSJoe Perches 			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
982edc93052STejun Heo 
983edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
984edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
985edc93052STejun Heo 	}
986edc93052STejun Heo }
987edc93052STejun Heo 
988cb85696dSJames Laird /*
989cb85696dSJames Laird  * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
990cb85696dSJames Laird  * booting in BIOS compatibility mode.  We restore the registers but not ID.
991cb85696dSJames Laird  */
992cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
993cb85696dSJames Laird {
994cb85696dSJames Laird 	u32 val;
995cb85696dSJames Laird 
996cb85696dSJames Laird 	printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
997cb85696dSJames Laird 
998cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
999cb85696dSJames Laird 	val |= 1 << 0x1b;
1000cb85696dSJames Laird 	/* the following changes the device ID, but appears not to affect function */
1001cb85696dSJames Laird 	/* val = (val & ~0xf0000000) | 0x80000000; */
1002cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
1003cb85696dSJames Laird 
1004cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
1005cb85696dSJames Laird 	val |= 1 << 0xc;
1006cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
1007cb85696dSJames Laird 
1008cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x4a4, &val);
1009cb85696dSJames Laird 	val &= 0xff;
1010cb85696dSJames Laird 	val |= 0x01060100;
1011cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x4a4, val);
1012cb85696dSJames Laird 
1013cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
1014cb85696dSJames Laird 	val &= ~(1 << 0xc);
1015cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
1016cb85696dSJames Laird 
1017cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
1018cb85696dSJames Laird 	val &= ~(1 << 0x1b);
1019cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
1020cb85696dSJames Laird }
1021cb85696dSJames Laird 
1022cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev)
1023cb85696dSJames Laird {
1024cb85696dSJames Laird 	return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
1025cb85696dSJames Laird 		pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
1026cb85696dSJames Laird 		pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
1027cb85696dSJames Laird 		pdev->subsystem_device == 0xcb89;
1028cb85696dSJames Laird }
1029cb85696dSJames Laird 
10302fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
10312fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
103258a09b38SShane Huang {
103358a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
103403d783bfSTejun Heo 		/*
103503d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
103603d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
10372fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
10382fcad9d2STejun Heo 		 *
103903d783bfSTejun Heo 		 * Please read bko#9412 for more info.
104003d783bfSTejun Heo 		 */
104158a09b38SShane Huang 		{
104258a09b38SShane Huang 			.ident = "ASUS M2A-VM",
104358a09b38SShane Huang 			.matches = {
104458a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
104558a09b38SShane Huang 					  "ASUSTeK Computer INC."),
104658a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
104758a09b38SShane Huang 			},
104803d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
104958a09b38SShane Huang 		},
1050e65cc194SMark Nelson 		/*
1051e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
1052e65cc194SMark Nelson 		 * support 64bit DMA.
1053e65cc194SMark Nelson 		 *
1054e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
1055e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
1056e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
1057e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
1058e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
1059e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
1060e65cc194SMark Nelson 		 *
1061e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
1062e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
1063e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
1064e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
1065e65cc194SMark Nelson 		 */
1066e65cc194SMark Nelson 		{
1067e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
1068e65cc194SMark Nelson 			.matches = {
1069e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1070e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
1071e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
1072e65cc194SMark Nelson 			},
1073e65cc194SMark Nelson 		},
10743c4aa91fSMark Nelson 		/*
1075ff0173c1SMark Nelson 		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support
1076ff0173c1SMark Nelson 		 * 64bit DMA.
1077ff0173c1SMark Nelson 		 *
1078ff0173c1SMark Nelson 		 * This board also had the typo mentioned above in the
1079ff0173c1SMark Nelson 		 * Manufacturer DMI field (fixed in BIOS version 1.5), so
1080ff0173c1SMark Nelson 		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again.
1081ff0173c1SMark Nelson 		 */
1082ff0173c1SMark Nelson 		{
1083ff0173c1SMark Nelson 			.ident = "MSI K9AGM2",
1084ff0173c1SMark Nelson 			.matches = {
1085ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1086ff0173c1SMark Nelson 					  "MICRO-STAR INTER"),
1087ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"),
1088ff0173c1SMark Nelson 			},
1089ff0173c1SMark Nelson 		},
1090ff0173c1SMark Nelson 		/*
10913c4aa91fSMark Nelson 		 * All BIOS versions for the Asus M3A support 64bit DMA.
10923c4aa91fSMark Nelson 		 * (all release versions from 0301 to 1206 were tested)
10933c4aa91fSMark Nelson 		 */
10943c4aa91fSMark Nelson 		{
10953c4aa91fSMark Nelson 			.ident = "ASUS M3A",
10963c4aa91fSMark Nelson 			.matches = {
10973c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
10983c4aa91fSMark Nelson 					  "ASUSTeK Computer INC."),
10993c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
11003c4aa91fSMark Nelson 			},
11013c4aa91fSMark Nelson 		},
110258a09b38SShane Huang 		{ }
110358a09b38SShane Huang 	};
110403d783bfSTejun Heo 	const struct dmi_system_id *match;
11052fcad9d2STejun Heo 	int year, month, date;
11062fcad9d2STejun Heo 	char buf[9];
110758a09b38SShane Huang 
110803d783bfSTejun Heo 	match = dmi_first_match(sysids);
110958a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
111003d783bfSTejun Heo 	    !match)
111158a09b38SShane Huang 		return false;
111258a09b38SShane Huang 
1113e65cc194SMark Nelson 	if (!match->driver_data)
1114e65cc194SMark Nelson 		goto enable_64bit;
1115e65cc194SMark Nelson 
111603d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
111703d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
111803d783bfSTejun Heo 
1119e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
1120e65cc194SMark Nelson 		goto enable_64bit;
1121e65cc194SMark Nelson 	else {
1122a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
1123a44fec1fSJoe Perches 			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
1124a44fec1fSJoe Perches 			 match->ident);
11252fcad9d2STejun Heo 		return false;
11262fcad9d2STejun Heo 	}
1127e65cc194SMark Nelson 
1128e65cc194SMark Nelson enable_64bit:
1129a44fec1fSJoe Perches 	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
1130e65cc194SMark Nelson 	return true;
113158a09b38SShane Huang }
113258a09b38SShane Huang 
11331fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
11341fd68434SRafael J. Wysocki {
11351fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
11361fd68434SRafael J. Wysocki 		{
11371fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
11381fd68434SRafael J. Wysocki 			.matches = {
11391fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11401fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
11411fd68434SRafael J. Wysocki 			},
11421fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
11431fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
11441fd68434SRafael J. Wysocki 		},
1145d2f9c061SMaciej Rutecki 		{
1146d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
1147d2f9c061SMaciej Rutecki 			.matches = {
1148d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1149d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
1150d2f9c061SMaciej Rutecki 			},
1151d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
1152d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
1153d2f9c061SMaciej Rutecki 		},
11541fd68434SRafael J. Wysocki 
11551fd68434SRafael J. Wysocki 		{ }	/* terminate list */
11561fd68434SRafael J. Wysocki 	};
11571fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
11581fd68434SRafael J. Wysocki 
11591fd68434SRafael J. Wysocki 	if (dmi) {
11601fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
11611fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
11621fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
11631fd68434SRafael J. Wysocki 	}
11641fd68434SRafael J. Wysocki 
11651fd68434SRafael J. Wysocki 	return false;
11661fd68434SRafael J. Wysocki }
11671fd68434SRafael J. Wysocki 
11689b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
11699b10ae86STejun Heo {
11709b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
11719b10ae86STejun Heo 		/*
11729b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
11739b10ae86STejun Heo 		 * to the harddisk doesn't become online after
11749b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
11759deb3431STejun Heo 		 *
11769deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
11779deb3431STejun Heo 		 *
11789deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
11799deb3431STejun Heo 		 * apparently recycling both product and version
11809deb3431STejun Heo 		 * strings.
11819deb3431STejun Heo 		 *
11829deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
11839b10ae86STejun Heo 		 */
11849b10ae86STejun Heo 		{
11859b10ae86STejun Heo 			.ident = "dv4",
11869b10ae86STejun Heo 			.matches = {
11879b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11889b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
11899b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
11909b10ae86STejun Heo 			},
11919deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
11929b10ae86STejun Heo 		},
11939b10ae86STejun Heo 		{
11949b10ae86STejun Heo 			.ident = "dv5",
11959b10ae86STejun Heo 			.matches = {
11969b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
11979b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
11989b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
11999b10ae86STejun Heo 			},
12009deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
12019b10ae86STejun Heo 		},
12029b10ae86STejun Heo 		{
12039b10ae86STejun Heo 			.ident = "dv6",
12049b10ae86STejun Heo 			.matches = {
12059b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12069b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12079b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
12089b10ae86STejun Heo 			},
12099deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
12109b10ae86STejun Heo 		},
12119b10ae86STejun Heo 		{
12129b10ae86STejun Heo 			.ident = "HDX18",
12139b10ae86STejun Heo 			.matches = {
12149b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12159b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
12169b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
12179b10ae86STejun Heo 			},
12189deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
12199b10ae86STejun Heo 		},
1220cedc9bf9STejun Heo 		/*
1221cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
1222cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
122325985edcSLucas De Marchi 		 * work.  Between, there are V1.06, V2.06 and V3.03
1224cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
1225cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
12269deb3431STejun Heo 		 *
12279deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
1228cedc9bf9STejun Heo 		 */
1229cedc9bf9STejun Heo 		{
1230cedc9bf9STejun Heo 			.ident = "G725",
1231cedc9bf9STejun Heo 			.matches = {
1232cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
1233cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
1234cedc9bf9STejun Heo 			},
12359deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
1236cedc9bf9STejun Heo 		},
12379b10ae86STejun Heo 		{ }	/* terminate list */
12389b10ae86STejun Heo 	};
12399b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
12409deb3431STejun Heo 	int year, month, date;
12419deb3431STejun Heo 	char buf[9];
12429b10ae86STejun Heo 
12439b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
12449b10ae86STejun Heo 		return false;
12459b10ae86STejun Heo 
12469deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
12479deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
12489b10ae86STejun Heo 
12499deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
12509b10ae86STejun Heo }
12519b10ae86STejun Heo 
1252240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev)
1253240630e6SHans de Goede {
1254240630e6SHans de Goede 	static const struct dmi_system_id sysids[] = {
1255240630e6SHans de Goede 		/* Various Lenovo 50 series have LPM issues with older BIOSen */
1256240630e6SHans de Goede 		{
1257240630e6SHans de Goede 			.matches = {
1258240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1259240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"),
1260240630e6SHans de Goede 			},
1261240630e6SHans de Goede 			.driver_data = "20180406", /* 1.31 */
1262240630e6SHans de Goede 		},
1263240630e6SHans de Goede 		{
1264240630e6SHans de Goede 			.matches = {
1265240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1266240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"),
1267240630e6SHans de Goede 			},
1268240630e6SHans de Goede 			.driver_data = "20180420", /* 1.28 */
1269240630e6SHans de Goede 		},
1270240630e6SHans de Goede 		{
1271240630e6SHans de Goede 			.matches = {
1272240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1273240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"),
1274240630e6SHans de Goede 			},
1275240630e6SHans de Goede 			.driver_data = "20180315", /* 1.33 */
1276240630e6SHans de Goede 		},
1277240630e6SHans de Goede 		{
1278240630e6SHans de Goede 			.matches = {
1279240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1280240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"),
1281240630e6SHans de Goede 			},
1282240630e6SHans de Goede 			/*
1283240630e6SHans de Goede 			 * Note date based on release notes, 2.35 has been
1284240630e6SHans de Goede 			 * reported to be good, but I've been unable to get
1285240630e6SHans de Goede 			 * a hold of the reporter to get the DMI BIOS date.
1286240630e6SHans de Goede 			 * TODO: fix this.
1287240630e6SHans de Goede 			 */
1288240630e6SHans de Goede 			.driver_data = "20180310", /* 2.35 */
1289240630e6SHans de Goede 		},
1290240630e6SHans de Goede 		{ }	/* terminate list */
1291240630e6SHans de Goede 	};
1292240630e6SHans de Goede 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1293240630e6SHans de Goede 	int year, month, date;
1294240630e6SHans de Goede 	char buf[9];
1295240630e6SHans de Goede 
1296240630e6SHans de Goede 	if (!dmi)
1297240630e6SHans de Goede 		return false;
1298240630e6SHans de Goede 
1299240630e6SHans de Goede 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
1300240630e6SHans de Goede 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
1301240630e6SHans de Goede 
1302240630e6SHans de Goede 	return strcmp(buf, dmi->driver_data) < 0;
1303240630e6SHans de Goede }
1304240630e6SHans de Goede 
13055594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
13065594639aSTejun Heo {
13075594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
13085594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
13095594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
13105594639aSTejun Heo 		/*
13115594639aSTejun Heo 		 * There are several gigabyte boards which use
13125594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
13135594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
13145594639aSTejun Heo 		 * online but fail to answer properly to SRST or
13155594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
13165594639aSTejun Heo 		 * causing libata to retry quite a few times leading
13175594639aSTejun Heo 		 * to excessive detection delay.
13185594639aSTejun Heo 		 *
13195594639aSTejun Heo 		 * As these firmwares respond to the second reset try
13205594639aSTejun Heo 		 * with invalid device signature, considering unknown
13215594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
13225594639aSTejun Heo 		 */
13235594639aSTejun Heo 		{
13245594639aSTejun Heo 			.ident = "EP45-DQ6",
13255594639aSTejun Heo 			.matches = {
13265594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
13275594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
13285594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
13295594639aSTejun Heo 			},
13305594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
13315594639aSTejun Heo 		},
13325594639aSTejun Heo 		{
13335594639aSTejun Heo 			.ident = "EP45-DS5",
13345594639aSTejun Heo 			.matches = {
13355594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
13365594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
13375594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
13385594639aSTejun Heo 			},
13395594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
13405594639aSTejun Heo 		},
13415594639aSTejun Heo 		{ }	/* terminate list */
13425594639aSTejun Heo 	};
13435594639aSTejun Heo #undef ENCODE_BUSDEVFN
13445594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
13455594639aSTejun Heo 	unsigned int val;
13465594639aSTejun Heo 
13475594639aSTejun Heo 	if (!dmi)
13485594639aSTejun Heo 		return false;
13495594639aSTejun Heo 
13505594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
13515594639aSTejun Heo 
13525594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
13535594639aSTejun Heo }
13545594639aSTejun Heo 
13550cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev)
13560cf4a7d6SJacob Pan {
13570cf4a7d6SJacob Pan 	/* device with broken DEVSLP but still showing SDS capability */
13580cf4a7d6SJacob Pan 	static const struct pci_device_id ids[] = {
13590cf4a7d6SJacob Pan 		{ PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
13600cf4a7d6SJacob Pan 		{}
13610cf4a7d6SJacob Pan 	};
13620cf4a7d6SJacob Pan 
13630cf4a7d6SJacob Pan 	return pci_match_id(ids, pdev);
13640cf4a7d6SJacob Pan }
13650cf4a7d6SJacob Pan 
13668e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
1367f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
1368f80ae7e4STejun Heo {
1369f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
1370f80ae7e4STejun Heo 		/*
1371f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
1372f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
1373f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
1374f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
1375f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
1376f80ae7e4STejun Heo 		 * failures.  Filter it out.
1377f80ae7e4STejun Heo 		 */
1378f80ae7e4STejun Heo 		{
1379f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
1380f80ae7e4STejun Heo 			.matches = {
1381f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1382f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1383f80ae7e4STejun Heo 			},
1384f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1385f80ae7e4STejun Heo 		},
1386f80ae7e4STejun Heo 		{ }
1387f80ae7e4STejun Heo 	};
1388f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1389f80ae7e4STejun Heo 	unsigned int filter;
1390f80ae7e4STejun Heo 	int i;
1391f80ae7e4STejun Heo 
1392f80ae7e4STejun Heo 	if (!dmi)
1393f80ae7e4STejun Heo 		return;
1394f80ae7e4STejun Heo 
1395f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1396a44fec1fSJoe Perches 	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
1397f80ae7e4STejun Heo 		 filter, dmi->ident);
1398f80ae7e4STejun Heo 
1399f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1400f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1401f80ae7e4STejun Heo 		struct ata_link *link;
1402f80ae7e4STejun Heo 		struct ata_device *dev;
1403f80ae7e4STejun Heo 
1404f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1405f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1406f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1407f80ae7e4STejun Heo 	}
1408f80ae7e4STejun Heo }
14098e513217SMarkus Trippelsdorf #else
14108e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
14118e513217SMarkus Trippelsdorf {}
14128e513217SMarkus Trippelsdorf #endif
1413f80ae7e4STejun Heo 
14148bfd1743SSui Chen /*
14158bfd1743SSui Chen  * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected
14168bfd1743SSui Chen  * as DUMMY, or detected but eventually get a "link down" and never get up
14178bfd1743SSui Chen  * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the
14188bfd1743SSui Chen  * port_map may hold a value of 0x00.
14198bfd1743SSui Chen  *
14208bfd1743SSui Chen  * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports
14218bfd1743SSui Chen  * and can significantly reduce the occurrence of the problem.
14228bfd1743SSui Chen  *
14238bfd1743SSui Chen  * https://bugzilla.kernel.org/show_bug.cgi?id=189471
14248bfd1743SSui Chen  */
14258bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv,
14268bfd1743SSui Chen 				    struct pci_dev *pdev)
14278bfd1743SSui Chen {
14288bfd1743SSui Chen 	static const struct dmi_system_id sysids[] = {
14298bfd1743SSui Chen 		{
14308bfd1743SSui Chen 			.ident = "Acer Switch Alpha 12",
14318bfd1743SSui Chen 			.matches = {
14328bfd1743SSui Chen 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
14338bfd1743SSui Chen 				DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271")
14348bfd1743SSui Chen 			},
14358bfd1743SSui Chen 		},
14368bfd1743SSui Chen 		{ }
14378bfd1743SSui Chen 	};
14388bfd1743SSui Chen 
14398bfd1743SSui Chen 	if (dmi_check_system(sysids)) {
14408bfd1743SSui Chen 		dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n");
14418bfd1743SSui Chen 		if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) {
14428bfd1743SSui Chen 			hpriv->port_map = 0x7;
14438bfd1743SSui Chen 			hpriv->cap = 0xC734FF02;
14448bfd1743SSui Chen 		}
14458bfd1743SSui Chen 	}
14468bfd1743SSui Chen }
14478bfd1743SSui Chen 
1448d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64
1449d243bed3STirumalesh Chalamarla /*
1450d243bed3STirumalesh Chalamarla  * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
1451d243bed3STirumalesh Chalamarla  * Workaround is to make sure all pending IRQs are served before leaving
1452d243bed3STirumalesh Chalamarla  * handler.
1453d243bed3STirumalesh Chalamarla  */
1454d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
1455d243bed3STirumalesh Chalamarla {
1456d243bed3STirumalesh Chalamarla 	struct ata_host *host = dev_instance;
1457d243bed3STirumalesh Chalamarla 	struct ahci_host_priv *hpriv;
1458d243bed3STirumalesh Chalamarla 	unsigned int rc = 0;
1459d243bed3STirumalesh Chalamarla 	void __iomem *mmio;
1460d243bed3STirumalesh Chalamarla 	u32 irq_stat, irq_masked;
1461d243bed3STirumalesh Chalamarla 	unsigned int handled = 1;
1462d243bed3STirumalesh Chalamarla 
1463d243bed3STirumalesh Chalamarla 	VPRINTK("ENTER\n");
1464d243bed3STirumalesh Chalamarla 	hpriv = host->private_data;
1465d243bed3STirumalesh Chalamarla 	mmio = hpriv->mmio;
1466d243bed3STirumalesh Chalamarla 	irq_stat = readl(mmio + HOST_IRQ_STAT);
1467d243bed3STirumalesh Chalamarla 	if (!irq_stat)
1468d243bed3STirumalesh Chalamarla 		return IRQ_NONE;
1469d243bed3STirumalesh Chalamarla 
1470d243bed3STirumalesh Chalamarla 	do {
1471d243bed3STirumalesh Chalamarla 		irq_masked = irq_stat & hpriv->port_map;
1472d243bed3STirumalesh Chalamarla 		spin_lock(&host->lock);
1473d243bed3STirumalesh Chalamarla 		rc = ahci_handle_port_intr(host, irq_masked);
1474d243bed3STirumalesh Chalamarla 		if (!rc)
1475d243bed3STirumalesh Chalamarla 			handled = 0;
1476d243bed3STirumalesh Chalamarla 		writel(irq_stat, mmio + HOST_IRQ_STAT);
1477d243bed3STirumalesh Chalamarla 		irq_stat = readl(mmio + HOST_IRQ_STAT);
1478d243bed3STirumalesh Chalamarla 		spin_unlock(&host->lock);
1479d243bed3STirumalesh Chalamarla 	} while (irq_stat);
1480d243bed3STirumalesh Chalamarla 	VPRINTK("EXIT\n");
1481d243bed3STirumalesh Chalamarla 
1482d243bed3STirumalesh Chalamarla 	return IRQ_RETVAL(handled);
1483d243bed3STirumalesh Chalamarla }
1484d243bed3STirumalesh Chalamarla #endif
1485d243bed3STirumalesh Chalamarla 
1486aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar,
1487aecec8b6SChristoph Hellwig 		struct ahci_host_priv *hpriv)
1488aecec8b6SChristoph Hellwig {
1489aecec8b6SChristoph Hellwig 	int i, count = 0;
1490aecec8b6SChristoph Hellwig 	u32 cap;
1491aecec8b6SChristoph Hellwig 
1492aecec8b6SChristoph Hellwig 	/*
1493aecec8b6SChristoph Hellwig 	 * Check if this device might have remapped nvme devices.
1494aecec8b6SChristoph Hellwig 	 */
1495aecec8b6SChristoph Hellwig 	if (pdev->vendor != PCI_VENDOR_ID_INTEL ||
1496aecec8b6SChristoph Hellwig 	    pci_resource_len(pdev, bar) < SZ_512K ||
1497aecec8b6SChristoph Hellwig 	    bar != AHCI_PCI_BAR_STANDARD ||
1498aecec8b6SChristoph Hellwig 	    !(readl(hpriv->mmio + AHCI_VSCAP) & 1))
1499aecec8b6SChristoph Hellwig 		return;
1500aecec8b6SChristoph Hellwig 
1501aecec8b6SChristoph Hellwig 	cap = readq(hpriv->mmio + AHCI_REMAP_CAP);
1502aecec8b6SChristoph Hellwig 	for (i = 0; i < AHCI_MAX_REMAP; i++) {
1503aecec8b6SChristoph Hellwig 		if ((cap & (1 << i)) == 0)
1504aecec8b6SChristoph Hellwig 			continue;
1505aecec8b6SChristoph Hellwig 		if (readl(hpriv->mmio + ahci_remap_dcc(i))
1506aecec8b6SChristoph Hellwig 				!= PCI_CLASS_STORAGE_EXPRESS)
1507aecec8b6SChristoph Hellwig 			continue;
1508aecec8b6SChristoph Hellwig 
1509aecec8b6SChristoph Hellwig 		/* We've found a remapped device */
1510aecec8b6SChristoph Hellwig 		count++;
1511aecec8b6SChristoph Hellwig 	}
1512aecec8b6SChristoph Hellwig 
1513aecec8b6SChristoph Hellwig 	if (!count)
1514aecec8b6SChristoph Hellwig 		return;
1515aecec8b6SChristoph Hellwig 
1516aecec8b6SChristoph Hellwig 	dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count);
1517f723fa4eSChristoph Hellwig 	dev_warn(&pdev->dev,
1518f723fa4eSChristoph Hellwig 		 "Switch your BIOS from RAID to AHCI mode to use them.\n");
1519f723fa4eSChristoph Hellwig 
1520f723fa4eSChristoph Hellwig 	/*
1521f723fa4eSChristoph Hellwig 	 * Don't rely on the msi-x capability in the remap case,
1522f723fa4eSChristoph Hellwig 	 * share the legacy interrupt across ahci and remapped devices.
1523f723fa4eSChristoph Hellwig 	 */
1524f723fa4eSChristoph Hellwig 	hpriv->flags |= AHCI_HFLAG_NO_MSI;
1525aecec8b6SChristoph Hellwig }
1526aecec8b6SChristoph Hellwig 
15270b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port)
1528ee2aad42SRobert Richter {
15290b9e2988SChristoph Hellwig 	return pci_irq_vector(to_pci_dev(host->dev), port);
1530ee2aad42SRobert Richter }
1531ee2aad42SRobert Richter 
1532a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
15337b92b4f6SAlexander Gordeev 			struct ahci_host_priv *hpriv)
15345ca72c4fSAlexander Gordeev {
15350b9e2988SChristoph Hellwig 	int nvec;
15365ca72c4fSAlexander Gordeev 
15377b92b4f6SAlexander Gordeev 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
1538a1c82311SRobert Richter 		return -ENODEV;
15397b92b4f6SAlexander Gordeev 
15405ca72c4fSAlexander Gordeev 	/*
15417b92b4f6SAlexander Gordeev 	 * If number of MSIs is less than number of ports then Sharing Last
15427b92b4f6SAlexander Gordeev 	 * Message mode could be enforced. In this case assume that advantage
15437b92b4f6SAlexander Gordeev 	 * of multipe MSIs is negated and use single MSI mode instead.
15445ca72c4fSAlexander Gordeev 	 */
154517a51f12SChristoph Hellwig 	if (n_ports > 1) {
15460b9e2988SChristoph Hellwig 		nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX,
15470b9e2988SChristoph Hellwig 				PCI_IRQ_MSIX | PCI_IRQ_MSI);
15480b9e2988SChristoph Hellwig 		if (nvec > 0) {
15490b9e2988SChristoph Hellwig 			if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) {
15500b9e2988SChristoph Hellwig 				hpriv->get_irq_vector = ahci_get_irq_vector;
1551c3ebd6a9SAlexander Gordeev 				hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
155221bfd1aaSRobert Richter 				return nvec;
1553a1c82311SRobert Richter 			}
1554a1c82311SRobert Richter 
1555d684a90dSDan Williams 			/*
155617a51f12SChristoph Hellwig 			 * Fallback to single MSI mode if the controller
155717a51f12SChristoph Hellwig 			 * enforced MRSM mode.
1558d684a90dSDan Williams 			 */
155917a51f12SChristoph Hellwig 			printk(KERN_INFO
156017a51f12SChristoph Hellwig 				"ahci: MRSM is on, fallback to single MSI\n");
15610b9e2988SChristoph Hellwig 			pci_free_irq_vectors(pdev);
15620b9e2988SChristoph Hellwig 		}
1563a478b097SChristoph Hellwig 	}
1564d684a90dSDan Williams 
15650b9e2988SChristoph Hellwig 	/*
15660b9e2988SChristoph Hellwig 	 * If the host is not capable of supporting per-port vectors, fall
15670b9e2988SChristoph Hellwig 	 * back to single MSI before finally attempting single MSI-X.
15680b9e2988SChristoph Hellwig 	 */
15690b9e2988SChristoph Hellwig 	nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
15700b9e2988SChristoph Hellwig 	if (nvec == 1)
1571a1c82311SRobert Richter 		return nvec;
15720b9e2988SChristoph Hellwig 	return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
15735ca72c4fSAlexander Gordeev }
15745ca72c4fSAlexander Gordeev 
1575b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap,
1576b1a9585cSSrinivas Pandruvada 					   struct ahci_host_priv *hpriv)
1577b1a9585cSSrinivas Pandruvada {
1578b1a9585cSSrinivas Pandruvada 	int policy = CONFIG_SATA_MOBILE_LPM_POLICY;
1579b1a9585cSSrinivas Pandruvada 
1580b1a9585cSSrinivas Pandruvada 
1581b1a9585cSSrinivas Pandruvada 	/* Ignore processing for non mobile platforms */
1582b1a9585cSSrinivas Pandruvada 	if (!(hpriv->flags & AHCI_HFLAG_IS_MOBILE))
1583b1a9585cSSrinivas Pandruvada 		return;
1584b1a9585cSSrinivas Pandruvada 
1585b1a9585cSSrinivas Pandruvada 	/* user modified policy via module param */
1586b1a9585cSSrinivas Pandruvada 	if (mobile_lpm_policy != -1) {
1587b1a9585cSSrinivas Pandruvada 		policy = mobile_lpm_policy;
1588b1a9585cSSrinivas Pandruvada 		goto update_policy;
1589b1a9585cSSrinivas Pandruvada 	}
1590b1a9585cSSrinivas Pandruvada 
1591b1a9585cSSrinivas Pandruvada #ifdef CONFIG_ACPI
1592b1a9585cSSrinivas Pandruvada 	if (policy > ATA_LPM_MED_POWER &&
1593b1a9585cSSrinivas Pandruvada 	    (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) {
1594b1a9585cSSrinivas Pandruvada 		if (hpriv->cap & HOST_CAP_PART)
1595b1a9585cSSrinivas Pandruvada 			policy = ATA_LPM_MIN_POWER_WITH_PARTIAL;
1596b1a9585cSSrinivas Pandruvada 		else if (hpriv->cap & HOST_CAP_SSC)
1597b1a9585cSSrinivas Pandruvada 			policy = ATA_LPM_MIN_POWER;
1598b1a9585cSSrinivas Pandruvada 	}
1599b1a9585cSSrinivas Pandruvada #endif
1600b1a9585cSSrinivas Pandruvada 
1601b1a9585cSSrinivas Pandruvada update_policy:
1602b1a9585cSSrinivas Pandruvada 	if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER)
1603b1a9585cSSrinivas Pandruvada 		ap->target_lpm_policy = policy;
1604b1a9585cSSrinivas Pandruvada }
1605b1a9585cSSrinivas Pandruvada 
1606c312ef17SDan Williams static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
1607c312ef17SDan Williams {
1608c312ef17SDan Williams 	const struct pci_device_id *id = pci_match_id(ahci_pci_tbl, pdev);
1609c312ef17SDan Williams 	u16 tmp16;
1610c312ef17SDan Williams 
1611c312ef17SDan Williams 	/*
1612c312ef17SDan Williams 	 * Only apply the 6-port PCS quirk for known legacy platforms.
1613c312ef17SDan Williams 	 */
1614c312ef17SDan Williams 	if (!id || id->vendor != PCI_VENDOR_ID_INTEL)
1615c312ef17SDan Williams 		return;
161609d6ac8dSDan Williams 
161709d6ac8dSDan Williams 	/* Skip applying the quirk on Denverton and beyond */
161809d6ac8dSDan Williams 	if (((enum board_ids) id->driver_data) >= board_ahci_pcs7)
1619c312ef17SDan Williams 		return;
1620c312ef17SDan Williams 
1621c312ef17SDan Williams 	/*
1622c312ef17SDan Williams 	 * port_map is determined from PORTS_IMPL PCI register which is
1623c312ef17SDan Williams 	 * implemented as write or write-once register.  If the register
1624c312ef17SDan Williams 	 * isn't programmed, ahci automatically generates it from number
1625c312ef17SDan Williams 	 * of ports, which is good enough for PCS programming. It is
1626c312ef17SDan Williams 	 * otherwise expected that platform firmware enables the ports
1627c312ef17SDan Williams 	 * before the OS boots.
1628c312ef17SDan Williams 	 */
1629c312ef17SDan Williams 	pci_read_config_word(pdev, PCS_6, &tmp16);
1630c312ef17SDan Williams 	if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
1631c312ef17SDan Williams 		tmp16 |= hpriv->port_map;
1632c312ef17SDan Williams 		pci_write_config_word(pdev, PCS_6, tmp16);
1633c312ef17SDan Williams 	}
1634c312ef17SDan Williams }
1635c312ef17SDan Williams 
1636c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1637c6fd2807SJeff Garzik {
1638e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1639e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
16404447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
164124dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1642c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
16434447d351STejun Heo 	struct ata_host *host;
1644c3ebd6a9SAlexander Gordeev 	int n_ports, i, rc;
1645318893e1SAlessandro Rubini 	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
1646c6fd2807SJeff Garzik 
1647c6fd2807SJeff Garzik 	VPRINTK("ENTER\n");
1648c6fd2807SJeff Garzik 
1649b429dd59SJustin P. Mattock 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1650c6fd2807SJeff Garzik 
165106296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1652c6fd2807SJeff Garzik 
16535b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
16545b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
16555b66c829SAlan Cox 	   AHCI stays out of the way */
16565b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
16575b66c829SAlan Cox 		return -ENODEV;
16585b66c829SAlan Cox 
1659cb85696dSJames Laird 	/* Apple BIOS on MCP89 prevents us using AHCI */
1660cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
1661cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
1662c6353b45STejun Heo 
16637a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
16647a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
16657a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
16667a02267eSMark Nelson 	 */
16677a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
1668a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1669a44fec1fSJoe Perches 			 "PDC42819 can only drive SATA devices with this driver\n");
16707a02267eSMark Nelson 
1671b7ae128dSRobert Richter 	/* Some devices use non-standard BARs */
1672318893e1SAlessandro Rubini 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
1673318893e1SAlessandro Rubini 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
16747f9c9f8eSHugh Daschbach 	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
16757f9c9f8eSHugh Daschbach 		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
1676b1314e3fSRadha Mohan Chintakuntla 	else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) {
1677b1314e3fSRadha Mohan Chintakuntla 		if (pdev->device == 0xa01c)
1678b7ae128dSRobert Richter 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM;
1679b1314e3fSRadha Mohan Chintakuntla 		if (pdev->device == 0xa084)
1680b1314e3fSRadha Mohan Chintakuntla 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5;
1681b1314e3fSRadha Mohan Chintakuntla 	}
1682318893e1SAlessandro Rubini 
16834447d351STejun Heo 	/* acquire resources */
168424dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1685c6fd2807SJeff Garzik 	if (rc)
1686c6fd2807SJeff Garzik 		return rc;
1687c6fd2807SJeff Garzik 
1688c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1689c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1690c4f7792cSTejun Heo 		u8 map;
1691c4f7792cSTejun Heo 
1692c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1693c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1694c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1695c4f7792cSTejun Heo 		 */
1696c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1697c4f7792cSTejun Heo 		if (map & 0x3) {
1698a44fec1fSJoe Perches 			dev_info(&pdev->dev,
1699a44fec1fSJoe Perches 				 "controller is in combined mode, can't enable AHCI mode\n");
1700c4f7792cSTejun Heo 			return -ENODEV;
1701c4f7792cSTejun Heo 		}
1702c4f7792cSTejun Heo 	}
1703c4f7792cSTejun Heo 
17046fec8871SPaul Bolle 	/* AHCI controllers often implement SFF compatible interface.
17056fec8871SPaul Bolle 	 * Grab all PCI BARs just in case.
17066fec8871SPaul Bolle 	 */
17076fec8871SPaul Bolle 	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
17086fec8871SPaul Bolle 	if (rc == -EBUSY)
17096fec8871SPaul Bolle 		pcim_pin_device(pdev);
17106fec8871SPaul Bolle 	if (rc)
17116fec8871SPaul Bolle 		return rc;
17126fec8871SPaul Bolle 
171324dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
171424dc5f33STejun Heo 	if (!hpriv)
171524dc5f33STejun Heo 		return -ENOMEM;
1716417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1717417a1a6dSTejun Heo 
1718e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1719e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1720e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1721e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1722e297d99eSTejun Heo 
1723e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1724e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1725e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1726e427fe04SShane Huang 
17272fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
17282fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
17292fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
173058a09b38SShane Huang 
1731318893e1SAlessandro Rubini 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
1732d8993349SAnton Vorontsov 
1733aecec8b6SChristoph Hellwig 	/* detect remapped nvme devices */
1734aecec8b6SChristoph Hellwig 	ahci_remap_check(pdev, ahci_pci_bar, hpriv);
1735aecec8b6SChristoph Hellwig 
17360cf4a7d6SJacob Pan 	/* must set flag prior to save config in order to take effect */
17370cf4a7d6SJacob Pan 	if (ahci_broken_devslp(pdev))
17380cf4a7d6SJacob Pan 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
17390cf4a7d6SJacob Pan 
1740d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64
1741d243bed3STirumalesh Chalamarla 	if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
1742d243bed3STirumalesh Chalamarla 		hpriv->irq_handler = ahci_thunderx_irq_handler;
1743d243bed3STirumalesh Chalamarla #endif
1744d243bed3STirumalesh Chalamarla 
17454447d351STejun Heo 	/* save initial config */
1746394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1747c6fd2807SJeff Garzik 
1748c312ef17SDan Williams 	/*
1749c312ef17SDan Williams 	 * If platform firmware failed to enable ports, try to enable
1750c312ef17SDan Williams 	 * them here.
1751c312ef17SDan Williams 	 */
1752c312ef17SDan Williams 	ahci_intel_pcs_quirk(pdev, hpriv);
1753c312ef17SDan Williams 
17544447d351STejun Heo 	/* prepare host */
1755453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1756453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
175783f2b963STejun Heo 		/*
175883f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
175983f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
176083f2b963STejun Heo 		 * capability, but it seems to be broken on some
176183f2b963STejun Heo 		 * chipsets including NVIDIAs.
176283f2b963STejun Heo 		 */
176383f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1764453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
176540fb59e7SMarc Carino 
176640fb59e7SMarc Carino 		/*
176740fb59e7SMarc Carino 		 * All AHCI controllers should be forward-compatible
176840fb59e7SMarc Carino 		 * with the new auxiliary field. This code should be
176940fb59e7SMarc Carino 		 * conditionalized if any buggy AHCI controllers are
177040fb59e7SMarc Carino 		 * encountered.
177140fb59e7SMarc Carino 		 */
177240fb59e7SMarc Carino 		pi.flags |= ATA_FLAG_FPDMA_AUX;
1773453d3131SRobert Hancock 	}
17744447d351STejun Heo 
17757d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
17767d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
17777d50b60bSTejun Heo 
17780cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
177918f7ba4cSKristen Carlson Accardi 
17801fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
17811fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
17821fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
17831fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
17841fd68434SRafael J. Wysocki 	}
17851fd68434SRafael J. Wysocki 
1786240630e6SHans de Goede 	if (ahci_broken_lpm(pdev)) {
1787240630e6SHans de Goede 		pi.flags |= ATA_FLAG_NO_LPM;
1788240630e6SHans de Goede 		dev_warn(&pdev->dev,
1789240630e6SHans de Goede 			 "BIOS update required for Link Power Management support\n");
1790240630e6SHans de Goede 	}
1791240630e6SHans de Goede 
17929b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
17939b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
1794a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
17959b10ae86STejun Heo 			 "BIOS update required for suspend/resume\n");
17969b10ae86STejun Heo 	}
17979b10ae86STejun Heo 
17985594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
17995594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
18005594639aSTejun Heo 		dev_info(&pdev->dev,
18015594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
18025594639aSTejun Heo 	}
18035594639aSTejun Heo 
18048bfd1743SSui Chen 
18058bfd1743SSui Chen 	/* Acer SA5-271 workaround modifies private_data */
18068bfd1743SSui Chen 	acer_sa5_271_workaround(hpriv, pdev);
18078bfd1743SSui Chen 
1808837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1809837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1810837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1811837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1812837f5f8fSTejun Heo 	 */
1813837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1814837f5f8fSTejun Heo 
1815837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
18164447d351STejun Heo 	if (!host)
18174447d351STejun Heo 		return -ENOMEM;
18184447d351STejun Heo 	host->private_data = hpriv;
18190b9e2988SChristoph Hellwig 
18200b9e2988SChristoph Hellwig 	if (ahci_init_msi(pdev, n_ports, hpriv) < 0) {
18210b9e2988SChristoph Hellwig 		/* legacy intx interrupts */
18220b9e2988SChristoph Hellwig 		pci_intx(pdev, 1);
18230b9e2988SChristoph Hellwig 	}
18240ce57f8aSChristoph Hellwig 	hpriv->irq = pci_irq_vector(pdev, 0);
182521bfd1aaSRobert Richter 
1826f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1827886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1828f3d7f23fSArjan van de Ven 	else
1829d2782d96SJingoo Han 		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
1830886ad09fSArjan van de Ven 
183118f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
183218f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
183318f7ba4cSKristen Carlson Accardi 
18344447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
18354447d351STejun Heo 		struct ata_port *ap = host->ports[i];
18364447d351STejun Heo 
1837318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
1838318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar,
1839cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
1840cbcdd875STejun Heo 
184118f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
184218f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
1843008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
184418f7ba4cSKristen Carlson Accardi 
1845b1a9585cSSrinivas Pandruvada 		ahci_update_initial_lpm_policy(ap, hpriv);
184618f7ba4cSKristen Carlson Accardi 
1847dab632e8SJeff Garzik 		/* disabled/not-implemented port */
1848350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
1849dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
18504447d351STejun Heo 	}
1851c6fd2807SJeff Garzik 
1852edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
1853edc93052STejun Heo 	ahci_p5wdh_workaround(host);
1854edc93052STejun Heo 
1855f80ae7e4STejun Heo 	/* apply gtf filter quirk */
1856f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
1857f80ae7e4STejun Heo 
1858c6fd2807SJeff Garzik 	/* initialize adapter */
18594447d351STejun Heo 	rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
1860c6fd2807SJeff Garzik 	if (rc)
186124dc5f33STejun Heo 		return rc;
1862c6fd2807SJeff Garzik 
1863c312ef17SDan Williams 	rc = ahci_reset_controller(host);
18644447d351STejun Heo 	if (rc)
18654447d351STejun Heo 		return rc;
1866c6fd2807SJeff Garzik 
1867781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
1868439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
1869c6fd2807SJeff Garzik 
18704447d351STejun Heo 	pci_set_master(pdev);
18715ca72c4fSAlexander Gordeev 
187202e53293SMika Westerberg 	rc = ahci_host_activate(host, &ahci_sht);
187302e53293SMika Westerberg 	if (rc)
187402e53293SMika Westerberg 		return rc;
187502e53293SMika Westerberg 
187602e53293SMika Westerberg 	pm_runtime_put_noidle(&pdev->dev);
187702e53293SMika Westerberg 	return 0;
187802e53293SMika Westerberg }
187902e53293SMika Westerberg 
188002e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev)
188102e53293SMika Westerberg {
188202e53293SMika Westerberg 	pm_runtime_get_noresume(&pdev->dev);
188302e53293SMika Westerberg 	ata_pci_remove_one(pdev);
1884c6fd2807SJeff Garzik }
1885c6fd2807SJeff Garzik 
18862fc75da0SAxel Lin module_pci_driver(ahci_pci_driver);
1887c6fd2807SJeff Garzik 
1888c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
1889c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
1890c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
1891c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
1892c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
1893