xref: /openbmc/linux/tools/testing/nvdimm/test/ndtest.c (revision 107b04e970cae754100efb99a5312c321208ca03)
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