Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  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	p->label_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
854				   sizeof(dma_addr_t), GFP_KERNEL);
855	p->dimm_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
856				  sizeof(dma_addr_t), GFP_KERNEL);
857
858	rc = ndtest_nvdimm_init(p);
859	if (rc)
860		goto err;
861
862	rc = ndtest_init_regions(p);
863	if (rc)
864		goto err;
865
866	rc = devm_add_action_or_reset(&pdev->dev, put_dimms, p);
867	if (rc)
868		goto err;
869
870	platform_set_drvdata(pdev, p);
871
872	return 0;
873
874err:
875	pr_err("%s:%d Failed nvdimm init\n", __func__, __LINE__);
876	return rc;
877}
878
879static const struct platform_device_id ndtest_id[] = {
880	{ KBUILD_MODNAME },
881	{ },
882};
883
884static struct platform_driver ndtest_driver = {
885	.probe = ndtest_probe,
886	.remove = ndtest_remove,
887	.driver = {
888		.name = KBUILD_MODNAME,
889	},
890	.id_table = ndtest_id,
891};
892
893static void ndtest_release(struct device *dev)
894{
895	struct ndtest_priv *p = to_ndtest_priv(dev);
896
897	kfree(p);
898}
899
900static void cleanup_devices(void)
901{
902	int i;
903
904	for (i = 0; i < NUM_INSTANCES; i++)
905		if (instances[i])
906			platform_device_unregister(&instances[i]->pdev);
907
908	nfit_test_teardown();
909
910	if (ndtest_pool)
911		gen_pool_destroy(ndtest_pool);
912
913
914	class_unregister(&ndtest_dimm_class);
915}
916
917static __init int ndtest_init(void)
918{
919	int rc, i;
920
921	pmem_test();
922	libnvdimm_test();
923	device_dax_test();
924	dax_pmem_test();
925
926	nfit_test_setup(ndtest_resource_lookup, NULL);
927
928	rc = class_register(&ndtest_dimm_class);
929	if (rc)
930		goto err_register;
931
932	ndtest_pool = gen_pool_create(ilog2(SZ_4M), NUMA_NO_NODE);
933	if (!ndtest_pool) {
934		rc = -ENOMEM;
935		goto err_register;
936	}
937
938	if (gen_pool_add(ndtest_pool, SZ_4G, SZ_4G, NUMA_NO_NODE)) {
939		rc = -ENOMEM;
940		goto err_register;
941	}
942
943	/* Each instance can be taken as a bus, which can have multiple dimms */
944	for (i = 0; i < NUM_INSTANCES; i++) {
945		struct ndtest_priv *priv;
946		struct platform_device *pdev;
947
948		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
949		if (!priv) {
950			rc = -ENOMEM;
951			goto err_register;
952		}
953
954		INIT_LIST_HEAD(&priv->resources);
955		pdev = &priv->pdev;
956		pdev->name = KBUILD_MODNAME;
957		pdev->id = i;
958		pdev->dev.release = ndtest_release;
959		rc = platform_device_register(pdev);
960		if (rc) {
961			put_device(&pdev->dev);
962			goto err_register;
963		}
964		get_device(&pdev->dev);
965
966		instances[i] = priv;
967	}
968
969	rc = platform_driver_register(&ndtest_driver);
970	if (rc)
971		goto err_register;
972
973	return 0;
974
975err_register:
976	pr_err("Error registering platform device\n");
977	cleanup_devices();
978
979	return rc;
980}
981
982static __exit void ndtest_exit(void)
983{
984	cleanup_devices();
985	platform_driver_unregister(&ndtest_driver);
986}
987
988module_init(ndtest_init);
989module_exit(ndtest_exit);
990MODULE_DESCRIPTION("Test non-NFIT devices");
991MODULE_LICENSE("GPL");
992MODULE_AUTHOR("IBM Corporation");