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