Merge tag 'Smack-for-5.6' of git://github.com/cschaufler/smack-next
[linux-2.6-microblaze.git] / arch / powerpc / platforms / pseries / papr_scm.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #define pr_fmt(fmt)     "papr-scm: " fmt
4
5 #include <linux/of.h>
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/ioport.h>
9 #include <linux/slab.h>
10 #include <linux/ndctl.h>
11 #include <linux/sched.h>
12 #include <linux/libnvdimm.h>
13 #include <linux/platform_device.h>
14 #include <linux/delay.h>
15
16 #include <asm/plpar_wrappers.h>
17
18 #define BIND_ANY_ADDR (~0ul)
19
20 #define PAPR_SCM_DIMM_CMD_MASK \
21         ((1ul << ND_CMD_GET_CONFIG_SIZE) | \
22          (1ul << ND_CMD_GET_CONFIG_DATA) | \
23          (1ul << ND_CMD_SET_CONFIG_DATA))
24
25 struct papr_scm_priv {
26         struct platform_device *pdev;
27         struct device_node *dn;
28         uint32_t drc_index;
29         uint64_t blocks;
30         uint64_t block_size;
31         int metadata_size;
32         bool is_volatile;
33
34         uint64_t bound_addr;
35
36         struct nvdimm_bus_descriptor bus_desc;
37         struct nvdimm_bus *bus;
38         struct nvdimm *nvdimm;
39         struct resource res;
40         struct nd_region *region;
41         struct nd_interleave_set nd_set;
42 };
43
44 static int drc_pmem_bind(struct papr_scm_priv *p)
45 {
46         unsigned long ret[PLPAR_HCALL_BUFSIZE];
47         uint64_t saved = 0;
48         uint64_t token;
49         int64_t rc;
50
51         /*
52          * When the hypervisor cannot map all the requested memory in a single
53          * hcall it returns H_BUSY and we call again with the token until
54          * we get H_SUCCESS. Aborting the retry loop before getting H_SUCCESS
55          * leave the system in an undefined state, so we wait.
56          */
57         token = 0;
58
59         do {
60                 rc = plpar_hcall(H_SCM_BIND_MEM, ret, p->drc_index, 0,
61                                 p->blocks, BIND_ANY_ADDR, token);
62                 token = ret[0];
63                 if (!saved)
64                         saved = ret[1];
65                 cond_resched();
66         } while (rc == H_BUSY);
67
68         if (rc)
69                 return rc;
70
71         p->bound_addr = saved;
72         dev_dbg(&p->pdev->dev, "bound drc 0x%x to 0x%lx\n",
73                 p->drc_index, (unsigned long)saved);
74         return rc;
75 }
76
77 static void drc_pmem_unbind(struct papr_scm_priv *p)
78 {
79         unsigned long ret[PLPAR_HCALL_BUFSIZE];
80         uint64_t token = 0;
81         int64_t rc;
82
83         dev_dbg(&p->pdev->dev, "unbind drc 0x%x\n", p->drc_index);
84
85         /* NB: unbind has the same retry requirements as drc_pmem_bind() */
86         do {
87
88                 /* Unbind of all SCM resources associated with drcIndex */
89                 rc = plpar_hcall(H_SCM_UNBIND_ALL, ret, H_UNBIND_SCOPE_DRC,
90                                  p->drc_index, token);
91                 token = ret[0];
92
93                 /* Check if we are stalled for some time */
94                 if (H_IS_LONG_BUSY(rc)) {
95                         msleep(get_longbusy_msecs(rc));
96                         rc = H_BUSY;
97                 } else if (rc == H_BUSY) {
98                         cond_resched();
99                 }
100
101         } while (rc == H_BUSY);
102
103         if (rc)
104                 dev_err(&p->pdev->dev, "unbind error: %lld\n", rc);
105         else
106                 dev_dbg(&p->pdev->dev, "unbind drc 0x%x complete\n",
107                         p->drc_index);
108
109         return;
110 }
111
112 static int drc_pmem_query_n_bind(struct papr_scm_priv *p)
113 {
114         unsigned long start_addr;
115         unsigned long end_addr;
116         unsigned long ret[PLPAR_HCALL_BUFSIZE];
117         int64_t rc;
118
119
120         rc = plpar_hcall(H_SCM_QUERY_BLOCK_MEM_BINDING, ret,
121                          p->drc_index, 0);
122         if (rc)
123                 goto err_out;
124         start_addr = ret[0];
125
126         /* Make sure the full region is bound. */
127         rc = plpar_hcall(H_SCM_QUERY_BLOCK_MEM_BINDING, ret,
128                          p->drc_index, p->blocks - 1);
129         if (rc)
130                 goto err_out;
131         end_addr = ret[0];
132
133         if ((end_addr - start_addr) != ((p->blocks - 1) * p->block_size))
134                 goto err_out;
135
136         p->bound_addr = start_addr;
137         dev_dbg(&p->pdev->dev, "bound drc 0x%x to 0x%lx\n", p->drc_index, start_addr);
138         return rc;
139
140 err_out:
141         dev_info(&p->pdev->dev,
142                  "Failed to query, trying an unbind followed by bind");
143         drc_pmem_unbind(p);
144         return drc_pmem_bind(p);
145 }
146
147
148 static int papr_scm_meta_get(struct papr_scm_priv *p,
149                              struct nd_cmd_get_config_data_hdr *hdr)
150 {
151         unsigned long data[PLPAR_HCALL_BUFSIZE];
152         unsigned long offset, data_offset;
153         int len, read;
154         int64_t ret;
155
156         if ((hdr->in_offset + hdr->in_length) > p->metadata_size)
157                 return -EINVAL;
158
159         for (len = hdr->in_length; len; len -= read) {
160
161                 data_offset = hdr->in_length - len;
162                 offset = hdr->in_offset + data_offset;
163
164                 if (len >= 8)
165                         read = 8;
166                 else if (len >= 4)
167                         read = 4;
168                 else if (len >= 2)
169                         read = 2;
170                 else
171                         read = 1;
172
173                 ret = plpar_hcall(H_SCM_READ_METADATA, data, p->drc_index,
174                                   offset, read);
175
176                 if (ret == H_PARAMETER) /* bad DRC index */
177                         return -ENODEV;
178                 if (ret)
179                         return -EINVAL; /* other invalid parameter */
180
181                 switch (read) {
182                 case 8:
183                         *(uint64_t *)(hdr->out_buf + data_offset) = be64_to_cpu(data[0]);
184                         break;
185                 case 4:
186                         *(uint32_t *)(hdr->out_buf + data_offset) = be32_to_cpu(data[0] & 0xffffffff);
187                         break;
188
189                 case 2:
190                         *(uint16_t *)(hdr->out_buf + data_offset) = be16_to_cpu(data[0] & 0xffff);
191                         break;
192
193                 case 1:
194                         *(uint8_t *)(hdr->out_buf + data_offset) = (data[0] & 0xff);
195                         break;
196                 }
197         }
198         return 0;
199 }
200
201 static int papr_scm_meta_set(struct papr_scm_priv *p,
202                              struct nd_cmd_set_config_hdr *hdr)
203 {
204         unsigned long offset, data_offset;
205         int len, wrote;
206         unsigned long data;
207         __be64 data_be;
208         int64_t ret;
209
210         if ((hdr->in_offset + hdr->in_length) > p->metadata_size)
211                 return -EINVAL;
212
213         for (len = hdr->in_length; len; len -= wrote) {
214
215                 data_offset = hdr->in_length - len;
216                 offset = hdr->in_offset + data_offset;
217
218                 if (len >= 8) {
219                         data = *(uint64_t *)(hdr->in_buf + data_offset);
220                         data_be = cpu_to_be64(data);
221                         wrote = 8;
222                 } else if (len >= 4) {
223                         data = *(uint32_t *)(hdr->in_buf + data_offset);
224                         data &= 0xffffffff;
225                         data_be = cpu_to_be32(data);
226                         wrote = 4;
227                 } else if (len >= 2) {
228                         data = *(uint16_t *)(hdr->in_buf + data_offset);
229                         data &= 0xffff;
230                         data_be = cpu_to_be16(data);
231                         wrote = 2;
232                 } else {
233                         data_be = *(uint8_t *)(hdr->in_buf + data_offset);
234                         data_be &= 0xff;
235                         wrote = 1;
236                 }
237
238                 ret = plpar_hcall_norets(H_SCM_WRITE_METADATA, p->drc_index,
239                                          offset, data_be, wrote);
240                 if (ret == H_PARAMETER) /* bad DRC index */
241                         return -ENODEV;
242                 if (ret)
243                         return -EINVAL; /* other invalid parameter */
244         }
245
246         return 0;
247 }
248
249 int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
250                 unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
251 {
252         struct nd_cmd_get_config_size *get_size_hdr;
253         struct papr_scm_priv *p;
254
255         /* Only dimm-specific calls are supported atm */
256         if (!nvdimm)
257                 return -EINVAL;
258
259         p = nvdimm_provider_data(nvdimm);
260
261         switch (cmd) {
262         case ND_CMD_GET_CONFIG_SIZE:
263                 get_size_hdr = buf;
264
265                 get_size_hdr->status = 0;
266                 get_size_hdr->max_xfer = 8;
267                 get_size_hdr->config_size = p->metadata_size;
268                 *cmd_rc = 0;
269                 break;
270
271         case ND_CMD_GET_CONFIG_DATA:
272                 *cmd_rc = papr_scm_meta_get(p, buf);
273                 break;
274
275         case ND_CMD_SET_CONFIG_DATA:
276                 *cmd_rc = papr_scm_meta_set(p, buf);
277                 break;
278
279         default:
280                 return -EINVAL;
281         }
282
283         dev_dbg(&p->pdev->dev, "returned with cmd_rc = %d\n", *cmd_rc);
284
285         return 0;
286 }
287
288 static inline int papr_scm_node(int node)
289 {
290         int min_dist = INT_MAX, dist;
291         int nid, min_node;
292
293         if ((node == NUMA_NO_NODE) || node_online(node))
294                 return node;
295
296         min_node = first_online_node;
297         for_each_online_node(nid) {
298                 dist = node_distance(node, nid);
299                 if (dist < min_dist) {
300                         min_dist = dist;
301                         min_node = nid;
302                 }
303         }
304         return min_node;
305 }
306
307 static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
308 {
309         struct device *dev = &p->pdev->dev;
310         struct nd_mapping_desc mapping;
311         struct nd_region_desc ndr_desc;
312         unsigned long dimm_flags;
313         int target_nid, online_nid;
314
315         p->bus_desc.ndctl = papr_scm_ndctl;
316         p->bus_desc.module = THIS_MODULE;
317         p->bus_desc.of_node = p->pdev->dev.of_node;
318         p->bus_desc.provider_name = kstrdup(p->pdev->name, GFP_KERNEL);
319
320         if (!p->bus_desc.provider_name)
321                 return -ENOMEM;
322
323         p->bus = nvdimm_bus_register(NULL, &p->bus_desc);
324         if (!p->bus) {
325                 dev_err(dev, "Error creating nvdimm bus %pOF\n", p->dn);
326                 kfree(p->bus_desc.provider_name);
327                 return -ENXIO;
328         }
329
330         dimm_flags = 0;
331         set_bit(NDD_ALIASING, &dimm_flags);
332
333         p->nvdimm = nvdimm_create(p->bus, p, NULL, dimm_flags,
334                                   PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
335         if (!p->nvdimm) {
336                 dev_err(dev, "Error creating DIMM object for %pOF\n", p->dn);
337                 goto err;
338         }
339
340         if (nvdimm_bus_check_dimm_count(p->bus, 1))
341                 goto err;
342
343         /* now add the region */
344
345         memset(&mapping, 0, sizeof(mapping));
346         mapping.nvdimm = p->nvdimm;
347         mapping.start = 0;
348         mapping.size = p->blocks * p->block_size; // XXX: potential overflow?
349
350         memset(&ndr_desc, 0, sizeof(ndr_desc));
351         target_nid = dev_to_node(&p->pdev->dev);
352         online_nid = papr_scm_node(target_nid);
353         ndr_desc.numa_node = online_nid;
354         ndr_desc.target_node = target_nid;
355         ndr_desc.res = &p->res;
356         ndr_desc.of_node = p->dn;
357         ndr_desc.provider_data = p;
358         ndr_desc.mapping = &mapping;
359         ndr_desc.num_mappings = 1;
360         ndr_desc.nd_set = &p->nd_set;
361
362         if (p->is_volatile)
363                 p->region = nvdimm_volatile_region_create(p->bus, &ndr_desc);
364         else
365                 p->region = nvdimm_pmem_region_create(p->bus, &ndr_desc);
366         if (!p->region) {
367                 dev_err(dev, "Error registering region %pR from %pOF\n",
368                                 ndr_desc.res, p->dn);
369                 goto err;
370         }
371         if (target_nid != online_nid)
372                 dev_info(dev, "Region registered with target node %d and online node %d",
373                          target_nid, online_nid);
374
375         return 0;
376
377 err:    nvdimm_bus_unregister(p->bus);
378         kfree(p->bus_desc.provider_name);
379         return -ENXIO;
380 }
381
382 static int papr_scm_probe(struct platform_device *pdev)
383 {
384         struct device_node *dn = pdev->dev.of_node;
385         u32 drc_index, metadata_size;
386         u64 blocks, block_size;
387         struct papr_scm_priv *p;
388         const char *uuid_str;
389         u64 uuid[2];
390         int rc;
391
392         /* check we have all the required DT properties */
393         if (of_property_read_u32(dn, "ibm,my-drc-index", &drc_index)) {
394                 dev_err(&pdev->dev, "%pOF: missing drc-index!\n", dn);
395                 return -ENODEV;
396         }
397
398         if (of_property_read_u64(dn, "ibm,block-size", &block_size)) {
399                 dev_err(&pdev->dev, "%pOF: missing block-size!\n", dn);
400                 return -ENODEV;
401         }
402
403         if (of_property_read_u64(dn, "ibm,number-of-blocks", &blocks)) {
404                 dev_err(&pdev->dev, "%pOF: missing number-of-blocks!\n", dn);
405                 return -ENODEV;
406         }
407
408         if (of_property_read_string(dn, "ibm,unit-guid", &uuid_str)) {
409                 dev_err(&pdev->dev, "%pOF: missing unit-guid!\n", dn);
410                 return -ENODEV;
411         }
412
413
414         p = kzalloc(sizeof(*p), GFP_KERNEL);
415         if (!p)
416                 return -ENOMEM;
417
418         /* optional DT properties */
419         of_property_read_u32(dn, "ibm,metadata-size", &metadata_size);
420
421         p->dn = dn;
422         p->drc_index = drc_index;
423         p->block_size = block_size;
424         p->blocks = blocks;
425         p->is_volatile = !of_property_read_bool(dn, "ibm,cache-flush-required");
426
427         /* We just need to ensure that set cookies are unique across */
428         uuid_parse(uuid_str, (uuid_t *) uuid);
429         /*
430          * cookie1 and cookie2 are not really little endian
431          * we store a little endian representation of the
432          * uuid str so that we can compare this with the label
433          * area cookie irrespective of the endian config with which
434          * the kernel is built.
435          */
436         p->nd_set.cookie1 = cpu_to_le64(uuid[0]);
437         p->nd_set.cookie2 = cpu_to_le64(uuid[1]);
438
439         /* might be zero */
440         p->metadata_size = metadata_size;
441         p->pdev = pdev;
442
443         /* request the hypervisor to bind this region to somewhere in memory */
444         rc = drc_pmem_bind(p);
445
446         /* If phyp says drc memory still bound then force unbound and retry */
447         if (rc == H_OVERLAP)
448                 rc = drc_pmem_query_n_bind(p);
449
450         if (rc != H_SUCCESS) {
451                 dev_err(&p->pdev->dev, "bind err: %d\n", rc);
452                 rc = -ENXIO;
453                 goto err;
454         }
455
456         /* setup the resource for the newly bound range */
457         p->res.start = p->bound_addr;
458         p->res.end   = p->bound_addr + p->blocks * p->block_size - 1;
459         p->res.name  = pdev->name;
460         p->res.flags = IORESOURCE_MEM;
461
462         rc = papr_scm_nvdimm_init(p);
463         if (rc)
464                 goto err2;
465
466         platform_set_drvdata(pdev, p);
467
468         return 0;
469
470 err2:   drc_pmem_unbind(p);
471 err:    kfree(p);
472         return rc;
473 }
474
475 static int papr_scm_remove(struct platform_device *pdev)
476 {
477         struct papr_scm_priv *p = platform_get_drvdata(pdev);
478
479         nvdimm_bus_unregister(p->bus);
480         drc_pmem_unbind(p);
481         kfree(p->bus_desc.provider_name);
482         kfree(p);
483
484         return 0;
485 }
486
487 static const struct of_device_id papr_scm_match[] = {
488         { .compatible = "ibm,pmemory" },
489         { },
490 };
491
492 static struct platform_driver papr_scm_driver = {
493         .probe = papr_scm_probe,
494         .remove = papr_scm_remove,
495         .driver = {
496                 .name = "papr_scm",
497                 .of_match_table = papr_scm_match,
498         },
499 };
500
501 module_platform_driver(papr_scm_driver);
502 MODULE_DEVICE_TABLE(of, papr_scm_match);
503 MODULE_LICENSE("GPL");
504 MODULE_AUTHOR("IBM Corporation");