Commit c14a868a authored by Dan Williams's avatar Dan Williams

tools/testing/nvdimm: unit test for acpi_nfit_notify()

We have had a couple bugs in this implementation in the past and before
we add another ->notify() implementation for nvdimm devices, lets allow
this routine to be exercised via nfit_test.

Rewrite acpi_nfit_notify() in terms of a generic struct device and
acpi_handle parameter, and then implement a mock acpi_evaluate_object()
that returns a _FIT payload.

Cc: Vishal Verma <vishal.l.verma@intel.com>
Reviewed-by: default avatarVishal Verma <vishal.l.verma@intel.com>
Acked-by: default avatarRafael J. Wysocki <rafael@kernel.org>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent c09f1218
...@@ -2670,11 +2670,10 @@ static int acpi_nfit_remove(struct acpi_device *adev) ...@@ -2670,11 +2670,10 @@ static int acpi_nfit_remove(struct acpi_device *adev)
return 0; return 0;
} }
static void acpi_nfit_notify(struct acpi_device *adev, u32 event) void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event)
{ {
struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(&adev->dev); struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(dev);
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
struct device *dev = &adev->dev;
union acpi_object *obj; union acpi_object *obj;
acpi_status status; acpi_status status;
int ret; int ret;
...@@ -2684,18 +2683,17 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event) ...@@ -2684,18 +2683,17 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
if (event != NFIT_NOTIFY_UPDATE) if (event != NFIT_NOTIFY_UPDATE)
return; return;
device_lock(dev);
if (!dev->driver) { if (!dev->driver) {
/* dev->driver may be null if we're being removed */ /* dev->driver may be null if we're being removed */
dev_dbg(dev, "%s: no driver found for dev\n", __func__); dev_dbg(dev, "%s: no driver found for dev\n", __func__);
goto out_unlock; return;
} }
if (!acpi_desc) { if (!acpi_desc) {
acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL); acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);
if (!acpi_desc) if (!acpi_desc)
goto out_unlock; return;
acpi_nfit_desc_init(acpi_desc, &adev->dev); acpi_nfit_desc_init(acpi_desc, dev);
} else { } else {
/* /*
* Finish previous registration before considering new * Finish previous registration before considering new
...@@ -2705,10 +2703,10 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event) ...@@ -2705,10 +2703,10 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
} }
/* Evaluate _FIT */ /* Evaluate _FIT */
status = acpi_evaluate_object(adev->handle, "_FIT", NULL, &buf); status = acpi_evaluate_object(handle, "_FIT", NULL, &buf);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
dev_err(dev, "failed to evaluate _FIT\n"); dev_err(dev, "failed to evaluate _FIT\n");
goto out_unlock; return;
} }
obj = buf.pointer; obj = buf.pointer;
...@@ -2720,9 +2718,14 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event) ...@@ -2720,9 +2718,14 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
} else } else
dev_err(dev, "Invalid _FIT\n"); dev_err(dev, "Invalid _FIT\n");
kfree(buf.pointer); kfree(buf.pointer);
}
EXPORT_SYMBOL_GPL(__acpi_nfit_notify);
out_unlock: static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
device_unlock(dev); {
device_lock(&adev->dev);
__acpi_nfit_notify(&adev->dev, adev->handle, event);
device_unlock(&adev->dev);
} }
static const struct acpi_device_id acpi_nfit_ids[] = { static const struct acpi_device_id acpi_nfit_ids[] = {
......
...@@ -227,5 +227,6 @@ static inline struct acpi_nfit_desc *to_acpi_desc( ...@@ -227,5 +227,6 @@ static inline struct acpi_nfit_desc *to_acpi_desc(
const u8 *to_nfit_uuid(enum nfit_uuids id); const u8 *to_nfit_uuid(enum nfit_uuids id);
int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz); int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz);
void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event);
void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev); void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev);
#endif /* __NFIT_H__ */ #endif /* __NFIT_H__ */
...@@ -13,6 +13,7 @@ ldflags-y += --wrap=__release_region ...@@ -13,6 +13,7 @@ ldflags-y += --wrap=__release_region
ldflags-y += --wrap=devm_memremap_pages ldflags-y += --wrap=devm_memremap_pages
ldflags-y += --wrap=insert_resource ldflags-y += --wrap=insert_resource
ldflags-y += --wrap=remove_resource ldflags-y += --wrap=remove_resource
ldflags-y += --wrap=acpi_evaluate_object
DRIVERS := ../../../drivers DRIVERS := ../../../drivers
NVDIMM_SRC := $(DRIVERS)/nvdimm NVDIMM_SRC := $(DRIVERS)/nvdimm
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/pfn_t.h> #include <linux/pfn_t.h>
#include <linux/acpi.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mm.h> #include <linux/mm.h>
#include "nfit_test.h" #include "nfit_test.h"
...@@ -276,4 +277,20 @@ void __wrap___devm_release_region(struct device *dev, struct resource *parent, ...@@ -276,4 +277,20 @@ void __wrap___devm_release_region(struct device *dev, struct resource *parent,
} }
EXPORT_SYMBOL(__wrap___devm_release_region); EXPORT_SYMBOL(__wrap___devm_release_region);
acpi_status __wrap_acpi_evaluate_object(acpi_handle handle, acpi_string path,
struct acpi_object_list *p, struct acpi_buffer *buf)
{
struct nfit_test_resource *nfit_res = get_nfit_res((long) handle);
union acpi_object **obj;
if (!nfit_res || strcmp(path, "_FIT") || !buf)
return acpi_evaluate_object(handle, path, p, buf);
obj = nfit_res->buf;
buf->length = sizeof(union acpi_object);
buf->pointer = *obj;
return AE_OK;
}
EXPORT_SYMBOL(__wrap_acpi_evaluate_object);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -154,6 +154,8 @@ struct nfit_test { ...@@ -154,6 +154,8 @@ struct nfit_test {
int (*alloc)(struct nfit_test *t); int (*alloc)(struct nfit_test *t);
void (*setup)(struct nfit_test *t); void (*setup)(struct nfit_test *t);
int setup_hotplug; int setup_hotplug;
union acpi_object **_fit;
dma_addr_t _fit_dma;
struct ars_state { struct ars_state {
struct nd_cmd_ars_status *ars_status; struct nd_cmd_ars_status *ars_status;
unsigned long deadline; unsigned long deadline;
...@@ -615,6 +617,10 @@ static int nfit_test0_alloc(struct nfit_test *t) ...@@ -615,6 +617,10 @@ static int nfit_test0_alloc(struct nfit_test *t)
return -ENOMEM; return -ENOMEM;
} }
t->_fit = test_alloc(t, sizeof(union acpi_object **), &t->_fit_dma);
if (!t->_fit)
return -ENOMEM;
return ars_state_init(&t->pdev.dev, &t->ars_state); return ars_state_init(&t->pdev.dev, &t->ars_state);
} }
...@@ -1408,6 +1414,7 @@ static int nfit_test_probe(struct platform_device *pdev) ...@@ -1408,6 +1414,7 @@ static int nfit_test_probe(struct platform_device *pdev)
struct acpi_nfit_desc *acpi_desc; struct acpi_nfit_desc *acpi_desc;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct nfit_test *nfit_test; struct nfit_test *nfit_test;
union acpi_object *obj;
int rc; int rc;
nfit_test = to_nfit_test(&pdev->dev); nfit_test = to_nfit_test(&pdev->dev);
...@@ -1475,15 +1482,17 @@ static int nfit_test_probe(struct platform_device *pdev) ...@@ -1475,15 +1482,17 @@ static int nfit_test_probe(struct platform_device *pdev)
if (nfit_test->setup != nfit_test0_setup) if (nfit_test->setup != nfit_test0_setup)
return 0; return 0;
flush_work(&acpi_desc->work);
nfit_test->setup_hotplug = 1; nfit_test->setup_hotplug = 1;
nfit_test->setup(nfit_test); nfit_test->setup(nfit_test);
rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_buf, obj = kzalloc(sizeof(*obj), GFP_KERNEL);
nfit_test->nfit_size); if (!obj)
if (rc) return -ENOMEM;
return rc; obj->type = ACPI_TYPE_BUFFER;
obj->buffer.length = nfit_test->nfit_size;
obj->buffer.pointer = nfit_test->nfit_buf;
*(nfit_test->_fit) = obj;
__acpi_nfit_notify(&pdev->dev, nfit_test, 0x80);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment