xref: /openbmc/linux/tools/testing/nvdimm/test/ndtest.c (revision 9a27e109a391c9021147553b97c3fe4356e2261c)
1*9a27e109SSantosh Sivaraj // SPDX-License-Identifier: GPL-2.0-only
2*9a27e109SSantosh Sivaraj #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3*9a27e109SSantosh Sivaraj 
4*9a27e109SSantosh Sivaraj #include <linux/platform_device.h>
5*9a27e109SSantosh Sivaraj #include <linux/device.h>
6*9a27e109SSantosh Sivaraj #include <linux/module.h>
7*9a27e109SSantosh Sivaraj #include <linux/genalloc.h>
8*9a27e109SSantosh Sivaraj #include <linux/vmalloc.h>
9*9a27e109SSantosh Sivaraj #include <linux/dma-mapping.h>
10*9a27e109SSantosh Sivaraj #include <linux/list_sort.h>
11*9a27e109SSantosh Sivaraj #include <linux/libnvdimm.h>
12*9a27e109SSantosh Sivaraj #include <linux/ndctl.h>
13*9a27e109SSantosh Sivaraj #include <nd-core.h>
14*9a27e109SSantosh Sivaraj #include <linux/printk.h>
15*9a27e109SSantosh Sivaraj #include <linux/seq_buf.h>
16*9a27e109SSantosh Sivaraj 
17*9a27e109SSantosh Sivaraj #include "../watermark.h"
18*9a27e109SSantosh Sivaraj #include "nfit_test.h"
19*9a27e109SSantosh Sivaraj #include "ndtest.h"
20*9a27e109SSantosh Sivaraj 
21*9a27e109SSantosh Sivaraj enum {
22*9a27e109SSantosh Sivaraj 	DIMM_SIZE = SZ_32M,
23*9a27e109SSantosh Sivaraj 	LABEL_SIZE = SZ_128K,
24*9a27e109SSantosh Sivaraj 	NUM_INSTANCES = 2,
25*9a27e109SSantosh Sivaraj 	NUM_DCR = 4,
26*9a27e109SSantosh Sivaraj };
27*9a27e109SSantosh Sivaraj 
28*9a27e109SSantosh Sivaraj static struct ndtest_priv *instances[NUM_INSTANCES];
29*9a27e109SSantosh Sivaraj static struct class *ndtest_dimm_class;
30*9a27e109SSantosh Sivaraj 
31*9a27e109SSantosh Sivaraj static inline struct ndtest_priv *to_ndtest_priv(struct device *dev)
32*9a27e109SSantosh Sivaraj {
33*9a27e109SSantosh Sivaraj 	struct platform_device *pdev = to_platform_device(dev);
34*9a27e109SSantosh Sivaraj 
35*9a27e109SSantosh Sivaraj 	return container_of(pdev, struct ndtest_priv, pdev);
36*9a27e109SSantosh Sivaraj }
37*9a27e109SSantosh Sivaraj 
38*9a27e109SSantosh Sivaraj static int ndtest_ctl(struct nvdimm_bus_descriptor *nd_desc,
39*9a27e109SSantosh Sivaraj 		      struct nvdimm *nvdimm, unsigned int cmd, void *buf,
40*9a27e109SSantosh Sivaraj 		      unsigned int buf_len, int *cmd_rc)
41*9a27e109SSantosh Sivaraj {
42*9a27e109SSantosh Sivaraj 	struct ndtest_dimm *dimm;
43*9a27e109SSantosh Sivaraj 	int _cmd_rc;
44*9a27e109SSantosh Sivaraj 
45*9a27e109SSantosh Sivaraj 	if (!cmd_rc)
46*9a27e109SSantosh Sivaraj 		cmd_rc = &_cmd_rc;
47*9a27e109SSantosh Sivaraj 
48*9a27e109SSantosh Sivaraj 	*cmd_rc = 0;
49*9a27e109SSantosh Sivaraj 
50*9a27e109SSantosh Sivaraj 	if (!nvdimm)
51*9a27e109SSantosh Sivaraj 		return -EINVAL;
52*9a27e109SSantosh Sivaraj 
53*9a27e109SSantosh Sivaraj 	dimm = nvdimm_provider_data(nvdimm);
54*9a27e109SSantosh Sivaraj 	if (!dimm)
55*9a27e109SSantosh Sivaraj 		return -EINVAL;
56*9a27e109SSantosh Sivaraj 
57*9a27e109SSantosh Sivaraj 	switch (cmd) {
58*9a27e109SSantosh Sivaraj 	case ND_CMD_GET_CONFIG_SIZE:
59*9a27e109SSantosh Sivaraj 	case ND_CMD_GET_CONFIG_DATA:
60*9a27e109SSantosh Sivaraj 	case ND_CMD_SET_CONFIG_DATA:
61*9a27e109SSantosh Sivaraj 	default:
62*9a27e109SSantosh Sivaraj 		return -EINVAL;
63*9a27e109SSantosh Sivaraj 	}
64*9a27e109SSantosh Sivaraj 
65*9a27e109SSantosh Sivaraj 	return 0;
66*9a27e109SSantosh Sivaraj }
67*9a27e109SSantosh Sivaraj 
68*9a27e109SSantosh Sivaraj static int ndtest_bus_register(struct ndtest_priv *p)
69*9a27e109SSantosh Sivaraj {
70*9a27e109SSantosh Sivaraj 	p->bus_desc.ndctl = ndtest_ctl;
71*9a27e109SSantosh Sivaraj 	p->bus_desc.module = THIS_MODULE;
72*9a27e109SSantosh Sivaraj 	p->bus_desc.provider_name = NULL;
73*9a27e109SSantosh Sivaraj 
74*9a27e109SSantosh Sivaraj 	p->bus = nvdimm_bus_register(&p->pdev.dev, &p->bus_desc);
75*9a27e109SSantosh Sivaraj 	if (!p->bus) {
76*9a27e109SSantosh Sivaraj 		dev_err(&p->pdev.dev, "Error creating nvdimm bus %pOF\n", p->dn);
77*9a27e109SSantosh Sivaraj 		return -ENOMEM;
78*9a27e109SSantosh Sivaraj 	}
79*9a27e109SSantosh Sivaraj 
80*9a27e109SSantosh Sivaraj 	return 0;
81*9a27e109SSantosh Sivaraj }
82*9a27e109SSantosh Sivaraj 
83*9a27e109SSantosh Sivaraj static int ndtest_remove(struct platform_device *pdev)
84*9a27e109SSantosh Sivaraj {
85*9a27e109SSantosh Sivaraj 	struct ndtest_priv *p = to_ndtest_priv(&pdev->dev);
86*9a27e109SSantosh Sivaraj 
87*9a27e109SSantosh Sivaraj 	nvdimm_bus_unregister(p->bus);
88*9a27e109SSantosh Sivaraj 	return 0;
89*9a27e109SSantosh Sivaraj }
90*9a27e109SSantosh Sivaraj 
91*9a27e109SSantosh Sivaraj static int ndtest_probe(struct platform_device *pdev)
92*9a27e109SSantosh Sivaraj {
93*9a27e109SSantosh Sivaraj 	struct ndtest_priv *p;
94*9a27e109SSantosh Sivaraj 
95*9a27e109SSantosh Sivaraj 	p = to_ndtest_priv(&pdev->dev);
96*9a27e109SSantosh Sivaraj 	if (ndtest_bus_register(p))
97*9a27e109SSantosh Sivaraj 		return -ENOMEM;
98*9a27e109SSantosh Sivaraj 
99*9a27e109SSantosh Sivaraj 	platform_set_drvdata(pdev, p);
100*9a27e109SSantosh Sivaraj 
101*9a27e109SSantosh Sivaraj 	return 0;
102*9a27e109SSantosh Sivaraj }
103*9a27e109SSantosh Sivaraj 
104*9a27e109SSantosh Sivaraj static const struct platform_device_id ndtest_id[] = {
105*9a27e109SSantosh Sivaraj 	{ KBUILD_MODNAME },
106*9a27e109SSantosh Sivaraj 	{ },
107*9a27e109SSantosh Sivaraj };
108*9a27e109SSantosh Sivaraj 
109*9a27e109SSantosh Sivaraj static struct platform_driver ndtest_driver = {
110*9a27e109SSantosh Sivaraj 	.probe = ndtest_probe,
111*9a27e109SSantosh Sivaraj 	.remove = ndtest_remove,
112*9a27e109SSantosh Sivaraj 	.driver = {
113*9a27e109SSantosh Sivaraj 		.name = KBUILD_MODNAME,
114*9a27e109SSantosh Sivaraj 	},
115*9a27e109SSantosh Sivaraj 	.id_table = ndtest_id,
116*9a27e109SSantosh Sivaraj };
117*9a27e109SSantosh Sivaraj 
118*9a27e109SSantosh Sivaraj static void ndtest_release(struct device *dev)
119*9a27e109SSantosh Sivaraj {
120*9a27e109SSantosh Sivaraj 	struct ndtest_priv *p = to_ndtest_priv(dev);
121*9a27e109SSantosh Sivaraj 
122*9a27e109SSantosh Sivaraj 	kfree(p);
123*9a27e109SSantosh Sivaraj }
124*9a27e109SSantosh Sivaraj 
125*9a27e109SSantosh Sivaraj static void cleanup_devices(void)
126*9a27e109SSantosh Sivaraj {
127*9a27e109SSantosh Sivaraj 	int i;
128*9a27e109SSantosh Sivaraj 
129*9a27e109SSantosh Sivaraj 	for (i = 0; i < NUM_INSTANCES; i++)
130*9a27e109SSantosh Sivaraj 		if (instances[i])
131*9a27e109SSantosh Sivaraj 			platform_device_unregister(&instances[i]->pdev);
132*9a27e109SSantosh Sivaraj 
133*9a27e109SSantosh Sivaraj 	nfit_test_teardown();
134*9a27e109SSantosh Sivaraj 
135*9a27e109SSantosh Sivaraj 	if (ndtest_dimm_class)
136*9a27e109SSantosh Sivaraj 		class_destroy(ndtest_dimm_class);
137*9a27e109SSantosh Sivaraj }
138*9a27e109SSantosh Sivaraj 
139*9a27e109SSantosh Sivaraj static __init int ndtest_init(void)
140*9a27e109SSantosh Sivaraj {
141*9a27e109SSantosh Sivaraj 	int rc, i;
142*9a27e109SSantosh Sivaraj 
143*9a27e109SSantosh Sivaraj 	pmem_test();
144*9a27e109SSantosh Sivaraj 	libnvdimm_test();
145*9a27e109SSantosh Sivaraj 	device_dax_test();
146*9a27e109SSantosh Sivaraj 	dax_pmem_test();
147*9a27e109SSantosh Sivaraj 	dax_pmem_core_test();
148*9a27e109SSantosh Sivaraj #ifdef CONFIG_DEV_DAX_PMEM_COMPAT
149*9a27e109SSantosh Sivaraj 	dax_pmem_compat_test();
150*9a27e109SSantosh Sivaraj #endif
151*9a27e109SSantosh Sivaraj 
152*9a27e109SSantosh Sivaraj 	ndtest_dimm_class = class_create(THIS_MODULE, "nfit_test_dimm");
153*9a27e109SSantosh Sivaraj 	if (IS_ERR(ndtest_dimm_class)) {
154*9a27e109SSantosh Sivaraj 		rc = PTR_ERR(ndtest_dimm_class);
155*9a27e109SSantosh Sivaraj 		goto err_register;
156*9a27e109SSantosh Sivaraj 	}
157*9a27e109SSantosh Sivaraj 
158*9a27e109SSantosh Sivaraj 	/* Each instance can be taken as a bus, which can have multiple dimms */
159*9a27e109SSantosh Sivaraj 	for (i = 0; i < NUM_INSTANCES; i++) {
160*9a27e109SSantosh Sivaraj 		struct ndtest_priv *priv;
161*9a27e109SSantosh Sivaraj 		struct platform_device *pdev;
162*9a27e109SSantosh Sivaraj 
163*9a27e109SSantosh Sivaraj 		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
164*9a27e109SSantosh Sivaraj 		if (!priv) {
165*9a27e109SSantosh Sivaraj 			rc = -ENOMEM;
166*9a27e109SSantosh Sivaraj 			goto err_register;
167*9a27e109SSantosh Sivaraj 		}
168*9a27e109SSantosh Sivaraj 
169*9a27e109SSantosh Sivaraj 		INIT_LIST_HEAD(&priv->resources);
170*9a27e109SSantosh Sivaraj 		pdev = &priv->pdev;
171*9a27e109SSantosh Sivaraj 		pdev->name = KBUILD_MODNAME;
172*9a27e109SSantosh Sivaraj 		pdev->id = i;
173*9a27e109SSantosh Sivaraj 		pdev->dev.release = ndtest_release;
174*9a27e109SSantosh Sivaraj 		rc = platform_device_register(pdev);
175*9a27e109SSantosh Sivaraj 		if (rc) {
176*9a27e109SSantosh Sivaraj 			put_device(&pdev->dev);
177*9a27e109SSantosh Sivaraj 			goto err_register;
178*9a27e109SSantosh Sivaraj 		}
179*9a27e109SSantosh Sivaraj 		get_device(&pdev->dev);
180*9a27e109SSantosh Sivaraj 
181*9a27e109SSantosh Sivaraj 		instances[i] = priv;
182*9a27e109SSantosh Sivaraj 	}
183*9a27e109SSantosh Sivaraj 
184*9a27e109SSantosh Sivaraj 	rc = platform_driver_register(&ndtest_driver);
185*9a27e109SSantosh Sivaraj 	if (rc)
186*9a27e109SSantosh Sivaraj 		goto err_register;
187*9a27e109SSantosh Sivaraj 
188*9a27e109SSantosh Sivaraj 	return 0;
189*9a27e109SSantosh Sivaraj 
190*9a27e109SSantosh Sivaraj err_register:
191*9a27e109SSantosh Sivaraj 	pr_err("Error registering platform device\n");
192*9a27e109SSantosh Sivaraj 	cleanup_devices();
193*9a27e109SSantosh Sivaraj 
194*9a27e109SSantosh Sivaraj 	return rc;
195*9a27e109SSantosh Sivaraj }
196*9a27e109SSantosh Sivaraj 
197*9a27e109SSantosh Sivaraj static __exit void ndtest_exit(void)
198*9a27e109SSantosh Sivaraj {
199*9a27e109SSantosh Sivaraj 	cleanup_devices();
200*9a27e109SSantosh Sivaraj 	platform_driver_unregister(&ndtest_driver);
201*9a27e109SSantosh Sivaraj }
202*9a27e109SSantosh Sivaraj 
203*9a27e109SSantosh Sivaraj module_init(ndtest_init);
204*9a27e109SSantosh Sivaraj module_exit(ndtest_exit);
205*9a27e109SSantosh Sivaraj MODULE_LICENSE("GPL");
206*9a27e109SSantosh Sivaraj MODULE_AUTHOR("IBM Corporation");
207