File Index
Files and directories
Sign in
FILE

ndtest.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/nvdimm/test/ndtest.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   3
   4#include <linux/platform_device.h>
   5#include <linux/device.h>
   6#include <linux/module.h>
   7#include <linux/genalloc.h>
   8#include <linux/vmalloc.h>
   9#include <linux/dma-mapping.h>
  10#include <linux/list_sort.h>
  11#include <linux/libnvdimm.h>
  12#include <linux/ndctl.h>
  13#include <nd-core.h>
  14#include <linux/printk.h>
  15#include <linux/seq_buf.h>
  16#include <linux/papr_scm.h>
  17#include <uapi/linux/papr_pdsm.h>
  18
  19#include "../watermark.h"
  20#include "nfit_test.h"
  21#include "ndtest.h"
  22
  23enum {
  24	DIMM_SIZE = SZ_32M,
  25	LABEL_SIZE = SZ_128K,
  26	NUM_INSTANCES = 2,
  27	NUM_DCR = 4,
  28	NDTEST_MAX_MAPPING = 6,
  29};
  30
  31#define NDTEST_SCM_DIMM_CMD_MASK	   \
  32	((1ul << ND_CMD_GET_CONFIG_SIZE) | \
  33	 (1ul << ND_CMD_GET_CONFIG_DATA) | \
  34	 (1ul << ND_CMD_SET_CONFIG_DATA) | \
  35	 (1ul << ND_CMD_CALL))
  36
  37#define NFIT_DIMM_HANDLE(node, socket, imc, chan, dimm)			\
  38	(((node & 0xfff) << 16) | ((socket & 0xf) << 12)		\
  39	 | ((imc & 0xf) << 8) | ((chan & 0xf) << 4) | (dimm & 0xf))
  40
  41static DEFINE_SPINLOCK(ndtest_lock);
  42static struct ndtest_priv *instances[NUM_INSTANCES];
  43
  44static const struct class ndtest_dimm_class = {
  45	.name = "nfit_test_dimm",
  46};
  47
  48static struct gen_pool *ndtest_pool;
  49
  50static struct ndtest_dimm dimm_group1[] = {
  51	{
  52		.size = DIMM_SIZE,
  53		.handle = NFIT_DIMM_HANDLE(0, 0, 0, 0, 0),
  54		.uuid_str = "1e5c75d2-b618-11ea-9aa3-507b9ddc0f72",
  55		.physical_id = 0,
  56		.num_formats = 2,
  57	},
  58	{
  59		.size = DIMM_SIZE,
  60		.handle = NFIT_DIMM_HANDLE(0, 0, 0, 0, 1),
  61		.uuid_str = "1c4d43ac-b618-11ea-be80-507b9ddc0f72",
  62		.physical_id = 1,
  63		.num_formats = 2,
  64	},
  65	{
  66		.size = DIMM_SIZE,
  67		.handle = NFIT_DIMM_HANDLE(0, 0, 1, 0, 0),
  68		.uuid_str = "a9f17ffc-b618-11ea-b36d-507b9ddc0f72",
  69		.physical_id = 2,
  70		.num_formats = 2,
  71	},
  72	{
  73		.size = DIMM_SIZE,
  74		.handle = NFIT_DIMM_HANDLE(0, 0, 1, 0, 1),
  75		.uuid_str = "b6b83b22-b618-11ea-8aae-507b9ddc0f72",
  76		.physical_id = 3,
  77		.num_formats = 2,
  78	},
  79	{
  80		.size = DIMM_SIZE,
  81		.handle = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0),
  82		.uuid_str = "bf9baaee-b618-11ea-b181-507b9ddc0f72",
  83		.physical_id = 4,
  84		.num_formats = 2,
  85	},
  86};
  87
  88static struct ndtest_dimm dimm_group2[] = {
  89	{
  90		.size = DIMM_SIZE,
  91		.handle = NFIT_DIMM_HANDLE(1, 0, 0, 0, 0),
  92		.uuid_str = "ca0817e2-b618-11ea-9db3-507b9ddc0f72",
  93		.physical_id = 0,
  94		.num_formats = 1,
  95		.flags = PAPR_PMEM_UNARMED | PAPR_PMEM_EMPTY |
  96			 PAPR_PMEM_SAVE_FAILED | PAPR_PMEM_SHUTDOWN_DIRTY |
  97			 PAPR_PMEM_HEALTH_FATAL,
  98	},
  99};
 100
 101static struct ndtest_mapping region0_mapping[] = {
 102	{
 103		.dimm = 0,
 104		.position = 0,
 105		.start = 0,
 106		.size = SZ_16M,
 107	},
 108	{
 109		.dimm = 1,
 110		.position = 1,
 111		.start = 0,
 112		.size = SZ_16M,
 113	}
 114};
 115
 116static struct ndtest_mapping region1_mapping[] = {
 117	{
 118		.dimm = 0,
 119		.position = 0,
 120		.start = SZ_16M,
 121		.size = SZ_16M,
 122	},
 123	{
 124		.dimm = 1,
 125		.position = 1,
 126		.start = SZ_16M,
 127		.size = SZ_16M,
 128	},
 129	{
 130		.dimm = 2,
 131		.position = 2,
 132		.start = SZ_16M,
 133		.size = SZ_16M,
 134	},
 135	{
 136		.dimm = 3,
 137		.position = 3,
 138		.start = SZ_16M,
 139		.size = SZ_16M,
 140	},
 141};
 142
 143static struct ndtest_region bus0_regions[] = {
 144	{
 145		.type = ND_DEVICE_NAMESPACE_PMEM,
 146		.num_mappings = ARRAY_SIZE(region0_mapping),
 147		.mapping = region0_mapping,
 148		.size = DIMM_SIZE,
 149		.range_index = 1,
 150	},
 151	{
 152		.type = ND_DEVICE_NAMESPACE_PMEM,
 153		.num_mappings = ARRAY_SIZE(region1_mapping),
 154		.mapping = region1_mapping,
 155		.size = DIMM_SIZE * 2,
 156		.range_index = 2,
 157	},
 158};
 159
 160static struct ndtest_mapping region6_mapping[] = {
 161	{
 162		.dimm = 0,
 163		.position = 0,
 164		.start = 0,
 165		.size = DIMM_SIZE,
 166	},
 167};
 168
 169static struct ndtest_region bus1_regions[] = {
 170	{
 171		.type = ND_DEVICE_NAMESPACE_IO,
 172		.num_mappings = ARRAY_SIZE(region6_mapping),
 173		.mapping = region6_mapping,
 174		.size = DIMM_SIZE,
 175		.range_index = 1,
 176	},
 177};
 178
 179static struct ndtest_config bus_configs[NUM_INSTANCES] = {
 180	/* bus 1 */
 181	{
 182		.dimm_start = 0,
 183		.dimm_count = ARRAY_SIZE(dimm_group1),
 184		.dimms = dimm_group1,
 185		.regions = bus0_regions,
 186		.num_regions = ARRAY_SIZE(bus0_regions),
 187	},
 188	/* bus 2 */
 189	{
 190		.dimm_start = ARRAY_SIZE(dimm_group1),
 191		.dimm_count = ARRAY_SIZE(dimm_group2),
 192		.dimms = dimm_group2,
 193		.regions = bus1_regions,
 194		.num_regions = ARRAY_SIZE(bus1_regions),
 195	},
 196};
 197
 198static inline struct ndtest_priv *to_ndtest_priv(struct device *dev)
 199{
 200	struct platform_device *pdev = to_platform_device(dev);
 201
 202	return container_of(pdev, struct ndtest_priv, pdev);
 203}
 204
 205static int ndtest_config_get(struct ndtest_dimm *p, unsigned int buf_len,
 206			     struct nd_cmd_get_config_data_hdr *hdr)
 207{
 208	unsigned int len;
 209
 210	if ((hdr->in_offset + hdr->in_length) > LABEL_SIZE)
 211		return -EINVAL;
 212
 213	hdr->status = 0;
 214	len = min(hdr->in_length, LABEL_SIZE - hdr->in_offset);
 215	memcpy(hdr->out_buf, p->label_area + hdr->in_offset, len);
 216
 217	return buf_len - len;
 218}
 219
 220static int ndtest_config_set(struct ndtest_dimm *p, unsigned int buf_len,
 221			     struct nd_cmd_set_config_hdr *hdr)
 222{
 223	unsigned int len;
 224
 225	if ((hdr->in_offset + hdr->in_length) > LABEL_SIZE)
 226		return -EINVAL;
 227
 228	len = min(hdr->in_length, LABEL_SIZE - hdr->in_offset);
 229	memcpy(p->label_area + hdr->in_offset, hdr->in_buf, len);
 230
 231	return buf_len - len;
 232}
 233
 234static int ndtest_get_config_size(struct ndtest_dimm *dimm, unsigned int buf_len,
 235				  struct nd_cmd_get_config_size *size)
 236{
 237	size->status = 0;
 238	size->max_xfer = 8;
 239	size->config_size = dimm->config_size;
 240
 241	return 0;
 242}
 243
 244static int ndtest_ctl(struct nvdimm_bus_descriptor *nd_desc,
 245		      struct nvdimm *nvdimm, unsigned int cmd, void *buf,
 246		      unsigned int buf_len, int *cmd_rc)
 247{
 248	struct ndtest_dimm *dimm;
 249	int _cmd_rc;
 250
 251	if (!cmd_rc)
 252		cmd_rc = &_cmd_rc;
 253
 254	*cmd_rc = 0;
 255
 256	if (!nvdimm)
 257		return -EINVAL;
 258
 259	dimm = nvdimm_provider_data(nvdimm);
 260	if (!dimm)
 261		return -EINVAL;
 262
 263	switch (cmd) {
 264	case ND_CMD_GET_CONFIG_SIZE:
 265		*cmd_rc = ndtest_get_config_size(dimm, buf_len, buf);
 266		break;
 267	case ND_CMD_GET_CONFIG_DATA:
 268		*cmd_rc = ndtest_config_get(dimm, buf_len, buf);
 269		break;
 270	case ND_CMD_SET_CONFIG_DATA:
 271		*cmd_rc = ndtest_config_set(dimm, buf_len, buf);
 272		break;
 273	default:
 274		return -EINVAL;
 275	}
 276
 277	/* Failures for a DIMM can be injected using fail_cmd and
 278	 * fail_cmd_code, see the device attributes below
 279	 */
 280	if ((1 << cmd) & dimm->fail_cmd)
 281		return dimm->fail_cmd_code ? dimm->fail_cmd_code : -EIO;
 282
 283	return 0;
 284}
 285
 286static struct nfit_test_resource *ndtest_resource_lookup(resource_size_t addr)
 287{
 288	int i;
 289
 290	for (i = 0; i < NUM_INSTANCES; i++) {
 291		struct nfit_test_resource *n, *nfit_res = NULL;
 292		struct ndtest_priv *t = instances[i];
 293
 294		if (!t)
 295			continue;
 296		spin_lock(&ndtest_lock);
 297		list_for_each_entry(n, &t->resources, list) {
 298			if (addr >= n->res.start && (addr < n->res.start
 299						+ resource_size(&n->res))) {
 300				nfit_res = n;
 301				break;
 302			} else if (addr >= (unsigned long) n->buf
 303					&& (addr < (unsigned long) n->buf
 304						+ resource_size(&n->res))) {
 305				nfit_res = n;
 306				break;
 307			}
 308		}
 309		spin_unlock(&ndtest_lock);
 310		if (nfit_res)
 311			return nfit_res;
 312	}
 313
 314	pr_warn("Failed to get resource\n");
 315
 316	return NULL;
 317}
 318
 319static void ndtest_release_resource(void *data)
 320{
 321	struct nfit_test_resource *res  = data;
 322
 323	spin_lock(&ndtest_lock);
 324	list_del(&res->list);
 325	spin_unlock(&ndtest_lock);
 326
 327	if (resource_size(&res->res) >= DIMM_SIZE)
 328		gen_pool_free(ndtest_pool, res->res.start,
 329				resource_size(&res->res));
 330	vfree(res->buf);
 331	kfree(res);
 332}
 333
 334static void *ndtest_alloc_resource(struct ndtest_priv *p, size_t size,
 335				   dma_addr_t *dma)
 336{
 337	dma_addr_t __dma;
 338	void *buf;
 339	struct nfit_test_resource *res;
 340	struct genpool_data_align data = {
 341		.align = SZ_128M,
 342	};
 343
 344	res = kzalloc(sizeof(*res), GFP_KERNEL);
 345	if (!res)
 346		return NULL;
 347
 348	buf = vmalloc(size);
 349	if (size >= DIMM_SIZE)
 350		__dma = gen_pool_alloc_algo(ndtest_pool, size,
 351					    gen_pool_first_fit_align, &data);
 352	else
 353		__dma = (unsigned long) buf;
 354
 355	if (!__dma)
 356		goto buf_err;
 357
 358	INIT_LIST_HEAD(&res->list);
 359	res->dev = &p->pdev.dev;
 360	res->buf = buf;
 361	res->res.start = __dma;
 362	res->res.end = __dma + size - 1;
 363	res->res.name = "NFIT";
 364	spin_lock_init(&res->lock);
 365	INIT_LIST_HEAD(&res->requests);
 366	spin_lock(&ndtest_lock);
 367	list_add(&res->list, &p->resources);
 368	spin_unlock(&ndtest_lock);
 369
 370	if (dma)
 371		*dma = __dma;
 372
 373	if (!devm_add_action(&p->pdev.dev, ndtest_release_resource, res))
 374		return res->buf;
 375
 376buf_err:
 377	if (__dma && size >= DIMM_SIZE)
 378		gen_pool_free(ndtest_pool, __dma, size);
 379	if (buf)
 380		vfree(buf);
 381	kfree(res);
 382
 383	return NULL;
 384}
 385
 386static ssize_t range_index_show(struct device *dev,
 387		struct device_attribute *attr, char *buf)
 388{
 389	struct nd_region *nd_region = to_nd_region(dev);
 390	struct ndtest_region *region = nd_region_provider_data(nd_region);
 391
 392	return sprintf(buf, "%d\n", region->range_index);
 393}
 394static DEVICE_ATTR_RO(range_index);
 395
 396static struct attribute *ndtest_region_attributes[] = {
 397	&dev_attr_range_index.attr,
 398	NULL,
 399};
 400
 401static const struct attribute_group ndtest_region_attribute_group = {
 402	.name = "papr",
 403	.attrs = ndtest_region_attributes,
 404};
 405
 406static const struct attribute_group *ndtest_region_attribute_groups[] = {
 407	&ndtest_region_attribute_group,
 408	NULL,
 409};
 410
 411static int ndtest_create_region(struct ndtest_priv *p,
 412				struct ndtest_region *region)
 413{
 414	struct nd_mapping_desc mappings[NDTEST_MAX_MAPPING];
 415	struct nd_region_desc *ndr_desc, _ndr_desc;
 416	struct nd_interleave_set *nd_set;
 417	struct resource res;
 418	int i, ndimm = region->mapping[0].dimm;
 419	u64 uuid[2];
 420
 421	memset(&res, 0, sizeof(res));
 422	memset(&mappings, 0, sizeof(mappings));
 423	memset(&_ndr_desc, 0, sizeof(_ndr_desc));
 424	ndr_desc = &_ndr_desc;
 425
 426	if (!ndtest_alloc_resource(p, region->size, &res.start))
 427		return -ENOMEM;
 428
 429	res.end = res.start + region->size - 1;
 430	ndr_desc->mapping = mappings;
 431	ndr_desc->res = &res;
 432	ndr_desc->provider_data = region;
 433	ndr_desc->attr_groups = ndtest_region_attribute_groups;
 434
 435	if (uuid_parse(p->config->dimms[ndimm].uuid_str, (uuid_t *)uuid)) {
 436		pr_err("failed to parse UUID\n");
 437		return -ENXIO;
 438	}
 439
 440	nd_set = devm_kzalloc(&p->pdev.dev, sizeof(*nd_set), GFP_KERNEL);
 441	if (!nd_set)
 442		return -ENOMEM;
 443
 444	nd_set->cookie1 = cpu_to_le64(uuid[0]);
 445	nd_set->cookie2 = cpu_to_le64(uuid[1]);
 446	nd_set->altcookie = nd_set->cookie1;
 447	ndr_desc->nd_set = nd_set;
 448
 449	for (i = 0; i < region->num_mappings; i++) {
 450		ndimm = region->mapping[i].dimm;
 451		mappings[i].start = region->mapping[i].start;
 452		mappings[i].size = region->mapping[i].size;
 453		mappings[i].position = region->mapping[i].position;
 454		mappings[i].nvdimm = p->config->dimms[ndimm].nvdimm;
 455	}
 456
 457	ndr_desc->num_mappings = region->num_mappings;
 458	region->region = nvdimm_pmem_region_create(p->bus, ndr_desc);
 459
 460	if (!region->region) {
 461		dev_err(&p->pdev.dev, "Error registering region %pR\n",
 462			ndr_desc->res);
 463		return -ENXIO;
 464	}
 465
 466	return 0;
 467}
 468
 469static int ndtest_init_regions(struct ndtest_priv *p)
 470{
 471	int i, ret = 0;
 472
 473	for (i = 0; i < p->config->num_regions; i++) {
 474		ret = ndtest_create_region(p, &p->config->regions[i]);
 475		if (ret)
 476			return ret;
 477	}
 478
 479	return 0;
 480}
 481
 482static void put_dimms(void *data)
 483{
 484	struct ndtest_priv *p = data;
 485	int i;
 486
 487	for (i = 0; i < p->config->dimm_count; i++)
 488		if (p->config->dimms[i].dev) {
 489			device_unregister(p->config->dimms[i].dev);
 490			p->config->dimms[i].dev = NULL;
 491		}
 492}
 493
 494static ssize_t handle_show(struct device *dev, struct device_attribute *attr,
 495		char *buf)
 496{
 497	struct ndtest_dimm *dimm = dev_get_drvdata(dev);
 498
 499	return sprintf(buf, "%#x\n", dimm->handle);
 500}
 501static DEVICE_ATTR_RO(handle);
 502
 503static ssize_t fail_cmd_show(struct device *dev, struct device_attribute *attr,
 504		char *buf)
 505{
 506	struct ndtest_dimm *dimm = dev_get_drvdata(dev);
 507
 508	return sprintf(buf, "%#x\n", dimm->fail_cmd);
 509}
 510
 511static ssize_t fail_cmd_store(struct device *dev, struct device_attribute *attr,
 512		const char *buf, size_t size)
 513{
 514	struct ndtest_dimm *dimm = dev_get_drvdata(dev);
 515	unsigned long val;
 516	ssize_t rc;
 517
 518	rc = kstrtol(buf, 0, &val);
 519	if (rc)
 520		return rc;
 521
 522	dimm->fail_cmd = val;
 523
 524	return size;
 525}
 526static DEVICE_ATTR_RW(fail_cmd);
 527
 528static ssize_t fail_cmd_code_show(struct device *dev, struct device_attribute *attr,
 529		char *buf)
 530{
 531	struct ndtest_dimm *dimm = dev_get_drvdata(dev);
 532
 533	return sprintf(buf, "%d\n", dimm->fail_cmd_code);
 534}
 535
 536static ssize_t fail_cmd_code_store(struct device *dev, struct device_attribute *attr,
 537		const char *buf, size_t size)
 538{
 539	struct ndtest_dimm *dimm = dev_get_drvdata(dev);
 540	unsigned long val;
 541	ssize_t rc;
 542
 543	rc = kstrtol(buf, 0, &val);
 544	if (rc)
 545		return rc;
 546
 547	dimm->fail_cmd_code = val;
 548	return size;
 549}
 550static DEVICE_ATTR_RW(fail_cmd_code);
 551
 552static struct attribute *dimm_attributes[] = {
 553	&dev_attr_handle.attr,
 554	&dev_attr_fail_cmd.attr,
 555	&dev_attr_fail_cmd_code.attr,
 556	NULL,
 557};
 558
 559static struct attribute_group dimm_attribute_group = {
 560	.attrs = dimm_attributes,
 561};
 562
 563static const struct attribute_group *dimm_attribute_groups[] = {
 564	&dimm_attribute_group,
 565	NULL,
 566};
 567
 568static ssize_t phys_id_show(struct device *dev,
 569		struct device_attribute *attr, char *buf)
 570{
 571	struct nvdimm *nvdimm = to_nvdimm(dev);
 572	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
 573
 574	return sprintf(buf, "%#x\n", dimm->physical_id);
 575}
 576static DEVICE_ATTR_RO(phys_id);
 577
 578static ssize_t vendor_show(struct device *dev,
 579			   struct device_attribute *attr, char *buf)
 580{
 581	return sprintf(buf, "0x1234567\n");
 582}
 583static DEVICE_ATTR_RO(vendor);
 584
 585static ssize_t id_show(struct device *dev,
 586		       struct device_attribute *attr, char *buf)
 587{
 588	struct nvdimm *nvdimm = to_nvdimm(dev);
 589	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
 590
 591	return sprintf(buf, "%04x-%02x-%04x-%08x", 0xabcd,
 592		       0xa, 2016, ~(dimm->handle));
 593}
 594static DEVICE_ATTR_RO(id);
 595
 596static ssize_t nvdimm_handle_show(struct device *dev,
 597				  struct device_attribute *attr, char *buf)
 598{
 599	struct nvdimm *nvdimm = to_nvdimm(dev);
 600	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
 601
 602	return sprintf(buf, "%#x\n", dimm->handle);
 603}
 604
 605static struct device_attribute dev_attr_nvdimm_show_handle =  {
 606	.attr	= { .name = "handle", .mode = 0444 },
 607	.show	= nvdimm_handle_show,
 608};
 609
 610static ssize_t subsystem_vendor_show(struct device *dev,
 611		struct device_attribute *attr, char *buf)
 612{
 613	return sprintf(buf, "0x%04x\n", 0);
 614}
 615static DEVICE_ATTR_RO(subsystem_vendor);
 616
 617static ssize_t dirty_shutdown_show(struct device *dev,
 618		struct device_attribute *attr, char *buf)
 619{
 620	return sprintf(buf, "%d\n", 42);
 621}
 622static DEVICE_ATTR_RO(dirty_shutdown);
 623
 624static ssize_t formats_show(struct device *dev,
 625		struct device_attribute *attr, char *buf)
 626{
 627	struct nvdimm *nvdimm = to_nvdimm(dev);
 628	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
 629
 630	return sprintf(buf, "%d\n", dimm->num_formats);
 631}
 632static DEVICE_ATTR_RO(formats);
 633
 634static ssize_t format_show(struct device *dev,
 635		struct device_attribute *attr, char *buf)
 636{
 637	struct nvdimm *nvdimm = to_nvdimm(dev);
 638	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
 639
 640	if (dimm->num_formats > 1)
 641		return sprintf(buf, "0x201\n");
 642
 643	return sprintf(buf, "0x101\n");
 644}
 645static DEVICE_ATTR_RO(format);
 646
 647static ssize_t format1_show(struct device *dev, struct device_attribute *attr,
 648			    char *buf)
 649{
 650	return sprintf(buf, "0x301\n");
 651}
 652static DEVICE_ATTR_RO(format1);
 653
 654static umode_t ndtest_nvdimm_attr_visible(struct kobject *kobj,
 655					struct attribute *a, int n)
 656{
 657	struct device *dev = container_of(kobj, struct device, kobj);
 658	struct nvdimm *nvdimm = to_nvdimm(dev);
 659	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
 660
 661	if (a == &dev_attr_format1.attr && dimm->num_formats <= 1)
 662		return 0;
 663
 664	return a->mode;
 665}
 666
 667static ssize_t flags_show(struct device *dev,
 668			  struct device_attribute *attr, char *buf)
 669{
 670	struct nvdimm *nvdimm = to_nvdimm(dev);
 671	struct ndtest_dimm *dimm = nvdimm_provider_data(nvdimm);
 672	struct seq_buf s;
 673	u64 flags;
 674
 675	flags = dimm->flags;
 676
 677	seq_buf_init(&s, buf, PAGE_SIZE);
 678	if (flags & PAPR_PMEM_UNARMED_MASK)
 679		seq_buf_printf(&s, "not_armed ");
 680
 681	if (flags & PAPR_PMEM_BAD_SHUTDOWN_MASK)
 682		seq_buf_printf(&s, "flush_fail ");
 683
 684	if (flags & PAPR_PMEM_BAD_RESTORE_MASK)
 685		seq_buf_printf(&s, "restore_fail ");
 686
 687	if (flags & PAPR_PMEM_SAVE_MASK)
 688		seq_buf_printf(&s, "save_fail ");
 689
 690	if (flags & PAPR_PMEM_SMART_EVENT_MASK)
 691		seq_buf_printf(&s, "smart_notify ");
 692
 693
 694	if (seq_buf_used(&s))
 695		seq_buf_printf(&s, "\n");
 696
 697	return seq_buf_used(&s);
 698}
 699static DEVICE_ATTR_RO(flags);
 700
 701static struct attribute *ndtest_nvdimm_attributes[] = {
 702	&dev_attr_nvdimm_show_handle.attr,
 703	&dev_attr_vendor.attr,
 704	&dev_attr_id.attr,
 705	&dev_attr_phys_id.attr,
 706	&dev_attr_subsystem_vendor.attr,
 707	&dev_attr_dirty_shutdown.attr,
 708	&dev_attr_formats.attr,
 709	&dev_attr_format.attr,
 710	&dev_attr_format1.attr,
 711	&dev_attr_flags.attr,
 712	NULL,
 713};
 714
 715static const struct attribute_group ndtest_nvdimm_attribute_group = {
 716	.name = "papr",
 717	.attrs = ndtest_nvdimm_attributes,
 718	.is_visible = ndtest_nvdimm_attr_visible,
 719};
 720
 721static const struct attribute_group *ndtest_nvdimm_attribute_groups[] = {
 722	&ndtest_nvdimm_attribute_group,
 723	NULL,
 724};
 725
 726static int ndtest_dimm_register(struct ndtest_priv *priv,
 727				struct ndtest_dimm *dimm, int id)
 728{
 729	struct device *dev = &priv->pdev.dev;
 730	unsigned long dimm_flags = dimm->flags;
 731
 732	if (dimm->num_formats > 1)
 733		set_bit(NDD_LABELING, &dimm_flags);
 734
 735	if (dimm->flags & PAPR_PMEM_UNARMED_MASK)
 736		set_bit(NDD_UNARMED, &dimm_flags);
 737
 738	dimm->nvdimm = nvdimm_create(priv->bus, dimm,
 739				    ndtest_nvdimm_attribute_groups, dimm_flags,
 740				    NDTEST_SCM_DIMM_CMD_MASK, 0, NULL);
 741	if (!dimm->nvdimm) {
 742		dev_err(dev, "Error creating DIMM object for %pOF\n", priv->dn);
 743		return -ENXIO;
 744	}
 745
 746	dimm->dev = device_create_with_groups(&ndtest_dimm_class,
 747					     &priv->pdev.dev,
 748					     0, dimm, dimm_attribute_groups,
 749					     "test_dimm%d", id);
 750	if (!dimm->dev) {
 751		pr_err("Could not create dimm device attributes\n");
 752		return -ENOMEM;
 753	}
 754
 755	return 0;
 756}
 757
 758static int ndtest_nvdimm_init(struct ndtest_priv *p)
 759{
 760	struct ndtest_dimm *d;
 761	void *res;
 762	int i, id;
 763
 764	for (i = 0; i < p->config->dimm_count; i++) {
 765		d = &p->config->dimms[i];
 766		d->id = id = p->config->dimm_start + i;
 767		res = ndtest_alloc_resource(p, LABEL_SIZE, NULL);
 768		if (!res)
 769			return -ENOMEM;
 770
 771		d->label_area = res;
 772		sprintf(d->label_area, "label%d", id);
 773		d->config_size = LABEL_SIZE;
 774
 775		if (!ndtest_alloc_resource(p, d->size,
 776					   &p->dimm_dma[id]))
 777			return -ENOMEM;
 778
 779		if (!ndtest_alloc_resource(p, LABEL_SIZE,
 780					   &p->label_dma[id]))
 781			return -ENOMEM;
 782
 783		if (!ndtest_alloc_resource(p, LABEL_SIZE,
 784					   &p->dcr_dma[id]))
 785			return -ENOMEM;
 786
 787		d->address = p->dimm_dma[id];
 788
 789		ndtest_dimm_register(p, d, id);
 790	}
 791
 792	return 0;
 793}
 794
 795static ssize_t compatible_show(struct device *dev,
 796			       struct device_attribute *attr, char *buf)
 797{
 798	return sprintf(buf, "nvdimm_test");
 799}
 800static DEVICE_ATTR_RO(compatible);
 801
 802static struct attribute *of_node_attributes[] = {
 803	&dev_attr_compatible.attr,
 804	NULL
 805};
 806
 807static const struct attribute_group of_node_attribute_group = {
 808	.name = "of_node",
 809	.attrs = of_node_attributes,
 810};
 811
 812static const struct attribute_group *ndtest_attribute_groups[] = {
 813	&of_node_attribute_group,
 814	NULL,
 815};
 816
 817static int ndtest_bus_register(struct ndtest_priv *p)
 818{
 819	p->config = &bus_configs[p->pdev.id];
 820
 821	p->bus_desc.ndctl = ndtest_ctl;
 822	p->bus_desc.module = THIS_MODULE;
 823	p->bus_desc.provider_name = NULL;
 824	p->bus_desc.attr_groups = ndtest_attribute_groups;
 825
 826	p->bus = nvdimm_bus_register(&p->pdev.dev, &p->bus_desc);
 827	if (!p->bus) {
 828		dev_err(&p->pdev.dev, "Error creating nvdimm bus %pOF\n", p->dn);
 829		return -ENOMEM;
 830	}
 831
 832	return 0;
 833}
 834
 835static void ndtest_remove(struct platform_device *pdev)
 836{
 837	struct ndtest_priv *p = to_ndtest_priv(&pdev->dev);
 838
 839	nvdimm_bus_unregister(p->bus);
 840}
 841
 842static int ndtest_probe(struct platform_device *pdev)
 843{
 844	struct ndtest_priv *p;
 845	int rc;
 846
 847	p = to_ndtest_priv(&pdev->dev);
 848	if (ndtest_bus_register(p))
 849		return -ENOMEM;
 850
 851	p->dcr_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
 852				 sizeof(dma_addr_t), GFP_KERNEL);
 853	if (!p->dcr_dma) {
 854		rc = -ENOMEM;
 855		goto err;
 856	}
 857	p->label_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
 858				   sizeof(dma_addr_t), GFP_KERNEL);
 859	if (!p->label_dma) {
 860		rc = -ENOMEM;
 861		goto err;
 862	}
 863	p->dimm_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
 864				  sizeof(dma_addr_t), GFP_KERNEL);
 865	if (!p->dimm_dma) {
 866		rc = -ENOMEM;
 867		goto err;
 868	}
 869	rc = ndtest_nvdimm_init(p);
 870	if (rc)
 871		goto err;
 872
 873	rc = ndtest_init_regions(p);
 874	if (rc)
 875		goto err;
 876
 877	rc = devm_add_action_or_reset(&pdev->dev, put_dimms, p);
 878	if (rc)
 879		goto err;
 880
 881	platform_set_drvdata(pdev, p);
 882
 883	return 0;
 884
 885err:
 886	pr_err("%s:%d Failed nvdimm init\n", __func__, __LINE__);
 887	return rc;
 888}
 889
 890static const struct platform_device_id ndtest_id[] = {
 891	{ KBUILD_MODNAME },
 892	{ },
 893};
 894
 895static struct platform_driver ndtest_driver = {
 896	.probe = ndtest_probe,
 897	.remove = ndtest_remove,
 898	.driver = {
 899		.name = KBUILD_MODNAME,
 900	},
 901	.id_table = ndtest_id,
 902};
 903
 904static void ndtest_release(struct device *dev)
 905{
 906	struct ndtest_priv *p = to_ndtest_priv(dev);
 907
 908	kfree(p);
 909}
 910
 911static void cleanup_devices(void)
 912{
 913	int i;
 914
 915	for (i = 0; i < NUM_INSTANCES; i++)
 916		if (instances[i])
 917			platform_device_unregister(&instances[i]->pdev);
 918
 919	nfit_test_teardown();
 920
 921	if (ndtest_pool)
 922		gen_pool_destroy(ndtest_pool);
 923
 924
 925	class_unregister(&ndtest_dimm_class);
 926}
 927
 928static __init int ndtest_init(void)
 929{
 930	int rc, i;
 931
 932	pmem_test();
 933	libnvdimm_test();
 934	device_dax_test();
 935	dax_pmem_test();
 936
 937	nfit_test_setup(ndtest_resource_lookup, NULL);
 938
 939	rc = class_register(&ndtest_dimm_class);
 940	if (rc)
 941		goto err_register;
 942
 943	ndtest_pool = gen_pool_create(ilog2(SZ_4M), NUMA_NO_NODE);
 944	if (!ndtest_pool) {
 945		rc = -ENOMEM;
 946		goto err_register;
 947	}
 948
 949	if (gen_pool_add(ndtest_pool, SZ_4G, SZ_4G, NUMA_NO_NODE)) {
 950		rc = -ENOMEM;
 951		goto err_register;
 952	}
 953
 954	/* Each instance can be taken as a bus, which can have multiple dimms */
 955	for (i = 0; i < NUM_INSTANCES; i++) {
 956		struct ndtest_priv *priv;
 957		struct platform_device *pdev;
 958
 959		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 960		if (!priv) {
 961			rc = -ENOMEM;
 962			goto err_register;
 963		}
 964
 965		INIT_LIST_HEAD(&priv->resources);
 966		pdev = &priv->pdev;
 967		pdev->name = KBUILD_MODNAME;
 968		pdev->id = i;
 969		pdev->dev.release = ndtest_release;
 970		rc = platform_device_register(pdev);
 971		if (rc) {
 972			put_device(&pdev->dev);
 973			goto err_register;
 974		}
 975		get_device(&pdev->dev);
 976
 977		instances[i] = priv;
 978	}
 979
 980	rc = platform_driver_register(&ndtest_driver);
 981	if (rc)
 982		goto err_register;
 983
 984	return 0;
 985
 986err_register:
 987	pr_err("Error registering platform device\n");
 988	cleanup_devices();
 989
 990	return rc;
 991}
 992
 993static __exit void ndtest_exit(void)
 994{
 995	cleanup_devices();
 996	platform_driver_unregister(&ndtest_driver);
 997}
 998
 999module_init(ndtest_init);
1000module_exit(ndtest_exit);
1001MODULE_DESCRIPTION("Test non-NFIT devices");
1002MODULE_LICENSE("GPL");
1003MODULE_AUTHOR("IBM Corporation");
~/ Read-only file preview.