xref: /openbmc/linux/drivers/ata/ahci.c (revision 7b7fd0ac7dc1ffcaf24d9bca0f051b0168e43cd4)
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>
29c6fd2807SJeff Garzik #include <scsi/scsi_host.h>
30c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h>
31c6fd2807SJeff Garzik #include <linux/libata.h>
32aecec8b6SChristoph Hellwig #include <linux/ahci-remap.h>
33aecec8b6SChristoph Hellwig #include <linux/io-64-nonatomic-lo-hi.h>
34365cfa1eSAnton Vorontsov #include "ahci.h"
35c6fd2807SJeff Garzik 
36c6fd2807SJeff Garzik #define DRV_NAME	"ahci"
377d50b60bSTejun Heo #define DRV_VERSION	"3.0"
38c6fd2807SJeff Garzik 
39c6fd2807SJeff Garzik enum {
40318893e1SAlessandro Rubini 	AHCI_PCI_BAR_STA2X11	= 0,
41b7ae128dSRobert Richter 	AHCI_PCI_BAR_CAVIUM	= 0,
42e49bd683STiezhu Yang 	AHCI_PCI_BAR_LOONGSON	= 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,
51b0dd4d7aSLennert Buytenhek 	board_ahci_43bit_dma,
52441577efSTejun Heo 	board_ahci_ign_iferr,
53099849afSMario Limonciello 	board_ahci_low_power,
54a17ab7abSPaul Menzel 	board_ahci_no_debounce_delay,
5566a7cbc3STejun Heo 	board_ahci_nomsi,
5667809f85SLevente Kurusa 	board_ahci_noncq,
57441577efSTejun Heo 	board_ahci_nosntf,
585f173107STejun Heo 	board_ahci_yes_fbs,
59441577efSTejun Heo 
60441577efSTejun Heo 	/* board IDs for specific chipsets in alphabetical order */
617d523bdcSHanna Hawa 	board_ahci_al,
62dbfe8ef5SDan Williams 	board_ahci_avn,
63441577efSTejun Heo 	board_ahci_mcp65,
6483f2b963STejun Heo 	board_ahci_mcp77,
6583f2b963STejun Heo 	board_ahci_mcp89,
66441577efSTejun Heo 	board_ahci_mv,
67441577efSTejun Heo 	board_ahci_sb600,
68441577efSTejun Heo 	board_ahci_sb700,	/* for SB700 and SB800 */
69441577efSTejun Heo 	board_ahci_vt8251,
70441577efSTejun Heo 
71c312ef17SDan Williams 	/*
72c312ef17SDan Williams 	 * board IDs for Intel chipsets that support more than 6 ports
73c312ef17SDan Williams 	 * *and* end up needing the PCS quirk.
74c312ef17SDan Williams 	 */
75c312ef17SDan Williams 	board_ahci_pcs7,
76c312ef17SDan Williams 
77441577efSTejun Heo 	/* aliases */
78441577efSTejun Heo 	board_ahci_mcp_linux	= board_ahci_mcp65,
79441577efSTejun Heo 	board_ahci_mcp67	= board_ahci_mcp65,
80441577efSTejun Heo 	board_ahci_mcp73	= board_ahci_mcp65,
8183f2b963STejun Heo 	board_ahci_mcp79	= board_ahci_mcp77,
82c6fd2807SJeff Garzik };
83c6fd2807SJeff Garzik 
84c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
8502e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *dev);
8610a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *dev);
8737e14e4fSAdam Vodopjan static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv);
88a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
89a1efdabaSTejun Heo 				 unsigned long deadline);
90dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
91dbfe8ef5SDan Williams 			      unsigned long deadline);
92cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
93cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev);
94a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
95a1efdabaSTejun Heo 				unsigned long deadline);
9602e53293SMika Westerberg #ifdef CONFIG_PM
9702e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev);
9802e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev);
99f1d848f9SMika Westerberg #ifdef CONFIG_PM_SLEEP
100f1d848f9SMika Westerberg static int ahci_pci_device_suspend(struct device *dev);
101f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev);
102438ac6d5STejun Heo #endif
10302e53293SMika Westerberg #endif /* CONFIG_PM */
104c6fd2807SJeff Garzik 
10525df73d9SBart Van Assche static const struct scsi_host_template ahci_sht = {
106fad16e7aSTejun Heo 	AHCI_SHT("ahci"),
107fad16e7aSTejun Heo };
108fad16e7aSTejun Heo 
109029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = {
110029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
111a1efdabaSTejun Heo 	.hardreset		= ahci_vt8251_hardreset,
112ad616ffbSTejun Heo };
113ad616ffbSTejun Heo 
114029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = {
115029cfd6bSTejun Heo 	.inherits		= &ahci_ops,
116a1efdabaSTejun Heo 	.hardreset		= ahci_p5wdh_hardreset,
117edc93052STejun Heo };
118edc93052STejun Heo 
119dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = {
120dbfe8ef5SDan Williams 	.inherits		= &ahci_ops,
121dbfe8ef5SDan Williams 	.hardreset		= ahci_avn_hardreset,
122dbfe8ef5SDan Williams };
123dbfe8ef5SDan Williams 
124c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = {
125441577efSTejun Heo 	/* by features */
126facb8fa6SJeffrin Jose 	[board_ahci] = {
1271188c0d8STejun Heo 		.flags		= AHCI_FLAG_COMMON,
12814bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
129469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
130c6fd2807SJeff Garzik 		.port_ops	= &ahci_ops,
131c6fd2807SJeff Garzik 	},
132b0dd4d7aSLennert Buytenhek 	[board_ahci_43bit_dma] = {
133b0dd4d7aSLennert Buytenhek 		AHCI_HFLAGS	(AHCI_HFLAG_43BIT_ONLY),
134b0dd4d7aSLennert Buytenhek 		.flags		= AHCI_FLAG_COMMON,
135b0dd4d7aSLennert Buytenhek 		.pio_mask	= ATA_PIO4,
136b0dd4d7aSLennert Buytenhek 		.udma_mask	= ATA_UDMA6,
137b0dd4d7aSLennert Buytenhek 		.port_ops	= &ahci_ops,
138b0dd4d7aSLennert Buytenhek 	},
139facb8fa6SJeffrin Jose 	[board_ahci_ign_iferr] = {
140417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
141417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
14214bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
143469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
14441669553STejun Heo 		.port_ops	= &ahci_ops,
14541669553STejun Heo 	},
146099849afSMario Limonciello 	[board_ahci_low_power] = {
147e5c89479SMario Limonciello 		AHCI_HFLAGS	(AHCI_HFLAG_USE_LPM_POLICY),
148ebb82e3cSHans de Goede 		.flags		= AHCI_FLAG_COMMON,
149ebb82e3cSHans de Goede 		.pio_mask	= ATA_PIO4,
150ebb82e3cSHans de Goede 		.udma_mask	= ATA_UDMA6,
151ebb82e3cSHans de Goede 		.port_ops	= &ahci_ops,
152ebb82e3cSHans de Goede 	},
153a17ab7abSPaul Menzel 	[board_ahci_no_debounce_delay] = {
154a17ab7abSPaul Menzel 		.flags		= AHCI_FLAG_COMMON,
155a17ab7abSPaul Menzel 		.link_flags	= ATA_LFLAG_NO_DEBOUNCE_DELAY,
156a17ab7abSPaul Menzel 		.pio_mask	= ATA_PIO4,
157a17ab7abSPaul Menzel 		.udma_mask	= ATA_UDMA6,
158a17ab7abSPaul Menzel 		.port_ops	= &ahci_ops,
159a17ab7abSPaul Menzel 	},
16066a7cbc3STejun Heo 	[board_ahci_nomsi] = {
16166a7cbc3STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_MSI),
16266a7cbc3STejun Heo 		.flags		= AHCI_FLAG_COMMON,
16366a7cbc3STejun Heo 		.pio_mask	= ATA_PIO4,
16466a7cbc3STejun Heo 		.udma_mask	= ATA_UDMA6,
16566a7cbc3STejun Heo 		.port_ops	= &ahci_ops,
16666a7cbc3STejun Heo 	},
16767809f85SLevente Kurusa 	[board_ahci_noncq] = {
16867809f85SLevente Kurusa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ),
16967809f85SLevente Kurusa 		.flags		= AHCI_FLAG_COMMON,
17067809f85SLevente Kurusa 		.pio_mask	= ATA_PIO4,
17167809f85SLevente Kurusa 		.udma_mask	= ATA_UDMA6,
17267809f85SLevente Kurusa 		.port_ops	= &ahci_ops,
17367809f85SLevente Kurusa 	},
174facb8fa6SJeffrin Jose 	[board_ahci_nosntf] = {
175441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
176441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
177441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
178441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
179441577efSTejun Heo 		.port_ops	= &ahci_ops,
180441577efSTejun Heo 	},
181facb8fa6SJeffrin Jose 	[board_ahci_yes_fbs] = {
1825f173107STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),
1835f173107STejun Heo 		.flags		= AHCI_FLAG_COMMON,
1845f173107STejun Heo 		.pio_mask	= ATA_PIO4,
1855f173107STejun Heo 		.udma_mask	= ATA_UDMA6,
1865f173107STejun Heo 		.port_ops	= &ahci_ops,
1875f173107STejun Heo 	},
188441577efSTejun Heo 	/* by chipsets */
1897d523bdcSHanna Hawa 	[board_ahci_al] = {
1907d523bdcSHanna Hawa 		AHCI_HFLAGS	(AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_MSI),
1917d523bdcSHanna Hawa 		.flags		= AHCI_FLAG_COMMON,
1927d523bdcSHanna Hawa 		.pio_mask	= ATA_PIO4,
1937d523bdcSHanna Hawa 		.udma_mask	= ATA_UDMA6,
1947d523bdcSHanna Hawa 		.port_ops	= &ahci_ops,
1957d523bdcSHanna Hawa 	},
196dbfe8ef5SDan Williams 	[board_ahci_avn] = {
197dbfe8ef5SDan Williams 		.flags		= AHCI_FLAG_COMMON,
198dbfe8ef5SDan Williams 		.pio_mask	= ATA_PIO4,
199dbfe8ef5SDan Williams 		.udma_mask	= ATA_UDMA6,
200dbfe8ef5SDan Williams 		.port_ops	= &ahci_avn_ops,
201dbfe8ef5SDan Williams 	},
202facb8fa6SJeffrin Jose 	[board_ahci_mcp65] = {
20383f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
20483f2b963STejun Heo 				 AHCI_HFLAG_YES_NCQ),
205ae01b249STejun Heo 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
20683f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
20783f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
20883f2b963STejun Heo 		.port_ops	= &ahci_ops,
20983f2b963STejun Heo 	},
210facb8fa6SJeffrin Jose 	[board_ahci_mcp77] = {
21183f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),
21283f2b963STejun Heo 		.flags		= AHCI_FLAG_COMMON,
21383f2b963STejun Heo 		.pio_mask	= ATA_PIO4,
21483f2b963STejun Heo 		.udma_mask	= ATA_UDMA6,
21583f2b963STejun Heo 		.port_ops	= &ahci_ops,
21683f2b963STejun Heo 	},
217facb8fa6SJeffrin Jose 	[board_ahci_mcp89] = {
21883f2b963STejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),
219441577efSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
220441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
221441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
222441577efSTejun Heo 		.port_ops	= &ahci_ops,
223441577efSTejun Heo 	},
224facb8fa6SJeffrin Jose 	[board_ahci_mv] = {
225441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
226441577efSTejun Heo 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
2279cbe056fSSergei Shtylyov 		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
228441577efSTejun Heo 		.pio_mask	= ATA_PIO4,
229441577efSTejun Heo 		.udma_mask	= ATA_UDMA6,
230441577efSTejun Heo 		.port_ops	= &ahci_ops,
231441577efSTejun Heo 	},
232facb8fa6SJeffrin Jose 	[board_ahci_sb600] = {
233417a1a6dSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
2342fcad9d2STejun Heo 				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |
2352fcad9d2STejun Heo 				 AHCI_HFLAG_32BIT_ONLY),
236417a1a6dSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
23714bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
238469248abSJeff Garzik 		.udma_mask	= ATA_UDMA6,
239345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
24055a61604SConke Hu 	},
241facb8fa6SJeffrin Jose 	[board_ahci_sb700] = {	/* for SB700 and SB800 */
242bd17243aSShane Huang 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
243e39fc8c9SShane Huang 		.flags		= AHCI_FLAG_COMMON,
24414bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
245e39fc8c9SShane Huang 		.udma_mask	= ATA_UDMA6,
246345347c5SYuan-Hsin Chen 		.port_ops	= &ahci_pmp_retry_srst_ops,
247e39fc8c9SShane Huang 	},
248facb8fa6SJeffrin Jose 	[board_ahci_vt8251] = {
249441577efSTejun Heo 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
250e297d99eSTejun Heo 		.flags		= AHCI_FLAG_COMMON,
25114bdef98SErik Inge Bolsø 		.pio_mask	= ATA_PIO4,
252e297d99eSTejun Heo 		.udma_mask	= ATA_UDMA6,
253441577efSTejun Heo 		.port_ops	= &ahci_vt8251_ops,
2541b677afdSShaohua Li 	},
255c312ef17SDan Williams 	[board_ahci_pcs7] = {
256c312ef17SDan Williams 		.flags		= AHCI_FLAG_COMMON,
257c312ef17SDan Williams 		.pio_mask	= ATA_PIO4,
258c312ef17SDan Williams 		.udma_mask	= ATA_UDMA6,
259c312ef17SDan Williams 		.port_ops	= &ahci_ops,
260c312ef17SDan Williams 	},
261c6fd2807SJeff Garzik };
262c6fd2807SJeff Garzik 
263c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = {
264c6fd2807SJeff Garzik 	/* Intel */
2655e125d13SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x06d6), board_ahci }, /* Comet Lake PCH-H RAID */
26654bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
26754bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
26854bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
26954bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */
27054bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */
27182490c09STejun Heo 	{ PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */
27254bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */
27354bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
27454bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
27554bb3a94SJeff Garzik 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
2767a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
2770e96dc47SKrzysztof Kozlowski 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8/Lewisburg RAID*/
2787a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
2797a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
2807a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
2817a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
2827a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
2837a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
2847a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
2857a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
286099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x2929), board_ahci_low_power }, /* ICH9M */
287099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x292a), board_ahci_low_power }, /* ICH9M */
288099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x292b), board_ahci_low_power }, /* ICH9M */
289099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x292c), board_ahci_low_power }, /* ICH9M */
290099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x292f), board_ahci_low_power }, /* ICH9M */
2917a234affSTejun Heo 	{ PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
292099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci_low_power }, /* ICH9M */
293d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
294d4155e6fSJason Gaston 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
29516ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
296b2dde6afSMark Goodwin 	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
29716ad1ad9SJason Gaston 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
298c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
299c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
300adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
3018e48b6b3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
302099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci_low_power }, /* PCH M AHCI */
303adcb5308SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
304099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_low_power }, /* PCH M RAID */
305c1f57d9bSDavid Milburn 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
306c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci_pcs7 }, /* DNV AHCI */
307c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci_pcs7 }, /* DNV AHCI */
308c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b2), board_ahci_pcs7 }, /* DNV AHCI */
309c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b3), board_ahci_pcs7 }, /* DNV AHCI */
310c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b4), board_ahci_pcs7 }, /* DNV AHCI */
311c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b5), board_ahci_pcs7 }, /* DNV AHCI */
312c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b6), board_ahci_pcs7 }, /* DNV AHCI */
313c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19b7), board_ahci_pcs7 }, /* DNV AHCI */
314c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19bE), board_ahci_pcs7 }, /* DNV AHCI */
315c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19bF), board_ahci_pcs7 }, /* DNV AHCI */
316c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c0), board_ahci_pcs7 }, /* DNV AHCI */
317c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c1), board_ahci_pcs7 }, /* DNV AHCI */
318c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c2), board_ahci_pcs7 }, /* DNV AHCI */
319c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c3), board_ahci_pcs7 }, /* DNV AHCI */
320c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c4), board_ahci_pcs7 }, /* DNV AHCI */
321c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c5), board_ahci_pcs7 }, /* DNV AHCI */
322c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c6), board_ahci_pcs7 }, /* DNV AHCI */
323c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19c7), board_ahci_pcs7 }, /* DNV AHCI */
324c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci_pcs7 }, /* DNV AHCI */
325c312ef17SDan Williams 	{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci_pcs7 }, /* DNV AHCI */
3265623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
327099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci_low_power }, /* CPT M AHCI */
3285623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
329099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci_low_power }, /* CPT M RAID */
3305623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
3315623cab8SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
332992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
333992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
334992b3fb9SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
335a4a461a6SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
336181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
337099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci_low_power }, /* Panther M AHCI */
338181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
339181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
340181e3ceaSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
341099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci_low_power }, /* Panther M RAID */
3422cab7a4cSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
343ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
344099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci_low_power }, /* Lynx M AHCI */
345ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
346099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci_low_power }, /* Lynx M RAID */
347ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
348099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci_low_power }, /* Lynx M RAID */
349ea4ace66SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
350099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_low_power }, /* Lynx M RAID */
351099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci_low_power }, /* Lynx LP AHCI */
352099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci_low_power }, /* Lynx LP AHCI */
353099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci_low_power }, /* Lynx LP RAID */
354099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c05), board_ahci_low_power }, /* Lynx LP RAID */
355099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c06), board_ahci_low_power }, /* Lynx LP RAID */
356099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci_low_power }, /* Lynx LP RAID */
357099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_low_power }, /* Lynx LP RAID */
358099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_low_power }, /* Lynx LP RAID */
359099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_low_power }, /* Cannon Lake PCH-LP AHCI */
36029e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
36129e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
36229e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
36329e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */
36429e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */
36529e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
36629e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
36729e674ddSSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
368dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */
369dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */
370dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */
371dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */
372dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */
373dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
374dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
375dbfe8ef5SDan Williams 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
3760e96dc47SKrzysztof Kozlowski 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg/Lewisburg AHCI*/
3775716fb0dSDan Williams 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* *burg SATA0 'RAID' */
3785716fb0dSDan Williams 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* *burg SATA1 'RAID' */
3795716fb0dSDan Williams 	{ PCI_VDEVICE(INTEL, 0x282f), board_ahci }, /* *burg SATA2 'RAID' */
3808e85f605SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x43d4), board_ahci }, /* Rocket Lake PCH-H RAID */
3818e85f605SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x43d5), board_ahci }, /* Rocket Lake PCH-H RAID */
3828e85f605SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x43d6), board_ahci }, /* Rocket Lake PCH-H RAID */
3838e85f605SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0x43d7), board_ahci }, /* Rocket Lake PCH-H RAID */
384151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
385151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
386151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
387151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
388151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
389151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
390151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
391151743fdSJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
3921cfc7df3SSeth Heasley 	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
393099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci_low_power }, /* Wildcat LP AHCI */
394099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci_low_power }, /* Wildcat LP RAID */
395099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci_low_power }, /* Wildcat LP RAID */
396099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_low_power }, /* Wildcat LP RAID */
3971b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
398099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci_low_power }, /* 9 Series M AHCI */
3991b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
400099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci_low_power }, /* 9 Series M RAID */
4011b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
402099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci_low_power }, /* 9 Series M RAID */
4031b071a09SJames Ralston 	{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
404099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_low_power }, /* 9 Series M RAID */
405099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9d03), board_ahci_low_power }, /* Sunrise LP AHCI */
406099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9d05), board_ahci_low_power }, /* Sunrise LP RAID */
407099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x9d07), board_ahci_low_power }, /* Sunrise LP RAID */
408c5967b79SCharles_Rose@Dell.com 	{ PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */
409099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0xa103), board_ahci_low_power }, /* Sunrise M AHCI */
410690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
411c5967b79SCharles_Rose@Dell.com 	{ PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */
412099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci_low_power }, /* Sunrise M RAID */
413690000b9SJames Ralston 	{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
4144d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
4154d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
416f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
417f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
4184d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
4194d92f009SAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
420f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
421f5bdd66cSAlexandra Yates 	{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
422f919dde0SMika Westerberg 	{ PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */
42332d25454SKai-Heng Feng 	{ PCI_VDEVICE(INTEL, 0x06d7), board_ahci }, /* Comet Lake-H RAID */
42458c42b0bSMika Westerberg 	{ PCI_VDEVICE(INTEL, 0xa386), board_ahci }, /* Comet Lake PCH-V RAID */
425099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x0f22), board_ahci_low_power }, /* Bay Trail AHCI */
426099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x0f23), board_ahci_low_power }, /* Bay Trail AHCI */
427099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x22a3), board_ahci_low_power }, /* Cherry Tr. AHCI */
428099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_low_power }, /* ApolloLake AHCI */
429099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x34d3), board_ahci_low_power }, /* Ice Lake LP AHCI */
430099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x02d3), board_ahci_low_power }, /* Comet Lake PCH-U AHCI */
431099849afSMario Limonciello 	{ PCI_VDEVICE(INTEL, 0x02d7), board_ahci_low_power }, /* Comet Lake PCH RAID */
4322a2df98eSWerner Fischer 	/* Elkhart Lake IDs 0x4b60 & 0x4b62 https://sata-io.org/product/8803 not tested yet */
4332a2df98eSWerner Fischer 	{ PCI_VDEVICE(INTEL, 0x4b63), board_ahci_low_power }, /* Elkhart Lake AHCI */
434c6fd2807SJeff Garzik 
435e34bb370STejun Heo 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
436e34bb370STejun Heo 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
437e34bb370STejun Heo 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
4381fefb8fdSBen Hutchings 	/* JMicron 362B and 362C have an AHCI function with IDE class code */
4391fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
4401fefb8fdSBen Hutchings 	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
44191f15fb3SZhang Rui 	/* May need to update quirk_jmicron_async_suspend() for additions */
442c6fd2807SJeff Garzik 
443c6fd2807SJeff Garzik 	/* ATI */
444c65ec1c2SConke Hu 	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
445e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */
446e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */
447e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */
448e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */
449e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */
450e39fc8c9SShane Huang 	{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
451c6fd2807SJeff Garzik 
4527d523bdcSHanna Hawa 	/* Amazon's Annapurna Labs support */
4537d523bdcSHanna Hawa 	{ PCI_DEVICE(PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031),
4547d523bdcSHanna Hawa 		.class = PCI_CLASS_STORAGE_SATA_AHCI,
4557d523bdcSHanna Hawa 		.class_mask = 0xffffff,
4567d523bdcSHanna Hawa 		board_ahci_al },
457e2dd90b1SShane Huang 	/* AMD */
4585deab536SShane Huang 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
459a17ab7abSPaul Menzel 	{ PCI_VDEVICE(AMD, 0x7801), board_ahci_no_debounce_delay }, /* AMD Hudson-2 (AHCI mode) */
460fafe5c3dSShane Huang 	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
461099849afSMario Limonciello 	{ PCI_VDEVICE(AMD, 0x7901), board_ahci_low_power }, /* AMD Green Sardine */
462e2dd90b1SShane Huang 	/* AMD is using RAID class only for ahci controllers */
463e2dd90b1SShane Huang 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
464e2dd90b1SShane Huang 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
465e2dd90b1SShane Huang 
4669c54cd10SCharles Rose 	/* Dell S140/S150 */
4679c54cd10SCharles Rose 	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_SUBVENDOR_ID_DELL, PCI_ANY_ID,
4689c54cd10SCharles Rose 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
4699c54cd10SCharles Rose 
470c6fd2807SJeff Garzik 	/* VIA */
47154bb3a94SJeff Garzik 	{ PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */
472bf335542STejun Heo 	{ PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */
473c6fd2807SJeff Garzik 
474c6fd2807SJeff Garzik 	/* NVIDIA */
475e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 },	/* MCP65 */
476e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 },	/* MCP65 */
477e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 },	/* MCP65 */
478e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 },	/* MCP65 */
479e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 },	/* MCP65 */
480e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 },	/* MCP65 */
481e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 },	/* MCP65 */
482e297d99eSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 },	/* MCP65 */
483441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 },	/* MCP67 */
484441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 },	/* MCP67 */
485441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 },	/* MCP67 */
486441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 },	/* MCP67 */
487441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 },	/* MCP67 */
488441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 },	/* MCP67 */
489441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 },	/* MCP67 */
490441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 },	/* MCP67 */
491441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 },	/* MCP67 */
492441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 },	/* MCP67 */
493441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 },	/* MCP67 */
494441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 },	/* MCP67 */
495441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux },	/* Linux ID */
496441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux },	/* Linux ID */
497441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux },	/* Linux ID */
498441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux },	/* Linux ID */
499441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux },	/* Linux ID */
500441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux },	/* Linux ID */
501441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux },	/* Linux ID */
502441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux },	/* Linux ID */
503441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux },	/* Linux ID */
504441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux },	/* Linux ID */
505441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux },	/* Linux ID */
506441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux },	/* Linux ID */
507441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux },	/* Linux ID */
508441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux },	/* Linux ID */
509441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux },	/* Linux ID */
510441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux },	/* Linux ID */
511441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 },	/* MCP73 */
512441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 },	/* MCP73 */
513441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 },	/* MCP73 */
514441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 },	/* MCP73 */
515441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 },	/* MCP73 */
516441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 },	/* MCP73 */
517441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 },	/* MCP73 */
518441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 },	/* MCP73 */
519441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 },	/* MCP73 */
520441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 },	/* MCP73 */
521441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 },	/* MCP73 */
522441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 },	/* MCP73 */
523441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 },	/* MCP77 */
524441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 },	/* MCP77 */
525441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 },	/* MCP77 */
526441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 },	/* MCP77 */
527441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 },	/* MCP77 */
528441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 },	/* MCP77 */
529441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 },	/* MCP77 */
530441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 },	/* MCP77 */
531441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 },	/* MCP77 */
532441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 },	/* MCP77 */
533441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 },	/* MCP77 */
534441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 },	/* MCP77 */
535441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 },	/* MCP79 */
536441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 },	/* MCP79 */
537441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 },	/* MCP79 */
538441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 },	/* MCP79 */
539441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 },	/* MCP79 */
540441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 },	/* MCP79 */
541441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 },	/* MCP79 */
542441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 },	/* MCP79 */
543441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 },	/* MCP79 */
544441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 },	/* MCP79 */
545441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 },	/* MCP79 */
546441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 },	/* MCP79 */
547441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 },	/* MCP89 */
548441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 },	/* MCP89 */
549441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 },	/* MCP89 */
550441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 },	/* MCP89 */
551441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 },	/* MCP89 */
552441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 },	/* MCP89 */
553441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 },	/* MCP89 */
554441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 },	/* MCP89 */
555441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 },	/* MCP89 */
556441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 },	/* MCP89 */
557441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 },	/* MCP89 */
558441577efSTejun Heo 	{ PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 },	/* MCP89 */
559c6fd2807SJeff Garzik 
560c6fd2807SJeff Garzik 	/* SiS */
56120e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1184), board_ahci },		/* SiS 966 */
56220e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */
56320e2de4aSTejun Heo 	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */
564c6fd2807SJeff Garzik 
565318893e1SAlessandro Rubini 	/* ST Microelectronics */
566318893e1SAlessandro Rubini 	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */
567318893e1SAlessandro Rubini 
568cd70c266SJeff Garzik 	/* Marvell */
569cd70c266SJeff Garzik 	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
570c40e7cb8SJose Alberto Reguero 	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */
57169fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
57210aca06cSAnssi Hannula 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
57310aca06cSAnssi Hannula 	  .class_mask = 0xffffff,
5745f173107STejun Heo 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
57569fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
576467b41c6SPer Jessen 	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
577e098f5cbSSimon Guinot 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
578e098f5cbSSimon Guinot 			 PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
579e098f5cbSSimon Guinot 	  .driver_data = board_ahci_yes_fbs },			/* 88se9170 */
58069fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
581642d8925SMatt Johnson 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
582fcce9a35SGeorge Spelvin 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
583c5edfff9SMurali Karicheri 	  .driver_data = board_ahci_yes_fbs },			/* 88se9182 */
584c5edfff9SMurali Karicheri 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
585fcce9a35SGeorge Spelvin 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */
58669fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
58717c60c6bSAlan Cox 	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */
588754a292fSAndreas Schrägle 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0),
589754a292fSAndreas Schrägle 	  .driver_data = board_ahci_yes_fbs },
590a40cf3f3SJohannes Thumshirn 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), 	/* 88se91a2 */
591a40cf3f3SJohannes Thumshirn 	  .driver_data = board_ahci_yes_fbs },
59269fd3157SMyron Stowe 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
59350be5e36STejun Heo 	  .driver_data = board_ahci_yes_fbs },
5946d5278a6SSamir Benmendil 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
5956d5278a6SSamir Benmendil 	  .driver_data = board_ahci_yes_fbs },
596f4a8d4f2SPaul Menzel 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9235),
597f4a8d4f2SPaul Menzel 	  .driver_data = board_ahci_no_debounce_delay },
59828b2182dSHans de Goede 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */
59928b2182dSHans de Goede 	  .driver_data = board_ahci_yes_fbs },
60028b2182dSHans de Goede 	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */
601d2518365SJérôme Carretero 	  .driver_data = board_ahci_yes_fbs },
602cd70c266SJeff Garzik 
603c77a036bSMark Nelson 	/* Promise */
604c77a036bSMark Nelson 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
605b32bfc06SRomain Degez 	{ PCI_VDEVICE(PROMISE, 0x3781), board_ahci },   /* FastTrak TX8660 ahci-mode */
606c77a036bSMark Nelson 
607b0dd4d7aSLennert Buytenhek 	/* ASMedia */
608f6e4aca0SLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci_43bit_dma },	/* ASM1060 */
609f6e4aca0SLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci_43bit_dma },	/* ASM1060 */
610b0dd4d7aSLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci_43bit_dma },	/* ASM1061 */
611b0dd4d7aSLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci_43bit_dma },	/* ASM1061/1062 */
612f6e4aca0SLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci_43bit_dma },	/* ASM1061R */
613f6e4aca0SLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci_43bit_dma },	/* ASM1062R */
614f6e4aca0SLennert Buytenhek 	{ PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci_43bit_dma },	/* ASM1062+JMB575 */
6151f9b7a5dSSzuying Chen 	{ PCI_VDEVICE(ASMEDIA, 0x1062), board_ahci },	/* ASM1062A */
6161f9b7a5dSSzuying Chen 	{ PCI_VDEVICE(ASMEDIA, 0x1064), board_ahci },	/* ASM1064 */
6171f9b7a5dSSzuying Chen 	{ PCI_VDEVICE(ASMEDIA, 0x1164), board_ahci },   /* ASM1164 */
6181f9b7a5dSSzuying Chen 	{ PCI_VDEVICE(ASMEDIA, 0x1165), board_ahci },   /* ASM1165 */
6191f9b7a5dSSzuying Chen 	{ PCI_VDEVICE(ASMEDIA, 0x1166), board_ahci },   /* ASM1166 */
620c9703765SKeng-Yu Lin 
62167809f85SLevente Kurusa 	/*
62266a7cbc3STejun Heo 	 * Samsung SSDs found on some macbooks.  NCQ times out if MSI is
62366a7cbc3STejun Heo 	 * enabled.  https://bugzilla.kernel.org/show_bug.cgi?id=60731
62467809f85SLevente Kurusa 	 */
62566a7cbc3STejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
6262b21ef0aSTejun Heo 	{ PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi },
62767809f85SLevente Kurusa 
6287f9c9f8eSHugh Daschbach 	/* Enmotus */
6297f9c9f8eSHugh Daschbach 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
6307f9c9f8eSHugh Daschbach 
631e49bd683STiezhu Yang 	/* Loongson */
632e49bd683STiezhu Yang 	{ PCI_VDEVICE(LOONGSON, 0x7a08), board_ahci },
633e49bd683STiezhu Yang 
634415ae2b5SJeff Garzik 	/* Generic, PCI class code for AHCI */
635415ae2b5SJeff Garzik 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
636c9f89475SConke Hu 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
637415ae2b5SJeff Garzik 
638c6fd2807SJeff Garzik 	{ }	/* terminate list */
639c6fd2807SJeff Garzik };
640c6fd2807SJeff Garzik 
641f1d848f9SMika Westerberg static const struct dev_pm_ops ahci_pci_pm_ops = {
642f1d848f9SMika Westerberg 	SET_SYSTEM_SLEEP_PM_OPS(ahci_pci_device_suspend, ahci_pci_device_resume)
64302e53293SMika Westerberg 	SET_RUNTIME_PM_OPS(ahci_pci_device_runtime_suspend,
64402e53293SMika Westerberg 			   ahci_pci_device_runtime_resume, NULL)
645f1d848f9SMika Westerberg };
646c6fd2807SJeff Garzik 
647c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = {
648c6fd2807SJeff Garzik 	.name			= DRV_NAME,
649c6fd2807SJeff Garzik 	.id_table		= ahci_pci_tbl,
650c6fd2807SJeff Garzik 	.probe			= ahci_init_one,
65102e53293SMika Westerberg 	.remove			= ahci_remove_one,
65210a663a1SPrabhakar Kushwaha 	.shutdown		= ahci_shutdown_one,
653f1d848f9SMika Westerberg 	.driver = {
654f1d848f9SMika Westerberg 		.pm		= &ahci_pci_pm_ops,
655f1d848f9SMika Westerberg 	},
656c6fd2807SJeff Garzik };
657c6fd2807SJeff Garzik 
6585219d653SJavier Martinez Canillas #if IS_ENABLED(CONFIG_PATA_MARVELL)
6595b66c829SAlan Cox static int marvell_enable;
6605b66c829SAlan Cox #else
6615b66c829SAlan Cox static int marvell_enable = 1;
6625b66c829SAlan Cox #endif
6635b66c829SAlan Cox module_param(marvell_enable, int, 0644);
6645b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
6655b66c829SAlan Cox 
666b1a9585cSSrinivas Pandruvada static int mobile_lpm_policy = -1;
667ebb82e3cSHans de Goede module_param(mobile_lpm_policy, int, 0644);
668ebb82e3cSHans de Goede MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
6695b66c829SAlan Cox 
670*9c122d02SDamien Le Moal static char *ahci_mask_port_map;
671*9c122d02SDamien Le Moal module_param_named(mask_port_map, ahci_mask_port_map, charp, 0444);
672*9c122d02SDamien Le Moal MODULE_PARM_DESC(mask_port_map,
673*9c122d02SDamien Le Moal 		 "32-bits port map masks to ignore controllers ports. "
674*9c122d02SDamien Le Moal 		 "Valid values are: "
675*9c122d02SDamien Le Moal 		 "\"<mask>\" to apply the same mask to all AHCI controller "
676*9c122d02SDamien Le Moal 		 "devices, and \"<pci_dev>=<mask>,<pci_dev>=<mask>,...\" to "
677*9c122d02SDamien Le Moal 		 "specify different masks for the controllers specified, "
678*9c122d02SDamien Le Moal 		 "where <pci_dev> is the PCI ID of an AHCI controller in the "
679*9c122d02SDamien Le Moal 		 "form \"domain:bus:dev.func\"");
680*9c122d02SDamien Le Moal 
ahci_apply_port_map_mask(struct device * dev,struct ahci_host_priv * hpriv,char * mask_s)681*9c122d02SDamien Le Moal static void ahci_apply_port_map_mask(struct device *dev,
682*9c122d02SDamien Le Moal 				     struct ahci_host_priv *hpriv, char *mask_s)
683*9c122d02SDamien Le Moal {
684*9c122d02SDamien Le Moal 	unsigned int mask;
685*9c122d02SDamien Le Moal 
686*9c122d02SDamien Le Moal 	if (kstrtouint(mask_s, 0, &mask)) {
687*9c122d02SDamien Le Moal 		dev_err(dev, "Invalid port map mask\n");
688*9c122d02SDamien Le Moal 		return;
689*9c122d02SDamien Le Moal 	}
690*9c122d02SDamien Le Moal 
691*9c122d02SDamien Le Moal 	hpriv->mask_port_map = mask;
692*9c122d02SDamien Le Moal }
693*9c122d02SDamien Le Moal 
ahci_get_port_map_mask(struct device * dev,struct ahci_host_priv * hpriv)694*9c122d02SDamien Le Moal static void ahci_get_port_map_mask(struct device *dev,
695*9c122d02SDamien Le Moal 				   struct ahci_host_priv *hpriv)
696*9c122d02SDamien Le Moal {
697*9c122d02SDamien Le Moal 	char *param, *end, *str, *mask_s;
698*9c122d02SDamien Le Moal 	char *name;
699*9c122d02SDamien Le Moal 
700*9c122d02SDamien Le Moal 	if (!strlen(ahci_mask_port_map))
701*9c122d02SDamien Le Moal 		return;
702*9c122d02SDamien Le Moal 
703*9c122d02SDamien Le Moal 	str = kstrdup(ahci_mask_port_map, GFP_KERNEL);
704*9c122d02SDamien Le Moal 	if (!str)
705*9c122d02SDamien Le Moal 		return;
706*9c122d02SDamien Le Moal 
707*9c122d02SDamien Le Moal 	/* Handle single mask case */
708*9c122d02SDamien Le Moal 	if (!strchr(str, '=')) {
709*9c122d02SDamien Le Moal 		ahci_apply_port_map_mask(dev, hpriv, str);
710*9c122d02SDamien Le Moal 		goto free;
711*9c122d02SDamien Le Moal 	}
712*9c122d02SDamien Le Moal 
713*9c122d02SDamien Le Moal 	/*
714*9c122d02SDamien Le Moal 	 * Mask list case: parse the parameter to apply the mask only if
715*9c122d02SDamien Le Moal 	 * the device name matches.
716*9c122d02SDamien Le Moal 	 */
717*9c122d02SDamien Le Moal 	param = str;
718*9c122d02SDamien Le Moal 	end = param + strlen(param);
719*9c122d02SDamien Le Moal 	while (param && param < end && *param) {
720*9c122d02SDamien Le Moal 		name = param;
721*9c122d02SDamien Le Moal 		param = strchr(name, '=');
722*9c122d02SDamien Le Moal 		if (!param)
723*9c122d02SDamien Le Moal 			break;
724*9c122d02SDamien Le Moal 
725*9c122d02SDamien Le Moal 		*param = '\0';
726*9c122d02SDamien Le Moal 		param++;
727*9c122d02SDamien Le Moal 		if (param >= end)
728*9c122d02SDamien Le Moal 			break;
729*9c122d02SDamien Le Moal 
730*9c122d02SDamien Le Moal 		if (strcmp(dev_name(dev), name) != 0) {
731*9c122d02SDamien Le Moal 			param = strchr(param, ',');
732*9c122d02SDamien Le Moal 			if (param)
733*9c122d02SDamien Le Moal 				param++;
734*9c122d02SDamien Le Moal 			continue;
735*9c122d02SDamien Le Moal 		}
736*9c122d02SDamien Le Moal 
737*9c122d02SDamien Le Moal 		mask_s = param;
738*9c122d02SDamien Le Moal 		param = strchr(mask_s, ',');
739*9c122d02SDamien Le Moal 		if (param) {
740*9c122d02SDamien Le Moal 			*param = '\0';
741*9c122d02SDamien Le Moal 			param++;
742*9c122d02SDamien Le Moal 		}
743*9c122d02SDamien Le Moal 
744*9c122d02SDamien Le Moal 		ahci_apply_port_map_mask(dev, hpriv, mask_s);
745*9c122d02SDamien Le Moal 	}
746*9c122d02SDamien Le Moal 
747*9c122d02SDamien Le Moal free:
748*9c122d02SDamien Le Moal 	kfree(str);
749*9c122d02SDamien Le Moal }
750*9c122d02SDamien Le Moal 
ahci_pci_save_initial_config(struct pci_dev * pdev,struct ahci_host_priv * hpriv)751394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev,
752394d6e53SAnton Vorontsov 					 struct ahci_host_priv *hpriv)
753394d6e53SAnton Vorontsov {
754394d6e53SAnton Vorontsov 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
755394d6e53SAnton Vorontsov 		dev_info(&pdev->dev, "JMB361 has only one port\n");
75688589772SSerge Semin 		hpriv->saved_port_map = 1;
757394d6e53SAnton Vorontsov 	}
758394d6e53SAnton Vorontsov 
759394d6e53SAnton Vorontsov 	/*
760394d6e53SAnton Vorontsov 	 * Temporary Marvell 6145 hack: PATA port presence
761394d6e53SAnton Vorontsov 	 * is asserted through the standard AHCI port
762394d6e53SAnton Vorontsov 	 * presence register, as bit 4 (counting from 0)
763394d6e53SAnton Vorontsov 	 */
764394d6e53SAnton Vorontsov 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
765394d6e53SAnton Vorontsov 		if (pdev->device == 0x6121)
7669a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0x3;
767394d6e53SAnton Vorontsov 		else
7689a23c1d6SAntoine Tenart 			hpriv->mask_port_map = 0xf;
769394d6e53SAnton Vorontsov 		dev_info(&pdev->dev,
770394d6e53SAnton Vorontsov 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
771394d6e53SAnton Vorontsov 	}
772394d6e53SAnton Vorontsov 
773*9c122d02SDamien Le Moal 	/* Handle port map masks passed as module parameter. */
774*9c122d02SDamien Le Moal 	if (ahci_mask_port_map)
775*9c122d02SDamien Le Moal 		ahci_get_port_map_mask(&pdev->dev, hpriv);
776*9c122d02SDamien Le Moal 
777725c7b57SAntoine Ténart 	ahci_save_initial_config(&pdev->dev, hpriv);
778394d6e53SAnton Vorontsov }
779394d6e53SAnton Vorontsov 
ahci_pci_reset_controller(struct ata_host * host)78037e14e4fSAdam Vodopjan static int ahci_pci_reset_controller(struct ata_host *host)
78137e14e4fSAdam Vodopjan {
78237e14e4fSAdam Vodopjan 	struct pci_dev *pdev = to_pci_dev(host->dev);
78337e14e4fSAdam Vodopjan 	struct ahci_host_priv *hpriv = host->private_data;
78437e14e4fSAdam Vodopjan 	int rc;
78537e14e4fSAdam Vodopjan 
78637e14e4fSAdam Vodopjan 	rc = ahci_reset_controller(host);
78737e14e4fSAdam Vodopjan 	if (rc)
78837e14e4fSAdam Vodopjan 		return rc;
78937e14e4fSAdam Vodopjan 
79037e14e4fSAdam Vodopjan 	/*
79137e14e4fSAdam Vodopjan 	 * If platform firmware failed to enable ports, try to enable
79237e14e4fSAdam Vodopjan 	 * them here.
79337e14e4fSAdam Vodopjan 	 */
79437e14e4fSAdam Vodopjan 	ahci_intel_pcs_quirk(pdev, hpriv);
79537e14e4fSAdam Vodopjan 
79637e14e4fSAdam Vodopjan 	return 0;
79737e14e4fSAdam Vodopjan }
79837e14e4fSAdam Vodopjan 
ahci_pci_init_controller(struct ata_host * host)799781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host)
800781d6550SAnton Vorontsov {
801781d6550SAnton Vorontsov 	struct ahci_host_priv *hpriv = host->private_data;
802781d6550SAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
803781d6550SAnton Vorontsov 	void __iomem *port_mmio;
804781d6550SAnton Vorontsov 	u32 tmp;
805c40e7cb8SJose Alberto Reguero 	int mv;
8062bcd866bSJeff Garzik 
807417a1a6dSTejun Heo 	if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
808c40e7cb8SJose Alberto Reguero 		if (pdev->device == 0x6121)
809c40e7cb8SJose Alberto Reguero 			mv = 2;
810c40e7cb8SJose Alberto Reguero 		else
811c40e7cb8SJose Alberto Reguero 			mv = 4;
8127cbbfbe0SSerge Semin 		port_mmio = __ahci_port_base(hpriv, mv);
813cd70c266SJeff Garzik 
814cd70c266SJeff Garzik 		writel(0, port_mmio + PORT_IRQ_MASK);
815cd70c266SJeff Garzik 
816cd70c266SJeff Garzik 		/* clear port IRQ */
817cd70c266SJeff Garzik 		tmp = readl(port_mmio + PORT_IRQ_STAT);
81893c77114SHannes Reinecke 		dev_dbg(&pdev->dev, "PORT_IRQ_STAT 0x%x\n", tmp);
819cd70c266SJeff Garzik 		if (tmp)
820cd70c266SJeff Garzik 			writel(tmp, port_mmio + PORT_IRQ_STAT);
821cd70c266SJeff Garzik 	}
822cd70c266SJeff Garzik 
823781d6550SAnton Vorontsov 	ahci_init_controller(host);
824c6fd2807SJeff Garzik }
825c6fd2807SJeff Garzik 
ahci_vt8251_hardreset(struct ata_link * link,unsigned int * class,unsigned long deadline)826cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
827d4b2bab4STejun Heo 				 unsigned long deadline)
828ad616ffbSTejun Heo {
829cc0680a5STejun Heo 	struct ata_port *ap = link->ap;
830039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
8319dadd45bSTejun Heo 	bool online;
832ad616ffbSTejun Heo 	int rc;
833ad616ffbSTejun Heo 
834fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
835ad616ffbSTejun Heo 
836cc0680a5STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
8379dadd45bSTejun Heo 				 deadline, &online, NULL);
838ad616ffbSTejun Heo 
839039ece38SHans de Goede 	hpriv->start_engine(ap);
840ad616ffbSTejun Heo 
841ad616ffbSTejun Heo 	/* vt8251 doesn't clear BSY on signature FIS reception,
842ad616ffbSTejun Heo 	 * request follow-up softreset.
843ad616ffbSTejun Heo 	 */
8449dadd45bSTejun Heo 	return online ? -EAGAIN : rc;
845ad616ffbSTejun Heo }
846ad616ffbSTejun Heo 
ahci_p5wdh_hardreset(struct ata_link * link,unsigned int * class,unsigned long deadline)847edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
848edc93052STejun Heo 				unsigned long deadline)
849edc93052STejun Heo {
850edc93052STejun Heo 	struct ata_port *ap = link->ap;
851edc93052STejun Heo 	struct ahci_port_priv *pp = ap->private_data;
852039ece38SHans de Goede 	struct ahci_host_priv *hpriv = ap->host->private_data;
853edc93052STejun Heo 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
854edc93052STejun Heo 	struct ata_taskfile tf;
8559dadd45bSTejun Heo 	bool online;
856edc93052STejun Heo 	int rc;
857edc93052STejun Heo 
858fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
859edc93052STejun Heo 
860edc93052STejun Heo 	/* clear D2H reception area to properly wait for D2H FIS */
861edc93052STejun Heo 	ata_tf_init(link->device, &tf);
862efcef265SSergey Shtylyov 	tf.status = ATA_BUSY;
863edc93052STejun Heo 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
864edc93052STejun Heo 
865edc93052STejun Heo 	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
8669dadd45bSTejun Heo 				 deadline, &online, NULL);
867edc93052STejun Heo 
868039ece38SHans de Goede 	hpriv->start_engine(ap);
869edc93052STejun Heo 
870edc93052STejun Heo 	/* The pseudo configuration device on SIMG4726 attached to
871edc93052STejun Heo 	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
872edc93052STejun Heo 	 * hardreset if no device is attached to the first downstream
873edc93052STejun Heo 	 * port && the pseudo device locks up on SRST w/ PMP==0.  To
874edc93052STejun Heo 	 * work around this, wait for !BSY only briefly.  If BSY isn't
875edc93052STejun Heo 	 * cleared, perform CLO and proceed to IDENTIFY (achieved by
876edc93052STejun Heo 	 * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA).
877edc93052STejun Heo 	 *
878edc93052STejun Heo 	 * Wait for two seconds.  Devices attached to downstream port
879edc93052STejun Heo 	 * which can't process the following IDENTIFY after this will
880edc93052STejun Heo 	 * have to be reset again.  For most cases, this should
881edc93052STejun Heo 	 * suffice while making probing snappish enough.
882edc93052STejun Heo 	 */
8839dadd45bSTejun Heo 	if (online) {
8849dadd45bSTejun Heo 		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
8859dadd45bSTejun Heo 					  ahci_check_ready);
886edc93052STejun Heo 		if (rc)
88778d5ae39SShane Huang 			ahci_kick_engine(ap);
8889dadd45bSTejun Heo 	}
8899dadd45bSTejun Heo 	return rc;
890edc93052STejun Heo }
891edc93052STejun Heo 
892dbfe8ef5SDan Williams /*
893dbfe8ef5SDan Williams  * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports.
894dbfe8ef5SDan Williams  *
895dbfe8ef5SDan Williams  * It has been observed with some SSDs that the timing of events in the
896dbfe8ef5SDan Williams  * link synchronization phase can leave the port in a state that can not
897dbfe8ef5SDan Williams  * be recovered by a SATA-hard-reset alone.  The failing signature is
898dbfe8ef5SDan Williams  * SStatus.DET stuck at 1 ("Device presence detected but Phy
899dbfe8ef5SDan Williams  * communication not established").  It was found that unloading and
900dbfe8ef5SDan Williams  * reloading the driver when this problem occurs allows the drive
901dbfe8ef5SDan Williams  * connection to be recovered (DET advanced to 0x3).  The critical
902dbfe8ef5SDan Williams  * component of reloading the driver is that the port state machines are
903dbfe8ef5SDan Williams  * reset by bouncing "port enable" in the AHCI PCS configuration
904dbfe8ef5SDan Williams  * register.  So, reproduce that effect by bouncing a port whenever we
905dbfe8ef5SDan Williams  * see DET==1 after a reset.
906dbfe8ef5SDan Williams  */
ahci_avn_hardreset(struct ata_link * link,unsigned int * class,unsigned long deadline)907dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
908dbfe8ef5SDan Williams 			      unsigned long deadline)
909dbfe8ef5SDan Williams {
910d14d41ccSSergey Shtylyov 	const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context);
911dbfe8ef5SDan Williams 	struct ata_port *ap = link->ap;
912dbfe8ef5SDan Williams 	struct ahci_port_priv *pp = ap->private_data;
913dbfe8ef5SDan Williams 	struct ahci_host_priv *hpriv = ap->host->private_data;
914dbfe8ef5SDan Williams 	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
915dbfe8ef5SDan Williams 	unsigned long tmo = deadline - jiffies;
916dbfe8ef5SDan Williams 	struct ata_taskfile tf;
917dbfe8ef5SDan Williams 	bool online;
918dbfe8ef5SDan Williams 	int rc, i;
919dbfe8ef5SDan Williams 
920fa89f53bSEvan Wang 	hpriv->stop_engine(ap);
921dbfe8ef5SDan Williams 
922dbfe8ef5SDan Williams 	for (i = 0; i < 2; i++) {
923dbfe8ef5SDan Williams 		u16 val;
924dbfe8ef5SDan Williams 		u32 sstatus;
925dbfe8ef5SDan Williams 		int port = ap->port_no;
926dbfe8ef5SDan Williams 		struct ata_host *host = ap->host;
927dbfe8ef5SDan Williams 		struct pci_dev *pdev = to_pci_dev(host->dev);
928dbfe8ef5SDan Williams 
929dbfe8ef5SDan Williams 		/* clear D2H reception area to properly wait for D2H FIS */
930dbfe8ef5SDan Williams 		ata_tf_init(link->device, &tf);
931efcef265SSergey Shtylyov 		tf.status = ATA_BUSY;
932dbfe8ef5SDan Williams 		ata_tf_to_fis(&tf, 0, 0, d2h_fis);
933dbfe8ef5SDan Williams 
934dbfe8ef5SDan Williams 		rc = sata_link_hardreset(link, timing, deadline, &online,
935dbfe8ef5SDan Williams 				ahci_check_ready);
936dbfe8ef5SDan Williams 
937dbfe8ef5SDan Williams 		if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 ||
938dbfe8ef5SDan Williams 				(sstatus & 0xf) != 1)
939dbfe8ef5SDan Williams 			break;
940dbfe8ef5SDan Williams 
941e276c9bdSXu Wang 		ata_link_info(link,  "avn bounce port%d\n", port);
942dbfe8ef5SDan Williams 
943dbfe8ef5SDan Williams 		pci_read_config_word(pdev, 0x92, &val);
944dbfe8ef5SDan Williams 		val &= ~(1 << port);
945dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
946dbfe8ef5SDan Williams 		ata_msleep(ap, 1000);
947dbfe8ef5SDan Williams 		val |= 1 << port;
948dbfe8ef5SDan Williams 		pci_write_config_word(pdev, 0x92, val);
949dbfe8ef5SDan Williams 		deadline += tmo;
950dbfe8ef5SDan Williams 	}
951dbfe8ef5SDan Williams 
952dbfe8ef5SDan Williams 	hpriv->start_engine(ap);
953dbfe8ef5SDan Williams 
954dbfe8ef5SDan Williams 	if (online)
955dbfe8ef5SDan Williams 		*class = ahci_dev_classify(ap);
956dbfe8ef5SDan Williams 
957dbfe8ef5SDan Williams 	return rc;
958dbfe8ef5SDan Williams }
959dbfe8ef5SDan Williams 
960dbfe8ef5SDan Williams 
96102e53293SMika Westerberg #ifdef CONFIG_PM
ahci_pci_disable_interrupts(struct ata_host * host)96202e53293SMika Westerberg static void ahci_pci_disable_interrupts(struct ata_host *host)
963c6fd2807SJeff Garzik {
9649b10ae86STejun Heo 	struct ahci_host_priv *hpriv = host->private_data;
965d8993349SAnton Vorontsov 	void __iomem *mmio = hpriv->mmio;
966c6fd2807SJeff Garzik 	u32 ctl;
967c6fd2807SJeff Garzik 
968c6fd2807SJeff Garzik 	/* AHCI spec rev1.1 section 8.3.3:
969c6fd2807SJeff Garzik 	 * Software must disable interrupts prior to requesting a
970c6fd2807SJeff Garzik 	 * transition of the HBA to D3 state.
971c6fd2807SJeff Garzik 	 */
972c6fd2807SJeff Garzik 	ctl = readl(mmio + HOST_CTL);
973c6fd2807SJeff Garzik 	ctl &= ~HOST_IRQ_EN;
974c6fd2807SJeff Garzik 	writel(ctl, mmio + HOST_CTL);
975c6fd2807SJeff Garzik 	readl(mmio + HOST_CTL); /* flush */
97602e53293SMika Westerberg }
977f1d848f9SMika Westerberg 
ahci_pci_device_runtime_suspend(struct device * dev)97802e53293SMika Westerberg static int ahci_pci_device_runtime_suspend(struct device *dev)
97902e53293SMika Westerberg {
98002e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
98102e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
98202e53293SMika Westerberg 
98302e53293SMika Westerberg 	ahci_pci_disable_interrupts(host);
98402e53293SMika Westerberg 	return 0;
98502e53293SMika Westerberg }
98602e53293SMika Westerberg 
ahci_pci_device_runtime_resume(struct device * dev)98702e53293SMika Westerberg static int ahci_pci_device_runtime_resume(struct device *dev)
98802e53293SMika Westerberg {
98902e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
99002e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
99102e53293SMika Westerberg 	int rc;
99202e53293SMika Westerberg 
99337e14e4fSAdam Vodopjan 	rc = ahci_pci_reset_controller(host);
99402e53293SMika Westerberg 	if (rc)
99502e53293SMika Westerberg 		return rc;
99602e53293SMika Westerberg 	ahci_pci_init_controller(host);
99702e53293SMika Westerberg 	return 0;
99802e53293SMika Westerberg }
99902e53293SMika Westerberg 
100002e53293SMika Westerberg #ifdef CONFIG_PM_SLEEP
ahci_pci_device_suspend(struct device * dev)100102e53293SMika Westerberg static int ahci_pci_device_suspend(struct device *dev)
100202e53293SMika Westerberg {
100302e53293SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
100402e53293SMika Westerberg 	struct ata_host *host = pci_get_drvdata(pdev);
100502e53293SMika Westerberg 	struct ahci_host_priv *hpriv = host->private_data;
100602e53293SMika Westerberg 
100702e53293SMika Westerberg 	if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
100802e53293SMika Westerberg 		dev_err(&pdev->dev,
100902e53293SMika Westerberg 			"BIOS update required for suspend/resume\n");
101002e53293SMika Westerberg 		return -EIO;
101102e53293SMika Westerberg 	}
101202e53293SMika Westerberg 
101302e53293SMika Westerberg 	ahci_pci_disable_interrupts(host);
1014ec87cf37SSergey Shtylyov 	ata_host_suspend(host, PMSG_SUSPEND);
1015ec87cf37SSergey Shtylyov 	return 0;
1016c6fd2807SJeff Garzik }
1017c6fd2807SJeff Garzik 
ahci_pci_device_resume(struct device * dev)1018f1d848f9SMika Westerberg static int ahci_pci_device_resume(struct device *dev)
1019c6fd2807SJeff Garzik {
1020f1d848f9SMika Westerberg 	struct pci_dev *pdev = to_pci_dev(dev);
10210a86e1c8SJingoo Han 	struct ata_host *host = pci_get_drvdata(pdev);
1022c6fd2807SJeff Garzik 	int rc;
1023c6fd2807SJeff Garzik 
1024cb85696dSJames Laird 	/* Apple BIOS helpfully mangles the registers on resume */
1025cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
1026cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
1027cb85696dSJames Laird 
1028c6fd2807SJeff Garzik 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
102937e14e4fSAdam Vodopjan 		rc = ahci_pci_reset_controller(host);
1030c6fd2807SJeff Garzik 		if (rc)
1031c6fd2807SJeff Garzik 			return rc;
1032c6fd2807SJeff Garzik 
1033781d6550SAnton Vorontsov 		ahci_pci_init_controller(host);
1034c6fd2807SJeff Garzik 	}
1035c6fd2807SJeff Garzik 
1036cca3974eSJeff Garzik 	ata_host_resume(host);
1037c6fd2807SJeff Garzik 
1038c6fd2807SJeff Garzik 	return 0;
1039c6fd2807SJeff Garzik }
1040438ac6d5STejun Heo #endif
1041c6fd2807SJeff Garzik 
104202e53293SMika Westerberg #endif /* CONFIG_PM */
104302e53293SMika Westerberg 
ahci_configure_dma_masks(struct pci_dev * pdev,struct ahci_host_priv * hpriv)1044b0dd4d7aSLennert Buytenhek static int ahci_configure_dma_masks(struct pci_dev *pdev,
1045b0dd4d7aSLennert Buytenhek 				    struct ahci_host_priv *hpriv)
1046c6fd2807SJeff Garzik {
1047b0dd4d7aSLennert Buytenhek 	int dma_bits;
1048c6fd2807SJeff Garzik 	int rc;
1049c6fd2807SJeff Garzik 
1050b0dd4d7aSLennert Buytenhek 	if (hpriv->cap & HOST_CAP_64) {
1051b0dd4d7aSLennert Buytenhek 		dma_bits = 64;
1052b0dd4d7aSLennert Buytenhek 		if (hpriv->flags & AHCI_HFLAG_43BIT_ONLY)
1053b0dd4d7aSLennert Buytenhek 			dma_bits = 43;
1054b0dd4d7aSLennert Buytenhek 	} else {
1055b0dd4d7aSLennert Buytenhek 		dma_bits = 32;
1056b0dd4d7aSLennert Buytenhek 	}
1057b0dd4d7aSLennert Buytenhek 
1058318893e1SAlessandro Rubini 	/*
1059318893e1SAlessandro Rubini 	 * If the device fixup already set the dma_mask to some non-standard
1060318893e1SAlessandro Rubini 	 * value, don't extend it here. This happens on STA2X11, for example.
1061b1716871SChristoph Hellwig 	 *
1062b1716871SChristoph Hellwig 	 * XXX: manipulating the DMA mask from platform code is completely
1063a7ba70f1SNicolas Saenz Julienne 	 * bogus, platform code should use dev->bus_dma_limit instead..
1064318893e1SAlessandro Rubini 	 */
1065318893e1SAlessandro Rubini 	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32))
1066318893e1SAlessandro Rubini 		return 0;
1067318893e1SAlessandro Rubini 
1068b1716871SChristoph Hellwig 	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits));
1069b1716871SChristoph Hellwig 	if (rc)
1070b1716871SChristoph Hellwig 		dev_err(&pdev->dev, "DMA enable failed\n");
1071c6fd2807SJeff Garzik 	return rc;
1072c6fd2807SJeff Garzik }
1073c6fd2807SJeff Garzik 
ahci_pci_print_info(struct ata_host * host)1074439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host)
1075439fcaecSAnton Vorontsov {
1076439fcaecSAnton Vorontsov 	struct pci_dev *pdev = to_pci_dev(host->dev);
1077439fcaecSAnton Vorontsov 	u16 cc;
1078439fcaecSAnton Vorontsov 	const char *scc_s;
1079439fcaecSAnton Vorontsov 
1080439fcaecSAnton Vorontsov 	pci_read_config_word(pdev, 0x0a, &cc);
1081439fcaecSAnton Vorontsov 	if (cc == PCI_CLASS_STORAGE_IDE)
1082439fcaecSAnton Vorontsov 		scc_s = "IDE";
1083439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_SATA)
1084439fcaecSAnton Vorontsov 		scc_s = "SATA";
1085439fcaecSAnton Vorontsov 	else if (cc == PCI_CLASS_STORAGE_RAID)
1086439fcaecSAnton Vorontsov 		scc_s = "RAID";
1087439fcaecSAnton Vorontsov 	else
1088439fcaecSAnton Vorontsov 		scc_s = "unknown";
1089439fcaecSAnton Vorontsov 
1090439fcaecSAnton Vorontsov 	ahci_print_info(host, scc_s);
1091439fcaecSAnton Vorontsov }
1092439fcaecSAnton Vorontsov 
1093edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is
1094edc93052STejun Heo  * hardwired to on-board SIMG 4726.  The chipset is ICH8 and doesn't
1095edc93052STejun Heo  * support PMP and the 4726 either directly exports the device
1096edc93052STejun Heo  * attached to the first downstream port or acts as a hardware storage
1097edc93052STejun Heo  * controller and emulate a single ATA device (can be RAID 0/1 or some
1098edc93052STejun Heo  * other configuration).
1099edc93052STejun Heo  *
1100edc93052STejun Heo  * When there's no device attached to the first downstream port of the
1101edc93052STejun Heo  * 4726, "Config Disk" appears, which is a pseudo ATA device to
1102edc93052STejun Heo  * configure the 4726.  However, ATA emulation of the device is very
1103edc93052STejun Heo  * lame.  It doesn't send signature D2H Reg FIS after the initial
1104edc93052STejun Heo  * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues.
1105edc93052STejun Heo  *
1106edc93052STejun Heo  * The following function works around the problem by always using
1107edc93052STejun Heo  * hardreset on the port and not depending on receiving signature FIS
1108edc93052STejun Heo  * afterward.  If signature FIS isn't received soon, ATA class is
1109edc93052STejun Heo  * assumed without follow-up softreset.
1110edc93052STejun Heo  */
ahci_p5wdh_workaround(struct ata_host * host)1111edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host)
1112edc93052STejun Heo {
11131bd06867SMathias Krause 	static const struct dmi_system_id sysids[] = {
1114edc93052STejun Heo 		{
1115edc93052STejun Heo 			.ident = "P5W DH Deluxe",
1116edc93052STejun Heo 			.matches = {
1117edc93052STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR,
1118edc93052STejun Heo 					  "ASUSTEK COMPUTER INC"),
1119edc93052STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
1120edc93052STejun Heo 			},
1121edc93052STejun Heo 		},
1122edc93052STejun Heo 		{ }
1123edc93052STejun Heo 	};
1124edc93052STejun Heo 	struct pci_dev *pdev = to_pci_dev(host->dev);
1125edc93052STejun Heo 
1126edc93052STejun Heo 	if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) &&
1127edc93052STejun Heo 	    dmi_check_system(sysids)) {
1128edc93052STejun Heo 		struct ata_port *ap = host->ports[1];
1129edc93052STejun Heo 
1130a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1131a44fec1fSJoe Perches 			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");
1132edc93052STejun Heo 
1133edc93052STejun Heo 		ap->ops = &ahci_p5wdh_ops;
1134edc93052STejun Heo 		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;
1135edc93052STejun Heo 	}
1136edc93052STejun Heo }
1137edc93052STejun Heo 
1138cb85696dSJames Laird /*
1139cb85696dSJames Laird  * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
1140cb85696dSJames Laird  * booting in BIOS compatibility mode.  We restore the registers but not ID.
1141cb85696dSJames Laird  */
ahci_mcp89_apple_enable(struct pci_dev * pdev)1142cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
1143cb85696dSJames Laird {
1144cb85696dSJames Laird 	u32 val;
1145cb85696dSJames Laird 
1146cb85696dSJames Laird 	printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
1147cb85696dSJames Laird 
1148cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
1149cb85696dSJames Laird 	val |= 1 << 0x1b;
1150cb85696dSJames Laird 	/* the following changes the device ID, but appears not to affect function */
1151cb85696dSJames Laird 	/* val = (val & ~0xf0000000) | 0x80000000; */
1152cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
1153cb85696dSJames Laird 
1154cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
1155cb85696dSJames Laird 	val |= 1 << 0xc;
1156cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
1157cb85696dSJames Laird 
1158cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x4a4, &val);
1159cb85696dSJames Laird 	val &= 0xff;
1160cb85696dSJames Laird 	val |= 0x01060100;
1161cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x4a4, val);
1162cb85696dSJames Laird 
1163cb85696dSJames Laird 	pci_read_config_dword(pdev, 0x54c, &val);
1164cb85696dSJames Laird 	val &= ~(1 << 0xc);
1165cb85696dSJames Laird 	pci_write_config_dword(pdev, 0x54c, val);
1166cb85696dSJames Laird 
1167cb85696dSJames Laird 	pci_read_config_dword(pdev, 0xf8, &val);
1168cb85696dSJames Laird 	val &= ~(1 << 0x1b);
1169cb85696dSJames Laird 	pci_write_config_dword(pdev, 0xf8, val);
1170cb85696dSJames Laird }
1171cb85696dSJames Laird 
is_mcp89_apple(struct pci_dev * pdev)1172cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev)
1173cb85696dSJames Laird {
1174cb85696dSJames Laird 	return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
1175cb85696dSJames Laird 		pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
1176cb85696dSJames Laird 		pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
1177cb85696dSJames Laird 		pdev->subsystem_device == 0xcb89;
1178cb85696dSJames Laird }
1179cb85696dSJames Laird 
11802fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */
ahci_sb600_enable_64bit(struct pci_dev * pdev)11812fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
118258a09b38SShane Huang {
118358a09b38SShane Huang 	static const struct dmi_system_id sysids[] = {
118403d783bfSTejun Heo 		/*
118503d783bfSTejun Heo 		 * The oldest version known to be broken is 0901 and
118603d783bfSTejun Heo 		 * working is 1501 which was released on 2007-10-26.
11872fcad9d2STejun Heo 		 * Enable 64bit DMA on 1501 and anything newer.
11882fcad9d2STejun Heo 		 *
118903d783bfSTejun Heo 		 * Please read bko#9412 for more info.
119003d783bfSTejun Heo 		 */
119158a09b38SShane Huang 		{
119258a09b38SShane Huang 			.ident = "ASUS M2A-VM",
119358a09b38SShane Huang 			.matches = {
119458a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_VENDOR,
119558a09b38SShane Huang 					  "ASUSTeK Computer INC."),
119658a09b38SShane Huang 				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
119758a09b38SShane Huang 			},
119803d783bfSTejun Heo 			.driver_data = "20071026",	/* yyyymmdd */
119958a09b38SShane Huang 		},
1200e65cc194SMark Nelson 		/*
1201e65cc194SMark Nelson 		 * All BIOS versions for the MSI K9A2 Platinum (MS-7376)
1202e65cc194SMark Nelson 		 * support 64bit DMA.
1203e65cc194SMark Nelson 		 *
1204e65cc194SMark Nelson 		 * BIOS versions earlier than 1.5 had the Manufacturer DMI
1205e65cc194SMark Nelson 		 * fields as "MICRO-STAR INTERANTIONAL CO.,LTD".
1206e65cc194SMark Nelson 		 * This spelling mistake was fixed in BIOS version 1.5, so
1207e65cc194SMark Nelson 		 * 1.5 and later have the Manufacturer as
1208e65cc194SMark Nelson 		 * "MICRO-STAR INTERNATIONAL CO.,LTD".
1209e65cc194SMark Nelson 		 * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER".
1210e65cc194SMark Nelson 		 *
1211e65cc194SMark Nelson 		 * BIOS versions earlier than 1.9 had a Board Product Name
1212e65cc194SMark Nelson 		 * DMI field of "MS-7376". This was changed to be
1213e65cc194SMark Nelson 		 * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still
1214e65cc194SMark Nelson 		 * match on DMI_BOARD_NAME of "MS-7376".
1215e65cc194SMark Nelson 		 */
1216e65cc194SMark Nelson 		{
1217e65cc194SMark Nelson 			.ident = "MSI K9A2 Platinum",
1218e65cc194SMark Nelson 			.matches = {
1219e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1220e65cc194SMark Nelson 					  "MICRO-STAR INTER"),
1221e65cc194SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),
1222e65cc194SMark Nelson 			},
1223e65cc194SMark Nelson 		},
12243c4aa91fSMark Nelson 		/*
1225ff0173c1SMark Nelson 		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support
1226ff0173c1SMark Nelson 		 * 64bit DMA.
1227ff0173c1SMark Nelson 		 *
1228ff0173c1SMark Nelson 		 * This board also had the typo mentioned above in the
1229ff0173c1SMark Nelson 		 * Manufacturer DMI field (fixed in BIOS version 1.5), so
1230ff0173c1SMark Nelson 		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again.
1231ff0173c1SMark Nelson 		 */
1232ff0173c1SMark Nelson 		{
1233ff0173c1SMark Nelson 			.ident = "MSI K9AGM2",
1234ff0173c1SMark Nelson 			.matches = {
1235ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
1236ff0173c1SMark Nelson 					  "MICRO-STAR INTER"),
1237ff0173c1SMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"),
1238ff0173c1SMark Nelson 			},
1239ff0173c1SMark Nelson 		},
1240ff0173c1SMark Nelson 		/*
12413c4aa91fSMark Nelson 		 * All BIOS versions for the Asus M3A support 64bit DMA.
12423c4aa91fSMark Nelson 		 * (all release versions from 0301 to 1206 were tested)
12433c4aa91fSMark Nelson 		 */
12443c4aa91fSMark Nelson 		{
12453c4aa91fSMark Nelson 			.ident = "ASUS M3A",
12463c4aa91fSMark Nelson 			.matches = {
12473c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_VENDOR,
12483c4aa91fSMark Nelson 					  "ASUSTeK Computer INC."),
12493c4aa91fSMark Nelson 				DMI_MATCH(DMI_BOARD_NAME, "M3A"),
12503c4aa91fSMark Nelson 			},
12513c4aa91fSMark Nelson 		},
125258a09b38SShane Huang 		{ }
125358a09b38SShane Huang 	};
125403d783bfSTejun Heo 	const struct dmi_system_id *match;
12552fcad9d2STejun Heo 	int year, month, date;
12562fcad9d2STejun Heo 	char buf[9];
125758a09b38SShane Huang 
125803d783bfSTejun Heo 	match = dmi_first_match(sysids);
125958a09b38SShane Huang 	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
126003d783bfSTejun Heo 	    !match)
126158a09b38SShane Huang 		return false;
126258a09b38SShane Huang 
1263e65cc194SMark Nelson 	if (!match->driver_data)
1264e65cc194SMark Nelson 		goto enable_64bit;
1265e65cc194SMark Nelson 
126603d783bfSTejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
126703d783bfSTejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
126803d783bfSTejun Heo 
1269e65cc194SMark Nelson 	if (strcmp(buf, match->driver_data) >= 0)
1270e65cc194SMark Nelson 		goto enable_64bit;
1271e65cc194SMark Nelson 	else {
1272a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
1273a44fec1fSJoe Perches 			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n",
1274a44fec1fSJoe Perches 			 match->ident);
12752fcad9d2STejun Heo 		return false;
12762fcad9d2STejun Heo 	}
1277e65cc194SMark Nelson 
1278e65cc194SMark Nelson enable_64bit:
1279a44fec1fSJoe Perches 	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);
1280e65cc194SMark Nelson 	return true;
128158a09b38SShane Huang }
128258a09b38SShane Huang 
ahci_broken_system_poweroff(struct pci_dev * pdev)12831fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
12841fd68434SRafael J. Wysocki {
12851fd68434SRafael J. Wysocki 	static const struct dmi_system_id broken_systems[] = {
12861fd68434SRafael J. Wysocki 		{
12871fd68434SRafael J. Wysocki 			.ident = "HP Compaq nx6310",
12881fd68434SRafael J. Wysocki 			.matches = {
12891fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
12901fd68434SRafael J. Wysocki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
12911fd68434SRafael J. Wysocki 			},
12921fd68434SRafael J. Wysocki 			/* PCI slot number of the controller */
12931fd68434SRafael J. Wysocki 			.driver_data = (void *)0x1FUL,
12941fd68434SRafael J. Wysocki 		},
1295d2f9c061SMaciej Rutecki 		{
1296d2f9c061SMaciej Rutecki 			.ident = "HP Compaq 6720s",
1297d2f9c061SMaciej Rutecki 			.matches = {
1298d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1299d2f9c061SMaciej Rutecki 				DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"),
1300d2f9c061SMaciej Rutecki 			},
1301d2f9c061SMaciej Rutecki 			/* PCI slot number of the controller */
1302d2f9c061SMaciej Rutecki 			.driver_data = (void *)0x1FUL,
1303d2f9c061SMaciej Rutecki 		},
13041fd68434SRafael J. Wysocki 
13051fd68434SRafael J. Wysocki 		{ }	/* terminate list */
13061fd68434SRafael J. Wysocki 	};
13071fd68434SRafael J. Wysocki 	const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
13081fd68434SRafael J. Wysocki 
13091fd68434SRafael J. Wysocki 	if (dmi) {
13101fd68434SRafael J. Wysocki 		unsigned long slot = (unsigned long)dmi->driver_data;
13111fd68434SRafael J. Wysocki 		/* apply the quirk only to on-board controllers */
13121fd68434SRafael J. Wysocki 		return slot == PCI_SLOT(pdev->devfn);
13131fd68434SRafael J. Wysocki 	}
13141fd68434SRafael J. Wysocki 
13151fd68434SRafael J. Wysocki 	return false;
13161fd68434SRafael J. Wysocki }
13171fd68434SRafael J. Wysocki 
ahci_broken_suspend(struct pci_dev * pdev)13189b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev)
13199b10ae86STejun Heo {
13209b10ae86STejun Heo 	static const struct dmi_system_id sysids[] = {
13219b10ae86STejun Heo 		/*
13229b10ae86STejun Heo 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
13239b10ae86STejun Heo 		 * to the harddisk doesn't become online after
13249b10ae86STejun Heo 		 * resuming from STR.  Warn and fail suspend.
13259deb3431STejun Heo 		 *
13269deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
13279deb3431STejun Heo 		 *
13289deb3431STejun Heo 		 * Use dates instead of versions to match as HP is
13299deb3431STejun Heo 		 * apparently recycling both product and version
13309deb3431STejun Heo 		 * strings.
13319deb3431STejun Heo 		 *
13329deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
13339b10ae86STejun Heo 		 */
13349b10ae86STejun Heo 		{
13359b10ae86STejun Heo 			.ident = "dv4",
13369b10ae86STejun Heo 			.matches = {
13379b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
13389b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
13399b10ae86STejun Heo 					  "HP Pavilion dv4 Notebook PC"),
13409b10ae86STejun Heo 			},
13419deb3431STejun Heo 			.driver_data = "20090105",	/* F.30 */
13429b10ae86STejun Heo 		},
13439b10ae86STejun Heo 		{
13449b10ae86STejun Heo 			.ident = "dv5",
13459b10ae86STejun Heo 			.matches = {
13469b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
13479b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
13489b10ae86STejun Heo 					  "HP Pavilion dv5 Notebook PC"),
13499b10ae86STejun Heo 			},
13509deb3431STejun Heo 			.driver_data = "20090506",	/* F.16 */
13519b10ae86STejun Heo 		},
13529b10ae86STejun Heo 		{
13539b10ae86STejun Heo 			.ident = "dv6",
13549b10ae86STejun Heo 			.matches = {
13559b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
13569b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
13579b10ae86STejun Heo 					  "HP Pavilion dv6 Notebook PC"),
13589b10ae86STejun Heo 			},
13599deb3431STejun Heo 			.driver_data = "20090423",	/* F.21 */
13609b10ae86STejun Heo 		},
13619b10ae86STejun Heo 		{
13629b10ae86STejun Heo 			.ident = "HDX18",
13639b10ae86STejun Heo 			.matches = {
13649b10ae86STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
13659b10ae86STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME,
13669b10ae86STejun Heo 					  "HP HDX18 Notebook PC"),
13679b10ae86STejun Heo 			},
13689deb3431STejun Heo 			.driver_data = "20090430",	/* F.23 */
13699b10ae86STejun Heo 		},
1370cedc9bf9STejun Heo 		/*
1371cedc9bf9STejun Heo 		 * Acer eMachines G725 has the same problem.  BIOS
1372cedc9bf9STejun Heo 		 * V1.03 is known to be broken.  V3.04 is known to
137325985edcSLucas De Marchi 		 * work.  Between, there are V1.06, V2.06 and V3.03
1374cedc9bf9STejun Heo 		 * that we don't have much idea about.  For now,
1375cedc9bf9STejun Heo 		 * blacklist anything older than V3.04.
13769deb3431STejun Heo 		 *
13779deb3431STejun Heo 		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
1378cedc9bf9STejun Heo 		 */
1379cedc9bf9STejun Heo 		{
1380cedc9bf9STejun Heo 			.ident = "G725",
1381cedc9bf9STejun Heo 			.matches = {
1382cedc9bf9STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
1383cedc9bf9STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
1384cedc9bf9STejun Heo 			},
13859deb3431STejun Heo 			.driver_data = "20091216",	/* V3.04 */
1386cedc9bf9STejun Heo 		},
13879b10ae86STejun Heo 		{ }	/* terminate list */
13889b10ae86STejun Heo 	};
13899b10ae86STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
13909deb3431STejun Heo 	int year, month, date;
13919deb3431STejun Heo 	char buf[9];
13929b10ae86STejun Heo 
13939b10ae86STejun Heo 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
13949b10ae86STejun Heo 		return false;
13959b10ae86STejun Heo 
13969deb3431STejun Heo 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
13979deb3431STejun Heo 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
13989b10ae86STejun Heo 
13999deb3431STejun Heo 	return strcmp(buf, dmi->driver_data) < 0;
14009b10ae86STejun Heo }
14019b10ae86STejun Heo 
ahci_broken_lpm(struct pci_dev * pdev)1402240630e6SHans de Goede static bool ahci_broken_lpm(struct pci_dev *pdev)
1403240630e6SHans de Goede {
1404240630e6SHans de Goede 	static const struct dmi_system_id sysids[] = {
1405240630e6SHans de Goede 		/* Various Lenovo 50 series have LPM issues with older BIOSen */
1406240630e6SHans de Goede 		{
1407240630e6SHans de Goede 			.matches = {
1408240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1409240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"),
1410240630e6SHans de Goede 			},
1411240630e6SHans de Goede 			.driver_data = "20180406", /* 1.31 */
1412240630e6SHans de Goede 		},
1413240630e6SHans de Goede 		{
1414240630e6SHans de Goede 			.matches = {
1415240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1416240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"),
1417240630e6SHans de Goede 			},
1418240630e6SHans de Goede 			.driver_data = "20180420", /* 1.28 */
1419240630e6SHans de Goede 		},
1420240630e6SHans de Goede 		{
1421240630e6SHans de Goede 			.matches = {
1422240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1423240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"),
1424240630e6SHans de Goede 			},
1425240630e6SHans de Goede 			.driver_data = "20180315", /* 1.33 */
1426240630e6SHans de Goede 		},
1427240630e6SHans de Goede 		{
1428240630e6SHans de Goede 			.matches = {
1429240630e6SHans de Goede 				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1430240630e6SHans de Goede 				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"),
1431240630e6SHans de Goede 			},
1432240630e6SHans de Goede 			/*
1433240630e6SHans de Goede 			 * Note date based on release notes, 2.35 has been
1434240630e6SHans de Goede 			 * reported to be good, but I've been unable to get
1435240630e6SHans de Goede 			 * a hold of the reporter to get the DMI BIOS date.
1436240630e6SHans de Goede 			 * TODO: fix this.
1437240630e6SHans de Goede 			 */
1438240630e6SHans de Goede 			.driver_data = "20180310", /* 2.35 */
1439240630e6SHans de Goede 		},
1440240630e6SHans de Goede 		{ }	/* terminate list */
1441240630e6SHans de Goede 	};
1442240630e6SHans de Goede 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1443240630e6SHans de Goede 	int year, month, date;
1444240630e6SHans de Goede 	char buf[9];
1445240630e6SHans de Goede 
1446240630e6SHans de Goede 	if (!dmi)
1447240630e6SHans de Goede 		return false;
1448240630e6SHans de Goede 
1449240630e6SHans de Goede 	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
1450240630e6SHans de Goede 	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
1451240630e6SHans de Goede 
1452240630e6SHans de Goede 	return strcmp(buf, dmi->driver_data) < 0;
1453240630e6SHans de Goede }
1454240630e6SHans de Goede 
ahci_broken_online(struct pci_dev * pdev)14555594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev)
14565594639aSTejun Heo {
14575594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func)			\
14585594639aSTejun Heo 	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
14595594639aSTejun Heo 	static const struct dmi_system_id sysids[] = {
14605594639aSTejun Heo 		/*
14615594639aSTejun Heo 		 * There are several gigabyte boards which use
14625594639aSTejun Heo 		 * SIMG5723s configured as hardware RAID.  Certain
14635594639aSTejun Heo 		 * 5723 firmware revisions shipped there keep the link
14645594639aSTejun Heo 		 * online but fail to answer properly to SRST or
14655594639aSTejun Heo 		 * IDENTIFY when no device is attached downstream
14665594639aSTejun Heo 		 * causing libata to retry quite a few times leading
14675594639aSTejun Heo 		 * to excessive detection delay.
14685594639aSTejun Heo 		 *
14695594639aSTejun Heo 		 * As these firmwares respond to the second reset try
14705594639aSTejun Heo 		 * with invalid device signature, considering unknown
14715594639aSTejun Heo 		 * sig as offline works around the problem acceptably.
14725594639aSTejun Heo 		 */
14735594639aSTejun Heo 		{
14745594639aSTejun Heo 			.ident = "EP45-DQ6",
14755594639aSTejun Heo 			.matches = {
14765594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
14775594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
14785594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
14795594639aSTejun Heo 			},
14805594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
14815594639aSTejun Heo 		},
14825594639aSTejun Heo 		{
14835594639aSTejun Heo 			.ident = "EP45-DS5",
14845594639aSTejun Heo 			.matches = {
14855594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_VENDOR,
14865594639aSTejun Heo 					  "Gigabyte Technology Co., Ltd."),
14875594639aSTejun Heo 				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
14885594639aSTejun Heo 			},
14895594639aSTejun Heo 			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
14905594639aSTejun Heo 		},
14915594639aSTejun Heo 		{ }	/* terminate list */
14925594639aSTejun Heo 	};
14935594639aSTejun Heo #undef ENCODE_BUSDEVFN
14945594639aSTejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
14955594639aSTejun Heo 	unsigned int val;
14965594639aSTejun Heo 
14975594639aSTejun Heo 	if (!dmi)
14985594639aSTejun Heo 		return false;
14995594639aSTejun Heo 
15005594639aSTejun Heo 	val = (unsigned long)dmi->driver_data;
15015594639aSTejun Heo 
15025594639aSTejun Heo 	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
15035594639aSTejun Heo }
15045594639aSTejun Heo 
ahci_broken_devslp(struct pci_dev * pdev)15050cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev)
15060cf4a7d6SJacob Pan {
15070cf4a7d6SJacob Pan 	/* device with broken DEVSLP but still showing SDS capability */
15080cf4a7d6SJacob Pan 	static const struct pci_device_id ids[] = {
15090cf4a7d6SJacob Pan 		{ PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
15100cf4a7d6SJacob Pan 		{}
15110cf4a7d6SJacob Pan 	};
15120cf4a7d6SJacob Pan 
15130cf4a7d6SJacob Pan 	return pci_match_id(ids, pdev);
15140cf4a7d6SJacob Pan }
15150cf4a7d6SJacob Pan 
15168e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI
ahci_gtf_filter_workaround(struct ata_host * host)1517f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host)
1518f80ae7e4STejun Heo {
1519f80ae7e4STejun Heo 	static const struct dmi_system_id sysids[] = {
1520f80ae7e4STejun Heo 		/*
1521f80ae7e4STejun Heo 		 * Aspire 3810T issues a bunch of SATA enable commands
1522f80ae7e4STejun Heo 		 * via _GTF including an invalid one and one which is
1523f80ae7e4STejun Heo 		 * rejected by the device.  Among the successful ones
1524f80ae7e4STejun Heo 		 * is FPDMA non-zero offset enable which when enabled
1525f80ae7e4STejun Heo 		 * only on the drive side leads to NCQ command
1526f80ae7e4STejun Heo 		 * failures.  Filter it out.
1527f80ae7e4STejun Heo 		 */
1528f80ae7e4STejun Heo 		{
1529f80ae7e4STejun Heo 			.ident = "Aspire 3810T",
1530f80ae7e4STejun Heo 			.matches = {
1531f80ae7e4STejun Heo 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1532f80ae7e4STejun Heo 				DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"),
1533f80ae7e4STejun Heo 			},
1534f80ae7e4STejun Heo 			.driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET,
1535f80ae7e4STejun Heo 		},
1536f80ae7e4STejun Heo 		{ }
1537f80ae7e4STejun Heo 	};
1538f80ae7e4STejun Heo 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
1539f80ae7e4STejun Heo 	unsigned int filter;
1540f80ae7e4STejun Heo 	int i;
1541f80ae7e4STejun Heo 
1542f80ae7e4STejun Heo 	if (!dmi)
1543f80ae7e4STejun Heo 		return;
1544f80ae7e4STejun Heo 
1545f80ae7e4STejun Heo 	filter = (unsigned long)dmi->driver_data;
1546a44fec1fSJoe Perches 	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n",
1547f80ae7e4STejun Heo 		 filter, dmi->ident);
1548f80ae7e4STejun Heo 
1549f80ae7e4STejun Heo 	for (i = 0; i < host->n_ports; i++) {
1550f80ae7e4STejun Heo 		struct ata_port *ap = host->ports[i];
1551f80ae7e4STejun Heo 		struct ata_link *link;
1552f80ae7e4STejun Heo 		struct ata_device *dev;
1553f80ae7e4STejun Heo 
1554f80ae7e4STejun Heo 		ata_for_each_link(link, ap, EDGE)
1555f80ae7e4STejun Heo 			ata_for_each_dev(dev, link, ALL)
1556f80ae7e4STejun Heo 				dev->gtf_filter |= filter;
1557f80ae7e4STejun Heo 	}
1558f80ae7e4STejun Heo }
15598e513217SMarkus Trippelsdorf #else
ahci_gtf_filter_workaround(struct ata_host * host)15608e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host)
15618e513217SMarkus Trippelsdorf {}
15628e513217SMarkus Trippelsdorf #endif
1563f80ae7e4STejun Heo 
15648bfd1743SSui Chen /*
15658bfd1743SSui Chen  * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected
15668bfd1743SSui Chen  * as DUMMY, or detected but eventually get a "link down" and never get up
15678bfd1743SSui Chen  * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the
15688bfd1743SSui Chen  * port_map may hold a value of 0x00.
15698bfd1743SSui Chen  *
15708bfd1743SSui Chen  * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports
15718bfd1743SSui Chen  * and can significantly reduce the occurrence of the problem.
15728bfd1743SSui Chen  *
15738bfd1743SSui Chen  * https://bugzilla.kernel.org/show_bug.cgi?id=189471
15748bfd1743SSui Chen  */
acer_sa5_271_workaround(struct ahci_host_priv * hpriv,struct pci_dev * pdev)15758bfd1743SSui Chen static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv,
15768bfd1743SSui Chen 				    struct pci_dev *pdev)
15778bfd1743SSui Chen {
15788bfd1743SSui Chen 	static const struct dmi_system_id sysids[] = {
15798bfd1743SSui Chen 		{
15808bfd1743SSui Chen 			.ident = "Acer Switch Alpha 12",
15818bfd1743SSui Chen 			.matches = {
15828bfd1743SSui Chen 				DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
15838bfd1743SSui Chen 				DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271")
15848bfd1743SSui Chen 			},
15858bfd1743SSui Chen 		},
15868bfd1743SSui Chen 		{ }
15878bfd1743SSui Chen 	};
15888bfd1743SSui Chen 
15898bfd1743SSui Chen 	if (dmi_check_system(sysids)) {
15908bfd1743SSui Chen 		dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n");
15918bfd1743SSui Chen 		if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) {
15928bfd1743SSui Chen 			hpriv->port_map = 0x7;
15938bfd1743SSui Chen 			hpriv->cap = 0xC734FF02;
15948bfd1743SSui Chen 		}
15958bfd1743SSui Chen 	}
15968bfd1743SSui Chen }
15978bfd1743SSui Chen 
1598d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64
1599d243bed3STirumalesh Chalamarla /*
1600d243bed3STirumalesh Chalamarla  * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
1601d243bed3STirumalesh Chalamarla  * Workaround is to make sure all pending IRQs are served before leaving
1602d243bed3STirumalesh Chalamarla  * handler.
1603d243bed3STirumalesh Chalamarla  */
ahci_thunderx_irq_handler(int irq,void * dev_instance)1604d243bed3STirumalesh Chalamarla static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
1605d243bed3STirumalesh Chalamarla {
1606d243bed3STirumalesh Chalamarla 	struct ata_host *host = dev_instance;
1607d243bed3STirumalesh Chalamarla 	struct ahci_host_priv *hpriv;
1608d243bed3STirumalesh Chalamarla 	unsigned int rc = 0;
1609d243bed3STirumalesh Chalamarla 	void __iomem *mmio;
1610d243bed3STirumalesh Chalamarla 	u32 irq_stat, irq_masked;
1611d243bed3STirumalesh Chalamarla 	unsigned int handled = 1;
1612d243bed3STirumalesh Chalamarla 
1613d243bed3STirumalesh Chalamarla 	hpriv = host->private_data;
1614d243bed3STirumalesh Chalamarla 	mmio = hpriv->mmio;
1615d243bed3STirumalesh Chalamarla 	irq_stat = readl(mmio + HOST_IRQ_STAT);
1616d243bed3STirumalesh Chalamarla 	if (!irq_stat)
1617d243bed3STirumalesh Chalamarla 		return IRQ_NONE;
1618d243bed3STirumalesh Chalamarla 
1619d243bed3STirumalesh Chalamarla 	do {
1620d243bed3STirumalesh Chalamarla 		irq_masked = irq_stat & hpriv->port_map;
1621d243bed3STirumalesh Chalamarla 		spin_lock(&host->lock);
1622d243bed3STirumalesh Chalamarla 		rc = ahci_handle_port_intr(host, irq_masked);
1623d243bed3STirumalesh Chalamarla 		if (!rc)
1624d243bed3STirumalesh Chalamarla 			handled = 0;
1625d243bed3STirumalesh Chalamarla 		writel(irq_stat, mmio + HOST_IRQ_STAT);
1626d243bed3STirumalesh Chalamarla 		irq_stat = readl(mmio + HOST_IRQ_STAT);
1627d243bed3STirumalesh Chalamarla 		spin_unlock(&host->lock);
1628d243bed3STirumalesh Chalamarla 	} while (irq_stat);
1629d243bed3STirumalesh Chalamarla 
1630d243bed3STirumalesh Chalamarla 	return IRQ_RETVAL(handled);
1631d243bed3STirumalesh Chalamarla }
1632d243bed3STirumalesh Chalamarla #endif
1633d243bed3STirumalesh Chalamarla 
ahci_remap_check(struct pci_dev * pdev,int bar,struct ahci_host_priv * hpriv)1634aecec8b6SChristoph Hellwig static void ahci_remap_check(struct pci_dev *pdev, int bar,
1635aecec8b6SChristoph Hellwig 		struct ahci_host_priv *hpriv)
1636aecec8b6SChristoph Hellwig {
1637894fba7fSKai-Heng Feng 	int i;
1638aecec8b6SChristoph Hellwig 	u32 cap;
1639aecec8b6SChristoph Hellwig 
1640aecec8b6SChristoph Hellwig 	/*
1641aecec8b6SChristoph Hellwig 	 * Check if this device might have remapped nvme devices.
1642aecec8b6SChristoph Hellwig 	 */
1643aecec8b6SChristoph Hellwig 	if (pdev->vendor != PCI_VENDOR_ID_INTEL ||
1644aecec8b6SChristoph Hellwig 	    pci_resource_len(pdev, bar) < SZ_512K ||
1645aecec8b6SChristoph Hellwig 	    bar != AHCI_PCI_BAR_STANDARD ||
1646aecec8b6SChristoph Hellwig 	    !(readl(hpriv->mmio + AHCI_VSCAP) & 1))
1647aecec8b6SChristoph Hellwig 		return;
1648aecec8b6SChristoph Hellwig 
1649aecec8b6SChristoph Hellwig 	cap = readq(hpriv->mmio + AHCI_REMAP_CAP);
1650aecec8b6SChristoph Hellwig 	for (i = 0; i < AHCI_MAX_REMAP; i++) {
1651aecec8b6SChristoph Hellwig 		if ((cap & (1 << i)) == 0)
1652aecec8b6SChristoph Hellwig 			continue;
1653aecec8b6SChristoph Hellwig 		if (readl(hpriv->mmio + ahci_remap_dcc(i))
1654aecec8b6SChristoph Hellwig 				!= PCI_CLASS_STORAGE_EXPRESS)
1655aecec8b6SChristoph Hellwig 			continue;
1656aecec8b6SChristoph Hellwig 
1657aecec8b6SChristoph Hellwig 		/* We've found a remapped device */
1658894fba7fSKai-Heng Feng 		hpriv->remapped_nvme++;
1659aecec8b6SChristoph Hellwig 	}
1660aecec8b6SChristoph Hellwig 
1661894fba7fSKai-Heng Feng 	if (!hpriv->remapped_nvme)
1662aecec8b6SChristoph Hellwig 		return;
1663aecec8b6SChristoph Hellwig 
1664894fba7fSKai-Heng Feng 	dev_warn(&pdev->dev, "Found %u remapped NVMe devices.\n",
1665894fba7fSKai-Heng Feng 		 hpriv->remapped_nvme);
1666f723fa4eSChristoph Hellwig 	dev_warn(&pdev->dev,
1667f723fa4eSChristoph Hellwig 		 "Switch your BIOS from RAID to AHCI mode to use them.\n");
1668f723fa4eSChristoph Hellwig 
1669f723fa4eSChristoph Hellwig 	/*
1670f723fa4eSChristoph Hellwig 	 * Don't rely on the msi-x capability in the remap case,
1671f723fa4eSChristoph Hellwig 	 * share the legacy interrupt across ahci and remapped devices.
1672f723fa4eSChristoph Hellwig 	 */
1673f723fa4eSChristoph Hellwig 	hpriv->flags |= AHCI_HFLAG_NO_MSI;
1674aecec8b6SChristoph Hellwig }
1675aecec8b6SChristoph Hellwig 
ahci_get_irq_vector(struct ata_host * host,int port)16760b9e2988SChristoph Hellwig static int ahci_get_irq_vector(struct ata_host *host, int port)
1677ee2aad42SRobert Richter {
16780b9e2988SChristoph Hellwig 	return pci_irq_vector(to_pci_dev(host->dev), port);
1679ee2aad42SRobert Richter }
1680ee2aad42SRobert Richter 
ahci_init_msi(struct pci_dev * pdev,unsigned int n_ports,struct ahci_host_priv * hpriv)1681a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
16827b92b4f6SAlexander Gordeev 			struct ahci_host_priv *hpriv)
16835ca72c4fSAlexander Gordeev {
16840b9e2988SChristoph Hellwig 	int nvec;
16855ca72c4fSAlexander Gordeev 
16867b92b4f6SAlexander Gordeev 	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
1687a1c82311SRobert Richter 		return -ENODEV;
16887b92b4f6SAlexander Gordeev 
16895ca72c4fSAlexander Gordeev 	/*
16907b92b4f6SAlexander Gordeev 	 * If number of MSIs is less than number of ports then Sharing Last
16917b92b4f6SAlexander Gordeev 	 * Message mode could be enforced. In this case assume that advantage
16927b92b4f6SAlexander Gordeev 	 * of multipe MSIs is negated and use single MSI mode instead.
16935ca72c4fSAlexander Gordeev 	 */
169417a51f12SChristoph Hellwig 	if (n_ports > 1) {
16950b9e2988SChristoph Hellwig 		nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX,
16960b9e2988SChristoph Hellwig 				PCI_IRQ_MSIX | PCI_IRQ_MSI);
16970b9e2988SChristoph Hellwig 		if (nvec > 0) {
16980b9e2988SChristoph Hellwig 			if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) {
16990b9e2988SChristoph Hellwig 				hpriv->get_irq_vector = ahci_get_irq_vector;
1700c3ebd6a9SAlexander Gordeev 				hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
170121bfd1aaSRobert Richter 				return nvec;
1702a1c82311SRobert Richter 			}
1703a1c82311SRobert Richter 
1704d684a90dSDan Williams 			/*
170517a51f12SChristoph Hellwig 			 * Fallback to single MSI mode if the controller
170617a51f12SChristoph Hellwig 			 * enforced MRSM mode.
1707d684a90dSDan Williams 			 */
170817a51f12SChristoph Hellwig 			printk(KERN_INFO
170917a51f12SChristoph Hellwig 				"ahci: MRSM is on, fallback to single MSI\n");
17100b9e2988SChristoph Hellwig 			pci_free_irq_vectors(pdev);
17110b9e2988SChristoph Hellwig 		}
1712a478b097SChristoph Hellwig 	}
1713d684a90dSDan Williams 
17140b9e2988SChristoph Hellwig 	/*
17150b9e2988SChristoph Hellwig 	 * If the host is not capable of supporting per-port vectors, fall
17160b9e2988SChristoph Hellwig 	 * back to single MSI before finally attempting single MSI-X.
17170b9e2988SChristoph Hellwig 	 */
17180b9e2988SChristoph Hellwig 	nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
17190b9e2988SChristoph Hellwig 	if (nvec == 1)
1720a1c82311SRobert Richter 		return nvec;
17210b9e2988SChristoph Hellwig 	return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
17225ca72c4fSAlexander Gordeev }
17235ca72c4fSAlexander Gordeev 
ahci_update_initial_lpm_policy(struct ata_port * ap,struct ahci_host_priv * hpriv)1724b1a9585cSSrinivas Pandruvada static void ahci_update_initial_lpm_policy(struct ata_port *ap,
1725b1a9585cSSrinivas Pandruvada 					   struct ahci_host_priv *hpriv)
1726b1a9585cSSrinivas Pandruvada {
172755b01415SMario Limonciello 	int policy = CONFIG_SATA_MOBILE_LPM_POLICY;
1728b1a9585cSSrinivas Pandruvada 
1729b1a9585cSSrinivas Pandruvada 
1730e5c89479SMario Limonciello 	/* Ignore processing for chipsets that don't use policy */
1731e5c89479SMario Limonciello 	if (!(hpriv->flags & AHCI_HFLAG_USE_LPM_POLICY))
1732b1a9585cSSrinivas Pandruvada 		return;
1733b1a9585cSSrinivas Pandruvada 
1734b1a9585cSSrinivas Pandruvada 	/* user modified policy via module param */
1735b1a9585cSSrinivas Pandruvada 	if (mobile_lpm_policy != -1) {
1736b1a9585cSSrinivas Pandruvada 		policy = mobile_lpm_policy;
1737b1a9585cSSrinivas Pandruvada 		goto update_policy;
1738b1a9585cSSrinivas Pandruvada 	}
1739b1a9585cSSrinivas Pandruvada 
1740fee60730SRafael J. Wysocki 	if (policy > ATA_LPM_MED_POWER && pm_suspend_default_s2idle()) {
1741b1a9585cSSrinivas Pandruvada 		if (hpriv->cap & HOST_CAP_PART)
1742b1a9585cSSrinivas Pandruvada 			policy = ATA_LPM_MIN_POWER_WITH_PARTIAL;
1743b1a9585cSSrinivas Pandruvada 		else if (hpriv->cap & HOST_CAP_SSC)
1744b1a9585cSSrinivas Pandruvada 			policy = ATA_LPM_MIN_POWER;
1745b1a9585cSSrinivas Pandruvada 	}
1746b1a9585cSSrinivas Pandruvada 
1747b1a9585cSSrinivas Pandruvada update_policy:
1748b1a9585cSSrinivas Pandruvada 	if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER)
1749b1a9585cSSrinivas Pandruvada 		ap->target_lpm_policy = policy;
1750b1a9585cSSrinivas Pandruvada }
1751b1a9585cSSrinivas Pandruvada 
ahci_intel_pcs_quirk(struct pci_dev * pdev,struct ahci_host_priv * hpriv)1752c312ef17SDan Williams static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
1753c312ef17SDan Williams {
1754c312ef17SDan Williams 	const struct pci_device_id *id = pci_match_id(ahci_pci_tbl, pdev);
1755c312ef17SDan Williams 	u16 tmp16;
1756c312ef17SDan Williams 
1757c312ef17SDan Williams 	/*
1758c312ef17SDan Williams 	 * Only apply the 6-port PCS quirk for known legacy platforms.
1759c312ef17SDan Williams 	 */
1760c312ef17SDan Williams 	if (!id || id->vendor != PCI_VENDOR_ID_INTEL)
1761c312ef17SDan Williams 		return;
176209d6ac8dSDan Williams 
176309d6ac8dSDan Williams 	/* Skip applying the quirk on Denverton and beyond */
176409d6ac8dSDan Williams 	if (((enum board_ids) id->driver_data) >= board_ahci_pcs7)
1765c312ef17SDan Williams 		return;
1766c312ef17SDan Williams 
1767c312ef17SDan Williams 	/*
1768c312ef17SDan Williams 	 * port_map is determined from PORTS_IMPL PCI register which is
1769c312ef17SDan Williams 	 * implemented as write or write-once register.  If the register
1770c312ef17SDan Williams 	 * isn't programmed, ahci automatically generates it from number
1771c312ef17SDan Williams 	 * of ports, which is good enough for PCS programming. It is
1772c312ef17SDan Williams 	 * otherwise expected that platform firmware enables the ports
1773c312ef17SDan Williams 	 * before the OS boots.
1774c312ef17SDan Williams 	 */
1775c312ef17SDan Williams 	pci_read_config_word(pdev, PCS_6, &tmp16);
1776c312ef17SDan Williams 	if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
1777c312ef17SDan Williams 		tmp16 |= hpriv->port_map;
1778c312ef17SDan Williams 		pci_write_config_word(pdev, PCS_6, tmp16);
1779c312ef17SDan Williams 	}
1780c312ef17SDan Williams }
1781c312ef17SDan Williams 
remapped_nvme_show(struct device * dev,struct device_attribute * attr,char * buf)1782894fba7fSKai-Heng Feng static ssize_t remapped_nvme_show(struct device *dev,
1783894fba7fSKai-Heng Feng 				  struct device_attribute *attr,
1784894fba7fSKai-Heng Feng 				  char *buf)
1785894fba7fSKai-Heng Feng {
1786894fba7fSKai-Heng Feng 	struct ata_host *host = dev_get_drvdata(dev);
1787894fba7fSKai-Heng Feng 	struct ahci_host_priv *hpriv = host->private_data;
1788894fba7fSKai-Heng Feng 
1789179a0282SDamien Le Moal 	return sysfs_emit(buf, "%u\n", hpriv->remapped_nvme);
1790894fba7fSKai-Heng Feng }
1791894fba7fSKai-Heng Feng 
1792894fba7fSKai-Heng Feng static DEVICE_ATTR_RO(remapped_nvme);
1793894fba7fSKai-Heng Feng 
ahci_init_one(struct pci_dev * pdev,const struct pci_device_id * ent)1794c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1795c6fd2807SJeff Garzik {
1796e297d99eSTejun Heo 	unsigned int board_id = ent->driver_data;
1797e297d99eSTejun Heo 	struct ata_port_info pi = ahci_port_info[board_id];
17984447d351STejun Heo 	const struct ata_port_info *ppi[] = { &pi, NULL };
179924dc5f33STejun Heo 	struct device *dev = &pdev->dev;
1800c6fd2807SJeff Garzik 	struct ahci_host_priv *hpriv;
18014447d351STejun Heo 	struct ata_host *host;
1802c3ebd6a9SAlexander Gordeev 	int n_ports, i, rc;
1803318893e1SAlessandro Rubini 	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;
1804c6fd2807SJeff Garzik 
1805b429dd59SJustin P. Mattock 	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
1806c6fd2807SJeff Garzik 
180706296a1eSJoe Perches 	ata_print_version_once(&pdev->dev, DRV_VERSION);
1808c6fd2807SJeff Garzik 
18095b66c829SAlan Cox 	/* The AHCI driver can only drive the SATA ports, the PATA driver
18105b66c829SAlan Cox 	   can drive them all so if both drivers are selected make sure
18115b66c829SAlan Cox 	   AHCI stays out of the way */
18125b66c829SAlan Cox 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
18135b66c829SAlan Cox 		return -ENODEV;
18145b66c829SAlan Cox 
1815cb85696dSJames Laird 	/* Apple BIOS on MCP89 prevents us using AHCI */
1816cb85696dSJames Laird 	if (is_mcp89_apple(pdev))
1817cb85696dSJames Laird 		ahci_mcp89_apple_enable(pdev);
1818c6353b45STejun Heo 
18197a02267eSMark Nelson 	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
18207a02267eSMark Nelson 	 * At the moment, we can only use the AHCI mode. Let the users know
18217a02267eSMark Nelson 	 * that for SAS drives they're out of luck.
18227a02267eSMark Nelson 	 */
18237a02267eSMark Nelson 	if (pdev->vendor == PCI_VENDOR_ID_PROMISE)
1824a44fec1fSJoe Perches 		dev_info(&pdev->dev,
1825a44fec1fSJoe Perches 			 "PDC42819 can only drive SATA devices with this driver\n");
18267a02267eSMark Nelson 
1827b7ae128dSRobert Richter 	/* Some devices use non-standard BARs */
1828318893e1SAlessandro Rubini 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
1829318893e1SAlessandro Rubini 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
18307f9c9f8eSHugh Daschbach 	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
18317f9c9f8eSHugh Daschbach 		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
1832b1314e3fSRadha Mohan Chintakuntla 	else if (pdev->vendor == PCI_VENDOR_ID_CAVIUM) {
1833b1314e3fSRadha Mohan Chintakuntla 		if (pdev->device == 0xa01c)
1834b7ae128dSRobert Richter 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM;
1835b1314e3fSRadha Mohan Chintakuntla 		if (pdev->device == 0xa084)
1836b1314e3fSRadha Mohan Chintakuntla 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5;
1837e49bd683STiezhu Yang 	} else if (pdev->vendor == PCI_VENDOR_ID_LOONGSON) {
1838e49bd683STiezhu Yang 		if (pdev->device == 0x7a08)
1839e49bd683STiezhu Yang 			ahci_pci_bar = AHCI_PCI_BAR_LOONGSON;
1840b1314e3fSRadha Mohan Chintakuntla 	}
1841318893e1SAlessandro Rubini 
18424447d351STejun Heo 	/* acquire resources */
184324dc5f33STejun Heo 	rc = pcim_enable_device(pdev);
1844c6fd2807SJeff Garzik 	if (rc)
1845c6fd2807SJeff Garzik 		return rc;
1846c6fd2807SJeff Garzik 
1847c4f7792cSTejun Heo 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
1848c4f7792cSTejun Heo 	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {
1849c4f7792cSTejun Heo 		u8 map;
1850c4f7792cSTejun Heo 
1851c4f7792cSTejun Heo 		/* ICH6s share the same PCI ID for both piix and ahci
1852c4f7792cSTejun Heo 		 * modes.  Enabling ahci mode while MAP indicates
1853c4f7792cSTejun Heo 		 * combined mode is a bad idea.  Yield to ata_piix.
1854c4f7792cSTejun Heo 		 */
1855c4f7792cSTejun Heo 		pci_read_config_byte(pdev, ICH_MAP, &map);
1856c4f7792cSTejun Heo 		if (map & 0x3) {
1857a44fec1fSJoe Perches 			dev_info(&pdev->dev,
1858a44fec1fSJoe Perches 				 "controller is in combined mode, can't enable AHCI mode\n");
1859c4f7792cSTejun Heo 			return -ENODEV;
1860c4f7792cSTejun Heo 		}
1861c4f7792cSTejun Heo 	}
1862c4f7792cSTejun Heo 
18636fec8871SPaul Bolle 	/* AHCI controllers often implement SFF compatible interface.
18646fec8871SPaul Bolle 	 * Grab all PCI BARs just in case.
18656fec8871SPaul Bolle 	 */
18666fec8871SPaul Bolle 	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
18676fec8871SPaul Bolle 	if (rc == -EBUSY)
18686fec8871SPaul Bolle 		pcim_pin_device(pdev);
18696fec8871SPaul Bolle 	if (rc)
18706fec8871SPaul Bolle 		return rc;
18716fec8871SPaul Bolle 
187224dc5f33STejun Heo 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
187324dc5f33STejun Heo 	if (!hpriv)
187424dc5f33STejun Heo 		return -ENOMEM;
1875417a1a6dSTejun Heo 	hpriv->flags |= (unsigned long)pi.private_data;
1876417a1a6dSTejun Heo 
1877e297d99eSTejun Heo 	/* MCP65 revision A1 and A2 can't do MSI */
1878e297d99eSTejun Heo 	if (board_id == board_ahci_mcp65 &&
1879e297d99eSTejun Heo 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
1880e297d99eSTejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_MSI;
1881e297d99eSTejun Heo 
1882e427fe04SShane Huang 	/* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
1883e427fe04SShane Huang 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
1884e427fe04SShane Huang 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
1885e427fe04SShane Huang 
18862fcad9d2STejun Heo 	/* only some SB600s can do 64bit DMA */
18872fcad9d2STejun Heo 	if (ahci_sb600_enable_64bit(pdev))
18882fcad9d2STejun Heo 		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY;
188958a09b38SShane Huang 
1890318893e1SAlessandro Rubini 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
1891d8993349SAnton Vorontsov 
1892aecec8b6SChristoph Hellwig 	/* detect remapped nvme devices */
1893aecec8b6SChristoph Hellwig 	ahci_remap_check(pdev, ahci_pci_bar, hpriv);
1894aecec8b6SChristoph Hellwig 
1895894fba7fSKai-Heng Feng 	sysfs_add_file_to_group(&pdev->dev.kobj,
1896894fba7fSKai-Heng Feng 				&dev_attr_remapped_nvme.attr,
1897894fba7fSKai-Heng Feng 				NULL);
1898894fba7fSKai-Heng Feng 
18990cf4a7d6SJacob Pan 	/* must set flag prior to save config in order to take effect */
19000cf4a7d6SJacob Pan 	if (ahci_broken_devslp(pdev))
19010cf4a7d6SJacob Pan 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
19020cf4a7d6SJacob Pan 
1903d243bed3STirumalesh Chalamarla #ifdef CONFIG_ARM64
1904234e6d2cSXingui Yang 	if (pdev->vendor == PCI_VENDOR_ID_HUAWEI &&
1905234e6d2cSXingui Yang 	    pdev->device == 0xa235 &&
1906234e6d2cSXingui Yang 	    pdev->revision < 0x30)
1907234e6d2cSXingui Yang 		hpriv->flags |= AHCI_HFLAG_NO_SXS;
1908234e6d2cSXingui Yang 
1909d243bed3STirumalesh Chalamarla 	if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
1910d243bed3STirumalesh Chalamarla 		hpriv->irq_handler = ahci_thunderx_irq_handler;
1911d243bed3STirumalesh Chalamarla #endif
1912d243bed3STirumalesh Chalamarla 
19134447d351STejun Heo 	/* save initial config */
1914394d6e53SAnton Vorontsov 	ahci_pci_save_initial_config(pdev, hpriv);
1915c6fd2807SJeff Garzik 
19164447d351STejun Heo 	/* prepare host */
1917453d3131SRobert Hancock 	if (hpriv->cap & HOST_CAP_NCQ) {
1918453d3131SRobert Hancock 		pi.flags |= ATA_FLAG_NCQ;
191983f2b963STejun Heo 		/*
192083f2b963STejun Heo 		 * Auto-activate optimization is supposed to be
192183f2b963STejun Heo 		 * supported on all AHCI controllers indicating NCQ
192283f2b963STejun Heo 		 * capability, but it seems to be broken on some
192383f2b963STejun Heo 		 * chipsets including NVIDIAs.
192483f2b963STejun Heo 		 */
192583f2b963STejun Heo 		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))
1926453d3131SRobert Hancock 			pi.flags |= ATA_FLAG_FPDMA_AA;
192740fb59e7SMarc Carino 
192840fb59e7SMarc Carino 		/*
192940fb59e7SMarc Carino 		 * All AHCI controllers should be forward-compatible
193040fb59e7SMarc Carino 		 * with the new auxiliary field. This code should be
193140fb59e7SMarc Carino 		 * conditionalized if any buggy AHCI controllers are
193240fb59e7SMarc Carino 		 * encountered.
193340fb59e7SMarc Carino 		 */
193440fb59e7SMarc Carino 		pi.flags |= ATA_FLAG_FPDMA_AUX;
1935453d3131SRobert Hancock 	}
19364447d351STejun Heo 
19377d50b60bSTejun Heo 	if (hpriv->cap & HOST_CAP_PMP)
19387d50b60bSTejun Heo 		pi.flags |= ATA_FLAG_PMP;
19397d50b60bSTejun Heo 
19400cbb0e77SAnton Vorontsov 	ahci_set_em_messages(hpriv, &pi);
194118f7ba4cSKristen Carlson Accardi 
19421fd68434SRafael J. Wysocki 	if (ahci_broken_system_poweroff(pdev)) {
19431fd68434SRafael J. Wysocki 		pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
19441fd68434SRafael J. Wysocki 		dev_info(&pdev->dev,
19451fd68434SRafael J. Wysocki 			"quirky BIOS, skipping spindown on poweroff\n");
19461fd68434SRafael J. Wysocki 	}
19471fd68434SRafael J. Wysocki 
1948240630e6SHans de Goede 	if (ahci_broken_lpm(pdev)) {
1949240630e6SHans de Goede 		pi.flags |= ATA_FLAG_NO_LPM;
1950240630e6SHans de Goede 		dev_warn(&pdev->dev,
1951240630e6SHans de Goede 			 "BIOS update required for Link Power Management support\n");
1952240630e6SHans de Goede 	}
1953240630e6SHans de Goede 
19549b10ae86STejun Heo 	if (ahci_broken_suspend(pdev)) {
19559b10ae86STejun Heo 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
1956a44fec1fSJoe Perches 		dev_warn(&pdev->dev,
19579b10ae86STejun Heo 			 "BIOS update required for suspend/resume\n");
19589b10ae86STejun Heo 	}
19599b10ae86STejun Heo 
19605594639aSTejun Heo 	if (ahci_broken_online(pdev)) {
19615594639aSTejun Heo 		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
19625594639aSTejun Heo 		dev_info(&pdev->dev,
19635594639aSTejun Heo 			 "online status unreliable, applying workaround\n");
19645594639aSTejun Heo 	}
19655594639aSTejun Heo 
19668bfd1743SSui Chen 
19678bfd1743SSui Chen 	/* Acer SA5-271 workaround modifies private_data */
19688bfd1743SSui Chen 	acer_sa5_271_workaround(hpriv, pdev);
19698bfd1743SSui Chen 
1970837f5f8fSTejun Heo 	/* CAP.NP sometimes indicate the index of the last enabled
1971837f5f8fSTejun Heo 	 * port, at other times, that of the last possible port, so
1972837f5f8fSTejun Heo 	 * determining the maximum port number requires looking at
1973837f5f8fSTejun Heo 	 * both CAP.NP and port_map.
1974837f5f8fSTejun Heo 	 */
1975837f5f8fSTejun Heo 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
1976837f5f8fSTejun Heo 
1977837f5f8fSTejun Heo 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
1978d8d54126SNiklas Cassel 	if (!host) {
1979d8d54126SNiklas Cassel 		rc = -ENOMEM;
1980d8d54126SNiklas Cassel 		goto err_rm_sysfs_file;
1981d8d54126SNiklas Cassel 	}
19824447d351STejun Heo 	host->private_data = hpriv;
19830b9e2988SChristoph Hellwig 
19840b9e2988SChristoph Hellwig 	if (ahci_init_msi(pdev, n_ports, hpriv) < 0) {
19850b9e2988SChristoph Hellwig 		/* legacy intx interrupts */
19860b9e2988SChristoph Hellwig 		pci_intx(pdev, 1);
19870b9e2988SChristoph Hellwig 	}
19880ce57f8aSChristoph Hellwig 	hpriv->irq = pci_irq_vector(pdev, 0);
198921bfd1aaSRobert Richter 
1990f3d7f23fSArjan van de Ven 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
1991886ad09fSArjan van de Ven 		host->flags |= ATA_HOST_PARALLEL_SCAN;
1992f3d7f23fSArjan van de Ven 	else
1993d2782d96SJingoo Han 		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
1994886ad09fSArjan van de Ven 
199524e0e61dSNiklas Cassel 	if (!(hpriv->cap & HOST_CAP_PART))
199624e0e61dSNiklas Cassel 		host->flags |= ATA_HOST_NO_PART;
199724e0e61dSNiklas Cassel 
199824e0e61dSNiklas Cassel 	if (!(hpriv->cap & HOST_CAP_SSC))
199924e0e61dSNiklas Cassel 		host->flags |= ATA_HOST_NO_SSC;
200024e0e61dSNiklas Cassel 
200124e0e61dSNiklas Cassel 	if (!(hpriv->cap2 & HOST_CAP2_SDS))
200224e0e61dSNiklas Cassel 		host->flags |= ATA_HOST_NO_DEVSLP;
200324e0e61dSNiklas Cassel 
200418f7ba4cSKristen Carlson Accardi 	if (pi.flags & ATA_FLAG_EM)
200518f7ba4cSKristen Carlson Accardi 		ahci_reset_em(host);
200618f7ba4cSKristen Carlson Accardi 
20074447d351STejun Heo 	for (i = 0; i < host->n_ports; i++) {
20084447d351STejun Heo 		struct ata_port *ap = host->ports[i];
20094447d351STejun Heo 
2010318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar");
2011318893e1SAlessandro Rubini 		ata_port_pbar_desc(ap, ahci_pci_bar,
2012cbcdd875STejun Heo 				   0x100 + ap->port_no * 0x80, "port");
2013cbcdd875STejun Heo 
201418f7ba4cSKristen Carlson Accardi 		/* set enclosure management message type */
201518f7ba4cSKristen Carlson Accardi 		if (ap->flags & ATA_FLAG_EM)
2016008dbd61SHarry Zhang 			ap->em_message_type = hpriv->em_msg_type;
201718f7ba4cSKristen Carlson Accardi 
2018b1a9585cSSrinivas Pandruvada 		ahci_update_initial_lpm_policy(ap, hpriv);
201918f7ba4cSKristen Carlson Accardi 
2020dab632e8SJeff Garzik 		/* disabled/not-implemented port */
2021350756f6STejun Heo 		if (!(hpriv->port_map & (1 << i)))
2022dab632e8SJeff Garzik 			ap->ops = &ata_dummy_port_ops;
20234447d351STejun Heo 	}
2024c6fd2807SJeff Garzik 
2025edc93052STejun Heo 	/* apply workaround for ASUS P5W DH Deluxe mainboard */
2026edc93052STejun Heo 	ahci_p5wdh_workaround(host);
2027edc93052STejun Heo 
2028f80ae7e4STejun Heo 	/* apply gtf filter quirk */
2029f80ae7e4STejun Heo 	ahci_gtf_filter_workaround(host);
2030f80ae7e4STejun Heo 
2031c6fd2807SJeff Garzik 	/* initialize adapter */
2032b0dd4d7aSLennert Buytenhek 	rc = ahci_configure_dma_masks(pdev, hpriv);
2033c6fd2807SJeff Garzik 	if (rc)
2034d8d54126SNiklas Cassel 		goto err_rm_sysfs_file;
2035c6fd2807SJeff Garzik 
203637e14e4fSAdam Vodopjan 	rc = ahci_pci_reset_controller(host);
20374447d351STejun Heo 	if (rc)
2038d8d54126SNiklas Cassel 		goto err_rm_sysfs_file;
2039c6fd2807SJeff Garzik 
2040781d6550SAnton Vorontsov 	ahci_pci_init_controller(host);
2041439fcaecSAnton Vorontsov 	ahci_pci_print_info(host);
2042c6fd2807SJeff Garzik 
20434447d351STejun Heo 	pci_set_master(pdev);
20445ca72c4fSAlexander Gordeev 
204502e53293SMika Westerberg 	rc = ahci_host_activate(host, &ahci_sht);
204602e53293SMika Westerberg 	if (rc)
2047d8d54126SNiklas Cassel 		goto err_rm_sysfs_file;
204802e53293SMika Westerberg 
204902e53293SMika Westerberg 	pm_runtime_put_noidle(&pdev->dev);
205002e53293SMika Westerberg 	return 0;
2051d8d54126SNiklas Cassel 
2052d8d54126SNiklas Cassel err_rm_sysfs_file:
2053d8d54126SNiklas Cassel 	sysfs_remove_file_from_group(&pdev->dev.kobj,
2054d8d54126SNiklas Cassel 				     &dev_attr_remapped_nvme.attr, NULL);
2055d8d54126SNiklas Cassel 	return rc;
205602e53293SMika Westerberg }
205702e53293SMika Westerberg 
ahci_shutdown_one(struct pci_dev * pdev)205810a663a1SPrabhakar Kushwaha static void ahci_shutdown_one(struct pci_dev *pdev)
205910a663a1SPrabhakar Kushwaha {
206010a663a1SPrabhakar Kushwaha 	ata_pci_shutdown_one(pdev);
206110a663a1SPrabhakar Kushwaha }
206210a663a1SPrabhakar Kushwaha 
ahci_remove_one(struct pci_dev * pdev)206302e53293SMika Westerberg static void ahci_remove_one(struct pci_dev *pdev)
206402e53293SMika Westerberg {
2065894fba7fSKai-Heng Feng 	sysfs_remove_file_from_group(&pdev->dev.kobj,
2066894fba7fSKai-Heng Feng 				     &dev_attr_remapped_nvme.attr,
2067894fba7fSKai-Heng Feng 				     NULL);
206802e53293SMika Westerberg 	pm_runtime_get_noresume(&pdev->dev);
206902e53293SMika Westerberg 	ata_pci_remove_one(pdev);
2070c6fd2807SJeff Garzik }
2071c6fd2807SJeff Garzik 
20722fc75da0SAxel Lin module_pci_driver(ahci_pci_driver);
2073c6fd2807SJeff Garzik 
2074c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik");
2075c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver");
2076c6fd2807SJeff Garzik MODULE_LICENSE("GPL");
2077c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);
2078c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION);
2079