Page MenuHomeFreeBSD

D18346.id51839.diff
No OneTemporary

D18346.id51839.diff

Index: sys/dev/nvdimm/nvdimm_spa.c
===================================================================
--- sys/dev/nvdimm/nvdimm_spa.c
+++ sys/dev/nvdimm/nvdimm_spa.c
@@ -64,19 +64,6 @@
#include <dev/acpica/acpivar.h>
#include <dev/nvdimm/nvdimm_var.h>
-struct SPA_mapping *spa_mappings;
-int spa_mappings_cnt;
-
-static int
-nvdimm_spa_count(void *nfitsubtbl __unused, void *arg)
-{
- int *cnt;
-
- cnt = arg;
- (*cnt)++;
- return (0);
-}
-
static struct nvdimm_SPA_uuid_list_elm {
const char *u_name;
const char *u_id_str;
@@ -276,30 +263,30 @@
static void
nvdimm_spa_g_thread(void *arg)
{
- struct SPA_mapping *spa;
+ struct g_spa_softc *sc;
struct bio *bp;
struct uio auio;
struct iovec aiovec;
int error;
- spa = arg;
+ sc = arg;
for (;;) {
- mtx_lock(&spa->spa_g_mtx);
+ mtx_lock(&sc->spa_g_mtx);
for (;;) {
- bp = bioq_takefirst(&spa->spa_g_queue);
+ bp = bioq_takefirst(&sc->spa_g_queue);
if (bp != NULL)
break;
- msleep(&spa->spa_g_queue, &spa->spa_g_mtx, PRIBIO,
+ msleep(&sc->spa_g_queue, &sc->spa_g_mtx, PRIBIO,
"spa_g", 0);
- if (!spa->spa_g_proc_run) {
- spa->spa_g_proc_exiting = true;
- wakeup(&spa->spa_g_queue);
- mtx_unlock(&spa->spa_g_mtx);
+ if (!sc->spa_g_proc_run) {
+ sc->spa_g_proc_exiting = true;
+ wakeup(&sc->spa_g_queue);
+ mtx_unlock(&sc->spa_g_mtx);
kproc_exit(0);
}
continue;
}
- mtx_unlock(&spa->spa_g_mtx);
+ mtx_unlock(&sc->spa_g_mtx);
if (bp->bio_cmd != BIO_READ && bp->bio_cmd != BIO_WRITE &&
bp->bio_cmd != BIO_FLUSH) {
error = EOPNOTSUPP;
@@ -308,13 +295,15 @@
error = 0;
if (bp->bio_cmd == BIO_FLUSH) {
- if (spa->spa_kva != NULL) {
- pmap_large_map_wb(spa->spa_kva, spa->spa_len);
+ if (sc->spa->spa_kva != NULL) {
+ pmap_large_map_wb(sc->spa->spa_kva,
+ sc->spa->spa_len);
} else {
pmap_flush_cache_phys_range(
- (vm_paddr_t)spa->spa_phys_base,
- (vm_paddr_t)spa->spa_phys_base +
- spa->spa_len, nvdimm_spa_memattr(spa));
+ (vm_paddr_t)sc->spa->spa_phys_base,
+ (vm_paddr_t)sc->spa->spa_phys_base +
+ sc->spa->spa_len,
+ nvdimm_spa_memattr(sc->spa));
}
/*
* XXX flush IMC
@@ -323,8 +312,8 @@
}
if ((bp->bio_flags & BIO_UNMAPPED) != 0) {
- if (spa->spa_kva != NULL) {
- aiovec.iov_base = (char *)spa->spa_kva +
+ if (sc->spa->spa_kva != NULL) {
+ aiovec.iov_base = (char *)sc->spa->spa_kva +
bp->bio_offset;
aiovec.iov_len = bp->bio_length;
auio.uio_iov = &aiovec;
@@ -338,7 +327,8 @@
error = uiomove_fromphys(bp->bio_ma,
bp->bio_ma_offset, bp->bio_length, &auio);
} else {
- nvdimm_spa_g_all_unmapped(spa, bp, bp->bio_cmd);
+ nvdimm_spa_g_all_unmapped(sc->spa, bp,
+ bp->bio_cmd);
error = 0;
}
} else {
@@ -352,9 +342,9 @@
auio.uio_rw = bp->bio_cmd == BIO_READ ? UIO_READ :
UIO_WRITE;
auio.uio_td = curthread;
- error = nvdimm_spa_uio(spa, &auio);
+ error = nvdimm_spa_uio(sc->spa, &auio);
}
- devstat_end_transaction_bio(spa->spa_g_devstat, bp);
+ devstat_end_transaction_bio(sc->spa_g_devstat, bp);
completed:
bp->bio_completed = bp->bio_length;
g_io_deliver(bp, error);
@@ -364,18 +354,18 @@
static void
nvdimm_spa_g_start(struct bio *bp)
{
- struct SPA_mapping *spa;
+ struct g_spa_softc *sc;
- spa = bp->bio_to->geom->softc;
+ sc = bp->bio_to->geom->softc;
if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
- mtx_lock(&spa->spa_g_stat_mtx);
- devstat_start_transaction_bio(spa->spa_g_devstat, bp);
- mtx_unlock(&spa->spa_g_stat_mtx);
+ mtx_lock(&sc->spa_g_stat_mtx);
+ devstat_start_transaction_bio(sc->spa_g_devstat, bp);
+ mtx_unlock(&sc->spa_g_stat_mtx);
}
- mtx_lock(&spa->spa_g_mtx);
- bioq_disksort(&spa->spa_g_queue, bp);
- wakeup(&spa->spa_g_queue);
- mtx_unlock(&spa->spa_g_mtx);
+ mtx_lock(&sc->spa_g_mtx);
+ bioq_disksort(&sc->spa_g_queue, bp);
+ wakeup(&sc->spa_g_queue);
+ mtx_unlock(&sc->spa_g_mtx);
}
static int
@@ -385,19 +375,78 @@
return (0);
}
-static g_init_t nvdimm_spa_g_init;
-static g_fini_t nvdimm_spa_g_fini;
+static int nvdimm_spa_g_destroy_geom(struct gctl_req *req, struct g_class *cp,
+ struct g_geom *gp)
+{
+ struct g_spa_softc *sc;
+
+ sc = gp->softc;
+ mtx_lock(&sc->spa_g_mtx);
+ sc->spa_g_proc_run = false;
+ wakeup(&sc->spa_g_queue);
+ while (!sc->spa_g_proc_exiting)
+ msleep(&sc->spa_g_queue, &sc->spa_g_mtx, PRIBIO, "spa_e", 0);
+ mtx_unlock(&sc->spa_g_mtx);
+ g_topology_assert();
+ g_wither_geom(gp, ENXIO);
+ sc->spa_p = NULL;
+ if (sc->spa_g_devstat != NULL) {
+ devstat_remove_entry(sc->spa_g_devstat);
+ sc->spa_g_devstat = NULL;
+ }
+ sc->spa->spa_g = NULL;
+ free(sc, M_NVDIMM);
+ gp->softc = NULL;
+
+ return (0);
+}
struct g_class nvdimm_spa_g_class = {
.name = "SPA",
.version = G_VERSION,
.start = nvdimm_spa_g_start,
.access = nvdimm_spa_g_access,
- .init = nvdimm_spa_g_init,
- .fini = nvdimm_spa_g_fini,
+ .destroy_geom = nvdimm_spa_g_destroy_geom,
};
DECLARE_GEOM_CLASS(nvdimm_spa_g_class, g_spa);
+static int
+nvdimm_spa_g_create(struct SPA_mapping *spa)
+{
+ struct g_spa_softc *sc;
+ int error;
+
+ sc = malloc(sizeof(*sc), M_NVDIMM, M_WAITOK | M_ZERO);
+ sc->spa = spa;
+ bioq_init(&sc->spa_g_queue);
+ mtx_init(&sc->spa_g_mtx, "spag", NULL, MTX_DEF);
+ mtx_init(&sc->spa_g_stat_mtx, "spagst", NULL, MTX_DEF);
+ sc->spa_g_proc_run = true;
+ sc->spa_g_proc_exiting = false;
+ error = kproc_create(nvdimm_spa_g_thread, sc, &sc->spa_g_proc, 0, 0,
+ "g_spa%d", spa->spa_nfit_idx);
+ if (error != 0) {
+ printf("NVDIMM SPA%d cannot create geom worker, error %d\n",
+ spa->spa_nfit_idx, error);
+ return (error);
+ }
+ g_topology_lock();
+ spa->spa_g = g_new_geomf(&nvdimm_spa_g_class, "spa%d",
+ spa->spa_nfit_idx);
+ spa->spa_g->softc = sc;
+ sc->spa_p = g_new_providerf(spa->spa_g, "spa%d", spa->spa_nfit_idx);
+ sc->spa_p->mediasize = spa->spa_len;
+ sc->spa_p->sectorsize = DEV_BSIZE;
+ sc->spa_p->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE |
+ G_PF_ACCEPT_UNMAPPED;
+ g_error_provider(sc->spa_p, 0);
+ sc->spa_g_devstat = devstat_new_entry("spa", spa->spa_nfit_idx,
+ DEV_BSIZE, DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT,
+ DEVSTAT_PRIORITY_MAX);
+ g_topology_unlock();
+ return (0);
+}
+
static int
nvdimm_spa_init_one(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr,
int spa_type)
@@ -464,35 +513,9 @@
if (error1 == 0)
error1 = error;
}
-
- bioq_init(&spa->spa_g_queue);
- mtx_init(&spa->spa_g_mtx, "spag", NULL, MTX_DEF);
- mtx_init(&spa->spa_g_stat_mtx, "spagst", NULL, MTX_DEF);
- spa->spa_g_proc_run = true;
- spa->spa_g_proc_exiting = false;
- error = kproc_create(nvdimm_spa_g_thread, spa, &spa->spa_g_proc, 0, 0,
- "g_spa%d", spa->spa_nfit_idx);
- if (error != 0) {
- printf("NVDIMM SPA%d cannot create geom worker, error %d\n",
- spa->spa_nfit_idx, error);
- if (error1 == 0)
- error1 = error;
- } else {
- g_topology_assert();
- spa->spa_g = g_new_geomf(&nvdimm_spa_g_class, "spa%d",
- spa->spa_nfit_idx);
- spa->spa_g->softc = spa;
- spa->spa_p = g_new_providerf(spa->spa_g, "spa%d",
- spa->spa_nfit_idx);
- spa->spa_p->mediasize = spa->spa_len;
- spa->spa_p->sectorsize = DEV_BSIZE;
- spa->spa_p->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE |
- G_PF_ACCEPT_UNMAPPED;
- g_error_provider(spa->spa_p, 0);
- spa->spa_g_devstat = devstat_new_entry("spa", spa->spa_nfit_idx,
- DEV_BSIZE, DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT,
- DEVSTAT_PRIORITY_MAX);
- }
+ error = nvdimm_spa_g_create(spa);
+ if (error1 == 0)
+ error1 = error;
return (error1);
}
@@ -500,22 +523,10 @@
nvdimm_spa_fini_one(struct SPA_mapping *spa)
{
- mtx_lock(&spa->spa_g_mtx);
- spa->spa_g_proc_run = false;
- wakeup(&spa->spa_g_queue);
- while (!spa->spa_g_proc_exiting)
- msleep(&spa->spa_g_queue, &spa->spa_g_mtx, PRIBIO, "spa_e", 0);
- mtx_unlock(&spa->spa_g_mtx);
if (spa->spa_g != NULL) {
g_topology_lock();
- g_wither_geom(spa->spa_g, ENXIO);
+ nvdimm_spa_g_destroy_geom(NULL, spa->spa_g->class, spa->spa_g);
g_topology_unlock();
- spa->spa_g = NULL;
- spa->spa_p = NULL;
- }
- if (spa->spa_g_devstat != NULL) {
- devstat_remove_entry(spa->spa_g_devstat);
- spa->spa_g_devstat = NULL;
}
if (spa->spa_dev != NULL) {
destroy_dev(spa->spa_dev);
@@ -526,19 +537,34 @@
pmap_large_unmap(spa->spa_kva, spa->spa_len);
spa->spa_kva = NULL;
}
- mtx_destroy(&spa->spa_g_mtx);
- mtx_destroy(&spa->spa_g_stat_mtx);
+}
+
+
+static char *nvdimm_root_id[] = {"ACPI0012", NULL};
+
+static int
+nvdimm_root_probe(device_t dev)
+{
+ int rv;
+
+ if (acpi_disabled("nvdimm"))
+ return (ENXIO);
+ rv = ACPI_ID_PROBE(device_get_parent(dev), dev, nvdimm_root_id, NULL);
+ if (rv <= 0)
+ device_set_desc(dev, "ACPI NVDIMM root device");
+
+ return (rv);
}
static int
nvdimm_spa_parse(void *nfitsubtbl, void *arg)
{
ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr;
+ struct nvdimm_root_dev *root;
struct SPA_mapping *spa;
- int error, *i, j;
+ int error, j;
- i = arg;
- spa = &spa_mappings[*i];
+ root = arg;
nfitaddr = nfitsubtbl;
for (j = 0; j < nitems(nvdimm_SPA_uuid_list); j++) {
@@ -546,9 +572,14 @@
if (uuidcmp((struct uuid *)&nfitaddr->RangeGuid,
&nvdimm_SPA_uuid_list[j].u_id) != 0)
continue;
+ spa = malloc(sizeof(*spa), M_NVDIMM, M_WAITOK | M_ZERO);
error = nvdimm_spa_init_one(spa, nfitaddr, j);
- if (error != 0)
+ if (error != 0) {
nvdimm_spa_fini_one(spa);
+ free(spa, M_NVDIMM);
+ } else {
+ SLIST_INSERT_HEAD(&root->spas, spa, link);
+ }
break;
}
if (j == nitems(nvdimm_SPA_uuid_list) && bootverbose) {
@@ -556,12 +587,61 @@
printf_uuid((struct uuid *)&nfitaddr->RangeGuid);
printf("\n");
}
- (*i)++;
return (0);
}
static int
-nvdimm_spa_init1(ACPI_TABLE_NFIT *nfitbl)
+nvdimm_root_attach(device_t dev)
+{
+ ACPI_TABLE_NFIT *nfitbl;
+ ACPI_STATUS status;
+ struct nvdimm_root_dev *root;
+ int error;
+
+ error = 0;
+ root = device_get_softc(dev);
+ root->nv_root_dev = dev;
+ status = AcpiGetTable(ACPI_SIG_NFIT, 1, (ACPI_TABLE_HEADER **)&nfitbl);
+ if (ACPI_FAILURE(status)) {
+ device_printf(dev, "NFIT table not found\n");
+ return (ENXIO);
+ }
+ error = nvdimm_iterate_nfit(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS,
+ nvdimm_spa_parse, root);
+ AcpiPutTable(&nfitbl->Header);
+ return (error);
+}
+
+static int
+nvdimm_root_detach(device_t dev)
+{
+ struct nvdimm_root_dev *root;
+ struct SPA_mapping *spa, *next;
+
+ root = device_get_softc(dev);
+ SLIST_FOREACH_SAFE(spa, &root->spas, link, next) {
+ nvdimm_spa_fini_one(spa);
+ SLIST_REMOVE_HEAD(&root->spas, link);
+ free(spa, M_NVDIMM);
+ }
+ return (0);
+}
+
+static device_method_t nvdimm_root_methods[] = {
+ DEVMETHOD(device_probe, nvdimm_root_probe),
+ DEVMETHOD(device_attach, nvdimm_root_attach),
+ DEVMETHOD(device_detach, nvdimm_root_detach),
+ DEVMETHOD_END
+};
+
+static driver_t nvdimm_root_driver = {
+ "nvdimm_root",
+ nvdimm_root_methods,
+ sizeof(struct nvdimm_root_dev),
+};
+
+static void
+nvdimm_root_init(void)
{
struct nvdimm_SPA_uuid_list_elm *sle;
int error, i;
@@ -574,60 +654,36 @@
printf("nvdimm_identify: error %d parsing "
"known SPA UUID %d %s\n", error, i,
sle->u_id_str);
- return (error);
+ return;
}
}
-
- error = nvdimm_iterate_nfit(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS,
- nvdimm_spa_count, &spa_mappings_cnt);
- if (error != 0)
- return (error);
- spa_mappings = malloc(sizeof(struct SPA_mapping) * spa_mappings_cnt,
- M_NVDIMM, M_WAITOK | M_ZERO);
- i = 0;
- error = nvdimm_iterate_nfit(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS,
- nvdimm_spa_parse, &i);
- if (error != 0) {
- free(spa_mappings, M_NVDIMM);
- spa_mappings = NULL;
- return (error);
- }
- return (0);
}
-static void
-nvdimm_spa_g_init(struct g_class *mp __unused)
+static int
+nvdimm_root_modevent(struct module *mod, int what, void *arg)
{
- ACPI_TABLE_NFIT *nfitbl;
- ACPI_STATUS status;
int error;
- spa_mappings_cnt = 0;
- spa_mappings = NULL;
- if (acpi_disabled("nvdimm"))
- return;
- status = AcpiGetTable(ACPI_SIG_NFIT, 1, (ACPI_TABLE_HEADER **)&nfitbl);
- if (ACPI_FAILURE(status)) {
- if (bootverbose)
- printf("nvdimm_spa_g_init: cannot find NFIT\n");
- return;
- }
- error = nvdimm_spa_init1(nfitbl);
- if (error != 0)
- printf("nvdimm_spa_g_init: error %d\n", error);
- AcpiPutTable(&nfitbl->Header);
-}
+ switch (what) {
+ case MOD_LOAD:
+ nvdimm_root_init();
+ error = 0;
+ break;
-static void
-nvdimm_spa_g_fini(struct g_class *mp __unused)
-{
- int i;
+ case MOD_QUIESCE:
+ case MOD_UNLOAD:
+ error = 0;
+ break;
- if (spa_mappings == NULL)
- return;
- for (i = 0; i < spa_mappings_cnt; i++)
- nvdimm_spa_fini_one(&spa_mappings[i]);
- free(spa_mappings, M_NVDIMM);
- spa_mappings = NULL;
- spa_mappings_cnt = 0;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+
+ return (error);
}
+
+static devclass_t nvdimm_root_devclass;
+DRIVER_MODULE(nvdimm_root, acpi, nvdimm_root_driver, nvdimm_root_devclass,
+ nvdimm_root_modevent, NULL);
+MODULE_DEPEND(nvdimm_root, acpi, 1, 1, 1);
Index: sys/dev/nvdimm/nvdimm_var.h
===================================================================
--- sys/dev/nvdimm/nvdimm_var.h
+++ sys/dev/nvdimm/nvdimm_var.h
@@ -34,6 +34,11 @@
typedef uint32_t nfit_handle_t;
+struct nvdimm_root_dev {
+ device_t nv_root_dev;
+ SLIST_HEAD(, SPA_mapping) spas;
+};
+
struct nvdimm_dev {
device_t nv_dev;
nfit_handle_t nv_handle;
@@ -54,6 +59,7 @@
};
struct SPA_mapping {
+ SLIST_ENTRY(SPA_mapping) link;
enum SPA_mapping_type spa_type;
int spa_domain;
int spa_nfit_idx;
@@ -61,15 +67,19 @@
uint64_t spa_len;
uint64_t spa_efi_mem_flags;
void *spa_kva;
+ struct vm_object *spa_obj;
struct cdev *spa_dev;
struct g_geom *spa_g;
+};
+
+struct g_spa_softc {
+ struct SPA_mapping *spa;
struct g_provider *spa_p;
struct bio_queue_head spa_g_queue;
struct mtx spa_g_mtx;
struct mtx spa_g_stat_mtx;
struct devstat *spa_g_devstat;
struct proc *spa_g_proc;
- struct vm_object *spa_obj;
bool spa_g_proc_run;
bool spa_g_proc_exiting;
};
@@ -79,9 +89,6 @@
void *arg;
};
-extern struct SPA_mapping *spa_mappings;
-extern int spa_mappings_cnt;
-
MALLOC_DECLARE(M_NVDIMM);
struct nvdimm_dev *nvdimm_find_by_handle(nfit_handle_t nv_handle);

File Metadata

Mime Type
text/plain
Expires
Wed, Feb 25, 4:36 PM (11 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28991898
Default Alt Text
D18346.id51839.diff (14 KB)

Event Timeline