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

Commit f0f2c072 authored by Ross Zwisler's avatar Ross Zwisler Committed by Dan Williams
Browse files

nfit: add support for NVDIMM "latch" flag

Add support in the NFIT BLK I/O path for the "latch" flag
defined in the "Get Block NVDIMM Flags" _DSM function:

http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf



This flag requires the driver to read back the command register after it
is written in the block I/O path.  This ensures that the hardware has
fully processed the new command and moved the aperture appropriately.

Signed-off-by: default avatarRoss Zwisler <ross.zwisler@linux.intel.com>
Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent c2ad2954
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
@@ -1059,7 +1059,9 @@ static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw,

	writeq(cmd, mmio->base + offset);
	wmb_blk(nfit_blk);
	/* FIXME: conditionally perform read-back if mandated by firmware */

	if (nfit_blk->dimm_flags & ND_BLK_DCR_LATCH)
		readq(mmio->base + offset);
}

static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk,
@@ -1266,6 +1268,28 @@ static int nfit_blk_init_interleave(struct nfit_blk_mmio *mmio,
	return 0;
}

static int acpi_nfit_blk_get_flags(struct nvdimm_bus_descriptor *nd_desc,
		struct nvdimm *nvdimm, struct nfit_blk *nfit_blk)
{
	struct nd_cmd_dimm_flags flags;
	int rc;

	memset(&flags, 0, sizeof(flags));
	rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_DIMM_FLAGS, &flags,
			sizeof(flags));

	if (rc >= 0 && flags.status == 0)
		nfit_blk->dimm_flags = flags.flags;
	else if (rc == -ENOTTY) {
		/* fall back to a conservative default */
		nfit_blk->dimm_flags = ND_BLK_DCR_LATCH;
		rc = 0;
	} else
		rc = -ENXIO;

	return rc;
}

static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
		struct device *dev)
{
@@ -1340,6 +1364,13 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
		return rc;
	}

	rc = acpi_nfit_blk_get_flags(nd_desc, nvdimm, nfit_blk);
	if (rc < 0) {
		dev_dbg(dev, "%s: %s failed get DIMM flags\n",
				__func__, nvdimm_name(nvdimm));
		return rc;
	}

	nfit_flush = nfit_mem->nfit_flush;
	if (nfit_flush && nfit_flush->flush->hint_count != 0) {
		nfit_blk->nvdimm_flush = devm_ioremap_nocache(dev,
+5 −0
Original line number Diff line number Diff line
@@ -40,6 +40,10 @@ enum nfit_uuids {
	NFIT_UUID_MAX,
};

enum {
	ND_BLK_DCR_LATCH = 2,
};

struct nfit_spa {
	struct acpi_nfit_system_address *spa;
	struct list_head list;
@@ -131,6 +135,7 @@ struct nfit_blk {
	u64 stat_offset;
	u64 cmd_offset;
	void __iomem *nvdimm_flush;
	u32 dimm_flags;
};

enum spa_map_type {