Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5ae3b25 authored by Dan Williams's avatar Dan Williams
Browse files

libnvdimm, nfit: move flush hint mapping to region-device driver-data



In preparation for triggering flushes of a DIMM's writes-posted-queue
(WPQ) via the pmem driver move mapping of flush hint addresses to the
region driver.  Since this uses devm_nvdimm_memremap() the flush
addresses will remain mapped while any region to which the dimm belongs
is active.

We need to communicate more information to the nvdimm core to facilitate
this mapping, namely each dimm object now carries an array of flush hint
address resources.

Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent a8a6d2e0
Loading
Loading
Loading
Loading
+20 −1
Original line number Original line Diff line number Diff line
@@ -714,9 +714,24 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
		}
		}


		list_for_each_entry(nfit_flush, &acpi_desc->flushes, list) {
		list_for_each_entry(nfit_flush, &acpi_desc->flushes, list) {
			struct acpi_nfit_flush_address *flush;
			u16 i;

			if (nfit_flush->flush->device_handle != device_handle)
			if (nfit_flush->flush->device_handle != device_handle)
				continue;
				continue;
			nfit_mem->nfit_flush = nfit_flush;
			nfit_mem->nfit_flush = nfit_flush;
			flush = nfit_flush->flush;
			nfit_mem->flush_wpq = devm_kzalloc(acpi_desc->dev,
					flush->hint_count
					* sizeof(struct resource), GFP_KERNEL);
			if (!nfit_mem->flush_wpq)
				return -ENOMEM;
			for (i = 0; i < flush->hint_count; i++) {
				struct resource *res = &nfit_mem->flush_wpq[i];

				res->start = flush->hint_address[i];
				res->end = res->start + 8 - 1;
			}
			break;
			break;
		}
		}


@@ -1171,6 +1186,7 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
	int dimm_count = 0;
	int dimm_count = 0;


	list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
	list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
		struct acpi_nfit_flush_address *flush;
		unsigned long flags = 0, cmd_mask;
		unsigned long flags = 0, cmd_mask;
		struct nvdimm *nvdimm;
		struct nvdimm *nvdimm;
		u32 device_handle;
		u32 device_handle;
@@ -1204,9 +1220,12 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
		if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
		if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
			cmd_mask |= nfit_mem->dsm_mask;
			cmd_mask |= nfit_mem->dsm_mask;


		flush = nfit_mem->nfit_flush ? nfit_mem->nfit_flush->flush
			: NULL;
		nvdimm = nvdimm_create(acpi_desc->nvdimm_bus, nfit_mem,
		nvdimm = nvdimm_create(acpi_desc->nvdimm_bus, nfit_mem,
				acpi_nfit_dimm_attribute_groups,
				acpi_nfit_dimm_attribute_groups,
				flags, cmd_mask);
				flags, cmd_mask, flush ? flush->hint_count : 0,
				nfit_mem->flush_wpq);
		if (!nvdimm)
		if (!nvdimm)
			return -ENOMEM;
			return -ENOMEM;


+1 −0
Original line number Original line Diff line number Diff line
@@ -127,6 +127,7 @@ struct nfit_mem {
	struct list_head list;
	struct list_head list;
	struct acpi_device *adev;
	struct acpi_device *adev;
	struct acpi_nfit_desc *acpi_desc;
	struct acpi_nfit_desc *acpi_desc;
	struct resource *flush_wpq;
	unsigned long dsm_mask;
	unsigned long dsm_mask;
	int family;
	int family;
};
};
+4 −1
Original line number Original line Diff line number Diff line
@@ -346,7 +346,8 @@ EXPORT_SYMBOL_GPL(nvdimm_attribute_group);


struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
		const struct attribute_group **groups, unsigned long flags,
		const struct attribute_group **groups, unsigned long flags,
		unsigned long cmd_mask)
		unsigned long cmd_mask, int num_flush,
		struct resource *flush_wpq)
{
{
	struct nvdimm *nvdimm = kzalloc(sizeof(*nvdimm), GFP_KERNEL);
	struct nvdimm *nvdimm = kzalloc(sizeof(*nvdimm), GFP_KERNEL);
	struct device *dev;
	struct device *dev;
@@ -362,6 +363,8 @@ struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
	nvdimm->provider_data = provider_data;
	nvdimm->provider_data = provider_data;
	nvdimm->flags = flags;
	nvdimm->flags = flags;
	nvdimm->cmd_mask = cmd_mask;
	nvdimm->cmd_mask = cmd_mask;
	nvdimm->num_flush = num_flush;
	nvdimm->flush_wpq = flush_wpq;
	atomic_set(&nvdimm->busy, 0);
	atomic_set(&nvdimm->busy, 0);
	dev = &nvdimm->dev;
	dev = &nvdimm->dev;
	dev_set_name(dev, "nmem%d", nvdimm->id);
	dev_set_name(dev, "nmem%d", nvdimm->id);
+2 −1
Original line number Original line Diff line number Diff line
@@ -41,7 +41,8 @@ struct nvdimm {
	unsigned long cmd_mask;
	unsigned long cmd_mask;
	struct device dev;
	struct device dev;
	atomic_t busy;
	atomic_t busy;
	int id;
	int id, num_flush;
	struct resource *flush_wpq;
};
};


bool is_nvdimm(struct device *dev);
bool is_nvdimm(struct device *dev);
+5 −3
Original line number Original line Diff line number Diff line
@@ -49,9 +49,10 @@ struct nvdimm_drvdata {
	struct kref kref;
	struct kref kref;
};
};


struct nd_region_namespaces {
struct nd_region_data {
	int count;
	int ns_count;
	int active;
	int ns_active;
	void __iomem *flush_wpq[0][0];
};
};


static inline struct nd_namespace_index *to_namespace_index(
static inline struct nd_namespace_index *to_namespace_index(
@@ -324,6 +325,7 @@ static inline void devm_nsio_disable(struct device *dev,
}
}
#endif
#endif
int nd_blk_region_init(struct nd_region *nd_region);
int nd_blk_region_init(struct nd_region *nd_region);
int nd_region_activate(struct nd_region *nd_region);
void __nd_iostat_start(struct bio *bio, unsigned long *start);
void __nd_iostat_start(struct bio *bio, unsigned long *start);
static inline bool nd_iostat_start(struct bio *bio, unsigned long *start)
static inline bool nd_iostat_start(struct bio *bio, unsigned long *start)
{
{
Loading