mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 20:32:04 +09:00
nfit, libnvdimm: fix interleave set cookie calculation
am: 66dd58f56e
Change-Id: If1b31bbd5fe6a404d167a6b207bef928b998fba0
This commit is contained in:
@@ -965,7 +965,7 @@ static size_t sizeof_nfit_set_info(int num_mappings)
|
||||
+ num_mappings * sizeof(struct nfit_set_info_map);
|
||||
}
|
||||
|
||||
static int cmp_map(const void *m0, const void *m1)
|
||||
static int cmp_map_compat(const void *m0, const void *m1)
|
||||
{
|
||||
const struct nfit_set_info_map *map0 = m0;
|
||||
const struct nfit_set_info_map *map1 = m1;
|
||||
@@ -974,6 +974,14 @@ static int cmp_map(const void *m0, const void *m1)
|
||||
sizeof(u64));
|
||||
}
|
||||
|
||||
static int cmp_map(const void *m0, const void *m1)
|
||||
{
|
||||
const struct nfit_set_info_map *map0 = m0;
|
||||
const struct nfit_set_info_map *map1 = m1;
|
||||
|
||||
return map0->region_offset - map1->region_offset;
|
||||
}
|
||||
|
||||
/* Retrieve the nth entry referencing this spa */
|
||||
static struct acpi_nfit_memory_map *memdev_from_spa(
|
||||
struct acpi_nfit_desc *acpi_desc, u16 range_index, int n)
|
||||
@@ -1029,6 +1037,12 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
|
||||
sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
|
||||
cmp_map, NULL);
|
||||
nd_set->cookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
|
||||
|
||||
/* support namespaces created with the wrong sort order */
|
||||
sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
|
||||
cmp_map_compat, NULL);
|
||||
nd_set->altcookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
|
||||
|
||||
ndr_desc->nd_set = nd_set;
|
||||
devm_kfree(dev, info);
|
||||
|
||||
|
||||
@@ -1534,6 +1534,7 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id)
|
||||
static int find_pmem_label_set(struct nd_region *nd_region,
|
||||
struct nd_namespace_pmem *nspm)
|
||||
{
|
||||
u64 altcookie = nd_region_interleave_set_altcookie(nd_region);
|
||||
u64 cookie = nd_region_interleave_set_cookie(nd_region);
|
||||
struct nd_namespace_label *nd_label;
|
||||
u8 select_id[NSLABEL_UUID_LEN];
|
||||
@@ -1542,8 +1543,10 @@ static int find_pmem_label_set(struct nd_region *nd_region,
|
||||
int rc = -ENODEV, l;
|
||||
u16 i;
|
||||
|
||||
if (cookie == 0)
|
||||
if (cookie == 0) {
|
||||
dev_dbg(&nd_region->dev, "invalid interleave-set-cookie\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a complete set of labels by uuid. By definition we can start
|
||||
@@ -1552,13 +1555,24 @@ static int find_pmem_label_set(struct nd_region *nd_region,
|
||||
for_each_label(l, nd_label, nd_region->mapping[0].labels) {
|
||||
u64 isetcookie = __le64_to_cpu(nd_label->isetcookie);
|
||||
|
||||
if (isetcookie != cookie)
|
||||
continue;
|
||||
if (isetcookie != cookie) {
|
||||
dev_dbg(&nd_region->dev, "invalid cookie in label: %pUb\n",
|
||||
nd_label->uuid);
|
||||
if (isetcookie != altcookie)
|
||||
continue;
|
||||
|
||||
dev_dbg(&nd_region->dev, "valid altcookie in label: %pUb\n",
|
||||
nd_label->uuid);
|
||||
}
|
||||
|
||||
for (i = 0; nd_region->ndr_mappings; i++) {
|
||||
if (has_uuid_at_pos(nd_region, nd_label->uuid, cookie, i))
|
||||
continue;
|
||||
if (has_uuid_at_pos(nd_region, nd_label->uuid, altcookie, i))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; nd_region->ndr_mappings; i++)
|
||||
if (!has_uuid_at_pos(nd_region, nd_label->uuid,
|
||||
cookie, i))
|
||||
break;
|
||||
if (i < nd_region->ndr_mappings) {
|
||||
/*
|
||||
* Give up if we don't find an instance of a
|
||||
|
||||
@@ -245,6 +245,7 @@ struct nd_region *to_nd_region(struct device *dev);
|
||||
int nd_region_to_nstype(struct nd_region *nd_region);
|
||||
int nd_region_register_namespaces(struct nd_region *nd_region, int *err);
|
||||
u64 nd_region_interleave_set_cookie(struct nd_region *nd_region);
|
||||
u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region);
|
||||
void nvdimm_bus_lock(struct device *dev);
|
||||
void nvdimm_bus_unlock(struct device *dev);
|
||||
bool is_nvdimm_bus_locked(struct device *dev);
|
||||
|
||||
@@ -379,6 +379,15 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region)
|
||||
{
|
||||
struct nd_interleave_set *nd_set = nd_region->nd_set;
|
||||
|
||||
if (nd_set)
|
||||
return nd_set->altcookie;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon successful probe/remove, take/release a reference on the
|
||||
* associated interleave set (if present), and plant new btt + namespace
|
||||
|
||||
@@ -83,6 +83,8 @@ struct nd_cmd_desc {
|
||||
|
||||
struct nd_interleave_set {
|
||||
u64 cookie;
|
||||
/* compatibility with initial buggy Linux implementation */
|
||||
u64 altcookie;
|
||||
};
|
||||
|
||||
struct nd_region_desc {
|
||||
|
||||
Reference in New Issue
Block a user