diff options
Diffstat (limited to 'tools/testing/nvdimm/test/nfit.c')
-rw-r--r-- | tools/testing/nvdimm/test/nfit.c | 352 |
1 files changed, 224 insertions, 128 deletions
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index c919866853a0..c9a6458cb63e 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -13,6 +13,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/workqueue.h> #include <linux/libnvdimm.h> #include <linux/vmalloc.h> #include <linux/device.h> @@ -98,11 +99,13 @@ enum { NUM_PM = 3, NUM_DCR = 5, + NUM_HINTS = 8, NUM_BDW = NUM_DCR, NUM_SPA = NUM_PM + NUM_DCR + NUM_BDW, NUM_MEM = NUM_DCR + NUM_BDW + 2 /* spa0 iset */ + 4 /* spa1 iset */, DIMM_SIZE = SZ_32M, LABEL_SIZE = SZ_128K, + SPA_VCD_SIZE = SZ_4M, SPA0_SIZE = DIMM_SIZE, SPA1_SIZE = DIMM_SIZE*2, SPA2_SIZE = DIMM_SIZE, @@ -129,6 +132,8 @@ static u32 handle[NUM_DCR] = { [4] = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0), }; +static unsigned long dimm_fail_cmd_flags[NUM_DCR]; + struct nfit_test { struct acpi_nfit_desc acpi_desc; struct platform_device pdev; @@ -151,11 +156,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) @@ -408,6 +416,9 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, if (i >= ARRAY_SIZE(handle)) return -ENXIO; + if ((1 << func) & dimm_fail_cmd_flags[i]) + return -EIO; + switch (func) { case ND_CMD_GET_CONFIG_SIZE: rc = nfit_test_cmd_get_config_size(buf, buf_len); @@ -425,6 +436,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; @@ -464,18 +478,12 @@ static struct nfit_test *instances[NUM_NFITS]; static void release_nfit_res(void *data) { struct nfit_test_resource *nfit_res = data; - struct resource *res = nfit_res->res; spin_lock(&nfit_test_lock); list_del(&nfit_res->list); spin_unlock(&nfit_test_lock); - if (is_vmalloc_addr(nfit_res->buf)) - vfree(nfit_res->buf); - else - dma_free_coherent(nfit_res->dev, resource_size(res), - nfit_res->buf, res->start); - kfree(res); + vfree(nfit_res->buf); kfree(nfit_res); } @@ -483,12 +491,11 @@ static void *__test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma, void *buf) { struct device *dev = &t->pdev.dev; - struct resource *res = kzalloc(sizeof(*res) * 2, GFP_KERNEL); struct nfit_test_resource *nfit_res = kzalloc(sizeof(*nfit_res), GFP_KERNEL); int rc; - if (!res || !buf || !nfit_res) + if (!buf || !nfit_res) goto err; rc = devm_add_action(dev, release_nfit_res, nfit_res); if (rc) @@ -497,21 +504,19 @@ static void *__test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma, memset(buf, 0, size); nfit_res->dev = dev; nfit_res->buf = buf; - nfit_res->res = res; - res->start = *dma; - res->end = *dma + size - 1; - res->name = "NFIT"; + nfit_res->res.start = *dma; + nfit_res->res.end = *dma + size - 1; + nfit_res->res.name = "NFIT"; + spin_lock_init(&nfit_res->lock); + INIT_LIST_HEAD(&nfit_res->requests); spin_lock(&nfit_test_lock); list_add(&nfit_res->list, &t->resources); spin_unlock(&nfit_test_lock); return nfit_res->buf; err: - if (buf && !is_vmalloc_addr(buf)) - dma_free_coherent(dev, size, buf, *dma); - else if (buf) + if (buf) vfree(buf); - kfree(res); kfree(nfit_res); return NULL; } @@ -524,15 +529,6 @@ static void *test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma) return __test_alloc(t, size, dma, buf); } -static void *test_alloc_coherent(struct nfit_test *t, size_t size, - dma_addr_t *dma) -{ - struct device *dev = &t->pdev.dev; - void *buf = dma_alloc_coherent(dev, size, dma, GFP_KERNEL); - - return __test_alloc(t, size, dma, buf); -} - static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr) { int i; @@ -545,13 +541,13 @@ static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr) continue; spin_lock(&nfit_test_lock); list_for_each_entry(n, &t->resources, list) { - if (addr >= n->res->start && (addr < n->res->start - + resource_size(n->res))) { + if (addr >= n->res.start && (addr < n->res.start + + resource_size(&n->res))) { nfit_res = n; break; } else if (addr >= (unsigned long) n->buf && (addr < (unsigned long) n->buf - + resource_size(n->res))) { + + resource_size(&n->res))) { nfit_res = n; break; } @@ -576,6 +572,86 @@ 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 dimm_name_to_id(struct device *dev) +{ + int dimm; + + if (sscanf(dev_name(dev), "test_dimm%d", &dimm) != 1 + || dimm >= NUM_DCR || dimm < 0) + return -ENXIO; + return dimm; +} + + +static ssize_t handle_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int dimm = dimm_name_to_id(dev); + + if (dimm < 0) + return dimm; + + return sprintf(buf, "%#x", handle[dimm]); +} +DEVICE_ATTR_RO(handle); + +static ssize_t fail_cmd_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int dimm = dimm_name_to_id(dev); + + if (dimm < 0) + return dimm; + + return sprintf(buf, "%#lx\n", dimm_fail_cmd_flags[dimm]); +} + +static ssize_t fail_cmd_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + int dimm = dimm_name_to_id(dev); + unsigned long val; + ssize_t rc; + + if (dimm < 0) + return dimm; + + rc = kstrtol(buf, 0, &val); + if (rc) + return rc; + + dimm_fail_cmd_flags[dimm] = val; + return size; +} +static DEVICE_ATTR_RW(fail_cmd); + +static struct attribute *nfit_test_dimm_attributes[] = { + &dev_attr_fail_cmd.attr, + &dev_attr_handle.attr, + NULL, +}; + +static struct attribute_group nfit_test_dimm_attribute_group = { + .attrs = nfit_test_dimm_attributes, +}; + +static const struct attribute_group *nfit_test_dimm_attribute_groups[] = { + &nfit_test_dimm_attribute_group, + NULL, +}; + static int nfit_test0_alloc(struct nfit_test *t) { size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA @@ -584,7 +660,8 @@ static int nfit_test0_alloc(struct nfit_test *t) + offsetof(struct acpi_nfit_control_region, window_size) * NUM_DCR + sizeof(struct acpi_nfit_data_region) * NUM_BDW - + sizeof(struct acpi_nfit_flush_address) * NUM_DCR; + + (sizeof(struct acpi_nfit_flush_address) + + sizeof(u64) * NUM_HINTS) * NUM_DCR; int i; t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); @@ -592,15 +669,15 @@ static int nfit_test0_alloc(struct nfit_test *t) return -ENOMEM; t->nfit_size = nfit_size; - t->spa_set[0] = test_alloc_coherent(t, SPA0_SIZE, &t->spa_set_dma[0]); + t->spa_set[0] = test_alloc(t, SPA0_SIZE, &t->spa_set_dma[0]); if (!t->spa_set[0]) return -ENOMEM; - t->spa_set[1] = test_alloc_coherent(t, SPA1_SIZE, &t->spa_set_dma[1]); + t->spa_set[1] = test_alloc(t, SPA1_SIZE, &t->spa_set_dma[1]); if (!t->spa_set[1]) return -ENOMEM; - t->spa_set[2] = test_alloc_coherent(t, SPA0_SIZE, &t->spa_set_dma[2]); + t->spa_set[2] = test_alloc(t, SPA0_SIZE, &t->spa_set_dma[2]); if (!t->spa_set[2]) return -ENOMEM; @@ -614,7 +691,9 @@ static int nfit_test0_alloc(struct nfit_test *t) return -ENOMEM; sprintf(t->label[i], "label%d", i); - t->flush[i] = test_alloc(t, 8, &t->flush_dma[i]); + t->flush[i] = test_alloc(t, max(PAGE_SIZE, + sizeof(u64) * NUM_HINTS), + &t->flush_dma[i]); if (!t->flush[i]) return -ENOMEM; } @@ -625,12 +704,27 @@ 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_with_groups(nfit_test_dimm, + &t->pdev.dev, 0, NULL, + nfit_test_dimm_attribute_groups, + "test_dimm%d", i); + if (!t->dimm_dev[i]) + return -ENOMEM; + } + return ars_state_init(&t->pdev.dev, &t->ars_state); } static int nfit_test1_alloc(struct nfit_test *t) { - size_t nfit_size = sizeof(struct acpi_nfit_system_address) + size_t nfit_size = sizeof(struct acpi_nfit_system_address) * 2 + sizeof(struct acpi_nfit_memory_map) + offsetof(struct acpi_nfit_control_region, window_size); @@ -639,15 +733,31 @@ static int nfit_test1_alloc(struct nfit_test *t) return -ENOMEM; t->nfit_size = nfit_size; - t->spa_set[0] = test_alloc_coherent(t, SPA2_SIZE, &t->spa_set_dma[0]); + t->spa_set[0] = test_alloc(t, SPA2_SIZE, &t->spa_set_dma[0]); if (!t->spa_set[0]) return -ENOMEM; + t->spa_set[1] = test_alloc(t, SPA_VCD_SIZE, &t->spa_set_dma[1]); + if (!t->spa_set[1]) + return -ENOMEM; + return ars_state_init(&t->pdev.dev, &t->ars_state); } +static void dcr_common_init(struct acpi_nfit_control_region *dcr) +{ + dcr->vendor_id = 0xabcd; + dcr->device_id = 0; + dcr->revision_id = 1; + dcr->valid_fields = 1; + dcr->manufacturing_location = 0xa; + dcr->manufacturing_date = cpu_to_be16(2016); +} + static void nfit_test0_setup(struct nfit_test *t) { + const int flush_hint_size = sizeof(struct acpi_nfit_flush_address) + + (sizeof(u64) * NUM_HINTS); struct acpi_nfit_desc *acpi_desc; struct acpi_nfit_memory_map *memdev; void *nfit_buf = t->nfit_buf; @@ -655,7 +765,7 @@ static void nfit_test0_setup(struct nfit_test *t) struct acpi_nfit_control_region *dcr; struct acpi_nfit_data_region *bdw; struct acpi_nfit_flush_address *flush; - unsigned int offset; + unsigned int offset, i; /* * spa0 (interleave first half of dimm0 and dimm1, note storage @@ -972,9 +1082,7 @@ static void nfit_test0_setup(struct nfit_test *t) dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; dcr->header.length = sizeof(struct acpi_nfit_control_region); dcr->region_index = 0+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~handle[0]; dcr->code = NFIT_FIC_BLK; dcr->windows = 1; @@ -989,9 +1097,7 @@ static void nfit_test0_setup(struct nfit_test *t) dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; dcr->header.length = sizeof(struct acpi_nfit_control_region); dcr->region_index = 1+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~handle[1]; dcr->code = NFIT_FIC_BLK; dcr->windows = 1; @@ -1006,9 +1112,7 @@ static void nfit_test0_setup(struct nfit_test *t) dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; dcr->header.length = sizeof(struct acpi_nfit_control_region); dcr->region_index = 2+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~handle[2]; dcr->code = NFIT_FIC_BLK; dcr->windows = 1; @@ -1023,9 +1127,7 @@ static void nfit_test0_setup(struct nfit_test *t) dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; dcr->header.length = sizeof(struct acpi_nfit_control_region); dcr->region_index = 3+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~handle[3]; dcr->code = NFIT_FIC_BLK; dcr->windows = 1; @@ -1042,9 +1144,7 @@ static void nfit_test0_setup(struct nfit_test *t) dcr->header.length = offsetof(struct acpi_nfit_control_region, window_size); dcr->region_index = 4+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~handle[0]; dcr->code = NFIT_FIC_BYTEN; dcr->windows = 0; @@ -1056,9 +1156,7 @@ static void nfit_test0_setup(struct nfit_test *t) dcr->header.length = offsetof(struct acpi_nfit_control_region, window_size); dcr->region_index = 5+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~handle[1]; dcr->code = NFIT_FIC_BYTEN; dcr->windows = 0; @@ -1070,9 +1168,7 @@ static void nfit_test0_setup(struct nfit_test *t) dcr->header.length = offsetof(struct acpi_nfit_control_region, window_size); dcr->region_index = 6+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~handle[2]; dcr->code = NFIT_FIC_BYTEN; dcr->windows = 0; @@ -1084,9 +1180,7 @@ static void nfit_test0_setup(struct nfit_test *t) dcr->header.length = offsetof(struct acpi_nfit_control_region, window_size); dcr->region_index = 7+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~handle[3]; dcr->code = NFIT_FIC_BYTEN; dcr->windows = 0; @@ -1141,45 +1235,47 @@ static void nfit_test0_setup(struct nfit_test *t) /* flush0 (dimm0) */ flush = nfit_buf + offset; flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; - flush->header.length = sizeof(struct acpi_nfit_flush_address); + flush->header.length = flush_hint_size; flush->device_handle = handle[0]; - flush->hint_count = 1; - flush->hint_address[0] = t->flush_dma[0]; + flush->hint_count = NUM_HINTS; + for (i = 0; i < NUM_HINTS; i++) + flush->hint_address[i] = t->flush_dma[0] + i * sizeof(u64); /* flush1 (dimm1) */ - flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 1; + flush = nfit_buf + offset + flush_hint_size * 1; flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; - flush->header.length = sizeof(struct acpi_nfit_flush_address); + flush->header.length = flush_hint_size; flush->device_handle = handle[1]; - flush->hint_count = 1; - flush->hint_address[0] = t->flush_dma[1]; + flush->hint_count = NUM_HINTS; + for (i = 0; i < NUM_HINTS; i++) + flush->hint_address[i] = t->flush_dma[1] + i * sizeof(u64); /* flush2 (dimm2) */ - flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 2; + flush = nfit_buf + offset + flush_hint_size * 2; flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; - flush->header.length = sizeof(struct acpi_nfit_flush_address); + flush->header.length = flush_hint_size; flush->device_handle = handle[2]; - flush->hint_count = 1; - flush->hint_address[0] = t->flush_dma[2]; + flush->hint_count = NUM_HINTS; + for (i = 0; i < NUM_HINTS; i++) + flush->hint_address[i] = t->flush_dma[2] + i * sizeof(u64); /* flush3 (dimm3) */ - flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 3; + flush = nfit_buf + offset + flush_hint_size * 3; flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; - flush->header.length = sizeof(struct acpi_nfit_flush_address); + flush->header.length = flush_hint_size; flush->device_handle = handle[3]; - flush->hint_count = 1; - flush->hint_address[0] = t->flush_dma[3]; + flush->hint_count = NUM_HINTS; + for (i = 0; i < NUM_HINTS; i++) + flush->hint_address[i] = t->flush_dma[3] + i * sizeof(u64); if (t->setup_hotplug) { - offset = offset + sizeof(struct acpi_nfit_flush_address) * 4; + offset = offset + flush_hint_size * 4; /* dcr-descriptor4: blk */ dcr = nfit_buf + offset; dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; dcr->header.length = sizeof(struct acpi_nfit_control_region); dcr->region_index = 8+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~handle[4]; dcr->code = NFIT_FIC_BLK; dcr->windows = 1; @@ -1196,9 +1292,7 @@ static void nfit_test0_setup(struct nfit_test *t) dcr->header.length = offsetof(struct acpi_nfit_control_region, window_size); dcr->region_index = 9+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~handle[4]; dcr->code = NFIT_FIC_BYTEN; dcr->windows = 0; @@ -1300,10 +1394,12 @@ static void nfit_test0_setup(struct nfit_test *t) /* flush3 (dimm4) */ flush = nfit_buf + offset; flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; - flush->header.length = sizeof(struct acpi_nfit_flush_address); + flush->header.length = flush_hint_size; flush->device_handle = handle[4]; - flush->hint_count = 1; - flush->hint_address[0] = t->flush_dma[4]; + flush->hint_count = NUM_HINTS; + for (i = 0; i < NUM_HINTS; i++) + flush->hint_address[i] = t->flush_dma[4] + + i * sizeof(u64); } post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); @@ -1339,7 +1435,16 @@ static void nfit_test1_setup(struct nfit_test *t) spa->address = t->spa_set_dma[0]; spa->length = SPA2_SIZE; - offset += sizeof(*spa); + /* virtual cd region */ + spa = nfit_buf + sizeof(*spa); + spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; + spa->header.length = sizeof(*spa); + memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_VCD), 16); + spa->range_index = 0; + spa->address = t->spa_set_dma[1]; + spa->length = SPA_VCD_SIZE; + + offset += sizeof(*spa) * 2; /* mem-region0 (spa0, dimm0) */ memdev = nfit_buf + offset; memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; @@ -1365,9 +1470,7 @@ static void nfit_test1_setup(struct nfit_test *t) dcr->header.length = offsetof(struct acpi_nfit_control_region, window_size); dcr->region_index = 0+1; - dcr->vendor_id = 0xabcd; - dcr->device_id = 0; - dcr->revision_id = 1; + dcr_common_init(dcr); dcr->serial_number = ~0; dcr->code = NFIT_FIC_BYTE; dcr->windows = 0; @@ -1409,6 +1512,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); @@ -1462,20 +1567,16 @@ static int nfit_test_probe(struct platform_device *pdev) nfit_test->setup(nfit_test); acpi_desc = &nfit_test->acpi_desc; acpi_nfit_desc_init(acpi_desc, &pdev->dev); - acpi_desc->nfit = nfit_test->nfit_buf; acpi_desc->blk_do_io = nfit_test_blk_do_io; nd_desc = &acpi_desc->nd_desc; nd_desc->provider_name = NULL; + nd_desc->module = THIS_MODULE; nd_desc->ndctl = nfit_test_ctl; - acpi_desc->nvdimm_bus = nvdimm_bus_register(&pdev->dev, nd_desc); - if (!acpi_desc->nvdimm_bus) - return -ENXIO; - rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_size); - if (rc) { - nvdimm_bus_unregister(acpi_desc->nvdimm_bus); + rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_buf, + nfit_test->nfit_size); + if (rc) return rc; - } if (nfit_test->setup != nfit_test0_setup) return 0; @@ -1483,22 +1584,33 @@ static int nfit_test_probe(struct platform_device *pdev) nfit_test->setup_hotplug = 1; nfit_test->setup(nfit_test); - rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_size); - if (rc) { - nvdimm_bus_unregister(acpi_desc->nvdimm_bus); - 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; } static int nfit_test_remove(struct platform_device *pdev) { - struct nfit_test *nfit_test = to_nfit_test(&pdev->dev); - struct acpi_nfit_desc *acpi_desc = &nfit_test->acpi_desc; - - nvdimm_bus_unregister(acpi_desc->nvdimm_bus); - return 0; } @@ -1523,22 +1635,19 @@ static struct platform_driver nfit_test_driver = { .id_table = nfit_test_id, }; -#ifdef CONFIG_CMA_SIZE_MBYTES -#define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES -#else -#define CMA_SIZE_MBYTES 0 -#endif - 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++) { struct nfit_test *nfit_test; struct platform_device *pdev; - static int once; nfit_test = kzalloc(sizeof(*nfit_test), GFP_KERNEL); if (!nfit_test) { @@ -1577,20 +1686,6 @@ static __init int nfit_test_init(void) goto err_register; instances[i] = nfit_test; - - if (!once++) { - dma_addr_t dma; - void *buf; - - buf = dma_alloc_coherent(&pdev->dev, SZ_128M, &dma, - GFP_KERNEL); - if (!buf) { - rc = -ENOMEM; - dev_warn(&pdev->dev, "need 128M of free cma\n"); - goto err_register; - } - dma_free_coherent(&pdev->dev, SZ_128M, buf, dma); - } } rc = platform_driver_register(&nfit_test_driver); @@ -1614,6 +1709,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); |