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 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) {
			struct acpi_nfit_flush_address *flush;
			u16 i;

			if (nfit_flush->flush->device_handle != device_handle)
				continue;
			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;
		}

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

	list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
		struct acpi_nfit_flush_address *flush;
		unsigned long flags = 0, cmd_mask;
		struct nvdimm *nvdimm;
		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)
			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,
				acpi_nfit_dimm_attribute_groups,
				flags, cmd_mask);
				flags, cmd_mask, flush ? flush->hint_count : 0,
				nfit_mem->flush_wpq);
		if (!nvdimm)
			return -ENOMEM;

+1 −0
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ struct nfit_mem {
	struct list_head list;
	struct acpi_device *adev;
	struct acpi_nfit_desc *acpi_desc;
	struct resource *flush_wpq;
	unsigned long dsm_mask;
	int family;
};
+4 −1
Original line number 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,
		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 device *dev;
@@ -362,6 +363,8 @@ struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
	nvdimm->provider_data = provider_data;
	nvdimm->flags = flags;
	nvdimm->cmd_mask = cmd_mask;
	nvdimm->num_flush = num_flush;
	nvdimm->flush_wpq = flush_wpq;
	atomic_set(&nvdimm->busy, 0);
	dev = &nvdimm->dev;
	dev_set_name(dev, "nmem%d", nvdimm->id);
+2 −1
Original line number Diff line number Diff line
@@ -41,7 +41,8 @@ struct nvdimm {
	unsigned long cmd_mask;
	struct device dev;
	atomic_t busy;
	int id;
	int id, num_flush;
	struct resource *flush_wpq;
};

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

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

static inline struct nd_namespace_index *to_namespace_index(
@@ -324,6 +325,7 @@ static inline void devm_nsio_disable(struct device *dev,
}
#endif
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);
static inline bool nd_iostat_start(struct bio *bio, unsigned long *start)
{
Loading