Date: Thu, 5 Sep 2019 23:02:09 +0000 (UTC) From: Warner Losh <imp@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r351904 - in stable/12/sys: conf dev/ahci dev/nvme modules/nvme Message-ID: <201909052302.x85N29fj027993@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201909052302.x85N29fj027993>