[ndctl PATCH v2] util: distinguish error codes for sysfs_{read, write}_attr()
by Dan Williams
There are occasions where it would be good to know the difference
between a sysfs attribute failing to be accessed because we could not
open versus could not read/write.
Cc: Linda Knippers <linda.knippers(a)hpe.com>
[ljk: just return the errno directly]
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
util/sysfs.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/util/sysfs.c b/util/sysfs.c
index 31d1a898eba2..4178aeced087 100644
--- a/util/sysfs.c
+++ b/util/sysfs.c
@@ -34,13 +34,13 @@ int __sysfs_read_attr(struct log_ctx *ctx, const char *path, char *buf)
if (fd < 0) {
log_dbg(ctx, "failed to open %s: %s\n", path, strerror(errno));
- return -1;
+ return -errno;
}
n = read(fd, buf, SYSFS_ATTR_SIZE);
close(fd);
if (n < 0 || n >= SYSFS_ATTR_SIZE) {
log_dbg(ctx, "failed to read %s: %s\n", path, strerror(errno));
- return -1;
+ return -errno;
}
buf[n] = 0;
if (n && buf[n-1] == '\n')
@@ -56,7 +56,7 @@ static int write_attr(struct log_ctx *ctx, const char *path,
if (fd < 0) {
log_dbg(ctx, "failed to open %s: %s\n", path, strerror(errno));
- return -1;
+ return -errno;
}
n = write(fd, buf, len);
close(fd);
@@ -64,7 +64,7 @@ static int write_attr(struct log_ctx *ctx, const char *path,
if (!quiet)
log_dbg(ctx, "failed to write %s to %s: %s\n", buf, path,
strerror(errno));
- return -1;
+ return -errno;
}
return 0;
}
5 years, 2 months
[ndctl PATCH] util: distinguish error codes for sysfs_{read, write}_attr()
by Dan Williams
There are occasions where it would be good to know the difference
between a sysfs attribute failing to be accessed because we could not
open versus could not read/write.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
util/sysfs.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/util/sysfs.c b/util/sysfs.c
index 31d1a898eba2..7905455890dc 100644
--- a/util/sysfs.c
+++ b/util/sysfs.c
@@ -34,13 +34,13 @@ int __sysfs_read_attr(struct log_ctx *ctx, const char *path, char *buf)
if (fd < 0) {
log_dbg(ctx, "failed to open %s: %s\n", path, strerror(errno));
- return -1;
+ return -ENOENT;
}
n = read(fd, buf, SYSFS_ATTR_SIZE);
close(fd);
if (n < 0 || n >= SYSFS_ATTR_SIZE) {
log_dbg(ctx, "failed to read %s: %s\n", path, strerror(errno));
- return -1;
+ return -EIO;
}
buf[n] = 0;
if (n && buf[n-1] == '\n')
@@ -56,7 +56,7 @@ static int write_attr(struct log_ctx *ctx, const char *path,
if (fd < 0) {
log_dbg(ctx, "failed to open %s: %s\n", path, strerror(errno));
- return -1;
+ return -ENOENT;
}
n = write(fd, buf, len);
close(fd);
@@ -64,7 +64,7 @@ static int write_attr(struct log_ctx *ctx, const char *path,
if (!quiet)
log_dbg(ctx, "failed to write %s to %s: %s\n", buf, path,
strerror(errno));
- return -1;
+ return -EIO;
}
return 0;
}
5 years, 2 months
[PATCH 0/3] Enable DSM pass thru for root functions
by Jerry Hoemann
The new ACPI 6.2 spec has added new NVDIMM root DSM functions
that managibility and test software needs to call.
This patch set enables the calling of root functions DSMs via the
pass thru mechanism.
Details
__nd_ioctl:
Check pass thru functions against nd_cmd_clear_to_send.
acpi_nfit_init_dsms:
Set additional bits in cmd_mask for new functions.
ndctl.h:
Define data structure for the new 6.2 functions.
Add new function names to nvdimm_bus_cmd_name.
Jerry Hoemann (3):
libnvdimm: passthru functions clear to send
acpi, nfit: Enable DSM pass thru for root functions.
libnvdimm: New ACPI 6.2 DSM functions
drivers/acpi/nfit/core.c | 3 ++-
drivers/nvdimm/bus.c | 4 +++-
include/uapi/linux/ndctl.h | 45 ++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 49 insertions(+), 3 deletions(-)
--
1.8.5.6
5 years, 2 months
[ndctl PATCH] ndctl, namespace: add ndctl_namespace_{set, get}_enforce_mode() support
by Dan Williams
The v1.2 namespace label specification includes an 'abstraction_guid' to
identify that a custom protocol is needed to access a namespace beyond
the base access mechanism (pmem vs blk-aperture). Previously these
custom protocols were discovered by probing for an info block at a
pre-defined location. Now, with this guid, the info block to probe and
the expected protocol to load can be hinted by the guid. This helps
prevent inadvertent access when an info block becomes corrupted or when
a given environment goes not have support for the protocol identified by
the guid.
The kernel's new 'holder_class' attribute is independent of the label
format and enables limiting the claim type for a namespace. For example,
setting holder_class to 'btt' prevents 'dax' and 'pfn' instances from
attaching to a namespace. In the v1.2 label case this setting is
persisted in the label, in the v1.1 label case this setting is
ephemeral / lost when the driver is unloaded.
Cc: Vishal Verma <vishal.l.verma(a)intel.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
ndctl/lib/libndctl.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
ndctl/lib/libndctl.sym | 2 ++
ndctl/libndctl.h.in | 7 ++++--
ndctl/namespace.c | 11 +++++++++
test/libndctl.c | 51 +++++++++++++++++++++++++++++++++++++++++
5 files changed, 128 insertions(+), 2 deletions(-)
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 4acebc05d6db..e0b49615aa88 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -268,6 +268,7 @@ struct ndctl_namespace {
int type, id, buf_len, raw_mode;
int generation;
unsigned long long resource, size;
+ enum ndctl_namespace_mode enforce_mode;
char *alt_name;
uuid_t uuid;
struct ndctl_lbasize lbasize;
@@ -2858,6 +2859,31 @@ static char *get_block_device(struct ndctl_ctx *ctx, const char *block_path)
static int parse_lbasize_supported(struct ndctl_ctx *ctx, const char *devname,
const char *buf, struct ndctl_lbasize *lba);
+static const char *enforce_id_to_name(enum ndctl_namespace_mode mode)
+{
+ static const char *id_to_name[] = {
+ [NDCTL_NS_MODE_MEMORY] = "pfn",
+ [NDCTL_NS_MODE_SAFE] = "btt", /* TODO: convert to btt2 */
+ [NDCTL_NS_MODE_RAW] = "",
+ [NDCTL_NS_MODE_DAX] = "dax",
+ [NDCTL_NS_MODE_UNKNOWN] = "<unknown>",
+ };
+
+ if (mode < NDCTL_NS_MODE_UNKNOWN && mode >= 0)
+ return id_to_name[mode];
+ return id_to_name[NDCTL_NS_MODE_UNKNOWN];
+}
+
+static enum ndctl_namespace_mode enforce_name_to_id(const char *name)
+{
+ int i;
+
+ for (i = 0; i < NDCTL_NS_MODE_UNKNOWN; i++)
+ if (strcmp(enforce_id_to_name(i), name) == 0)
+ return i;
+ return NDCTL_NS_MODE_UNKNOWN;
+}
+
static void *add_namespace(void *parent, int id, const char *ndns_base)
{
const char *devname = devpath_to_devname(ndns_base);
@@ -2903,6 +2929,10 @@ static void *add_namespace(void *parent, int id, const char *ndns_base)
if (sysfs_read_attr(ctx, path, buf) == 0)
ndns->numa_node = strtol(buf, NULL, 0);
+ sprintf(path, "%s/holder_class", ndns_base);
+ if (sysfs_read_attr(ctx, path, buf) == 0)
+ ndns->enforce_mode = enforce_name_to_id(buf);
+
switch (ndns->type) {
case ND_DEVICE_NAMESPACE_BLK:
sprintf(path, "%s/sector_size", ndns_base);
@@ -3150,6 +3180,35 @@ NDCTL_EXPORT enum ndctl_namespace_mode ndctl_namespace_get_mode(
return -ENXIO;
}
+NDCTL_EXPORT enum ndctl_namespace_mode ndctl_namespace_get_enforce_mode(
+ struct ndctl_namespace *ndns)
+{
+ return ndns->enforce_mode;
+}
+
+NDCTL_EXPORT int ndctl_namespace_set_enforce_mode(struct ndctl_namespace *ndns,
+ enum ndctl_namespace_mode mode)
+{
+ struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
+ char *path = ndns->ndns_buf;
+ int len = ndns->buf_len;
+ int rc;
+
+ if (mode < 0 || mode >= NDCTL_NS_MODE_UNKNOWN)
+ return -EINVAL;
+
+ if (snprintf(path, len, "%s/holder_class", ndns->ndns_path) >= len) {
+ err(ctx, "%s: buffer too small!\n",
+ ndctl_namespace_get_devname(ndns));
+ return -ENOMEM;
+ }
+
+ rc = sysfs_write_attr(ctx, path, enforce_id_to_name(mode));
+ if (rc >= 0)
+ ndns->enforce_mode = mode;
+ return rc;
+}
+
NDCTL_EXPORT int ndctl_namespace_is_valid(struct ndctl_namespace *ndns)
{
struct ndctl_region *region = ndctl_namespace_get_region(ndns);
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 9bc36a37a813..0e592435ff70 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -169,6 +169,8 @@ global:
ndctl_namespace_get_devname;
ndctl_namespace_get_block_device;
ndctl_namespace_get_mode;
+ ndctl_namespace_set_enforce_mode;
+ ndctl_namespace_get_enforce_mode;
ndctl_region_get_nstype;
ndctl_namespace_get_type;
ndctl_namespace_get_type_name;
diff --git a/ndctl/libndctl.h.in b/ndctl/libndctl.h.in
index 2c45d2daa81b..3943ad240062 100644
--- a/ndctl/libndctl.h.in
+++ b/ndctl/libndctl.h.in
@@ -489,10 +489,14 @@ enum ndctl_namespace_mode {
NDCTL_NS_MODE_SAFE,
NDCTL_NS_MODE_RAW,
NDCTL_NS_MODE_DAX,
- NDCTL_NS_MODE_UNKNOWN,
+ NDCTL_NS_MODE_UNKNOWN, /* must be last entry */
};
enum ndctl_namespace_mode ndctl_namespace_get_mode(
struct ndctl_namespace *ndns);
+enum ndctl_namespace_mode ndctl_namespace_get_enforce_mode(
+ struct ndctl_namespace *ndns);
+int ndctl_namespace_set_enforce_mode(struct ndctl_namespace *ndns,
+ enum ndctl_namespace_mode mode);
int ndctl_namespace_is_enabled(struct ndctl_namespace *ndns);
int ndctl_namespace_enable(struct ndctl_namespace *ndns);
int ndctl_namespace_disable(struct ndctl_namespace *ndns);
@@ -520,7 +524,6 @@ int ndctl_namespace_set_sector_size(struct ndctl_namespace *ndns,
int ndctl_namespace_get_raw_mode(struct ndctl_namespace *ndns);
int ndctl_namespace_set_raw_mode(struct ndctl_namespace *ndns, int raw_mode);
int ndctl_namespace_get_numa_node(struct ndctl_namespace *ndns);
-
struct ndctl_btt;
struct ndctl_btt *ndctl_btt_get_first(struct ndctl_region *region);
struct ndctl_btt *ndctl_btt_get_next(struct ndctl_btt *btt);
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
index 895e39bb8c7d..8f264c348f51 100644
--- a/ndctl/namespace.c
+++ b/ndctl/namespace.c
@@ -360,6 +360,15 @@ static int setup_namespace(struct ndctl_region *region,
try(ndctl_namespace, set_sector_size, ndns, p->sector_size);
uuid_generate(uuid);
+
+ /*
+ * Note, this call to ndctl_namespace_set_mode() is not error
+ * checked since kernels older than 4.13 do not support this
+ * property of namespaces and it is an opportunistic enforcement
+ * mechanism.
+ */
+ ndctl_namespace_set_enforce_mode(ndns, p->mode);
+
if (do_setup_pfn(ndns, p)) {
struct ndctl_pfn *pfn = ndctl_region_get_pfn_seed(region);
@@ -780,6 +789,8 @@ static int namespace_destroy(struct ndctl_region *region,
return rc;
}
+ ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_RAW);
+
if (pfn || btt || dax) {
rc = zero_info_block(ndns);
if (rc)
diff --git a/test/libndctl.c b/test/libndctl.c
index 0381ee2cdefb..24aff36fef62 100644
--- a/test/libndctl.c
+++ b/test/libndctl.c
@@ -736,6 +736,8 @@ static int __check_dax_create(struct ndctl_region *region,
enum ndctl_pfn_loc loc, uuid_t uuid)
{
struct ndctl_dax *dax_seed = ndctl_region_get_dax_seed(region);
+ struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
+ struct ndctl_test *test = ndctl_get_private_data(ctx);
enum ndctl_namespace_mode mode;
struct ndctl_dax *dax;
const char *devname;
@@ -753,6 +755,12 @@ static int __check_dax_create(struct ndctl_region *region,
* alignment is PAGE_SIZE
*/
ndctl_dax_set_align(dax, SZ_4K);
+
+ rc = ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_DAX);
+ if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0)) && rc < 0) {
+ fprintf(stderr, "%s: failed to enforce dax mode\n", devname);
+ return rc;
+ }
ndctl_dax_set_namespace(dax, ndns);
rc = ndctl_dax_enable(dax);
if (rc) {
@@ -838,6 +846,8 @@ static int __check_pfn_create(struct ndctl_region *region,
void *buf, enum ndctl_pfn_loc loc, uuid_t uuid)
{
struct ndctl_pfn *pfn_seed = ndctl_region_get_pfn_seed(region);
+ struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
+ struct ndctl_test *test = ndctl_get_private_data(ctx);
enum ndctl_namespace_mode mode;
struct ndctl_pfn *pfn;
const char *devname;
@@ -857,6 +867,11 @@ static int __check_pfn_create(struct ndctl_region *region,
* alignment is PAGE_SIZE
*/
ndctl_pfn_set_align(pfn, SZ_4K);
+ rc = ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_MEMORY);
+ if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0)) && rc < 0) {
+ fprintf(stderr, "%s: failed to enforce pfn mode\n", devname);
+ return rc;
+ }
ndctl_pfn_set_namespace(pfn, ndns);
rc = ndctl_pfn_enable(pfn);
if (rc) {
@@ -1067,6 +1082,12 @@ static int check_btt_create(struct ndctl_region *region, struct ndctl_namespace
devname = ndctl_btt_get_devname(btt);
ndctl_btt_set_uuid(btt, btt_s->uuid);
ndctl_btt_set_sector_size(btt, btt_s->sector_sizes[i]);
+ rc = ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_SAFE);
+ if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0)) && rc < 0) {
+ fprintf(stderr, "%s: failed to enforce btt mode\n", devname);
+ goto err;
+ }
+
ndctl_btt_set_namespace(btt, ndns);
rc = ndctl_btt_enable(btt);
if (namespace->ro == (rc == 0)) {
@@ -1237,9 +1258,12 @@ static int check_pfn_autodetect(struct ndctl_bus *bus,
struct namespace *namespace)
{
struct ndctl_region *region = ndctl_namespace_get_region(ndns);
+ struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
const char *devname = ndctl_namespace_get_devname(ndns);
+ struct ndctl_test *test = ndctl_get_private_data(ctx);
struct pfn *auto_pfn = namespace->pfn_settings;
struct ndctl_pfn *pfn, *found = NULL;
+ enum ndctl_namespace_mode mode;
ssize_t rc = -ENXIO;
char bdev[50];
int fd, ro;
@@ -1265,6 +1289,13 @@ static int check_pfn_autodetect(struct ndctl_bus *bus,
if (!found)
return -ENXIO;
+ mode = ndctl_namespace_get_enforce_mode(ndns);
+ if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0))
+ && mode != NDCTL_NS_MODE_MEMORY) {
+ fprintf(stderr, "%s expected enforce_mode pfn\n", devname);
+ return -ENXIO;
+ }
+
sprintf(bdev, "/dev/%s", ndctl_pfn_get_block_device(pfn));
fd = open(bdev, O_RDONLY);
if (fd < 0)
@@ -1324,9 +1355,12 @@ static int check_dax_autodetect(struct ndctl_bus *bus,
struct namespace *namespace)
{
struct ndctl_region *region = ndctl_namespace_get_region(ndns);
+ struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
const char *devname = ndctl_namespace_get_devname(ndns);
+ struct ndctl_test *test = ndctl_get_private_data(ctx);
struct dax *auto_dax = namespace->dax_settings;
struct ndctl_dax *dax, *found = NULL;
+ enum ndctl_namespace_mode mode;
ssize_t rc = -ENXIO;
char bdev[50];
int fd;
@@ -1352,6 +1386,13 @@ static int check_dax_autodetect(struct ndctl_bus *bus,
if (!found)
return -ENXIO;
+ mode = ndctl_namespace_get_enforce_mode(ndns);
+ if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0))
+ && mode != NDCTL_NS_MODE_DAX) {
+ fprintf(stderr, "%s expected enforce_mode dax\n", devname);
+ return -ENXIO;
+ }
+
rc = validate_dax(dax);
if (rc) {
fprintf(stderr, "%s: %s validate_dax failed\n", __func__,
@@ -1399,9 +1440,12 @@ static int check_btt_autodetect(struct ndctl_bus *bus,
struct namespace *namespace)
{
struct ndctl_region *region = ndctl_namespace_get_region(ndns);
+ struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
const char *devname = ndctl_namespace_get_devname(ndns);
+ struct ndctl_test *test = ndctl_get_private_data(ctx);
struct btt *auto_btt = namespace->btt_settings;
struct ndctl_btt *btt, *found = NULL;
+ enum ndctl_namespace_mode mode;
ssize_t rc = -ENXIO;
char bdev[50];
int fd, ro;
@@ -1427,6 +1471,13 @@ static int check_btt_autodetect(struct ndctl_bus *bus,
if (!found)
return -ENXIO;
+ mode = ndctl_namespace_get_enforce_mode(ndns);
+ if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0))
+ && mode != NDCTL_NS_MODE_SAFE) {
+ fprintf(stderr, "%s expected enforce_mode btt\n", devname);
+ return -ENXIO;
+ }
+
sprintf(bdev, "/dev/%s", ndctl_btt_get_block_device(btt));
fd = open(bdev, O_RDONLY);
if (fd < 0)
5 years, 2 months
[ndctl PATCH] test: update dpa-alloc for v1.2 labels
by Dan Williams
The v1.2 specification changes the default label size from 128 to 256.
Account for this difference by initializing DEFAULT_AVAILABLE_SLOTS from
sysfs directly, rather than hard-coding.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
test/dpa-alloc.c | 17 +++++------------
1 file changed, 5 insertions(+), 12 deletions(-)
diff --git a/test/dpa-alloc.c b/test/dpa-alloc.c
index 9c80fa3fc8c9..d13cf5dde66f 100644
--- a/test/dpa-alloc.c
+++ b/test/dpa-alloc.c
@@ -38,7 +38,6 @@ static const char *NFIT_PROVIDER0 = "nfit_test.0";
static const char *NFIT_PROVIDER1 = "nfit_test.1";
#define SZ_4K 0x1000UL
#define NUM_NAMESPACES 4
-#define DEFAULT_AVAILABLE_SLOTS 1015
struct test_dpa_namespace {
struct ndctl_namespace *ndns;
@@ -48,8 +47,8 @@ struct test_dpa_namespace {
static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
{
+ unsigned int default_available_slots, available_slots, i;
struct ndctl_region *region, *blk_region = NULL;
- unsigned int available_slots, i;
struct ndctl_namespace *ndns;
struct ndctl_dimm *dimm;
unsigned long size;
@@ -110,13 +109,7 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
return -ENXIO;
}
- available_slots = ndctl_dimm_get_available_labels(dimm);
- if (available_slots < DEFAULT_AVAILABLE_SLOTS) {
- fprintf(stderr, "%s: expected %d\n",
- ndctl_dimm_get_devname(dimm),
- DEFAULT_AVAILABLE_SLOTS);
- return -ENXIO;
- }
+ default_available_slots = ndctl_dimm_get_available_labels(dimm);
/* grow namespaces */
for (i = 0; i < ARRAY_SIZE(namespaces); i++) {
@@ -151,10 +144,10 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
}
available_slots = ndctl_dimm_get_available_labels(dimm);
- if (available_slots != DEFAULT_AVAILABLE_SLOTS
+ if (available_slots != default_available_slots
- ARRAY_SIZE(namespaces)) {
fprintf(stderr, "expected %ld slots available\n",
- DEFAULT_AVAILABLE_SLOTS
+ default_available_slots
- ARRAY_SIZE(namespaces));
return -ENOSPC;
}
@@ -278,7 +271,7 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
}
available_slots = ndctl_dimm_get_available_labels(dimm);
- if (available_slots != DEFAULT_AVAILABLE_SLOTS - 1) {
+ if (available_slots != default_available_slots - 1) {
fprintf(stderr, "mishandled slot count\n");
return -ENXIO;
}
5 years, 2 months
[PATCH] Add support of NVDIMM memory error notification in ACPI 6.2
by Toshi Kani
ACPI 6.2 defines a new ACPI notification value to NVDIMM Root Device
in Table 5-169.
0x81 Unconsumed Uncorrectable Memory Error Detected
Used to pro-actively notify OSPM of uncorrectable memory errors
detected (for example a memory scrubbing engine that continuously
scans the NVDIMMs memory). This is an optional notification. Only
locations that were mapped in to SPA by the platform will generate
a notification.
Add support of this notification value by initiating an ARS scan. This
will find new error locations and add their badblocks information.
Link: http://www.uefi.org/sites/default/files/resources/ACPI_6_2.pdf
Signed-off-by: Toshi Kani <toshi.kani(a)hpe.com>
Cc: Dan Williams <dan.j.williams(a)intel.com>
Cc: Rafael J. Wysocki <rjw(a)rjwysocki.net>
Cc: Vishal Verma <vishal.l.verma(a)intel.com>
---
drivers/acpi/nfit/core.c | 28 ++++++++++++++++++++++------
drivers/acpi/nfit/nfit.h | 1 +
2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 656acb5..cc22778 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -2967,7 +2967,7 @@ static int acpi_nfit_remove(struct acpi_device *adev)
return 0;
}
-void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event)
+static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle)
{
struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(dev);
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -2975,11 +2975,6 @@ void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event)
acpi_status status;
int ret;
- dev_dbg(dev, "%s: event: %d\n", __func__, event);
-
- if (event != NFIT_NOTIFY_UPDATE)
- return;
-
if (!dev->driver) {
/* dev->driver may be null if we're being removed */
dev_dbg(dev, "%s: no driver found for dev\n", __func__);
@@ -3016,6 +3011,27 @@ void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event)
dev_err(dev, "Invalid _FIT\n");
kfree(buf.pointer);
}
+
+static void acpi_nfit_uc_error_notify(struct device *dev, acpi_handle handle)
+{
+ struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(dev);
+
+ acpi_nfit_ars_rescan(acpi_desc);
+}
+
+void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event)
+{
+ dev_dbg(dev, "%s: event: 0x%x\n", __func__, event);
+
+ switch (event) {
+ case NFIT_NOTIFY_UPDATE:
+ return acpi_nfit_update_notify(dev, handle);
+ case NFIT_NOTIFY_UC_MEMORY_ERROR:
+ return acpi_nfit_uc_error_notify(dev, handle);
+ default:
+ return;
+ }
+}
EXPORT_SYMBOL_GPL(__acpi_nfit_notify);
static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h
index 58fb7d6..6cf9d21 100644
--- a/drivers/acpi/nfit/nfit.h
+++ b/drivers/acpi/nfit/nfit.h
@@ -80,6 +80,7 @@ enum {
enum nfit_root_notifiers {
NFIT_NOTIFY_UPDATE = 0x80,
+ NFIT_NOTIFY_UC_MEMORY_ERROR = 0x81,
};
enum nfit_dimm_notifiers {
5 years, 2 months
如何制作一个优秀的PPT报告和演示
by 您好:
您好:
收件人: "linux-nvdimm"<linux-nvdimm(a)lists.01.org>;
制作报表、报告,做产品演示(PPT)是企业白领几乎每天都要进行的工作
通过报告和演示
董事会从中了解公司的运营情况
领导从中了解您的成果和能力
客户从中了解产品的优势和特点
项目成员从中了解目前的进展和下一步的工作。
*详*情*请*查*阅*附*件*大*纲*
5 years, 2 months
掌握合伙人的甄选、估值、分钱、退出机制
by 于总
------------------ 原始邮件 ------------------
收件人: "linux-nvdimm"<linux-nvdimm(a)lists.01.org>;
详 细 课 程 大 纲 请 阅 读 附 件
5 years, 2 months
转发:/绩效管理推进及薪酬体系设计
by 请您查阅信件
世纪实业(广西)有限公司
收件人: "linux-nvdimm"<linux-nvdimm(a)lists.01.org>;
详 情 请 查 阅 附 件 大 纲
5 years, 2 months