]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/ata/ahci.c
Merge tag 'sound-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[karo-tx-linux.git] / drivers / ata / ahci.c
index 9669fc7c19df7fe05b922daf25e0392677433e26..2fc52407306c15c27b9fb0b11c2db4ef4641aeba 100644 (file)
@@ -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);
@@ -1436,13 +1472,6 @@ static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
                                "ahci: MRSM is on, fallback to single MSI\n");
                        pci_free_irq_vectors(pdev);
                }
-
-               /*
-                * -ENOSPC indicated we don't have enough vectors.  Don't bother
-                * trying a single vectors for any other error:
-                */
-               if (nvec < 0 && nvec != -ENOSPC)
-                       return nvec;
        }
 
        /*
@@ -1548,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;