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 28*9399ab61SSantosh Sivaraj #define NDTEST_SCM_DIMM_CMD_MASK \ 29*9399ab61SSantosh Sivaraj ((1ul << ND_CMD_GET_CONFIG_SIZE) | \ 30*9399ab61SSantosh Sivaraj (1ul << ND_CMD_GET_CONFIG_DATA) | \ 31*9399ab61SSantosh Sivaraj (1ul << ND_CMD_SET_CONFIG_DATA) | \ 32*9399ab61SSantosh Sivaraj (1ul << ND_CMD_CALL)) 33*9399ab61SSantosh Sivaraj 34*9399ab61SSantosh Sivaraj #define NFIT_DIMM_HANDLE(node, socket, imc, chan, dimm) \ 35*9399ab61SSantosh Sivaraj (((node & 0xfff) << 16) | ((socket & 0xf) << 12) \ 36*9399ab61SSantosh Sivaraj | ((imc & 0xf) << 8) | ((chan & 0xf) << 4) | (dimm & 0xf)) 37*9399ab61SSantosh Sivaraj 38*9399ab61SSantosh Sivaraj static DEFINE_SPINLOCK(ndtest_lock); 399a27e109SSantosh Sivaraj static struct ndtest_priv *instances[NUM_INSTANCES]; 409a27e109SSantosh Sivaraj static struct class *ndtest_dimm_class; 41*9399ab61SSantosh Sivaraj static struct gen_pool *ndtest_pool; 42*9399ab61SSantosh Sivaraj 43*9399ab61SSantosh Sivaraj static struct ndtest_dimm dimm_group1[] = { 44*9399ab61SSantosh Sivaraj { 45*9399ab61SSantosh Sivaraj .size = DIMM_SIZE, 46*9399ab61SSantosh Sivaraj .handle = NFIT_DIMM_HANDLE(0, 0, 0, 0, 0), 47*9399ab61SSantosh Sivaraj .uuid_str = "1e5c75d2-b618-11ea-9aa3-507b9ddc0f72", 48*9399ab61SSantosh Sivaraj .physical_id = 0, 49*9399ab61SSantosh Sivaraj .num_formats = 2, 50*9399ab61SSantosh Sivaraj }, 51*9399ab61SSantosh Sivaraj { 52*9399ab61SSantosh Sivaraj .size = DIMM_SIZE, 53*9399ab61SSantosh Sivaraj .handle = NFIT_DIMM_HANDLE(0, 0, 0, 0, 1), 54*9399ab61SSantosh Sivaraj .uuid_str = "1c4d43ac-b618-11ea-be80-507b9ddc0f72", 55*9399ab61SSantosh Sivaraj .physical_id = 1, 56*9399ab61SSantosh Sivaraj .num_formats = 2, 57*9399ab61SSantosh Sivaraj }, 58*9399ab61SSantosh Sivaraj { 59*9399ab61SSantosh Sivaraj .size = DIMM_SIZE, 60*9399ab61SSantosh Sivaraj .handle = NFIT_DIMM_HANDLE(0, 0, 1, 0, 0), 61*9399ab61SSantosh Sivaraj .uuid_str = "a9f17ffc-b618-11ea-b36d-507b9ddc0f72", 62*9399ab61SSantosh Sivaraj .physical_id = 2, 63*9399ab61SSantosh Sivaraj .num_formats = 2, 64*9399ab61SSantosh Sivaraj }, 65*9399ab61SSantosh Sivaraj { 66*9399ab61SSantosh Sivaraj .size = DIMM_SIZE, 67*9399ab61SSantosh Sivaraj .handle = NFIT_DIMM_HANDLE(0, 0, 1, 0, 1), 68*9399ab61SSantosh Sivaraj .uuid_str = "b6b83b22-b618-11ea-8aae-507b9ddc0f72", 69*9399ab61SSantosh Sivaraj .physical_id = 3, 70*9399ab61SSantosh Sivaraj .num_formats = 2, 71*9399ab61SSantosh Sivaraj }, 72*9399ab61SSantosh Sivaraj { 73*9399ab61SSantosh Sivaraj .size = DIMM_SIZE, 74*9399ab61SSantosh Sivaraj .handle = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0), 75*9399ab61SSantosh Sivaraj .uuid_str = "bf9baaee-b618-11ea-b181-507b9ddc0f72", 76*9399ab61SSantosh Sivaraj .physical_id = 4, 77*9399ab61SSantosh Sivaraj .num_formats = 2, 78*9399ab61SSantosh Sivaraj }, 79*9399ab61SSantosh Sivaraj }; 80*9399ab61SSantosh Sivaraj 81*9399ab61SSantosh Sivaraj static struct ndtest_dimm dimm_group2[] = { 82*9399ab61SSantosh Sivaraj { 83*9399ab61SSantosh Sivaraj .size = DIMM_SIZE, 84*9399ab61SSantosh Sivaraj .handle = NFIT_DIMM_HANDLE(1, 0, 0, 0, 0), 85*9399ab61SSantosh Sivaraj .uuid_str = "ca0817e2-b618-11ea-9db3-507b9ddc0f72", 86*9399ab61SSantosh Sivaraj .physical_id = 0, 87*9399ab61SSantosh Sivaraj .num_formats = 1, 88*9399ab61SSantosh Sivaraj }, 89*9399ab61SSantosh Sivaraj }; 90*9399ab61SSantosh Sivaraj 91*9399ab61SSantosh Sivaraj static struct ndtest_config bus_configs[NUM_INSTANCES] = { 92*9399ab61SSantosh Sivaraj /* bus 1 */ 93*9399ab61SSantosh Sivaraj { 94*9399ab61SSantosh Sivaraj .dimm_start = 0, 95*9399ab61SSantosh Sivaraj .dimm_count = ARRAY_SIZE(dimm_group1), 96*9399ab61SSantosh Sivaraj .dimms = dimm_group1, 97*9399ab61SSantosh Sivaraj }, 98*9399ab61SSantosh Sivaraj /* bus 2 */ 99*9399ab61SSantosh Sivaraj { 100*9399ab61SSantosh Sivaraj .dimm_start = ARRAY_SIZE(dimm_group1), 101*9399ab61SSantosh Sivaraj .dimm_count = ARRAY_SIZE(dimm_group2), 102*9399ab61SSantosh Sivaraj .dimms = dimm_group2, 103*9399ab61SSantosh Sivaraj }, 104*9399ab61SSantosh Sivaraj }; 1059a27e109SSantosh Sivaraj 1069a27e109SSantosh Sivaraj static inline struct ndtest_priv *to_ndtest_priv(struct device *dev) 1079a27e109SSantosh Sivaraj { 1089a27e109SSantosh Sivaraj struct platform_device *pdev = to_platform_device(dev); 1099a27e109SSantosh Sivaraj 1109a27e109SSantosh Sivaraj return container_of(pdev, struct ndtest_priv, pdev); 1119a27e109SSantosh Sivaraj } 1129a27e109SSantosh Sivaraj 1139a27e109SSantosh Sivaraj static int ndtest_ctl(struct nvdimm_bus_descriptor *nd_desc, 1149a27e109SSantosh Sivaraj struct nvdimm *nvdimm, unsigned int cmd, void *buf, 1159a27e109SSantosh Sivaraj unsigned int buf_len, int *cmd_rc) 1169a27e109SSantosh Sivaraj { 1179a27e109SSantosh Sivaraj struct ndtest_dimm *dimm; 1189a27e109SSantosh Sivaraj int _cmd_rc; 1199a27e109SSantosh Sivaraj 1209a27e109SSantosh Sivaraj if (!cmd_rc) 1219a27e109SSantosh Sivaraj cmd_rc = &_cmd_rc; 1229a27e109SSantosh Sivaraj 1239a27e109SSantosh Sivaraj *cmd_rc = 0; 1249a27e109SSantosh Sivaraj 1259a27e109SSantosh Sivaraj if (!nvdimm) 1269a27e109SSantosh Sivaraj return -EINVAL; 1279a27e109SSantosh Sivaraj 1289a27e109SSantosh Sivaraj dimm = nvdimm_provider_data(nvdimm); 1299a27e109SSantosh Sivaraj if (!dimm) 1309a27e109SSantosh Sivaraj return -EINVAL; 1319a27e109SSantosh Sivaraj 1329a27e109SSantosh Sivaraj switch (cmd) { 1339a27e109SSantosh Sivaraj case ND_CMD_GET_CONFIG_SIZE: 1349a27e109SSantosh Sivaraj case ND_CMD_GET_CONFIG_DATA: 1359a27e109SSantosh Sivaraj case ND_CMD_SET_CONFIG_DATA: 1369a27e109SSantosh Sivaraj default: 1379a27e109SSantosh Sivaraj return -EINVAL; 1389a27e109SSantosh Sivaraj } 1399a27e109SSantosh Sivaraj 1409a27e109SSantosh Sivaraj return 0; 1419a27e109SSantosh Sivaraj } 1429a27e109SSantosh Sivaraj 143*9399ab61SSantosh Sivaraj static void ndtest_release_resource(void *data) 144*9399ab61SSantosh Sivaraj { 145*9399ab61SSantosh Sivaraj struct nfit_test_resource *res = data; 146*9399ab61SSantosh Sivaraj 147*9399ab61SSantosh Sivaraj spin_lock(&ndtest_lock); 148*9399ab61SSantosh Sivaraj list_del(&res->list); 149*9399ab61SSantosh Sivaraj spin_unlock(&ndtest_lock); 150*9399ab61SSantosh Sivaraj 151*9399ab61SSantosh Sivaraj if (resource_size(&res->res) >= DIMM_SIZE) 152*9399ab61SSantosh Sivaraj gen_pool_free(ndtest_pool, res->res.start, 153*9399ab61SSantosh Sivaraj resource_size(&res->res)); 154*9399ab61SSantosh Sivaraj vfree(res->buf); 155*9399ab61SSantosh Sivaraj kfree(res); 156*9399ab61SSantosh Sivaraj } 157*9399ab61SSantosh Sivaraj 158*9399ab61SSantosh Sivaraj static void *ndtest_alloc_resource(struct ndtest_priv *p, size_t size, 159*9399ab61SSantosh Sivaraj dma_addr_t *dma) 160*9399ab61SSantosh Sivaraj { 161*9399ab61SSantosh Sivaraj dma_addr_t __dma; 162*9399ab61SSantosh Sivaraj void *buf; 163*9399ab61SSantosh Sivaraj struct nfit_test_resource *res; 164*9399ab61SSantosh Sivaraj struct genpool_data_align data = { 165*9399ab61SSantosh Sivaraj .align = SZ_128M, 166*9399ab61SSantosh Sivaraj }; 167*9399ab61SSantosh Sivaraj 168*9399ab61SSantosh Sivaraj res = kzalloc(sizeof(*res), GFP_KERNEL); 169*9399ab61SSantosh Sivaraj if (!res) 170*9399ab61SSantosh Sivaraj return NULL; 171*9399ab61SSantosh Sivaraj 172*9399ab61SSantosh Sivaraj buf = vmalloc(size); 173*9399ab61SSantosh Sivaraj if (size >= DIMM_SIZE) 174*9399ab61SSantosh Sivaraj __dma = gen_pool_alloc_algo(ndtest_pool, size, 175*9399ab61SSantosh Sivaraj gen_pool_first_fit_align, &data); 176*9399ab61SSantosh Sivaraj else 177*9399ab61SSantosh Sivaraj __dma = (unsigned long) buf; 178*9399ab61SSantosh Sivaraj 179*9399ab61SSantosh Sivaraj if (!__dma) 180*9399ab61SSantosh Sivaraj goto buf_err; 181*9399ab61SSantosh Sivaraj 182*9399ab61SSantosh Sivaraj INIT_LIST_HEAD(&res->list); 183*9399ab61SSantosh Sivaraj res->dev = &p->pdev.dev; 184*9399ab61SSantosh Sivaraj res->buf = buf; 185*9399ab61SSantosh Sivaraj res->res.start = __dma; 186*9399ab61SSantosh Sivaraj res->res.end = __dma + size - 1; 187*9399ab61SSantosh Sivaraj res->res.name = "NFIT"; 188*9399ab61SSantosh Sivaraj spin_lock_init(&res->lock); 189*9399ab61SSantosh Sivaraj INIT_LIST_HEAD(&res->requests); 190*9399ab61SSantosh Sivaraj spin_lock(&ndtest_lock); 191*9399ab61SSantosh Sivaraj list_add(&res->list, &p->resources); 192*9399ab61SSantosh Sivaraj spin_unlock(&ndtest_lock); 193*9399ab61SSantosh Sivaraj 194*9399ab61SSantosh Sivaraj if (dma) 195*9399ab61SSantosh Sivaraj *dma = __dma; 196*9399ab61SSantosh Sivaraj 197*9399ab61SSantosh Sivaraj if (!devm_add_action(&p->pdev.dev, ndtest_release_resource, res)) 198*9399ab61SSantosh Sivaraj return res->buf; 199*9399ab61SSantosh Sivaraj 200*9399ab61SSantosh Sivaraj buf_err: 201*9399ab61SSantosh Sivaraj if (__dma && size >= DIMM_SIZE) 202*9399ab61SSantosh Sivaraj gen_pool_free(ndtest_pool, __dma, size); 203*9399ab61SSantosh Sivaraj if (buf) 204*9399ab61SSantosh Sivaraj vfree(buf); 205*9399ab61SSantosh Sivaraj kfree(res); 206*9399ab61SSantosh Sivaraj 207*9399ab61SSantosh Sivaraj return NULL; 208*9399ab61SSantosh Sivaraj } 209*9399ab61SSantosh Sivaraj 210*9399ab61SSantosh Sivaraj static void put_dimms(void *data) 211*9399ab61SSantosh Sivaraj { 212*9399ab61SSantosh Sivaraj struct ndtest_priv *p = data; 213*9399ab61SSantosh Sivaraj int i; 214*9399ab61SSantosh Sivaraj 215*9399ab61SSantosh Sivaraj for (i = 0; i < p->config->dimm_count; i++) 216*9399ab61SSantosh Sivaraj if (p->config->dimms[i].dev) { 217*9399ab61SSantosh Sivaraj device_unregister(p->config->dimms[i].dev); 218*9399ab61SSantosh Sivaraj p->config->dimms[i].dev = NULL; 219*9399ab61SSantosh Sivaraj } 220*9399ab61SSantosh Sivaraj } 221*9399ab61SSantosh Sivaraj 222*9399ab61SSantosh Sivaraj static int ndtest_dimm_register(struct ndtest_priv *priv, 223*9399ab61SSantosh Sivaraj struct ndtest_dimm *dimm, int id) 224*9399ab61SSantosh Sivaraj { 225*9399ab61SSantosh Sivaraj struct device *dev = &priv->pdev.dev; 226*9399ab61SSantosh Sivaraj unsigned long dimm_flags = dimm->flags; 227*9399ab61SSantosh Sivaraj 228*9399ab61SSantosh Sivaraj if (dimm->num_formats > 1) { 229*9399ab61SSantosh Sivaraj set_bit(NDD_ALIASING, &dimm_flags); 230*9399ab61SSantosh Sivaraj set_bit(NDD_LABELING, &dimm_flags); 231*9399ab61SSantosh Sivaraj } 232*9399ab61SSantosh Sivaraj 233*9399ab61SSantosh Sivaraj dimm->nvdimm = nvdimm_create(priv->bus, dimm, NULL, dimm_flags, 234*9399ab61SSantosh Sivaraj NDTEST_SCM_DIMM_CMD_MASK, 0, NULL); 235*9399ab61SSantosh Sivaraj if (!dimm->nvdimm) { 236*9399ab61SSantosh Sivaraj dev_err(dev, "Error creating DIMM object for %pOF\n", priv->dn); 237*9399ab61SSantosh Sivaraj return -ENXIO; 238*9399ab61SSantosh Sivaraj } 239*9399ab61SSantosh Sivaraj 240*9399ab61SSantosh Sivaraj dimm->dev = device_create_with_groups(ndtest_dimm_class, 241*9399ab61SSantosh Sivaraj &priv->pdev.dev, 242*9399ab61SSantosh Sivaraj 0, dimm, NULL, 243*9399ab61SSantosh Sivaraj "test_dimm%d", id); 244*9399ab61SSantosh Sivaraj if (!dimm->dev) { 245*9399ab61SSantosh Sivaraj pr_err("Could not create dimm device attributes\n"); 246*9399ab61SSantosh Sivaraj return -ENOMEM; 247*9399ab61SSantosh Sivaraj } 248*9399ab61SSantosh Sivaraj 249*9399ab61SSantosh Sivaraj return 0; 250*9399ab61SSantosh Sivaraj } 251*9399ab61SSantosh Sivaraj 252*9399ab61SSantosh Sivaraj static int ndtest_nvdimm_init(struct ndtest_priv *p) 253*9399ab61SSantosh Sivaraj { 254*9399ab61SSantosh Sivaraj struct ndtest_dimm *d; 255*9399ab61SSantosh Sivaraj void *res; 256*9399ab61SSantosh Sivaraj int i, id; 257*9399ab61SSantosh Sivaraj 258*9399ab61SSantosh Sivaraj for (i = 0; i < p->config->dimm_count; i++) { 259*9399ab61SSantosh Sivaraj d = &p->config->dimms[i]; 260*9399ab61SSantosh Sivaraj d->id = id = p->config->dimm_start + i; 261*9399ab61SSantosh Sivaraj res = ndtest_alloc_resource(p, LABEL_SIZE, NULL); 262*9399ab61SSantosh Sivaraj if (!res) 263*9399ab61SSantosh Sivaraj return -ENOMEM; 264*9399ab61SSantosh Sivaraj 265*9399ab61SSantosh Sivaraj d->label_area = res; 266*9399ab61SSantosh Sivaraj sprintf(d->label_area, "label%d", id); 267*9399ab61SSantosh Sivaraj d->config_size = LABEL_SIZE; 268*9399ab61SSantosh Sivaraj 269*9399ab61SSantosh Sivaraj if (!ndtest_alloc_resource(p, d->size, 270*9399ab61SSantosh Sivaraj &p->dimm_dma[id])) 271*9399ab61SSantosh Sivaraj return -ENOMEM; 272*9399ab61SSantosh Sivaraj 273*9399ab61SSantosh Sivaraj if (!ndtest_alloc_resource(p, LABEL_SIZE, 274*9399ab61SSantosh Sivaraj &p->label_dma[id])) 275*9399ab61SSantosh Sivaraj return -ENOMEM; 276*9399ab61SSantosh Sivaraj 277*9399ab61SSantosh Sivaraj if (!ndtest_alloc_resource(p, LABEL_SIZE, 278*9399ab61SSantosh Sivaraj &p->dcr_dma[id])) 279*9399ab61SSantosh Sivaraj return -ENOMEM; 280*9399ab61SSantosh Sivaraj 281*9399ab61SSantosh Sivaraj d->address = p->dimm_dma[id]; 282*9399ab61SSantosh Sivaraj 283*9399ab61SSantosh Sivaraj ndtest_dimm_register(p, d, id); 284*9399ab61SSantosh Sivaraj } 285*9399ab61SSantosh Sivaraj 286*9399ab61SSantosh Sivaraj return 0; 287*9399ab61SSantosh Sivaraj } 288*9399ab61SSantosh Sivaraj 289107b04e9SSantosh Sivaraj static ssize_t compatible_show(struct device *dev, 290107b04e9SSantosh Sivaraj struct device_attribute *attr, char *buf) 291107b04e9SSantosh Sivaraj { 292107b04e9SSantosh Sivaraj return sprintf(buf, "nvdimm_test"); 293107b04e9SSantosh Sivaraj } 294107b04e9SSantosh Sivaraj static DEVICE_ATTR_RO(compatible); 295107b04e9SSantosh Sivaraj 296107b04e9SSantosh Sivaraj static struct attribute *of_node_attributes[] = { 297107b04e9SSantosh Sivaraj &dev_attr_compatible.attr, 298107b04e9SSantosh Sivaraj NULL 299107b04e9SSantosh Sivaraj }; 300107b04e9SSantosh Sivaraj 301107b04e9SSantosh Sivaraj static const struct attribute_group of_node_attribute_group = { 302107b04e9SSantosh Sivaraj .name = "of_node", 303107b04e9SSantosh Sivaraj .attrs = of_node_attributes, 304107b04e9SSantosh Sivaraj }; 305107b04e9SSantosh Sivaraj 306107b04e9SSantosh Sivaraj static const struct attribute_group *ndtest_attribute_groups[] = { 307107b04e9SSantosh Sivaraj &of_node_attribute_group, 308107b04e9SSantosh Sivaraj NULL, 309107b04e9SSantosh Sivaraj }; 310107b04e9SSantosh Sivaraj 3119a27e109SSantosh Sivaraj static int ndtest_bus_register(struct ndtest_priv *p) 3129a27e109SSantosh Sivaraj { 313*9399ab61SSantosh Sivaraj p->config = &bus_configs[p->pdev.id]; 314*9399ab61SSantosh Sivaraj 3159a27e109SSantosh Sivaraj p->bus_desc.ndctl = ndtest_ctl; 3169a27e109SSantosh Sivaraj p->bus_desc.module = THIS_MODULE; 3179a27e109SSantosh Sivaraj p->bus_desc.provider_name = NULL; 318107b04e9SSantosh Sivaraj p->bus_desc.attr_groups = ndtest_attribute_groups; 3199a27e109SSantosh Sivaraj 3209a27e109SSantosh Sivaraj p->bus = nvdimm_bus_register(&p->pdev.dev, &p->bus_desc); 3219a27e109SSantosh Sivaraj if (!p->bus) { 3229a27e109SSantosh Sivaraj dev_err(&p->pdev.dev, "Error creating nvdimm bus %pOF\n", p->dn); 3239a27e109SSantosh Sivaraj return -ENOMEM; 3249a27e109SSantosh Sivaraj } 3259a27e109SSantosh Sivaraj 3269a27e109SSantosh Sivaraj return 0; 3279a27e109SSantosh Sivaraj } 3289a27e109SSantosh Sivaraj 3299a27e109SSantosh Sivaraj static int ndtest_remove(struct platform_device *pdev) 3309a27e109SSantosh Sivaraj { 3319a27e109SSantosh Sivaraj struct ndtest_priv *p = to_ndtest_priv(&pdev->dev); 3329a27e109SSantosh Sivaraj 3339a27e109SSantosh Sivaraj nvdimm_bus_unregister(p->bus); 3349a27e109SSantosh Sivaraj return 0; 3359a27e109SSantosh Sivaraj } 3369a27e109SSantosh Sivaraj 3379a27e109SSantosh Sivaraj static int ndtest_probe(struct platform_device *pdev) 3389a27e109SSantosh Sivaraj { 3399a27e109SSantosh Sivaraj struct ndtest_priv *p; 340*9399ab61SSantosh Sivaraj int rc; 3419a27e109SSantosh Sivaraj 3429a27e109SSantosh Sivaraj p = to_ndtest_priv(&pdev->dev); 3439a27e109SSantosh Sivaraj if (ndtest_bus_register(p)) 3449a27e109SSantosh Sivaraj return -ENOMEM; 3459a27e109SSantosh Sivaraj 346*9399ab61SSantosh Sivaraj p->dcr_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR, 347*9399ab61SSantosh Sivaraj sizeof(dma_addr_t), GFP_KERNEL); 348*9399ab61SSantosh Sivaraj p->label_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR, 349*9399ab61SSantosh Sivaraj sizeof(dma_addr_t), GFP_KERNEL); 350*9399ab61SSantosh Sivaraj p->dimm_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR, 351*9399ab61SSantosh Sivaraj sizeof(dma_addr_t), GFP_KERNEL); 352*9399ab61SSantosh Sivaraj 353*9399ab61SSantosh Sivaraj rc = ndtest_nvdimm_init(p); 354*9399ab61SSantosh Sivaraj if (rc) 355*9399ab61SSantosh Sivaraj goto err; 356*9399ab61SSantosh Sivaraj 357*9399ab61SSantosh Sivaraj rc = devm_add_action_or_reset(&pdev->dev, put_dimms, p); 358*9399ab61SSantosh Sivaraj if (rc) 359*9399ab61SSantosh Sivaraj goto err; 360*9399ab61SSantosh Sivaraj 3619a27e109SSantosh Sivaraj platform_set_drvdata(pdev, p); 3629a27e109SSantosh Sivaraj 3639a27e109SSantosh Sivaraj return 0; 364*9399ab61SSantosh Sivaraj 365*9399ab61SSantosh Sivaraj err: 366*9399ab61SSantosh Sivaraj pr_err("%s:%d Failed nvdimm init\n", __func__, __LINE__); 367*9399ab61SSantosh Sivaraj return rc; 3689a27e109SSantosh Sivaraj } 3699a27e109SSantosh Sivaraj 3709a27e109SSantosh Sivaraj static const struct platform_device_id ndtest_id[] = { 3719a27e109SSantosh Sivaraj { KBUILD_MODNAME }, 3729a27e109SSantosh Sivaraj { }, 3739a27e109SSantosh Sivaraj }; 3749a27e109SSantosh Sivaraj 3759a27e109SSantosh Sivaraj static struct platform_driver ndtest_driver = { 3769a27e109SSantosh Sivaraj .probe = ndtest_probe, 3779a27e109SSantosh Sivaraj .remove = ndtest_remove, 3789a27e109SSantosh Sivaraj .driver = { 3799a27e109SSantosh Sivaraj .name = KBUILD_MODNAME, 3809a27e109SSantosh Sivaraj }, 3819a27e109SSantosh Sivaraj .id_table = ndtest_id, 3829a27e109SSantosh Sivaraj }; 3839a27e109SSantosh Sivaraj 3849a27e109SSantosh Sivaraj static void ndtest_release(struct device *dev) 3859a27e109SSantosh Sivaraj { 3869a27e109SSantosh Sivaraj struct ndtest_priv *p = to_ndtest_priv(dev); 3879a27e109SSantosh Sivaraj 3889a27e109SSantosh Sivaraj kfree(p); 3899a27e109SSantosh Sivaraj } 3909a27e109SSantosh Sivaraj 3919a27e109SSantosh Sivaraj static void cleanup_devices(void) 3929a27e109SSantosh Sivaraj { 3939a27e109SSantosh Sivaraj int i; 3949a27e109SSantosh Sivaraj 3959a27e109SSantosh Sivaraj for (i = 0; i < NUM_INSTANCES; i++) 3969a27e109SSantosh Sivaraj if (instances[i]) 3979a27e109SSantosh Sivaraj platform_device_unregister(&instances[i]->pdev); 3989a27e109SSantosh Sivaraj 3999a27e109SSantosh Sivaraj nfit_test_teardown(); 4009a27e109SSantosh Sivaraj 401*9399ab61SSantosh Sivaraj if (ndtest_pool) 402*9399ab61SSantosh Sivaraj gen_pool_destroy(ndtest_pool); 403*9399ab61SSantosh Sivaraj 404*9399ab61SSantosh Sivaraj 4059a27e109SSantosh Sivaraj if (ndtest_dimm_class) 4069a27e109SSantosh Sivaraj class_destroy(ndtest_dimm_class); 4079a27e109SSantosh Sivaraj } 4089a27e109SSantosh Sivaraj 4099a27e109SSantosh Sivaraj static __init int ndtest_init(void) 4109a27e109SSantosh Sivaraj { 4119a27e109SSantosh Sivaraj int rc, i; 4129a27e109SSantosh Sivaraj 4139a27e109SSantosh Sivaraj pmem_test(); 4149a27e109SSantosh Sivaraj libnvdimm_test(); 4159a27e109SSantosh Sivaraj device_dax_test(); 4169a27e109SSantosh Sivaraj dax_pmem_test(); 4179a27e109SSantosh Sivaraj dax_pmem_core_test(); 4189a27e109SSantosh Sivaraj #ifdef CONFIG_DEV_DAX_PMEM_COMPAT 4199a27e109SSantosh Sivaraj dax_pmem_compat_test(); 4209a27e109SSantosh Sivaraj #endif 4219a27e109SSantosh Sivaraj 4229a27e109SSantosh Sivaraj ndtest_dimm_class = class_create(THIS_MODULE, "nfit_test_dimm"); 4239a27e109SSantosh Sivaraj if (IS_ERR(ndtest_dimm_class)) { 4249a27e109SSantosh Sivaraj rc = PTR_ERR(ndtest_dimm_class); 4259a27e109SSantosh Sivaraj goto err_register; 4269a27e109SSantosh Sivaraj } 4279a27e109SSantosh Sivaraj 428*9399ab61SSantosh Sivaraj ndtest_pool = gen_pool_create(ilog2(SZ_4M), NUMA_NO_NODE); 429*9399ab61SSantosh Sivaraj if (!ndtest_pool) { 430*9399ab61SSantosh Sivaraj rc = -ENOMEM; 431*9399ab61SSantosh Sivaraj goto err_register; 432*9399ab61SSantosh Sivaraj } 433*9399ab61SSantosh Sivaraj 434*9399ab61SSantosh Sivaraj if (gen_pool_add(ndtest_pool, SZ_4G, SZ_4G, NUMA_NO_NODE)) { 435*9399ab61SSantosh Sivaraj rc = -ENOMEM; 436*9399ab61SSantosh Sivaraj goto err_register; 437*9399ab61SSantosh Sivaraj } 438*9399ab61SSantosh Sivaraj 4399a27e109SSantosh Sivaraj /* Each instance can be taken as a bus, which can have multiple dimms */ 4409a27e109SSantosh Sivaraj for (i = 0; i < NUM_INSTANCES; i++) { 4419a27e109SSantosh Sivaraj struct ndtest_priv *priv; 4429a27e109SSantosh Sivaraj struct platform_device *pdev; 4439a27e109SSantosh Sivaraj 4449a27e109SSantosh Sivaraj priv = kzalloc(sizeof(*priv), GFP_KERNEL); 4459a27e109SSantosh Sivaraj if (!priv) { 4469a27e109SSantosh Sivaraj rc = -ENOMEM; 4479a27e109SSantosh Sivaraj goto err_register; 4489a27e109SSantosh Sivaraj } 4499a27e109SSantosh Sivaraj 4509a27e109SSantosh Sivaraj INIT_LIST_HEAD(&priv->resources); 4519a27e109SSantosh Sivaraj pdev = &priv->pdev; 4529a27e109SSantosh Sivaraj pdev->name = KBUILD_MODNAME; 4539a27e109SSantosh Sivaraj pdev->id = i; 4549a27e109SSantosh Sivaraj pdev->dev.release = ndtest_release; 4559a27e109SSantosh Sivaraj rc = platform_device_register(pdev); 4569a27e109SSantosh Sivaraj if (rc) { 4579a27e109SSantosh Sivaraj put_device(&pdev->dev); 4589a27e109SSantosh Sivaraj goto err_register; 4599a27e109SSantosh Sivaraj } 4609a27e109SSantosh Sivaraj get_device(&pdev->dev); 4619a27e109SSantosh Sivaraj 4629a27e109SSantosh Sivaraj instances[i] = priv; 4639a27e109SSantosh Sivaraj } 4649a27e109SSantosh Sivaraj 4659a27e109SSantosh Sivaraj rc = platform_driver_register(&ndtest_driver); 4669a27e109SSantosh Sivaraj if (rc) 4679a27e109SSantosh Sivaraj goto err_register; 4689a27e109SSantosh Sivaraj 4699a27e109SSantosh Sivaraj return 0; 4709a27e109SSantosh Sivaraj 4719a27e109SSantosh Sivaraj err_register: 4729a27e109SSantosh Sivaraj pr_err("Error registering platform device\n"); 4739a27e109SSantosh Sivaraj cleanup_devices(); 4749a27e109SSantosh Sivaraj 4759a27e109SSantosh Sivaraj return rc; 4769a27e109SSantosh Sivaraj } 4779a27e109SSantosh Sivaraj 4789a27e109SSantosh Sivaraj static __exit void ndtest_exit(void) 4799a27e109SSantosh Sivaraj { 4809a27e109SSantosh Sivaraj cleanup_devices(); 4819a27e109SSantosh Sivaraj platform_driver_unregister(&ndtest_driver); 4829a27e109SSantosh Sivaraj } 4839a27e109SSantosh Sivaraj 4849a27e109SSantosh Sivaraj module_init(ndtest_init); 4859a27e109SSantosh Sivaraj module_exit(ndtest_exit); 4869a27e109SSantosh Sivaraj MODULE_LICENSE("GPL"); 4879a27e109SSantosh Sivaraj MODULE_AUTHOR("IBM Corporation"); 488