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, 56*b7ae128dSRobert 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 */ 71441577efSTejun Heo board_ahci_mcp65, 7283f2b963STejun Heo board_ahci_mcp77, 7383f2b963STejun Heo board_ahci_mcp89, 74441577efSTejun Heo board_ahci_mv, 75441577efSTejun Heo board_ahci_sb600, 76441577efSTejun Heo board_ahci_sb700, /* for SB700 and SB800 */ 77441577efSTejun Heo board_ahci_vt8251, 78441577efSTejun Heo 79441577efSTejun Heo /* aliases */ 80441577efSTejun Heo board_ahci_mcp_linux = board_ahci_mcp65, 81441577efSTejun Heo board_ahci_mcp67 = board_ahci_mcp65, 82441577efSTejun Heo board_ahci_mcp73 = board_ahci_mcp65, 8383f2b963STejun Heo board_ahci_mcp79 = board_ahci_mcp77, 84c6fd2807SJeff Garzik }; 85c6fd2807SJeff Garzik 86c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 87a1efdabaSTejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 88a1efdabaSTejun Heo unsigned long deadline); 89cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev); 90cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev); 91a1efdabaSTejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 92a1efdabaSTejun Heo unsigned long deadline); 93438ac6d5STejun Heo #ifdef CONFIG_PM 94c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); 95c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev); 96438ac6d5STejun Heo #endif 97c6fd2807SJeff Garzik 98fad16e7aSTejun Heo static struct scsi_host_template ahci_sht = { 99fad16e7aSTejun Heo AHCI_SHT("ahci"), 100fad16e7aSTejun Heo }; 101fad16e7aSTejun Heo 102029cfd6bSTejun Heo static struct ata_port_operations ahci_vt8251_ops = { 103029cfd6bSTejun Heo .inherits = &ahci_ops, 104a1efdabaSTejun Heo .hardreset = ahci_vt8251_hardreset, 105ad616ffbSTejun Heo }; 106ad616ffbSTejun Heo 107029cfd6bSTejun Heo static struct ata_port_operations ahci_p5wdh_ops = { 108029cfd6bSTejun Heo .inherits = &ahci_ops, 109a1efdabaSTejun Heo .hardreset = ahci_p5wdh_hardreset, 110edc93052STejun Heo }; 111edc93052STejun Heo 112c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 113441577efSTejun Heo /* by features */ 114facb8fa6SJeffrin Jose [board_ahci] = { 1151188c0d8STejun Heo .flags = AHCI_FLAG_COMMON, 11614bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 117469248abSJeff Garzik .udma_mask = ATA_UDMA6, 118c6fd2807SJeff Garzik .port_ops = &ahci_ops, 119c6fd2807SJeff Garzik }, 120facb8fa6SJeffrin Jose [board_ahci_ign_iferr] = { 121417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), 122417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 12314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 124469248abSJeff Garzik .udma_mask = ATA_UDMA6, 12541669553STejun Heo .port_ops = &ahci_ops, 12641669553STejun Heo }, 12766a7cbc3STejun Heo [board_ahci_nomsi] = { 12866a7cbc3STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), 12966a7cbc3STejun Heo .flags = AHCI_FLAG_COMMON, 13066a7cbc3STejun Heo .pio_mask = ATA_PIO4, 13166a7cbc3STejun Heo .udma_mask = ATA_UDMA6, 13266a7cbc3STejun Heo .port_ops = &ahci_ops, 13366a7cbc3STejun Heo }, 13467809f85SLevente Kurusa [board_ahci_noncq] = { 13567809f85SLevente Kurusa AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), 13667809f85SLevente Kurusa .flags = AHCI_FLAG_COMMON, 13767809f85SLevente Kurusa .pio_mask = ATA_PIO4, 13867809f85SLevente Kurusa .udma_mask = ATA_UDMA6, 13967809f85SLevente Kurusa .port_ops = &ahci_ops, 14067809f85SLevente Kurusa }, 141facb8fa6SJeffrin Jose [board_ahci_nosntf] = { 142441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), 143441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 144441577efSTejun Heo .pio_mask = ATA_PIO4, 145441577efSTejun Heo .udma_mask = ATA_UDMA6, 146441577efSTejun Heo .port_ops = &ahci_ops, 147441577efSTejun Heo }, 148facb8fa6SJeffrin Jose [board_ahci_yes_fbs] = { 1495f173107STejun Heo AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), 1505f173107STejun Heo .flags = AHCI_FLAG_COMMON, 1515f173107STejun Heo .pio_mask = ATA_PIO4, 1525f173107STejun Heo .udma_mask = ATA_UDMA6, 1535f173107STejun Heo .port_ops = &ahci_ops, 1545f173107STejun Heo }, 155441577efSTejun Heo /* by chipsets */ 156facb8fa6SJeffrin Jose [board_ahci_mcp65] = { 15783f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP | 15883f2b963STejun Heo AHCI_HFLAG_YES_NCQ), 159ae01b249STejun Heo .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM, 16083f2b963STejun Heo .pio_mask = ATA_PIO4, 16183f2b963STejun Heo .udma_mask = ATA_UDMA6, 16283f2b963STejun Heo .port_ops = &ahci_ops, 16383f2b963STejun Heo }, 164facb8fa6SJeffrin Jose [board_ahci_mcp77] = { 16583f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP), 16683f2b963STejun Heo .flags = AHCI_FLAG_COMMON, 16783f2b963STejun Heo .pio_mask = ATA_PIO4, 16883f2b963STejun Heo .udma_mask = ATA_UDMA6, 16983f2b963STejun Heo .port_ops = &ahci_ops, 17083f2b963STejun Heo }, 171facb8fa6SJeffrin Jose [board_ahci_mcp89] = { 17283f2b963STejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA), 173441577efSTejun Heo .flags = AHCI_FLAG_COMMON, 174441577efSTejun Heo .pio_mask = ATA_PIO4, 175441577efSTejun Heo .udma_mask = ATA_UDMA6, 176441577efSTejun Heo .port_ops = &ahci_ops, 177441577efSTejun Heo }, 178facb8fa6SJeffrin Jose [board_ahci_mv] = { 179441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | 180441577efSTejun Heo AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), 1819cbe056fSSergei Shtylyov .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, 182441577efSTejun Heo .pio_mask = ATA_PIO4, 183441577efSTejun Heo .udma_mask = ATA_UDMA6, 184441577efSTejun Heo .port_ops = &ahci_ops, 185441577efSTejun Heo }, 186facb8fa6SJeffrin Jose [board_ahci_sb600] = { 187417a1a6dSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | 1882fcad9d2STejun Heo AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | 1892fcad9d2STejun Heo AHCI_HFLAG_32BIT_ONLY), 190417a1a6dSTejun Heo .flags = AHCI_FLAG_COMMON, 19114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 192469248abSJeff Garzik .udma_mask = ATA_UDMA6, 193345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 19455a61604SConke Hu }, 195facb8fa6SJeffrin Jose [board_ahci_sb700] = { /* for SB700 and SB800 */ 196bd17243aSShane Huang AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), 197e39fc8c9SShane Huang .flags = AHCI_FLAG_COMMON, 19814bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 199e39fc8c9SShane Huang .udma_mask = ATA_UDMA6, 200345347c5SYuan-Hsin Chen .port_ops = &ahci_pmp_retry_srst_ops, 201e39fc8c9SShane Huang }, 202facb8fa6SJeffrin Jose [board_ahci_vt8251] = { 203441577efSTejun Heo AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), 204e297d99eSTejun Heo .flags = AHCI_FLAG_COMMON, 20514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 206e297d99eSTejun Heo .udma_mask = ATA_UDMA6, 207441577efSTejun Heo .port_ops = &ahci_vt8251_ops, 2081b677afdSShaohua Li }, 209c6fd2807SJeff Garzik }; 210c6fd2807SJeff Garzik 211c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 212c6fd2807SJeff Garzik /* Intel */ 21354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 21454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 21554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 21654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 21754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 21882490c09STejun Heo { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ 21954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 22054bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 22154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 22254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 2237a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 2241b677afdSShaohua Li { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ 2257a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 2267a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 2277a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 2287a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 2297a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 2307a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 2317a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 2327a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 2337a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ 2347a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ 2357a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ 2367a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */ 2377a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ 2387a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 2397a234affSTejun Heo { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ 240d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ 241d4155e6fSJason Gaston { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ 24216ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ 243b2dde6afSMark Goodwin { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ 24416ad1ad9SJason Gaston { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ 245c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ 246c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ 247adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ 2488e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ 249c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ 250adcb5308SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ 2518e48b6b3SSeth Heasley { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ 252c1f57d9bSDavid Milburn { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ 2535623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ 2545623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ 2555623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ 2565623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ 2575623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ 2585623cab8SSeth Heasley { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ 259992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ 260992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ 261992b3fb9SSeth Heasley { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ 26264a3903dSSeth Heasley { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ 263a4a461a6SSeth Heasley { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ 264181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ 265181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */ 266181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ 267181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ 268181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ 269181e3ceaSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */ 2702cab7a4cSSeth Heasley { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ 271ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ 272ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */ 273ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ 274ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */ 275ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ 276ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ 277ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ 278ea4ace66SSeth Heasley { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ 27977b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ 28077b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ 28177b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ 28277b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */ 28377b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */ 28477b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */ 28577b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */ 28677b12bc9SJames Ralston { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */ 28729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ 28829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ 28929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ 29029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ 29129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ 29229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ 29329e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ 29429e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ 29529e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */ 29629e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */ 29729e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */ 29829e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */ 29929e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */ 30029e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */ 30129e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */ 30229e674ddSSeth Heasley { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */ 303efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ 304efda332cSJames Ralston { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ 305151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ 306151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ 307151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ 308151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ 309151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ 310151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ 311151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ 312151743fdSJames Ralston { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ 3131cfc7df3SSeth Heasley { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ 3149f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */ 3159f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */ 3169f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ 3179f961a5fSJames Ralston { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */ 3181b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ 3191b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */ 3201b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ 3211b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */ 3221b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ 3231b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ 3241b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ 3251b071a09SJames Ralston { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ 326249cd0a1SDevin Ryles { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */ 327249cd0a1SDevin Ryles { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */ 328249cd0a1SDevin Ryles { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */ 329690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */ 330690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ 331690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */ 332690000b9SJames Ralston { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ 333c6fd2807SJeff Garzik 334e34bb370STejun Heo /* JMicron 360/1/3/5/6, match class to avoid IDE function */ 335e34bb370STejun Heo { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 336e34bb370STejun Heo PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, 3371fefb8fdSBen Hutchings /* JMicron 362B and 362C have an AHCI function with IDE class code */ 3381fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, 3391fefb8fdSBen Hutchings { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr }, 340c6fd2807SJeff Garzik 341c6fd2807SJeff Garzik /* ATI */ 342c65ec1c2SConke Hu { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ 343e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb700 }, /* ATI SB700/800 */ 344e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb700 }, /* ATI SB700/800 */ 345e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb700 }, /* ATI SB700/800 */ 346e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb700 }, /* ATI SB700/800 */ 347e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ 348e39fc8c9SShane Huang { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ 349c6fd2807SJeff Garzik 350e2dd90b1SShane Huang /* AMD */ 3515deab536SShane Huang { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ 352fafe5c3dSShane Huang { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ 353e2dd90b1SShane Huang /* AMD is using RAID class only for ahci controllers */ 354e2dd90b1SShane Huang { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 355e2dd90b1SShane Huang PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, 356e2dd90b1SShane Huang 357c6fd2807SJeff Garzik /* VIA */ 35854bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 359bf335542STejun Heo { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ 360c6fd2807SJeff Garzik 361c6fd2807SJeff Garzik /* NVIDIA */ 362e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci_mcp65 }, /* MCP65 */ 363e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci_mcp65 }, /* MCP65 */ 364e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci_mcp65 }, /* MCP65 */ 365e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci_mcp65 }, /* MCP65 */ 366e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045c), board_ahci_mcp65 }, /* MCP65 */ 367e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ 368e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ 369e297d99eSTejun Heo { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ 370441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_mcp67 }, /* MCP67 */ 371441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_mcp67 }, /* MCP67 */ 372441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_mcp67 }, /* MCP67 */ 373441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_mcp67 }, /* MCP67 */ 374441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_mcp67 }, /* MCP67 */ 375441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_mcp67 }, /* MCP67 */ 376441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_mcp67 }, /* MCP67 */ 377441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_mcp67 }, /* MCP67 */ 378441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_mcp67 }, /* MCP67 */ 379441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_mcp67 }, /* MCP67 */ 380441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_mcp67 }, /* MCP67 */ 381441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_mcp67 }, /* MCP67 */ 382441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_mcp_linux }, /* Linux ID */ 383441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0581), board_ahci_mcp_linux }, /* Linux ID */ 384441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0582), board_ahci_mcp_linux }, /* Linux ID */ 385441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0583), board_ahci_mcp_linux }, /* Linux ID */ 386441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0584), board_ahci_mcp_linux }, /* Linux ID */ 387441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0585), board_ahci_mcp_linux }, /* Linux ID */ 388441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0586), board_ahci_mcp_linux }, /* Linux ID */ 389441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0587), board_ahci_mcp_linux }, /* Linux ID */ 390441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0588), board_ahci_mcp_linux }, /* Linux ID */ 391441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0589), board_ahci_mcp_linux }, /* Linux ID */ 392441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058a), board_ahci_mcp_linux }, /* Linux ID */ 393441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058b), board_ahci_mcp_linux }, /* Linux ID */ 394441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058c), board_ahci_mcp_linux }, /* Linux ID */ 395441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058d), board_ahci_mcp_linux }, /* Linux ID */ 396441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058e), board_ahci_mcp_linux }, /* Linux ID */ 397441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x058f), board_ahci_mcp_linux }, /* Linux ID */ 398441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_mcp73 }, /* MCP73 */ 399441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_mcp73 }, /* MCP73 */ 400441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_mcp73 }, /* MCP73 */ 401441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_mcp73 }, /* MCP73 */ 402441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_mcp73 }, /* MCP73 */ 403441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_mcp73 }, /* MCP73 */ 404441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_mcp73 }, /* MCP73 */ 405441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_mcp73 }, /* MCP73 */ 406441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_mcp73 }, /* MCP73 */ 407441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_mcp73 }, /* MCP73 */ 408441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_mcp73 }, /* MCP73 */ 409441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_mcp73 }, /* MCP73 */ 410441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci_mcp77 }, /* MCP77 */ 411441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci_mcp77 }, /* MCP77 */ 412441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci_mcp77 }, /* MCP77 */ 413441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci_mcp77 }, /* MCP77 */ 414441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci_mcp77 }, /* MCP77 */ 415441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci_mcp77 }, /* MCP77 */ 416441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci_mcp77 }, /* MCP77 */ 417441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci_mcp77 }, /* MCP77 */ 418441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci_mcp77 }, /* MCP77 */ 419441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci_mcp77 }, /* MCP77 */ 420441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci_mcp77 }, /* MCP77 */ 421441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci_mcp77 }, /* MCP77 */ 422441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab4), board_ahci_mcp79 }, /* MCP79 */ 423441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab5), board_ahci_mcp79 }, /* MCP79 */ 424441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab6), board_ahci_mcp79 }, /* MCP79 */ 425441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab7), board_ahci_mcp79 }, /* MCP79 */ 426441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci_mcp79 }, /* MCP79 */ 427441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci_mcp79 }, /* MCP79 */ 428441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci_mcp79 }, /* MCP79 */ 429441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci_mcp79 }, /* MCP79 */ 430441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci_mcp79 }, /* MCP79 */ 431441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci_mcp79 }, /* MCP79 */ 432441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci_mcp79 }, /* MCP79 */ 433441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci_mcp79 }, /* MCP79 */ 434441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci_mcp89 }, /* MCP89 */ 435441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci_mcp89 }, /* MCP89 */ 436441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci_mcp89 }, /* MCP89 */ 437441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci_mcp89 }, /* MCP89 */ 438441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci_mcp89 }, /* MCP89 */ 439441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci_mcp89 }, /* MCP89 */ 440441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci_mcp89 }, /* MCP89 */ 441441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci_mcp89 }, /* MCP89 */ 442441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci_mcp89 }, /* MCP89 */ 443441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci_mcp89 }, /* MCP89 */ 444441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci_mcp89 }, /* MCP89 */ 445441577efSTejun Heo { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci_mcp89 }, /* MCP89 */ 446c6fd2807SJeff Garzik 447c6fd2807SJeff Garzik /* SiS */ 44820e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 44920e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ 45020e2de4aSTejun Heo { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 451c6fd2807SJeff Garzik 452318893e1SAlessandro Rubini /* ST Microelectronics */ 453318893e1SAlessandro Rubini { PCI_VDEVICE(STMICRO, 0xCC06), board_ahci }, /* ST ConneXt */ 454318893e1SAlessandro Rubini 455cd70c266SJeff Garzik /* Marvell */ 456cd70c266SJeff Garzik { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ 457c40e7cb8SJose Alberto Reguero { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ 45869fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), 45910aca06cSAnssi Hannula .class = PCI_CLASS_STORAGE_SATA_AHCI, 46010aca06cSAnssi Hannula .class_mask = 0xffffff, 4615f173107STejun Heo .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ 46269fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), 463467b41c6SPer Jessen .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ 464e098f5cbSSimon Guinot { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178, 465e098f5cbSSimon Guinot PCI_VENDOR_ID_MARVELL_EXT, 0x9170), 466e098f5cbSSimon Guinot .driver_data = board_ahci_yes_fbs }, /* 88se9170 */ 46769fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), 468642d8925SMatt Johnson .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 469fcce9a35SGeorge Spelvin { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), 470c5edfff9SMurali Karicheri .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ 471c5edfff9SMurali Karicheri { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), 472fcce9a35SGeorge Spelvin .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ 47369fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), 47417c60c6bSAlan Cox .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ 475754a292fSAndreas Schrägle { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), 476754a292fSAndreas Schrägle .driver_data = board_ahci_yes_fbs }, 47769fd3157SMyron Stowe { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), 47850be5e36STejun Heo .driver_data = board_ahci_yes_fbs }, 4796d5278a6SSamir Benmendil { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), 4806d5278a6SSamir Benmendil .driver_data = board_ahci_yes_fbs }, 481d2518365SJérôme Carretero { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), 482d2518365SJérôme Carretero .driver_data = board_ahci_yes_fbs }, 483cd70c266SJeff Garzik 484c77a036bSMark Nelson /* Promise */ 485c77a036bSMark Nelson { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ 486b32bfc06SRomain Degez { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ 487c77a036bSMark Nelson 488c9703765SKeng-Yu Lin /* Asmedia */ 4897b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ 4907b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ 4917b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ 4927b4f6ecaSAlan Cox { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ 493c9703765SKeng-Yu Lin 49467809f85SLevente Kurusa /* 49566a7cbc3STejun Heo * Samsung SSDs found on some macbooks. NCQ times out if MSI is 49666a7cbc3STejun Heo * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 49767809f85SLevente Kurusa */ 49866a7cbc3STejun Heo { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, 4992b21ef0aSTejun Heo { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, 50067809f85SLevente Kurusa 5017f9c9f8eSHugh Daschbach /* Enmotus */ 5027f9c9f8eSHugh Daschbach { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, 5037f9c9f8eSHugh Daschbach 504415ae2b5SJeff Garzik /* Generic, PCI class code for AHCI */ 505415ae2b5SJeff Garzik { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 506c9f89475SConke Hu PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, 507415ae2b5SJeff Garzik 508c6fd2807SJeff Garzik { } /* terminate list */ 509c6fd2807SJeff Garzik }; 510c6fd2807SJeff Garzik 511c6fd2807SJeff Garzik 512c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 513c6fd2807SJeff Garzik .name = DRV_NAME, 514c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 515c6fd2807SJeff Garzik .probe = ahci_init_one, 51624dc5f33STejun Heo .remove = ata_pci_remove_one, 517438ac6d5STejun Heo #ifdef CONFIG_PM 518c6fd2807SJeff Garzik .suspend = ahci_pci_device_suspend, 519c6fd2807SJeff Garzik .resume = ahci_pci_device_resume, 520438ac6d5STejun Heo #endif 521c6fd2807SJeff Garzik }; 522c6fd2807SJeff Garzik 5235b66c829SAlan Cox #if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE) 5245b66c829SAlan Cox static int marvell_enable; 5255b66c829SAlan Cox #else 5265b66c829SAlan Cox static int marvell_enable = 1; 5275b66c829SAlan Cox #endif 5285b66c829SAlan Cox module_param(marvell_enable, int, 0644); 5295b66c829SAlan Cox MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); 5305b66c829SAlan Cox 5315b66c829SAlan Cox 532394d6e53SAnton Vorontsov static void ahci_pci_save_initial_config(struct pci_dev *pdev, 533394d6e53SAnton Vorontsov struct ahci_host_priv *hpriv) 534394d6e53SAnton Vorontsov { 535394d6e53SAnton Vorontsov if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { 536394d6e53SAnton Vorontsov dev_info(&pdev->dev, "JMB361 has only one port\n"); 5379a23c1d6SAntoine Tenart hpriv->force_port_map = 1; 538394d6e53SAnton Vorontsov } 539394d6e53SAnton Vorontsov 540394d6e53SAnton Vorontsov /* 541394d6e53SAnton Vorontsov * Temporary Marvell 6145 hack: PATA port presence 542394d6e53SAnton Vorontsov * is asserted through the standard AHCI port 543394d6e53SAnton Vorontsov * presence register, as bit 4 (counting from 0) 544394d6e53SAnton Vorontsov */ 545394d6e53SAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 546394d6e53SAnton Vorontsov if (pdev->device == 0x6121) 5479a23c1d6SAntoine Tenart hpriv->mask_port_map = 0x3; 548394d6e53SAnton Vorontsov else 5499a23c1d6SAntoine Tenart hpriv->mask_port_map = 0xf; 550394d6e53SAnton Vorontsov dev_info(&pdev->dev, 551394d6e53SAnton Vorontsov "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); 552394d6e53SAnton Vorontsov } 553394d6e53SAnton Vorontsov 554725c7b57SAntoine Ténart ahci_save_initial_config(&pdev->dev, hpriv); 555394d6e53SAnton Vorontsov } 556394d6e53SAnton Vorontsov 5573303040dSAnton Vorontsov static int ahci_pci_reset_controller(struct ata_host *host) 5583303040dSAnton Vorontsov { 5593303040dSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 5603303040dSAnton Vorontsov 5613303040dSAnton Vorontsov ahci_reset_controller(host); 5623303040dSAnton Vorontsov 563c6fd2807SJeff Garzik if (pdev->vendor == PCI_VENDOR_ID_INTEL) { 5643303040dSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 565c6fd2807SJeff Garzik u16 tmp16; 566c6fd2807SJeff Garzik 567c6fd2807SJeff Garzik /* configure PCS */ 568c6fd2807SJeff Garzik pci_read_config_word(pdev, 0x92, &tmp16); 56949f29090STejun Heo if ((tmp16 & hpriv->port_map) != hpriv->port_map) { 57049f29090STejun Heo tmp16 |= hpriv->port_map; 571c6fd2807SJeff Garzik pci_write_config_word(pdev, 0x92, tmp16); 572c6fd2807SJeff Garzik } 57349f29090STejun Heo } 574c6fd2807SJeff Garzik 575c6fd2807SJeff Garzik return 0; 576c6fd2807SJeff Garzik } 577c6fd2807SJeff Garzik 578781d6550SAnton Vorontsov static void ahci_pci_init_controller(struct ata_host *host) 579781d6550SAnton Vorontsov { 580781d6550SAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data; 581781d6550SAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 582781d6550SAnton Vorontsov void __iomem *port_mmio; 583781d6550SAnton Vorontsov u32 tmp; 584c40e7cb8SJose Alberto Reguero int mv; 5852bcd866bSJeff Garzik 586417a1a6dSTejun Heo if (hpriv->flags & AHCI_HFLAG_MV_PATA) { 587c40e7cb8SJose Alberto Reguero if (pdev->device == 0x6121) 588c40e7cb8SJose Alberto Reguero mv = 2; 589c40e7cb8SJose Alberto Reguero else 590c40e7cb8SJose Alberto Reguero mv = 4; 591c40e7cb8SJose Alberto Reguero port_mmio = __ahci_port_base(host, mv); 592cd70c266SJeff Garzik 593cd70c266SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 594cd70c266SJeff Garzik 595cd70c266SJeff Garzik /* clear port IRQ */ 596cd70c266SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 597cd70c266SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 598cd70c266SJeff Garzik if (tmp) 599cd70c266SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 600cd70c266SJeff Garzik } 601cd70c266SJeff Garzik 602781d6550SAnton Vorontsov ahci_init_controller(host); 603c6fd2807SJeff Garzik } 604c6fd2807SJeff Garzik 605cc0680a5STejun Heo static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, 606d4b2bab4STejun Heo unsigned long deadline) 607ad616ffbSTejun Heo { 608cc0680a5STejun Heo struct ata_port *ap = link->ap; 609039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 6109dadd45bSTejun Heo bool online; 611ad616ffbSTejun Heo int rc; 612ad616ffbSTejun Heo 613ad616ffbSTejun Heo DPRINTK("ENTER\n"); 614ad616ffbSTejun Heo 6154447d351STejun Heo ahci_stop_engine(ap); 616ad616ffbSTejun Heo 617cc0680a5STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6189dadd45bSTejun Heo deadline, &online, NULL); 619ad616ffbSTejun Heo 620039ece38SHans de Goede hpriv->start_engine(ap); 621ad616ffbSTejun Heo 622ad616ffbSTejun Heo DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 623ad616ffbSTejun Heo 624ad616ffbSTejun Heo /* vt8251 doesn't clear BSY on signature FIS reception, 625ad616ffbSTejun Heo * request follow-up softreset. 626ad616ffbSTejun Heo */ 6279dadd45bSTejun Heo return online ? -EAGAIN : rc; 628ad616ffbSTejun Heo } 629ad616ffbSTejun Heo 630edc93052STejun Heo static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, 631edc93052STejun Heo unsigned long deadline) 632edc93052STejun Heo { 633edc93052STejun Heo struct ata_port *ap = link->ap; 634edc93052STejun Heo struct ahci_port_priv *pp = ap->private_data; 635039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data; 636edc93052STejun Heo u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 637edc93052STejun Heo struct ata_taskfile tf; 6389dadd45bSTejun Heo bool online; 639edc93052STejun Heo int rc; 640edc93052STejun Heo 641edc93052STejun Heo ahci_stop_engine(ap); 642edc93052STejun Heo 643edc93052STejun Heo /* clear D2H reception area to properly wait for D2H FIS */ 644edc93052STejun Heo ata_tf_init(link->device, &tf); 6459bbb1b0eSSergei Shtylyov tf.command = ATA_BUSY; 646edc93052STejun Heo ata_tf_to_fis(&tf, 0, 0, d2h_fis); 647edc93052STejun Heo 648edc93052STejun Heo rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), 6499dadd45bSTejun Heo deadline, &online, NULL); 650edc93052STejun Heo 651039ece38SHans de Goede hpriv->start_engine(ap); 652edc93052STejun Heo 653edc93052STejun Heo /* The pseudo configuration device on SIMG4726 attached to 654edc93052STejun Heo * ASUS P5W-DH Deluxe doesn't send signature FIS after 655edc93052STejun Heo * hardreset if no device is attached to the first downstream 656edc93052STejun Heo * port && the pseudo device locks up on SRST w/ PMP==0. To 657edc93052STejun Heo * work around this, wait for !BSY only briefly. If BSY isn't 658edc93052STejun Heo * cleared, perform CLO and proceed to IDENTIFY (achieved by 659edc93052STejun Heo * ATA_LFLAG_NO_SRST and ATA_LFLAG_ASSUME_ATA). 660edc93052STejun Heo * 661edc93052STejun Heo * Wait for two seconds. Devices attached to downstream port 662edc93052STejun Heo * which can't process the following IDENTIFY after this will 663edc93052STejun Heo * have to be reset again. For most cases, this should 664edc93052STejun Heo * suffice while making probing snappish enough. 665edc93052STejun Heo */ 6669dadd45bSTejun Heo if (online) { 6679dadd45bSTejun Heo rc = ata_wait_after_reset(link, jiffies + 2 * HZ, 6689dadd45bSTejun Heo ahci_check_ready); 669edc93052STejun Heo if (rc) 67078d5ae39SShane Huang ahci_kick_engine(ap); 6719dadd45bSTejun Heo } 6729dadd45bSTejun Heo return rc; 673edc93052STejun Heo } 674edc93052STejun Heo 675438ac6d5STejun Heo #ifdef CONFIG_PM 676c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) 677c6fd2807SJeff Garzik { 6780a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 6799b10ae86STejun Heo struct ahci_host_priv *hpriv = host->private_data; 680d8993349SAnton Vorontsov void __iomem *mmio = hpriv->mmio; 681c6fd2807SJeff Garzik u32 ctl; 682c6fd2807SJeff Garzik 6839b10ae86STejun Heo if (mesg.event & PM_EVENT_SUSPEND && 6849b10ae86STejun Heo hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { 685a44fec1fSJoe Perches dev_err(&pdev->dev, 6869b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 6879b10ae86STejun Heo return -EIO; 6889b10ae86STejun Heo } 6899b10ae86STejun Heo 6903a2d5b70SRafael J. Wysocki if (mesg.event & PM_EVENT_SLEEP) { 691c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 692c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 693c6fd2807SJeff Garzik * transition of the HBA to D3 state. 694c6fd2807SJeff Garzik */ 695c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 696c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 697c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 698c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 699c6fd2807SJeff Garzik } 700c6fd2807SJeff Garzik 701c6fd2807SJeff Garzik return ata_pci_device_suspend(pdev, mesg); 702c6fd2807SJeff Garzik } 703c6fd2807SJeff Garzik 704c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev) 705c6fd2807SJeff Garzik { 7060a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 707c6fd2807SJeff Garzik int rc; 708c6fd2807SJeff Garzik 709553c4aa6STejun Heo rc = ata_pci_device_do_resume(pdev); 710553c4aa6STejun Heo if (rc) 711553c4aa6STejun Heo return rc; 712c6fd2807SJeff Garzik 713cb85696dSJames Laird /* Apple BIOS helpfully mangles the registers on resume */ 714cb85696dSJames Laird if (is_mcp89_apple(pdev)) 715cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 716cb85696dSJames Laird 717c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 7183303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 719c6fd2807SJeff Garzik if (rc) 720c6fd2807SJeff Garzik return rc; 721c6fd2807SJeff Garzik 722781d6550SAnton Vorontsov ahci_pci_init_controller(host); 723c6fd2807SJeff Garzik } 724c6fd2807SJeff Garzik 725cca3974eSJeff Garzik ata_host_resume(host); 726c6fd2807SJeff Garzik 727c6fd2807SJeff Garzik return 0; 728c6fd2807SJeff Garzik } 729438ac6d5STejun Heo #endif 730c6fd2807SJeff Garzik 7314447d351STejun Heo static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) 732c6fd2807SJeff Garzik { 733c6fd2807SJeff Garzik int rc; 734c6fd2807SJeff Garzik 735318893e1SAlessandro Rubini /* 736318893e1SAlessandro Rubini * If the device fixup already set the dma_mask to some non-standard 737318893e1SAlessandro Rubini * value, don't extend it here. This happens on STA2X11, for example. 738318893e1SAlessandro Rubini */ 739318893e1SAlessandro Rubini if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) 740318893e1SAlessandro Rubini return 0; 741318893e1SAlessandro Rubini 742c6fd2807SJeff Garzik if (using_dac && 743c54c719bSQuentin Lambert !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { 744c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); 745c6fd2807SJeff Garzik if (rc) { 746c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 747c6fd2807SJeff Garzik if (rc) { 748a44fec1fSJoe Perches dev_err(&pdev->dev, 749c6fd2807SJeff Garzik "64-bit DMA enable failed\n"); 750c6fd2807SJeff Garzik return rc; 751c6fd2807SJeff Garzik } 752c6fd2807SJeff Garzik } 753c6fd2807SJeff Garzik } else { 754c54c719bSQuentin Lambert rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 755c6fd2807SJeff Garzik if (rc) { 756a44fec1fSJoe Perches dev_err(&pdev->dev, "32-bit DMA enable failed\n"); 757c6fd2807SJeff Garzik return rc; 758c6fd2807SJeff Garzik } 759c54c719bSQuentin Lambert rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 760c6fd2807SJeff Garzik if (rc) { 761a44fec1fSJoe Perches dev_err(&pdev->dev, 762c6fd2807SJeff Garzik "32-bit consistent DMA enable failed\n"); 763c6fd2807SJeff Garzik return rc; 764c6fd2807SJeff Garzik } 765c6fd2807SJeff Garzik } 766c6fd2807SJeff Garzik return 0; 767c6fd2807SJeff Garzik } 768c6fd2807SJeff Garzik 769439fcaecSAnton Vorontsov static void ahci_pci_print_info(struct ata_host *host) 770439fcaecSAnton Vorontsov { 771439fcaecSAnton Vorontsov struct pci_dev *pdev = to_pci_dev(host->dev); 772439fcaecSAnton Vorontsov u16 cc; 773439fcaecSAnton Vorontsov const char *scc_s; 774439fcaecSAnton Vorontsov 775439fcaecSAnton Vorontsov pci_read_config_word(pdev, 0x0a, &cc); 776439fcaecSAnton Vorontsov if (cc == PCI_CLASS_STORAGE_IDE) 777439fcaecSAnton Vorontsov scc_s = "IDE"; 778439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_SATA) 779439fcaecSAnton Vorontsov scc_s = "SATA"; 780439fcaecSAnton Vorontsov else if (cc == PCI_CLASS_STORAGE_RAID) 781439fcaecSAnton Vorontsov scc_s = "RAID"; 782439fcaecSAnton Vorontsov else 783439fcaecSAnton Vorontsov scc_s = "unknown"; 784439fcaecSAnton Vorontsov 785439fcaecSAnton Vorontsov ahci_print_info(host, scc_s); 786439fcaecSAnton Vorontsov } 787439fcaecSAnton Vorontsov 788edc93052STejun Heo /* On ASUS P5W DH Deluxe, the second port of PCI device 00:1f.2 is 789edc93052STejun Heo * hardwired to on-board SIMG 4726. The chipset is ICH8 and doesn't 790edc93052STejun Heo * support PMP and the 4726 either directly exports the device 791edc93052STejun Heo * attached to the first downstream port or acts as a hardware storage 792edc93052STejun Heo * controller and emulate a single ATA device (can be RAID 0/1 or some 793edc93052STejun Heo * other configuration). 794edc93052STejun Heo * 795edc93052STejun Heo * When there's no device attached to the first downstream port of the 796edc93052STejun Heo * 4726, "Config Disk" appears, which is a pseudo ATA device to 797edc93052STejun Heo * configure the 4726. However, ATA emulation of the device is very 798edc93052STejun Heo * lame. It doesn't send signature D2H Reg FIS after the initial 799edc93052STejun Heo * hardreset, pukes on SRST w/ PMP==0 and has bunch of other issues. 800edc93052STejun Heo * 801edc93052STejun Heo * The following function works around the problem by always using 802edc93052STejun Heo * hardreset on the port and not depending on receiving signature FIS 803edc93052STejun Heo * afterward. If signature FIS isn't received soon, ATA class is 804edc93052STejun Heo * assumed without follow-up softreset. 805edc93052STejun Heo */ 806edc93052STejun Heo static void ahci_p5wdh_workaround(struct ata_host *host) 807edc93052STejun Heo { 8081bd06867SMathias Krause static const struct dmi_system_id sysids[] = { 809edc93052STejun Heo { 810edc93052STejun Heo .ident = "P5W DH Deluxe", 811edc93052STejun Heo .matches = { 812edc93052STejun Heo DMI_MATCH(DMI_SYS_VENDOR, 813edc93052STejun Heo "ASUSTEK COMPUTER INC"), 814edc93052STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"), 815edc93052STejun Heo }, 816edc93052STejun Heo }, 817edc93052STejun Heo { } 818edc93052STejun Heo }; 819edc93052STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 820edc93052STejun Heo 821edc93052STejun Heo if (pdev->bus->number == 0 && pdev->devfn == PCI_DEVFN(0x1f, 2) && 822edc93052STejun Heo dmi_check_system(sysids)) { 823edc93052STejun Heo struct ata_port *ap = host->ports[1]; 824edc93052STejun Heo 825a44fec1fSJoe Perches dev_info(&pdev->dev, 826a44fec1fSJoe Perches "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n"); 827edc93052STejun Heo 828edc93052STejun Heo ap->ops = &ahci_p5wdh_ops; 829edc93052STejun Heo ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; 830edc93052STejun Heo } 831edc93052STejun Heo } 832edc93052STejun Heo 833cb85696dSJames Laird /* 834cb85696dSJames Laird * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when 835cb85696dSJames Laird * booting in BIOS compatibility mode. We restore the registers but not ID. 836cb85696dSJames Laird */ 837cb85696dSJames Laird static void ahci_mcp89_apple_enable(struct pci_dev *pdev) 838cb85696dSJames Laird { 839cb85696dSJames Laird u32 val; 840cb85696dSJames Laird 841cb85696dSJames Laird printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); 842cb85696dSJames Laird 843cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 844cb85696dSJames Laird val |= 1 << 0x1b; 845cb85696dSJames Laird /* the following changes the device ID, but appears not to affect function */ 846cb85696dSJames Laird /* val = (val & ~0xf0000000) | 0x80000000; */ 847cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 848cb85696dSJames Laird 849cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 850cb85696dSJames Laird val |= 1 << 0xc; 851cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 852cb85696dSJames Laird 853cb85696dSJames Laird pci_read_config_dword(pdev, 0x4a4, &val); 854cb85696dSJames Laird val &= 0xff; 855cb85696dSJames Laird val |= 0x01060100; 856cb85696dSJames Laird pci_write_config_dword(pdev, 0x4a4, val); 857cb85696dSJames Laird 858cb85696dSJames Laird pci_read_config_dword(pdev, 0x54c, &val); 859cb85696dSJames Laird val &= ~(1 << 0xc); 860cb85696dSJames Laird pci_write_config_dword(pdev, 0x54c, val); 861cb85696dSJames Laird 862cb85696dSJames Laird pci_read_config_dword(pdev, 0xf8, &val); 863cb85696dSJames Laird val &= ~(1 << 0x1b); 864cb85696dSJames Laird pci_write_config_dword(pdev, 0xf8, val); 865cb85696dSJames Laird } 866cb85696dSJames Laird 867cb85696dSJames Laird static bool is_mcp89_apple(struct pci_dev *pdev) 868cb85696dSJames Laird { 869cb85696dSJames Laird return pdev->vendor == PCI_VENDOR_ID_NVIDIA && 870cb85696dSJames Laird pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && 871cb85696dSJames Laird pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 872cb85696dSJames Laird pdev->subsystem_device == 0xcb89; 873cb85696dSJames Laird } 874cb85696dSJames Laird 8752fcad9d2STejun Heo /* only some SB600 ahci controllers can do 64bit DMA */ 8762fcad9d2STejun Heo static bool ahci_sb600_enable_64bit(struct pci_dev *pdev) 87758a09b38SShane Huang { 87858a09b38SShane Huang static const struct dmi_system_id sysids[] = { 87903d783bfSTejun Heo /* 88003d783bfSTejun Heo * The oldest version known to be broken is 0901 and 88103d783bfSTejun Heo * working is 1501 which was released on 2007-10-26. 8822fcad9d2STejun Heo * Enable 64bit DMA on 1501 and anything newer. 8832fcad9d2STejun Heo * 88403d783bfSTejun Heo * Please read bko#9412 for more info. 88503d783bfSTejun Heo */ 88658a09b38SShane Huang { 88758a09b38SShane Huang .ident = "ASUS M2A-VM", 88858a09b38SShane Huang .matches = { 88958a09b38SShane Huang DMI_MATCH(DMI_BOARD_VENDOR, 89058a09b38SShane Huang "ASUSTeK Computer INC."), 89158a09b38SShane Huang DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), 89258a09b38SShane Huang }, 89303d783bfSTejun Heo .driver_data = "20071026", /* yyyymmdd */ 89458a09b38SShane Huang }, 895e65cc194SMark Nelson /* 896e65cc194SMark Nelson * All BIOS versions for the MSI K9A2 Platinum (MS-7376) 897e65cc194SMark Nelson * support 64bit DMA. 898e65cc194SMark Nelson * 899e65cc194SMark Nelson * BIOS versions earlier than 1.5 had the Manufacturer DMI 900e65cc194SMark Nelson * fields as "MICRO-STAR INTERANTIONAL CO.,LTD". 901e65cc194SMark Nelson * This spelling mistake was fixed in BIOS version 1.5, so 902e65cc194SMark Nelson * 1.5 and later have the Manufacturer as 903e65cc194SMark Nelson * "MICRO-STAR INTERNATIONAL CO.,LTD". 904e65cc194SMark Nelson * So try to match on DMI_BOARD_VENDOR of "MICRO-STAR INTER". 905e65cc194SMark Nelson * 906e65cc194SMark Nelson * BIOS versions earlier than 1.9 had a Board Product Name 907e65cc194SMark Nelson * DMI field of "MS-7376". This was changed to be 908e65cc194SMark Nelson * "K9A2 Platinum (MS-7376)" in version 1.9, but we can still 909e65cc194SMark Nelson * match on DMI_BOARD_NAME of "MS-7376". 910e65cc194SMark Nelson */ 911e65cc194SMark Nelson { 912e65cc194SMark Nelson .ident = "MSI K9A2 Platinum", 913e65cc194SMark Nelson .matches = { 914e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 915e65cc194SMark Nelson "MICRO-STAR INTER"), 916e65cc194SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7376"), 917e65cc194SMark Nelson }, 918e65cc194SMark Nelson }, 9193c4aa91fSMark Nelson /* 920ff0173c1SMark Nelson * All BIOS versions for the MSI K9AGM2 (MS-7327) support 921ff0173c1SMark Nelson * 64bit DMA. 922ff0173c1SMark Nelson * 923ff0173c1SMark Nelson * This board also had the typo mentioned above in the 924ff0173c1SMark Nelson * Manufacturer DMI field (fixed in BIOS version 1.5), so 925ff0173c1SMark Nelson * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. 926ff0173c1SMark Nelson */ 927ff0173c1SMark Nelson { 928ff0173c1SMark Nelson .ident = "MSI K9AGM2", 929ff0173c1SMark Nelson .matches = { 930ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 931ff0173c1SMark Nelson "MICRO-STAR INTER"), 932ff0173c1SMark Nelson DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), 933ff0173c1SMark Nelson }, 934ff0173c1SMark Nelson }, 935ff0173c1SMark Nelson /* 9363c4aa91fSMark Nelson * All BIOS versions for the Asus M3A support 64bit DMA. 9373c4aa91fSMark Nelson * (all release versions from 0301 to 1206 were tested) 9383c4aa91fSMark Nelson */ 9393c4aa91fSMark Nelson { 9403c4aa91fSMark Nelson .ident = "ASUS M3A", 9413c4aa91fSMark Nelson .matches = { 9423c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_VENDOR, 9433c4aa91fSMark Nelson "ASUSTeK Computer INC."), 9443c4aa91fSMark Nelson DMI_MATCH(DMI_BOARD_NAME, "M3A"), 9453c4aa91fSMark Nelson }, 9463c4aa91fSMark Nelson }, 94758a09b38SShane Huang { } 94858a09b38SShane Huang }; 94903d783bfSTejun Heo const struct dmi_system_id *match; 9502fcad9d2STejun Heo int year, month, date; 9512fcad9d2STejun Heo char buf[9]; 95258a09b38SShane Huang 95303d783bfSTejun Heo match = dmi_first_match(sysids); 95458a09b38SShane Huang if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || 95503d783bfSTejun Heo !match) 95658a09b38SShane Huang return false; 95758a09b38SShane Huang 958e65cc194SMark Nelson if (!match->driver_data) 959e65cc194SMark Nelson goto enable_64bit; 960e65cc194SMark Nelson 96103d783bfSTejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 96203d783bfSTejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 96303d783bfSTejun Heo 964e65cc194SMark Nelson if (strcmp(buf, match->driver_data) >= 0) 965e65cc194SMark Nelson goto enable_64bit; 966e65cc194SMark Nelson else { 967a44fec1fSJoe Perches dev_warn(&pdev->dev, 968a44fec1fSJoe Perches "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", 969a44fec1fSJoe Perches match->ident); 9702fcad9d2STejun Heo return false; 9712fcad9d2STejun Heo } 972e65cc194SMark Nelson 973e65cc194SMark Nelson enable_64bit: 974a44fec1fSJoe Perches dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident); 975e65cc194SMark Nelson return true; 97658a09b38SShane Huang } 97758a09b38SShane Huang 9781fd68434SRafael J. Wysocki static bool ahci_broken_system_poweroff(struct pci_dev *pdev) 9791fd68434SRafael J. Wysocki { 9801fd68434SRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 9811fd68434SRafael J. Wysocki { 9821fd68434SRafael J. Wysocki .ident = "HP Compaq nx6310", 9831fd68434SRafael J. Wysocki .matches = { 9841fd68434SRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 9851fd68434SRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"), 9861fd68434SRafael J. Wysocki }, 9871fd68434SRafael J. Wysocki /* PCI slot number of the controller */ 9881fd68434SRafael J. Wysocki .driver_data = (void *)0x1FUL, 9891fd68434SRafael J. Wysocki }, 990d2f9c061SMaciej Rutecki { 991d2f9c061SMaciej Rutecki .ident = "HP Compaq 6720s", 992d2f9c061SMaciej Rutecki .matches = { 993d2f9c061SMaciej Rutecki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 994d2f9c061SMaciej Rutecki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), 995d2f9c061SMaciej Rutecki }, 996d2f9c061SMaciej Rutecki /* PCI slot number of the controller */ 997d2f9c061SMaciej Rutecki .driver_data = (void *)0x1FUL, 998d2f9c061SMaciej Rutecki }, 9991fd68434SRafael J. Wysocki 10001fd68434SRafael J. Wysocki { } /* terminate list */ 10011fd68434SRafael J. Wysocki }; 10021fd68434SRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 10031fd68434SRafael J. Wysocki 10041fd68434SRafael J. Wysocki if (dmi) { 10051fd68434SRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 10061fd68434SRafael J. Wysocki /* apply the quirk only to on-board controllers */ 10071fd68434SRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 10081fd68434SRafael J. Wysocki } 10091fd68434SRafael J. Wysocki 10101fd68434SRafael J. Wysocki return false; 10111fd68434SRafael J. Wysocki } 10121fd68434SRafael J. Wysocki 10139b10ae86STejun Heo static bool ahci_broken_suspend(struct pci_dev *pdev) 10149b10ae86STejun Heo { 10159b10ae86STejun Heo static const struct dmi_system_id sysids[] = { 10169b10ae86STejun Heo /* 10179b10ae86STejun Heo * On HP dv[4-6] and HDX18 with earlier BIOSen, link 10189b10ae86STejun Heo * to the harddisk doesn't become online after 10199b10ae86STejun Heo * resuming from STR. Warn and fail suspend. 10209deb3431STejun Heo * 10219deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=12276 10229deb3431STejun Heo * 10239deb3431STejun Heo * Use dates instead of versions to match as HP is 10249deb3431STejun Heo * apparently recycling both product and version 10259deb3431STejun Heo * strings. 10269deb3431STejun Heo * 10279deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15462 10289b10ae86STejun Heo */ 10299b10ae86STejun Heo { 10309b10ae86STejun Heo .ident = "dv4", 10319b10ae86STejun Heo .matches = { 10329b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 10339b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 10349b10ae86STejun Heo "HP Pavilion dv4 Notebook PC"), 10359b10ae86STejun Heo }, 10369deb3431STejun Heo .driver_data = "20090105", /* F.30 */ 10379b10ae86STejun Heo }, 10389b10ae86STejun Heo { 10399b10ae86STejun Heo .ident = "dv5", 10409b10ae86STejun Heo .matches = { 10419b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 10429b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 10439b10ae86STejun Heo "HP Pavilion dv5 Notebook PC"), 10449b10ae86STejun Heo }, 10459deb3431STejun Heo .driver_data = "20090506", /* F.16 */ 10469b10ae86STejun Heo }, 10479b10ae86STejun Heo { 10489b10ae86STejun Heo .ident = "dv6", 10499b10ae86STejun Heo .matches = { 10509b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 10519b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 10529b10ae86STejun Heo "HP Pavilion dv6 Notebook PC"), 10539b10ae86STejun Heo }, 10549deb3431STejun Heo .driver_data = "20090423", /* F.21 */ 10559b10ae86STejun Heo }, 10569b10ae86STejun Heo { 10579b10ae86STejun Heo .ident = "HDX18", 10589b10ae86STejun Heo .matches = { 10599b10ae86STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 10609b10ae86STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, 10619b10ae86STejun Heo "HP HDX18 Notebook PC"), 10629b10ae86STejun Heo }, 10639deb3431STejun Heo .driver_data = "20090430", /* F.23 */ 10649b10ae86STejun Heo }, 1065cedc9bf9STejun Heo /* 1066cedc9bf9STejun Heo * Acer eMachines G725 has the same problem. BIOS 1067cedc9bf9STejun Heo * V1.03 is known to be broken. V3.04 is known to 106825985edcSLucas De Marchi * work. Between, there are V1.06, V2.06 and V3.03 1069cedc9bf9STejun Heo * that we don't have much idea about. For now, 1070cedc9bf9STejun Heo * blacklist anything older than V3.04. 10719deb3431STejun Heo * 10729deb3431STejun Heo * http://bugzilla.kernel.org/show_bug.cgi?id=15104 1073cedc9bf9STejun Heo */ 1074cedc9bf9STejun Heo { 1075cedc9bf9STejun Heo .ident = "G725", 1076cedc9bf9STejun Heo .matches = { 1077cedc9bf9STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), 1078cedc9bf9STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), 1079cedc9bf9STejun Heo }, 10809deb3431STejun Heo .driver_data = "20091216", /* V3.04 */ 1081cedc9bf9STejun Heo }, 10829b10ae86STejun Heo { } /* terminate list */ 10839b10ae86STejun Heo }; 10849b10ae86STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 10859deb3431STejun Heo int year, month, date; 10869deb3431STejun Heo char buf[9]; 10879b10ae86STejun Heo 10889b10ae86STejun Heo if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) 10899b10ae86STejun Heo return false; 10909b10ae86STejun Heo 10919deb3431STejun Heo dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); 10929deb3431STejun Heo snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); 10939b10ae86STejun Heo 10949deb3431STejun Heo return strcmp(buf, dmi->driver_data) < 0; 10959b10ae86STejun Heo } 10969b10ae86STejun Heo 10975594639aSTejun Heo static bool ahci_broken_online(struct pci_dev *pdev) 10985594639aSTejun Heo { 10995594639aSTejun Heo #define ENCODE_BUSDEVFN(bus, slot, func) \ 11005594639aSTejun Heo (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func))) 11015594639aSTejun Heo static const struct dmi_system_id sysids[] = { 11025594639aSTejun Heo /* 11035594639aSTejun Heo * There are several gigabyte boards which use 11045594639aSTejun Heo * SIMG5723s configured as hardware RAID. Certain 11055594639aSTejun Heo * 5723 firmware revisions shipped there keep the link 11065594639aSTejun Heo * online but fail to answer properly to SRST or 11075594639aSTejun Heo * IDENTIFY when no device is attached downstream 11085594639aSTejun Heo * causing libata to retry quite a few times leading 11095594639aSTejun Heo * to excessive detection delay. 11105594639aSTejun Heo * 11115594639aSTejun Heo * As these firmwares respond to the second reset try 11125594639aSTejun Heo * with invalid device signature, considering unknown 11135594639aSTejun Heo * sig as offline works around the problem acceptably. 11145594639aSTejun Heo */ 11155594639aSTejun Heo { 11165594639aSTejun Heo .ident = "EP45-DQ6", 11175594639aSTejun Heo .matches = { 11185594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 11195594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 11205594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"), 11215594639aSTejun Heo }, 11225594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0), 11235594639aSTejun Heo }, 11245594639aSTejun Heo { 11255594639aSTejun Heo .ident = "EP45-DS5", 11265594639aSTejun Heo .matches = { 11275594639aSTejun Heo DMI_MATCH(DMI_BOARD_VENDOR, 11285594639aSTejun Heo "Gigabyte Technology Co., Ltd."), 11295594639aSTejun Heo DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"), 11305594639aSTejun Heo }, 11315594639aSTejun Heo .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0), 11325594639aSTejun Heo }, 11335594639aSTejun Heo { } /* terminate list */ 11345594639aSTejun Heo }; 11355594639aSTejun Heo #undef ENCODE_BUSDEVFN 11365594639aSTejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 11375594639aSTejun Heo unsigned int val; 11385594639aSTejun Heo 11395594639aSTejun Heo if (!dmi) 11405594639aSTejun Heo return false; 11415594639aSTejun Heo 11425594639aSTejun Heo val = (unsigned long)dmi->driver_data; 11435594639aSTejun Heo 11445594639aSTejun Heo return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); 11455594639aSTejun Heo } 11465594639aSTejun Heo 11470cf4a7d6SJacob Pan static bool ahci_broken_devslp(struct pci_dev *pdev) 11480cf4a7d6SJacob Pan { 11490cf4a7d6SJacob Pan /* device with broken DEVSLP but still showing SDS capability */ 11500cf4a7d6SJacob Pan static const struct pci_device_id ids[] = { 11510cf4a7d6SJacob Pan { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ 11520cf4a7d6SJacob Pan {} 11530cf4a7d6SJacob Pan }; 11540cf4a7d6SJacob Pan 11550cf4a7d6SJacob Pan return pci_match_id(ids, pdev); 11560cf4a7d6SJacob Pan } 11570cf4a7d6SJacob Pan 11588e513217SMarkus Trippelsdorf #ifdef CONFIG_ATA_ACPI 1159f80ae7e4STejun Heo static void ahci_gtf_filter_workaround(struct ata_host *host) 1160f80ae7e4STejun Heo { 1161f80ae7e4STejun Heo static const struct dmi_system_id sysids[] = { 1162f80ae7e4STejun Heo /* 1163f80ae7e4STejun Heo * Aspire 3810T issues a bunch of SATA enable commands 1164f80ae7e4STejun Heo * via _GTF including an invalid one and one which is 1165f80ae7e4STejun Heo * rejected by the device. Among the successful ones 1166f80ae7e4STejun Heo * is FPDMA non-zero offset enable which when enabled 1167f80ae7e4STejun Heo * only on the drive side leads to NCQ command 1168f80ae7e4STejun Heo * failures. Filter it out. 1169f80ae7e4STejun Heo */ 1170f80ae7e4STejun Heo { 1171f80ae7e4STejun Heo .ident = "Aspire 3810T", 1172f80ae7e4STejun Heo .matches = { 1173f80ae7e4STejun Heo DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 1174f80ae7e4STejun Heo DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3810T"), 1175f80ae7e4STejun Heo }, 1176f80ae7e4STejun Heo .driver_data = (void *)ATA_ACPI_FILTER_FPDMA_OFFSET, 1177f80ae7e4STejun Heo }, 1178f80ae7e4STejun Heo { } 1179f80ae7e4STejun Heo }; 1180f80ae7e4STejun Heo const struct dmi_system_id *dmi = dmi_first_match(sysids); 1181f80ae7e4STejun Heo unsigned int filter; 1182f80ae7e4STejun Heo int i; 1183f80ae7e4STejun Heo 1184f80ae7e4STejun Heo if (!dmi) 1185f80ae7e4STejun Heo return; 1186f80ae7e4STejun Heo 1187f80ae7e4STejun Heo filter = (unsigned long)dmi->driver_data; 1188a44fec1fSJoe Perches dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", 1189f80ae7e4STejun Heo filter, dmi->ident); 1190f80ae7e4STejun Heo 1191f80ae7e4STejun Heo for (i = 0; i < host->n_ports; i++) { 1192f80ae7e4STejun Heo struct ata_port *ap = host->ports[i]; 1193f80ae7e4STejun Heo struct ata_link *link; 1194f80ae7e4STejun Heo struct ata_device *dev; 1195f80ae7e4STejun Heo 1196f80ae7e4STejun Heo ata_for_each_link(link, ap, EDGE) 1197f80ae7e4STejun Heo ata_for_each_dev(dev, link, ALL) 1198f80ae7e4STejun Heo dev->gtf_filter |= filter; 1199f80ae7e4STejun Heo } 1200f80ae7e4STejun Heo } 12018e513217SMarkus Trippelsdorf #else 12028e513217SMarkus Trippelsdorf static inline void ahci_gtf_filter_workaround(struct ata_host *host) 12038e513217SMarkus Trippelsdorf {} 12048e513217SMarkus Trippelsdorf #endif 1205f80ae7e4STejun Heo 1206ee2aad42SRobert Richter static struct msi_desc *msix_get_desc(struct pci_dev *dev, u16 entry) 1207ee2aad42SRobert Richter { 1208ee2aad42SRobert Richter struct msi_desc *desc; 1209ee2aad42SRobert Richter 1210ee2aad42SRobert Richter list_for_each_entry(desc, &dev->msi_list, list) { 1211ee2aad42SRobert Richter if (desc->msi_attrib.entry_nr == entry) 1212ee2aad42SRobert Richter return desc; 1213ee2aad42SRobert Richter } 1214ee2aad42SRobert Richter 1215ee2aad42SRobert Richter return NULL; 1216ee2aad42SRobert Richter } 1217ee2aad42SRobert Richter 1218ee2aad42SRobert Richter /* 1219ee2aad42SRobert Richter * ahci_init_msix() only implements single MSI-X support, not multiple 1220ee2aad42SRobert Richter * MSI-X per-port interrupts. This is needed for host controllers that only 1221ee2aad42SRobert Richter * have MSI-X support implemented, but no MSI or intx. 1222ee2aad42SRobert Richter */ 1223ee2aad42SRobert Richter static int ahci_init_msix(struct pci_dev *pdev, unsigned int n_ports, 1224ee2aad42SRobert Richter struct ahci_host_priv *hpriv) 1225ee2aad42SRobert Richter { 1226ee2aad42SRobert Richter struct msi_desc *desc; 1227ee2aad42SRobert Richter int rc, nvec; 1228ee2aad42SRobert Richter struct msix_entry entry = {}; 1229ee2aad42SRobert Richter 1230ee2aad42SRobert Richter /* Do not init MSI-X if MSI is disabled for the device */ 1231ee2aad42SRobert Richter if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1232ee2aad42SRobert Richter return -ENODEV; 1233ee2aad42SRobert Richter 1234ee2aad42SRobert Richter nvec = pci_msix_vec_count(pdev); 1235ee2aad42SRobert Richter if (nvec < 0) 1236ee2aad42SRobert Richter return nvec; 1237ee2aad42SRobert Richter 1238ee2aad42SRobert Richter if (!nvec) { 1239ee2aad42SRobert Richter rc = -ENODEV; 1240ee2aad42SRobert Richter goto fail; 1241ee2aad42SRobert Richter } 1242ee2aad42SRobert Richter 1243ee2aad42SRobert Richter /* 1244ee2aad42SRobert Richter * There can be more than one vector (e.g. for error detection or 1245ee2aad42SRobert Richter * hdd hotplug). Only the first vector (entry.entry = 0) is used. 1246ee2aad42SRobert Richter */ 1247ee2aad42SRobert Richter rc = pci_enable_msix_exact(pdev, &entry, 1); 1248ee2aad42SRobert Richter if (rc < 0) 1249ee2aad42SRobert Richter goto fail; 1250ee2aad42SRobert Richter 1251ee2aad42SRobert Richter desc = msix_get_desc(pdev, 0); /* first entry */ 1252ee2aad42SRobert Richter if (!desc) { 1253ee2aad42SRobert Richter rc = -EINVAL; 1254ee2aad42SRobert Richter goto fail; 1255ee2aad42SRobert Richter } 1256ee2aad42SRobert Richter 1257ee2aad42SRobert Richter hpriv->irq = desc->irq; 1258ee2aad42SRobert Richter 1259ee2aad42SRobert Richter return 1; 1260ee2aad42SRobert Richter fail: 1261ee2aad42SRobert Richter dev_err(&pdev->dev, 1262ee2aad42SRobert Richter "failed to enable MSI-X with error %d, # of vectors: %d\n", 1263ee2aad42SRobert Richter rc, nvec); 1264ee2aad42SRobert Richter 1265ee2aad42SRobert Richter return rc; 1266ee2aad42SRobert Richter } 1267ee2aad42SRobert Richter 1268a1c82311SRobert Richter static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, 12697b92b4f6SAlexander Gordeev struct ahci_host_priv *hpriv) 12705ca72c4fSAlexander Gordeev { 1271ccf8f53cSAlexander Gordeev int rc, nvec; 12725ca72c4fSAlexander Gordeev 12737b92b4f6SAlexander Gordeev if (hpriv->flags & AHCI_HFLAG_NO_MSI) 1274a1c82311SRobert Richter return -ENODEV; 12757b92b4f6SAlexander Gordeev 1276fc061d96SAlexander Gordeev nvec = pci_msi_vec_count(pdev); 1277fc061d96SAlexander Gordeev if (nvec < 0) 1278a1c82311SRobert Richter return nvec; 12797b92b4f6SAlexander Gordeev 12805ca72c4fSAlexander Gordeev /* 12817b92b4f6SAlexander Gordeev * If number of MSIs is less than number of ports then Sharing Last 12827b92b4f6SAlexander Gordeev * Message mode could be enforced. In this case assume that advantage 12837b92b4f6SAlexander Gordeev * of multipe MSIs is negated and use single MSI mode instead. 12845ca72c4fSAlexander Gordeev */ 1285fc061d96SAlexander Gordeev if (nvec < n_ports) 12867b92b4f6SAlexander Gordeev goto single_msi; 12875ca72c4fSAlexander Gordeev 1288ccf8f53cSAlexander Gordeev rc = pci_enable_msi_exact(pdev, nvec); 1289ccf8f53cSAlexander Gordeev if (rc == -ENOSPC) 1290fc40363bSAlexander Gordeev goto single_msi; 1291a1c82311SRobert Richter if (rc < 0) 1292a1c82311SRobert Richter return rc; 1293ab0f9e78SAlexander Gordeev 1294ab0f9e78SAlexander Gordeev /* fallback to single MSI mode if the controller enforced MRSM mode */ 1295ab0f9e78SAlexander Gordeev if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) { 1296ab0f9e78SAlexander Gordeev pci_disable_msi(pdev); 1297ab0f9e78SAlexander Gordeev printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n"); 1298ab0f9e78SAlexander Gordeev goto single_msi; 1299ab0f9e78SAlexander Gordeev } 13007b92b4f6SAlexander Gordeev 1301c3ebd6a9SAlexander Gordeev if (nvec > 1) 1302c3ebd6a9SAlexander Gordeev hpriv->flags |= AHCI_HFLAG_MULTI_MSI; 1303c3ebd6a9SAlexander Gordeev 130421bfd1aaSRobert Richter goto out; 13057b92b4f6SAlexander Gordeev 13067b92b4f6SAlexander Gordeev single_msi: 130721bfd1aaSRobert Richter nvec = 1; 130821bfd1aaSRobert Richter 1309a1c82311SRobert Richter rc = pci_enable_msi(pdev); 1310a1c82311SRobert Richter if (rc < 0) 1311a1c82311SRobert Richter return rc; 131221bfd1aaSRobert Richter out: 131321bfd1aaSRobert Richter hpriv->irq = pdev->irq; 13147b92b4f6SAlexander Gordeev 131521bfd1aaSRobert Richter return nvec; 1316a1c82311SRobert Richter } 1317a1c82311SRobert Richter 1318a1c82311SRobert Richter static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, 1319a1c82311SRobert Richter struct ahci_host_priv *hpriv) 1320a1c82311SRobert Richter { 1321a1c82311SRobert Richter int nvec; 1322a1c82311SRobert Richter 1323a1c82311SRobert Richter nvec = ahci_init_msi(pdev, n_ports, hpriv); 1324a1c82311SRobert Richter if (nvec >= 0) 1325a1c82311SRobert Richter return nvec; 1326a1c82311SRobert Richter 1327ee2aad42SRobert Richter /* 1328ee2aad42SRobert Richter * Currently, MSI-X support only implements single IRQ mode and 1329ee2aad42SRobert Richter * exists for controllers which can't do other types of IRQ. Only 1330ee2aad42SRobert Richter * set it up if MSI fails. 1331ee2aad42SRobert Richter */ 1332ee2aad42SRobert Richter nvec = ahci_init_msix(pdev, n_ports, hpriv); 1333ee2aad42SRobert Richter if (nvec >= 0) 1334ee2aad42SRobert Richter return nvec; 1335ee2aad42SRobert Richter 1336a1c82311SRobert Richter /* lagacy intx interrupts */ 13375ca72c4fSAlexander Gordeev pci_intx(pdev, 1); 133821bfd1aaSRobert Richter hpriv->irq = pdev->irq; 1339a1c82311SRobert Richter 13405ca72c4fSAlexander Gordeev return 0; 13415ca72c4fSAlexander Gordeev } 13425ca72c4fSAlexander Gordeev 1343c6fd2807SJeff Garzik static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1344c6fd2807SJeff Garzik { 1345e297d99eSTejun Heo unsigned int board_id = ent->driver_data; 1346e297d99eSTejun Heo struct ata_port_info pi = ahci_port_info[board_id]; 13474447d351STejun Heo const struct ata_port_info *ppi[] = { &pi, NULL }; 134824dc5f33STejun Heo struct device *dev = &pdev->dev; 1349c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 13504447d351STejun Heo struct ata_host *host; 1351c3ebd6a9SAlexander Gordeev int n_ports, i, rc; 1352318893e1SAlessandro Rubini int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; 1353c6fd2807SJeff Garzik 1354c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1355c6fd2807SJeff Garzik 1356b429dd59SJustin P. Mattock WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1357c6fd2807SJeff Garzik 135806296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 1359c6fd2807SJeff Garzik 13605b66c829SAlan Cox /* The AHCI driver can only drive the SATA ports, the PATA driver 13615b66c829SAlan Cox can drive them all so if both drivers are selected make sure 13625b66c829SAlan Cox AHCI stays out of the way */ 13635b66c829SAlan Cox if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) 13645b66c829SAlan Cox return -ENODEV; 13655b66c829SAlan Cox 1366cb85696dSJames Laird /* Apple BIOS on MCP89 prevents us using AHCI */ 1367cb85696dSJames Laird if (is_mcp89_apple(pdev)) 1368cb85696dSJames Laird ahci_mcp89_apple_enable(pdev); 1369c6353b45STejun Heo 13707a02267eSMark Nelson /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode. 13717a02267eSMark Nelson * At the moment, we can only use the AHCI mode. Let the users know 13727a02267eSMark Nelson * that for SAS drives they're out of luck. 13737a02267eSMark Nelson */ 13747a02267eSMark Nelson if (pdev->vendor == PCI_VENDOR_ID_PROMISE) 1375a44fec1fSJoe Perches dev_info(&pdev->dev, 1376a44fec1fSJoe Perches "PDC42819 can only drive SATA devices with this driver\n"); 13777a02267eSMark Nelson 1378*b7ae128dSRobert Richter /* Some devices use non-standard BARs */ 1379318893e1SAlessandro Rubini if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) 1380318893e1SAlessandro Rubini ahci_pci_bar = AHCI_PCI_BAR_STA2X11; 13817f9c9f8eSHugh Daschbach else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) 13827f9c9f8eSHugh Daschbach ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; 1383*b7ae128dSRobert Richter else if (pdev->vendor == 0x177d && pdev->device == 0xa01c) 1384*b7ae128dSRobert Richter ahci_pci_bar = AHCI_PCI_BAR_CAVIUM; 1385318893e1SAlessandro Rubini 1386e6b7e41cSChuansheng Liu /* 1387e6b7e41cSChuansheng Liu * The JMicron chip 361/363 contains one SATA controller and one 1388e6b7e41cSChuansheng Liu * PATA controller,for powering on these both controllers, we must 1389e6b7e41cSChuansheng Liu * follow the sequence one by one, otherwise one of them can not be 1390e6b7e41cSChuansheng Liu * powered on successfully, so here we disable the async suspend 1391e6b7e41cSChuansheng Liu * method for these chips. 1392e6b7e41cSChuansheng Liu */ 1393e6b7e41cSChuansheng Liu if (pdev->vendor == PCI_VENDOR_ID_JMICRON && 1394e6b7e41cSChuansheng Liu (pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 || 1395e6b7e41cSChuansheng Liu pdev->device == PCI_DEVICE_ID_JMICRON_JMB361)) 1396e6b7e41cSChuansheng Liu device_disable_async_suspend(&pdev->dev); 1397e6b7e41cSChuansheng Liu 13984447d351STejun Heo /* acquire resources */ 139924dc5f33STejun Heo rc = pcim_enable_device(pdev); 1400c6fd2807SJeff Garzik if (rc) 1401c6fd2807SJeff Garzik return rc; 1402c6fd2807SJeff Garzik 1403c4f7792cSTejun Heo if (pdev->vendor == PCI_VENDOR_ID_INTEL && 1404c4f7792cSTejun Heo (pdev->device == 0x2652 || pdev->device == 0x2653)) { 1405c4f7792cSTejun Heo u8 map; 1406c4f7792cSTejun Heo 1407c4f7792cSTejun Heo /* ICH6s share the same PCI ID for both piix and ahci 1408c4f7792cSTejun Heo * modes. Enabling ahci mode while MAP indicates 1409c4f7792cSTejun Heo * combined mode is a bad idea. Yield to ata_piix. 1410c4f7792cSTejun Heo */ 1411c4f7792cSTejun Heo pci_read_config_byte(pdev, ICH_MAP, &map); 1412c4f7792cSTejun Heo if (map & 0x3) { 1413a44fec1fSJoe Perches dev_info(&pdev->dev, 1414a44fec1fSJoe Perches "controller is in combined mode, can't enable AHCI mode\n"); 1415c4f7792cSTejun Heo return -ENODEV; 1416c4f7792cSTejun Heo } 1417c4f7792cSTejun Heo } 1418c4f7792cSTejun Heo 14196fec8871SPaul Bolle /* AHCI controllers often implement SFF compatible interface. 14206fec8871SPaul Bolle * Grab all PCI BARs just in case. 14216fec8871SPaul Bolle */ 14226fec8871SPaul Bolle rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); 14236fec8871SPaul Bolle if (rc == -EBUSY) 14246fec8871SPaul Bolle pcim_pin_device(pdev); 14256fec8871SPaul Bolle if (rc) 14266fec8871SPaul Bolle return rc; 14276fec8871SPaul Bolle 142824dc5f33STejun Heo hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); 142924dc5f33STejun Heo if (!hpriv) 143024dc5f33STejun Heo return -ENOMEM; 1431417a1a6dSTejun Heo hpriv->flags |= (unsigned long)pi.private_data; 1432417a1a6dSTejun Heo 1433e297d99eSTejun Heo /* MCP65 revision A1 and A2 can't do MSI */ 1434e297d99eSTejun Heo if (board_id == board_ahci_mcp65 && 1435e297d99eSTejun Heo (pdev->revision == 0xa1 || pdev->revision == 0xa2)) 1436e297d99eSTejun Heo hpriv->flags |= AHCI_HFLAG_NO_MSI; 1437e297d99eSTejun Heo 1438e427fe04SShane Huang /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */ 1439e427fe04SShane Huang if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) 1440e427fe04SShane Huang hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; 1441e427fe04SShane Huang 14422fcad9d2STejun Heo /* only some SB600s can do 64bit DMA */ 14432fcad9d2STejun Heo if (ahci_sb600_enable_64bit(pdev)) 14442fcad9d2STejun Heo hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; 144558a09b38SShane Huang 1446318893e1SAlessandro Rubini hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; 1447d8993349SAnton Vorontsov 14480cf4a7d6SJacob Pan /* must set flag prior to save config in order to take effect */ 14490cf4a7d6SJacob Pan if (ahci_broken_devslp(pdev)) 14500cf4a7d6SJacob Pan hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; 14510cf4a7d6SJacob Pan 14524447d351STejun Heo /* save initial config */ 1453394d6e53SAnton Vorontsov ahci_pci_save_initial_config(pdev, hpriv); 1454c6fd2807SJeff Garzik 14554447d351STejun Heo /* prepare host */ 1456453d3131SRobert Hancock if (hpriv->cap & HOST_CAP_NCQ) { 1457453d3131SRobert Hancock pi.flags |= ATA_FLAG_NCQ; 145883f2b963STejun Heo /* 145983f2b963STejun Heo * Auto-activate optimization is supposed to be 146083f2b963STejun Heo * supported on all AHCI controllers indicating NCQ 146183f2b963STejun Heo * capability, but it seems to be broken on some 146283f2b963STejun Heo * chipsets including NVIDIAs. 146383f2b963STejun Heo */ 146483f2b963STejun Heo if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA)) 1465453d3131SRobert Hancock pi.flags |= ATA_FLAG_FPDMA_AA; 146640fb59e7SMarc Carino 146740fb59e7SMarc Carino /* 146840fb59e7SMarc Carino * All AHCI controllers should be forward-compatible 146940fb59e7SMarc Carino * with the new auxiliary field. This code should be 147040fb59e7SMarc Carino * conditionalized if any buggy AHCI controllers are 147140fb59e7SMarc Carino * encountered. 147240fb59e7SMarc Carino */ 147340fb59e7SMarc Carino pi.flags |= ATA_FLAG_FPDMA_AUX; 1474453d3131SRobert Hancock } 14754447d351STejun Heo 14767d50b60bSTejun Heo if (hpriv->cap & HOST_CAP_PMP) 14777d50b60bSTejun Heo pi.flags |= ATA_FLAG_PMP; 14787d50b60bSTejun Heo 14790cbb0e77SAnton Vorontsov ahci_set_em_messages(hpriv, &pi); 148018f7ba4cSKristen Carlson Accardi 14811fd68434SRafael J. Wysocki if (ahci_broken_system_poweroff(pdev)) { 14821fd68434SRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN; 14831fd68434SRafael J. Wysocki dev_info(&pdev->dev, 14841fd68434SRafael J. Wysocki "quirky BIOS, skipping spindown on poweroff\n"); 14851fd68434SRafael J. Wysocki } 14861fd68434SRafael J. Wysocki 14879b10ae86STejun Heo if (ahci_broken_suspend(pdev)) { 14889b10ae86STejun Heo hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; 1489a44fec1fSJoe Perches dev_warn(&pdev->dev, 14909b10ae86STejun Heo "BIOS update required for suspend/resume\n"); 14919b10ae86STejun Heo } 14929b10ae86STejun Heo 14935594639aSTejun Heo if (ahci_broken_online(pdev)) { 14945594639aSTejun Heo hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE; 14955594639aSTejun Heo dev_info(&pdev->dev, 14965594639aSTejun Heo "online status unreliable, applying workaround\n"); 14975594639aSTejun Heo } 14985594639aSTejun Heo 1499837f5f8fSTejun Heo /* CAP.NP sometimes indicate the index of the last enabled 1500837f5f8fSTejun Heo * port, at other times, that of the last possible port, so 1501837f5f8fSTejun Heo * determining the maximum port number requires looking at 1502837f5f8fSTejun Heo * both CAP.NP and port_map. 1503837f5f8fSTejun Heo */ 1504837f5f8fSTejun Heo n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); 1505837f5f8fSTejun Heo 1506837f5f8fSTejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 15074447d351STejun Heo if (!host) 15084447d351STejun Heo return -ENOMEM; 15094447d351STejun Heo host->private_data = hpriv; 15104447d351STejun Heo 151121bfd1aaSRobert Richter ahci_init_interrupts(pdev, n_ports, hpriv); 151221bfd1aaSRobert Richter 1513f3d7f23fSArjan van de Ven if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) 1514886ad09fSArjan van de Ven host->flags |= ATA_HOST_PARALLEL_SCAN; 1515f3d7f23fSArjan van de Ven else 1516d2782d96SJingoo Han dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); 1517886ad09fSArjan van de Ven 151818f7ba4cSKristen Carlson Accardi if (pi.flags & ATA_FLAG_EM) 151918f7ba4cSKristen Carlson Accardi ahci_reset_em(host); 152018f7ba4cSKristen Carlson Accardi 15214447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 15224447d351STejun Heo struct ata_port *ap = host->ports[i]; 15234447d351STejun Heo 1524318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); 1525318893e1SAlessandro Rubini ata_port_pbar_desc(ap, ahci_pci_bar, 1526cbcdd875STejun Heo 0x100 + ap->port_no * 0x80, "port"); 1527cbcdd875STejun Heo 152818f7ba4cSKristen Carlson Accardi /* set enclosure management message type */ 152918f7ba4cSKristen Carlson Accardi if (ap->flags & ATA_FLAG_EM) 1530008dbd61SHarry Zhang ap->em_message_type = hpriv->em_msg_type; 153118f7ba4cSKristen Carlson Accardi 153218f7ba4cSKristen Carlson Accardi 1533dab632e8SJeff Garzik /* disabled/not-implemented port */ 1534350756f6STejun Heo if (!(hpriv->port_map & (1 << i))) 1535dab632e8SJeff Garzik ap->ops = &ata_dummy_port_ops; 15364447d351STejun Heo } 1537c6fd2807SJeff Garzik 1538edc93052STejun Heo /* apply workaround for ASUS P5W DH Deluxe mainboard */ 1539edc93052STejun Heo ahci_p5wdh_workaround(host); 1540edc93052STejun Heo 1541f80ae7e4STejun Heo /* apply gtf filter quirk */ 1542f80ae7e4STejun Heo ahci_gtf_filter_workaround(host); 1543f80ae7e4STejun Heo 1544c6fd2807SJeff Garzik /* initialize adapter */ 15454447d351STejun Heo rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); 1546c6fd2807SJeff Garzik if (rc) 154724dc5f33STejun Heo return rc; 1548c6fd2807SJeff Garzik 15493303040dSAnton Vorontsov rc = ahci_pci_reset_controller(host); 15504447d351STejun Heo if (rc) 15514447d351STejun Heo return rc; 1552c6fd2807SJeff Garzik 1553781d6550SAnton Vorontsov ahci_pci_init_controller(host); 1554439fcaecSAnton Vorontsov ahci_pci_print_info(host); 1555c6fd2807SJeff Garzik 15564447d351STejun Heo pci_set_master(pdev); 15575ca72c4fSAlexander Gordeev 155821bfd1aaSRobert Richter return ahci_host_activate(host, &ahci_sht); 1559c6fd2807SJeff Garzik } 1560c6fd2807SJeff Garzik 15612fc75da0SAxel Lin module_pci_driver(ahci_pci_driver); 1562c6fd2807SJeff Garzik 1563c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1564c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1565c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1566c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1567c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1568