Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145802721
D18346.id51839.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D18346.id51839.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D18346: nvdimm: add a driver for the NVDIMM root device
Attached
Detach File
Event Timeline
Log In to Comment