Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F167079139
D18346.id51612.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D18346.id51612.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;
@@ -125,6 +112,19 @@
},
};
+static int
+spa_type_from_uuid(const struct uuid *u)
+{
+ int i;
+
+ for (i = 0; i < nitems(nvdimm_SPA_uuid_list); i++) {
+ if (uuidcmp(u, &nvdimm_SPA_uuid_list[i].u_id) != 0)
+ continue;
+ return (i);
+ }
+ return (SPA_TYPE_UNKNOWN);
+}
+
static vm_memattr_t
nvdimm_spa_memattr(struct SPA_mapping *spa)
{
@@ -276,30 +276,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 +308,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 +325,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 +340,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 +355,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 +367,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,31 +388,98 @@
return (0);
}
-static g_init_t nvdimm_spa_g_init;
-static g_fini_t nvdimm_spa_g_fini;
+static g_ctl_destroy_geom_t nvdimm_spa_g_destroy_geom;
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_init_one(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr,
- int spa_type)
+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_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_lock();
+ g_wither_geom(gp, ENXIO);
+ g_topology_unlock();
+ 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);
+}
+
+static int
+nvdimm_spa_init_one(void *nfitsubtbl, void *arg)
+{
+ struct SPA_mapping *spa;
+ ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr;
struct make_dev_args mda;
struct sglist *spa_sg;
int error, error1;
- spa->spa_type = spa_type;
+ spa = arg;
+ nfitaddr = nfitsubtbl;
+ if (spa->spa_nfit_idx != nfitaddr->RangeIndex)
+ return (0);
+
+ spa->spa_type = spa_type_from_uuid((struct uuid *)&nfitaddr->RangeGuid);
spa->spa_domain = ((nfitaddr->Flags & ACPI_NFIT_PROXIMITY_VALID) != 0) ?
nfitaddr->ProximityDomain : -1;
- spa->spa_nfit_idx = nfitaddr->RangeIndex;
spa->spa_phys_base = nfitaddr->Address;
spa->spa_len = nfitaddr->Length;
spa->spa_efi_mem_flags = nfitaddr->MemoryMapping;
@@ -417,11 +487,9 @@
printf("NVDIMM SPA%d base %#016jx len %#016jx %s fl %#jx\n",
spa->spa_nfit_idx,
(uintmax_t)spa->spa_phys_base, (uintmax_t)spa->spa_len,
- nvdimm_SPA_uuid_list[spa_type].u_name,
+ nvdimm_SPA_uuid_list[spa->spa_type].u_name,
spa->spa_efi_mem_flags);
}
- if (!nvdimm_SPA_uuid_list[spa_type].u_usr_acc)
- return (0);
error1 = pmap_large_map(spa->spa_phys_base, spa->spa_len,
&spa->spa_kva, nvdimm_spa_memattr(spa));
@@ -465,34 +533,10 @@
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,23 +544,8 @@
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);
- 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_g != NULL)
+ nvdimm_spa_g_destroy_geom(NULL, spa->spa_g->class, spa->spa_g);
if (spa->spa_dev != NULL) {
destroy_dev(spa->spa_dev);
spa->spa_dev = NULL;
@@ -526,42 +555,81 @@
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 int
-nvdimm_spa_parse(void *nfitsubtbl, void *arg)
+nvdimm_spa_create_dev(void *nfitsubtbl, void *arg)
{
ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr;
- struct SPA_mapping *spa;
- int error, *i, j;
+ device_t child;
+ int i;
- i = arg;
- spa = &spa_mappings[*i];
nfitaddr = nfitsubtbl;
+ i = spa_type_from_uuid((struct uuid *)&nfitaddr->RangeGuid);
+ if (i == SPA_TYPE_UNKNOWN || !nvdimm_SPA_uuid_list[i].u_usr_acc)
+ return (0);
+ child = device_find_child(arg, "nvdimm_spa", nfitaddr->RangeIndex);
+ if (child == NULL)
+ BUS_ADD_CHILD(arg, 1, "nvdimm_spa", nfitaddr->RangeIndex);
+ return (0);
+}
- for (j = 0; j < nitems(nvdimm_SPA_uuid_list); j++) {
- /* XXXKIB: is ACPI UUID representation compatible ? */
- if (uuidcmp((struct uuid *)&nfitaddr->RangeGuid,
- &nvdimm_SPA_uuid_list[j].u_id) != 0)
- continue;
- error = nvdimm_spa_init_one(spa, nfitaddr, j);
- if (error != 0)
- nvdimm_spa_fini_one(spa);
- break;
- }
- if (j == nitems(nvdimm_SPA_uuid_list) && bootverbose) {
- printf("Unknown SPA UUID %d ", nfitaddr->RangeIndex);
- printf_uuid((struct uuid *)&nfitaddr->RangeGuid);
- printf("\n");
- }
- (*i)++;
+static void
+nvdimm_spa_identify(driver_t *driver, device_t parent)
+{
+ ACPI_TABLE_NFIT *nfitbl;
+ ACPI_STATUS status;
+
+ if (acpi_disabled("nvdimm"))
+ return;
+ status = AcpiGetTable(ACPI_SIG_NFIT, 1, (ACPI_TABLE_HEADER **)&nfitbl);
+ if (ACPI_FAILURE(status))
+ return;
+ nvdimm_iterate_nfit(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS,
+ nvdimm_spa_create_dev, parent);
+ AcpiPutTable(&nfitbl->Header);
+}
+
+static int
+nvdimm_spa_probe(device_t dev)
+{
+
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+nvdimm_spa_attach(device_t dev)
+{
+ struct SPA_mapping *spa;
+ ACPI_TABLE_NFIT *nfitbl;
+ ACPI_STATUS status;
+ int error;
+
+ spa = device_get_softc(dev);
+ status = AcpiGetTable(ACPI_SIG_NFIT, 1, (ACPI_TABLE_HEADER **)&nfitbl);
+ if (ACPI_FAILURE(status))
+ return (ENXIO);
+ spa->spa_nfit_idx = device_get_unit(dev);
+ error = nvdimm_iterate_nfit(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS,
+ nvdimm_spa_init_one, spa);
+ AcpiPutTable(&nfitbl->Header);
+ if (error != 0)
+ nvdimm_spa_fini_one(spa);
+ return (error);
+}
+
+static int
+nvdimm_spa_detach(device_t dev)
+{
+ struct SPA_mapping *spa;
+
+ spa = device_get_softc(dev);
+ nvdimm_spa_fini_one(spa);
return (0);
}
static int
-nvdimm_spa_init1(ACPI_TABLE_NFIT *nfitbl)
+nvdimm_spa_init(void)
{
struct nvdimm_SPA_uuid_list_elm *sle;
int error, i;
@@ -571,63 +639,54 @@
error = parse_uuid(sle->u_id_str, &sle->u_id);
if (error != 0) {
if (bootverbose)
- printf("nvdimm_identify: error %d parsing "
+ printf("nvdimm_spa_init: error %d parsing "
"known SPA UUID %d %s\n", error, i,
sle->u_id_str);
return (error);
}
}
- 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_spa_modev(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;
+ switch (what) {
+ case MOD_LOAD:
+ error = nvdimm_spa_init();
+ break;
+
+ case MOD_UNLOAD:
+ case MOD_QUIESCE:
+ error = 0;
+ break;
+
+ default:
+ error = EOPNOTSUPP;
+ break;
}
- error = nvdimm_spa_init1(nfitbl);
- if (error != 0)
- printf("nvdimm_spa_g_init: error %d\n", error);
- AcpiPutTable(&nfitbl->Header);
+
+ return (error);
}
-static void
-nvdimm_spa_g_fini(struct g_class *mp __unused)
-{
- int i;
+static device_method_t nvdimm_spa_methods[] = {
+ DEVMETHOD(device_identify, nvdimm_spa_identify),
+ DEVMETHOD(device_probe, nvdimm_spa_probe),
+ DEVMETHOD(device_attach, nvdimm_spa_attach),
+ DEVMETHOD(device_detach, nvdimm_spa_detach),
+ DEVMETHOD_END
+};
- 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;
-}
+static driver_t nvdimm_spa_driver = {
+ "nvdimm_spa",
+ nvdimm_spa_methods,
+ sizeof(struct SPA_mapping),
+};
+
+static devclass_t nvdimm_spa_devclass;
+DRIVER_MODULE(nvdimm_spa, acpi, nvdimm_spa_driver, nvdimm_spa_devclass,
+ nvdimm_spa_modev, 0);
+MODULE_DEPEND(nvdimm_spa, acpi, 1, 1, 1);
Index: sys/dev/nvdimm/nvdimm_var.h
===================================================================
--- sys/dev/nvdimm/nvdimm_var.h
+++ sys/dev/nvdimm/nvdimm_var.h
@@ -51,6 +51,7 @@
SPA_TYPE_VOLATILE_VIRTUAL_CD = 5,
SPA_TYPE_PERSISTENT_VIRTUAL_DISK= 6,
SPA_TYPE_PERSISTENT_VIRTUAL_CD = 7,
+ SPA_TYPE_UNKNOWN = 127,
};
struct SPA_mapping {
@@ -61,15 +62,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 +84,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, Aug 19, 9:58 PM (8 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36964297
Default Alt Text
D18346.id51612.diff (15 KB)
Attached To
Mode
D18346: nvdimm: add a driver for the NVDIMM root device
Attached
Detach File
Event Timeline
Log In to Comment