| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright(c) 2013-2015 Intel Corporation. All rights reserved. |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of version 2 of the GNU General Public License as |
|---|
| 6 | | - * published by the Free Software Foundation. |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 9 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 10 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 11 | | - * General Public License for more details. |
|---|
| 12 | 4 | */ |
|---|
| 13 | 5 | #include <linux/module.h> |
|---|
| 14 | 6 | #include <linux/device.h> |
|---|
| .. | .. |
|---|
| 18 | 10 | #include <linux/nd.h> |
|---|
| 19 | 11 | #include "nd-core.h" |
|---|
| 20 | 12 | #include "pmem.h" |
|---|
| 13 | +#include "pfn.h" |
|---|
| 21 | 14 | #include "nd.h" |
|---|
| 22 | 15 | |
|---|
| 23 | 16 | static void namespace_io_release(struct device *dev) |
|---|
| .. | .. |
|---|
| 52 | 45 | kfree(nsblk); |
|---|
| 53 | 46 | } |
|---|
| 54 | 47 | |
|---|
| 55 | | -static const struct device_type namespace_io_device_type = { |
|---|
| 56 | | - .name = "nd_namespace_io", |
|---|
| 57 | | - .release = namespace_io_release, |
|---|
| 58 | | -}; |
|---|
| 59 | | - |
|---|
| 60 | | -static const struct device_type namespace_pmem_device_type = { |
|---|
| 61 | | - .name = "nd_namespace_pmem", |
|---|
| 62 | | - .release = namespace_pmem_release, |
|---|
| 63 | | -}; |
|---|
| 64 | | - |
|---|
| 65 | | -static const struct device_type namespace_blk_device_type = { |
|---|
| 66 | | - .name = "nd_namespace_blk", |
|---|
| 67 | | - .release = namespace_blk_release, |
|---|
| 68 | | -}; |
|---|
| 69 | | - |
|---|
| 70 | | -static bool is_namespace_pmem(const struct device *dev) |
|---|
| 71 | | -{ |
|---|
| 72 | | - return dev ? dev->type == &namespace_pmem_device_type : false; |
|---|
| 73 | | -} |
|---|
| 74 | | - |
|---|
| 75 | | -static bool is_namespace_blk(const struct device *dev) |
|---|
| 76 | | -{ |
|---|
| 77 | | - return dev ? dev->type == &namespace_blk_device_type : false; |
|---|
| 78 | | -} |
|---|
| 79 | | - |
|---|
| 80 | | -static bool is_namespace_io(const struct device *dev) |
|---|
| 81 | | -{ |
|---|
| 82 | | - return dev ? dev->type == &namespace_io_device_type : false; |
|---|
| 83 | | -} |
|---|
| 48 | +static bool is_namespace_pmem(const struct device *dev); |
|---|
| 49 | +static bool is_namespace_blk(const struct device *dev); |
|---|
| 50 | +static bool is_namespace_io(const struct device *dev); |
|---|
| 84 | 51 | |
|---|
| 85 | 52 | static int is_uuid_busy(struct device *dev, void *data) |
|---|
| 86 | 53 | { |
|---|
| .. | .. |
|---|
| 274 | 241 | if (dev->driver || to_ndns(dev)->claim) |
|---|
| 275 | 242 | return -EBUSY; |
|---|
| 276 | 243 | |
|---|
| 277 | | - input = kmemdup(buf, len + 1, GFP_KERNEL); |
|---|
| 244 | + input = kstrndup(buf, len, GFP_KERNEL); |
|---|
| 278 | 245 | if (!input) |
|---|
| 279 | 246 | return -ENOMEM; |
|---|
| 280 | 247 | |
|---|
| 281 | | - input[len] = '\0'; |
|---|
| 282 | 248 | pos = strim(input); |
|---|
| 283 | 249 | if (strlen(pos) + 1 > NSLABEL_NAME_LEN) { |
|---|
| 284 | 250 | rc = -EINVAL; |
|---|
| .. | .. |
|---|
| 419 | 385 | struct nd_region *nd_region = to_nd_region(dev->parent); |
|---|
| 420 | 386 | ssize_t rc; |
|---|
| 421 | 387 | |
|---|
| 422 | | - device_lock(dev); |
|---|
| 388 | + nd_device_lock(dev); |
|---|
| 423 | 389 | nvdimm_bus_lock(dev); |
|---|
| 424 | 390 | wait_nvdimm_bus_probe_idle(dev); |
|---|
| 425 | 391 | rc = __alt_name_store(dev, buf, len); |
|---|
| .. | .. |
|---|
| 427 | 393 | rc = nd_namespace_label_update(nd_region, dev); |
|---|
| 428 | 394 | dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc); |
|---|
| 429 | 395 | nvdimm_bus_unlock(dev); |
|---|
| 430 | | - device_unlock(dev); |
|---|
| 396 | + nd_device_unlock(dev); |
|---|
| 431 | 397 | |
|---|
| 432 | 398 | return rc < 0 ? rc : len; |
|---|
| 433 | 399 | } |
|---|
| .. | .. |
|---|
| 576 | 542 | { |
|---|
| 577 | 543 | bool is_reserve = strcmp(label_id->id, "pmem-reserve") == 0; |
|---|
| 578 | 544 | bool is_pmem = strncmp(label_id->id, "pmem", 4) == 0; |
|---|
| 545 | + unsigned long align; |
|---|
| 546 | + |
|---|
| 547 | + align = nd_region->align / nd_region->ndr_mappings; |
|---|
| 548 | + valid->start = ALIGN(valid->start, align); |
|---|
| 549 | + valid->end = ALIGN_DOWN(valid->end + 1, align) - 1; |
|---|
| 579 | 550 | |
|---|
| 580 | 551 | if (valid->start >= valid->end) |
|---|
| 581 | 552 | goto invalid; |
|---|
| .. | .. |
|---|
| 1015 | 986 | return -ENXIO; |
|---|
| 1016 | 987 | } |
|---|
| 1017 | 988 | |
|---|
| 1018 | | - div_u64_rem(val, SZ_4K * nd_region->ndr_mappings, &remainder); |
|---|
| 989 | + div_u64_rem(val, nd_region->align, &remainder); |
|---|
| 1019 | 990 | if (remainder) { |
|---|
| 1020 | | - dev_dbg(dev, "%llu is not %dK aligned\n", val, |
|---|
| 1021 | | - (SZ_4K * nd_region->ndr_mappings) / SZ_1K); |
|---|
| 991 | + dev_dbg(dev, "%llu is not %ldK aligned\n", val, |
|---|
| 992 | + nd_region->align / SZ_1K); |
|---|
| 1022 | 993 | return -EINVAL; |
|---|
| 1023 | 994 | } |
|---|
| 1024 | 995 | |
|---|
| .. | .. |
|---|
| 1086 | 1057 | if (rc) |
|---|
| 1087 | 1058 | return rc; |
|---|
| 1088 | 1059 | |
|---|
| 1089 | | - device_lock(dev); |
|---|
| 1060 | + nd_device_lock(dev); |
|---|
| 1090 | 1061 | nvdimm_bus_lock(dev); |
|---|
| 1091 | 1062 | wait_nvdimm_bus_probe_idle(dev); |
|---|
| 1092 | 1063 | rc = __size_store(dev, val); |
|---|
| .. | .. |
|---|
| 1112 | 1083 | dev_dbg(dev, "%llx %s (%d)\n", val, rc < 0 ? "fail" : "success", rc); |
|---|
| 1113 | 1084 | |
|---|
| 1114 | 1085 | nvdimm_bus_unlock(dev); |
|---|
| 1115 | | - device_unlock(dev); |
|---|
| 1086 | + nd_device_unlock(dev); |
|---|
| 1116 | 1087 | |
|---|
| 1117 | 1088 | return rc < 0 ? rc : len; |
|---|
| 1118 | 1089 | } |
|---|
| .. | .. |
|---|
| 1295 | 1266 | } else |
|---|
| 1296 | 1267 | return -ENXIO; |
|---|
| 1297 | 1268 | |
|---|
| 1298 | | - device_lock(dev); |
|---|
| 1269 | + nd_device_lock(dev); |
|---|
| 1299 | 1270 | nvdimm_bus_lock(dev); |
|---|
| 1300 | 1271 | wait_nvdimm_bus_probe_idle(dev); |
|---|
| 1301 | 1272 | if (to_ndns(dev)->claim) |
|---|
| .. | .. |
|---|
| 1311 | 1282 | dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, |
|---|
| 1312 | 1283 | buf[len - 1] == '\n' ? "" : "\n"); |
|---|
| 1313 | 1284 | nvdimm_bus_unlock(dev); |
|---|
| 1314 | | - device_unlock(dev); |
|---|
| 1285 | + nd_device_unlock(dev); |
|---|
| 1315 | 1286 | |
|---|
| 1316 | 1287 | return rc < 0 ? rc : len; |
|---|
| 1317 | 1288 | } |
|---|
| .. | .. |
|---|
| 1338 | 1309 | return -ENXIO; |
|---|
| 1339 | 1310 | return sprintf(buf, "%#llx\n", (unsigned long long) res->start); |
|---|
| 1340 | 1311 | } |
|---|
| 1341 | | -static DEVICE_ATTR_RO(resource); |
|---|
| 1312 | +static DEVICE_ATTR_ADMIN_RO(resource); |
|---|
| 1342 | 1313 | |
|---|
| 1343 | 1314 | static const unsigned long blk_lbasize_supported[] = { 512, 520, 528, |
|---|
| 1344 | 1315 | 4096, 4104, 4160, 4224, 0 }; |
|---|
| .. | .. |
|---|
| 1385 | 1356 | } else |
|---|
| 1386 | 1357 | return -ENXIO; |
|---|
| 1387 | 1358 | |
|---|
| 1388 | | - device_lock(dev); |
|---|
| 1359 | + nd_device_lock(dev); |
|---|
| 1389 | 1360 | nvdimm_bus_lock(dev); |
|---|
| 1390 | 1361 | if (to_ndns(dev)->claim) |
|---|
| 1391 | 1362 | rc = -EBUSY; |
|---|
| .. | .. |
|---|
| 1396 | 1367 | dev_dbg(dev, "result: %zd %s: %s%s", rc, rc < 0 ? "tried" : "wrote", |
|---|
| 1397 | 1368 | buf, buf[len - 1] == '\n' ? "" : "\n"); |
|---|
| 1398 | 1369 | nvdimm_bus_unlock(dev); |
|---|
| 1399 | | - device_unlock(dev); |
|---|
| 1370 | + nd_device_unlock(dev); |
|---|
| 1400 | 1371 | |
|---|
| 1401 | 1372 | return rc ? rc : len; |
|---|
| 1402 | 1373 | } |
|---|
| .. | .. |
|---|
| 1511 | 1482 | struct nd_namespace_common *ndns = to_ndns(dev); |
|---|
| 1512 | 1483 | ssize_t rc; |
|---|
| 1513 | 1484 | |
|---|
| 1514 | | - device_lock(dev); |
|---|
| 1485 | + nd_device_lock(dev); |
|---|
| 1515 | 1486 | rc = sprintf(buf, "%s\n", ndns->claim ? dev_name(ndns->claim) : ""); |
|---|
| 1516 | | - device_unlock(dev); |
|---|
| 1487 | + nd_device_unlock(dev); |
|---|
| 1517 | 1488 | |
|---|
| 1518 | 1489 | return rc; |
|---|
| 1519 | 1490 | } |
|---|
| 1520 | 1491 | static DEVICE_ATTR_RO(holder); |
|---|
| 1521 | 1492 | |
|---|
| 1522 | | -static ssize_t __holder_class_store(struct device *dev, const char *buf) |
|---|
| 1493 | +static int __holder_class_store(struct device *dev, const char *buf) |
|---|
| 1523 | 1494 | { |
|---|
| 1524 | 1495 | struct nd_namespace_common *ndns = to_ndns(dev); |
|---|
| 1525 | 1496 | |
|---|
| 1526 | 1497 | if (dev->driver || ndns->claim) |
|---|
| 1527 | 1498 | return -EBUSY; |
|---|
| 1528 | 1499 | |
|---|
| 1529 | | - if (strcmp(buf, "btt") == 0 || strcmp(buf, "btt\n") == 0) |
|---|
| 1530 | | - ndns->claim_class = btt_claim_class(dev); |
|---|
| 1531 | | - else if (strcmp(buf, "pfn") == 0 || strcmp(buf, "pfn\n") == 0) |
|---|
| 1500 | + if (sysfs_streq(buf, "btt")) { |
|---|
| 1501 | + int rc = btt_claim_class(dev); |
|---|
| 1502 | + |
|---|
| 1503 | + if (rc < NVDIMM_CCLASS_NONE) |
|---|
| 1504 | + return rc; |
|---|
| 1505 | + ndns->claim_class = rc; |
|---|
| 1506 | + } else if (sysfs_streq(buf, "pfn")) |
|---|
| 1532 | 1507 | ndns->claim_class = NVDIMM_CCLASS_PFN; |
|---|
| 1533 | | - else if (strcmp(buf, "dax") == 0 || strcmp(buf, "dax\n") == 0) |
|---|
| 1508 | + else if (sysfs_streq(buf, "dax")) |
|---|
| 1534 | 1509 | ndns->claim_class = NVDIMM_CCLASS_DAX; |
|---|
| 1535 | | - else if (strcmp(buf, "") == 0 || strcmp(buf, "\n") == 0) |
|---|
| 1510 | + else if (sysfs_streq(buf, "")) |
|---|
| 1536 | 1511 | ndns->claim_class = NVDIMM_CCLASS_NONE; |
|---|
| 1537 | 1512 | else |
|---|
| 1538 | 1513 | return -EINVAL; |
|---|
| 1539 | | - |
|---|
| 1540 | | - /* btt_claim_class() could've returned an error */ |
|---|
| 1541 | | - if (ndns->claim_class < 0) |
|---|
| 1542 | | - return ndns->claim_class; |
|---|
| 1543 | 1514 | |
|---|
| 1544 | 1515 | return 0; |
|---|
| 1545 | 1516 | } |
|---|
| .. | .. |
|---|
| 1548 | 1519 | struct device_attribute *attr, const char *buf, size_t len) |
|---|
| 1549 | 1520 | { |
|---|
| 1550 | 1521 | struct nd_region *nd_region = to_nd_region(dev->parent); |
|---|
| 1551 | | - ssize_t rc; |
|---|
| 1522 | + int rc; |
|---|
| 1552 | 1523 | |
|---|
| 1553 | | - device_lock(dev); |
|---|
| 1524 | + nd_device_lock(dev); |
|---|
| 1554 | 1525 | nvdimm_bus_lock(dev); |
|---|
| 1555 | 1526 | wait_nvdimm_bus_probe_idle(dev); |
|---|
| 1556 | 1527 | rc = __holder_class_store(dev, buf); |
|---|
| 1557 | 1528 | if (rc >= 0) |
|---|
| 1558 | 1529 | rc = nd_namespace_label_update(nd_region, dev); |
|---|
| 1559 | | - dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc); |
|---|
| 1530 | + dev_dbg(dev, "%s(%d)\n", rc < 0 ? "fail " : "", rc); |
|---|
| 1560 | 1531 | nvdimm_bus_unlock(dev); |
|---|
| 1561 | | - device_unlock(dev); |
|---|
| 1532 | + nd_device_unlock(dev); |
|---|
| 1562 | 1533 | |
|---|
| 1563 | 1534 | return rc < 0 ? rc : len; |
|---|
| 1564 | 1535 | } |
|---|
| .. | .. |
|---|
| 1569 | 1540 | struct nd_namespace_common *ndns = to_ndns(dev); |
|---|
| 1570 | 1541 | ssize_t rc; |
|---|
| 1571 | 1542 | |
|---|
| 1572 | | - device_lock(dev); |
|---|
| 1543 | + nd_device_lock(dev); |
|---|
| 1573 | 1544 | if (ndns->claim_class == NVDIMM_CCLASS_NONE) |
|---|
| 1574 | 1545 | rc = sprintf(buf, "\n"); |
|---|
| 1575 | 1546 | else if ((ndns->claim_class == NVDIMM_CCLASS_BTT) || |
|---|
| .. | .. |
|---|
| 1581 | 1552 | rc = sprintf(buf, "dax\n"); |
|---|
| 1582 | 1553 | else |
|---|
| 1583 | 1554 | rc = sprintf(buf, "<unknown>\n"); |
|---|
| 1584 | | - device_unlock(dev); |
|---|
| 1555 | + nd_device_unlock(dev); |
|---|
| 1585 | 1556 | |
|---|
| 1586 | 1557 | return rc; |
|---|
| 1587 | 1558 | } |
|---|
| .. | .. |
|---|
| 1595 | 1566 | char *mode; |
|---|
| 1596 | 1567 | ssize_t rc; |
|---|
| 1597 | 1568 | |
|---|
| 1598 | | - device_lock(dev); |
|---|
| 1569 | + nd_device_lock(dev); |
|---|
| 1599 | 1570 | claim = ndns->claim; |
|---|
| 1600 | 1571 | if (claim && is_nd_btt(claim)) |
|---|
| 1601 | 1572 | mode = "safe"; |
|---|
| .. | .. |
|---|
| 1608 | 1579 | else |
|---|
| 1609 | 1580 | mode = "raw"; |
|---|
| 1610 | 1581 | rc = sprintf(buf, "%s\n", mode); |
|---|
| 1611 | | - device_unlock(dev); |
|---|
| 1582 | + nd_device_unlock(dev); |
|---|
| 1612 | 1583 | |
|---|
| 1613 | 1584 | return rc; |
|---|
| 1614 | 1585 | } |
|---|
| .. | .. |
|---|
| 1654 | 1625 | { |
|---|
| 1655 | 1626 | struct device *dev = container_of(kobj, struct device, kobj); |
|---|
| 1656 | 1627 | |
|---|
| 1657 | | - if (a == &dev_attr_resource.attr) { |
|---|
| 1658 | | - if (is_namespace_blk(dev)) |
|---|
| 1659 | | - return 0; |
|---|
| 1660 | | - return 0400; |
|---|
| 1661 | | - } |
|---|
| 1628 | + if (a == &dev_attr_resource.attr && is_namespace_blk(dev)) |
|---|
| 1629 | + return 0; |
|---|
| 1662 | 1630 | |
|---|
| 1663 | 1631 | if (is_namespace_pmem(dev) || is_namespace_blk(dev)) { |
|---|
| 1664 | 1632 | if (a == &dev_attr_size.attr) |
|---|
| .. | .. |
|---|
| 1667 | 1635 | return a->mode; |
|---|
| 1668 | 1636 | } |
|---|
| 1669 | 1637 | |
|---|
| 1670 | | - if (a == &dev_attr_nstype.attr || a == &dev_attr_size.attr |
|---|
| 1671 | | - || a == &dev_attr_holder.attr |
|---|
| 1672 | | - || a == &dev_attr_holder_class.attr |
|---|
| 1673 | | - || a == &dev_attr_force_raw.attr |
|---|
| 1674 | | - || a == &dev_attr_mode.attr) |
|---|
| 1638 | + /* base is_namespace_io() attributes */ |
|---|
| 1639 | + if (a == &dev_attr_nstype.attr || a == &dev_attr_size.attr || |
|---|
| 1640 | + a == &dev_attr_holder.attr || a == &dev_attr_holder_class.attr || |
|---|
| 1641 | + a == &dev_attr_force_raw.attr || a == &dev_attr_mode.attr || |
|---|
| 1642 | + a == &dev_attr_resource.attr) |
|---|
| 1675 | 1643 | return a->mode; |
|---|
| 1676 | 1644 | |
|---|
| 1677 | 1645 | return 0; |
|---|
| .. | .. |
|---|
| 1688 | 1656 | &nd_numa_attribute_group, |
|---|
| 1689 | 1657 | NULL, |
|---|
| 1690 | 1658 | }; |
|---|
| 1659 | + |
|---|
| 1660 | +static const struct device_type namespace_io_device_type = { |
|---|
| 1661 | + .name = "nd_namespace_io", |
|---|
| 1662 | + .release = namespace_io_release, |
|---|
| 1663 | + .groups = nd_namespace_attribute_groups, |
|---|
| 1664 | +}; |
|---|
| 1665 | + |
|---|
| 1666 | +static const struct device_type namespace_pmem_device_type = { |
|---|
| 1667 | + .name = "nd_namespace_pmem", |
|---|
| 1668 | + .release = namespace_pmem_release, |
|---|
| 1669 | + .groups = nd_namespace_attribute_groups, |
|---|
| 1670 | +}; |
|---|
| 1671 | + |
|---|
| 1672 | +static const struct device_type namespace_blk_device_type = { |
|---|
| 1673 | + .name = "nd_namespace_blk", |
|---|
| 1674 | + .release = namespace_blk_release, |
|---|
| 1675 | + .groups = nd_namespace_attribute_groups, |
|---|
| 1676 | +}; |
|---|
| 1677 | + |
|---|
| 1678 | +static bool is_namespace_pmem(const struct device *dev) |
|---|
| 1679 | +{ |
|---|
| 1680 | + return dev ? dev->type == &namespace_pmem_device_type : false; |
|---|
| 1681 | +} |
|---|
| 1682 | + |
|---|
| 1683 | +static bool is_namespace_blk(const struct device *dev) |
|---|
| 1684 | +{ |
|---|
| 1685 | + return dev ? dev->type == &namespace_blk_device_type : false; |
|---|
| 1686 | +} |
|---|
| 1687 | + |
|---|
| 1688 | +static bool is_namespace_io(const struct device *dev) |
|---|
| 1689 | +{ |
|---|
| 1690 | + return dev ? dev->type == &namespace_io_device_type : false; |
|---|
| 1691 | +} |
|---|
| 1691 | 1692 | |
|---|
| 1692 | 1693 | struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev) |
|---|
| 1693 | 1694 | { |
|---|
| .. | .. |
|---|
| 1712 | 1713 | * Flush any in-progess probes / removals in the driver |
|---|
| 1713 | 1714 | * for the raw personality of this namespace. |
|---|
| 1714 | 1715 | */ |
|---|
| 1715 | | - device_lock(&ndns->dev); |
|---|
| 1716 | | - device_unlock(&ndns->dev); |
|---|
| 1716 | + nd_device_lock(&ndns->dev); |
|---|
| 1717 | + nd_device_unlock(&ndns->dev); |
|---|
| 1717 | 1718 | if (ndns->dev.driver) { |
|---|
| 1718 | 1719 | dev_dbg(&ndns->dev, "is active, can't bind %s\n", |
|---|
| 1719 | 1720 | dev_name(dev)); |
|---|
| .. | .. |
|---|
| 1744 | 1745 | return ERR_PTR(-ENODEV); |
|---|
| 1745 | 1746 | } |
|---|
| 1746 | 1747 | |
|---|
| 1748 | + /* |
|---|
| 1749 | + * Note, alignment validation for fsdax and devdax mode |
|---|
| 1750 | + * namespaces happens in nd_pfn_validate() where infoblock |
|---|
| 1751 | + * padding parameters can be applied. |
|---|
| 1752 | + */ |
|---|
| 1753 | + if (pmem_should_map_pages(dev)) { |
|---|
| 1754 | + struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); |
|---|
| 1755 | + struct resource *res = &nsio->res; |
|---|
| 1756 | + |
|---|
| 1757 | + if (!IS_ALIGNED(res->start | (res->end + 1), |
|---|
| 1758 | + memremap_compat_align())) { |
|---|
| 1759 | + dev_err(&ndns->dev, "%pr misaligned, unable to map\n", res); |
|---|
| 1760 | + return ERR_PTR(-EOPNOTSUPP); |
|---|
| 1761 | + } |
|---|
| 1762 | + } |
|---|
| 1763 | + |
|---|
| 1747 | 1764 | if (is_namespace_pmem(&ndns->dev)) { |
|---|
| 1748 | 1765 | struct nd_namespace_pmem *nspm; |
|---|
| 1749 | 1766 | |
|---|
| .. | .. |
|---|
| 1767 | 1784 | return ndns; |
|---|
| 1768 | 1785 | } |
|---|
| 1769 | 1786 | EXPORT_SYMBOL(nvdimm_namespace_common_probe); |
|---|
| 1787 | + |
|---|
| 1788 | +int devm_namespace_enable(struct device *dev, struct nd_namespace_common *ndns, |
|---|
| 1789 | + resource_size_t size) |
|---|
| 1790 | +{ |
|---|
| 1791 | + if (is_namespace_blk(&ndns->dev)) |
|---|
| 1792 | + return 0; |
|---|
| 1793 | + return devm_nsio_enable(dev, to_nd_namespace_io(&ndns->dev), size); |
|---|
| 1794 | +} |
|---|
| 1795 | +EXPORT_SYMBOL_GPL(devm_namespace_enable); |
|---|
| 1796 | + |
|---|
| 1797 | +void devm_namespace_disable(struct device *dev, struct nd_namespace_common *ndns) |
|---|
| 1798 | +{ |
|---|
| 1799 | + if (is_namespace_blk(&ndns->dev)) |
|---|
| 1800 | + return; |
|---|
| 1801 | + devm_nsio_disable(dev, to_nd_namespace_io(&ndns->dev)); |
|---|
| 1802 | +} |
|---|
| 1803 | +EXPORT_SYMBOL_GPL(devm_namespace_disable); |
|---|
| 1770 | 1804 | |
|---|
| 1771 | 1805 | static struct device **create_namespace_io(struct nd_region *nd_region) |
|---|
| 1772 | 1806 | { |
|---|
| .. | .. |
|---|
| 1831 | 1865 | && !guid_equal(&nd_set->type_guid, |
|---|
| 1832 | 1866 | &nd_label->type_guid)) { |
|---|
| 1833 | 1867 | dev_dbg(ndd->dev, "expect type_guid %pUb got %pUb\n", |
|---|
| 1834 | | - nd_set->type_guid.b, |
|---|
| 1835 | | - nd_label->type_guid.b); |
|---|
| 1868 | + &nd_set->type_guid, |
|---|
| 1869 | + &nd_label->type_guid); |
|---|
| 1836 | 1870 | continue; |
|---|
| 1837 | 1871 | } |
|---|
| 1838 | 1872 | |
|---|
| .. | .. |
|---|
| 2087 | 2121 | } |
|---|
| 2088 | 2122 | dev_set_name(dev, "namespace%d.%d", nd_region->id, nsblk->id); |
|---|
| 2089 | 2123 | dev->parent = &nd_region->dev; |
|---|
| 2090 | | - dev->groups = nd_namespace_attribute_groups; |
|---|
| 2091 | 2124 | |
|---|
| 2092 | 2125 | return &nsblk->common.dev; |
|---|
| 2093 | 2126 | } |
|---|
| .. | .. |
|---|
| 2118 | 2151 | return NULL; |
|---|
| 2119 | 2152 | } |
|---|
| 2120 | 2153 | dev_set_name(dev, "namespace%d.%d", nd_region->id, nspm->id); |
|---|
| 2121 | | - dev->parent = &nd_region->dev; |
|---|
| 2122 | | - dev->groups = nd_namespace_attribute_groups; |
|---|
| 2123 | 2154 | nd_namespace_pmem_set_resource(nd_region, nspm, 0); |
|---|
| 2124 | 2155 | |
|---|
| 2125 | 2156 | return dev; |
|---|
| .. | .. |
|---|
| 2237 | 2268 | if (namespace_label_has(ndd, type_guid)) { |
|---|
| 2238 | 2269 | if (!guid_equal(&nd_set->type_guid, &nd_label->type_guid)) { |
|---|
| 2239 | 2270 | dev_dbg(ndd->dev, "expect type_guid %pUb got %pUb\n", |
|---|
| 2240 | | - nd_set->type_guid.b, |
|---|
| 2241 | | - nd_label->type_guid.b); |
|---|
| 2271 | + &nd_set->type_guid, |
|---|
| 2272 | + &nd_label->type_guid); |
|---|
| 2242 | 2273 | return ERR_PTR(-EAGAIN); |
|---|
| 2243 | 2274 | } |
|---|
| 2244 | 2275 | |
|---|
| .. | .. |
|---|
| 2473 | 2504 | return devs; |
|---|
| 2474 | 2505 | } |
|---|
| 2475 | 2506 | |
|---|
| 2507 | +static void deactivate_labels(void *region) |
|---|
| 2508 | +{ |
|---|
| 2509 | + struct nd_region *nd_region = region; |
|---|
| 2510 | + int i; |
|---|
| 2511 | + |
|---|
| 2512 | + for (i = 0; i < nd_region->ndr_mappings; i++) { |
|---|
| 2513 | + struct nd_mapping *nd_mapping = &nd_region->mapping[i]; |
|---|
| 2514 | + struct nvdimm_drvdata *ndd = nd_mapping->ndd; |
|---|
| 2515 | + struct nvdimm *nvdimm = nd_mapping->nvdimm; |
|---|
| 2516 | + |
|---|
| 2517 | + mutex_lock(&nd_mapping->lock); |
|---|
| 2518 | + nd_mapping_free_labels(nd_mapping); |
|---|
| 2519 | + mutex_unlock(&nd_mapping->lock); |
|---|
| 2520 | + |
|---|
| 2521 | + put_ndd(ndd); |
|---|
| 2522 | + nd_mapping->ndd = NULL; |
|---|
| 2523 | + if (ndd) |
|---|
| 2524 | + atomic_dec(&nvdimm->busy); |
|---|
| 2525 | + } |
|---|
| 2526 | +} |
|---|
| 2527 | + |
|---|
| 2476 | 2528 | static int init_active_labels(struct nd_region *nd_region) |
|---|
| 2477 | 2529 | { |
|---|
| 2478 | | - int i; |
|---|
| 2530 | + int i, rc = 0; |
|---|
| 2479 | 2531 | |
|---|
| 2480 | 2532 | for (i = 0; i < nd_region->ndr_mappings; i++) { |
|---|
| 2481 | 2533 | struct nd_mapping *nd_mapping = &nd_region->mapping[i]; |
|---|
| .. | .. |
|---|
| 2491 | 2543 | if (!ndd) { |
|---|
| 2492 | 2544 | if (test_bit(NDD_LOCKED, &nvdimm->flags)) |
|---|
| 2493 | 2545 | /* fail, label data may be unreadable */; |
|---|
| 2494 | | - else if (test_bit(NDD_ALIASING, &nvdimm->flags)) |
|---|
| 2546 | + else if (test_bit(NDD_LABELING, &nvdimm->flags)) |
|---|
| 2495 | 2547 | /* fail, labels needed to disambiguate dpa */; |
|---|
| 2496 | 2548 | else |
|---|
| 2497 | | - return 0; |
|---|
| 2549 | + continue; |
|---|
| 2498 | 2550 | |
|---|
| 2499 | 2551 | dev_err(&nd_region->dev, "%s: is %s, failing probe\n", |
|---|
| 2500 | 2552 | dev_name(&nd_mapping->nvdimm->dev), |
|---|
| 2501 | 2553 | test_bit(NDD_LOCKED, &nvdimm->flags) |
|---|
| 2502 | 2554 | ? "locked" : "disabled"); |
|---|
| 2503 | | - return -ENXIO; |
|---|
| 2555 | + rc = -ENXIO; |
|---|
| 2556 | + goto out; |
|---|
| 2504 | 2557 | } |
|---|
| 2505 | 2558 | nd_mapping->ndd = ndd; |
|---|
| 2506 | 2559 | atomic_inc(&nvdimm->busy); |
|---|
| .. | .. |
|---|
| 2517 | 2570 | if (!label_ent) |
|---|
| 2518 | 2571 | break; |
|---|
| 2519 | 2572 | label = nd_label_active(ndd, j); |
|---|
| 2573 | + if (test_bit(NDD_NOBLK, &nvdimm->flags)) { |
|---|
| 2574 | + u32 flags = __le32_to_cpu(label->flags); |
|---|
| 2575 | + |
|---|
| 2576 | + flags &= ~NSLABEL_FLAG_LOCAL; |
|---|
| 2577 | + label->flags = __cpu_to_le32(flags); |
|---|
| 2578 | + } |
|---|
| 2520 | 2579 | label_ent->label = label; |
|---|
| 2521 | 2580 | |
|---|
| 2522 | 2581 | mutex_lock(&nd_mapping->lock); |
|---|
| .. | .. |
|---|
| 2524 | 2583 | mutex_unlock(&nd_mapping->lock); |
|---|
| 2525 | 2584 | } |
|---|
| 2526 | 2585 | |
|---|
| 2527 | | - if (j >= count) |
|---|
| 2528 | | - continue; |
|---|
| 2529 | | - |
|---|
| 2530 | | - mutex_lock(&nd_mapping->lock); |
|---|
| 2531 | | - nd_mapping_free_labels(nd_mapping); |
|---|
| 2532 | | - mutex_unlock(&nd_mapping->lock); |
|---|
| 2533 | | - return -ENOMEM; |
|---|
| 2586 | + if (j < count) |
|---|
| 2587 | + break; |
|---|
| 2534 | 2588 | } |
|---|
| 2535 | 2589 | |
|---|
| 2536 | | - return 0; |
|---|
| 2590 | + if (i < nd_region->ndr_mappings) |
|---|
| 2591 | + rc = -ENOMEM; |
|---|
| 2592 | + |
|---|
| 2593 | +out: |
|---|
| 2594 | + if (rc) { |
|---|
| 2595 | + deactivate_labels(nd_region); |
|---|
| 2596 | + return rc; |
|---|
| 2597 | + } |
|---|
| 2598 | + |
|---|
| 2599 | + return devm_add_action_or_reset(&nd_region->dev, deactivate_labels, |
|---|
| 2600 | + nd_region); |
|---|
| 2537 | 2601 | } |
|---|
| 2538 | 2602 | |
|---|
| 2539 | 2603 | int nd_region_register_namespaces(struct nd_region *nd_region, int *err) |
|---|
| .. | .. |
|---|
| 2590 | 2654 | if (id < 0) |
|---|
| 2591 | 2655 | break; |
|---|
| 2592 | 2656 | dev_set_name(dev, "namespace%d.%d", nd_region->id, id); |
|---|
| 2593 | | - dev->groups = nd_namespace_attribute_groups; |
|---|
| 2594 | 2657 | nd_device_register(dev); |
|---|
| 2595 | 2658 | } |
|---|
| 2596 | 2659 | if (i) |
|---|