aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/nvdimm
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/nvdimm')
-rw-r--r--sys/dev/nvdimm/nvdimm.c45
-rw-r--r--sys/dev/nvdimm/nvdimm_spa.c115
-rw-r--r--sys/dev/nvdimm/nvdimm_var.h11
3 files changed, 60 insertions, 111 deletions
diff --git a/sys/dev/nvdimm/nvdimm.c b/sys/dev/nvdimm/nvdimm.c
index bdc4f57ab2dd..b93e50e88080 100644
--- a/sys/dev/nvdimm/nvdimm.c
+++ b/sys/dev/nvdimm/nvdimm.c
@@ -227,6 +227,31 @@ nvdimm_resume(device_t dev)
return (0);
}
+static int
+nvdimm_root_create_spa(void *nfitsubtbl, void *arg)
+{
+ enum SPA_mapping_type spa_type;
+ ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr;
+ struct SPA_mapping *spa;
+ struct nvdimm_root_dev *dev;
+ int error;
+
+ nfitaddr = nfitsubtbl;
+ dev = arg;
+ spa_type = nvdimm_spa_type_from_uuid(
+ (struct uuid *)nfitaddr->RangeGuid);
+ if (spa_type == SPA_TYPE_UNKNOWN)
+ return (0);
+ spa = malloc(sizeof(struct SPA_mapping), M_NVDIMM, M_WAITOK | M_ZERO);
+ error = nvdimm_spa_init(spa, nfitaddr, spa_type);
+ if (error != 0) {
+ nvdimm_spa_fini(spa);
+ free(spa, M_NVDIMM);
+ }
+ SLIST_INSERT_HEAD(&dev->spas, spa, link);
+ return (0);
+}
+
static ACPI_STATUS
nvdimm_root_create_dev(ACPI_HANDLE handle, UINT32 nesting_level, void *context,
void **return_value)
@@ -276,6 +301,7 @@ nvdimm_root_attach(device_t dev)
{
ACPI_HANDLE handle;
ACPI_STATUS status;
+ ACPI_TABLE_NFIT *nfitbl;
int error;
handle = acpi_get_handle(dev);
@@ -284,15 +310,33 @@ nvdimm_root_attach(device_t dev)
if (ACPI_FAILURE(status))
device_printf(dev, "failed adding children\n");
error = bus_generic_attach(dev);
+ if (error != 0)
+ return (error);
+ status = AcpiGetTable(ACPI_SIG_NFIT, 1, (ACPI_TABLE_HEADER **)&nfitbl);
+ if (ACPI_FAILURE(status)) {
+ device_printf(dev, "cannot get NFIT\n");
+ return (ENXIO);
+ }
+ error = nvdimm_iterate_nfit(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS,
+ nvdimm_root_create_spa, device_get_softc(dev));
+ AcpiPutTable(&nfitbl->Header);
return (error);
}
static int
nvdimm_root_detach(device_t dev)
{
+ struct nvdimm_root_dev *root;
+ struct SPA_mapping *spa, *next;
device_t *children;
int i, error, num_children;
+ root = device_get_softc(dev);
+ SLIST_FOREACH_SAFE(spa, &root->spas, link, next) {
+ nvdimm_spa_fini(spa);
+ SLIST_REMOVE_HEAD(&root->spas, link);
+ free(spa, M_NVDIMM);
+ }
error = bus_generic_detach(dev);
if (error != 0)
return (error);
@@ -356,6 +400,7 @@ static device_method_t nvdimm_root_methods[] = {
static driver_t nvdimm_root_driver = {
"nvdimm_root",
nvdimm_root_methods,
+ sizeof(struct nvdimm_root_dev),
};
DRIVER_MODULE(nvdimm_root, acpi, nvdimm_root_driver, nvdimm_root_devclass, NULL,
diff --git a/sys/dev/nvdimm/nvdimm_spa.c b/sys/dev/nvdimm/nvdimm_spa.c
index b621193f951d..0bbb41746d85 100644
--- a/sys/dev/nvdimm/nvdimm_spa.c
+++ b/sys/dev/nvdimm/nvdimm_spa.c
@@ -82,19 +82,6 @@ __FBSDID("$FreeBSD$");
#define UUID_INITIALIZER_PERSISTENT_VIRTUAL_CD \
{0x08018188,0x42cd,0xbb48,0x10,0x0f,{0x53,0x87,0xd5,0x3d,0xed,0x3d}}
-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;
struct uuid u_id;
@@ -419,22 +406,17 @@ nvdimm_spa_g_access(struct g_provider *pp, int r, int w, int e)
return (0);
}
-static g_init_t nvdimm_spa_g_init;
-static g_fini_t nvdimm_spa_g_fini;
-
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,
};
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)
+int
+nvdimm_spa_init(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr,
+ enum SPA_mapping_type spa_type)
{
struct make_dev_args mda;
struct sglist *spa_sg;
@@ -512,7 +494,7 @@ nvdimm_spa_init_one(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr,
if (error1 == 0)
error1 = error;
} else {
- g_topology_assert();
+ g_topology_lock();
spa->spa_g = g_new_geomf(&nvdimm_spa_g_class, "spa%d",
spa->spa_nfit_idx);
spa->spa_g->softc = spa;
@@ -526,12 +508,13 @@ nvdimm_spa_init_one(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr,
spa->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 (error1);
}
-static void
-nvdimm_spa_fini_one(struct SPA_mapping *spa)
+void
+nvdimm_spa_fini(struct SPA_mapping *spa)
{
mtx_lock(&spa->spa_g_mtx);
@@ -563,87 +546,3 @@ nvdimm_spa_fini_one(struct SPA_mapping *spa)
mtx_destroy(&spa->spa_g_mtx);
mtx_destroy(&spa->spa_g_stat_mtx);
}
-
-static int
-nvdimm_spa_parse(void *nfitsubtbl, void *arg)
-{
- ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr;
- struct SPA_mapping *spa;
- enum SPA_mapping_type spa_type;
- int error, *i;
-
- i = arg;
- spa = &spa_mappings[(*i)++];
- nfitaddr = nfitsubtbl;
- spa_type = nvdimm_spa_type_from_uuid(
- (struct uuid *)&nfitaddr->RangeGuid);
- if (spa_type == SPA_TYPE_UNKNOWN) {
- printf("Unknown SPA UUID %d ", nfitaddr->RangeIndex);
- printf_uuid((struct uuid *)&nfitaddr->RangeGuid);
- printf("\n");
- return (0);
- }
- error = nvdimm_spa_init_one(spa, nfitaddr, spa_type);
- if (error != 0)
- nvdimm_spa_fini_one(spa);
- return (0);
-}
-
-static int
-nvdimm_spa_init1(ACPI_TABLE_NFIT *nfitbl)
-{
- int error, i;
-
- 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)
-{
- 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);
-}
-
-static void
-nvdimm_spa_g_fini(struct g_class *mp __unused)
-{
- int i;
-
- 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;
-}
diff --git a/sys/dev/nvdimm/nvdimm_var.h b/sys/dev/nvdimm/nvdimm_var.h
index c70476e38b98..6e627c24918a 100644
--- a/sys/dev/nvdimm/nvdimm_var.h
+++ b/sys/dev/nvdimm/nvdimm_var.h
@@ -44,6 +44,10 @@ __BUS_ACCESSOR(nvdimm_root, acpi_handle, NVDIMM_ROOT, ACPI_HANDLE, ACPI_HANDLE)
__BUS_ACCESSOR(nvdimm_root, device_handle, NVDIMM_ROOT, DEVICE_HANDLE,
nfit_handle_t)
+struct nvdimm_root_dev {
+ SLIST_HEAD(, SPA_mapping) spas;
+};
+
struct nvdimm_dev {
device_t nv_dev;
nfit_handle_t nv_handle;
@@ -64,6 +68,7 @@ enum SPA_mapping_type {
};
struct SPA_mapping {
+ SLIST_ENTRY(SPA_mapping) link;
enum SPA_mapping_type spa_type;
int spa_domain;
int spa_nfit_idx;
@@ -84,14 +89,14 @@ struct SPA_mapping {
bool spa_g_proc_exiting;
};
-extern struct SPA_mapping *spa_mappings;
-extern int spa_mappings_cnt;
-
MALLOC_DECLARE(M_NVDIMM);
enum SPA_mapping_type nvdimm_spa_type_from_uuid(struct uuid *);
struct nvdimm_dev *nvdimm_find_by_handle(nfit_handle_t nv_handle);
int nvdimm_iterate_nfit(ACPI_TABLE_NFIT *nfitbl, enum AcpiNfitType type,
int (*cb)(void *, void *), void *arg);
+int nvdimm_spa_init(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr,
+ enum SPA_mapping_type spa_type);
+void nvdimm_spa_fini(struct SPA_mapping *spa);
#endif /* __DEV_NVDIMM_VAR_H__ */