Author: imp
Date: Thu Sep  5 23:02:08 2019
New Revision: 351904
URL: https://svnweb.freebsd.org/changeset/base/351904

Log:
  MFC r351356:
  
    Create a AHCI attachment for nvme.

Added:
  stable/12/sys/dev/nvme/nvme_ahci.c
     - copied unchanged from r351356, head/sys/dev/nvme/nvme_ahci.c
Modified:
  stable/12/sys/conf/files
  stable/12/sys/dev/ahci/ahci.c
  stable/12/sys/dev/ahci/ahci.h
  stable/12/sys/dev/ahci/ahci_pci.c
  stable/12/sys/modules/nvme/Makefile
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/conf/files
==============================================================================
--- stable/12/sys/conf/files    Thu Sep  5 23:01:12 2019        (r351903)
+++ stable/12/sys/conf/files    Thu Sep  5 23:02:08 2019        (r351904)
@@ -2574,6 +2574,7 @@ dev/nsp/nsp_pccard.c              optional nsp pccard
 dev/null/null.c                        standard
 dev/nvd/nvd.c                  optional nvd nvme
 dev/nvme/nvme.c                        optional nvme
+dev/nvme/nvme_ahci.c           optional nvme ahci
 dev/nvme/nvme_ctrlr.c          optional nvme
 dev/nvme/nvme_ctrlr_cmd.c      optional nvme
 dev/nvme/nvme_ns.c             optional nvme

Modified: stable/12/sys/dev/ahci/ahci.c
==============================================================================
--- stable/12/sys/dev/ahci/ahci.c       Thu Sep  5 23:01:12 2019        
(r351903)
+++ stable/12/sys/dev/ahci/ahci.c       Thu Sep  5 23:02:08 2019        
(r351904)
@@ -347,6 +347,16 @@ ahci_attach(device_t dev)
                if ((ctlr->ichannels & (1 << unit)) == 0)
                        device_disable(child);
        }
+       /* Attach any remapped NVME device */
+       for (; unit < ctlr->channels + ctlr->remapped_devices; unit++) {
+               child = device_add_child(dev, "nvme", -1);
+               if (child == NULL) {
+                       device_printf(dev, "failed to add remapped NVMe 
device");
+                           continue;
+               }
+               device_set_ivars(child, (void *)(intptr_t)(unit | 
AHCI_REMAPPED_UNIT));
+       }
+
        if (ctlr->caps & AHCI_CAP_EMS) {
                child = device_add_child(dev, "ahciem", -1);
                if (child == NULL)
@@ -497,6 +507,12 @@ ahci_intr(void *data)
                                ctlr->interrupt[unit].function(arg);
                }
        }
+       for (; unit < ctlr->channels + ctlr->remapped_devices; unit++) {
+               if ((arg = ctlr->interrupt[unit].argument)) {
+                       ctlr->interrupt[unit].function(arg);
+               }
+       }
+
        /* AHCI declares level triggered IS. */
        if (!(ctlr->quirks & AHCI_Q_EDGEIS))
                ATA_OUTL(ctlr->r_mem, AHCI_IS, is);
@@ -546,12 +562,23 @@ ahci_alloc_resource(device_t dev, device_t child, int 
        struct resource *res;
        rman_res_t st;
        int offset, size, unit;
+       bool is_remapped;
 
        unit = (intptr_t)device_get_ivars(child);
+       if (unit & AHCI_REMAPPED_UNIT) {
+               unit &= ~AHCI_REMAPPED_UNIT;
+               unit -= ctlr->channels;
+               is_remapped = true;
+       } else
+               is_remapped = false;
        res = NULL;
        switch (type) {
        case SYS_RES_MEMORY:
-               if (unit >= 0) {
+               if (is_remapped) {
+                       offset = ctlr->remap_offset + unit * ctlr->remap_size;
+                       size = ctlr->remap_size;
+               }
+               else if (unit >= 0) {
                        offset = AHCI_OFFSET + (unit << 7);
                        size = 128;
                } else if (*rid == 0) {
@@ -612,7 +639,7 @@ ahci_setup_intr(device_t dev, device_t child, struct r
     void *argument, void **cookiep)
 {
        struct ahci_controller *ctlr = device_get_softc(dev);
-       int unit = (intptr_t)device_get_ivars(child);
+       int unit = (intptr_t)device_get_ivars(child) & ~AHCI_REMAPPED_UNIT;
 
        if (filter != NULL) {
                printf("ahci.c: we cannot use a filter here\n");
@@ -628,7 +655,7 @@ ahci_teardown_intr(device_t dev, device_t child, struc
     void *cookie)
 {
        struct ahci_controller *ctlr = device_get_softc(dev);
-       int unit = (intptr_t)device_get_ivars(child);
+       int unit = (intptr_t)device_get_ivars(child) & ~AHCI_REMAPPED_UNIT;
 
        ctlr->interrupt[unit].function = NULL;
        ctlr->interrupt[unit].argument = NULL;
@@ -641,7 +668,7 @@ ahci_print_child(device_t dev, device_t child)
        int retval, channel;
 
        retval = bus_print_child_header(dev, child);
-       channel = (int)(intptr_t)device_get_ivars(child);
+       channel = (int)(intptr_t)device_get_ivars(child) & ~AHCI_REMAPPED_UNIT;
        if (channel >= 0)
                retval += printf(" at channel %d", channel);
        retval += bus_print_child_footer(dev, child);
@@ -654,7 +681,7 @@ ahci_child_location_str(device_t dev, device_t child, 
 {
        int channel;
 
-       channel = (int)(intptr_t)device_get_ivars(child);
+       channel = (int)(intptr_t)device_get_ivars(child) & ~AHCI_REMAPPED_UNIT;
        if (channel >= 0)
                snprintf(buf, buflen, "channel=%d", channel);
        return (0);

Modified: stable/12/sys/dev/ahci/ahci.h
==============================================================================
--- stable/12/sys/dev/ahci/ahci.h       Thu Sep  5 23:01:12 2019        
(r351903)
+++ stable/12/sys/dev/ahci/ahci.h       Thu Sep  5 23:02:08 2019        
(r351904)
@@ -214,6 +214,7 @@
 #define                AHCI_CAP2_SADM  0x00000010
 #define                AHCI_CAP2_DESO  0x00000020
 
+#define AHCI_VSCAP                  0xa4
 #define AHCI_OFFSET                 0x100
 #define AHCI_STEP                   0x80
 
@@ -318,6 +319,10 @@
 /* Total main work area. */
 #define AHCI_WORK_SIZE              (AHCI_CT_OFFSET + AHCI_CT_SIZE * 
ch->numslots)
 
+
+/* NVMe remapped device */
+#define AHCI_REMAPPED_UNIT     (1 << 31)
+
 struct ahci_dma_prd {
     u_int64_t                   dba;
     u_int32_t                   reserved;
@@ -518,6 +523,9 @@ struct ahci_controller {
        int                     cccv;           /* CCC vector */
        int                     direct;         /* Direct command completion */
        int                     msi;            /* MSI interupts */
+       int                     remapped_devices; /* Remapped NVMe devices */
+       uint32_t                remap_offset;
+       uint32_t                remap_size;
        struct {
                void                    (*function)(void *);
                void                    *argument;

Modified: stable/12/sys/dev/ahci/ahci_pci.c
==============================================================================
--- stable/12/sys/dev/ahci/ahci_pci.c   Thu Sep  5 23:01:12 2019        
(r351903)
+++ stable/12/sys/dev/ahci/ahci_pci.c   Thu Sep  5 23:02:08 2019        
(r351904)
@@ -495,6 +495,48 @@ ahci_pci_attach(device_t dev)
            &ctlr->r_rid, RF_ACTIVE)))
                return ENXIO;
 
+       /*
+        * Intel RAID hardware can remap NVMe devices inside its BAR.
+        * Try to detect this. Either we have to add the device
+        * here, or the user has to change the mode in the BIOS
+        * from RST to AHCI.
+        */
+       if (pci_get_vendor(dev) == 0x8086) {
+               uint32_t vscap;
+
+               vscap = ATA_INL(ctlr->r_mem, AHCI_VSCAP);
+               if (vscap & 1) {
+                       uint32_t cap = ATA_INL(ctlr->r_mem, 0x800); /* Intel's 
REMAP CAP */
+                       int i;
+
+                       ctlr->remap_offset = 0x4000;
+                       ctlr->remap_size = 0x4000;
+
+                       /*
+                        * Check each of the devices that might be remapped to
+                        * make sure they are an nvme device. At the present,
+                        * nvme are the only known devices remapped.
+                        */
+                       for (i = 0; i < 3; i++) {
+                               if (cap & (1 << i) &&
+                                   (ATA_INL(ctlr->r_mem, 0x880 + i * 0x80) ==
+                                    ((PCIC_STORAGE << 16) |
+                                     (PCIS_STORAGE_NVM << 8) |
+                                     PCIP_STORAGE_NVM_ENTERPRISE_NVMHCI_1_0))) 
{
+                                       ctlr->remapped_devices++;
+                               }
+                       }
+
+                       /* If we have any remapped device, disable MSI */
+                       if (ctlr->remapped_devices > 0) {
+                               device_printf(dev, "Detected %d nvme remapped 
devices\n",
+                                   ctlr->remapped_devices);
+                               ctlr->quirks |= (AHCI_Q_NOMSIX | AHCI_Q_NOMSI);
+                       }
+               }
+       }
+
+
        if (ctlr->quirks & AHCI_Q_NOMSIX)
                msix_count = 0;
 

Copied: stable/12/sys/dev/nvme/nvme_ahci.c (from r351356, 
head/sys/dev/nvme/nvme_ahci.c)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/12/sys/dev/nvme/nvme_ahci.c  Thu Sep  5 23:02:08 2019        
(r351904, copy of r351356, head/sys/dev/nvme/nvme_ahci.c)
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (C) 2017 Olivier Houchard
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+
+#include "nvme_private.h"
+
+static int    nvme_ahci_probe(device_t dev);
+static int    nvme_ahci_attach(device_t dev);
+static int    nvme_ahci_detach(device_t dev);
+
+static device_method_t nvme_ahci_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,     nvme_ahci_probe),
+       DEVMETHOD(device_attach,    nvme_ahci_attach),
+       DEVMETHOD(device_detach,    nvme_ahci_detach),
+       DEVMETHOD(device_shutdown,  nvme_shutdown),
+       { 0, 0 }
+};
+
+static driver_t nvme_ahci_driver = {
+       "nvme",
+       nvme_ahci_methods,
+       sizeof(struct nvme_controller),
+};
+
+DRIVER_MODULE(nvme, ahci, nvme_ahci_driver, nvme_devclass, NULL, 0);
+MODULE_VERSION(nvme_ahci, 1);
+
+static int
+nvme_ahci_probe (device_t device)
+{
+       return (0);
+}
+
+static int
+nvme_ahci_attach(device_t dev)
+{
+       struct nvme_controller*ctrlr = DEVICE2SOFTC(dev);
+       int ret;
+
+       /* Map MMIO registers */
+       ctrlr->resource_id = 0;
+
+       ctrlr->resource = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+           &ctrlr->resource_id, RF_ACTIVE);
+
+       if(ctrlr->resource == NULL) {
+               nvme_printf(ctrlr, "unable to allocate mem resource\n");
+               ret = ENOMEM;
+               goto bad;
+       }
+       ctrlr->bus_tag = rman_get_bustag(ctrlr->resource);
+       ctrlr->bus_handle = rman_get_bushandle(ctrlr->resource);
+       ctrlr->regs = (struct nvme_registers *)ctrlr->bus_handle;
+
+       /* Allocate and setup IRQ */
+       ctrlr->rid = 0;
+       ctrlr->res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+           &ctrlr->rid, RF_SHAREABLE | RF_ACTIVE);
+
+       if (ctrlr->res == NULL) {
+               nvme_printf(ctrlr, "unable to allocate shared IRQ\n");
+               ret = ENOMEM;
+               goto bad;
+       }
+
+       ctrlr->msix_enabled = 0;
+       ctrlr->num_io_queues = 1;
+       ctrlr->num_cpus_per_ioq = mp_ncpus;
+       if (bus_setup_intr(dev, ctrlr->res,
+           INTR_TYPE_MISC | INTR_MPSAFE, NULL, nvme_ctrlr_intx_handler,
+           ctrlr, &ctrlr->tag) != 0) {
+               nvme_printf(ctrlr, "unable to setup intx handler\n");
+               ret = ENOMEM;
+               goto bad;
+       }
+       ctrlr->tag = (void *)0x1;
+
+       return nvme_attach(dev);
+bad:
+       if (ctrlr->resource != NULL) {
+               bus_release_resource(dev, SYS_RES_MEMORY,
+                   ctrlr->resource_id, ctrlr->resource);
+       }
+       if (ctrlr->res)
+               bus_release_resource(ctrlr->dev, SYS_RES_IRQ,
+                   rman_get_rid(ctrlr->res), ctrlr->res);
+       return (ret);
+}
+
+static int
+nvme_ahci_detach(device_t dev)
+{
+
+       return (nvme_detach(dev));
+}

Modified: stable/12/sys/modules/nvme/Makefile
==============================================================================
--- stable/12/sys/modules/nvme/Makefile Thu Sep  5 23:01:12 2019        
(r351903)
+++ stable/12/sys/modules/nvme/Makefile Thu Sep  5 23:02:08 2019        
(r351904)
@@ -5,6 +5,7 @@
 KMOD = nvme
 
 SRCS = nvme.c                  \
+       nvme_ahci.c             \
        nvme_ctrlr.c            \
        nvme_ctrlr_cmd.c        \
        nvme_ns.c               \
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to