19a27e109SSantosh Sivaraj // SPDX-License-Identifier: GPL-2.0-only 29a27e109SSantosh Sivaraj #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 39a27e109SSantosh Sivaraj 49a27e109SSantosh Sivaraj #include <linux/platform_device.h> 59a27e109SSantosh Sivaraj #include <linux/device.h> 69a27e109SSantosh Sivaraj #include <linux/module.h> 79a27e109SSantosh Sivaraj #include <linux/genalloc.h> 89a27e109SSantosh Sivaraj #include <linux/vmalloc.h> 99a27e109SSantosh Sivaraj #include <linux/dma-mapping.h> 109a27e109SSantosh Sivaraj #include <linux/list_sort.h> 119a27e109SSantosh Sivaraj #include <linux/libnvdimm.h> 129a27e109SSantosh Sivaraj #include <linux/ndctl.h> 139a27e109SSantosh Sivaraj #include <nd-core.h> 149a27e109SSantosh Sivaraj #include <linux/printk.h> 159a27e109SSantosh Sivaraj #include <linux/seq_buf.h> 169a27e109SSantosh Sivaraj 179a27e109SSantosh Sivaraj #include "../watermark.h" 189a27e109SSantosh Sivaraj #include "nfit_test.h" 199a27e109SSantosh Sivaraj #include "ndtest.h" 209a27e109SSantosh Sivaraj 219a27e109SSantosh Sivaraj enum { 229a27e109SSantosh Sivaraj DIMM_SIZE = SZ_32M, 239a27e109SSantosh Sivaraj LABEL_SIZE = SZ_128K, 249a27e109SSantosh Sivaraj NUM_INSTANCES = 2, 259a27e109SSantosh Sivaraj NUM_DCR = 4, 269a27e109SSantosh Sivaraj }; 279a27e109SSantosh Sivaraj 289a27e109SSantosh Sivaraj static struct ndtest_priv *instances[NUM_INSTANCES]; 299a27e109SSantosh Sivaraj static struct class *ndtest_dimm_class; 309a27e109SSantosh Sivaraj 319a27e109SSantosh Sivaraj static inline struct ndtest_priv *to_ndtest_priv(struct device *dev) 329a27e109SSantosh Sivaraj { 339a27e109SSantosh Sivaraj struct platform_device *pdev = to_platform_device(dev); 349a27e109SSantosh Sivaraj 359a27e109SSantosh Sivaraj return container_of(pdev, struct ndtest_priv, pdev); 369a27e109SSantosh Sivaraj } 379a27e109SSantosh Sivaraj 389a27e109SSantosh Sivaraj static int ndtest_ctl(struct nvdimm_bus_descriptor *nd_desc, 399a27e109SSantosh Sivaraj struct nvdimm *nvdimm, unsigned int cmd, void *buf, 409a27e109SSantosh Sivaraj unsigned int buf_len, int *cmd_rc) 419a27e109SSantosh Sivaraj { 429a27e109SSantosh Sivaraj struct ndtest_dimm *dimm; 439a27e109SSantosh Sivaraj int _cmd_rc; 449a27e109SSantosh Sivaraj 459a27e109SSantosh Sivaraj if (!cmd_rc) 469a27e109SSantosh Sivaraj cmd_rc = &_cmd_rc; 479a27e109SSantosh Sivaraj 489a27e109SSantosh Sivaraj *cmd_rc = 0; 499a27e109SSantosh Sivaraj 509a27e109SSantosh Sivaraj if (!nvdimm) 519a27e109SSantosh Sivaraj return -EINVAL; 529a27e109SSantosh Sivaraj 539a27e109SSantosh Sivaraj dimm = nvdimm_provider_data(nvdimm); 549a27e109SSantosh Sivaraj if (!dimm) 559a27e109SSantosh Sivaraj return -EINVAL; 569a27e109SSantosh Sivaraj 579a27e109SSantosh Sivaraj switch (cmd) { 589a27e109SSantosh Sivaraj case ND_CMD_GET_CONFIG_SIZE: 599a27e109SSantosh Sivaraj case ND_CMD_GET_CONFIG_DATA: 609a27e109SSantosh Sivaraj case ND_CMD_SET_CONFIG_DATA: 619a27e109SSantosh Sivaraj default: 629a27e109SSantosh Sivaraj return -EINVAL; 639a27e109SSantosh Sivaraj } 649a27e109SSantosh Sivaraj 659a27e109SSantosh Sivaraj return 0; 669a27e109SSantosh Sivaraj } 679a27e109SSantosh Sivaraj 68*107b04e9SSantosh Sivaraj static ssize_t compatible_show(struct device *dev, 69*107b04e9SSantosh Sivaraj struct device_attribute *attr, char *buf) 70*107b04e9SSantosh Sivaraj { 71*107b04e9SSantosh Sivaraj return sprintf(buf, "nvdimm_test"); 72*107b04e9SSantosh Sivaraj } 73*107b04e9SSantosh Sivaraj static DEVICE_ATTR_RO(compatible); 74*107b04e9SSantosh Sivaraj 75*107b04e9SSantosh Sivaraj static struct attribute *of_node_attributes[] = { 76*107b04e9SSantosh Sivaraj &dev_attr_compatible.attr, 77*107b04e9SSantosh Sivaraj NULL 78*107b04e9SSantosh Sivaraj }; 79*107b04e9SSantosh Sivaraj 80*107b04e9SSantosh Sivaraj static const struct attribute_group of_node_attribute_group = { 81*107b04e9SSantosh Sivaraj .name = "of_node", 82*107b04e9SSantosh Sivaraj .attrs = of_node_attributes, 83*107b04e9SSantosh Sivaraj }; 84*107b04e9SSantosh Sivaraj 85*107b04e9SSantosh Sivaraj static const struct attribute_group *ndtest_attribute_groups[] = { 86*107b04e9SSantosh Sivaraj &of_node_attribute_group, 87*107b04e9SSantosh Sivaraj NULL, 88*107b04e9SSantosh Sivaraj }; 89*107b04e9SSantosh Sivaraj 909a27e109SSantosh Sivaraj static int ndtest_bus_register(struct ndtest_priv *p) 919a27e109SSantosh Sivaraj { 929a27e109SSantosh Sivaraj p->bus_desc.ndctl = ndtest_ctl; 939a27e109SSantosh Sivaraj p->bus_desc.module = THIS_MODULE; 949a27e109SSantosh Sivaraj p->bus_desc.provider_name = NULL; 95*107b04e9SSantosh Sivaraj p->bus_desc.attr_groups = ndtest_attribute_groups; 969a27e109SSantosh Sivaraj 979a27e109SSantosh Sivaraj p->bus = nvdimm_bus_register(&p->pdev.dev, &p->bus_desc); 989a27e109SSantosh Sivaraj if (!p->bus) { 999a27e109SSantosh Sivaraj dev_err(&p->pdev.dev, "Error creating nvdimm bus %pOF\n", p->dn); 1009a27e109SSantosh Sivaraj return -ENOMEM; 1019a27e109SSantosh Sivaraj } 1029a27e109SSantosh Sivaraj 1039a27e109SSantosh Sivaraj return 0; 1049a27e109SSantosh Sivaraj } 1059a27e109SSantosh Sivaraj 1069a27e109SSantosh Sivaraj static int ndtest_remove(struct platform_device *pdev) 1079a27e109SSantosh Sivaraj { 1089a27e109SSantosh Sivaraj struct ndtest_priv *p = to_ndtest_priv(&pdev->dev); 1099a27e109SSantosh Sivaraj 1109a27e109SSantosh Sivaraj nvdimm_bus_unregister(p->bus); 1119a27e109SSantosh Sivaraj return 0; 1129a27e109SSantosh Sivaraj } 1139a27e109SSantosh Sivaraj 1149a27e109SSantosh Sivaraj static int ndtest_probe(struct platform_device *pdev) 1159a27e109SSantosh Sivaraj { 1169a27e109SSantosh Sivaraj struct ndtest_priv *p; 1179a27e109SSantosh Sivaraj 1189a27e109SSantosh Sivaraj p = to_ndtest_priv(&pdev->dev); 1199a27e109SSantosh Sivaraj if (ndtest_bus_register(p)) 1209a27e109SSantosh Sivaraj return -ENOMEM; 1219a27e109SSantosh Sivaraj 1229a27e109SSantosh Sivaraj platform_set_drvdata(pdev, p); 1239a27e109SSantosh Sivaraj 1249a27e109SSantosh Sivaraj return 0; 1259a27e109SSantosh Sivaraj } 1269a27e109SSantosh Sivaraj 1279a27e109SSantosh Sivaraj static const struct platform_device_id ndtest_id[] = { 1289a27e109SSantosh Sivaraj { KBUILD_MODNAME }, 1299a27e109SSantosh Sivaraj { }, 1309a27e109SSantosh Sivaraj }; 1319a27e109SSantosh Sivaraj 1329a27e109SSantosh Sivaraj static struct platform_driver ndtest_driver = { 1339a27e109SSantosh Sivaraj .probe = ndtest_probe, 1349a27e109SSantosh Sivaraj .remove = ndtest_remove, 1359a27e109SSantosh Sivaraj .driver = { 1369a27e109SSantosh Sivaraj .name = KBUILD_MODNAME, 1379a27e109SSantosh Sivaraj }, 1389a27e109SSantosh Sivaraj .id_table = ndtest_id, 1399a27e109SSantosh Sivaraj }; 1409a27e109SSantosh Sivaraj 1419a27e109SSantosh Sivaraj static void ndtest_release(struct device *dev) 1429a27e109SSantosh Sivaraj { 1439a27e109SSantosh Sivaraj struct ndtest_priv *p = to_ndtest_priv(dev); 1449a27e109SSantosh Sivaraj 1459a27e109SSantosh Sivaraj kfree(p); 1469a27e109SSantosh Sivaraj } 1479a27e109SSantosh Sivaraj 1489a27e109SSantosh Sivaraj static void cleanup_devices(void) 1499a27e109SSantosh Sivaraj { 1509a27e109SSantosh Sivaraj int i; 1519a27e109SSantosh Sivaraj 1529a27e109SSantosh Sivaraj for (i = 0; i < NUM_INSTANCES; i++) 1539a27e109SSantosh Sivaraj if (instances[i]) 1549a27e109SSantosh Sivaraj platform_device_unregister(&instances[i]->pdev); 1559a27e109SSantosh Sivaraj 1569a27e109SSantosh Sivaraj nfit_test_teardown(); 1579a27e109SSantosh Sivaraj 1589a27e109SSantosh Sivaraj if (ndtest_dimm_class) 1599a27e109SSantosh Sivaraj class_destroy(ndtest_dimm_class); 1609a27e109SSantosh Sivaraj } 1619a27e109SSantosh Sivaraj 1629a27e109SSantosh Sivaraj static __init int ndtest_init(void) 1639a27e109SSantosh Sivaraj { 1649a27e109SSantosh Sivaraj int rc, i; 1659a27e109SSantosh Sivaraj 1669a27e109SSantosh Sivaraj pmem_test(); 1679a27e109SSantosh Sivaraj libnvdimm_test(); 1689a27e109SSantosh Sivaraj device_dax_test(); 1699a27e109SSantosh Sivaraj dax_pmem_test(); 1709a27e109SSantosh Sivaraj dax_pmem_core_test(); 1719a27e109SSantosh Sivaraj #ifdef CONFIG_DEV_DAX_PMEM_COMPAT 1729a27e109SSantosh Sivaraj dax_pmem_compat_test(); 1739a27e109SSantosh Sivaraj #endif 1749a27e109SSantosh Sivaraj 1759a27e109SSantosh Sivaraj ndtest_dimm_class = class_create(THIS_MODULE, "nfit_test_dimm"); 1769a27e109SSantosh Sivaraj if (IS_ERR(ndtest_dimm_class)) { 1779a27e109SSantosh Sivaraj rc = PTR_ERR(ndtest_dimm_class); 1789a27e109SSantosh Sivaraj goto err_register; 1799a27e109SSantosh Sivaraj } 1809a27e109SSantosh Sivaraj 1819a27e109SSantosh Sivaraj /* Each instance can be taken as a bus, which can have multiple dimms */ 1829a27e109SSantosh Sivaraj for (i = 0; i < NUM_INSTANCES; i++) { 1839a27e109SSantosh Sivaraj struct ndtest_priv *priv; 1849a27e109SSantosh Sivaraj struct platform_device *pdev; 1859a27e109SSantosh Sivaraj 1869a27e109SSantosh Sivaraj priv = kzalloc(sizeof(*priv), GFP_KERNEL); 1879a27e109SSantosh Sivaraj if (!priv) { 1889a27e109SSantosh Sivaraj rc = -ENOMEM; 1899a27e109SSantosh Sivaraj goto err_register; 1909a27e109SSantosh Sivaraj } 1919a27e109SSantosh Sivaraj 1929a27e109SSantosh Sivaraj INIT_LIST_HEAD(&priv->resources); 1939a27e109SSantosh Sivaraj pdev = &priv->pdev; 1949a27e109SSantosh Sivaraj pdev->name = KBUILD_MODNAME; 1959a27e109SSantosh Sivaraj pdev->id = i; 1969a27e109SSantosh Sivaraj pdev->dev.release = ndtest_release; 1979a27e109SSantosh Sivaraj rc = platform_device_register(pdev); 1989a27e109SSantosh Sivaraj if (rc) { 1999a27e109SSantosh Sivaraj put_device(&pdev->dev); 2009a27e109SSantosh Sivaraj goto err_register; 2019a27e109SSantosh Sivaraj } 2029a27e109SSantosh Sivaraj get_device(&pdev->dev); 2039a27e109SSantosh Sivaraj 2049a27e109SSantosh Sivaraj instances[i] = priv; 2059a27e109SSantosh Sivaraj } 2069a27e109SSantosh Sivaraj 2079a27e109SSantosh Sivaraj rc = platform_driver_register(&ndtest_driver); 2089a27e109SSantosh Sivaraj if (rc) 2099a27e109SSantosh Sivaraj goto err_register; 2109a27e109SSantosh Sivaraj 2119a27e109SSantosh Sivaraj return 0; 2129a27e109SSantosh Sivaraj 2139a27e109SSantosh Sivaraj err_register: 2149a27e109SSantosh Sivaraj pr_err("Error registering platform device\n"); 2159a27e109SSantosh Sivaraj cleanup_devices(); 2169a27e109SSantosh Sivaraj 2179a27e109SSantosh Sivaraj return rc; 2189a27e109SSantosh Sivaraj } 2199a27e109SSantosh Sivaraj 2209a27e109SSantosh Sivaraj static __exit void ndtest_exit(void) 2219a27e109SSantosh Sivaraj { 2229a27e109SSantosh Sivaraj cleanup_devices(); 2239a27e109SSantosh Sivaraj platform_driver_unregister(&ndtest_driver); 2249a27e109SSantosh Sivaraj } 2259a27e109SSantosh Sivaraj 2269a27e109SSantosh Sivaraj module_init(ndtest_init); 2279a27e109SSantosh Sivaraj module_exit(ndtest_exit); 2289a27e109SSantosh Sivaraj MODULE_LICENSE("GPL"); 2299a27e109SSantosh Sivaraj MODULE_AUTHOR("IBM Corporation"); 230