hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/nvdimm/pfn_devs.c
....@@ -1,14 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright(c) 2013-2016 Intel Corporation. All rights reserved.
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of version 2 of the GNU General Public License as
6
- * published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope that it will be useful, but
9
- * WITHOUT ANY WARRANTY; without even the implied warranty of
10
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
- * General Public License for more details.
124 */
135 #include <linux/memremap.h>
146 #include <linux/blkdev.h>
....@@ -33,17 +25,6 @@
3325 kfree(nd_pfn->uuid);
3426 kfree(nd_pfn);
3527 }
36
-
37
-static struct device_type nd_pfn_device_type = {
38
- .name = "nd_pfn",
39
- .release = nd_pfn_release,
40
-};
41
-
42
-bool is_nd_pfn(struct device *dev)
43
-{
44
- return dev ? dev->type == &nd_pfn_device_type : false;
45
-}
46
-EXPORT_SYMBOL(is_nd_pfn);
4728
4829 struct nd_pfn *to_nd_pfn(struct device *dev)
4930 {
....@@ -75,7 +56,7 @@
7556 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
7657 ssize_t rc = 0;
7758
78
- device_lock(dev);
59
+ nd_device_lock(dev);
7960 nvdimm_bus_lock(dev);
8061 if (dev->driver)
8162 rc = -EBUSY;
....@@ -97,7 +78,7 @@
9778 dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
9879 buf[len - 1] == '\n' ? "" : "\n");
9980 nvdimm_bus_unlock(dev);
100
- device_unlock(dev);
81
+ nd_device_unlock(dev);
10182
10283 return rc ? rc : len;
10384 }
....@@ -111,43 +92,46 @@
11192 return sprintf(buf, "%ld\n", nd_pfn->align);
11293 }
11394
114
-static const unsigned long *nd_pfn_supported_alignments(void)
95
+static unsigned long *nd_pfn_supported_alignments(unsigned long *alignments)
11596 {
116
- /*
117
- * This needs to be a non-static variable because the *_SIZE
118
- * macros aren't always constants.
119
- */
120
- const unsigned long supported_alignments[] = {
121
- PAGE_SIZE,
122
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
123
- HPAGE_PMD_SIZE,
124
-#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
125
- HPAGE_PUD_SIZE,
126
-#endif
127
-#endif
128
- 0,
129
- };
130
- static unsigned long data[ARRAY_SIZE(supported_alignments)];
13197
132
- memcpy(data, supported_alignments, sizeof(data));
98
+ alignments[0] = PAGE_SIZE;
13399
134
- return data;
100
+ if (has_transparent_hugepage()) {
101
+ alignments[1] = HPAGE_PMD_SIZE;
102
+ if (IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD))
103
+ alignments[2] = HPAGE_PUD_SIZE;
104
+ }
105
+
106
+ return alignments;
107
+}
108
+
109
+/*
110
+ * Use pmd mapping if supported as default alignment
111
+ */
112
+static unsigned long nd_pfn_default_alignment(void)
113
+{
114
+
115
+ if (has_transparent_hugepage())
116
+ return HPAGE_PMD_SIZE;
117
+ return PAGE_SIZE;
135118 }
136119
137120 static ssize_t align_store(struct device *dev,
138121 struct device_attribute *attr, const char *buf, size_t len)
139122 {
140123 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
124
+ unsigned long aligns[MAX_NVDIMM_ALIGN] = { [0] = 0, };
141125 ssize_t rc;
142126
143
- device_lock(dev);
127
+ nd_device_lock(dev);
144128 nvdimm_bus_lock(dev);
145129 rc = nd_size_select_store(dev, buf, &nd_pfn->align,
146
- nd_pfn_supported_alignments());
130
+ nd_pfn_supported_alignments(aligns));
147131 dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
148132 buf[len - 1] == '\n' ? "" : "\n");
149133 nvdimm_bus_unlock(dev);
150
- device_unlock(dev);
134
+ nd_device_unlock(dev);
151135
152136 return rc ? rc : len;
153137 }
....@@ -169,11 +153,11 @@
169153 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
170154 ssize_t rc;
171155
172
- device_lock(dev);
156
+ nd_device_lock(dev);
173157 rc = nd_uuid_store(dev, &nd_pfn->uuid, buf, len);
174158 dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
175159 buf[len - 1] == '\n' ? "" : "\n");
176
- device_unlock(dev);
160
+ nd_device_unlock(dev);
177161
178162 return rc ? rc : len;
179163 }
....@@ -198,13 +182,13 @@
198182 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
199183 ssize_t rc;
200184
201
- device_lock(dev);
185
+ nd_device_lock(dev);
202186 nvdimm_bus_lock(dev);
203187 rc = nd_namespace_store(dev, &nd_pfn->ndns, buf, len);
204188 dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
205189 buf[len - 1] == '\n' ? "" : "\n");
206190 nvdimm_bus_unlock(dev);
207
- device_unlock(dev);
191
+ nd_device_unlock(dev);
208192
209193 return rc;
210194 }
....@@ -216,7 +200,7 @@
216200 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
217201 ssize_t rc;
218202
219
- device_lock(dev);
203
+ nd_device_lock(dev);
220204 if (dev->driver) {
221205 struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
222206 u64 offset = __le64_to_cpu(pfn_sb->dataoff);
....@@ -230,11 +214,11 @@
230214 /* no address to convey if the pfn instance is disabled */
231215 rc = -ENXIO;
232216 }
233
- device_unlock(dev);
217
+ nd_device_unlock(dev);
234218
235219 return rc;
236220 }
237
-static DEVICE_ATTR_RO(resource);
221
+static DEVICE_ATTR_ADMIN_RO(resource);
238222
239223 static ssize_t size_show(struct device *dev,
240224 struct device_attribute *attr, char *buf)
....@@ -242,7 +226,7 @@
242226 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
243227 ssize_t rc;
244228
245
- device_lock(dev);
229
+ nd_device_lock(dev);
246230 if (dev->driver) {
247231 struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
248232 u64 offset = __le64_to_cpu(pfn_sb->dataoff);
....@@ -258,7 +242,7 @@
258242 /* no size to convey if the pfn instance is disabled */
259243 rc = -ENXIO;
260244 }
261
- device_unlock(dev);
245
+ nd_device_unlock(dev);
262246
263247 return rc;
264248 }
....@@ -267,7 +251,10 @@
267251 static ssize_t supported_alignments_show(struct device *dev,
268252 struct device_attribute *attr, char *buf)
269253 {
270
- return nd_size_select_show(0, nd_pfn_supported_alignments(), buf);
254
+ unsigned long aligns[MAX_NVDIMM_ALIGN] = { [0] = 0, };
255
+
256
+ return nd_size_select_show(0,
257
+ nd_pfn_supported_alignments(aligns), buf);
271258 }
272259 static DEVICE_ATTR_RO(supported_alignments);
273260
....@@ -282,24 +269,28 @@
282269 NULL,
283270 };
284271
285
-static umode_t pfn_visible(struct kobject *kobj, struct attribute *a, int n)
286
-{
287
- if (a == &dev_attr_resource.attr)
288
- return 0400;
289
- return a->mode;
290
-}
291
-
292
-struct attribute_group nd_pfn_attribute_group = {
272
+static struct attribute_group nd_pfn_attribute_group = {
293273 .attrs = nd_pfn_attributes,
294
- .is_visible = pfn_visible,
295274 };
296275
297
-static const struct attribute_group *nd_pfn_attribute_groups[] = {
276
+const struct attribute_group *nd_pfn_attribute_groups[] = {
298277 &nd_pfn_attribute_group,
299278 &nd_device_attribute_group,
300279 &nd_numa_attribute_group,
301280 NULL,
302281 };
282
+
283
+static const struct device_type nd_pfn_device_type = {
284
+ .name = "nd_pfn",
285
+ .release = nd_pfn_release,
286
+ .groups = nd_pfn_attribute_groups,
287
+};
288
+
289
+bool is_nd_pfn(struct device *dev)
290
+{
291
+ return dev ? dev->type == &nd_pfn_device_type : false;
292
+}
293
+EXPORT_SYMBOL(is_nd_pfn);
303294
304295 struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
305296 struct nd_namespace_common *ndns)
....@@ -310,7 +301,7 @@
310301 return NULL;
311302
312303 nd_pfn->mode = PFN_MODE_NONE;
313
- nd_pfn->align = PFN_DEFAULT_ALIGNMENT;
304
+ nd_pfn->align = nd_pfn_default_alignment();
314305 dev = &nd_pfn->dev;
315306 device_initialize(&nd_pfn->dev);
316307 if (ndns && !__nd_attach_ndns(&nd_pfn->dev, ndns, &nd_pfn->ndns)) {
....@@ -339,7 +330,6 @@
339330
340331 dev = &nd_pfn->dev;
341332 dev_set_name(dev, "pfn%d.%d", nd_region->id, nd_pfn->id);
342
- dev->groups = nd_pfn_attribute_groups;
343333 dev->type = &nd_pfn_device_type;
344334 dev->parent = &nd_region->dev;
345335
....@@ -361,6 +351,89 @@
361351 return dev;
362352 }
363353
354
+/*
355
+ * nd_pfn_clear_memmap_errors() clears any errors in the volatile memmap
356
+ * space associated with the namespace. If the memmap is set to DRAM, then
357
+ * this is a no-op. Since the memmap area is freshly initialized during
358
+ * probe, we have an opportunity to clear any badblocks in this area.
359
+ */
360
+static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn)
361
+{
362
+ struct nd_region *nd_region = to_nd_region(nd_pfn->dev.parent);
363
+ struct nd_namespace_common *ndns = nd_pfn->ndns;
364
+ void *zero_page = page_address(ZERO_PAGE(0));
365
+ struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
366
+ int num_bad, meta_num, rc, bb_present;
367
+ sector_t first_bad, meta_start;
368
+ struct nd_namespace_io *nsio;
369
+
370
+ if (nd_pfn->mode != PFN_MODE_PMEM)
371
+ return 0;
372
+
373
+ nsio = to_nd_namespace_io(&ndns->dev);
374
+ meta_start = (SZ_4K + sizeof(*pfn_sb)) >> 9;
375
+ meta_num = (le64_to_cpu(pfn_sb->dataoff) >> 9) - meta_start;
376
+
377
+ /*
378
+ * re-enable the namespace with correct size so that we can access
379
+ * the device memmap area.
380
+ */
381
+ devm_namespace_disable(&nd_pfn->dev, ndns);
382
+ rc = devm_namespace_enable(&nd_pfn->dev, ndns, le64_to_cpu(pfn_sb->dataoff));
383
+ if (rc)
384
+ return rc;
385
+
386
+ do {
387
+ unsigned long zero_len;
388
+ u64 nsoff;
389
+
390
+ bb_present = badblocks_check(&nd_region->bb, meta_start,
391
+ meta_num, &first_bad, &num_bad);
392
+ if (bb_present) {
393
+ dev_dbg(&nd_pfn->dev, "meta: %x badblocks at %llx\n",
394
+ num_bad, first_bad);
395
+ nsoff = ALIGN_DOWN((nd_region->ndr_start
396
+ + (first_bad << 9)) - nsio->res.start,
397
+ PAGE_SIZE);
398
+ zero_len = ALIGN(num_bad << 9, PAGE_SIZE);
399
+ while (zero_len) {
400
+ unsigned long chunk = min(zero_len, PAGE_SIZE);
401
+
402
+ rc = nvdimm_write_bytes(ndns, nsoff, zero_page,
403
+ chunk, 0);
404
+ if (rc)
405
+ break;
406
+
407
+ zero_len -= chunk;
408
+ nsoff += chunk;
409
+ }
410
+ if (rc) {
411
+ dev_err(&nd_pfn->dev,
412
+ "error clearing %x badblocks at %llx\n",
413
+ num_bad, first_bad);
414
+ return rc;
415
+ }
416
+ }
417
+ } while (bb_present);
418
+
419
+ return 0;
420
+}
421
+
422
+static bool nd_supported_alignment(unsigned long align)
423
+{
424
+ int i;
425
+ unsigned long supported[MAX_NVDIMM_ALIGN] = { [0] = 0, };
426
+
427
+ if (align == 0)
428
+ return false;
429
+
430
+ nd_pfn_supported_alignments(supported);
431
+ for (i = 0; supported[i]; i++)
432
+ if (align == supported[i])
433
+ return true;
434
+ return false;
435
+}
436
+
364437 /**
365438 * nd_pfn_validate - read and validate info-block
366439 * @nd_pfn: fsdax namespace runtime state / properties
....@@ -373,6 +446,7 @@
373446 int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
374447 {
375448 u64 checksum, offset;
449
+ struct resource *res;
376450 enum nd_pfn_mode mode;
377451 struct nd_namespace_io *nsio;
378452 unsigned long align, start_pad;
....@@ -409,6 +483,11 @@
409483 if (__le16_to_cpu(pfn_sb->version_minor) < 2)
410484 pfn_sb->align = 0;
411485
486
+ if (__le16_to_cpu(pfn_sb->version_minor) < 4) {
487
+ pfn_sb->page_struct_size = cpu_to_le16(64);
488
+ pfn_sb->page_size = cpu_to_le32(PAGE_SIZE);
489
+ }
490
+
412491 switch (le32_to_cpu(pfn_sb->mode)) {
413492 case PFN_MODE_RAM:
414493 case PFN_MODE_PMEM:
....@@ -423,6 +502,34 @@
423502 if (align == 0)
424503 align = 1UL << ilog2(offset);
425504 mode = le32_to_cpu(pfn_sb->mode);
505
+
506
+ if ((le32_to_cpu(pfn_sb->page_size) > PAGE_SIZE) &&
507
+ (mode == PFN_MODE_PMEM)) {
508
+ dev_err(&nd_pfn->dev,
509
+ "init failed, page size mismatch %d\n",
510
+ le32_to_cpu(pfn_sb->page_size));
511
+ return -EOPNOTSUPP;
512
+ }
513
+
514
+ if ((le16_to_cpu(pfn_sb->page_struct_size) < sizeof(struct page)) &&
515
+ (mode == PFN_MODE_PMEM)) {
516
+ dev_err(&nd_pfn->dev,
517
+ "init failed, struct page size mismatch %d\n",
518
+ le16_to_cpu(pfn_sb->page_struct_size));
519
+ return -EOPNOTSUPP;
520
+ }
521
+
522
+ /*
523
+ * Check whether the we support the alignment. For Dax if the
524
+ * superblock alignment is not matching, we won't initialize
525
+ * the device.
526
+ */
527
+ if (!nd_supported_alignment(align) &&
528
+ !memcmp(pfn_sb->signature, DAX_SIG, PFN_SIG_LEN)) {
529
+ dev_err(&nd_pfn->dev, "init failed, alignment mismatch: "
530
+ "%ld:%ld\n", nd_pfn->align, align);
531
+ return -EOPNOTSUPP;
532
+ }
426533
427534 if (!nd_pfn->uuid) {
428535 /*
....@@ -455,14 +562,14 @@
455562 dev_dbg(&nd_pfn->dev, "align: %lx:%lx mode: %d:%d\n",
456563 nd_pfn->align, align, nd_pfn->mode,
457564 mode);
458
- return -EINVAL;
565
+ return -EOPNOTSUPP;
459566 }
460567 }
461568
462569 if (align > nvdimm_namespace_capacity(ndns)) {
463570 dev_err(&nd_pfn->dev, "alignment: %lx exceeds capacity %llx\n",
464571 align, nvdimm_namespace_capacity(ndns));
465
- return -EINVAL;
572
+ return -EOPNOTSUPP;
466573 }
467574
468575 /*
....@@ -472,18 +579,31 @@
472579 * established.
473580 */
474581 nsio = to_nd_namespace_io(&ndns->dev);
475
- if (offset >= resource_size(&nsio->res)) {
582
+ res = &nsio->res;
583
+ if (offset >= resource_size(res)) {
476584 dev_err(&nd_pfn->dev, "pfn array size exceeds capacity of %s\n",
477585 dev_name(&ndns->dev));
478
- return -EBUSY;
586
+ return -EOPNOTSUPP;
479587 }
480588
481
- if ((align && !IS_ALIGNED(nsio->res.start + offset + start_pad, align))
589
+ if ((align && !IS_ALIGNED(res->start + offset + start_pad, align))
482590 || !IS_ALIGNED(offset, PAGE_SIZE)) {
483591 dev_err(&nd_pfn->dev,
484592 "bad offset: %#llx dax disabled align: %#lx\n",
485593 offset, align);
486
- return -ENXIO;
594
+ return -EOPNOTSUPP;
595
+ }
596
+
597
+ if (!IS_ALIGNED(res->start + le32_to_cpu(pfn_sb->start_pad),
598
+ memremap_compat_align())) {
599
+ dev_err(&nd_pfn->dev, "resource start misaligned\n");
600
+ return -EOPNOTSUPP;
601
+ }
602
+
603
+ if (!IS_ALIGNED(res->end + 1 - le32_to_cpu(pfn_sb->end_trunc),
604
+ memremap_compat_align())) {
605
+ dev_err(&nd_pfn->dev, "resource end misaligned\n");
606
+ return -EOPNOTSUPP;
487607 }
488608
489609 return 0;
....@@ -531,117 +651,79 @@
531651 EXPORT_SYMBOL(nd_pfn_probe);
532652
533653 /*
534
- * We hotplug memory at section granularity, pad the reserved area from
535
- * the previous section base to the namespace base address.
654
+ * We hotplug memory at sub-section granularity, pad the reserved area
655
+ * from the previous section base to the namespace base address.
536656 */
537657 static unsigned long init_altmap_base(resource_size_t base)
538658 {
539659 unsigned long base_pfn = PHYS_PFN(base);
540660
541
- return PFN_SECTION_ALIGN_DOWN(base_pfn);
661
+ return SUBSECTION_ALIGN_DOWN(base_pfn);
542662 }
543663
544664 static unsigned long init_altmap_reserve(resource_size_t base)
545665 {
546
- unsigned long reserve = PFN_UP(SZ_8K);
666
+ unsigned long reserve = nd_info_block_reserve() >> PAGE_SHIFT;
547667 unsigned long base_pfn = PHYS_PFN(base);
548668
549
- reserve += base_pfn - PFN_SECTION_ALIGN_DOWN(base_pfn);
669
+ reserve += base_pfn - SUBSECTION_ALIGN_DOWN(base_pfn);
550670 return reserve;
551671 }
552672
553673 static int __nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap)
554674 {
555
- struct resource *res = &pgmap->res;
675
+ struct range *range = &pgmap->range;
556676 struct vmem_altmap *altmap = &pgmap->altmap;
557677 struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
558678 u64 offset = le64_to_cpu(pfn_sb->dataoff);
559679 u32 start_pad = __le32_to_cpu(pfn_sb->start_pad);
560680 u32 end_trunc = __le32_to_cpu(pfn_sb->end_trunc);
681
+ u32 reserve = nd_info_block_reserve();
561682 struct nd_namespace_common *ndns = nd_pfn->ndns;
562683 struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
563684 resource_size_t base = nsio->res.start + start_pad;
685
+ resource_size_t end = nsio->res.end - end_trunc;
564686 struct vmem_altmap __altmap = {
565687 .base_pfn = init_altmap_base(base),
566688 .reserve = init_altmap_reserve(base),
689
+ .end_pfn = PHYS_PFN(end),
567690 };
568691
569
- memcpy(res, &nsio->res, sizeof(*res));
570
- res->start += start_pad;
571
- res->end -= end_trunc;
572
-
692
+ *range = (struct range) {
693
+ .start = nsio->res.start + start_pad,
694
+ .end = nsio->res.end - end_trunc,
695
+ };
696
+ pgmap->nr_range = 1;
573697 if (nd_pfn->mode == PFN_MODE_RAM) {
574
- if (offset < SZ_8K)
698
+ if (offset < reserve)
575699 return -EINVAL;
576700 nd_pfn->npfns = le64_to_cpu(pfn_sb->npfns);
577
- pgmap->altmap_valid = false;
578701 } else if (nd_pfn->mode == PFN_MODE_PMEM) {
579
- nd_pfn->npfns = PFN_SECTION_ALIGN_UP((resource_size(res)
580
- - offset) / PAGE_SIZE);
702
+ nd_pfn->npfns = PHYS_PFN((range_len(range) - offset));
581703 if (le64_to_cpu(nd_pfn->pfn_sb->npfns) > nd_pfn->npfns)
582704 dev_info(&nd_pfn->dev,
583705 "number of pfns truncated from %lld to %ld\n",
584706 le64_to_cpu(nd_pfn->pfn_sb->npfns),
585707 nd_pfn->npfns);
586708 memcpy(altmap, &__altmap, sizeof(*altmap));
587
- altmap->free = PHYS_PFN(offset - SZ_8K);
709
+ altmap->free = PHYS_PFN(offset - reserve);
588710 altmap->alloc = 0;
589
- pgmap->altmap_valid = true;
711
+ pgmap->flags |= PGMAP_ALTMAP_VALID;
590712 } else
591713 return -ENXIO;
592714
593715 return 0;
594716 }
595717
596
-static u64 phys_pmem_align_down(struct nd_pfn *nd_pfn, u64 phys)
597
-{
598
- return min_t(u64, PHYS_SECTION_ALIGN_DOWN(phys),
599
- ALIGN_DOWN(phys, nd_pfn->align));
600
-}
601
-
602
-/*
603
- * Check if pmem collides with 'System RAM', or other regions when
604
- * section aligned. Trim it accordingly.
605
- */
606
-static void trim_pfn_device(struct nd_pfn *nd_pfn, u32 *start_pad, u32 *end_trunc)
607
-{
608
- struct nd_namespace_common *ndns = nd_pfn->ndns;
609
- struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
610
- struct nd_region *nd_region = to_nd_region(nd_pfn->dev.parent);
611
- const resource_size_t start = nsio->res.start;
612
- const resource_size_t end = start + resource_size(&nsio->res);
613
- resource_size_t adjust, size;
614
-
615
- *start_pad = 0;
616
- *end_trunc = 0;
617
-
618
- adjust = start - PHYS_SECTION_ALIGN_DOWN(start);
619
- size = resource_size(&nsio->res) + adjust;
620
- if (region_intersects(start - adjust, size, IORESOURCE_SYSTEM_RAM,
621
- IORES_DESC_NONE) == REGION_MIXED
622
- || nd_region_conflict(nd_region, start - adjust, size))
623
- *start_pad = PHYS_SECTION_ALIGN_UP(start) - start;
624
-
625
- /* Now check that end of the range does not collide. */
626
- adjust = PHYS_SECTION_ALIGN_UP(end) - end;
627
- size = resource_size(&nsio->res) + adjust;
628
- if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM,
629
- IORES_DESC_NONE) == REGION_MIXED
630
- || !IS_ALIGNED(end, nd_pfn->align)
631
- || nd_region_conflict(nd_region, start, size))
632
- *end_trunc = end - phys_pmem_align_down(nd_pfn, end);
633
-}
634
-
635718 static int nd_pfn_init(struct nd_pfn *nd_pfn)
636719 {
637
- u32 dax_label_reserve = is_nd_dax(&nd_pfn->dev) ? SZ_128K : 0;
638720 struct nd_namespace_common *ndns = nd_pfn->ndns;
639721 struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
640722 resource_size_t start, size;
641723 struct nd_region *nd_region;
642
- u32 start_pad, end_trunc;
724
+ unsigned long npfns, align;
725
+ u32 end_trunc;
643726 struct nd_pfn_sb *pfn_sb;
644
- unsigned long npfns;
645727 phys_addr_t offset;
646728 const char *sig;
647729 u64 checksum;
....@@ -658,6 +740,8 @@
658740 sig = PFN_SIG;
659741
660742 rc = nd_pfn_validate(nd_pfn, sig);
743
+ if (rc == 0)
744
+ return nd_pfn_clear_memmap_errors(nd_pfn);
661745 if (rc != -ENODEV)
662746 return rc;
663747
....@@ -672,44 +756,56 @@
672756 return -ENXIO;
673757 }
674758
675
- memset(pfn_sb, 0, sizeof(*pfn_sb));
676
-
677
- trim_pfn_device(nd_pfn, &start_pad, &end_trunc);
678
- if (start_pad + end_trunc)
679
- dev_info(&nd_pfn->dev, "%s alignment collision, truncate %d bytes\n",
680
- dev_name(&ndns->dev), start_pad + end_trunc);
681
-
682759 /*
683760 * Note, we use 64 here for the standard size of struct page,
684761 * debugging options may cause it to be larger in which case the
685762 * implementation will limit the pfns advertised through
686763 * ->direct_access() to those that are included in the memmap.
687764 */
688
- start = nsio->res.start + start_pad;
765
+ start = nsio->res.start;
689766 size = resource_size(&nsio->res);
690
- npfns = PFN_SECTION_ALIGN_UP((size - start_pad - end_trunc - SZ_8K)
691
- / PAGE_SIZE);
767
+ npfns = PHYS_PFN(size - SZ_8K);
768
+ align = max(nd_pfn->align, memremap_compat_align());
769
+
770
+ /*
771
+ * When @start is misaligned fail namespace creation. See
772
+ * the 'struct nd_pfn_sb' commentary on why ->start_pad is not
773
+ * an option.
774
+ */
775
+ if (!IS_ALIGNED(start, memremap_compat_align())) {
776
+ dev_err(&nd_pfn->dev, "%s: start %pa misaligned to %#lx\n",
777
+ dev_name(&ndns->dev), &start,
778
+ memremap_compat_align());
779
+ return -EINVAL;
780
+ }
781
+ end_trunc = start + size - ALIGN_DOWN(start + size, align);
692782 if (nd_pfn->mode == PFN_MODE_PMEM) {
693783 /*
694784 * The altmap should be padded out to the block size used
695785 * when populating the vmemmap. This *should* be equal to
696786 * PMD_SIZE for most architectures.
787
+ *
788
+ * Also make sure size of struct page is less than 64. We
789
+ * want to make sure we use large enough size here so that
790
+ * we don't have a dynamic reserve space depending on
791
+ * struct page size. But we also want to make sure we notice
792
+ * when we end up adding new elements to struct page.
697793 */
698
- offset = ALIGN(start + SZ_8K + 64 * npfns + dax_label_reserve,
699
- max(nd_pfn->align, PMD_SIZE)) - start;
794
+ BUILD_BUG_ON(sizeof(struct page) > MAX_STRUCT_PAGE_SIZE);
795
+ offset = ALIGN(start + SZ_8K + MAX_STRUCT_PAGE_SIZE * npfns, align)
796
+ - start;
700797 } else if (nd_pfn->mode == PFN_MODE_RAM)
701
- offset = ALIGN(start + SZ_8K + dax_label_reserve,
702
- nd_pfn->align) - start;
798
+ offset = ALIGN(start + SZ_8K, align) - start;
703799 else
704800 return -ENXIO;
705801
706
- if (offset + start_pad + end_trunc >= size) {
802
+ if (offset >= size) {
707803 dev_err(&nd_pfn->dev, "%s unable to satisfy requested alignment\n",
708804 dev_name(&ndns->dev));
709805 return -ENXIO;
710806 }
711807
712
- npfns = (size - offset - start_pad - end_trunc) / SZ_4K;
808
+ npfns = PHYS_PFN(size - offset - end_trunc);
713809 pfn_sb->mode = cpu_to_le32(nd_pfn->mode);
714810 pfn_sb->dataoff = cpu_to_le64(offset);
715811 pfn_sb->npfns = cpu_to_le64(npfns);
....@@ -717,13 +813,18 @@
717813 memcpy(pfn_sb->uuid, nd_pfn->uuid, 16);
718814 memcpy(pfn_sb->parent_uuid, nd_dev_to_uuid(&ndns->dev), 16);
719815 pfn_sb->version_major = cpu_to_le16(1);
720
- pfn_sb->version_minor = cpu_to_le16(3);
721
- pfn_sb->start_pad = cpu_to_le32(start_pad);
816
+ pfn_sb->version_minor = cpu_to_le16(4);
722817 pfn_sb->end_trunc = cpu_to_le32(end_trunc);
723818 pfn_sb->align = cpu_to_le32(nd_pfn->align);
819
+ pfn_sb->page_struct_size = cpu_to_le16(MAX_STRUCT_PAGE_SIZE);
820
+ pfn_sb->page_size = cpu_to_le32(PAGE_SIZE);
724821 checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb);
725822 pfn_sb->checksum = cpu_to_le64(checksum);
726823
824
+ rc = nd_pfn_clear_memmap_errors(nd_pfn);
825
+ if (rc)
826
+ return rc;
827
+
727828 return nvdimm_write_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb), 0);
728829 }
729830