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

Commit 14e49454 authored by Vishal Verma's avatar Vishal Verma Committed by Dan Williams
Browse files

libnvdimm, btt: BTT updates for UEFI 2.7 format



The UEFI 2.7 specification defines an updated BTT metadata format,
bumping the revision to 2.0. Add support for the new format, while
retaining compatibility for the old 1.1 format.

Cc: Toshi Kani <toshi.kani@hpe.com>
Cc: Linda Knippers <linda.knippers@hpe.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarVishal Verma <vishal.l.verma@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 5e93746f
Loading
Loading
Loading
Loading
+20 −8
Original line number Original line Diff line number Diff line
@@ -37,8 +37,8 @@ static int arena_read_bytes(struct arena_info *arena, resource_size_t offset,
	struct nd_btt *nd_btt = arena->nd_btt;
	struct nd_btt *nd_btt = arena->nd_btt;
	struct nd_namespace_common *ndns = nd_btt->ndns;
	struct nd_namespace_common *ndns = nd_btt->ndns;


	/* arena offsets are 4K from the base of the device */
	/* arena offsets may be shifted from the base of the device */
	offset += SZ_4K;
	offset += arena->nd_btt->initial_offset;
	return nvdimm_read_bytes(ndns, offset, buf, n, flags);
	return nvdimm_read_bytes(ndns, offset, buf, n, flags);
}
}


@@ -48,8 +48,8 @@ static int arena_write_bytes(struct arena_info *arena, resource_size_t offset,
	struct nd_btt *nd_btt = arena->nd_btt;
	struct nd_btt *nd_btt = arena->nd_btt;
	struct nd_namespace_common *ndns = nd_btt->ndns;
	struct nd_namespace_common *ndns = nd_btt->ndns;


	/* arena offsets are 4K from the base of the device */
	/* arena offsets may be shifted from the base of the device */
	offset += SZ_4K;
	offset += arena->nd_btt->initial_offset;
	return nvdimm_write_bytes(ndns, offset, buf, n, flags);
	return nvdimm_write_bytes(ndns, offset, buf, n, flags);
}
}


@@ -576,8 +576,8 @@ static struct arena_info *alloc_arena(struct btt *btt, size_t size,
	arena->internal_lbasize = roundup(arena->external_lbasize,
	arena->internal_lbasize = roundup(arena->external_lbasize,
					INT_LBASIZE_ALIGNMENT);
					INT_LBASIZE_ALIGNMENT);
	arena->nfree = BTT_DEFAULT_NFREE;
	arena->nfree = BTT_DEFAULT_NFREE;
	arena->version_major = 1;
	arena->version_major = btt->nd_btt->version_major;
	arena->version_minor = 1;
	arena->version_minor = btt->nd_btt->version_minor;


	if (available % BTT_PG_SIZE)
	if (available % BTT_PG_SIZE)
		available -= (available % BTT_PG_SIZE);
		available -= (available % BTT_PG_SIZE);
@@ -1425,6 +1425,7 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns)
{
{
	struct nd_btt *nd_btt = to_nd_btt(ndns->claim);
	struct nd_btt *nd_btt = to_nd_btt(ndns->claim);
	struct nd_region *nd_region;
	struct nd_region *nd_region;
	struct btt_sb *btt_sb;
	struct btt *btt;
	struct btt *btt;
	size_t rawsize;
	size_t rawsize;


@@ -1433,10 +1434,21 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns)
		return -ENODEV;
		return -ENODEV;
	}
	}


	rawsize = nvdimm_namespace_capacity(ndns) - SZ_4K;
	btt_sb = devm_kzalloc(&nd_btt->dev, sizeof(*btt_sb), GFP_KERNEL);

	/*
	 * If this returns < 0, that is ok as it just means there wasn't
	 * an existing BTT, and we're creating a new one. We still need to
	 * call this as we need the version dependent fields in nd_btt to be
	 * set correctly based on the holder class
	 */
	nd_btt_version(nd_btt, ndns, btt_sb);

	rawsize = nvdimm_namespace_capacity(ndns) - nd_btt->initial_offset;
	if (rawsize < ARENA_MIN_SIZE) {
	if (rawsize < ARENA_MIN_SIZE) {
		dev_dbg(&nd_btt->dev, "%s must be at least %ld bytes\n",
		dev_dbg(&nd_btt->dev, "%s must be at least %ld bytes\n",
				dev_name(&ndns->dev), ARENA_MIN_SIZE + SZ_4K);
				dev_name(&ndns->dev),
				ARENA_MIN_SIZE + nd_btt->initial_offset);
		return -ENXIO;
		return -ENXIO;
	}
	}
	nd_region = to_nd_region(nd_btt->dev.parent);
	nd_region = to_nd_region(nd_btt->dev.parent);
+2 −0
Original line number Original line Diff line number Diff line
@@ -184,5 +184,7 @@ struct btt {
};
};


bool nd_btt_arena_is_valid(struct nd_btt *nd_btt, struct btt_sb *super);
bool nd_btt_arena_is_valid(struct nd_btt *nd_btt, struct btt_sb *super);
int nd_btt_version(struct nd_btt *nd_btt, struct nd_namespace_common *ndns,
		struct btt_sb *btt_sb);


#endif
#endif
+41 −5
Original line number Original line Diff line number Diff line
@@ -260,20 +260,55 @@ bool nd_btt_arena_is_valid(struct nd_btt *nd_btt, struct btt_sb *super)
}
}
EXPORT_SYMBOL(nd_btt_arena_is_valid);
EXPORT_SYMBOL(nd_btt_arena_is_valid);


int nd_btt_version(struct nd_btt *nd_btt, struct nd_namespace_common *ndns,
		struct btt_sb *btt_sb)
{
	if (ndns->claim_class == NVDIMM_CCLASS_BTT2) {
		/* Probe/setup for BTT v2.0 */
		nd_btt->initial_offset = 0;
		nd_btt->version_major = 2;
		nd_btt->version_minor = 0;
		if (nvdimm_read_bytes(ndns, 0, btt_sb, sizeof(*btt_sb), 0))
			return -ENXIO;
		if (!nd_btt_arena_is_valid(nd_btt, btt_sb))
			return -ENODEV;
		if ((le16_to_cpu(btt_sb->version_major) != 2) ||
				(le16_to_cpu(btt_sb->version_minor) != 0))
			return -ENODEV;
	} else {
		/*
		 * Probe/setup for BTT v1.1 (NVDIMM_CCLASS_NONE or
		 * NVDIMM_CCLASS_BTT)
		 */
		nd_btt->initial_offset = SZ_4K;
		nd_btt->version_major = 1;
		nd_btt->version_minor = 1;
		if (nvdimm_read_bytes(ndns, SZ_4K, btt_sb, sizeof(*btt_sb), 0))
			return -ENXIO;
		if (!nd_btt_arena_is_valid(nd_btt, btt_sb))
			return -ENODEV;
		if ((le16_to_cpu(btt_sb->version_major) != 1) ||
				(le16_to_cpu(btt_sb->version_minor) != 1))
			return -ENODEV;
	}
	return 0;
}
EXPORT_SYMBOL(nd_btt_version);

static int __nd_btt_probe(struct nd_btt *nd_btt,
static int __nd_btt_probe(struct nd_btt *nd_btt,
		struct nd_namespace_common *ndns, struct btt_sb *btt_sb)
		struct nd_namespace_common *ndns, struct btt_sb *btt_sb)
{
{
	int rc;

	if (!btt_sb || !ndns || !nd_btt)
	if (!btt_sb || !ndns || !nd_btt)
		return -ENODEV;
		return -ENODEV;


	if (nvdimm_read_bytes(ndns, SZ_4K, btt_sb, sizeof(*btt_sb), 0))
		return -ENXIO;

	if (nvdimm_namespace_capacity(ndns) < SZ_16M)
	if (nvdimm_namespace_capacity(ndns) < SZ_16M)
		return -ENXIO;
		return -ENXIO;


	if (!nd_btt_arena_is_valid(nd_btt, btt_sb))
	rc = nd_btt_version(nd_btt, ndns, btt_sb);
		return -ENODEV;
	if (rc < 0)
		return rc;


	nd_btt->lbasize = le32_to_cpu(btt_sb->external_lbasize);
	nd_btt->lbasize = le32_to_cpu(btt_sb->external_lbasize);
	nd_btt->uuid = kmemdup(btt_sb->uuid, 16, GFP_KERNEL);
	nd_btt->uuid = kmemdup(btt_sb->uuid, 16, GFP_KERNEL);
@@ -298,6 +333,7 @@ int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns)
	switch (ndns->claim_class) {
	switch (ndns->claim_class) {
	case NVDIMM_CCLASS_NONE:
	case NVDIMM_CCLASS_NONE:
	case NVDIMM_CCLASS_BTT:
	case NVDIMM_CCLASS_BTT:
	case NVDIMM_CCLASS_BTT2:
		break;
		break;
	default:
	default:
		return -ENODEV;
		return -ENODEV;
+1 −0
Original line number Original line Diff line number Diff line
@@ -189,6 +189,7 @@ ssize_t nd_namespace_store(struct device *dev,
	case NVDIMM_CCLASS_NONE:
	case NVDIMM_CCLASS_NONE:
		break;
		break;
	case NVDIMM_CCLASS_BTT:
	case NVDIMM_CCLASS_BTT:
	case NVDIMM_CCLASS_BTT2:
		if (!is_nd_btt(dev)) {
		if (!is_nd_btt(dev)) {
			len = -EBUSY;
			len = -EBUSY;
			goto out_attach;
			goto out_attach;
+6 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@
#include "nd.h"
#include "nd.h"


static guid_t nvdimm_btt_guid;
static guid_t nvdimm_btt_guid;
static guid_t nvdimm_btt2_guid;
static guid_t nvdimm_pfn_guid;
static guid_t nvdimm_pfn_guid;
static guid_t nvdimm_dax_guid;
static guid_t nvdimm_dax_guid;


@@ -578,6 +579,8 @@ enum nvdimm_claim_class to_nvdimm_cclass(guid_t *guid)
{
{
	if (guid_equal(guid, &nvdimm_btt_guid))
	if (guid_equal(guid, &nvdimm_btt_guid))
		return NVDIMM_CCLASS_BTT;
		return NVDIMM_CCLASS_BTT;
	else if (guid_equal(guid, &nvdimm_btt2_guid))
		return NVDIMM_CCLASS_BTT2;
	else if (guid_equal(guid, &nvdimm_pfn_guid))
	else if (guid_equal(guid, &nvdimm_pfn_guid))
		return NVDIMM_CCLASS_PFN;
		return NVDIMM_CCLASS_PFN;
	else if (guid_equal(guid, &nvdimm_dax_guid))
	else if (guid_equal(guid, &nvdimm_dax_guid))
@@ -593,6 +596,8 @@ static const guid_t *to_abstraction_guid(enum nvdimm_claim_class claim_class,
{
{
	if (claim_class == NVDIMM_CCLASS_BTT)
	if (claim_class == NVDIMM_CCLASS_BTT)
		return &nvdimm_btt_guid;
		return &nvdimm_btt_guid;
	else if (claim_class == NVDIMM_CCLASS_BTT2)
		return &nvdimm_btt2_guid;
	else if (claim_class == NVDIMM_CCLASS_PFN)
	else if (claim_class == NVDIMM_CCLASS_PFN)
		return &nvdimm_pfn_guid;
		return &nvdimm_pfn_guid;
	else if (claim_class == NVDIMM_CCLASS_DAX)
	else if (claim_class == NVDIMM_CCLASS_DAX)
@@ -1158,6 +1163,7 @@ int nd_blk_namespace_label_update(struct nd_region *nd_region,
int __init nd_label_init(void)
int __init nd_label_init(void)
{
{
	WARN_ON(guid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_guid));
	WARN_ON(guid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_guid));
	WARN_ON(guid_parse(NVDIMM_BTT2_GUID, &nvdimm_btt2_guid));
	WARN_ON(guid_parse(NVDIMM_PFN_GUID, &nvdimm_pfn_guid));
	WARN_ON(guid_parse(NVDIMM_PFN_GUID, &nvdimm_pfn_guid));
	WARN_ON(guid_parse(NVDIMM_DAX_GUID, &nvdimm_dax_guid));
	WARN_ON(guid_parse(NVDIMM_DAX_GUID, &nvdimm_dax_guid));


Loading