Index: sys/dev/nvdimm/nvdimm.c =================================================================== --- sys/dev/nvdimm/nvdimm.c +++ sys/dev/nvdimm/nvdimm.c @@ -227,6 +227,31 @@ 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 @@ { ACPI_HANDLE handle; ACPI_STATUS status; + ACPI_TABLE_NFIT *nfitbl; int error; handle = acpi_get_handle(dev); @@ -284,15 +310,33 @@ 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 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, Index: sys/dev/nvdimm/nvdimm_spa.c =================================================================== --- sys/dev/nvdimm/nvdimm_spa.c +++ sys/dev/nvdimm/nvdimm_spa.c @@ -82,19 +82,6 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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; -} Index: sys/dev/nvdimm/nvdimm_var.h =================================================================== --- sys/dev/nvdimm/nvdimm_var.h +++ sys/dev/nvdimm/nvdimm_var.h @@ -44,6 +44,10 @@ __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 @@ }; 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 @@ 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__ */