Skip to content

Commit a1facc1

Browse files
djbwstellarhopper
authored andcommitted
ACPI: NFIT: Add runtime firmware activate support
Plumb the platform specific backend for the generic libnvdimm firmware activate interface. Register dimm level operations to arm/disarm activation, and register bus level operations to report the dynamic platform-quiesce time relative to the number of dimms armed for firmware activation. A new nfit-specific bus attribute "firmware_activate_noidle" is added to allow the activation to switch between platform enforced, and OS opportunistic device quiesce. In other words, let the hibernate cycle handle in-flight device-dma rather than the platform attempting to increase PCI-E timeouts and the like. Cc: Dave Jiang <[email protected]> Cc: Ira Weiny <[email protected]> Cc: Vishal Verma <[email protected]> Signed-off-by: Dan Williams <[email protected]> Signed-off-by: Vishal Verma <[email protected]>
1 parent 48001ea commit a1facc1

File tree

7 files changed

+461
-7
lines changed

7 files changed

+461
-7
lines changed

Documentation/ABI/testing/sysfs-bus-nfit

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,25 @@ Description:
202202
functions. See the section named 'NVDIMM Root Device _DSMs' in
203203
the ACPI specification.
204204

205+
What: /sys/bus/nd/devices/ndbusX/nfit/firmware_activate_noidle
206+
Date: Apr, 2020
207+
KernelVersion: v5.8
208+
209+
Description:
210+
(RW) The Intel platform implementation of firmware activate
211+
support exposes an option let the platform force idle devices in
212+
the system over the activation event, or trust that the OS will
213+
do it. The safe default is to let the platform force idle
214+
devices since the kernel is already in a suspend state, and on
215+
the chance that a driver does not properly quiesce bus-mastering
216+
after a suspend callback the platform will handle it. However,
217+
the activation might abort if, for example, platform firmware
218+
determines that the activation time exceeds the max PCI-E
219+
completion timeout. Since the platform does not know whether the
220+
OS is running the activation from a suspend context it aborts,
221+
but if the system owner trusts driver suspend callback to be
222+
sufficient then 'firmware_activation_noidle' can be
223+
enabled to bypass the activation abort.
205224

206225
What: /sys/bus/nd/devices/regionX/nfit/range_index
207226
Date: Jun, 2015

drivers/acpi/nfit/core.c

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,8 +1392,12 @@ static umode_t nfit_visible(struct kobject *kobj, struct attribute *a, int n)
13921392
struct device *dev = container_of(kobj, struct device, kobj);
13931393
struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev);
13941394

1395-
if (a == &dev_attr_scrub.attr && !ars_supported(nvdimm_bus))
1396-
return 0;
1395+
if (a == &dev_attr_scrub.attr)
1396+
return ars_supported(nvdimm_bus) ? a->mode : 0;
1397+
1398+
if (a == &dev_attr_firmware_activate_noidle.attr)
1399+
return intel_fwa_supported(nvdimm_bus) ? a->mode : 0;
1400+
13971401
return a->mode;
13981402
}
13991403

@@ -1402,6 +1406,7 @@ static struct attribute *acpi_nfit_attributes[] = {
14021406
&dev_attr_scrub.attr,
14031407
&dev_attr_hw_error_scrub.attr,
14041408
&dev_attr_bus_dsm_mask.attr,
1409+
&dev_attr_firmware_activate_noidle.attr,
14051410
NULL,
14061411
};
14071412

@@ -2019,6 +2024,26 @@ static const struct nvdimm_security_ops *acpi_nfit_get_security_ops(int family)
20192024
}
20202025
}
20212026

2027+
static const struct nvdimm_fw_ops *acpi_nfit_get_fw_ops(
2028+
struct nfit_mem *nfit_mem)
2029+
{
2030+
unsigned long mask;
2031+
struct acpi_nfit_desc *acpi_desc = nfit_mem->acpi_desc;
2032+
struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
2033+
2034+
if (!nd_desc->fw_ops)
2035+
return NULL;
2036+
2037+
if (nfit_mem->family != NVDIMM_FAMILY_INTEL)
2038+
return NULL;
2039+
2040+
mask = nfit_mem->dsm_mask & NVDIMM_INTEL_FW_ACTIVATE_CMDMASK;
2041+
if (mask != NVDIMM_INTEL_FW_ACTIVATE_CMDMASK)
2042+
return NULL;
2043+
2044+
return intel_fw_ops;
2045+
}
2046+
20222047
static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
20232048
{
20242049
struct nfit_mem *nfit_mem;
@@ -2095,7 +2120,8 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
20952120
acpi_nfit_dimm_attribute_groups,
20962121
flags, cmd_mask, flush ? flush->hint_count : 0,
20972122
nfit_mem->flush_wpq, &nfit_mem->id[0],
2098-
acpi_nfit_get_security_ops(nfit_mem->family));
2123+
acpi_nfit_get_security_ops(nfit_mem->family),
2124+
acpi_nfit_get_fw_ops(nfit_mem));
20992125
if (!nvdimm)
21002126
return -ENOMEM;
21012127

@@ -2170,8 +2196,10 @@ static void acpi_nfit_init_dsms(struct acpi_nfit_desc *acpi_desc)
21702196
if (acpi_desc->bus_cmd_force_en) {
21712197
nd_desc->cmd_mask = acpi_desc->bus_cmd_force_en;
21722198
mask = &nd_desc->bus_family_mask;
2173-
if (acpi_desc->family_dsm_mask[NVDIMM_BUS_FAMILY_INTEL])
2199+
if (acpi_desc->family_dsm_mask[NVDIMM_BUS_FAMILY_INTEL]) {
21742200
set_bit(NVDIMM_BUS_FAMILY_INTEL, mask);
2201+
nd_desc->fw_ops = intel_bus_fw_ops;
2202+
}
21752203
}
21762204

21772205
adev = to_acpi_dev(acpi_desc);
@@ -2202,6 +2230,11 @@ static void acpi_nfit_init_dsms(struct acpi_nfit_desc *acpi_desc)
22022230
for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
22032231
if (acpi_check_dsm(adev->handle, guid, 1, 1ULL << i))
22042232
set_bit(i, mask);
2233+
2234+
if (*mask == dsm_mask) {
2235+
set_bit(NVDIMM_BUS_FAMILY_INTEL, &nd_desc->bus_family_mask);
2236+
nd_desc->fw_ops = intel_bus_fw_ops;
2237+
}
22052238
}
22062239

22072240
static ssize_t range_index_show(struct device *dev,

0 commit comments

Comments
 (0)