.. | .. |
---|
| 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) |
---|