Merge branch 'for-4.9/libnvdimm' into libnvdimm-for-next
[deliverable/linux.git] / tools / testing / nvdimm / test / nfit.c
index dd48f421844c7902773526d8c0845109ab9c5e55..99ea68674f0a99d5baae862dae802f4452f0c7df 100644 (file)
@@ -154,11 +154,14 @@ struct nfit_test {
        int (*alloc)(struct nfit_test *t);
        void (*setup)(struct nfit_test *t);
        int setup_hotplug;
+       union acpi_object **_fit;
+       dma_addr_t _fit_dma;
        struct ars_state {
                struct nd_cmd_ars_status *ars_status;
                unsigned long deadline;
                spinlock_t lock;
        } ars_state;
+       struct device *dimm_dev[NUM_DCR];
 };
 
 static struct nfit_test *to_nfit_test(struct device *dev)
@@ -428,6 +431,9 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
                        break;
                case ND_CMD_SMART_THRESHOLD:
                        rc = nfit_test_cmd_smart_threshold(buf, buf_len);
+                       device_lock(&t->pdev.dev);
+                       __acpi_nvdimm_notify(t->dimm_dev[i], 0x81);
+                       device_unlock(&t->pdev.dev);
                        break;
                default:
                        return -ENOTTY;
@@ -564,6 +570,18 @@ static int ars_state_init(struct device *dev, struct ars_state *ars_state)
        return 0;
 }
 
+static void put_dimms(void *data)
+{
+       struct device **dimm_dev = data;
+       int i;
+
+       for (i = 0; i < NUM_DCR; i++)
+               if (dimm_dev[i])
+                       device_unregister(dimm_dev[i]);
+}
+
+static struct class *nfit_test_dimm;
+
 static int nfit_test0_alloc(struct nfit_test *t)
 {
        size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA
@@ -615,6 +633,19 @@ static int nfit_test0_alloc(struct nfit_test *t)
                        return -ENOMEM;
        }
 
+       t->_fit = test_alloc(t, sizeof(union acpi_object **), &t->_fit_dma);
+       if (!t->_fit)
+               return -ENOMEM;
+
+       if (devm_add_action_or_reset(&t->pdev.dev, put_dimms, t->dimm_dev))
+               return -ENOMEM;
+       for (i = 0; i < NUM_DCR; i++) {
+               t->dimm_dev[i] = device_create(nfit_test_dimm, &t->pdev.dev, 0,
+                               NULL, "test_dimm%d", i);
+               if (!t->dimm_dev[i])
+                       return -ENOMEM;
+       }
+
        return ars_state_init(&t->pdev.dev, &t->ars_state);
 }
 
@@ -1408,6 +1439,8 @@ static int nfit_test_probe(struct platform_device *pdev)
        struct acpi_nfit_desc *acpi_desc;
        struct device *dev = &pdev->dev;
        struct nfit_test *nfit_test;
+       struct nfit_mem *nfit_mem;
+       union acpi_object *obj;
        int rc;
 
        nfit_test = to_nfit_test(&pdev->dev);
@@ -1475,14 +1508,30 @@ static int nfit_test_probe(struct platform_device *pdev)
        if (nfit_test->setup != nfit_test0_setup)
                return 0;
 
-       flush_work(&acpi_desc->work);
        nfit_test->setup_hotplug = 1;
        nfit_test->setup(nfit_test);
 
-       rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_buf,
-                       nfit_test->nfit_size);
-       if (rc)
-               return rc;
+       obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+       if (!obj)
+               return -ENOMEM;
+       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);
+
+       /* associate dimm devices with nfit_mem data for notification testing */
+       mutex_lock(&acpi_desc->init_mutex);
+       list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
+               u32 nfit_handle = __to_nfit_memdev(nfit_mem)->device_handle;
+               int i;
+
+               for (i = 0; i < NUM_DCR; i++)
+                       if (nfit_handle == handle[i])
+                               dev_set_drvdata(nfit_test->dimm_dev[i],
+                                               nfit_mem);
+       }
+       mutex_unlock(&acpi_desc->init_mutex);
 
        return 0;
 }
@@ -1517,6 +1566,10 @@ static __init int nfit_test_init(void)
 {
        int rc, i;
 
+       nfit_test_dimm = class_create(THIS_MODULE, "nfit_test_dimm");
+       if (IS_ERR(nfit_test_dimm))
+               return PTR_ERR(nfit_test_dimm);
+
        nfit_test_setup(nfit_test_lookup);
 
        for (i = 0; i < NUM_NFITS; i++) {
@@ -1583,6 +1636,7 @@ static __exit void nfit_test_exit(void)
        for (i = 0; i < NUM_NFITS; i++)
                platform_device_unregister(&instances[i]->pdev);
        nfit_test_teardown();
+       class_destroy(nfit_test_dimm);
 }
 
 module_init(nfit_test_init);
This page took 0.026937 seconds and 5 git commands to generate.