Skip to content

Commit 9399ab6

Browse files
santoshsdjbw
authored andcommitted
ndtest: Add dimms to the two buses
A config array is used to hold the dimms for each bus. These dimms are registered with nvdimm, and new nvdimms are created on the buses. Signed-off-by: Santosh Sivaraj <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dan Williams <[email protected]>
1 parent 107b04e commit 9399ab6

File tree

2 files changed

+294
-0
lines changed

2 files changed

+294
-0
lines changed

tools/testing/nvdimm/test/ndtest.c

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,83 @@ enum {
2525
NUM_DCR = 4,
2626
};
2727

28+
#define NDTEST_SCM_DIMM_CMD_MASK \
29+
((1ul << ND_CMD_GET_CONFIG_SIZE) | \
30+
(1ul << ND_CMD_GET_CONFIG_DATA) | \
31+
(1ul << ND_CMD_SET_CONFIG_DATA) | \
32+
(1ul << ND_CMD_CALL))
33+
34+
#define NFIT_DIMM_HANDLE(node, socket, imc, chan, dimm) \
35+
(((node & 0xfff) << 16) | ((socket & 0xf) << 12) \
36+
| ((imc & 0xf) << 8) | ((chan & 0xf) << 4) | (dimm & 0xf))
37+
38+
static DEFINE_SPINLOCK(ndtest_lock);
2839
static struct ndtest_priv *instances[NUM_INSTANCES];
2940
static struct class *ndtest_dimm_class;
41+
static struct gen_pool *ndtest_pool;
42+
43+
static struct ndtest_dimm dimm_group1[] = {
44+
{
45+
.size = DIMM_SIZE,
46+
.handle = NFIT_DIMM_HANDLE(0, 0, 0, 0, 0),
47+
.uuid_str = "1e5c75d2-b618-11ea-9aa3-507b9ddc0f72",
48+
.physical_id = 0,
49+
.num_formats = 2,
50+
},
51+
{
52+
.size = DIMM_SIZE,
53+
.handle = NFIT_DIMM_HANDLE(0, 0, 0, 0, 1),
54+
.uuid_str = "1c4d43ac-b618-11ea-be80-507b9ddc0f72",
55+
.physical_id = 1,
56+
.num_formats = 2,
57+
},
58+
{
59+
.size = DIMM_SIZE,
60+
.handle = NFIT_DIMM_HANDLE(0, 0, 1, 0, 0),
61+
.uuid_str = "a9f17ffc-b618-11ea-b36d-507b9ddc0f72",
62+
.physical_id = 2,
63+
.num_formats = 2,
64+
},
65+
{
66+
.size = DIMM_SIZE,
67+
.handle = NFIT_DIMM_HANDLE(0, 0, 1, 0, 1),
68+
.uuid_str = "b6b83b22-b618-11ea-8aae-507b9ddc0f72",
69+
.physical_id = 3,
70+
.num_formats = 2,
71+
},
72+
{
73+
.size = DIMM_SIZE,
74+
.handle = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0),
75+
.uuid_str = "bf9baaee-b618-11ea-b181-507b9ddc0f72",
76+
.physical_id = 4,
77+
.num_formats = 2,
78+
},
79+
};
80+
81+
static struct ndtest_dimm dimm_group2[] = {
82+
{
83+
.size = DIMM_SIZE,
84+
.handle = NFIT_DIMM_HANDLE(1, 0, 0, 0, 0),
85+
.uuid_str = "ca0817e2-b618-11ea-9db3-507b9ddc0f72",
86+
.physical_id = 0,
87+
.num_formats = 1,
88+
},
89+
};
90+
91+
static struct ndtest_config bus_configs[NUM_INSTANCES] = {
92+
/* bus 1 */
93+
{
94+
.dimm_start = 0,
95+
.dimm_count = ARRAY_SIZE(dimm_group1),
96+
.dimms = dimm_group1,
97+
},
98+
/* bus 2 */
99+
{
100+
.dimm_start = ARRAY_SIZE(dimm_group1),
101+
.dimm_count = ARRAY_SIZE(dimm_group2),
102+
.dimms = dimm_group2,
103+
},
104+
};
30105

31106
static inline struct ndtest_priv *to_ndtest_priv(struct device *dev)
32107
{
@@ -65,6 +140,152 @@ static int ndtest_ctl(struct nvdimm_bus_descriptor *nd_desc,
65140
return 0;
66141
}
67142

143+
static void ndtest_release_resource(void *data)
144+
{
145+
struct nfit_test_resource *res = data;
146+
147+
spin_lock(&ndtest_lock);
148+
list_del(&res->list);
149+
spin_unlock(&ndtest_lock);
150+
151+
if (resource_size(&res->res) >= DIMM_SIZE)
152+
gen_pool_free(ndtest_pool, res->res.start,
153+
resource_size(&res->res));
154+
vfree(res->buf);
155+
kfree(res);
156+
}
157+
158+
static void *ndtest_alloc_resource(struct ndtest_priv *p, size_t size,
159+
dma_addr_t *dma)
160+
{
161+
dma_addr_t __dma;
162+
void *buf;
163+
struct nfit_test_resource *res;
164+
struct genpool_data_align data = {
165+
.align = SZ_128M,
166+
};
167+
168+
res = kzalloc(sizeof(*res), GFP_KERNEL);
169+
if (!res)
170+
return NULL;
171+
172+
buf = vmalloc(size);
173+
if (size >= DIMM_SIZE)
174+
__dma = gen_pool_alloc_algo(ndtest_pool, size,
175+
gen_pool_first_fit_align, &data);
176+
else
177+
__dma = (unsigned long) buf;
178+
179+
if (!__dma)
180+
goto buf_err;
181+
182+
INIT_LIST_HEAD(&res->list);
183+
res->dev = &p->pdev.dev;
184+
res->buf = buf;
185+
res->res.start = __dma;
186+
res->res.end = __dma + size - 1;
187+
res->res.name = "NFIT";
188+
spin_lock_init(&res->lock);
189+
INIT_LIST_HEAD(&res->requests);
190+
spin_lock(&ndtest_lock);
191+
list_add(&res->list, &p->resources);
192+
spin_unlock(&ndtest_lock);
193+
194+
if (dma)
195+
*dma = __dma;
196+
197+
if (!devm_add_action(&p->pdev.dev, ndtest_release_resource, res))
198+
return res->buf;
199+
200+
buf_err:
201+
if (__dma && size >= DIMM_SIZE)
202+
gen_pool_free(ndtest_pool, __dma, size);
203+
if (buf)
204+
vfree(buf);
205+
kfree(res);
206+
207+
return NULL;
208+
}
209+
210+
static void put_dimms(void *data)
211+
{
212+
struct ndtest_priv *p = data;
213+
int i;
214+
215+
for (i = 0; i < p->config->dimm_count; i++)
216+
if (p->config->dimms[i].dev) {
217+
device_unregister(p->config->dimms[i].dev);
218+
p->config->dimms[i].dev = NULL;
219+
}
220+
}
221+
222+
static int ndtest_dimm_register(struct ndtest_priv *priv,
223+
struct ndtest_dimm *dimm, int id)
224+
{
225+
struct device *dev = &priv->pdev.dev;
226+
unsigned long dimm_flags = dimm->flags;
227+
228+
if (dimm->num_formats > 1) {
229+
set_bit(NDD_ALIASING, &dimm_flags);
230+
set_bit(NDD_LABELING, &dimm_flags);
231+
}
232+
233+
dimm->nvdimm = nvdimm_create(priv->bus, dimm, NULL, dimm_flags,
234+
NDTEST_SCM_DIMM_CMD_MASK, 0, NULL);
235+
if (!dimm->nvdimm) {
236+
dev_err(dev, "Error creating DIMM object for %pOF\n", priv->dn);
237+
return -ENXIO;
238+
}
239+
240+
dimm->dev = device_create_with_groups(ndtest_dimm_class,
241+
&priv->pdev.dev,
242+
0, dimm, NULL,
243+
"test_dimm%d", id);
244+
if (!dimm->dev) {
245+
pr_err("Could not create dimm device attributes\n");
246+
return -ENOMEM;
247+
}
248+
249+
return 0;
250+
}
251+
252+
static int ndtest_nvdimm_init(struct ndtest_priv *p)
253+
{
254+
struct ndtest_dimm *d;
255+
void *res;
256+
int i, id;
257+
258+
for (i = 0; i < p->config->dimm_count; i++) {
259+
d = &p->config->dimms[i];
260+
d->id = id = p->config->dimm_start + i;
261+
res = ndtest_alloc_resource(p, LABEL_SIZE, NULL);
262+
if (!res)
263+
return -ENOMEM;
264+
265+
d->label_area = res;
266+
sprintf(d->label_area, "label%d", id);
267+
d->config_size = LABEL_SIZE;
268+
269+
if (!ndtest_alloc_resource(p, d->size,
270+
&p->dimm_dma[id]))
271+
return -ENOMEM;
272+
273+
if (!ndtest_alloc_resource(p, LABEL_SIZE,
274+
&p->label_dma[id]))
275+
return -ENOMEM;
276+
277+
if (!ndtest_alloc_resource(p, LABEL_SIZE,
278+
&p->dcr_dma[id]))
279+
return -ENOMEM;
280+
281+
d->address = p->dimm_dma[id];
282+
283+
ndtest_dimm_register(p, d, id);
284+
}
285+
286+
return 0;
287+
}
288+
68289
static ssize_t compatible_show(struct device *dev,
69290
struct device_attribute *attr, char *buf)
70291
{
@@ -89,6 +310,8 @@ static const struct attribute_group *ndtest_attribute_groups[] = {
89310

90311
static int ndtest_bus_register(struct ndtest_priv *p)
91312
{
313+
p->config = &bus_configs[p->pdev.id];
314+
92315
p->bus_desc.ndctl = ndtest_ctl;
93316
p->bus_desc.module = THIS_MODULE;
94317
p->bus_desc.provider_name = NULL;
@@ -114,14 +337,34 @@ static int ndtest_remove(struct platform_device *pdev)
114337
static int ndtest_probe(struct platform_device *pdev)
115338
{
116339
struct ndtest_priv *p;
340+
int rc;
117341

118342
p = to_ndtest_priv(&pdev->dev);
119343
if (ndtest_bus_register(p))
120344
return -ENOMEM;
121345

346+
p->dcr_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
347+
sizeof(dma_addr_t), GFP_KERNEL);
348+
p->label_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
349+
sizeof(dma_addr_t), GFP_KERNEL);
350+
p->dimm_dma = devm_kcalloc(&p->pdev.dev, NUM_DCR,
351+
sizeof(dma_addr_t), GFP_KERNEL);
352+
353+
rc = ndtest_nvdimm_init(p);
354+
if (rc)
355+
goto err;
356+
357+
rc = devm_add_action_or_reset(&pdev->dev, put_dimms, p);
358+
if (rc)
359+
goto err;
360+
122361
platform_set_drvdata(pdev, p);
123362

124363
return 0;
364+
365+
err:
366+
pr_err("%s:%d Failed nvdimm init\n", __func__, __LINE__);
367+
return rc;
125368
}
126369

127370
static const struct platform_device_id ndtest_id[] = {
@@ -155,6 +398,10 @@ static void cleanup_devices(void)
155398

156399
nfit_test_teardown();
157400

401+
if (ndtest_pool)
402+
gen_pool_destroy(ndtest_pool);
403+
404+
158405
if (ndtest_dimm_class)
159406
class_destroy(ndtest_dimm_class);
160407
}
@@ -178,6 +425,17 @@ static __init int ndtest_init(void)
178425
goto err_register;
179426
}
180427

428+
ndtest_pool = gen_pool_create(ilog2(SZ_4M), NUMA_NO_NODE);
429+
if (!ndtest_pool) {
430+
rc = -ENOMEM;
431+
goto err_register;
432+
}
433+
434+
if (gen_pool_add(ndtest_pool, SZ_4G, SZ_4G, NUMA_NO_NODE)) {
435+
rc = -ENOMEM;
436+
goto err_register;
437+
}
438+
181439
/* Each instance can be taken as a bus, which can have multiple dimms */
182440
for (i = 0; i < NUM_INSTANCES; i++) {
183441
struct ndtest_priv *priv;

tools/testing/nvdimm/test/ndtest.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,48 @@
55
#include <linux/platform_device.h>
66
#include <linux/libnvdimm.h>
77

8+
struct ndtest_config;
9+
810
struct ndtest_priv {
911
struct platform_device pdev;
1012
struct device_node *dn;
1113
struct list_head resources;
1214
struct nvdimm_bus_descriptor bus_desc;
1315
struct nvdimm_bus *bus;
16+
struct ndtest_config *config;
17+
18+
dma_addr_t *dcr_dma;
19+
dma_addr_t *label_dma;
20+
dma_addr_t *dimm_dma;
21+
};
22+
23+
struct ndtest_dimm {
24+
struct device *dev;
25+
struct nvdimm *nvdimm;
26+
struct ndtest_blk_mmio *mmio;
27+
struct nd_region *blk_region;
28+
29+
dma_addr_t address;
30+
unsigned long long flags;
31+
unsigned long config_size;
32+
void *label_area;
33+
char *uuid_str;
34+
35+
unsigned int size;
36+
unsigned int handle;
37+
unsigned int fail_cmd;
38+
unsigned int physical_id;
39+
unsigned int num_formats;
40+
int id;
41+
int fail_cmd_code;
42+
u8 no_alias;
43+
};
44+
45+
struct ndtest_config {
46+
struct ndtest_dimm *dimms;
47+
unsigned int dimm_count;
48+
unsigned int dimm_start;
49+
u8 num_regions;
1450
};
1551

1652
#endif /* NDTEST_H */

0 commit comments

Comments
 (0)