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.
This commit is contained in:
@@ -55,6 +55,10 @@ static bool no_init_ars;
|
||||
module_param(no_init_ars, bool, 0644);
|
||||
MODULE_PARM_DESC(no_init_ars, "Skip ARS run at nfit init time");
|
||||
|
||||
static bool force_labels;
|
||||
module_param(force_labels, bool, 0444);
|
||||
MODULE_PARM_DESC(force_labels, "Opt-in to labels despite missing methods");
|
||||
|
||||
LIST_HEAD(acpi_descs);
|
||||
DEFINE_MUTEX(acpi_desc_lock);
|
||||
|
||||
@@ -556,6 +560,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (out_obj->type != ACPI_TYPE_BUFFER) {
|
||||
dev_dbg(dev, "%s unexpected output object type cmd: %s type: %d\n",
|
||||
dimm_name, cmd_name, out_obj->type);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (call_pkg) {
|
||||
call_pkg->nd_fw_size = out_obj->buffer.length;
|
||||
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,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (out_obj->package.type != ACPI_TYPE_BUFFER) {
|
||||
dev_dbg(dev, "%s unexpected output object type cmd: %s type: %d\n",
|
||||
dimm_name, cmd_name, out_obj->type);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%s cmd: %s output length: %d\n", dimm_name,
|
||||
cmd_name, out_obj->buffer.length);
|
||||
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)
|
||||
|
||||
__weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
|
||||
{
|
||||
struct device *dev = &nfit_mem->adev->dev;
|
||||
struct nd_intel_smart smart = { 0 };
|
||||
union acpi_object in_buf = {
|
||||
.type = ACPI_TYPE_BUFFER,
|
||||
.buffer.pointer = (char *) &smart,
|
||||
.buffer.length = sizeof(smart),
|
||||
.buffer.type = ACPI_TYPE_BUFFER,
|
||||
.buffer.length = 0,
|
||||
};
|
||||
union acpi_object in_obj = {
|
||||
.type = ACPI_TYPE_PACKAGE,
|
||||
.package.type = ACPI_TYPE_PACKAGE,
|
||||
.package.count = 1,
|
||||
.package.elements = &in_buf,
|
||||
};
|
||||
@@ -1783,8 +1787,15 @@ __weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
|
||||
return;
|
||||
|
||||
out_obj = acpi_evaluate_dsm(handle, guid, revid, func, &in_obj);
|
||||
if (!out_obj)
|
||||
if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER
|
||||
|| out_obj->buffer.length < sizeof(smart)) {
|
||||
dev_dbg(dev->parent, "%s: failed to retrieve initial health\n",
|
||||
dev_name(dev));
|
||||
ACPI_FREE(out_obj);
|
||||
return;
|
||||
}
|
||||
memcpy(&smart, out_obj->buffer.pointer, sizeof(smart));
|
||||
ACPI_FREE(out_obj);
|
||||
|
||||
if (smart.flags & ND_INTEL_SMART_SHUTDOWN_VALID) {
|
||||
if (smart.shutdown_state)
|
||||
@@ -1795,7 +1806,6 @@ __weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
|
||||
set_bit(NFIT_MEM_DIRTY_COUNT, &nfit_mem->flags);
|
||||
nfit_mem->dirty_shutdown = smart.shutdown_count;
|
||||
}
|
||||
ACPI_FREE(out_obj);
|
||||
}
|
||||
|
||||
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,
|
||||
dev_set_drvdata(&adev_dimm->dev, nfit_mem);
|
||||
|
||||
/*
|
||||
* Until standardization materializes we need to consider 4
|
||||
* different command sets. Note, that checking for function0 (bit0)
|
||||
* tells us if any commands are reachable through this GUID.
|
||||
* There are 4 "legacy" NVDIMM command sets
|
||||
* (NVDIMM_FAMILY_{INTEL,MSFT,HPE1,HPE2}) that were created before
|
||||
* an EFI working group was established to constrain this
|
||||
* proliferation. The nfit driver probes for the supported command
|
||||
* set by GUID. Note, if you're a platform developer looking to add
|
||||
* a new command set to this probe, consider using an existing set,
|
||||
* or otherwise seek approval to publish the command set at
|
||||
* http://www.uefi.org/RFIC_LIST.
|
||||
*
|
||||
* Note, that checking for function0 (bit0) tells us if any commands
|
||||
* are reachable through this GUID.
|
||||
*/
|
||||
for (i = 0; i <= NVDIMM_FAMILY_MAX; i++)
|
||||
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,
|
||||
dsm_mask &= ~(1 << 8);
|
||||
} else if (nfit_mem->family == NVDIMM_FAMILY_MSFT) {
|
||||
dsm_mask = 0xffffffff;
|
||||
} else if (nfit_mem->family == NVDIMM_FAMILY_HYPERV) {
|
||||
dsm_mask = 0x1f;
|
||||
} else {
|
||||
dev_dbg(dev, "unknown dimm command family\n");
|
||||
nfit_mem->family = -1;
|
||||
@@ -1917,18 +1937,32 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
|
||||
| 1 << ND_CMD_SET_CONFIG_DATA;
|
||||
if (family == NVDIMM_FAMILY_INTEL
|
||||
&& (dsm_mask & label_mask) == label_mask)
|
||||
return 0;
|
||||
/* skip _LS{I,R,W} enabling */;
|
||||
else {
|
||||
if (acpi_nvdimm_has_method(adev_dimm, "_LSI")
|
||||
&& acpi_nvdimm_has_method(adev_dimm, "_LSR")) {
|
||||
dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev));
|
||||
set_bit(NFIT_MEM_LSR, &nfit_mem->flags);
|
||||
}
|
||||
|
||||
if (acpi_nvdimm_has_method(adev_dimm, "_LSI")
|
||||
&& acpi_nvdimm_has_method(adev_dimm, "_LSR")) {
|
||||
dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev));
|
||||
set_bit(NFIT_MEM_LSR, &nfit_mem->flags);
|
||||
}
|
||||
if (test_bit(NFIT_MEM_LSR, &nfit_mem->flags)
|
||||
&& acpi_nvdimm_has_method(adev_dimm, "_LSW")) {
|
||||
dev_dbg(dev, "%s: has _LSW\n", dev_name(&adev_dimm->dev));
|
||||
set_bit(NFIT_MEM_LSW, &nfit_mem->flags);
|
||||
}
|
||||
|
||||
if (test_bit(NFIT_MEM_LSR, &nfit_mem->flags)
|
||||
&& acpi_nvdimm_has_method(adev_dimm, "_LSW")) {
|
||||
dev_dbg(dev, "%s: has _LSW\n", dev_name(&adev_dimm->dev));
|
||||
set_bit(NFIT_MEM_LSW, &nfit_mem->flags);
|
||||
/*
|
||||
* Quirk read-only label configurations to preserve
|
||||
* access to label-less namespaces by default.
|
||||
*/
|
||||
if (!test_bit(NFIT_MEM_LSW, &nfit_mem->flags)
|
||||
&& !force_labels) {
|
||||
dev_dbg(dev, "%s: No _LSW, disable labels\n",
|
||||
dev_name(&adev_dimm->dev));
|
||||
clear_bit(NFIT_MEM_LSR, &nfit_mem->flags);
|
||||
} else
|
||||
dev_dbg(dev, "%s: Force enable labels\n",
|
||||
dev_name(&adev_dimm->dev));
|
||||
}
|
||||
|
||||
populate_shutdown_status(nfit_mem);
|
||||
@@ -2029,6 +2063,10 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
|
||||
cmd_mask |= nfit_mem->dsm_mask & NVDIMM_STANDARD_CMDMASK;
|
||||
}
|
||||
|
||||
/* Quirk to ignore LOCAL for labels on HYPERV DIMMs */
|
||||
if (nfit_mem->family == NVDIMM_FAMILY_HYPERV)
|
||||
set_bit(NDD_NOBLK, &flags);
|
||||
|
||||
if (test_bit(NFIT_MEM_LSR, &nfit_mem->flags)) {
|
||||
set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask);
|
||||
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)
|
||||
if ((mem_flags & ACPI_NFIT_MEM_FAILED_MASK) == 0)
|
||||
continue;
|
||||
|
||||
dev_info(acpi_desc->dev, "%s flags:%s%s%s%s%s\n",
|
||||
dev_err(acpi_desc->dev, "Error found in NVDIMM %s flags:%s%s%s%s%s\n",
|
||||
nvdimm_name(nvdimm),
|
||||
mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? " save_fail" : "",
|
||||
mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? " restore_fail":"",
|
||||
@@ -3731,6 +3769,7 @@ static __init int nfit_init(void)
|
||||
guid_parse(UUID_NFIT_DIMM_N_HPE1, &nfit_uuid[NFIT_DEV_DIMM_N_HPE1]);
|
||||
guid_parse(UUID_NFIT_DIMM_N_HPE2, &nfit_uuid[NFIT_DEV_DIMM_N_HPE2]);
|
||||
guid_parse(UUID_NFIT_DIMM_N_MSFT, &nfit_uuid[NFIT_DEV_DIMM_N_MSFT]);
|
||||
guid_parse(UUID_NFIT_DIMM_N_HYPERV, &nfit_uuid[NFIT_DEV_DIMM_N_HYPERV]);
|
||||
|
||||
nfit_wq = create_singlethread_workqueue("nfit");
|
||||
if (!nfit_wq)
|
||||
|
@@ -34,11 +34,14 @@
|
||||
/* https://msdn.microsoft.com/library/windows/hardware/mt604741 */
|
||||
#define UUID_NFIT_DIMM_N_MSFT "1ee68b36-d4bd-4a1a-9a16-4f8e53d46e05"
|
||||
|
||||
/* http://www.uefi.org/RFIC_LIST (see "Virtual NVDIMM 0x1901") */
|
||||
#define UUID_NFIT_DIMM_N_HYPERV "5746c5f2-a9a2-4264-ad0e-e4ddc9e09e80"
|
||||
|
||||
#define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \
|
||||
| ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \
|
||||
| ACPI_NFIT_MEM_NOT_ARMED | ACPI_NFIT_MEM_MAP_FAILED)
|
||||
|
||||
#define NVDIMM_FAMILY_MAX NVDIMM_FAMILY_MSFT
|
||||
#define NVDIMM_FAMILY_MAX NVDIMM_FAMILY_HYPERV
|
||||
|
||||
#define NVDIMM_STANDARD_CMDMASK \
|
||||
(1 << ND_CMD_SMART | 1 << ND_CMD_SMART_THRESHOLD | 1 << ND_CMD_DIMM_FLAGS \
|
||||
@@ -94,6 +97,7 @@ enum nfit_uuids {
|
||||
NFIT_DEV_DIMM_N_HPE1 = NVDIMM_FAMILY_HPE1,
|
||||
NFIT_DEV_DIMM_N_HPE2 = NVDIMM_FAMILY_HPE2,
|
||||
NFIT_DEV_DIMM_N_MSFT = NVDIMM_FAMILY_MSFT,
|
||||
NFIT_DEV_DIMM_N_HYPERV = NVDIMM_FAMILY_HYPERV,
|
||||
NFIT_SPA_VOLATILE,
|
||||
NFIT_SPA_PM,
|
||||
NFIT_SPA_DCR,
|
||||
|
Reference in New Issue
Block a user