diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 00:26:24 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 00:26:24 +0300 |
commit | b92e09bb5bf4db65aeb8ca0094fdd5142ed54451 (patch) | |
tree | 88607d2c9858a25e0f3bd1cc26224555a9ea8a3c /drivers/ata/ahci.c | |
parent | c11a6cfb0103d5d831e20bd9b75d10d13519fec5 (diff) | |
parent | aecec8b60422118b52e3347430ba9382e57d6d76 (diff) | |
download | linux-b92e09bb5bf4db65aeb8ca0094fdd5142ed54451.tar.xz |
Merge branch 'for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
Pull libata updates from Tejun Heo:
- Adam added opt-in ATA command priority support.
- There are machines which hide multiple nvme devices behind an ahci
BAR. Dan Williams proposed a solution to force-switch the mode but
deemed too hackishd. People are gonna discuss the proper way to
handle the situation in nvme standard meetings. For now, detect and
warn about the situation.
- Low level driver specific changes.
Christoph Hellwig pipes in about the hidden nvme warning:
"I wish that was the case. We've pretty much agreed that we'll want to
implement it as a virtual PCIe root bridge, similar to Intels other
'innovation' VMD that we work around that way.
But Intel management has apparently decided that they don't want to
spend more cycles on this now that Lenovo has an optional BIOS that
doesn't force this broken mode anymore, and no one outside of Intel
has enough information to implement something like this.
So for now I guess this warning is it, until Intel reconsideres and
spends resources on fixing up the damage their Chipset people caused"
* 'for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
ahci: warn about remapped NVMe devices
ahci-remap.h: add ahci remapping definitions
nvme: move NVMe class code to pci_ids.h
pata: imx: support controller modes up to PIO4
pata: imx: add support of setting timings for PIO modes
pata: imx: set controller PIO mode with .set_piomode callback
pata: imx: sort headers out
ata: set ncq_prio_enabled iff device has support
ata: ATA Command Priority Disabled By Default
ata: Enabling ATA Command Priorities
block: Add iocontext priority to request
ahci: qoriq: added ls1046a platform support
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; |