diff options
Diffstat (limited to 'drivers/nvdimm/namespace_devs.c')
-rw-r--r-- | drivers/nvdimm/namespace_devs.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index f05d9b0672bf..c96e31330213 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c | |||
@@ -1411,6 +1411,58 @@ static ssize_t dpa_extents_show(struct device *dev, | |||
1411 | } | 1411 | } |
1412 | static DEVICE_ATTR_RO(dpa_extents); | 1412 | static DEVICE_ATTR_RO(dpa_extents); |
1413 | 1413 | ||
1414 | static int btt_claim_class(struct device *dev) | ||
1415 | { | ||
1416 | struct nd_region *nd_region = to_nd_region(dev->parent); | ||
1417 | int i, loop_bitmask = 0; | ||
1418 | |||
1419 | for (i = 0; i < nd_region->ndr_mappings; i++) { | ||
1420 | struct nd_mapping *nd_mapping = &nd_region->mapping[i]; | ||
1421 | struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); | ||
1422 | struct nd_namespace_index *nsindex; | ||
1423 | |||
1424 | nsindex = to_namespace_index(ndd, ndd->ns_current); | ||
1425 | if (nsindex == NULL) | ||
1426 | loop_bitmask |= 1; | ||
1427 | else { | ||
1428 | /* check whether existing labels are v1.1 or v1.2 */ | ||
1429 | if (__le16_to_cpu(nsindex->major) == 1 | ||
1430 | && __le16_to_cpu(nsindex->minor) == 1) | ||
1431 | loop_bitmask |= 2; | ||
1432 | else | ||
1433 | loop_bitmask |= 4; | ||
1434 | } | ||
1435 | } | ||
1436 | /* | ||
1437 | * If nsindex is null loop_bitmask's bit 0 will be set, and if an index | ||
1438 | * block is found, a v1.1 label for any mapping will set bit 1, and a | ||
1439 | * v1.2 label will set bit 2. | ||
1440 | * | ||
1441 | * At the end of the loop, at most one of the three bits must be set. | ||
1442 | * If multiple bits were set, it means the different mappings disagree | ||
1443 | * about their labels, and this must be cleaned up first. | ||
1444 | * | ||
1445 | * If all the label index blocks are found to agree, nsindex of NULL | ||
1446 | * implies labels haven't been initialized yet, and when they will, | ||
1447 | * they will be of the 1.2 format, so we can assume BTT2.0 | ||
1448 | * | ||
1449 | * If 1.1 labels are found, we enforce BTT1.1, and if 1.2 labels are | ||
1450 | * found, we enforce BTT2.0 | ||
1451 | * | ||
1452 | * If the loop was never entered, default to BTT1.1 (legacy namespaces) | ||
1453 | */ | ||
1454 | switch (loop_bitmask) { | ||
1455 | case 0: | ||
1456 | case 2: | ||
1457 | return NVDIMM_CCLASS_BTT; | ||
1458 | case 1: | ||
1459 | case 4: | ||
1460 | return NVDIMM_CCLASS_BTT2; | ||
1461 | default: | ||
1462 | return -ENXIO; | ||
1463 | } | ||
1464 | } | ||
1465 | |||
1414 | static ssize_t holder_show(struct device *dev, | 1466 | static ssize_t holder_show(struct device *dev, |
1415 | struct device_attribute *attr, char *buf) | 1467 | struct device_attribute *attr, char *buf) |
1416 | { | 1468 | { |
@@ -1433,7 +1485,7 @@ static ssize_t __holder_class_store(struct device *dev, const char *buf) | |||
1433 | return -EBUSY; | 1485 | return -EBUSY; |
1434 | 1486 | ||
1435 | if (strcmp(buf, "btt") == 0 || strcmp(buf, "btt\n") == 0) | 1487 | if (strcmp(buf, "btt") == 0 || strcmp(buf, "btt\n") == 0) |
1436 | ndns->claim_class = NVDIMM_CCLASS_BTT; | 1488 | ndns->claim_class = btt_claim_class(dev); |
1437 | else if (strcmp(buf, "pfn") == 0 || strcmp(buf, "pfn\n") == 0) | 1489 | else if (strcmp(buf, "pfn") == 0 || strcmp(buf, "pfn\n") == 0) |
1438 | ndns->claim_class = NVDIMM_CCLASS_PFN; | 1490 | ndns->claim_class = NVDIMM_CCLASS_PFN; |
1439 | else if (strcmp(buf, "dax") == 0 || strcmp(buf, "dax\n") == 0) | 1491 | else if (strcmp(buf, "dax") == 0 || strcmp(buf, "dax\n") == 0) |
@@ -1443,6 +1495,10 @@ static ssize_t __holder_class_store(struct device *dev, const char *buf) | |||
1443 | else | 1495 | else |
1444 | return -EINVAL; | 1496 | return -EINVAL; |
1445 | 1497 | ||
1498 | /* btt_claim_class() could've returned an error */ | ||
1499 | if (ndns->claim_class < 0) | ||
1500 | return ndns->claim_class; | ||
1501 | |||
1446 | return 0; | 1502 | return 0; |
1447 | } | 1503 | } |
1448 | 1504 | ||
@@ -1474,7 +1530,8 @@ static ssize_t holder_class_show(struct device *dev, | |||
1474 | device_lock(dev); | 1530 | device_lock(dev); |
1475 | if (ndns->claim_class == NVDIMM_CCLASS_NONE) | 1531 | if (ndns->claim_class == NVDIMM_CCLASS_NONE) |
1476 | rc = sprintf(buf, "\n"); | 1532 | rc = sprintf(buf, "\n"); |
1477 | else if (ndns->claim_class == NVDIMM_CCLASS_BTT) | 1533 | else if ((ndns->claim_class == NVDIMM_CCLASS_BTT) || |
1534 | (ndns->claim_class == NVDIMM_CCLASS_BTT2)) | ||
1478 | rc = sprintf(buf, "btt\n"); | 1535 | rc = sprintf(buf, "btt\n"); |
1479 | else if (ndns->claim_class == NVDIMM_CCLASS_PFN) | 1536 | else if (ndns->claim_class == NVDIMM_CCLASS_PFN) |
1480 | rc = sprintf(buf, "pfn\n"); | 1537 | rc = sprintf(buf, "pfn\n"); |