Skip to content

Commit 451fed2

Browse files
committed
Merge branch 'for-5.1/libnvdimm' into libnvdimm-for-next
Merge miscellaneous libnvdimm sub-system updates for v5.1. Highlights include: * Support for the Hyper-V family of device-specific-methods (DSMs) * Several fixes and workarounds for Hyper-V compatibility. * Fix for the support to cache the dirty-shutdown-count at init.
2 parents ebe9f6f + 075c3fd commit 451fed2

File tree

13 files changed

+158
-59
lines changed

13 files changed

+158
-59
lines changed

MAINTAINERS

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4536,20 +4536,21 @@ S: Maintained
45364536
F: drivers/i2c/busses/i2c-diolan-u2c.c
45374537

45384538
FILESYSTEM DIRECT ACCESS (DAX)
4539-
M: Matthew Wilcox <willy@infradead.org>
4540-
M: Ross Zwisler <zwisler@kernel.org>
4541-
M: Jan Kara <jack@suse.cz>
4539+
M: Dan Williams <dan.j.williams@intel.com>
4540+
R: Matthew Wilcox <willy@infradead.org>
4541+
R: Jan Kara <jack@suse.cz>
45424542
L: linux-fsdevel@vger.kernel.org
4543+
L: linux-nvdimm@lists.01.org
45434544
S: Supported
45444545
F: fs/dax.c
45454546
F: include/linux/dax.h
45464547
F: include/trace/events/fs_dax.h
45474548

45484549
DEVICE DIRECT ACCESS (DAX)
45494550
M: Dan Williams <dan.j.williams@intel.com>
4550-
M: Dave Jiang <dave.jiang@intel.com>
4551-
M: Ross Zwisler <zwisler@kernel.org>
45524551
M: Vishal Verma <vishal.l.verma@intel.com>
4552+
M: Keith Busch <keith.busch@intel.com>
4553+
M: Dave Jiang <dave.jiang@intel.com>
45534554
L: linux-nvdimm@lists.01.org
45544555
S: Supported
45554556
F: drivers/dax/
@@ -8643,7 +8644,6 @@ S: Maintained
86438644
F: tools/lib/lockdep/
86448645

86458646
LIBNVDIMM BLK: MMIO-APERTURE DRIVER
8646-
M: Ross Zwisler <zwisler@kernel.org>
86478647
M: Dan Williams <dan.j.williams@intel.com>
86488648
M: Vishal Verma <vishal.l.verma@intel.com>
86498649
M: Dave Jiang <dave.jiang@intel.com>
@@ -8656,15 +8656,13 @@ F: drivers/nvdimm/region_devs.c
86568656
LIBNVDIMM BTT: BLOCK TRANSLATION TABLE
86578657
M: Vishal Verma <vishal.l.verma@intel.com>
86588658
M: Dan Williams <dan.j.williams@intel.com>
8659-
M: Ross Zwisler <zwisler@kernel.org>
86608659
M: Dave Jiang <dave.jiang@intel.com>
86618660
L: linux-nvdimm@lists.01.org
86628661
Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
86638662
S: Supported
86648663
F: drivers/nvdimm/btt*
86658664

86668665
LIBNVDIMM PMEM: PERSISTENT MEMORY DRIVER
8667-
M: Ross Zwisler <zwisler@kernel.org>
86688666
M: Dan Williams <dan.j.williams@intel.com>
86698667
M: Vishal Verma <vishal.l.verma@intel.com>
86708668
M: Dave Jiang <dave.jiang@intel.com>
@@ -8683,9 +8681,10 @@ F: Documentation/devicetree/bindings/pmem/pmem-region.txt
86838681

86848682
LIBNVDIMM: NON-VOLATILE MEMORY DEVICE SUBSYSTEM
86858683
M: Dan Williams <dan.j.williams@intel.com>
8686-
M: Ross Zwisler <zwisler@kernel.org>
86878684
M: Vishal Verma <vishal.l.verma@intel.com>
86888685
M: Dave Jiang <dave.jiang@intel.com>
8686+
M: Keith Busch <keith.busch@intel.com>
8687+
M: Ira Weiny <ira.weiny@intel.com>
86898688
L: linux-nvdimm@lists.01.org
86908689
Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
86918690
T: git git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git

drivers/acpi/nfit/core.c

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ static bool no_init_ars;
5555
module_param(no_init_ars, bool, 0644);
5656
MODULE_PARM_DESC(no_init_ars, "Skip ARS run at nfit init time");
5757

58+
static bool force_labels;
59+
module_param(force_labels, bool, 0444);
60+
MODULE_PARM_DESC(force_labels, "Opt-in to labels despite missing methods");
61+
5862
LIST_HEAD(acpi_descs);
5963
DEFINE_MUTEX(acpi_desc_lock);
6064

@@ -556,6 +560,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
556560
return -EINVAL;
557561
}
558562

563+
if (out_obj->type != ACPI_TYPE_BUFFER) {
564+
dev_dbg(dev, "%s unexpected output object type cmd: %s type: %d\n",
565+
dimm_name, cmd_name, out_obj->type);
566+
rc = -EINVAL;
567+
goto out;
568+
}
569+
559570
if (call_pkg) {
560571
call_pkg->nd_fw_size = out_obj->buffer.length;
561572
memcpy(call_pkg->nd_payload + call_pkg->nd_size_in,
@@ -574,13 +585,6 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
574585
return 0;
575586
}
576587

577-
if (out_obj->package.type != ACPI_TYPE_BUFFER) {
578-
dev_dbg(dev, "%s unexpected output object type cmd: %s type: %d\n",
579-
dimm_name, cmd_name, out_obj->type);
580-
rc = -EINVAL;
581-
goto out;
582-
}
583-
584588
dev_dbg(dev, "%s cmd: %s output length: %d\n", dimm_name,
585589
cmd_name, out_obj->buffer.length);
586590
print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4, 4,
@@ -1761,14 +1765,14 @@ static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
17611765

17621766
__weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
17631767
{
1768+
struct device *dev = &nfit_mem->adev->dev;
17641769
struct nd_intel_smart smart = { 0 };
17651770
union acpi_object in_buf = {
1766-
.type = ACPI_TYPE_BUFFER,
1767-
.buffer.pointer = (char *) &smart,
1768-
.buffer.length = sizeof(smart),
1771+
.buffer.type = ACPI_TYPE_BUFFER,
1772+
.buffer.length = 0,
17691773
};
17701774
union acpi_object in_obj = {
1771-
.type = ACPI_TYPE_PACKAGE,
1775+
.package.type = ACPI_TYPE_PACKAGE,
17721776
.package.count = 1,
17731777
.package.elements = &in_buf,
17741778
};
@@ -1783,8 +1787,15 @@ __weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
17831787
return;
17841788

17851789
out_obj = acpi_evaluate_dsm(handle, guid, revid, func, &in_obj);
1786-
if (!out_obj)
1790+
if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER
1791+
|| out_obj->buffer.length < sizeof(smart)) {
1792+
dev_dbg(dev->parent, "%s: failed to retrieve initial health\n",
1793+
dev_name(dev));
1794+
ACPI_FREE(out_obj);
17871795
return;
1796+
}
1797+
memcpy(&smart, out_obj->buffer.pointer, sizeof(smart));
1798+
ACPI_FREE(out_obj);
17881799

17891800
if (smart.flags & ND_INTEL_SMART_SHUTDOWN_VALID) {
17901801
if (smart.shutdown_state)
@@ -1795,7 +1806,6 @@ __weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
17951806
set_bit(NFIT_MEM_DIRTY_COUNT, &nfit_mem->flags);
17961807
nfit_mem->dirty_shutdown = smart.shutdown_count;
17971808
}
1798-
ACPI_FREE(out_obj);
17991809
}
18001810

18011811
static void populate_shutdown_status(struct nfit_mem *nfit_mem)
@@ -1863,9 +1873,17 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
18631873
dev_set_drvdata(&adev_dimm->dev, nfit_mem);
18641874

18651875
/*
1866-
* Until standardization materializes we need to consider 4
1867-
* different command sets. Note, that checking for function0 (bit0)
1868-
* tells us if any commands are reachable through this GUID.
1876+
* There are 4 "legacy" NVDIMM command sets
1877+
* (NVDIMM_FAMILY_{INTEL,MSFT,HPE1,HPE2}) that were created before
1878+
* an EFI working group was established to constrain this
1879+
* proliferation. The nfit driver probes for the supported command
1880+
* set by GUID. Note, if you're a platform developer looking to add
1881+
* a new command set to this probe, consider using an existing set,
1882+
* or otherwise seek approval to publish the command set at
1883+
* http://www.uefi.org/RFIC_LIST.
1884+
*
1885+
* Note, that checking for function0 (bit0) tells us if any commands
1886+
* are reachable through this GUID.
18691887
*/
18701888
for (i = 0; i <= NVDIMM_FAMILY_MAX; i++)
18711889
if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 1))
@@ -1888,6 +1906,8 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
18881906
dsm_mask &= ~(1 << 8);
18891907
} else if (nfit_mem->family == NVDIMM_FAMILY_MSFT) {
18901908
dsm_mask = 0xffffffff;
1909+
} else if (nfit_mem->family == NVDIMM_FAMILY_HYPERV) {
1910+
dsm_mask = 0x1f;
18911911
} else {
18921912
dev_dbg(dev, "unknown dimm command family\n");
18931913
nfit_mem->family = -1;
@@ -1917,18 +1937,32 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
19171937
| 1 << ND_CMD_SET_CONFIG_DATA;
19181938
if (family == NVDIMM_FAMILY_INTEL
19191939
&& (dsm_mask & label_mask) == label_mask)
1920-
return 0;
1940+
/* skip _LS{I,R,W} enabling */;
1941+
else {
1942+
if (acpi_nvdimm_has_method(adev_dimm, "_LSI")
1943+
&& acpi_nvdimm_has_method(adev_dimm, "_LSR")) {
1944+
dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev));
1945+
set_bit(NFIT_MEM_LSR, &nfit_mem->flags);
1946+
}
19211947

1922-
if (acpi_nvdimm_has_method(adev_dimm, "_LSI")
1923-
&& acpi_nvdimm_has_method(adev_dimm, "_LSR")) {
1924-
dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev));
1925-
set_bit(NFIT_MEM_LSR, &nfit_mem->flags);
1926-
}
1948+
if (test_bit(NFIT_MEM_LSR, &nfit_mem->flags)
1949+
&& acpi_nvdimm_has_method(adev_dimm, "_LSW")) {
1950+
dev_dbg(dev, "%s: has _LSW\n", dev_name(&adev_dimm->dev));
1951+
set_bit(NFIT_MEM_LSW, &nfit_mem->flags);
1952+
}
19271953

1928-
if (test_bit(NFIT_MEM_LSR, &nfit_mem->flags)
1929-
&& acpi_nvdimm_has_method(adev_dimm, "_LSW")) {
1930-
dev_dbg(dev, "%s: has _LSW\n", dev_name(&adev_dimm->dev));
1931-
set_bit(NFIT_MEM_LSW, &nfit_mem->flags);
1954+
/*
1955+
* Quirk read-only label configurations to preserve
1956+
* access to label-less namespaces by default.
1957+
*/
1958+
if (!test_bit(NFIT_MEM_LSW, &nfit_mem->flags)
1959+
&& !force_labels) {
1960+
dev_dbg(dev, "%s: No _LSW, disable labels\n",
1961+
dev_name(&adev_dimm->dev));
1962+
clear_bit(NFIT_MEM_LSR, &nfit_mem->flags);
1963+
} else
1964+
dev_dbg(dev, "%s: Force enable labels\n",
1965+
dev_name(&adev_dimm->dev));
19321966
}
19331967

19341968
populate_shutdown_status(nfit_mem);
@@ -2029,6 +2063,10 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
20292063
cmd_mask |= nfit_mem->dsm_mask & NVDIMM_STANDARD_CMDMASK;
20302064
}
20312065

2066+
/* Quirk to ignore LOCAL for labels on HYPERV DIMMs */
2067+
if (nfit_mem->family == NVDIMM_FAMILY_HYPERV)
2068+
set_bit(NDD_NOBLK, &flags);
2069+
20322070
if (test_bit(NFIT_MEM_LSR, &nfit_mem->flags)) {
20332071
set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask);
20342072
set_bit(ND_CMD_GET_CONFIG_DATA, &cmd_mask);
@@ -2052,7 +2090,7 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
20522090
if ((mem_flags & ACPI_NFIT_MEM_FAILED_MASK) == 0)
20532091
continue;
20542092

2055-
dev_info(acpi_desc->dev, "%s flags:%s%s%s%s%s\n",
2093+
dev_err(acpi_desc->dev, "Error found in NVDIMM %s flags:%s%s%s%s%s\n",
20562094
nvdimm_name(nvdimm),
20572095
mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? " save_fail" : "",
20582096
mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? " restore_fail":"",
@@ -3731,6 +3769,7 @@ static __init int nfit_init(void)
37313769
guid_parse(UUID_NFIT_DIMM_N_HPE1, &nfit_uuid[NFIT_DEV_DIMM_N_HPE1]);
37323770
guid_parse(UUID_NFIT_DIMM_N_HPE2, &nfit_uuid[NFIT_DEV_DIMM_N_HPE2]);
37333771
guid_parse(UUID_NFIT_DIMM_N_MSFT, &nfit_uuid[NFIT_DEV_DIMM_N_MSFT]);
3772+
guid_parse(UUID_NFIT_DIMM_N_HYPERV, &nfit_uuid[NFIT_DEV_DIMM_N_HYPERV]);
37343773

37353774
nfit_wq = create_singlethread_workqueue("nfit");
37363775
if (!nfit_wq)

drivers/acpi/nfit/nfit.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,14 @@
3434
/* https://msdn.microsoft.com/library/windows/hardware/mt604741 */
3535
#define UUID_NFIT_DIMM_N_MSFT "1ee68b36-d4bd-4a1a-9a16-4f8e53d46e05"
3636

37+
/* http://www.uefi.org/RFIC_LIST (see "Virtual NVDIMM 0x1901") */
38+
#define UUID_NFIT_DIMM_N_HYPERV "5746c5f2-a9a2-4264-ad0e-e4ddc9e09e80"
39+
3740
#define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \
3841
| ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \
3942
| ACPI_NFIT_MEM_NOT_ARMED | ACPI_NFIT_MEM_MAP_FAILED)
4043

41-
#define NVDIMM_FAMILY_MAX NVDIMM_FAMILY_MSFT
44+
#define NVDIMM_FAMILY_MAX NVDIMM_FAMILY_HYPERV
4245

4346
#define NVDIMM_STANDARD_CMDMASK \
4447
(1 << ND_CMD_SMART | 1 << ND_CMD_SMART_THRESHOLD | 1 << ND_CMD_DIMM_FLAGS \
@@ -94,6 +97,7 @@ enum nfit_uuids {
9497
NFIT_DEV_DIMM_N_HPE1 = NVDIMM_FAMILY_HPE1,
9598
NFIT_DEV_DIMM_N_HPE2 = NVDIMM_FAMILY_HPE2,
9699
NFIT_DEV_DIMM_N_MSFT = NVDIMM_FAMILY_MSFT,
100+
NFIT_DEV_DIMM_N_HYPERV = NVDIMM_FAMILY_HYPERV,
97101
NFIT_SPA_VOLATILE,
98102
NFIT_SPA_PM,
99103
NFIT_SPA_DCR,

drivers/nvdimm/btt.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -541,51 +541,60 @@ static int arena_clear_freelist_error(struct arena_info *arena, u32 lane)
541541

542542
static int btt_freelist_init(struct arena_info *arena)
543543
{
544-
int old, new, ret;
545-
u32 i, map_entry;
546-
struct log_entry log_new, log_old;
544+
int new, ret;
545+
struct log_entry log_new;
546+
u32 i, map_entry, log_oldmap, log_newmap;
547547

548548
arena->freelist = kcalloc(arena->nfree, sizeof(struct free_entry),
549549
GFP_KERNEL);
550550
if (!arena->freelist)
551551
return -ENOMEM;
552552

553553
for (i = 0; i < arena->nfree; i++) {
554-
old = btt_log_read(arena, i, &log_old, LOG_OLD_ENT);
555-
if (old < 0)
556-
return old;
557-
558554
new = btt_log_read(arena, i, &log_new, LOG_NEW_ENT);
559555
if (new < 0)
560556
return new;
561557

558+
/* old and new map entries with any flags stripped out */
559+
log_oldmap = ent_lba(le32_to_cpu(log_new.old_map));
560+
log_newmap = ent_lba(le32_to_cpu(log_new.new_map));
561+
562562
/* sub points to the next one to be overwritten */
563563
arena->freelist[i].sub = 1 - new;
564564
arena->freelist[i].seq = nd_inc_seq(le32_to_cpu(log_new.seq));
565-
arena->freelist[i].block = le32_to_cpu(log_new.old_map);
565+
arena->freelist[i].block = log_oldmap;
566566

567567
/*
568568
* FIXME: if error clearing fails during init, we want to make
569569
* the BTT read-only
570570
*/
571-
if (ent_e_flag(log_new.old_map)) {
571+
if (ent_e_flag(log_new.old_map) &&
572+
!ent_normal(log_new.old_map)) {
573+
arena->freelist[i].has_err = 1;
572574
ret = arena_clear_freelist_error(arena, i);
573575
if (ret)
574576
dev_err_ratelimited(to_dev(arena),
575577
"Unable to clear known errors\n");
576578
}
577579

578580
/* This implies a newly created or untouched flog entry */
579-
if (log_new.old_map == log_new.new_map)
581+
if (log_oldmap == log_newmap)
580582
continue;
581583

582584
/* Check if map recovery is needed */
583585
ret = btt_map_read(arena, le32_to_cpu(log_new.lba), &map_entry,
584586
NULL, NULL, 0);
585587
if (ret)
586588
return ret;
587-
if ((le32_to_cpu(log_new.new_map) != map_entry) &&
588-
(le32_to_cpu(log_new.old_map) == map_entry)) {
589+
590+
/*
591+
* The map_entry from btt_read_map is stripped of any flag bits,
592+
* so use the stripped out versions from the log as well for
593+
* testing whether recovery is needed. For restoration, use the
594+
* 'raw' version of the log entries as that captured what we
595+
* were going to write originally.
596+
*/
597+
if ((log_newmap != map_entry) && (log_oldmap == map_entry)) {
589598
/*
590599
* Last transaction wrote the flog, but wasn't able
591600
* to complete the map write. So fix up the map.

drivers/nvdimm/btt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
#define ent_e_flag(ent) (!!(ent & MAP_ERR_MASK))
4545
#define ent_z_flag(ent) (!!(ent & MAP_TRIM_MASK))
4646
#define set_e_flag(ent) (ent |= MAP_ERR_MASK)
47+
/* 'normal' is both e and z flags set */
48+
#define ent_normal(ent) (ent_e_flag(ent) && ent_z_flag(ent))
4749

4850
enum btt_init_state {
4951
INIT_UNCHECKED = 0,

drivers/nvdimm/btt_devs.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,19 @@ static ssize_t size_show(struct device *dev,
159159
}
160160
static DEVICE_ATTR_RO(size);
161161

162+
static ssize_t log_zero_flags_show(struct device *dev,
163+
struct device_attribute *attr, char *buf)
164+
{
165+
return sprintf(buf, "Y\n");
166+
}
167+
static DEVICE_ATTR_RO(log_zero_flags);
168+
162169
static struct attribute *nd_btt_attributes[] = {
163170
&dev_attr_sector_size.attr,
164171
&dev_attr_namespace.attr,
165172
&dev_attr_uuid.attr,
166173
&dev_attr_size.attr,
174+
&dev_attr_log_zero_flags.attr,
167175
NULL,
168176
};
169177

0 commit comments

Comments
 (0)