diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 74f4c662f776..2fc52407306c 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -46,6 +46,8 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_cmnd.h> #include <linux/libata.h> +#include <linux/ahci-remap.h> +#include <linux/io-64-nonatomic-lo-hi.h> #include "ahci.h" #define DRV_NAME "ahci" @@ -1400,6 +1402,40 @@ static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) } #endif +static void ahci_remap_check(struct pci_dev *pdev, int bar, + struct ahci_host_priv *hpriv) +{ + int i, count = 0; + u32 cap; + + /* + * Check if this device might have remapped nvme devices. + */ + if (pdev->vendor != PCI_VENDOR_ID_INTEL || + pci_resource_len(pdev, bar) < SZ_512K || + bar != AHCI_PCI_BAR_STANDARD || + !(readl(hpriv->mmio + AHCI_VSCAP) & 1)) + return; + + cap = readq(hpriv->mmio + AHCI_REMAP_CAP); + for (i = 0; i < AHCI_MAX_REMAP; i++) { + if ((cap & (1 << i)) == 0) + continue; + if (readl(hpriv->mmio + ahci_remap_dcc(i)) + != PCI_CLASS_STORAGE_EXPRESS) + continue; + + /* We've found a remapped device */ + count++; + } + + if (!count) + return; + + dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count); + dev_warn(&pdev->dev, "Switch your BIOS from RAID to AHCI mode to use them.\n"); +} + static int ahci_get_irq_vector(struct ata_host *host, int port) { return pci_irq_vector(to_pci_dev(host->dev), port); @@ -1541,6 +1577,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; + /* 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; |