1c6fd2807SJeff Garzik /* 2c6fd2807SJeff Garzik * ahci.c - AHCI SATA support 3c6fd2807SJeff Garzik * 48c3d3d4bSTejun Heo * Maintained by: Tejun Heo <tj@kernel.org> 5c6fd2807SJeff Garzik * Please ALWAYS copy linux-ide@vger.kernel.org 6c6fd2807SJeff Garzik * on emails. 7c6fd2807SJeff Garzik * 8c6fd2807SJeff Garzik * Copyright 2004-2005 Red Hat, Inc. 9c6fd2807SJeff Garzik * 10c6fd2807SJeff Garzik * 11c6fd2807SJeff Garzik * This program is free software; you can redistribute it and/or modify 12c6fd2807SJeff Garzik * it under the terms of the GNU General Public License as published by 13c6fd2807SJeff Garzik * the Free Software Foundation; either version 2, or (at your option) 14c6fd2807SJeff Garzik * any later version. 15c6fd2807SJeff Garzik * 16c6fd2807SJeff Garzik * This program is distributed in the hope that it will be useful, 17c6fd2807SJeff Garzik * but WITHOUT ANY WARRANTY; without even the implied warranty of 18c6fd2807SJeff Garzik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19c6fd2807SJeff Garzik * GNU General Public License for more details. 20c6fd2807SJeff Garzik * 21c6fd2807SJeff Garzik * You should have received a copy of the GNU General Public License 22c6fd2807SJeff Garzik * along with this program; see the file COPYING. If not, write to 23c6fd2807SJeff Garzik * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 24c6fd2807SJeff Garzik * 25c6fd2807SJeff Garzik * 26c6fd2807SJeff Garzik * libata documentation is available via 'make {ps|pdf}docs', 27c6fd2807SJeff Garzik * as Documentation/DocBook/libata.* 28c6fd2807SJeff Garzik * 29c6fd2807SJeff Garzik * AHCI hardware documentation: 30c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf 31c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf 32c6fd2807SJeff Garzik * 33c6fd2807SJeff Garzik */ 34c6fd2807SJeff Garzik 35c6fd2807SJeff Garzik #include <linux/kernel.h> 36c6fd2807SJeff Garzik #include <linux/module.h> 37c6fd2807SJeff Garzik #include <linux/pci.h> 38c6fd2807SJeff Garzik #include <linux/blkdev.h> 39c6fd2807SJeff Garzik #include <linux/delay.h> 40c6fd2807SJeff Garzik #include <linux/interrupt.h> 41c6fd2807SJeff Garzik #include <linux/dma-mapping.h> 42c6fd2807SJeff Garzik #include <linux/device.h> 43edc93052STejun Heo #include <linux/dmi.h> 445a0e3ad6STejun Heo #include <linux/gfp.h> 45ee2aad42SRobert Richter #include <linux/msi.h> 46c6fd2807SJeff Garzik #include <scsi/scsi_host.h> 47c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h> 48c6fd2807SJeff Garzik #include <linux/libata.h> 49365cfa1eSAnton Vorontsov #include "ahci.h" 50c6fd2807SJeff Garzik 51c6fd2807SJeff Garzik #define DRV_NAME "ahci" 527d50b60bSTejun Heo #define DRV_VERSION "3.0" 53c6fd2807SJeff Garzik 54c6fd2807SJeff Garzik enum { 55318893e1SAlessandro Rubini AHCI_PCI_BAR_STA2X11 = 0, 56b7ae128dSRobert Richter AHCI_PCI_BAR_CAVIUM = 0, 577f9c9f8eSHugh Daschbach AHCI_PCI_BAR_ENMOTUS = 2, 58318893e1SAlessandro Rubini AHCI_PCI_BAR_STANDARD = 5, 59441577efSTejun Heo }; 60c6fd2807SJeff Garzik 61441577efSTejun Heo enum board_ids { 62441577efSTejun Heo /* board IDs by feature in alphabetical order */ 63441577efSTejun Heo board_ahci, 64441577efSTejun Heo board_ahci_ign_iferr, 6566a7cbc3STejun Heo board_ahci_nomsi, 6667809f85SLevente Kurusa board_ahci_noncq, 67441577efSTejun Heo board_ahci_nosntf, 685f173107STejun Heo board_ahci_yes_fbs, 69441577efSTejun Heo 70441577efSTejun Heo /* board IDs for specific chipsets in alphabetical order */ 71dbfe8ef5SDan Williams board_ahci_avn, 72441577efSTejun Heo board_ahci_mcp65, 7383f2b963STejun Heo board_ahci_mcp77, 7483f2b963STejun Heo board_ahci_mcp89, 75441577efSTejun Heo board_ahci_mv, 76441577efSTejun Heo board_ahci_sb600, 77441577efSTejun Heo board_ahci_sb700, /* for SB700 and SB800 */ 78441577efSTejun Heo board_ahci_vt8251, 79441577efSTejun Heo 80441577efSTejun Heo /* aliases */ 81441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 82441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 83441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 8483f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 85c6fd2807SJeff Garzik }; 86c6fd2807SJeff Garzik 87c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 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); 96438ac6d5STejun Heo #ifdef CONFIG_PM 97c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); 98c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev); 99438ac6d5STejun Heo #endif 100c6fd2807SJeff Garzik 101fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = { 102fad16e7aSTejun Heo AHCI_SHT("ahci"), 103fad16e7aSTejun Heo }; 104fad16e7aSTejun Heo 105029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 106029cfd6bSTejun Heo .inherits = &ahci_ops, 107a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 108ad616ffbSTejun Heo }; 109ad616ffbSTejun Heo 110029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 111029cfd6bSTejun Heo .inherits = &ahci_ops, 112a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 113edc93052STejun Heo }; 114edc93052STejun Heo 115dbfe8ef5SDan Williams static struct ata_port_operations ahci_avn_ops = { 116dbfe8ef5SDan Williams .inherits = &ahci_ops, 117dbfe8ef5SDan Williams .hardreset = ahci_avn_hardreset, 118dbfe8ef5SDan Williams }; 119dbfe8ef5SDan Williams 120c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 121441577efSTejun Heo /* by features */ 122facb8fa6SJeffrin Jose [board_ahci] = { 1231188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 12414bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 125469248abSJeff Garzik .udma_mask = ATA_UDMA6, 126c6fd2807SJeff Garzik .port_ops = &ahci_ops, 127c6fd2807SJeff Garzik }, 128facb8fa6SJeffrin Jose [board_ahci_ign_iferr] = { 129417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 130417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 13114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 132469248abSJeff Garzik .udma_mask = ATA_UDMA6, 13341669553STejun Heo .port_ops = &ahci_ops, 13441669553STejun Heo }, 13566a7cbc3STejun Heo [board_ahci_nomsi] = { 13666a7cbc3STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), 13766a7cbc3STejun Heo .flags = AHCI_FLAG_COMMON, 13866a7cbc3STejun Heo .pio_mask = ATA_PIO4, 13966a7cbc3STejun Heo .udma_mask = ATA_UDMA6, 14066a7cbc3STejun Heo .port_ops = &ahci_ops, 14166a7cbc3STejun Heo }, 14267809f85SLevente Kurusa [board_ahci_noncq] = { 14367809f85SLevente Kurusa AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), 14467809f85SLevente Kurusa .flags = AHCI_FLAG_COMMON, 14567809f85SLevente Kurusa .pio_mask = ATA_PIO4, 14667809f85SLevente Kurusa .udma_mask = ATA_UDMA6, 14767809f85SLevente Kurusa .port_ops = &ahci_ops, 14867809f85SLevente Kurusa }, 149facb8fa6SJeffrin Jose [board_ahci_nosntf] = { 150441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 151441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 152441577efSTejun Heo .pio_mask = ATA_PIO4, 153441577efSTejun Heo .udma_mask = ATA_UDMA6, 154441577efSTejun Heo .port_ops = &ahci_ops, 155441577efSTejun Heo }, 156facb8fa6SJeffrin Jose [board_ahci_yes_fbs] = { 1575f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1585f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1595f173107STejun Heo .pio_mask = ATA_PIO4, 1605f173107STejun Heo .udma_mask = ATA_UDMA6, 1615f173107STejun Heo .port_ops = &ahci_ops, 1625f173107STejun Heo }, 163441577efSTejun Heo /* by chipsets */ 164dbfe8ef5SDan Williams [board_ahci_avn] = { 165dbfe8ef5SDan Williams .flags = AHCI_FLAG_COMMON, 166dbfe8ef5SDan Williams .pio_mask = ATA_PIO4, 167dbfe8ef5SDan Williams .udma_mask = ATA_UDMA6, 168dbfe8ef5SDan Williams .port_ops = &ahci_avn_ops, 169dbfe8ef5SDan Williams }, 170facb8fa6SJeffrin Jose [board_ahci_mcp65] = { 17183f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 17283f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 173ae01b249STejun Heo .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, 17483f2b963STejun Heo .pio_mask = ATA_PIO4, 17583f2b963STejun Heo .udma_mask = ATA_UDMA6, 17683f2b963STejun Heo .port_ops = &ahci_ops, 17783f2b963STejun Heo }, 178facb8fa6SJeffrin Jose [board_ahci_mcp77] = { 17983f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 18083f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 18183f2b963STejun Heo .pio_mask = ATA_PIO4, 18283f2b963STejun Heo .udma_mask = ATA_UDMA6, 18383f2b963STejun Heo .port_ops = &ahci_ops, 18483f2b963STejun Heo }, 185facb8fa6SJeffrin Jose [board_ahci_mcp89] = { 18683f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 187441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 188441577efSTejun Heo .pio_mask = ATA_PIO4, 189441577efSTejun Heo .udma_mask = ATA_UDMA6, 190441577efSTejun Heo .port_ops = &ahci_ops, 191441577efSTejun Heo }, 192facb8fa6SJeffrin Jose [board_ahci_mv] = { 193441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 194441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 1959cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 196441577efSTejun Heo .pio_mask = ATA_PIO4, 197441577efSTejun Heo .udma_mask = ATA_UDMA6, 198441577efSTejun Heo .port_ops = &ahci_ops, 199441577efSTejun Heo }, 200facb8fa6SJeffrin Jose [board_ahci_sb600] = { 201417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 2022fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 2032fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 204417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 20514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 206469248abSJeff Garzik .udma_mask = ATA_UDMA6, 207345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 20855a61604SConke Hu }, 209facb8fa6SJeffrin Jose [board_ahci_sb700] = { /* for SB700 and SB800 */ 210bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 211e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 21214bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 213e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 214345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 215e39fc8c9SShane Huang }, 216facb8fa6SJeffrin Jose [board_ahci_vt8251] = { 217441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 218e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 21914bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 220e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 221441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 2221b677afdSShaohua Li }, 223c6fd2807SJeff Garzik }; 224c6fd2807SJeff Garzik 225c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 226c6fd2807SJeff Garzik /* Intel */ 22754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 22854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 22954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 23054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 23154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 23282490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 23354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 23454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 23554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 23654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2377a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2381b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2397a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2407a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2417a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2427a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2437a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2447a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2457a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2467a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 2477a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ 2487a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ 2497a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ 2507a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */ 2517a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ 2527a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 2537a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ 254d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 255d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 25616ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 257b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 25816ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 259c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 260c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 261adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2628e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 263c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ 264adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 2658e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ 266c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 2675623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 2685623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ 2695623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 2705623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ 2715623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 2725623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 273992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 274992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 275992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 27664a3903dSSeth Heasley { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ 277a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 278181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ 279181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */ 280181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ 281181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ 282181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ 283181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */ 2842cab7a4cSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ 285ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ 286ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */ 287ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ 288ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */ 289ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ 290ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ 291ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ 292ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ 29377b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ 29477b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ 29577b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ 29677b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */ 29777b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */ 29877b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */ 29977b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */ 30077b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */ 30129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ 30229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ 30329e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ 30429e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ 30529e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ 30629e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ 30729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ 30829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ 309dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */ 310dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */ 311dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */ 312dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */ 313dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */ 314dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */ 315dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */ 316dbfe8ef5SDan Williams { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */ 317efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ 318efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ 319151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ 320151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ 321151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ 322151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ 323151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ 324151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ 325151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ 326151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ 3271cfc7df3SSeth Heasley { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ 3289f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */ 3299f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */ 3309f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ 3319f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */ 3321b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ 3331b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */ 3341b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ 3351b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */ 3361b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ 3371b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ 3381b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ 3391b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ 340249cd0a1SDevin Ryles { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */ 341249cd0a1SDevin Ryles { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */ 342249cd0a1SDevin Ryles { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */ 343690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */ 344690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ 345690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */ 346690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ 347c6fd2807SJeff Garzik 348e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 349e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 350e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 3511fefb8fdSBen Hutchings /* JMicron 362B and 362C have an AHCI function with IDE class code */ 3521fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, 3531fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, 35491f15fb3SZhang Rui /* May need to update quirk_jmicron_async_suspend() for additions */ 355c6fd2807SJeff Garzik 356c6fd2807SJeff Garzik /* ATI */ 357c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 358e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 359e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 360e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 361e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 362e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 363e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 364c6fd2807SJeff Garzik 365e2dd90b1SShane Huang /* AMD */ 3665deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 367fafe5c3dSShane Huang { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ 368e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 369e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 370e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 371e2dd90b1SShane Huang 372c6fd2807SJeff Garzik /* VIA */ 37354bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 374bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 375c6fd2807SJeff Garzik 376c6fd2807SJeff Garzik /* NVIDIA */ 377e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 378e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 379e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 380e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 381e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 382e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 383e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 384e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 385441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 386441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 387441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 388441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 389441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 390441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 391441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 392441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 393441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 394441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 395441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 396441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 397441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 398441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 399441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 400441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 401441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 402441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 403441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 404441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 405441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 406441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 407441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 408441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 409441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 410441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 411441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 412441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 413441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 414441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 415441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 416441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 417441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 418441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 419441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 420441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 421441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 422441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 423441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 424441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 425441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 426441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 427441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 428441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 429441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 430441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 431441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 432441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 433441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 434441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 435441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 436441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 437441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 438441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 439441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 440441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 441441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 442441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 443441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 444441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 445441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 446441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 447441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 448441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 449441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 450441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 451441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 452441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 453441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 454441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 455441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 456441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 457441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 458441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 459441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 460441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 461c6fd2807SJeff Garzik 462c6fd2807SJeff Garzik /* SiS */ 46320e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 46420e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 46520e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 466c6fd2807SJeff Garzik 467318893e1SAlessandro Rubini /* ST Microelectronics */ 468318893e1SAlessandro Rubini { PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */ 469318893e1SAlessandro Rubini 470cd70c266SJeff Garzik /* Marvell */ 471cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 472c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 47369fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), 47410aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 47510aca06cSAnssi Hannula .class_mask = 0xffffff, 4765f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 47769fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), 478467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 479e098f5cbSSimon Guinot { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178, 480e098f5cbSSimon Guinot PCI_VENDOR_ID_MARVELL_EXT, 0x9170), 481e098f5cbSSimon Guinot .driver_data = board_ahci_yes_fbs }, /* 88se9170 */ 48269fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), 483642d8925SMatt Johnson .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 484fcce9a35SGeorge Spelvin { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), 485c5edfff9SMurali Karicheri .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ 486c5edfff9SMurali Karicheri { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), 487fcce9a35SGeorge Spelvin .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 48869fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), 48917c60c6bSAlan Cox .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ 490754a292fSAndreas Schrägle { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), 491754a292fSAndreas Schrägle .driver_data = board_ahci_yes_fbs }, 492*a40cf3f3SJohannes Thumshirn { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a2), /* 88se91a2 */ 493*a40cf3f3SJohannes Thumshirn .driver_data = board_ahci_yes_fbs }, 49469fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), 49550be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 4966d5278a6SSamir Benmendil { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), 4976d5278a6SSamir Benmendil .driver_data = board_ahci_yes_fbs }, 498d2518365SJérôme Carretero { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), 499d2518365SJérôme Carretero .driver_data = board_ahci_yes_fbs }, 500cd70c266SJeff Garzik 501c77a036bSMark Nelson /* Promise */ 502c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 503b32bfc06SRomain Degez { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ 504c77a036bSMark Nelson 505c9703765SKeng-Yu Lin /* Asmedia */ 5067b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ 5077b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ 5087b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ 5097b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ 510c9703765SKeng-Yu Lin 51167809f85SLevente Kurusa /* 51266a7cbc3STejun Heo * Samsung SSDs found on some macbooks. NCQ times out if MSI is 51366a7cbc3STejun Heo * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 51467809f85SLevente Kurusa */ 51566a7cbc3STejun Heo { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, 5162b21ef0aSTejun Heo { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, 51767809f85SLevente Kurusa 5187f9c9f8eSHugh Daschbach /* Enmotus */ 5197f9c9f8eSHugh Daschbach { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, 5207f9c9f8eSHugh Daschbach 521415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 522415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 523c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 524415ae2b5SJeff Garzik 525c6fd2807SJeff Garzik { } /* terminate list */ 526c6fd2807SJeff Garzik }; 527c6fd2807SJeff Garzik 528c6fd2807SJeff Garzik 529c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 530c6fd2807SJeff Garzik .name = DRV_NAME, 531c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 532c6fd2807SJeff Garzik .probe = ahci_init_one, 53324dc5f33STejun Heo .remove = ata_pci_remove_one, 534438ac6d5STejun Heo #ifdef CONFIG_PM 535c6fd2807SJeff Garzik .suspend = ahci_pci_device_suspend, 536c6fd2807SJeff Garzik .resume = ahci_pci_device_resume, 537438ac6d5STejun Heo #endif 538c6fd2807SJeff Garzik }; 539c6fd2807SJeff Garzik 5405b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE) 5415b66c829SAlan Cox static int marvell_enable; 5425b66c829SAlan Cox #else 5435b66c829SAlan Cox static int marvell_enable = 1; 5445b66c829SAlan Cox #endif 5455b66c829SAlan Cox module_param(marvell_enable, int, 0644); 5465b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 5475b66c829SAlan Cox 5485b66c829SAlan Cox 549394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 550394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 551394d6e53SAnton Vorontsov { 552394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 553394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 5549a23c1d6SAntoine Tenart hpriv->force_port_map = 1; 555394d6e53SAnton Vorontsov } 556394d6e53SAnton Vorontsov 557394d6e53SAnton Vorontsov /* 558394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 559394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 560394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 561394d6e53SAnton Vorontsov */ 562394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 563394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 5649a23c1d6SAntoine Tenart hpriv->mask_port_map = 0x3; 565394d6e53SAnton Vorontsov else 5669a23c1d6SAntoine Tenart hpriv->mask_port_map = 0xf; 567394d6e53SAnton Vorontsov dev_info(&pdev->dev, 568394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 569394d6e53SAnton Vorontsov } 570394d6e53SAnton Vorontsov 571725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv); 572394d6e53SAnton Vorontsov } 573394d6e53SAnton Vorontsov 5743303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host) 5753303040dSAnton Vorontsov { 5763303040dSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 5773303040dSAnton Vorontsov 5783303040dSAnton Vorontsov ahci_reset_controller(host); 5793303040dSAnton Vorontsov 580c6fd2807SJeff Garzik if (pdev->vendor == PCI_VENDOR_ID_INTEL) { 5813303040dSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 582c6fd2807SJeff Garzik u16 tmp16; 583c6fd2807SJeff Garzik 584c6fd2807SJeff Garzik /* configure PCS */ 585c6fd2807SJeff Garzik pci_read_config_word(pdev, 0x92, &tmp16); 58649f29090STejun Heo if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 58749f29090STejun Heo tmp16 |= hpriv->port_map; 588c6fd2807SJeff Garzik pci_write_config_word(pdev, 0x92, tmp16); 589c6fd2807SJeff Garzik } 59049f29090STejun Heo } 591c6fd2807SJeff Garzik 592c6fd2807SJeff Garzik return 0; 593c6fd2807SJeff Garzik } 594c6fd2807SJeff Garzik 595781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 596781d6550SAnton Vorontsov { 597781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 598781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 599781d6550SAnton Vorontsov void __iomem *port_mmio; 600781d6550SAnton Vorontsov u32 tmp; 601c40e7cb8SJose Alberto Reguero int mv; 6022bcd866bSJeff Garzik 603417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 604c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 605c40e7cb8SJose Alberto Reguero mv = 2; 606c40e7cb8SJose Alberto Reguero else 607c40e7cb8SJose Alberto Reguero mv = 4; 608c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 609cd70c266SJeff Garzik 610cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 611cd70c266SJeff Garzik 612cd70c266SJeff Garzik /* clear port IRQ */ 613cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 614cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 615cd70c266SJeff Garzik if (tmp) 616cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 617cd70c266SJeff Garzik } 618cd70c266SJeff Garzik 619781d6550SAnton Vorontsov ahci_init_controller(host); 620c6fd2807SJeff Garzik } 621c6fd2807SJeff Garzik 622cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 623d4b2bab4STejun Heo unsigned long deadline) 624ad616ffbSTejun Heo { 625cc0680a5STejun Heo struct ata_port *ap = link->ap; 626039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 6279dadd45bSTejun Heo bool online; 628ad616ffbSTejun Heo int rc; 629ad616ffbSTejun Heo 630ad616ffbSTejun Heo DPRINTK("ENTER\n"); 631ad616ffbSTejun Heo 6324447d351STejun Heo ahci_stop_engine(ap); 633ad616ffbSTejun Heo 634cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6359dadd45bSTejun Heo deadline, &online, NULL); 636ad616ffbSTejun Heo 637039ece38SHans de Goede hpriv->start_engine(ap); 638ad616ffbSTejun Heo 639ad616ffbSTejun Heo DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 640ad616ffbSTejun Heo 641ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 642ad616ffbSTejun Heo * request follow-up softreset. 643ad616ffbSTejun Heo */ 6449dadd45bSTejun Heo return online ? -EAGAIN : rc; 645ad616ffbSTejun Heo } 646ad616ffbSTejun Heo 647edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 648edc93052STejun Heo unsigned long deadline) 649edc93052STejun Heo { 650edc93052STejun Heo struct ata_port *ap = link->ap; 651edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 652039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 653edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 654edc93052STejun Heo struct ata_taskfile tf; 6559dadd45bSTejun Heo bool online; 656edc93052STejun Heo int rc; 657edc93052STejun Heo 658edc93052STejun Heo ahci_stop_engine(ap); 659edc93052STejun Heo 660edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 661edc93052STejun Heo ata_tf_init(link->device, &tf); 6629bbb1b0eSSergei Shtylyov tf.command = ATA_BUSY; 663edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 664edc93052STejun Heo 665edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6669dadd45bSTejun Heo deadline, &online, NULL); 667edc93052STejun Heo 668039ece38SHans de Goede hpriv->start_engine(ap); 669edc93052STejun Heo 670edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 671edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 672edc93052STejun Heo * hardreset if no device is attached to the first downstream 673edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 674edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 675edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 676edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 677edc93052STejun Heo * 678edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 679edc93052STejun Heo * which can't process the following IDENTIFY after this will 680edc93052STejun Heo * have to be reset again. For most cases, this should 681edc93052STejun Heo * suffice while making probing snappish enough. 682edc93052STejun Heo */ 6839dadd45bSTejun Heo if (online) { 6849dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 6859dadd45bSTejun Heo ahci_check_ready); 686edc93052STejun Heo if (rc) 68778d5ae39SShane Huang ahci_kick_engine(ap); 6889dadd45bSTejun Heo } 6899dadd45bSTejun Heo return rc; 690edc93052STejun Heo } 691edc93052STejun Heo 692dbfe8ef5SDan Williams /* 693dbfe8ef5SDan Williams * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports. 694dbfe8ef5SDan Williams * 695dbfe8ef5SDan Williams * It has been observed with some SSDs that the timing of events in the 696dbfe8ef5SDan Williams * link synchronization phase can leave the port in a state that can not 697dbfe8ef5SDan Williams * be recovered by a SATA-hard-reset alone. The failing signature is 698dbfe8ef5SDan Williams * SStatus.DET stuck at 1 ("Device presence detected but Phy 699dbfe8ef5SDan Williams * communication not established"). It was found that unloading and 700dbfe8ef5SDan Williams * reloading the driver when this problem occurs allows the drive 701dbfe8ef5SDan Williams * connection to be recovered (DET advanced to 0x3). The critical 702dbfe8ef5SDan Williams * component of reloading the driver is that the port state machines are 703dbfe8ef5SDan Williams * reset by bouncing "port enable" in the AHCI PCS configuration 704dbfe8ef5SDan Williams * register. So, reproduce that effect by bouncing a port whenever we 705dbfe8ef5SDan Williams * see DET==1 after a reset. 706dbfe8ef5SDan Williams */ 707dbfe8ef5SDan Williams static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, 708dbfe8ef5SDan Williams unsigned long deadline) 709dbfe8ef5SDan Williams { 710dbfe8ef5SDan Williams const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); 711dbfe8ef5SDan Williams struct ata_port *ap = link->ap; 712dbfe8ef5SDan Williams struct ahci_port_priv *pp = ap->private_data; 713dbfe8ef5SDan Williams struct ahci_host_priv *hpriv = ap->host->private_data; 714dbfe8ef5SDan Williams u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 715dbfe8ef5SDan Williams unsigned long tmo = deadline - jiffies; 716dbfe8ef5SDan Williams struct ata_taskfile tf; 717dbfe8ef5SDan Williams bool online; 718dbfe8ef5SDan Williams int rc, i; 719dbfe8ef5SDan Williams 720dbfe8ef5SDan Williams DPRINTK("ENTER\n"); 721dbfe8ef5SDan Williams 722dbfe8ef5SDan Williams ahci_stop_engine(ap); 723dbfe8ef5SDan Williams 724dbfe8ef5SDan Williams for (i = 0; i < 2; i++) { 725dbfe8ef5SDan Williams u16 val; 726dbfe8ef5SDan Williams u32 sstatus; 727dbfe8ef5SDan Williams int port = ap->port_no; 728dbfe8ef5SDan Williams struct ata_host *host = ap->host; 729dbfe8ef5SDan Williams struct pci_dev *pdev = to_pci_dev(host->dev); 730dbfe8ef5SDan Williams 731dbfe8ef5SDan Williams /* clear D2H reception area to properly wait for D2H FIS */ 732dbfe8ef5SDan Williams ata_tf_init(link->device, &tf); 733dbfe8ef5SDan Williams tf.command = ATA_BUSY; 734dbfe8ef5SDan Williams ata_tf_to_fis(&tf, 0, 0, d2h_fis); 735dbfe8ef5SDan Williams 736dbfe8ef5SDan Williams rc = sata_link_hardreset(link, timing, deadline, &online, 737dbfe8ef5SDan Williams ahci_check_ready); 738dbfe8ef5SDan Williams 739dbfe8ef5SDan Williams if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 || 740dbfe8ef5SDan Williams (sstatus & 0xf) != 1) 741dbfe8ef5SDan Williams break; 742dbfe8ef5SDan Williams 743dbfe8ef5SDan Williams ata_link_printk(link, KERN_INFO, "avn bounce port%d\n", 744dbfe8ef5SDan Williams port); 745dbfe8ef5SDan Williams 746dbfe8ef5SDan Williams pci_read_config_word(pdev, 0x92, &val); 747dbfe8ef5SDan Williams val &= ~(1 << port); 748dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 749dbfe8ef5SDan Williams ata_msleep(ap, 1000); 750dbfe8ef5SDan Williams val |= 1 << port; 751dbfe8ef5SDan Williams pci_write_config_word(pdev, 0x92, val); 752dbfe8ef5SDan Williams deadline += tmo; 753dbfe8ef5SDan Williams } 754dbfe8ef5SDan Williams 755dbfe8ef5SDan Williams hpriv->start_engine(ap); 756dbfe8ef5SDan Williams 757dbfe8ef5SDan Williams if (online) 758dbfe8ef5SDan Williams *class = ahci_dev_classify(ap); 759dbfe8ef5SDan Williams 760dbfe8ef5SDan Williams DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 761dbfe8ef5SDan Williams return rc; 762dbfe8ef5SDan Williams } 763dbfe8ef5SDan Williams 764dbfe8ef5SDan Williams 765438ac6d5STejun Heo #ifdef CONFIG_PM 766c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) 767c6fd2807SJeff Garzik { 7680a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 7699b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 770d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 771c6fd2807SJeff Garzik u32 ctl; 772c6fd2807SJeff Garzik 7739b10ae86STejun Heo if (mesg.event & PM_EVENT_SUSPEND && 7749b10ae86STejun Heo hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 775a44fec1fSJoe Perches dev_err(&pdev->dev, 7769b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 7779b10ae86STejun Heo return -EIO; 7789b10ae86STejun Heo } 7799b10ae86STejun Heo 7803a2d5b70SRafael J. Wysocki if (mesg.event & PM_EVENT_SLEEP) { 781c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 782c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 783c6fd2807SJeff Garzik * transition of the HBA to D3 state. 784c6fd2807SJeff Garzik */ 785c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 786c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 787c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 788c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 789c6fd2807SJeff Garzik } 790c6fd2807SJeff Garzik 791c6fd2807SJeff Garzik return ata_pci_device_suspend(pdev, mesg); 792c6fd2807SJeff Garzik } 793c6fd2807SJeff Garzik 794c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev) 795c6fd2807SJeff Garzik { 7960a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 797c6fd2807SJeff Garzik int rc; 798c6fd2807SJeff Garzik 799553c4aa6STejun Heo rc = ata_pci_device_do_resume(pdev); 800553c4aa6STejun Heo if (rc) 801553c4aa6STejun Heo return rc; 802c6fd2807SJeff Garzik 803cb85696dSJames Laird /* Apple BIOS helpfully mangles the registers on resume */ 804cb85696dSJames Laird if (is_mcp89_apple(pdev)) 805cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 806cb85696dSJames Laird 807c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 8083303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 809c6fd2807SJeff Garzik if (rc) 810c6fd2807SJeff Garzik return rc; 811c6fd2807SJeff Garzik 812781d6550SAnton Vorontsov ahci_pci_init_controller(host); 813c6fd2807SJeff Garzik } 814c6fd2807SJeff Garzik 815cca3974eSJeff Garzik ata_host_resume(host); 816c6fd2807SJeff Garzik 817c6fd2807SJeff Garzik return 0; 818c6fd2807SJeff Garzik } 819438ac6d5STejun Heo #endif 820c6fd2807SJeff Garzik 8214447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) 822c6fd2807SJeff Garzik { 823c6fd2807SJeff Garzik int rc; 824c6fd2807SJeff Garzik 825318893e1SAlessandro Rubini /* 826318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 827318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 828318893e1SAlessandro Rubini */ 829318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 830318893e1SAlessandro Rubini return 0; 831318893e1SAlessandro Rubini 832c6fd2807SJeff Garzik if (using_dac && 833c54c719bSQuentin Lambert !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { 834c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); 835c6fd2807SJeff Garzik if (rc) { 836c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 837c6fd2807SJeff Garzik if (rc) { 838a44fec1fSJoe Perches dev_err(&pdev->dev, 839c6fd2807SJeff Garzik "64-bit DMA enable failed\n"); 840c6fd2807SJeff Garzik return rc; 841c6fd2807SJeff Garzik } 842c6fd2807SJeff Garzik } 843c6fd2807SJeff Garzik } else { 844c54c719bSQuentin Lambert rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 845c6fd2807SJeff Garzik if (rc) { 846a44fec1fSJoe Perches dev_err(&pdev->dev, "32-bit DMA enable failed\n"); 847c6fd2807SJeff Garzik return rc; 848c6fd2807SJeff Garzik } 849c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 850c6fd2807SJeff Garzik if (rc) { 851a44fec1fSJoe Perches dev_err(&pdev->dev, 852c6fd2807SJeff Garzik "32-bit consistent DMA enable failed\n"); 853c6fd2807SJeff Garzik return rc; 854c6fd2807SJeff Garzik } 855c6fd2807SJeff Garzik } 856c6fd2807SJeff Garzik return 0; 857c6fd2807SJeff Garzik } 858c6fd2807SJeff Garzik 859439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 860439fcaecSAnton Vorontsov { 861439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 862439fcaecSAnton Vorontsov u16 cc; 863439fcaecSAnton Vorontsov const char *scc_s; 864439fcaecSAnton Vorontsov 865439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 866439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 867439fcaecSAnton Vorontsov scc_s = "IDE"; 868439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 869439fcaecSAnton Vorontsov scc_s = "SATA"; 870439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 871439fcaecSAnton Vorontsov scc_s = "RAID"; 872439fcaecSAnton Vorontsov else 873439fcaecSAnton Vorontsov scc_s = "unknown"; 874439fcaecSAnton Vorontsov 875439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 876439fcaecSAnton Vorontsov } 877439fcaecSAnton Vorontsov 878edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 879edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 880edc93052STejun Heo * support PMP and the 4726 either directly exports the device 881edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 882edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 883edc93052STejun Heo * other configuration). 884edc93052STejun Heo * 885edc93052STejun Heo * When there's no device attached to the first downstream port of the 886edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 887edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 888edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 889edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 890edc93052STejun Heo * 891edc93052STejun Heo * The following function works around the problem by always using 892edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 893edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 894edc93052STejun Heo * assumed without follow-up softreset. 895edc93052STejun Heo */ 896edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 897edc93052STejun Heo { 8981bd06867SMathias Krause static const struct dmi_system_id sysids[] = { 899edc93052STejun Heo { 900edc93052STejun Heo .ident = "P5W DH Deluxe", 901edc93052STejun Heo .matches = { 902edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 903edc93052STejun Heo "ASUSTEK COMPUTER INC"), 904edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 905edc93052STejun Heo }, 906edc93052STejun Heo }, 907edc93052STejun Heo { } 908edc93052STejun Heo }; 909edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 910edc93052STejun Heo 911edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 912edc93052STejun Heo dmi_check_system(sysids)) { 913edc93052STejun Heo struct ata_port *ap = host->ports[1]; 914edc93052STejun Heo 915a44fec1fSJoe Perches dev_info(&pdev->dev, 916a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 917edc93052STejun Heo 918edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 919edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 920edc93052STejun Heo } 921edc93052STejun Heo } 922edc93052STejun Heo 923cb85696dSJames Laird /* 924cb85696dSJames Laird * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 925cb85696dSJames Laird * booting in BIOS compatibility mode. We restore the registers but not ID. 926cb85696dSJames Laird */ 927cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 928cb85696dSJames Laird { 929cb85696dSJames Laird u32 val; 930cb85696dSJames Laird 931cb85696dSJames Laird printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 932cb85696dSJames Laird 933cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 934cb85696dSJames Laird val |= 1 << 0x1b; 935cb85696dSJames Laird /* the following changes the device ID, but appears not to affect function */ 936cb85696dSJames Laird /* val = (val & ~0xf0000000) | 0x80000000; */ 937cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 938cb85696dSJames Laird 939cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 940cb85696dSJames Laird val |= 1 << 0xc; 941cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 942cb85696dSJames Laird 943cb85696dSJames Laird pci_read_config_dword(pdev, 0x4a4, &val); 944cb85696dSJames Laird val &= 0xff; 945cb85696dSJames Laird val |= 0x01060100; 946cb85696dSJames Laird pci_write_config_dword(pdev, 0x4a4, val); 947cb85696dSJames Laird 948cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 949cb85696dSJames Laird val &= ~(1 << 0xc); 950cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 951cb85696dSJames Laird 952cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 953cb85696dSJames Laird val &= ~(1 << 0x1b); 954cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 955cb85696dSJames Laird } 956cb85696dSJames Laird 957cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev) 958cb85696dSJames Laird { 959cb85696dSJames Laird return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 960cb85696dSJames Laird pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 961cb85696dSJames Laird pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 962cb85696dSJames Laird pdev->subsystem_device == 0xcb89; 963cb85696dSJames Laird } 964cb85696dSJames Laird 9652fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 9662fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 96758a09b38SShane Huang { 96858a09b38SShane Huang static const struct dmi_system_id sysids[] = { 96903d783bfSTejun Heo /* 97003d783bfSTejun Heo * The oldest version known to be broken is 0901 and 97103d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 9722fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 9732fcad9d2STejun Heo * 97403d783bfSTejun Heo * Please read bko#9412 for more info. 97503d783bfSTejun Heo */ 97658a09b38SShane Huang { 97758a09b38SShane Huang .ident = "ASUS M2A-VM", 97858a09b38SShane Huang .matches = { 97958a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 98058a09b38SShane Huang "ASUSTeK Computer INC."), 98158a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 98258a09b38SShane Huang }, 98303d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 98458a09b38SShane Huang }, 985e65cc194SMark Nelson /* 986e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 987e65cc194SMark Nelson * support 64bit DMA. 988e65cc194SMark Nelson * 989e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 990e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 991e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 992e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 993e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 994e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 995e65cc194SMark Nelson * 996e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 997e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 998e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 999e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 1000e65cc194SMark Nelson */ 1001e65cc194SMark Nelson { 1002e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 1003e65cc194SMark Nelson .matches = { 1004e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1005e65cc194SMark Nelson "MICRO-STAR INTER"), 1006e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 1007e65cc194SMark Nelson }, 1008e65cc194SMark Nelson }, 10093c4aa91fSMark Nelson /* 1010ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 1011ff0173c1SMark Nelson * 64bit DMA. 1012ff0173c1SMark Nelson * 1013ff0173c1SMark Nelson * This board also had the typo mentioned above in the 1014ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 1015ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 1016ff0173c1SMark Nelson */ 1017ff0173c1SMark Nelson { 1018ff0173c1SMark Nelson .ident = "MSI K9AGM2", 1019ff0173c1SMark Nelson .matches = { 1020ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 1021ff0173c1SMark Nelson "MICRO-STAR INTER"), 1022ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 1023ff0173c1SMark Nelson }, 1024ff0173c1SMark Nelson }, 1025ff0173c1SMark Nelson /* 10263c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 10273c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 10283c4aa91fSMark Nelson */ 10293c4aa91fSMark Nelson { 10303c4aa91fSMark Nelson .ident = "ASUS M3A", 10313c4aa91fSMark Nelson .matches = { 10323c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 10333c4aa91fSMark Nelson "ASUSTeK Computer INC."), 10343c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 10353c4aa91fSMark Nelson }, 10363c4aa91fSMark Nelson }, 103758a09b38SShane Huang { } 103858a09b38SShane Huang }; 103903d783bfSTejun Heo const struct dmi_system_id *match; 10402fcad9d2STejun Heo int year, month, date; 10412fcad9d2STejun Heo char buf[9]; 104258a09b38SShane Huang 104303d783bfSTejun Heo match = dmi_first_match(sysids); 104458a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 104503d783bfSTejun Heo !match) 104658a09b38SShane Huang return false; 104758a09b38SShane Huang 1048e65cc194SMark Nelson if (!match->driver_data) 1049e65cc194SMark Nelson goto enable_64bit; 1050e65cc194SMark Nelson 105103d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 105203d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 105303d783bfSTejun Heo 1054e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 1055e65cc194SMark Nelson goto enable_64bit; 1056e65cc194SMark Nelson else { 1057a44fec1fSJoe Perches dev_warn(&pdev->dev, 1058a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 1059a44fec1fSJoe Perches match->ident); 10602fcad9d2STejun Heo return false; 10612fcad9d2STejun Heo } 1062e65cc194SMark Nelson 1063e65cc194SMark Nelson enable_64bit: 1064a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 1065e65cc194SMark Nelson return true; 106658a09b38SShane Huang } 106758a09b38SShane Huang 10681fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 10691fd68434SRafael J. Wysocki { 10701fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 10711fd68434SRafael J. Wysocki { 10721fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 10731fd68434SRafael J. Wysocki .matches = { 10741fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 10751fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 10761fd68434SRafael J. Wysocki }, 10771fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 10781fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 10791fd68434SRafael J. Wysocki }, 1080d2f9c061SMaciej Rutecki { 1081d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 1082d2f9c061SMaciej Rutecki .matches = { 1083d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 1084d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 1085d2f9c061SMaciej Rutecki }, 1086d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 1087d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 1088d2f9c061SMaciej Rutecki }, 10891fd68434SRafael J. Wysocki 10901fd68434SRafael J. Wysocki { } /* terminate list */ 10911fd68434SRafael J. Wysocki }; 10921fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 10931fd68434SRafael J. Wysocki 10941fd68434SRafael J. Wysocki if (dmi) { 10951fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 10961fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 10971fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 10981fd68434SRafael J. Wysocki } 10991fd68434SRafael J. Wysocki 11001fd68434SRafael J. Wysocki return false; 11011fd68434SRafael J. Wysocki } 11021fd68434SRafael J. Wysocki 11039b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 11049b10ae86STejun Heo { 11059b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 11069b10ae86STejun Heo /* 11079b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 11089b10ae86STejun Heo * to the harddisk doesn't become online after 11099b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 11109deb3431STejun Heo * 11119deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 11129deb3431STejun Heo * 11139deb3431STejun Heo * Use dates instead of versions to match as HP is 11149deb3431STejun Heo * apparently recycling both product and version 11159deb3431STejun Heo * strings. 11169deb3431STejun Heo * 11179deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 11189b10ae86STejun Heo */ 11199b10ae86STejun Heo { 11209b10ae86STejun Heo .ident = "dv4", 11219b10ae86STejun Heo .matches = { 11229b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11239b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11249b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 11259b10ae86STejun Heo }, 11269deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 11279b10ae86STejun Heo }, 11289b10ae86STejun Heo { 11299b10ae86STejun Heo .ident = "dv5", 11309b10ae86STejun Heo .matches = { 11319b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11329b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11339b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 11349b10ae86STejun Heo }, 11359deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 11369b10ae86STejun Heo }, 11379b10ae86STejun Heo { 11389b10ae86STejun Heo .ident = "dv6", 11399b10ae86STejun Heo .matches = { 11409b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11419b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11429b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 11439b10ae86STejun Heo }, 11449deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 11459b10ae86STejun Heo }, 11469b10ae86STejun Heo { 11479b10ae86STejun Heo .ident = "HDX18", 11489b10ae86STejun Heo .matches = { 11499b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 11509b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 11519b10ae86STejun Heo "HP HDX18 Notebook PC"), 11529b10ae86STejun Heo }, 11539deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 11549b10ae86STejun Heo }, 1155cedc9bf9STejun Heo /* 1156cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 1157cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 115825985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 1159cedc9bf9STejun Heo * that we don't have much idea about. For now, 1160cedc9bf9STejun Heo * blacklist anything older than V3.04. 11619deb3431STejun Heo * 11629deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 1163cedc9bf9STejun Heo */ 1164cedc9bf9STejun Heo { 1165cedc9bf9STejun Heo .ident = "G725", 1166cedc9bf9STejun Heo .matches = { 1167cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 1168cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 1169cedc9bf9STejun Heo }, 11709deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 1171cedc9bf9STejun Heo }, 11729b10ae86STejun Heo { } /* terminate list */ 11739b10ae86STejun Heo }; 11749b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 11759deb3431STejun Heo int year, month, date; 11769deb3431STejun Heo char buf[9]; 11779b10ae86STejun Heo 11789b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 11799b10ae86STejun Heo return false; 11809b10ae86STejun Heo 11819deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 11829deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 11839b10ae86STejun Heo 11849deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 11859b10ae86STejun Heo } 11869b10ae86STejun Heo 11875594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 11885594639aSTejun Heo { 11895594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 11905594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 11915594639aSTejun Heo static const struct dmi_system_id sysids[] = { 11925594639aSTejun Heo /* 11935594639aSTejun Heo * There are several gigabyte boards which use 11945594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 11955594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 11965594639aSTejun Heo * online but fail to answer properly to SRST or 11975594639aSTejun Heo * IDENTIFY when no device is attached downstream 11985594639aSTejun Heo * causing libata to retry quite a few times leading 11995594639aSTejun Heo * to excessive detection delay. 12005594639aSTejun Heo * 12015594639aSTejun Heo * As these firmwares respond to the second reset try 12025594639aSTejun Heo * with invalid device signature, considering unknown 12035594639aSTejun Heo * sig as offline works around the problem acceptably. 12045594639aSTejun Heo */ 12055594639aSTejun Heo { 12065594639aSTejun Heo .ident = "EP45-DQ6", 12075594639aSTejun Heo .matches = { 12085594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 12095594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 12105594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 12115594639aSTejun Heo }, 12125594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 12135594639aSTejun Heo }, 12145594639aSTejun Heo { 12155594639aSTejun Heo .ident = "EP45-DS5", 12165594639aSTejun Heo .matches = { 12175594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 12185594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 12195594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 12205594639aSTejun Heo }, 12215594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 12225594639aSTejun Heo }, 12235594639aSTejun Heo { } /* terminate list */ 12245594639aSTejun Heo }; 12255594639aSTejun Heo #undef ENCODE_BUSDEVFN 12265594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 12275594639aSTejun Heo unsigned int val; 12285594639aSTejun Heo 12295594639aSTejun Heo if (!dmi) 12305594639aSTejun Heo return false; 12315594639aSTejun Heo 12325594639aSTejun Heo val = (unsigned long)dmi->driver_data; 12335594639aSTejun Heo 12345594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 12355594639aSTejun Heo } 12365594639aSTejun Heo 12370cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev) 12380cf4a7d6SJacob Pan { 12390cf4a7d6SJacob Pan /* device with broken DEVSLP but still showing SDS capability */ 12400cf4a7d6SJacob Pan static const struct pci_device_id ids[] = { 12410cf4a7d6SJacob Pan { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ 12420cf4a7d6SJacob Pan {} 12430cf4a7d6SJacob Pan }; 12440cf4a7d6SJacob Pan 12450cf4a7d6SJacob Pan return pci_match_id(ids, pdev); 12460cf4a7d6SJacob Pan } 12470cf4a7d6SJacob Pan 12488e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1249f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1250f80ae7e4STejun Heo { 1251f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1252f80ae7e4STejun Heo /* 1253f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1254f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1255f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1256f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1257f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1258f80ae7e4STejun Heo * failures. Filter it out. 1259f80ae7e4STejun Heo */ 1260f80ae7e4STejun Heo { 1261f80ae7e4STejun Heo .ident = "Aspire 3810T", 1262f80ae7e4STejun Heo .matches = { 1263f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1264f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1265f80ae7e4STejun Heo }, 1266f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1267f80ae7e4STejun Heo }, 1268f80ae7e4STejun Heo { } 1269f80ae7e4STejun Heo }; 1270f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1271f80ae7e4STejun Heo unsigned int filter; 1272f80ae7e4STejun Heo int i; 1273f80ae7e4STejun Heo 1274f80ae7e4STejun Heo if (!dmi) 1275f80ae7e4STejun Heo return; 1276f80ae7e4STejun Heo 1277f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1278a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1279f80ae7e4STejun Heo filter, dmi->ident); 1280f80ae7e4STejun Heo 1281f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1282f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1283f80ae7e4STejun Heo struct ata_link *link; 1284f80ae7e4STejun Heo struct ata_device *dev; 1285f80ae7e4STejun Heo 1286f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1287f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1288f80ae7e4STejun Heo dev->gtf_filter |= filter; 1289f80ae7e4STejun Heo } 1290f80ae7e4STejun Heo } 12918e513217SMarkus Trippelsdorf #else 12928e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 12938e513217SMarkus Trippelsdorf {} 12948e513217SMarkus Trippelsdorf #endif 1295f80ae7e4STejun Heo 1296ee2aad42SRobert Richter /* 1297ee2aad42SRobert Richter * ahci_init_msix() only implements single MSI-X support, not multiple 1298ee2aad42SRobert Richter * MSI-X per-port interrupts. This is needed for host controllers that only 1299ee2aad42SRobert Richter * have MSI-X support implemented, but no MSI or intx. 1300ee2aad42SRobert Richter */ 1301ee2aad42SRobert Richter static int ahci_init_msix(struct pci_dev *pdev, unsigned int n_ports, 1302ee2aad42SRobert Richter struct ahci_host_priv *hpriv) 1303ee2aad42SRobert Richter { 1304ee2aad42SRobert Richter int rc, nvec; 1305ee2aad42SRobert Richter struct msix_entry entry = {}; 1306ee2aad42SRobert Richter 1307ee2aad42SRobert Richter /* Do not init MSI-X if MSI is disabled for the device */ 1308ee2aad42SRobert Richter if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1309ee2aad42SRobert Richter return -ENODEV; 1310ee2aad42SRobert Richter 1311ee2aad42SRobert Richter nvec = pci_msix_vec_count(pdev); 1312ee2aad42SRobert Richter if (nvec < 0) 1313ee2aad42SRobert Richter return nvec; 1314ee2aad42SRobert Richter 1315ee2aad42SRobert Richter if (!nvec) { 1316ee2aad42SRobert Richter rc = -ENODEV; 1317ee2aad42SRobert Richter goto fail; 1318ee2aad42SRobert Richter } 1319ee2aad42SRobert Richter 1320ee2aad42SRobert Richter /* 1321ee2aad42SRobert Richter * There can be more than one vector (e.g. for error detection or 1322ee2aad42SRobert Richter * hdd hotplug). Only the first vector (entry.entry = 0) is used. 1323ee2aad42SRobert Richter */ 1324ee2aad42SRobert Richter rc = pci_enable_msix_exact(pdev, &entry, 1); 1325ee2aad42SRobert Richter if (rc < 0) 1326ee2aad42SRobert Richter goto fail; 1327ee2aad42SRobert Richter 132834c56932SRobert Richter hpriv->irq = entry.vector; 1329ee2aad42SRobert Richter 1330ee2aad42SRobert Richter return 1; 1331ee2aad42SRobert Richter fail: 1332ee2aad42SRobert Richter dev_err(&pdev->dev, 1333ee2aad42SRobert Richter "failed to enable MSI-X with error %d, # of vectors: %d\n", 1334ee2aad42SRobert Richter rc, nvec); 1335ee2aad42SRobert Richter 1336ee2aad42SRobert Richter return rc; 1337ee2aad42SRobert Richter } 1338ee2aad42SRobert Richter 1339a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, 13407b92b4f6SAlexander Gordeev struct ahci_host_priv *hpriv) 13415ca72c4fSAlexander Gordeev { 1342ccf8f53cSAlexander Gordeev int rc, nvec; 13435ca72c4fSAlexander Gordeev 13447b92b4f6SAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1345a1c82311SRobert Richter return -ENODEV; 13467b92b4f6SAlexander Gordeev 1347fc061d96SAlexander Gordeev nvec = pci_msi_vec_count(pdev); 1348fc061d96SAlexander Gordeev if (nvec < 0) 1349a1c82311SRobert Richter return nvec; 13507b92b4f6SAlexander Gordeev 13515ca72c4fSAlexander Gordeev /* 13527b92b4f6SAlexander Gordeev * If number of MSIs is less than number of ports then Sharing Last 13537b92b4f6SAlexander Gordeev * Message mode could be enforced. In this case assume that advantage 13547b92b4f6SAlexander Gordeev * of multipe MSIs is negated and use single MSI mode instead. 13555ca72c4fSAlexander Gordeev */ 1356fc061d96SAlexander Gordeev if (nvec < n_ports) 13577b92b4f6SAlexander Gordeev goto single_msi; 13585ca72c4fSAlexander Gordeev 1359ccf8f53cSAlexander Gordeev rc = pci_enable_msi_exact(pdev, nvec); 1360ccf8f53cSAlexander Gordeev if (rc == -ENOSPC) 1361fc40363bSAlexander Gordeev goto single_msi; 1362a1c82311SRobert Richter if (rc < 0) 1363a1c82311SRobert Richter return rc; 1364ab0f9e78SAlexander Gordeev 1365ab0f9e78SAlexander Gordeev /* fallback to single MSI mode if the controller enforced MRSM mode */ 1366ab0f9e78SAlexander Gordeev if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) { 1367ab0f9e78SAlexander Gordeev pci_disable_msi(pdev); 1368ab0f9e78SAlexander Gordeev printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n"); 1369ab0f9e78SAlexander Gordeev goto single_msi; 1370ab0f9e78SAlexander Gordeev } 13717b92b4f6SAlexander Gordeev 1372c3ebd6a9SAlexander Gordeev if (nvec > 1) 1373c3ebd6a9SAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 1374c3ebd6a9SAlexander Gordeev 137521bfd1aaSRobert Richter goto out; 13767b92b4f6SAlexander Gordeev 13777b92b4f6SAlexander Gordeev single_msi: 137821bfd1aaSRobert Richter nvec = 1; 13797b92b4f6SAlexander Gordeev 1380a1c82311SRobert Richter rc = pci_enable_msi(pdev); 1381a1c82311SRobert Richter if (rc < 0) 1382a1c82311SRobert Richter return rc; 138321bfd1aaSRobert Richter out: 138421bfd1aaSRobert Richter hpriv->irq = pdev->irq; 13857b92b4f6SAlexander Gordeev 138621bfd1aaSRobert Richter return nvec; 1387a1c82311SRobert Richter } 1388a1c82311SRobert Richter 1389a1c82311SRobert Richter static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, 1390a1c82311SRobert Richter struct ahci_host_priv *hpriv) 1391a1c82311SRobert Richter { 1392a1c82311SRobert Richter int nvec; 1393a1c82311SRobert Richter 1394a1c82311SRobert Richter nvec = ahci_init_msi(pdev, n_ports, hpriv); 1395a1c82311SRobert Richter if (nvec >= 0) 1396a1c82311SRobert Richter return nvec; 1397a1c82311SRobert Richter 1398ee2aad42SRobert Richter /* 1399ee2aad42SRobert Richter * Currently, MSI-X support only implements single IRQ mode and 1400ee2aad42SRobert Richter * exists for controllers which can't do other types of IRQ. Only 1401ee2aad42SRobert Richter * set it up if MSI fails. 1402ee2aad42SRobert Richter */ 1403ee2aad42SRobert Richter nvec = ahci_init_msix(pdev, n_ports, hpriv); 1404ee2aad42SRobert Richter if (nvec >= 0) 1405ee2aad42SRobert Richter return nvec; 1406ee2aad42SRobert Richter 1407a1c82311SRobert Richter /* lagacy intx interrupts */ 14085ca72c4fSAlexander Gordeev pci_intx(pdev, 1); 140921bfd1aaSRobert Richter hpriv->irq = pdev->irq; 1410a1c82311SRobert Richter 14115ca72c4fSAlexander Gordeev return 0; 14125ca72c4fSAlexander Gordeev } 14135ca72c4fSAlexander Gordeev 1414c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1415c6fd2807SJeff Garzik { 1416e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1417e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 14184447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 141924dc5f33STejun Heo struct device *dev = &pdev->dev; 1420c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 14214447d351STejun Heo struct ata_host *host; 1422c3ebd6a9SAlexander Gordeev int n_ports, i, rc; 1423318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1424c6fd2807SJeff Garzik 1425c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1426c6fd2807SJeff Garzik 1427b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1428c6fd2807SJeff Garzik 142906296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1430c6fd2807SJeff Garzik 14315b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 14325b66c829SAlan Cox can drive them all so if both drivers are selected make sure 14335b66c829SAlan Cox AHCI stays out of the way */ 14345b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 14355b66c829SAlan Cox return -ENODEV; 14365b66c829SAlan Cox 1437cb85696dSJames Laird /* Apple BIOS on MCP89 prevents us using AHCI */ 1438cb85696dSJames Laird if (is_mcp89_apple(pdev)) 1439cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 1440c6353b45STejun Heo 14417a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 14427a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 14437a02267eSMark Nelson * that for SAS drives they're out of luck. 14447a02267eSMark Nelson */ 14457a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1446a44fec1fSJoe Perches dev_info(&pdev->dev, 1447a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 14487a02267eSMark Nelson 1449b7ae128dSRobert Richter /* Some devices use non-standard BARs */ 1450318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1451318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 14527f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 14537f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1454b7ae128dSRobert Richter else if (pdev->vendor == 0x177d && pdev->device == 0xa01c) 1455b7ae128dSRobert Richter ahci_pci_bar = AHCI_PCI_BAR_CAVIUM; 1456318893e1SAlessandro Rubini 14574447d351STejun Heo /* acquire resources */ 145824dc5f33STejun Heo rc = pcim_enable_device(pdev); 1459c6fd2807SJeff Garzik if (rc) 1460c6fd2807SJeff Garzik return rc; 1461c6fd2807SJeff Garzik 1462c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1463c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1464c4f7792cSTejun Heo u8 map; 1465c4f7792cSTejun Heo 1466c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1467c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1468c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1469c4f7792cSTejun Heo */ 1470c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1471c4f7792cSTejun Heo if (map & 0x3) { 1472a44fec1fSJoe Perches dev_info(&pdev->dev, 1473a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1474c4f7792cSTejun Heo return -ENODEV; 1475c4f7792cSTejun Heo } 1476c4f7792cSTejun Heo } 1477c4f7792cSTejun Heo 14786fec8871SPaul Bolle /* AHCI controllers often implement SFF compatible interface. 14796fec8871SPaul Bolle * Grab all PCI BARs just in case. 14806fec8871SPaul Bolle */ 14816fec8871SPaul Bolle rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 14826fec8871SPaul Bolle if (rc == -EBUSY) 14836fec8871SPaul Bolle pcim_pin_device(pdev); 14846fec8871SPaul Bolle if (rc) 14856fec8871SPaul Bolle return rc; 14866fec8871SPaul Bolle 148724dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 148824dc5f33STejun Heo if (!hpriv) 148924dc5f33STejun Heo return -ENOMEM; 1490417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1491417a1a6dSTejun Heo 1492e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1493e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1494e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1495e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1496e297d99eSTejun Heo 1497e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1498e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1499e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1500e427fe04SShane Huang 15012fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 15022fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 15032fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 150458a09b38SShane Huang 1505318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1506d8993349SAnton Vorontsov 15070cf4a7d6SJacob Pan /* must set flag prior to save config in order to take effect */ 15080cf4a7d6SJacob Pan if (ahci_broken_devslp(pdev)) 15090cf4a7d6SJacob Pan hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; 15100cf4a7d6SJacob Pan 15114447d351STejun Heo /* save initial config */ 1512394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1513c6fd2807SJeff Garzik 15144447d351STejun Heo /* prepare host */ 1515453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1516453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 151783f2b963STejun Heo /* 151883f2b963STejun Heo * Auto-activate optimization is supposed to be 151983f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 152083f2b963STejun Heo * capability, but it seems to be broken on some 152183f2b963STejun Heo * chipsets including NVIDIAs. 152283f2b963STejun Heo */ 152383f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1524453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 152540fb59e7SMarc Carino 152640fb59e7SMarc Carino /* 152740fb59e7SMarc Carino * All AHCI controllers should be forward-compatible 152840fb59e7SMarc Carino * with the new auxiliary field. This code should be 152940fb59e7SMarc Carino * conditionalized if any buggy AHCI controllers are 153040fb59e7SMarc Carino * encountered. 153140fb59e7SMarc Carino */ 153240fb59e7SMarc Carino pi.flags |= ATA_FLAG_FPDMA_AUX; 1533453d3131SRobert Hancock } 15344447d351STejun Heo 15357d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 15367d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 15377d50b60bSTejun Heo 15380cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 153918f7ba4cSKristen Carlson Accardi 15401fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 15411fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 15421fd68434SRafael J. Wysocki dev_info(&pdev->dev, 15431fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 15441fd68434SRafael J. Wysocki } 15451fd68434SRafael J. Wysocki 15469b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 15479b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1548a44fec1fSJoe Perches dev_warn(&pdev->dev, 15499b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 15509b10ae86STejun Heo } 15519b10ae86STejun Heo 15525594639aSTejun Heo if (ahci_broken_online(pdev)) { 15535594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 15545594639aSTejun Heo dev_info(&pdev->dev, 15555594639aSTejun Heo "online status unreliable, applying workaround\n"); 15565594639aSTejun Heo } 15575594639aSTejun Heo 1558837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1559837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1560837f5f8fSTejun Heo * determining the maximum port number requires looking at 1561837f5f8fSTejun Heo * both CAP.NP and port_map. 1562837f5f8fSTejun Heo */ 1563837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1564837f5f8fSTejun Heo 1565837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 15664447d351STejun Heo if (!host) 15674447d351STejun Heo return -ENOMEM; 15684447d351STejun Heo host->private_data = hpriv; 15694447d351STejun Heo 157021bfd1aaSRobert Richter ahci_init_interrupts(pdev, n_ports, hpriv); 157121bfd1aaSRobert Richter 1572f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1573886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1574f3d7f23fSArjan van de Ven else 1575d2782d96SJingoo Han dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); 1576886ad09fSArjan van de Ven 157718f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 157818f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 157918f7ba4cSKristen Carlson Accardi 15804447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 15814447d351STejun Heo struct ata_port *ap = host->ports[i]; 15824447d351STejun Heo 1583318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1584318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1585cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1586cbcdd875STejun Heo 158718f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 158818f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1589008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 159018f7ba4cSKristen Carlson Accardi 159118f7ba4cSKristen Carlson Accardi 1592dab632e8SJeff Garzik /* disabled/not-implemented port */ 1593350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1594dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 15954447d351STejun Heo } 1596c6fd2807SJeff Garzik 1597edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1598edc93052STejun Heo ahci_p5wdh_workaround(host); 1599edc93052STejun Heo 1600f80ae7e4STejun Heo /* apply gtf filter quirk */ 1601f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1602f80ae7e4STejun Heo 1603c6fd2807SJeff Garzik /* initialize adapter */ 16044447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1605c6fd2807SJeff Garzik if (rc) 160624dc5f33STejun Heo return rc; 1607c6fd2807SJeff Garzik 16083303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 16094447d351STejun Heo if (rc) 16104447d351STejun Heo return rc; 1611c6fd2807SJeff Garzik 1612781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1613439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1614c6fd2807SJeff Garzik 16154447d351STejun Heo pci_set_master(pdev); 16165ca72c4fSAlexander Gordeev 161721bfd1aaSRobert Richter return ahci_host_activate(host, &ahci_sht); 1618c6fd2807SJeff Garzik } 1619c6fd2807SJeff Garzik 16202fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1621c6fd2807SJeff Garzik 1622c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1623c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1624c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1625c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1626c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1627