Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/nvdimm/nvdimm_spa.c
Show First 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
#include <vm/vm_page.h> | #include <vm/vm_page.h> | ||||
#include <vm/vm_pager.h> | #include <vm/vm_pager.h> | ||||
#include <contrib/dev/acpica/include/acpi.h> | #include <contrib/dev/acpica/include/acpi.h> | ||||
#include <contrib/dev/acpica/include/accommon.h> | #include <contrib/dev/acpica/include/accommon.h> | ||||
#include <contrib/dev/acpica/include/acuuid.h> | #include <contrib/dev/acpica/include/acuuid.h> | ||||
#include <dev/acpica/acpivar.h> | #include <dev/acpica/acpivar.h> | ||||
#include <dev/nvdimm/nvdimm_var.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 { | static struct nvdimm_SPA_uuid_list_elm { | ||||
const char *u_name; | const char *u_name; | ||||
const char *u_id_str; | const char *u_id_str; | ||||
struct uuid u_id; | struct uuid u_id; | ||||
const bool u_usr_acc; | const bool u_usr_acc; | ||||
} nvdimm_SPA_uuid_list[] = { | } nvdimm_SPA_uuid_list[] = { | ||||
[SPA_TYPE_VOLATILE_MEMORY] = { | [SPA_TYPE_VOLATILE_MEMORY] = { | ||||
.u_name = "VOLA MEM ", | .u_name = "VOLA MEM ", | ||||
▲ Show 20 Lines • Show All 293 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
nvdimm_spa_g_access(struct g_provider *pp, int r, int w, int e) | nvdimm_spa_g_access(struct g_provider *pp, int r, int w, int e) | ||||
{ | { | ||||
return (0); | return (0); | ||||
} | } | ||||
static g_init_t nvdimm_spa_g_init; | 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 = { | struct g_class nvdimm_spa_g_class = { | ||||
.name = "SPA", | .name = "SPA", | ||||
.version = G_VERSION, | .version = G_VERSION, | ||||
.start = nvdimm_spa_g_start, | .start = nvdimm_spa_g_start, | ||||
.access = nvdimm_spa_g_access, | .access = nvdimm_spa_g_access, | ||||
.init = nvdimm_spa_g_init, | .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); | DECLARE_GEOM_CLASS(nvdimm_spa_g_class, g_spa); | ||||
static int | static int | ||||
nvdimm_spa_init_one(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr, | nvdimm_spa_init_one(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr, | ||||
int spa_type) | int spa_type) | ||||
{ | { | ||||
struct make_dev_args mda; | struct make_dev_args mda; | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | nvdimm_spa_fini_one(struct SPA_mapping *spa) | ||||
mtx_lock(&spa->spa_g_mtx); | mtx_lock(&spa->spa_g_mtx); | ||||
spa->spa_g_proc_run = false; | spa->spa_g_proc_run = false; | ||||
wakeup(&spa->spa_g_queue); | wakeup(&spa->spa_g_queue); | ||||
while (!spa->spa_g_proc_exiting) | while (!spa->spa_g_proc_exiting) | ||||
msleep(&spa->spa_g_queue, &spa->spa_g_mtx, PRIBIO, "spa_e", 0); | msleep(&spa->spa_g_queue, &spa->spa_g_mtx, PRIBIO, "spa_e", 0); | ||||
mtx_unlock(&spa->spa_g_mtx); | mtx_unlock(&spa->spa_g_mtx); | ||||
if (spa->spa_g != NULL) { | if (spa->spa_g != NULL) { | ||||
g_topology_lock(); | |||||
g_wither_geom(spa->spa_g, ENXIO); | g_wither_geom(spa->spa_g, ENXIO); | ||||
g_topology_unlock(); | |||||
spa->spa_g = NULL; | spa->spa_g = NULL; | ||||
spa->spa_p = NULL; | spa->spa_p = NULL; | ||||
} | } | ||||
if (spa->spa_g_devstat != NULL) { | if (spa->spa_g_devstat != NULL) { | ||||
devstat_remove_entry(spa->spa_g_devstat); | devstat_remove_entry(spa->spa_g_devstat); | ||||
spa->spa_g_devstat = NULL; | spa->spa_g_devstat = NULL; | ||||
} | } | ||||
if (spa->spa_dev != NULL) { | if (spa->spa_dev != NULL) { | ||||
Show All 9 Lines | nvdimm_spa_fini_one(struct SPA_mapping *spa) | ||||
mtx_destroy(&spa->spa_g_stat_mtx); | mtx_destroy(&spa->spa_g_stat_mtx); | ||||
} | } | ||||
static int | static int | ||||
nvdimm_spa_parse(void *nfitsubtbl, void *arg) | nvdimm_spa_parse(void *nfitsubtbl, void *arg) | ||||
{ | { | ||||
ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr; | ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr; | ||||
struct SPA_mapping *spa; | struct SPA_mapping *spa; | ||||
int error, *i, j; | int error, j; | ||||
i = arg; | |||||
spa = &spa_mappings[*i]; | |||||
nfitaddr = nfitsubtbl; | nfitaddr = nfitsubtbl; | ||||
for (j = 0; j < nitems(nvdimm_SPA_uuid_list); j++) { | for (j = 0; j < nitems(nvdimm_SPA_uuid_list); j++) { | ||||
/* XXXKIB: is ACPI UUID representation compatible ? */ | |||||
if (uuidcmp((struct uuid *)&nfitaddr->RangeGuid, | if (uuidcmp((struct uuid *)&nfitaddr->RangeGuid, | ||||
&nvdimm_SPA_uuid_list[j].u_id) != 0) | &nvdimm_SPA_uuid_list[j].u_id) != 0) | ||||
continue; | continue; | ||||
spa = malloc(sizeof(struct SPA_mapping), M_NVDIMM, M_WAITOK | M_ZERO); | |||||
error = nvdimm_spa_init_one(spa, nfitaddr, j); | error = nvdimm_spa_init_one(spa, nfitaddr, j); | ||||
if (error != 0) | if (error != 0) { | ||||
g_topology_lock(); | |||||
nvdimm_spa_fini_one(spa); | nvdimm_spa_fini_one(spa); | ||||
g_topology_unlock(); | |||||
free(spa, M_NVDIMM); | |||||
} | |||||
break; | break; | ||||
} | } | ||||
if (j == nitems(nvdimm_SPA_uuid_list) && bootverbose) { | if (j == nitems(nvdimm_SPA_uuid_list) && bootverbose) { | ||||
printf("Unknown SPA UUID %d ", nfitaddr->RangeIndex); | printf("Unknown SPA UUID %d ", nfitaddr->RangeIndex); | ||||
printf_uuid((struct uuid *)&nfitaddr->RangeGuid); | printf_uuid((struct uuid *)&nfitaddr->RangeGuid); | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
(*i)++; | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
nvdimm_spa_init1(ACPI_TABLE_NFIT *nfitbl) | nvdimm_spa_init1(ACPI_TABLE_NFIT *nfitbl) | ||||
{ | { | ||||
struct nvdimm_SPA_uuid_list_elm *sle; | struct nvdimm_SPA_uuid_list_elm *sle; | ||||
int error, i; | int error, i; | ||||
for (i = 0; i < nitems(nvdimm_SPA_uuid_list); i++) { | for (i = 0; i < nitems(nvdimm_SPA_uuid_list); i++) { | ||||
sle = &nvdimm_SPA_uuid_list[i]; | sle = &nvdimm_SPA_uuid_list[i]; | ||||
error = parse_uuid(sle->u_id_str, &sle->u_id); | error = parse_uuid(sle->u_id_str, &sle->u_id); | ||||
if (error != 0) { | if (error != 0) { | ||||
if (bootverbose) | if (bootverbose) | ||||
printf("nvdimm_identify: error %d parsing " | printf("nvdimm_identify: error %d parsing " | ||||
"known SPA UUID %d %s\n", error, i, | "known SPA UUID %d %s\n", error, i, | ||||
sle->u_id_str); | sle->u_id_str); | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
error = nvdimm_iterate_nfit(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS, | error = nvdimm_iterate_nfit(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS, | ||||
nvdimm_spa_count, &spa_mappings_cnt); | nvdimm_spa_parse, NULL); | ||||
if (error != 0) | |||||
return (error); | 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 | static void | ||||
nvdimm_spa_g_init(struct g_class *mp __unused) | nvdimm_spa_g_init(struct g_class *mp __unused) | ||||
{ | { | ||||
ACPI_TABLE_NFIT *nfitbl; | ACPI_TABLE_NFIT *nfitbl; | ||||
ACPI_STATUS status; | ACPI_STATUS status; | ||||
int error; | int error; | ||||
spa_mappings_cnt = 0; | |||||
spa_mappings = NULL; | |||||
if (acpi_disabled("nvdimm")) | if (acpi_disabled("nvdimm")) | ||||
return; | return; | ||||
status = AcpiGetTable(ACPI_SIG_NFIT, 1, (ACPI_TABLE_HEADER **)&nfitbl); | status = AcpiGetTable(ACPI_SIG_NFIT, 1, (ACPI_TABLE_HEADER **)&nfitbl); | ||||
if (ACPI_FAILURE(status)) { | if (ACPI_FAILURE(status)) { | ||||
if (bootverbose) | if (bootverbose) | ||||
printf("nvdimm_spa_g_init: cannot find NFIT\n"); | printf("nvdimm_spa_g_init: cannot find NFIT\n"); | ||||
return; | return; | ||||
} | } | ||||
error = nvdimm_spa_init1(nfitbl); | error = nvdimm_spa_init1(nfitbl); | ||||
if (error != 0) | if (error != 0) | ||||
printf("nvdimm_spa_g_init: error %d\n", error); | printf("nvdimm_spa_g_init: error %d\n", error); | ||||
AcpiPutTable(&nfitbl->Header); | AcpiPutTable(&nfitbl->Header); | ||||
} | } | ||||
static void | static int | ||||
nvdimm_spa_g_fini(struct g_class *mp __unused) | nvdimm_spa_g_destroy_geom(struct gctl_req *req, struct g_class *cp, | ||||
struct g_geom *gp) | |||||
{ | { | ||||
int i; | struct SPA_mapping *spa; | ||||
if (spa_mappings == NULL) | spa = gp->softc; | ||||
return; | nvdimm_spa_fini_one(spa); | ||||
for (i = 0; i < spa_mappings_cnt; i++) | free(spa, M_NVDIMM); | ||||
nvdimm_spa_fini_one(&spa_mappings[i]); | return (0); | ||||
free(spa_mappings, M_NVDIMM); | |||||
spa_mappings = NULL; | |||||
spa_mappings_cnt = 0; | |||||
} | } |