Date: Sun, 21 Feb 2021 00:50:15 GMT From: Ravi Pokala <rpokala@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: ea5a304c734f - stable/13 - nvdimm(4): Export NVDIMM health flags via sysctl Message-ID: <202102210050.11L0oFvs081014@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by rpokala: URL: https://cgit.FreeBSD.org/src/commit/?id=ea5a304c734f7e391dad9bea9a0dc9345d763f5a commit ea5a304c734f7e391dad9bea9a0dc9345d763f5a Author: Ravi Pokala <rpokala@FreeBSD.org> AuthorDate: 2021-02-16 08:03:32 +0000 Commit: Ravi Pokala <rpokala@FreeBSD.org> CommitDate: 2021-02-21 00:47:55 +0000 nvdimm(4): Export NVDIMM health flags via sysctl The ACPI NFIT specification defines a set of "NVDIMM State Flags". These flags are already reported by `acpidump -t', but this change makes them available on a per-device basis, in a format that is more easily parsed. To simplify this, introduce acpi_nfit_get_memory_maps_by_dimm(), which locates the (ACPI_NFIT_MEMORY_MAP)s associated with a given (nfit_handle_t). Reviewed by: mav, cem Tested by: mav, rpokala (version for stable/12) MFC after: 3 days Sponsored by: Panasas Differential Revision: https://reviews.freebsd.org/D28700 (cherry picked from commit bdde49b7c7232c6936525f84ffb90856a7cd8e74) --- sys/dev/nvdimm/nvdimm.c | 65 +++++++++++++++++++++++++++++++++++++++++++- sys/dev/nvdimm/nvdimm_nfit.c | 10 +++++++ sys/dev/nvdimm/nvdimm_var.h | 3 ++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/sys/dev/nvdimm/nvdimm.c b/sys/dev/nvdimm/nvdimm.c index 66638636ef0e..0df894e4d9b6 100644 --- a/sys/dev/nvdimm/nvdimm.c +++ b/sys/dev/nvdimm/nvdimm.c @@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/malloc.h> #include <sys/module.h> +#include <sys/sbuf.h> +#include <sys/sysctl.h> #include <sys/uuid.h> #include <contrib/dev/acpica/include/acpi.h> @@ -332,12 +334,21 @@ static int nvdimm_attach(device_t dev) { struct nvdimm_dev *nv; + struct sysctl_ctx_list *ctx; + struct sysctl_oid *oid; + struct sysctl_oid_list *children; + struct sbuf *sb; ACPI_TABLE_NFIT *nfitbl; ACPI_HANDLE handle; ACPI_STATUS status; - int error; + ACPI_NFIT_MEMORY_MAP **maps; + int error, i, num_maps; + uint16_t flags; nv = device_get_softc(dev); + ctx = device_get_sysctl_ctx(dev); + oid = device_get_sysctl_tree(dev); + children = SYSCTL_CHILDREN(oid); handle = nvdimm_root_get_acpi_handle(dev); MPASS(handle != NULL); nv->nv_dev = dev; @@ -351,6 +362,57 @@ nvdimm_attach(device_t dev) } acpi_nfit_get_flush_addrs(nfitbl, nv->nv_handle, &nv->nv_flush_addr, &nv->nv_flush_addr_cnt); + + /* + * Each NVDIMM should have at least one memory map associated with it. + * If any of the maps have one of the error flags set, reflect that in + * the overall status. + */ + acpi_nfit_get_memory_maps_by_dimm(nfitbl, nv->nv_handle, &maps, + &num_maps); + if (num_maps == 0) { + free(nv->nv_flush_addr, M_NVDIMM); + free(maps, M_NVDIMM); + device_printf(dev, "cannot find memory map\n"); + return (ENXIO); + } + flags = 0; + for (i = 0; i < num_maps; i++) { + flags |= maps[i]->Flags; + } + free(maps, M_NVDIMM); + + /* sbuf_new_auto(9) is M_WAITOK; no need to check for NULL. */ + sb = sbuf_new_auto(); + (void) sbuf_printf(sb, "0x%b", flags, + "\20" + "\001SAVE_FAILED" + "\002RESTORE_FAILED" + "\003FLUSH_FAILED" + "\004NOT_ARMED" + "\005HEALTH_OBSERVED" + "\006HEALTH_ENABLED" + "\007MAP_FAILED"); + error = sbuf_finish(sb); + if (error != 0) { + sbuf_delete(sb); + free(nv->nv_flush_addr, M_NVDIMM); + device_printf(dev, "cannot convert flags to string\n"); + return (error); + } + /* strdup(9) is M_WAITOK; no need to check for NULL. */ + nv->nv_flags_str = strdup(sbuf_data(sb), M_NVDIMM); + sbuf_delete(sb); + SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "flags", + CTLFLAG_RD | CTLFLAG_MPSAFE, nv->nv_flags_str, 0, + "NVDIMM State Flags"); + /* + * Anything other than HEALTH_ENABLED indicates a fault condition of + * some kind, so log if that's seen. + */ + if ((flags & ~ACPI_NFIT_MEM_HEALTH_ENABLED) != 0) + device_printf(dev, "flags: %s\n", nv->nv_flags_str); + AcpiPutTable(&nfitbl->Header); error = read_label_area_size(nv); if (error == 0) { @@ -370,6 +432,7 @@ nvdimm_detach(device_t dev) struct nvdimm_label_entry *label, *next; nv = device_get_softc(dev); + free(nv->nv_flags_str, M_NVDIMM); free(nv->nv_flush_addr, M_NVDIMM); free(nv->label_index, M_NVDIMM); SLIST_FOREACH_SAFE(label, &nv->labels, link, next) { diff --git a/sys/dev/nvdimm/nvdimm_nfit.c b/sys/dev/nvdimm/nvdimm_nfit.c index ae00b88f8018..7396393a3a2c 100644 --- a/sys/dev/nvdimm/nvdimm_nfit.c +++ b/sys/dev/nvdimm/nvdimm_nfit.c @@ -201,3 +201,13 @@ acpi_nfit_get_flush_addrs(ACPI_TABLE_NFIT *nfitbl, nfit_handle_t dimm, for (i = 0; i < subtable->HintCount; i++) (*listp)[i] = (uint64_t *)(intptr_t)subtable->HintAddress[i]; } + +void +acpi_nfit_get_memory_maps_by_dimm(ACPI_TABLE_NFIT *nfitbl, nfit_handle_t dimm, + ACPI_NFIT_MEMORY_MAP ***listp, int *countp) +{ + + malloc_find_matches(nfitbl, ACPI_NFIT_TYPE_MEMORY_MAP, + offsetof(ACPI_NFIT_MEMORY_MAP, DeviceHandle), UINT32_MAX, dimm, + (void ***)listp, countp); +} diff --git a/sys/dev/nvdimm/nvdimm_var.h b/sys/dev/nvdimm/nvdimm_var.h index d69b1a70d8df..d163698e0660 100644 --- a/sys/dev/nvdimm/nvdimm_var.h +++ b/sys/dev/nvdimm/nvdimm_var.h @@ -93,6 +93,7 @@ struct nvdimm_dev { device_t nv_dev; nfit_handle_t nv_handle; uint64_t **nv_flush_addr; + char *nv_flags_str; int nv_flush_addr_cnt; uint32_t label_area_size; uint32_t max_label_xfer; @@ -163,6 +164,8 @@ void acpi_nfit_get_control_region(ACPI_TABLE_NFIT *nfitbl, uint16_t control_region_index, ACPI_NFIT_CONTROL_REGION **out); void acpi_nfit_get_flush_addrs(ACPI_TABLE_NFIT *nfitbl, nfit_handle_t dimm, uint64_t ***listp, int *countp); +void acpi_nfit_get_memory_maps_by_dimm(ACPI_TABLE_NFIT *nfitbl, + nfit_handle_t dimm, ACPI_NFIT_MEMORY_MAP ***listp, int *countp); enum SPA_mapping_type nvdimm_spa_type_from_name(const char *); enum SPA_mapping_type nvdimm_spa_type_from_uuid(struct uuid *); bool nvdimm_spa_type_user_accessible(enum SPA_mapping_type);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202102210050.11L0oFvs081014>