diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/nvdimm/label.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c index c858cfadea40..1d28cd656536 100644 --- a/drivers/nvdimm/label.c +++ b/drivers/nvdimm/label.c @@ -45,9 +45,27 @@ unsigned sizeof_namespace_label(struct nvdimm_drvdata *ndd) return ndd->nslabel_size; } +static size_t __sizeof_namespace_index(u32 nslot) +{ + return ALIGN(sizeof(struct nd_namespace_index) + DIV_ROUND_UP(nslot, 8), + NSINDEX_ALIGN); +} + +static int __nvdimm_num_label_slots(struct nvdimm_drvdata *ndd, + size_t index_size) +{ + return (ndd->nsarea.config_size - index_size * 2) / + sizeof_namespace_label(ndd); +} + int nvdimm_num_label_slots(struct nvdimm_drvdata *ndd) { - return ndd->nsarea.config_size / (sizeof_namespace_label(ndd) + 1); + u32 tmp_nslot, n; + + tmp_nslot = ndd->nsarea.config_size / sizeof_namespace_label(ndd); + n = __sizeof_namespace_index(tmp_nslot) / NSINDEX_ALIGN; + + return __nvdimm_num_label_slots(ndd, NSINDEX_ALIGN * n); } size_t sizeof_namespace_index(struct nvdimm_drvdata *ndd) @@ -55,18 +73,14 @@ size_t sizeof_namespace_index(struct nvdimm_drvdata *ndd) u32 nslot, space, size; /* - * The minimum index space is 512 bytes, with that amount of - * index we can describe ~1400 labels which is less than a byte - * of overhead per label. Round up to a byte of overhead per - * label and determine the size of the index region. Yes, this - * starts to waste space at larger config_sizes, but it's - * unlikely we'll ever see anything but 128K. + * Per UEFI 2.7, the minimum size of the Label Storage Area is large + * enough to hold 2 index blocks and 2 labels. The minimum index + * block size is 256 bytes, and the minimum label size is 256 bytes. */ nslot = nvdimm_num_label_slots(ndd); space = ndd->nsarea.config_size - nslot * sizeof_namespace_label(ndd); - size = ALIGN(sizeof(struct nd_namespace_index) + DIV_ROUND_UP(nslot, 8), - NSINDEX_ALIGN) * 2; - if (size <= space) + size = __sizeof_namespace_index(nslot) * 2; + if (size <= space && nslot >= 2) return size / 2; dev_err(ndd->dev, "label area (%d) too small to host (%d byte) labels\n", |