diff options
Diffstat (limited to 'drivers/ata/ahci.c')
| -rw-r--r-- | drivers/ata/ahci.c | 843 |
1 files changed, 557 insertions, 286 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 021ce46e2e57..7a7f88b3fa2b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * ahci.c - AHCI SATA support * @@ -7,29 +8,12 @@ * * Copyright 2004-2005 Red Hat, Inc. * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * * libata documentation is available via 'make {ps|pdf}docs', * as Documentation/driver-api/libata.rst * * AHCI hardware documentation: * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf - * */ #include <linux/kernel.h> @@ -42,7 +26,6 @@ #include <linux/device.h> #include <linux/dmi.h> #include <linux/gfp.h> -#include <linux/msi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_cmnd.h> #include <linux/libata.h> @@ -56,6 +39,7 @@ enum { AHCI_PCI_BAR_STA2X11 = 0, AHCI_PCI_BAR_CAVIUM = 0, + AHCI_PCI_BAR_LOONGSON = 0, AHCI_PCI_BAR_ENMOTUS = 2, AHCI_PCI_BAR_CAVIUM_GEN5 = 4, AHCI_PCI_BAR_STANDARD = 5, @@ -64,14 +48,25 @@ enum { enum board_ids { /* board IDs by feature in alphabetical order */ board_ahci, + board_ahci_43bit_dma, board_ahci_ign_iferr, - board_ahci_mobile, - board_ahci_nomsi, - board_ahci_noncq, - board_ahci_nosntf, + board_ahci_no_debounce_delay, + board_ahci_no_msi, + /* + * board_ahci_pcs_quirk is for legacy Intel platforms. + * Modern Intel platforms should use board_ahci instead. + * (Some modern Intel platforms might have been added with + * board_ahci_pcs_quirk, however, we cannot change them to board_ahci + * without testing that the platform actually works without the quirk.) + */ + board_ahci_pcs_quirk, + board_ahci_pcs_quirk_no_devslp, + board_ahci_pcs_quirk_no_sntf, board_ahci_yes_fbs, + board_ahci_yes_fbs_atapi_dma, /* board IDs for specific chipsets in alphabetical order */ + board_ahci_al, board_ahci_avn, board_ahci_mcp65, board_ahci_mcp77, @@ -90,6 +85,8 @@ enum board_ids { static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static void ahci_remove_one(struct pci_dev *dev); +static void ahci_shutdown_one(struct pci_dev *dev); +static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv); static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, @@ -107,23 +104,23 @@ static int ahci_pci_device_resume(struct device *dev); #endif #endif /* CONFIG_PM */ -static struct scsi_host_template ahci_sht = { +static const struct scsi_host_template ahci_sht = { AHCI_SHT("ahci"), }; static struct ata_port_operations ahci_vt8251_ops = { .inherits = &ahci_ops, - .hardreset = ahci_vt8251_hardreset, + .reset.hardreset = ahci_vt8251_hardreset, }; static struct ata_port_operations ahci_p5wdh_ops = { .inherits = &ahci_ops, - .hardreset = ahci_p5wdh_hardreset, + .reset.hardreset = ahci_p5wdh_hardreset, }; static struct ata_port_operations ahci_avn_ops = { .inherits = &ahci_ops, - .hardreset = ahci_avn_hardreset, + .reset.hardreset = ahci_avn_hardreset, }; static const struct ata_port_info ahci_port_info[] = { @@ -134,6 +131,13 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, + [board_ahci_43bit_dma] = { + AHCI_HFLAGS (AHCI_HFLAG_43BIT_ONLY), + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, [board_ahci_ign_iferr] = { AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), .flags = AHCI_FLAG_COMMON, @@ -141,29 +145,38 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, - [board_ahci_mobile] = { - AHCI_HFLAGS (AHCI_HFLAG_IS_MOBILE), + [board_ahci_no_debounce_delay] = { .flags = AHCI_FLAG_COMMON, + .link_flags = ATA_LFLAG_NO_DEBOUNCE_DELAY, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, - [board_ahci_nomsi] = { + [board_ahci_no_msi] = { AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), .flags = AHCI_FLAG_COMMON, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, - [board_ahci_noncq] = { - AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), + [board_ahci_pcs_quirk] = { + AHCI_HFLAGS (AHCI_HFLAG_INTEL_PCS_QUIRK), + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, + [board_ahci_pcs_quirk_no_devslp] = { + AHCI_HFLAGS (AHCI_HFLAG_INTEL_PCS_QUIRK | + AHCI_HFLAG_NO_DEVSLP), .flags = AHCI_FLAG_COMMON, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, - [board_ahci_nosntf] = { - AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), + [board_ahci_pcs_quirk_no_sntf] = { + AHCI_HFLAGS (AHCI_HFLAG_INTEL_PCS_QUIRK | + AHCI_HFLAG_NO_SNTF), .flags = AHCI_FLAG_COMMON, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, @@ -176,8 +189,24 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, + [board_ahci_yes_fbs_atapi_dma] = { + AHCI_HFLAGS (AHCI_HFLAG_YES_FBS | + AHCI_HFLAG_ATAPI_DMA_QUIRK), + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, /* by chipsets */ + [board_ahci_al] = { + AHCI_HFLAGS (AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_MSI), + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, [board_ahci_avn] = { + AHCI_HFLAGS (AHCI_HFLAG_INTEL_PCS_QUIRK), .flags = AHCI_FLAG_COMMON, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, @@ -240,46 +269,47 @@ static const struct ata_port_info ahci_port_info[] = { static const struct pci_device_id ahci_pci_tbl[] = { /* Intel */ - { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ - { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ - { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ - { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ - { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ + { PCI_VDEVICE(INTEL, 0x06d6), board_ahci_pcs_quirk }, /* Comet Lake PCH-H RAID */ + { PCI_VDEVICE(INTEL, 0x2652), board_ahci_pcs_quirk }, /* ICH6 */ + { PCI_VDEVICE(INTEL, 0x2653), board_ahci_pcs_quirk }, /* ICH6M */ + { PCI_VDEVICE(INTEL, 0x27c1), board_ahci_pcs_quirk }, /* ICH7 */ + { PCI_VDEVICE(INTEL, 0x27c5), board_ahci_pcs_quirk }, /* ICH7M */ + { PCI_VDEVICE(INTEL, 0x27c3), board_ahci_pcs_quirk }, /* ICH7R */ { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ - { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ - { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ - { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ - { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ - { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ - { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ - { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ - { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ - { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ - { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ - { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ - { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ - { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ - { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ - { PCI_VDEVICE(INTEL, 0x2929), board_ahci_mobile }, /* ICH9M */ - { PCI_VDEVICE(INTEL, 0x292a), board_ahci_mobile }, /* ICH9M */ - { PCI_VDEVICE(INTEL, 0x292b), board_ahci_mobile }, /* ICH9M */ - { PCI_VDEVICE(INTEL, 0x292c), board_ahci_mobile }, /* ICH9M */ - { PCI_VDEVICE(INTEL, 0x292f), board_ahci_mobile }, /* ICH9M */ - { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ - { PCI_VDEVICE(INTEL, 0x294e), board_ahci_mobile }, /* ICH9M */ - { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */ - { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ - { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ - { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ - { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ - { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */ - { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ - { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ - { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ - { PCI_VDEVICE(INTEL, 0x3b29), board_ahci_mobile }, /* PCH M AHCI */ - { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ - { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_mobile }, /* PCH M RAID */ - { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ + { PCI_VDEVICE(INTEL, 0x2681), board_ahci_pcs_quirk }, /* ESB2 */ + { PCI_VDEVICE(INTEL, 0x2682), board_ahci_pcs_quirk }, /* ESB2 */ + { PCI_VDEVICE(INTEL, 0x2683), board_ahci_pcs_quirk }, /* ESB2 */ + { PCI_VDEVICE(INTEL, 0x27c6), board_ahci_pcs_quirk }, /* ICH7-M DH */ + { PCI_VDEVICE(INTEL, 0x2821), board_ahci_pcs_quirk }, /* ICH8 */ + { PCI_VDEVICE(INTEL, 0x2822), board_ahci_pcs_quirk_no_sntf }, /* ICH8/Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0x2824), board_ahci_pcs_quirk }, /* ICH8 */ + { PCI_VDEVICE(INTEL, 0x2829), board_ahci_pcs_quirk }, /* ICH8M */ + { PCI_VDEVICE(INTEL, 0x282a), board_ahci_pcs_quirk }, /* ICH8M */ + { PCI_VDEVICE(INTEL, 0x2922), board_ahci_pcs_quirk }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2923), board_ahci_pcs_quirk }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2924), board_ahci_pcs_quirk }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2925), board_ahci_pcs_quirk }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2927), board_ahci_pcs_quirk }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2929), board_ahci_pcs_quirk }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x292a), board_ahci_pcs_quirk }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x292b), board_ahci_pcs_quirk }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x292c), board_ahci_pcs_quirk }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x292f), board_ahci_pcs_quirk }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x294d), board_ahci_pcs_quirk }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x294e), board_ahci_pcs_quirk }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x502a), board_ahci_pcs_quirk }, /* Tolapai */ + { PCI_VDEVICE(INTEL, 0x502b), board_ahci_pcs_quirk }, /* Tolapai */ + { PCI_VDEVICE(INTEL, 0x3a05), board_ahci_pcs_quirk }, /* ICH10 */ + { PCI_VDEVICE(INTEL, 0x3a22), board_ahci_pcs_quirk }, /* ICH10 */ + { PCI_VDEVICE(INTEL, 0x3a25), board_ahci_pcs_quirk }, /* ICH10 */ + { PCI_VDEVICE(INTEL, 0x3b22), board_ahci_pcs_quirk }, /* PCH AHCI */ + { PCI_VDEVICE(INTEL, 0x3b23), board_ahci_pcs_quirk }, /* PCH AHCI */ + { PCI_VDEVICE(INTEL, 0x3b24), board_ahci_pcs_quirk }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b25), board_ahci_pcs_quirk }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b29), board_ahci_pcs_quirk }, /* PCH M AHCI */ + { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci_pcs_quirk }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_pcs_quirk }, /* PCH M RAID */ + { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci_pcs_quirk }, /* PCH AHCI */ { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */ { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */ { PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */ @@ -300,49 +330,48 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */ { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */ { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ - { PCI_VDEVICE(INTEL, 0x1c03), board_ahci_mobile }, /* CPT M AHCI */ - { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ - { PCI_VDEVICE(INTEL, 0x1c05), board_ahci_mobile }, /* CPT M RAID */ - { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ - { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ - { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ - { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ - { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ - { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ - { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ - { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ - { PCI_VDEVICE(INTEL, 0x1e03), board_ahci_mobile }, /* Panther M AHCI */ - { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ - { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ - { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ - { PCI_VDEVICE(INTEL, 0x1e07), board_ahci_mobile }, /* Panther M RAID */ - { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ - { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ - { PCI_VDEVICE(INTEL, 0x8c03), board_ahci_mobile }, /* Lynx M AHCI */ - { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ - { PCI_VDEVICE(INTEL, 0x8c05), board_ahci_mobile }, /* Lynx M RAID */ - { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ - { PCI_VDEVICE(INTEL, 0x8c07), board_ahci_mobile }, /* Lynx M RAID */ - { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ - { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_mobile }, /* Lynx M RAID */ - { PCI_VDEVICE(INTEL, 0x9c02), board_ahci_mobile }, /* Lynx LP AHCI */ - { PCI_VDEVICE(INTEL, 0x9c03), board_ahci_mobile }, /* Lynx LP AHCI */ - { PCI_VDEVICE(INTEL, 0x9c04), board_ahci_mobile }, /* Lynx LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c05), board_ahci_mobile }, /* Lynx LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c06), board_ahci_mobile }, /* Lynx LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c07), board_ahci_mobile }, /* Lynx LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_mobile }, /* Lynx LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_mobile }, /* Lynx LP RAID */ - { PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_mobile }, /* Cannon Lake PCH-LP AHCI */ - { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ - { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ - { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ - { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ - { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ - { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ - { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ - { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1c02), board_ahci_pcs_quirk }, /* CPT AHCI */ + { PCI_VDEVICE(INTEL, 0x1c03), board_ahci_pcs_quirk }, /* CPT M AHCI */ + { PCI_VDEVICE(INTEL, 0x1c04), board_ahci_pcs_quirk }, /* CPT RAID */ + { PCI_VDEVICE(INTEL, 0x1c05), board_ahci_pcs_quirk }, /* CPT M RAID */ + { PCI_VDEVICE(INTEL, 0x1c06), board_ahci_pcs_quirk }, /* CPT RAID */ + { PCI_VDEVICE(INTEL, 0x1c07), board_ahci_pcs_quirk }, /* CPT RAID */ + { PCI_VDEVICE(INTEL, 0x1d02), board_ahci_pcs_quirk }, /* PBG AHCI */ + { PCI_VDEVICE(INTEL, 0x1d04), board_ahci_pcs_quirk }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x1d06), board_ahci_pcs_quirk }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x2323), board_ahci_pcs_quirk }, /* DH89xxCC AHCI */ + { PCI_VDEVICE(INTEL, 0x1e02), board_ahci_pcs_quirk }, /* Panther Point AHCI */ + { PCI_VDEVICE(INTEL, 0x1e03), board_ahci_pcs_quirk }, /* Panther M AHCI */ + { PCI_VDEVICE(INTEL, 0x1e04), board_ahci_pcs_quirk }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e05), board_ahci_pcs_quirk }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e06), board_ahci_pcs_quirk }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e07), board_ahci_pcs_quirk }, /* Panther M RAID */ + { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci_pcs_quirk }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x8c02), board_ahci_pcs_quirk }, /* Lynx Point AHCI */ + { PCI_VDEVICE(INTEL, 0x8c03), board_ahci_pcs_quirk }, /* Lynx M AHCI */ + { PCI_VDEVICE(INTEL, 0x8c04), board_ahci_pcs_quirk }, /* Lynx Point RAID */ + { PCI_VDEVICE(INTEL, 0x8c05), board_ahci_pcs_quirk }, /* Lynx M RAID */ + { PCI_VDEVICE(INTEL, 0x8c06), board_ahci_pcs_quirk }, /* Lynx Point RAID */ + { PCI_VDEVICE(INTEL, 0x8c07), board_ahci_pcs_quirk }, /* Lynx M RAID */ + { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci_pcs_quirk }, /* Lynx Point RAID */ + { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci_pcs_quirk }, /* Lynx M RAID */ + { PCI_VDEVICE(INTEL, 0x9c02), board_ahci_pcs_quirk }, /* Lynx LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c03), board_ahci_pcs_quirk }, /* Lynx LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c04), board_ahci_pcs_quirk }, /* Lynx LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c05), board_ahci_pcs_quirk }, /* Lynx LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c06), board_ahci_pcs_quirk }, /* Lynx LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c07), board_ahci_pcs_quirk }, /* Lynx LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_pcs_quirk }, /* Lynx LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_pcs_quirk }, /* Lynx LP RAID */ + { PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_pcs_quirk }, /* Cannon Lake PCH-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x1f22), board_ahci_pcs_quirk }, /* Avoton AHCI */ + { PCI_VDEVICE(INTEL, 0x1f23), board_ahci_pcs_quirk }, /* Avoton AHCI */ + { PCI_VDEVICE(INTEL, 0x1f24), board_ahci_pcs_quirk }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f25), board_ahci_pcs_quirk }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f26), board_ahci_pcs_quirk }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f27), board_ahci_pcs_quirk }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci_pcs_quirk }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci_pcs_quirk }, /* Avoton RAID */ { PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */ { PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */ { PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */ @@ -351,56 +380,64 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */ { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */ { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */ - { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ - { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ - { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ - { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ - { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ - { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ - { PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ - { PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ - { PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ - { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ - { PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ - { PCI_VDEVICE(INTEL, 0x9c83), board_ahci_mobile }, /* Wildcat LP AHCI */ - { PCI_VDEVICE(INTEL, 0x9c85), board_ahci_mobile }, /* Wildcat LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c87), board_ahci_mobile }, /* Wildcat LP RAID */ - { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_mobile }, /* Wildcat LP RAID */ - { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ - { PCI_VDEVICE(INTEL, 0x8c83), board_ahci_mobile }, /* 9 Series M AHCI */ - { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ - { PCI_VDEVICE(INTEL, 0x8c85), board_ahci_mobile }, /* 9 Series M RAID */ - { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ - { PCI_VDEVICE(INTEL, 0x8c87), board_ahci_mobile }, /* 9 Series M RAID */ - { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ - { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_mobile }, /* 9 Series M RAID */ - { PCI_VDEVICE(INTEL, 0x9d03), board_ahci_mobile }, /* Sunrise LP AHCI */ - { PCI_VDEVICE(INTEL, 0x9d05), board_ahci_mobile }, /* Sunrise LP RAID */ - { PCI_VDEVICE(INTEL, 0x9d07), board_ahci_mobile }, /* Sunrise LP RAID */ - { PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */ - { PCI_VDEVICE(INTEL, 0xa103), board_ahci_mobile }, /* Sunrise M AHCI */ - { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ - { PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */ - { PCI_VDEVICE(INTEL, 0xa107), board_ahci_mobile }, /* Sunrise M RAID */ - { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ - { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/ - { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/ - { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/ - { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/ - { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/ - { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/ - { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/ - { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/ - { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/ - { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/ - { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ - { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ - { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */ - { PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */ - { PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */ - { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */ - { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */ - { PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */ + { PCI_VDEVICE(INTEL, 0x2823), board_ahci_pcs_quirk }, /* Wellsburg/Lewisburg AHCI*/ + { PCI_VDEVICE(INTEL, 0x2826), board_ahci_pcs_quirk }, /* *burg SATA0 'RAID' */ + { PCI_VDEVICE(INTEL, 0x2827), board_ahci_pcs_quirk }, /* *burg SATA1 'RAID' */ + { PCI_VDEVICE(INTEL, 0x282f), board_ahci_pcs_quirk }, /* *burg SATA2 'RAID' */ + { PCI_VDEVICE(INTEL, 0x43d4), board_ahci_pcs_quirk }, /* Rocket Lake PCH-H RAID */ + { PCI_VDEVICE(INTEL, 0x43d5), board_ahci_pcs_quirk }, /* Rocket Lake PCH-H RAID */ + { PCI_VDEVICE(INTEL, 0x43d6), board_ahci_pcs_quirk }, /* Rocket Lake PCH-H RAID */ + { PCI_VDEVICE(INTEL, 0x43d7), board_ahci_pcs_quirk }, /* Rocket Lake PCH-H RAID */ + { PCI_VDEVICE(INTEL, 0x8d02), board_ahci_pcs_quirk }, /* Wellsburg AHCI */ + { PCI_VDEVICE(INTEL, 0x8d04), board_ahci_pcs_quirk }, /* Wellsburg RAID */ + { PCI_VDEVICE(INTEL, 0x8d06), board_ahci_pcs_quirk }, /* Wellsburg RAID */ + { PCI_VDEVICE(INTEL, 0x8d0e), board_ahci_pcs_quirk }, /* Wellsburg RAID */ + { PCI_VDEVICE(INTEL, 0x8d62), board_ahci_pcs_quirk }, /* Wellsburg AHCI */ + { PCI_VDEVICE(INTEL, 0x8d64), board_ahci_pcs_quirk }, /* Wellsburg RAID */ + { PCI_VDEVICE(INTEL, 0x8d66), board_ahci_pcs_quirk }, /* Wellsburg RAID */ + { PCI_VDEVICE(INTEL, 0x8d6e), board_ahci_pcs_quirk }, /* Wellsburg RAID */ + { PCI_VDEVICE(INTEL, 0x23a3), board_ahci_pcs_quirk }, /* Coleto Creek AHCI */ + { PCI_VDEVICE(INTEL, 0x9c83), board_ahci_pcs_quirk }, /* Wildcat LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c85), board_ahci_pcs_quirk }, /* Wildcat LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c87), board_ahci_pcs_quirk }, /* Wildcat LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci_pcs_quirk }, /* Wildcat LP RAID */ + { PCI_VDEVICE(INTEL, 0x8c82), board_ahci_pcs_quirk }, /* 9 Series AHCI */ + { PCI_VDEVICE(INTEL, 0x8c83), board_ahci_pcs_quirk }, /* 9 Series M AHCI */ + { PCI_VDEVICE(INTEL, 0x8c84), board_ahci_pcs_quirk }, /* 9 Series RAID */ + { PCI_VDEVICE(INTEL, 0x8c85), board_ahci_pcs_quirk }, /* 9 Series M RAID */ + { PCI_VDEVICE(INTEL, 0x8c86), board_ahci_pcs_quirk }, /* 9 Series RAID */ + { PCI_VDEVICE(INTEL, 0x8c87), board_ahci_pcs_quirk }, /* 9 Series M RAID */ + { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci_pcs_quirk }, /* 9 Series RAID */ + { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci_pcs_quirk }, /* 9 Series M RAID */ + { PCI_VDEVICE(INTEL, 0x9d03), board_ahci_pcs_quirk }, /* Sunrise LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9d05), board_ahci_pcs_quirk }, /* Sunrise LP RAID */ + { PCI_VDEVICE(INTEL, 0x9d07), board_ahci_pcs_quirk }, /* Sunrise LP RAID */ + { PCI_VDEVICE(INTEL, 0xa102), board_ahci_pcs_quirk }, /* Sunrise Point-H AHCI */ + { PCI_VDEVICE(INTEL, 0xa103), board_ahci_pcs_quirk }, /* Sunrise M AHCI */ + { PCI_VDEVICE(INTEL, 0xa105), board_ahci_pcs_quirk }, /* Sunrise Point-H RAID */ + { PCI_VDEVICE(INTEL, 0xa106), board_ahci_pcs_quirk }, /* Sunrise Point-H RAID */ + { PCI_VDEVICE(INTEL, 0xa107), board_ahci_pcs_quirk }, /* Sunrise M RAID */ + { PCI_VDEVICE(INTEL, 0xa10f), board_ahci_pcs_quirk }, /* Sunrise Point-H RAID */ + { PCI_VDEVICE(INTEL, 0xa182), board_ahci_pcs_quirk }, /* Lewisburg AHCI*/ + { PCI_VDEVICE(INTEL, 0xa186), board_ahci_pcs_quirk }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci_pcs_quirk }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci_pcs_quirk }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa202), board_ahci_pcs_quirk }, /* Lewisburg AHCI*/ + { PCI_VDEVICE(INTEL, 0xa206), board_ahci_pcs_quirk }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa252), board_ahci_pcs_quirk }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa256), board_ahci_pcs_quirk }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa356), board_ahci_pcs_quirk }, /* Cannon Lake PCH-H RAID */ + { PCI_VDEVICE(INTEL, 0x06d7), board_ahci_pcs_quirk }, /* Comet Lake-H RAID */ + { PCI_VDEVICE(INTEL, 0xa386), board_ahci_pcs_quirk }, /* Comet Lake PCH-V RAID */ + { PCI_VDEVICE(INTEL, 0x0f22), board_ahci_pcs_quirk }, /* Bay Trail AHCI */ + { PCI_VDEVICE(INTEL, 0x0f23), board_ahci_pcs_quirk_no_devslp }, /* Bay Trail AHCI */ + { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_pcs_quirk }, /* Cherry Tr. AHCI */ + { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_pcs_quirk }, /* ApolloLake AHCI */ + { PCI_VDEVICE(INTEL, 0x34d3), board_ahci_pcs_quirk }, /* Ice Lake LP AHCI */ + { PCI_VDEVICE(INTEL, 0x02d3), board_ahci_pcs_quirk }, /* Comet Lake PCH-U AHCI */ + { PCI_VDEVICE(INTEL, 0x02d7), board_ahci_pcs_quirk }, /* Comet Lake PCH RAID */ + /* Elkhart Lake IDs 0x4b60 & 0x4b62 https://sata-io.org/product/8803 not tested yet */ + { PCI_VDEVICE(INTEL, 0x4b63), board_ahci_pcs_quirk }, /* Elkhart Lake AHCI */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -419,13 +456,24 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb700 }, /* ATI SB700/800 */ { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */ + /* Amazon's Annapurna Labs support */ + { PCI_DEVICE(PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031), + .class = PCI_CLASS_STORAGE_SATA_AHCI, + .class_mask = 0xffffff, + board_ahci_al }, /* AMD */ { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ + { PCI_VDEVICE(AMD, 0x7801), board_ahci_no_debounce_delay }, /* AMD Hudson-2 (AHCI mode) */ { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ + { PCI_VDEVICE(AMD, 0x7901), board_ahci }, /* AMD Green Sardine */ /* AMD is using RAID class only for ahci controllers */ { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, + /* Dell S140/S150 */ + { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_SUBVENDOR_ID_DELL, PCI_ANY_ID, + PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci_pcs_quirk }, + /* VIA */ { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ { PCI_VDEVICE(VIA, 0x6287), board_ahci_vt8251 }, /* VIA VT8251 */ @@ -550,8 +598,12 @@ static const struct pci_device_id ahci_pci_tbl[] = { .driver_data = board_ahci_yes_fbs }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), .driver_data = board_ahci_yes_fbs }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9215), + .driver_data = board_ahci_yes_fbs_atapi_dma }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), .driver_data = board_ahci_yes_fbs }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9235), + .driver_data = board_ahci_no_debounce_delay }, { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */ .driver_data = board_ahci_yes_fbs }, { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */ @@ -561,24 +613,33 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ - /* Asmedia */ - { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ - { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ - { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ - { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ - { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */ - { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */ + /* ASMedia */ + { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci_43bit_dma }, /* ASM1060 */ + { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci_43bit_dma }, /* ASM1060 */ + { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci_43bit_dma }, /* ASM1061 */ + { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci_43bit_dma }, /* ASM1061/1062 */ + { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci_43bit_dma }, /* ASM1061R */ + { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci_43bit_dma }, /* ASM1062R */ + { PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci_43bit_dma }, /* ASM1062+JMB575 */ + { PCI_VDEVICE(ASMEDIA, 0x1062), board_ahci }, /* ASM1062A */ + { PCI_VDEVICE(ASMEDIA, 0x1064), board_ahci }, /* ASM1064 */ + { PCI_VDEVICE(ASMEDIA, 0x1164), board_ahci }, /* ASM1164 */ + { PCI_VDEVICE(ASMEDIA, 0x1165), board_ahci }, /* ASM1165 */ + { PCI_VDEVICE(ASMEDIA, 0x1166), board_ahci }, /* ASM1166 */ /* * Samsung SSDs found on some macbooks. NCQ times out if MSI is * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 */ - { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, - { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, + { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_no_msi }, + { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_no_msi }, /* Enmotus */ { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, + /* Loongson */ + { PCI_VDEVICE(LOONGSON, 0x7a08), board_ahci }, + /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, @@ -597,6 +658,7 @@ static struct pci_driver ahci_pci_driver = { .id_table = ahci_pci_tbl, .probe = ahci_init_one, .remove = ahci_remove_one, + .shutdown = ahci_shutdown_one, .driver = { .pm = &ahci_pci_pm_ops, }, @@ -612,14 +674,109 @@ MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); static int mobile_lpm_policy = -1; module_param(mobile_lpm_policy, int, 0644); -MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); +MODULE_PARM_DESC(mobile_lpm_policy, + "Default LPM policy. Despite its name, this parameter applies " + "to all chipsets, including desktop and server chipsets"); + +static char *ahci_mask_port_map; +module_param_named(mask_port_map, ahci_mask_port_map, charp, 0444); +MODULE_PARM_DESC(mask_port_map, + "32-bits port map masks to ignore controllers ports. " + "Valid values are: " + "\"<mask>\" to apply the same mask to all AHCI controller " + "devices, and \"<pci_dev>=<mask>,<pci_dev>=<mask>,...\" to " + "specify different masks for the controllers specified, " + "where <pci_dev> is the PCI ID of an AHCI controller in the " + "form \"domain:bus:dev.func\""); + +static char *ahci_mask_port_ext; +module_param_named(mask_port_ext, ahci_mask_port_ext, charp, 0444); +MODULE_PARM_DESC(mask_port_ext, + "32-bits mask to ignore the external/hotplug capability of ports. " + "Valid values are: " + "\"<mask>\" to apply the same mask to all AHCI controller " + "devices, and \"<pci_dev>=<mask>,<pci_dev>=<mask>,...\" to " + "specify different masks for the controllers specified, " + "where <pci_dev> is the PCI ID of an AHCI controller in the " + "form \"domain:bus:dev.func\""); + +static u32 ahci_port_mask(struct device *dev, char *mask_s) +{ + unsigned int mask; + + if (kstrtouint(mask_s, 0, &mask)) { + dev_err(dev, "Invalid port map mask\n"); + return 0; + } + + return mask; +} + +static u32 ahci_get_port_mask(struct device *dev, char *mask_p) +{ + char *param, *end, *str, *mask_s; + char *name; + u32 mask = 0; + + if (!mask_p || !strlen(mask_p)) + return 0; + + str = kstrdup(mask_p, GFP_KERNEL); + if (!str) + return 0; + + /* Handle single mask case */ + if (!strchr(str, '=')) { + mask = ahci_port_mask(dev, str); + goto free; + } + + /* + * Mask list case: parse the parameter to get the mask only if + * the device name matches. + */ + param = str; + end = param + strlen(param); + while (param && param < end && *param) { + name = param; + param = strchr(name, '='); + if (!param) + break; + + *param = '\0'; + param++; + if (param >= end) + break; + + if (strcmp(dev_name(dev), name) != 0) { + param = strchr(param, ','); + if (param) + param++; + continue; + } + + mask_s = param; + param = strchr(mask_s, ','); + if (param) { + *param = '\0'; + param++; + } + + mask = ahci_port_mask(dev, mask_s); + } + +free: + kfree(str); + + return mask; +} static void ahci_pci_save_initial_config(struct pci_dev *pdev, struct ahci_host_priv *hpriv) { if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { dev_info(&pdev->dev, "JMB361 has only one port\n"); - hpriv->force_port_map = 1; + hpriv->saved_port_map = 1; } /* @@ -636,29 +793,30 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev, "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); } + /* Handle port map masks passed as module parameter. */ + hpriv->mask_port_map = + ahci_get_port_mask(&pdev->dev, ahci_mask_port_map); + hpriv->mask_port_ext = + ahci_get_port_mask(&pdev->dev, ahci_mask_port_ext); + ahci_save_initial_config(&pdev->dev, hpriv); } static int ahci_pci_reset_controller(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); + struct ahci_host_priv *hpriv = host->private_data; int rc; rc = ahci_reset_controller(host); if (rc) return rc; - if (pdev->vendor == PCI_VENDOR_ID_INTEL) { - struct ahci_host_priv *hpriv = host->private_data; - u16 tmp16; - - /* configure PCS */ - pci_read_config_word(pdev, 0x92, &tmp16); - if ((tmp16 & hpriv->port_map) != hpriv->port_map) { - tmp16 |= hpriv->port_map; - pci_write_config_word(pdev, 0x92, tmp16); - } - } + /* + * If platform firmware failed to enable ports, try to enable + * them here. + */ + ahci_intel_pcs_quirk(pdev, hpriv); return 0; } @@ -676,13 +834,13 @@ static void ahci_pci_init_controller(struct ata_host *host) mv = 2; else mv = 4; - port_mmio = __ahci_port_base(host, mv); + port_mmio = __ahci_port_base(hpriv, mv); writel(0, port_mmio + PORT_IRQ_MASK); /* clear port IRQ */ tmp = readl(port_mmio + PORT_IRQ_STAT); - VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); + dev_dbg(&pdev->dev, "PORT_IRQ_STAT 0x%x\n", tmp); if (tmp) writel(tmp, port_mmio + PORT_IRQ_STAT); } @@ -698,8 +856,6 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, bool online; int rc; - DPRINTK("ENTER\n"); - hpriv->stop_engine(ap); rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), @@ -707,8 +863,6 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, hpriv->start_engine(ap); - DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); - /* vt8251 doesn't clear BSY on signature FIS reception, * request follow-up softreset. */ @@ -730,7 +884,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, /* clear D2H reception area to properly wait for D2H FIS */ ata_tf_init(link->device, &tf); - tf.command = ATA_BUSY; + tf.status = ATA_BUSY; ata_tf_to_fis(&tf, 0, 0, d2h_fis); rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), @@ -778,7 +932,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { - const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); + const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context); struct ata_port *ap = link->ap; struct ahci_port_priv *pp = ap->private_data; struct ahci_host_priv *hpriv = ap->host->private_data; @@ -788,8 +942,6 @@ static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, bool online; int rc, i; - DPRINTK("ENTER\n"); - hpriv->stop_engine(ap); for (i = 0; i < 2; i++) { @@ -801,7 +953,7 @@ static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, /* clear D2H reception area to properly wait for D2H FIS */ ata_tf_init(link->device, &tf); - tf.command = ATA_BUSY; + tf.status = ATA_BUSY; ata_tf_to_fis(&tf, 0, 0, d2h_fis); rc = sata_link_hardreset(link, timing, deadline, &online, @@ -811,8 +963,7 @@ static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, (sstatus & 0xf) != 1) break; - ata_link_printk(link, KERN_INFO, "avn bounce port%d\n", - port); + ata_link_info(link, "avn bounce port%d\n", port); pci_read_config_word(pdev, 0x92, &val); val &= ~(1 << port); @@ -828,7 +979,6 @@ static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, if (online) *class = ahci_dev_classify(ap); - DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); return rc; } @@ -886,7 +1036,8 @@ static int ahci_pci_device_suspend(struct device *dev) } ahci_pci_disable_interrupts(host); - return ata_host_suspend(host, PMSG_SUSPEND); + ata_host_suspend(host, PMSG_SUSPEND); + return 0; } static int ahci_pci_device_resume(struct device *dev) @@ -915,42 +1066,34 @@ static int ahci_pci_device_resume(struct device *dev) #endif /* CONFIG_PM */ -static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) +static int ahci_configure_dma_masks(struct pci_dev *pdev, + struct ahci_host_priv *hpriv) { + int dma_bits; int rc; + if (hpriv->cap & HOST_CAP_64) { + dma_bits = 64; + if (hpriv->flags & AHCI_HFLAG_43BIT_ONLY) + dma_bits = 43; + } else { + dma_bits = 32; + } + /* * If the device fixup already set the dma_mask to some non-standard * value, don't extend it here. This happens on STA2X11, for example. + * + * XXX: manipulating the DMA mask from platform code is completely + * bogus, platform code should use dev->bus_dma_limit instead.. */ if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) return 0; - if (using_dac && - !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (rc) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "64-bit DMA enable failed\n"); - return rc; - } - } - } else { - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, "32-bit DMA enable failed\n"); - return rc; - } - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "32-bit consistent DMA enable failed\n"); - return rc; - } - } - return 0; + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits)); + if (rc) + dev_err(&pdev->dev, "DMA enable failed\n"); + return rc; } static void ahci_pci_print_info(struct ata_host *host) @@ -1254,7 +1397,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev) * V1.03 is known to be broken. V3.04 is known to * work. Between, there are V1.06, V2.06 and V3.03 * that we don't have much idea about. For now, - * blacklist anything older than V3.04. + * assume that anything older than V3.04 is broken. * * http://bugzilla.kernel.org/show_bug.cgi?id=15104 */ @@ -1283,8 +1426,15 @@ static bool ahci_broken_suspend(struct pci_dev *pdev) static bool ahci_broken_lpm(struct pci_dev *pdev) { + /* + * Platforms with LPM problems. + * If driver_data is NULL, there is no existing BIOS version with + * functioning LPM. + * If driver_data is non-NULL, then driver_data contains the DMI BIOS + * build date of the first BIOS version with functioning LPM (i.e. older + * BIOS versions have broken LPM). + */ static const struct dmi_system_id sysids[] = { - /* Various Lenovo 50 series have LPM issues with older BIOSen */ { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), @@ -1311,13 +1461,30 @@ static bool ahci_broken_lpm(struct pci_dev *pdev) DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"), }, + .driver_data = "20180409", /* 2.35 */ + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "ASUSPRO D840MB_M840SA"), + }, + /* 320 is broken, there is no known good version. */ + }, + { /* - * Note date based on release notes, 2.35 has been - * reported to be good, but I've been unable to get - * a hold of the reporter to get the DMI BIOS date. - * TODO: fix this. + * AMD 500 Series Chipset SATA Controller [1022:43eb] + * on this motherboard timeouts on ports 5 and 6 when + * LPM is enabled, at least with WDC WD20EFAX-68FB5N0 + * hard drives. LPM with the same drive works fine on + * all other ports on the same controller. */ - .driver_data = "20180310", /* 2.35 */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, + "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, + "ROG STRIX B550-F GAMING (WI-FI)"), + }, + /* 3621 is broken, there is no known good version. */ }, { } /* terminate list */ }; @@ -1328,6 +1495,9 @@ static bool ahci_broken_lpm(struct pci_dev *pdev) if (!dmi) return false; + if (!dmi->driver_data) + return true; + dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); @@ -1384,17 +1554,6 @@ static bool ahci_broken_online(struct pci_dev *pdev) return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); } -static bool ahci_broken_devslp(struct pci_dev *pdev) -{ - /* device with broken DEVSLP but still showing SDS capability */ - static const struct pci_device_id ids[] = { - { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ - {} - }; - - return pci_match_id(ids, pdev); -} - #ifdef CONFIG_ATA_ACPI static void ahci_gtf_filter_workaround(struct ata_host *host) { @@ -1492,7 +1651,6 @@ static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) u32 irq_stat, irq_masked; unsigned int handled = 1; - VPRINTK("ENTER\n"); hpriv = host->private_data; mmio = hpriv->mmio; irq_stat = readl(mmio + HOST_IRQ_STAT); @@ -1509,7 +1667,6 @@ static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) irq_stat = readl(mmio + HOST_IRQ_STAT); spin_unlock(&host->lock); } while (irq_stat); - VPRINTK("EXIT\n"); return IRQ_RETVAL(handled); } @@ -1518,7 +1675,7 @@ static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) static void ahci_remap_check(struct pci_dev *pdev, int bar, struct ahci_host_priv *hpriv) { - int i, count = 0; + int i; u32 cap; /* @@ -1539,13 +1696,14 @@ static void ahci_remap_check(struct pci_dev *pdev, int bar, continue; /* We've found a remapped device */ - count++; + hpriv->remapped_nvme++; } - if (!count) + if (!hpriv->remapped_nvme) return; - dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count); + dev_warn(&pdev->dev, "Found %u remapped NVMe devices.\n", + hpriv->remapped_nvme); dev_warn(&pdev->dev, "Switch your BIOS from RAID to AHCI mode to use them.\n"); @@ -1561,18 +1719,20 @@ static int ahci_get_irq_vector(struct ata_host *host, int port) return pci_irq_vector(to_pci_dev(host->dev), port); } -static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, +static void ahci_init_irq(struct pci_dev *pdev, unsigned int n_ports, struct ahci_host_priv *hpriv) { int nvec; - if (hpriv->flags & AHCI_HFLAG_NO_MSI) - return -ENODEV; + if (hpriv->flags & AHCI_HFLAG_NO_MSI) { + pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_INTX); + return; + } /* * If number of MSIs is less than number of ports then Sharing Last * Message mode could be enforced. In this case assume that advantage - * of multipe MSIs is negated and use single MSI mode instead. + * of multiple MSIs is negated and use single MSI mode instead. */ if (n_ports > 1) { nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX, @@ -1581,7 +1741,7 @@ static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) { hpriv->get_irq_vector = ahci_get_irq_vector; hpriv->flags |= AHCI_HFLAG_MULTI_MSI; - return nvec; + return; } /* @@ -1596,23 +1756,71 @@ static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports, /* * If the host is not capable of supporting per-port vectors, fall - * back to single MSI before finally attempting single MSI-X. + * back to single MSI before finally attempting single MSI-X or + * a legacy INTx. */ nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); if (nvec == 1) - return nvec; - return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX); + return; + pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX | PCI_IRQ_INTX); +} + +static void ahci_mark_external_port(struct ata_port *ap) +{ + struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + u32 tmp; + + /* + * Mark external ports (hotplug-capable, eSATA), unless we were asked to + * ignore this feature. + */ + tmp = readl(port_mmio + PORT_CMD); + if (((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS)) || + (tmp & PORT_CMD_HPCP)) { + if (hpriv->mask_port_ext & (1U << ap->port_no)) { + ata_port_info(ap, + "Ignoring external/hotplug capability\n"); + return; + } + ap->pflags |= ATA_PFLAG_EXTERNAL; + } } -static void ahci_update_initial_lpm_policy(struct ata_port *ap, - struct ahci_host_priv *hpriv) +static void ahci_update_initial_lpm_policy(struct ata_port *ap) { + struct ahci_host_priv *hpriv = ap->host->private_data; int policy = CONFIG_SATA_MOBILE_LPM_POLICY; + /* + * AHCI contains a known incompatibility between LPM and hot-plug + * removal events, see 7.3.1 Hot Plug Removal Detection and Power + * Management Interaction in AHCI 1.3.1. Therefore, do not enable + * LPM if the port advertises itself as an external port. + */ + if (ap->pflags & ATA_PFLAG_EXTERNAL) { + ap->flags |= ATA_FLAG_NO_LPM; + ap->target_lpm_policy = ATA_LPM_MAX_POWER; + return; + } + + /* If no Partial or no Slumber, we cannot support DIPM. */ + if ((ap->host->flags & ATA_HOST_NO_PART) || + (ap->host->flags & ATA_HOST_NO_SSC)) { + ata_port_dbg(ap, "Host does not support DIPM\n"); + ap->flags |= ATA_FLAG_NO_DIPM; + } - /* Ignore processing for non mobile platforms */ - if (!(hpriv->flags & AHCI_HFLAG_IS_MOBILE)) + /* If no LPM states are supported by the HBA, do not bother with LPM */ + if ((ap->host->flags & ATA_HOST_NO_PART) && + (ap->host->flags & ATA_HOST_NO_SSC) && + (ap->host->flags & ATA_HOST_NO_DEVSLP)) { + ata_port_dbg(ap, + "No LPM states supported, forcing LPM max_power\n"); + ap->flags |= ATA_FLAG_NO_LPM; + ap->target_lpm_policy = ATA_LPM_MAX_POWER; return; + } /* user modified policy via module param */ if (mobile_lpm_policy != -1) { @@ -1620,21 +1828,52 @@ static void ahci_update_initial_lpm_policy(struct ata_port *ap, goto update_policy; } -#ifdef CONFIG_ACPI - if (policy > ATA_LPM_MED_POWER && - (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) { + if (policy > ATA_LPM_MED_POWER && pm_suspend_default_s2idle()) { if (hpriv->cap & HOST_CAP_PART) policy = ATA_LPM_MIN_POWER_WITH_PARTIAL; else if (hpriv->cap & HOST_CAP_SSC) policy = ATA_LPM_MIN_POWER; } -#endif update_policy: if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER) ap->target_lpm_policy = policy; } +static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv) +{ + u16 tmp16; + + if (!(hpriv->flags & AHCI_HFLAG_INTEL_PCS_QUIRK)) + return; + + /* + * port_map is determined from PORTS_IMPL PCI register which is + * implemented as write or write-once register. If the register + * isn't programmed, ahci automatically generates it from number + * of ports, which is good enough for PCS programming. It is + * otherwise expected that platform firmware enables the ports + * before the OS boots. + */ + pci_read_config_word(pdev, PCS_6, &tmp16); + if ((tmp16 & hpriv->port_map) != hpriv->port_map) { + tmp16 |= hpriv->port_map; + pci_write_config_word(pdev, PCS_6, tmp16); + } +} + +static ssize_t remapped_nvme_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ata_host *host = dev_get_drvdata(dev); + struct ahci_host_priv *hpriv = host->private_data; + + return sysfs_emit(buf, "%u\n", hpriv->remapped_nvme); +} + +static DEVICE_ATTR_RO(remapped_nvme); + static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned int board_id = ent->driver_data; @@ -1646,8 +1885,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) int n_ports, i, rc; int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; - VPRINTK("ENTER\n"); - WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); ata_print_version_once(&pdev->dev, DRV_VERSION); @@ -1680,6 +1917,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ahci_pci_bar = AHCI_PCI_BAR_CAVIUM; if (pdev->device == 0xa084) ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5; + } else if (pdev->vendor == PCI_VENDOR_ID_LOONGSON) { + if (pdev->device == 0x7a08) + ahci_pci_bar = AHCI_PCI_BAR_LOONGSON; } /* acquire resources */ @@ -1706,7 +1946,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* AHCI controllers often implement SFF compatible interface. * Grab all PCI BARs just in case. */ - rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); + rc = pcim_request_all_regions(pdev, DRV_NAME); if (rc == -EBUSY) pcim_pin_device(pdev); if (rc) @@ -1730,16 +1970,23 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (ahci_sb600_enable_64bit(pdev)) hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; - hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; + hpriv->mmio = pcim_iomap(pdev, ahci_pci_bar, 0); + if (!hpriv->mmio) + return -ENOMEM; /* detect remapped nvme devices */ ahci_remap_check(pdev, ahci_pci_bar, hpriv); - /* must set flag prior to save config in order to take effect */ - if (ahci_broken_devslp(pdev)) - hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; + sysfs_add_file_to_group(&pdev->dev.kobj, + &dev_attr_remapped_nvme.attr, + NULL); #ifdef CONFIG_ARM64 + if (pdev->vendor == PCI_VENDOR_ID_HUAWEI && + pdev->device == 0xa235 && + pdev->revision < 0x30) + hpriv->flags |= AHCI_HFLAG_NO_SXS; + if (pdev->vendor == 0x177d && pdev->device == 0xa01c) hpriv->irq_handler = ahci_thunderx_irq_handler; #endif @@ -1809,14 +2056,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); - if (!host) - return -ENOMEM; + if (!host) { + rc = -ENOMEM; + goto err_rm_sysfs_file; + } host->private_data = hpriv; - if (ahci_init_msi(pdev, n_ports, hpriv) < 0) { - /* legacy intx interrupts */ - pci_intx(pdev, 1); - } + ahci_init_irq(pdev, n_ports, hpriv); + hpriv->irq = pci_irq_vector(pdev, 0); if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) @@ -1824,6 +2071,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) else dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n"); + if (!(hpriv->cap & HOST_CAP_PART)) + host->flags |= ATA_HOST_NO_PART; + + if (!(hpriv->cap & HOST_CAP_SSC)) + host->flags |= ATA_HOST_NO_SSC; + + if (!(hpriv->cap2 & HOST_CAP2_SDS)) + host->flags |= ATA_HOST_NO_DEVSLP; + if (pi.flags & ATA_FLAG_EM) ahci_reset_em(host); @@ -1838,7 +2094,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (ap->flags & ATA_FLAG_EM) ap->em_message_type = hpriv->em_msg_type; - ahci_update_initial_lpm_policy(ap, hpriv); + ahci_mark_external_port(ap); + + ahci_update_initial_lpm_policy(ap); /* disabled/not-implemented port */ if (!(hpriv->port_map & (1 << i))) @@ -1852,13 +2110,13 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ahci_gtf_filter_workaround(host); /* initialize adapter */ - rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); + rc = ahci_configure_dma_masks(pdev, hpriv); if (rc) - return rc; + goto err_rm_sysfs_file; rc = ahci_pci_reset_controller(host); if (rc) - return rc; + goto err_rm_sysfs_file; ahci_pci_init_controller(host); ahci_pci_print_info(host); @@ -1867,14 +2125,27 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rc = ahci_host_activate(host, &ahci_sht); if (rc) - return rc; + goto err_rm_sysfs_file; pm_runtime_put_noidle(&pdev->dev); return 0; + +err_rm_sysfs_file: + sysfs_remove_file_from_group(&pdev->dev.kobj, + &dev_attr_remapped_nvme.attr, NULL); + return rc; +} + +static void ahci_shutdown_one(struct pci_dev *pdev) +{ + ata_pci_shutdown_one(pdev); } static void ahci_remove_one(struct pci_dev *pdev) { + sysfs_remove_file_from_group(&pdev->dev.kobj, + &dev_attr_remapped_nvme.attr, + NULL); pm_runtime_get_noresume(&pdev->dev); ata_pci_remove_one(pdev); } |
