Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/nvdimm/nvdimm_spa.c
Show First 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | #define UUID_INITIALIZER_VOLATILE_VIRTUAL_DISK \ | ||||
{0x77ab535a,0x45fc,0x624b,0x55,0x60,{0xf7,0xb2,0x81,0xd1,0xf9,0x6e}} | {0x77ab535a,0x45fc,0x624b,0x55,0x60,{0xf7,0xb2,0x81,0xd1,0xf9,0x6e}} | ||||
#define UUID_INITIALIZER_VOLATILE_VIRTUAL_CD \ | #define UUID_INITIALIZER_VOLATILE_VIRTUAL_CD \ | ||||
{0x3d5abd30,0x4175,0x87ce,0x6d,0x64,{0xd2,0xad,0xe5,0x23,0xc4,0xbb}} | {0x3d5abd30,0x4175,0x87ce,0x6d,0x64,{0xd2,0xad,0xe5,0x23,0xc4,0xbb}} | ||||
#define UUID_INITIALIZER_PERSISTENT_VIRTUAL_DISK \ | #define UUID_INITIALIZER_PERSISTENT_VIRTUAL_DISK \ | ||||
{0x5cea02c9,0x4d07,0x69d3,0x26,0x9f,{0x44,0x96,0xfb,0xe0,0x96,0xf9}} | {0x5cea02c9,0x4d07,0x69d3,0x26,0x9f,{0x44,0x96,0xfb,0xe0,0x96,0xf9}} | ||||
#define UUID_INITIALIZER_PERSISTENT_VIRTUAL_CD \ | #define UUID_INITIALIZER_PERSISTENT_VIRTUAL_CD \ | ||||
{0x08018188,0x42cd,0xbb48,0x10,0x0f,{0x53,0x87,0xd5,0x3d,0xed,0x3d}} | {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 { | static struct nvdimm_SPA_uuid_list_elm { | ||||
const char *u_name; | const char *u_name; | ||||
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 ", | ||||
.u_id = UUID_INITIALIZER_VOLATILE_MEMORY, | .u_id = UUID_INITIALIZER_VOLATILE_MEMORY, | ||||
▲ Show 20 Lines • Show All 308 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_fini_t nvdimm_spa_g_fini; | |||||
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, | |||||
.fini = nvdimm_spa_g_fini, | |||||
}; | }; | ||||
DECLARE_GEOM_CLASS(nvdimm_spa_g_class, g_spa); | DECLARE_GEOM_CLASS(nvdimm_spa_g_class, g_spa); | ||||
static int | int | ||||
nvdimm_spa_init_one(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr, | nvdimm_spa_init(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr, | ||||
int spa_type) | enum SPA_mapping_type spa_type) | ||||
{ | { | ||||
struct make_dev_args mda; | struct make_dev_args mda; | ||||
struct sglist *spa_sg; | struct sglist *spa_sg; | ||||
int error, error1; | int error, error1; | ||||
spa->spa_type = spa_type; | spa->spa_type = spa_type; | ||||
spa->spa_domain = ((nfitaddr->Flags & ACPI_NFIT_PROXIMITY_VALID) != 0) ? | spa->spa_domain = ((nfitaddr->Flags & ACPI_NFIT_PROXIMITY_VALID) != 0) ? | ||||
nfitaddr->ProximityDomain : -1; | nfitaddr->ProximityDomain : -1; | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | nvdimm_spa_init(struct SPA_mapping *spa, ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr, | ||||
error = kproc_create(nvdimm_spa_g_thread, spa, &spa->spa_g_proc, 0, 0, | error = kproc_create(nvdimm_spa_g_thread, spa, &spa->spa_g_proc, 0, 0, | ||||
"g_spa%d", spa->spa_nfit_idx); | "g_spa%d", spa->spa_nfit_idx); | ||||
if (error != 0) { | if (error != 0) { | ||||
printf("NVDIMM SPA%d cannot create geom worker, error %d\n", | printf("NVDIMM SPA%d cannot create geom worker, error %d\n", | ||||
spa->spa_nfit_idx, error); | spa->spa_nfit_idx, error); | ||||
if (error1 == 0) | if (error1 == 0) | ||||
error1 = error; | error1 = error; | ||||
} else { | } else { | ||||
g_topology_assert(); | g_topology_lock(); | ||||
spa->spa_g = g_new_geomf(&nvdimm_spa_g_class, "spa%d", | spa->spa_g = g_new_geomf(&nvdimm_spa_g_class, "spa%d", | ||||
spa->spa_nfit_idx); | spa->spa_nfit_idx); | ||||
spa->spa_g->softc = spa; | spa->spa_g->softc = spa; | ||||
spa->spa_p = g_new_providerf(spa->spa_g, "spa%d", | spa->spa_p = g_new_providerf(spa->spa_g, "spa%d", | ||||
spa->spa_nfit_idx); | spa->spa_nfit_idx); | ||||
spa->spa_p->mediasize = spa->spa_len; | spa->spa_p->mediasize = spa->spa_len; | ||||
spa->spa_p->sectorsize = DEV_BSIZE; | spa->spa_p->sectorsize = DEV_BSIZE; | ||||
spa->spa_p->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE | | spa->spa_p->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE | | ||||
G_PF_ACCEPT_UNMAPPED; | G_PF_ACCEPT_UNMAPPED; | ||||
g_error_provider(spa->spa_p, 0); | g_error_provider(spa->spa_p, 0); | ||||
spa->spa_g_devstat = devstat_new_entry("spa", spa->spa_nfit_idx, | spa->spa_g_devstat = devstat_new_entry("spa", spa->spa_nfit_idx, | ||||
DEV_BSIZE, DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT, | DEV_BSIZE, DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT, | ||||
DEVSTAT_PRIORITY_MAX); | DEVSTAT_PRIORITY_MAX); | ||||
g_topology_unlock(); | |||||
} | } | ||||
return (error1); | return (error1); | ||||
} | } | ||||
static void | void | ||||
nvdimm_spa_fini_one(struct SPA_mapping *spa) | nvdimm_spa_fini(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); | ||||
Show All 14 Lines | nvdimm_spa_fini(struct SPA_mapping *spa) | ||||
} | } | ||||
vm_object_deallocate(spa->spa_obj); | vm_object_deallocate(spa->spa_obj); | ||||
if (spa->spa_kva != NULL) { | if (spa->spa_kva != NULL) { | ||||
pmap_large_unmap(spa->spa_kva, spa->spa_len); | pmap_large_unmap(spa->spa_kva, spa->spa_len); | ||||
spa->spa_kva = NULL; | spa->spa_kva = NULL; | ||||
} | } | ||||
mtx_destroy(&spa->spa_g_mtx); | mtx_destroy(&spa->spa_g_mtx); | ||||
mtx_destroy(&spa->spa_g_stat_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; | |||||
} | } |