@@ -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 );
2839static struct ndtest_priv * instances [NUM_INSTANCES ];
2940static 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
31106static 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+
68289static 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
90311static 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)
114337static 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
127370static 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 ;
0 commit comments