Message ID | 151276680927.31888.15096916678580860198.stgit@djiang5-desk3.ch.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Fri, Dec 08, 2017 at 02:00:09PM -0700, Dave Jiang wrote: > In ACPI 6.2a the platform capability structure has been added to the NFIT > tables. That provides software the ability to determine whether a system > supports the auto flushing of CPU caches on power loss. If the capability > is supported, we do not need to do dax_write_cache(). Plumbing the path dax_flush() ? dax_write_cache() just sets or clears DAXDEV_WRITE_CACHE. dax_flush() is the place where we check DAXDEV_WRITE_CACHE and avoid calling arch_wb_cache_pmem() if the platform supports a flush-on-fail CPU cache. > to set the property on per region from the NFTI tables. NFIT > > This patch depends on the ACPI NFIT 6.2a platform capabilities support code > in include/acpi/actbl1.h. > > Signed-off-by: Dave Jiang <dave.jiang@intel.com> > --- > drivers/acpi/nfit/core.c | 20 ++++++++++++++++++++ > drivers/acpi/nfit/nfit.h | 1 + > drivers/nvdimm/pmem.c | 4 +++- > drivers/nvdimm/region_devs.c | 1 + > include/linux/libnvdimm.h | 5 +++++ > 5 files changed, 30 insertions(+), 1 deletion(-) > > diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c > index ff2580e7611d..c08b3da61b93 100644 > --- a/drivers/acpi/nfit/core.c > +++ b/drivers/acpi/nfit/core.c > @@ -838,6 +838,18 @@ static bool add_flush(struct acpi_nfit_desc *acpi_desc, > return true; > } > > +static bool add_platform_cap(struct acpi_nfit_desc *acpi_desc, > + struct acpi_nfit_capabilities *pcap) > +{ > + struct device *dev = acpi_desc->dev; > + u8 mask; 'mask' cannot be a u8, else you'll lose all the upper bits when you compute it. It needs to be a u32. > + > + mask = pcap->highest_capability - 1 + pcap->highest_capability; This calculation is broken. Take the simplest case, highest_capability = 0. This should translate into a mask of 0x1, so you only look at bit 0, but: 0 - 1 + 0 == -1 giving you a mask that includes all the bits. I think the mask you're looking for is: mask = (1 << (pcap->highest_capability + 1)) - 1; > + acpi_desc->platform_cap = pcap->capabilities & (u32)mask; > + dev_dbg(dev, "%s: cap: %#x\n", __func__, acpi_desc->platform_cap); > + return true; > +} > + > static void *add_table(struct acpi_nfit_desc *acpi_desc, > struct nfit_table_prev *prev, void *table, const void *end) > { <> > diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c > index 7fbc5c5dc8e1..13f2ed80899e 100644 > --- a/drivers/nvdimm/pmem.c > +++ b/drivers/nvdimm/pmem.c > @@ -35,6 +35,7 @@ > #include "pmem.h" > #include "pfn.h" > #include "nd.h" > +#include "nd-core.h" > > static struct device *to_dev(struct pmem_device *pmem) > { > @@ -334,7 +335,8 @@ static int pmem_attach_disk(struct device *dev, > dev_warn(dev, "unable to guarantee persistence of writes\n"); > fua = 0; > } > - wbc = nvdimm_has_cache(nd_region); > + wbc = nvdimm_has_cache(nd_region) & I'm guessing you meant: && > + !test_bit(ND_REGION_PERSIST_CACHE, &nd_region->flags); > > if (!devm_request_mem_region(dev, res->start, resource_size(res), > dev_name(&ndns->dev))) { > diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c > index abaf38c61220..87e8cd10de05 100644 > --- a/drivers/nvdimm/region_devs.c > +++ b/drivers/nvdimm/region_devs.c > @@ -994,6 +994,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, > dev->groups = ndr_desc->attr_groups; > nd_region->ndr_size = resource_size(ndr_desc->res); > nd_region->ndr_start = ndr_desc->res->start; > + Unrelated whitespace change. > nd_device_register(dev); > > return nd_region;
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index ff2580e7611d..c08b3da61b93 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -838,6 +838,18 @@ static bool add_flush(struct acpi_nfit_desc *acpi_desc, return true; } +static bool add_platform_cap(struct acpi_nfit_desc *acpi_desc, + struct acpi_nfit_capabilities *pcap) +{ + struct device *dev = acpi_desc->dev; + u8 mask; + + mask = pcap->highest_capability - 1 + pcap->highest_capability; + acpi_desc->platform_cap = pcap->capabilities & (u32)mask; + dev_dbg(dev, "%s: cap: %#x\n", __func__, acpi_desc->platform_cap); + return true; +} + static void *add_table(struct acpi_nfit_desc *acpi_desc, struct nfit_table_prev *prev, void *table, const void *end) { @@ -883,6 +895,10 @@ static void *add_table(struct acpi_nfit_desc *acpi_desc, case ACPI_NFIT_TYPE_SMBIOS: dev_dbg(dev, "%s: smbios\n", __func__); break; + case ACPI_NFIT_TYPE_CAPABILITIES: + if (!add_platform_cap(acpi_desc, table)) + return err; + break; default: dev_err(dev, "unknown table '%d' parsing nfit\n", hdr->type); break; @@ -2649,6 +2665,9 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc, else ndr_desc->numa_node = NUMA_NO_NODE; + if(acpi_desc->platform_cap & ACPI_NFIT_CAPABILITY_CACHE_FLUSH) + set_bit(ND_REGION_PERSIST_CACHE, &ndr_desc->flags); + list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) { struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev; struct nd_mapping_desc *mapping; @@ -3457,6 +3476,7 @@ static __init int nfit_init(void) BUILD_BUG_ON(sizeof(struct acpi_nfit_smbios) != 9); BUILD_BUG_ON(sizeof(struct acpi_nfit_control_region) != 80); BUILD_BUG_ON(sizeof(struct acpi_nfit_data_region) != 40); + BUILD_BUG_ON(sizeof(struct acpi_nfit_capabilities) != 16); guid_parse(UUID_VOLATILE_MEMORY, &nfit_uuid[NFIT_SPA_VOLATILE]); guid_parse(UUID_PERSISTENT_MEMORY, &nfit_uuid[NFIT_SPA_PM]); diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index f0cf18b2da8b..50d36e166d70 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h @@ -202,6 +202,7 @@ struct acpi_nfit_desc { unsigned long dimm_cmd_force_en; unsigned long bus_cmd_force_en; unsigned long bus_nfit_cmd_force_en; + unsigned int platform_cap; int (*blk_do_io)(struct nd_blk_region *ndbr, resource_size_t dpa, void *iobuf, u64 len, int rw); }; diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 7fbc5c5dc8e1..13f2ed80899e 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -35,6 +35,7 @@ #include "pmem.h" #include "pfn.h" #include "nd.h" +#include "nd-core.h" static struct device *to_dev(struct pmem_device *pmem) { @@ -334,7 +335,8 @@ static int pmem_attach_disk(struct device *dev, dev_warn(dev, "unable to guarantee persistence of writes\n"); fua = 0; } - wbc = nvdimm_has_cache(nd_region); + wbc = nvdimm_has_cache(nd_region) & + !test_bit(ND_REGION_PERSIST_CACHE, &nd_region->flags); if (!devm_request_mem_region(dev, res->start, resource_size(res), dev_name(&ndns->dev))) { diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index abaf38c61220..87e8cd10de05 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -994,6 +994,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, dev->groups = ndr_desc->attr_groups; nd_region->ndr_size = resource_size(ndr_desc->res); nd_region->ndr_start = ndr_desc->res->start; + nd_device_register(dev); return nd_region; diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h index f8109ddb5ef1..f2fc0da4da04 100644 --- a/include/linux/libnvdimm.h +++ b/include/linux/libnvdimm.h @@ -47,6 +47,11 @@ enum { /* region flag indicating to direct-map persistent memory by default */ ND_REGION_PAGEMAP = 0, + /* + * Platform ensures entire CPU store data path is flushed to pmem on + * system power loss. + */ + ND_REGION_PERSIST_CACHE = 1, /* mark newly adjusted resources as requiring a label update */ DPA_RESOURCE_ADJUSTED = 1 << 0,
In ACPI 6.2a the platform capability structure has been added to the NFIT tables. That provides software the ability to determine whether a system supports the auto flushing of CPU caches on power loss. If the capability is supported, we do not need to do dax_write_cache(). Plumbing the path to set the property on per region from the NFTI tables. This patch depends on the ACPI NFIT 6.2a platform capabilities support code in include/acpi/actbl1.h. Signed-off-by: Dave Jiang <dave.jiang@intel.com> --- drivers/acpi/nfit/core.c | 20 ++++++++++++++++++++ drivers/acpi/nfit/nfit.h | 1 + drivers/nvdimm/pmem.c | 4 +++- drivers/nvdimm/region_devs.c | 1 + include/linux/libnvdimm.h | 5 +++++ 5 files changed, 30 insertions(+), 1 deletion(-)