Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm

Pull libnvdimm fixes from Dan Williams:
"Several fixes to the DSM (ACPI device specific method) marshaling
implementation.

I consider these urgent enough to send for 4.9 consideration since
they fix the kernel's handling of ARS (Address Range Scrub) commands.
Especially for platforms without machine-check-recovery capabilities,
successful execution of ARS commands enables the platform to
potentially break out of an infinite reboot problem if a media error
is present in the boot path. There is also a one line fix for a
device-dax read-only mapping regression.

Commits 9a901f5495e2 ("acpi, nfit: fix extended status translations
for ACPI DSMs") and 325896ffdf90 ("device-dax: fix private mapping
restriction, permit read-only") are true regression fixes for changes
introduced this cycle.

Commit efda1b5d87cb ("acpi, nfit, libnvdimm: fix / harden ars_status
output length handling") fixes the kernel's handling of zero-length
results, this never would have worked in the past, but we only just
recently discovered a BIOS implementation that emits this arguably
spec non-compliant result.

The remaining two commits are additional fall out from thinking
through the implications of a zero / truncated length result of the
ARS Status command.

In order to mitigate the risk that these changes introduce yet more
regressions they are backstopped by a new unit test in commit
a7de92dac9f0 ("tools/testing/nvdimm: unit test acpi_nfit_ctl()") that
mocks up inputs to acpi_nfit_ctl()"

* 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
device-dax: fix private mapping restriction, permit read-only
tools/testing/nvdimm: unit test acpi_nfit_ctl()
acpi, nfit: fix bus vs dimm confusion in xlat_status
acpi, nfit: validate ars_status output buffer size
acpi, nfit, libnvdimm: fix / harden ars_status output length handling
acpi, nfit: fix extended status translations for ACPI DSMs

+326 -28
+40 -15
drivers/acpi/nfit/core.c
··· 94 94 return to_acpi_device(acpi_desc->dev); 95 95 } 96 96 97 - static int xlat_status(void *buf, unsigned int cmd, u32 status) 97 + static int xlat_bus_status(void *buf, unsigned int cmd, u32 status) 98 98 { 99 99 struct nd_cmd_clear_error *clear_err; 100 100 struct nd_cmd_ars_status *ars_status; ··· 113 113 flags = ND_ARS_PERSISTENT | ND_ARS_VOLATILE; 114 114 if ((status >> 16 & flags) == 0) 115 115 return -ENOTTY; 116 - break; 116 + return 0; 117 117 case ND_CMD_ARS_START: 118 118 /* ARS is in progress */ 119 119 if ((status & 0xffff) == NFIT_ARS_START_BUSY) ··· 122 122 /* Command failed */ 123 123 if (status & 0xffff) 124 124 return -EIO; 125 - break; 125 + return 0; 126 126 case ND_CMD_ARS_STATUS: 127 127 ars_status = buf; 128 128 /* Command failed */ ··· 146 146 * then just continue with the returned results. 147 147 */ 148 148 if (status == NFIT_ARS_STATUS_INTR) { 149 - if (ars_status->flags & NFIT_ARS_F_OVERFLOW) 149 + if (ars_status->out_length >= 40 && (ars_status->flags 150 + & NFIT_ARS_F_OVERFLOW)) 150 151 return -ENOSPC; 151 152 return 0; 152 153 } ··· 155 154 /* Unknown status */ 156 155 if (status >> 16) 157 156 return -EIO; 158 - break; 157 + return 0; 159 158 case ND_CMD_CLEAR_ERROR: 160 159 clear_err = buf; 161 160 if (status & 0xffff) ··· 164 163 return -EIO; 165 164 if (clear_err->length > clear_err->cleared) 166 165 return clear_err->cleared; 167 - break; 166 + return 0; 168 167 default: 169 168 break; 170 169 } ··· 175 174 return 0; 176 175 } 177 176 178 - static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, 179 - struct nvdimm *nvdimm, unsigned int cmd, void *buf, 180 - unsigned int buf_len, int *cmd_rc) 177 + static int xlat_status(struct nvdimm *nvdimm, void *buf, unsigned int cmd, 178 + u32 status) 179 + { 180 + if (!nvdimm) 181 + return xlat_bus_status(buf, cmd, status); 182 + if (status) 183 + return -EIO; 184 + return 0; 185 + } 186 + 187 + int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, 188 + unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) 181 189 { 182 190 struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc); 183 191 union acpi_object in_obj, in_buf, *out_obj; ··· 308 298 309 299 for (i = 0, offset = 0; i < desc->out_num; i++) { 310 300 u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, buf, 311 - (u32 *) out_obj->buffer.pointer); 301 + (u32 *) out_obj->buffer.pointer, 302 + out_obj->buffer.length - offset); 312 303 313 304 if (offset + out_size > out_obj->buffer.length) { 314 305 dev_dbg(dev, "%s:%s output object underflow cmd: %s field: %d\n", ··· 344 333 */ 345 334 rc = buf_len - offset - in_buf.buffer.length; 346 335 if (cmd_rc) 347 - *cmd_rc = xlat_status(buf, cmd, fw_status); 336 + *cmd_rc = xlat_status(nvdimm, buf, cmd, 337 + fw_status); 348 338 } else { 349 339 dev_err(dev, "%s:%s underrun cmd: %s buf_len: %d out_len: %d\n", 350 340 __func__, dimm_name, cmd_name, buf_len, ··· 355 343 } else { 356 344 rc = 0; 357 345 if (cmd_rc) 358 - *cmd_rc = xlat_status(buf, cmd, fw_status); 346 + *cmd_rc = xlat_status(nvdimm, buf, cmd, fw_status); 359 347 } 360 348 361 349 out: ··· 363 351 364 352 return rc; 365 353 } 354 + EXPORT_SYMBOL_GPL(acpi_nfit_ctl); 366 355 367 356 static const char *spa_type_name(u16 type) 368 357 { ··· 2014 2001 return cmd_rc; 2015 2002 } 2016 2003 2017 - static int ars_status_process_records(struct nvdimm_bus *nvdimm_bus, 2004 + static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc, 2018 2005 struct nd_cmd_ars_status *ars_status) 2019 2006 { 2007 + struct nvdimm_bus *nvdimm_bus = acpi_desc->nvdimm_bus; 2020 2008 int rc; 2021 2009 u32 i; 2022 2010 2011 + /* 2012 + * First record starts at 44 byte offset from the start of the 2013 + * payload. 2014 + */ 2015 + if (ars_status->out_length < 44) 2016 + return 0; 2023 2017 for (i = 0; i < ars_status->num_records; i++) { 2018 + /* only process full records */ 2019 + if (ars_status->out_length 2020 + < 44 + sizeof(struct nd_ars_record) * (i + 1)) 2021 + break; 2024 2022 rc = nvdimm_bus_add_poison(nvdimm_bus, 2025 2023 ars_status->records[i].err_address, 2026 2024 ars_status->records[i].length); 2027 2025 if (rc) 2028 2026 return rc; 2029 2027 } 2028 + if (i < ars_status->num_records) 2029 + dev_warn(acpi_desc->dev, "detected truncated ars results\n"); 2030 2030 2031 2031 return 0; 2032 2032 } ··· 2292 2266 if (rc < 0 && rc != -ENOSPC) 2293 2267 return rc; 2294 2268 2295 - if (ars_status_process_records(acpi_desc->nvdimm_bus, 2296 - acpi_desc->ars_status)) 2269 + if (ars_status_process_records(acpi_desc, acpi_desc->ars_status)) 2297 2270 return -ENOMEM; 2298 2271 2299 2272 return 0;
+2
drivers/acpi/nfit/nfit.h
··· 240 240 int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz); 241 241 void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event); 242 242 void __acpi_nvdimm_notify(struct device *dev, u32 event); 243 + int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, 244 + unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc); 243 245 void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev); 244 246 #endif /* __NFIT_H__ */
+1 -1
drivers/dax/dax.c
··· 271 271 return -ENXIO; 272 272 273 273 /* prevent private mappings from being established */ 274 - if ((vma->vm_flags & VM_SHARED) != VM_SHARED) { 274 + if ((vma->vm_flags & VM_MAYSHARE) != VM_MAYSHARE) { 275 275 dev_info(dev, "%s: %s: fail, attempted private mapping\n", 276 276 current->comm, func); 277 277 return -EINVAL;
+20 -5
drivers/nvdimm/bus.c
··· 715 715 716 716 u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd, 717 717 const struct nd_cmd_desc *desc, int idx, const u32 *in_field, 718 - const u32 *out_field) 718 + const u32 *out_field, unsigned long remainder) 719 719 { 720 720 if (idx >= desc->out_num) 721 721 return UINT_MAX; ··· 727 727 return in_field[1]; 728 728 else if (nvdimm && cmd == ND_CMD_VENDOR && idx == 2) 729 729 return out_field[1]; 730 - else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2) 731 - return out_field[1] - 8; 732 - else if (cmd == ND_CMD_CALL) { 730 + else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2) { 731 + /* 732 + * Per table 9-276 ARS Data in ACPI 6.1, out_field[1] is 733 + * "Size of Output Buffer in bytes, including this 734 + * field." 735 + */ 736 + if (out_field[1] < 4) 737 + return 0; 738 + /* 739 + * ACPI 6.1 is ambiguous if 'status' is included in the 740 + * output size. If we encounter an output size that 741 + * overshoots the remainder by 4 bytes, assume it was 742 + * including 'status'. 743 + */ 744 + if (out_field[1] - 8 == remainder) 745 + return remainder; 746 + return out_field[1] - 4; 747 + } else if (cmd == ND_CMD_CALL) { 733 748 struct nd_cmd_pkg *pkg = (struct nd_cmd_pkg *) in_field; 734 749 735 750 return pkg->nd_size_out; ··· 891 876 /* process an output envelope */ 892 877 for (i = 0; i < desc->out_num; i++) { 893 878 u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, 894 - (u32 *) in_env, (u32 *) out_env); 879 + (u32 *) in_env, (u32 *) out_env, 0); 895 880 u32 copy; 896 881 897 882 if (out_size == UINT_MAX) {
+1 -1
include/linux/libnvdimm.h
··· 143 143 const struct nd_cmd_desc *desc, int idx, void *buf); 144 144 u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd, 145 145 const struct nd_cmd_desc *desc, int idx, const u32 *in_field, 146 - const u32 *out_field); 146 + const u32 *out_field, unsigned long remainder); 147 147 int nvdimm_bus_check_dimm_count(struct nvdimm_bus *nvdimm_bus, int dimm_count); 148 148 struct nd_region *nvdimm_pmem_region_create(struct nvdimm_bus *nvdimm_bus, 149 149 struct nd_region_desc *ndr_desc);
+1
tools/testing/nvdimm/Kbuild
··· 14 14 ldflags-y += --wrap=insert_resource 15 15 ldflags-y += --wrap=remove_resource 16 16 ldflags-y += --wrap=acpi_evaluate_object 17 + ldflags-y += --wrap=acpi_evaluate_dsm 17 18 18 19 DRIVERS := ../../../drivers 19 20 NVDIMM_SRC := $(DRIVERS)/nvdimm
+22 -1
tools/testing/nvdimm/test/iomap.c
··· 26 26 27 27 static struct iomap_ops { 28 28 nfit_test_lookup_fn nfit_test_lookup; 29 + nfit_test_evaluate_dsm_fn evaluate_dsm; 29 30 struct list_head list; 30 31 } iomap_ops = { 31 32 .list = LIST_HEAD_INIT(iomap_ops.list), 32 33 }; 33 34 34 - void nfit_test_setup(nfit_test_lookup_fn lookup) 35 + void nfit_test_setup(nfit_test_lookup_fn lookup, 36 + nfit_test_evaluate_dsm_fn evaluate) 35 37 { 36 38 iomap_ops.nfit_test_lookup = lookup; 39 + iomap_ops.evaluate_dsm = evaluate; 37 40 list_add_rcu(&iomap_ops.list, &iomap_head); 38 41 } 39 42 EXPORT_SYMBOL(nfit_test_setup); ··· 369 366 return AE_OK; 370 367 } 371 368 EXPORT_SYMBOL(__wrap_acpi_evaluate_object); 369 + 370 + union acpi_object * __wrap_acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, 371 + u64 rev, u64 func, union acpi_object *argv4) 372 + { 373 + union acpi_object *obj = ERR_PTR(-ENXIO); 374 + struct iomap_ops *ops; 375 + 376 + rcu_read_lock(); 377 + ops = list_first_or_null_rcu(&iomap_head, typeof(*ops), list); 378 + if (ops) 379 + obj = ops->evaluate_dsm(handle, uuid, rev, func, argv4); 380 + rcu_read_unlock(); 381 + 382 + if (IS_ERR(obj)) 383 + return acpi_evaluate_dsm(handle, uuid, rev, func, argv4); 384 + return obj; 385 + } 386 + EXPORT_SYMBOL(__wrap_acpi_evaluate_dsm); 372 387 373 388 MODULE_LICENSE("GPL v2");
+232 -4
tools/testing/nvdimm/test/nfit.c
··· 23 23 #include <linux/sizes.h> 24 24 #include <linux/list.h> 25 25 #include <linux/slab.h> 26 + #include <nd-core.h> 26 27 #include <nfit.h> 27 28 #include <nd.h> 28 29 #include "nfit_test.h" ··· 1507 1506 return 0; 1508 1507 } 1509 1508 1509 + static unsigned long nfit_ctl_handle; 1510 + 1511 + union acpi_object *result; 1512 + 1513 + static union acpi_object *nfit_test_evaluate_dsm(acpi_handle handle, 1514 + const u8 *uuid, u64 rev, u64 func, union acpi_object *argv4) 1515 + { 1516 + if (handle != &nfit_ctl_handle) 1517 + return ERR_PTR(-ENXIO); 1518 + 1519 + return result; 1520 + } 1521 + 1522 + static int setup_result(void *buf, size_t size) 1523 + { 1524 + result = kmalloc(sizeof(union acpi_object) + size, GFP_KERNEL); 1525 + if (!result) 1526 + return -ENOMEM; 1527 + result->package.type = ACPI_TYPE_BUFFER, 1528 + result->buffer.pointer = (void *) (result + 1); 1529 + result->buffer.length = size; 1530 + memcpy(result->buffer.pointer, buf, size); 1531 + memset(buf, 0, size); 1532 + return 0; 1533 + } 1534 + 1535 + static int nfit_ctl_test(struct device *dev) 1536 + { 1537 + int rc, cmd_rc; 1538 + struct nvdimm *nvdimm; 1539 + struct acpi_device *adev; 1540 + struct nfit_mem *nfit_mem; 1541 + struct nd_ars_record *record; 1542 + struct acpi_nfit_desc *acpi_desc; 1543 + const u64 test_val = 0x0123456789abcdefULL; 1544 + unsigned long mask, cmd_size, offset; 1545 + union { 1546 + struct nd_cmd_get_config_size cfg_size; 1547 + struct nd_cmd_ars_status ars_stat; 1548 + struct nd_cmd_ars_cap ars_cap; 1549 + char buf[sizeof(struct nd_cmd_ars_status) 1550 + + sizeof(struct nd_ars_record)]; 1551 + } cmds; 1552 + 1553 + adev = devm_kzalloc(dev, sizeof(*adev), GFP_KERNEL); 1554 + if (!adev) 1555 + return -ENOMEM; 1556 + *adev = (struct acpi_device) { 1557 + .handle = &nfit_ctl_handle, 1558 + .dev = { 1559 + .init_name = "test-adev", 1560 + }, 1561 + }; 1562 + 1563 + acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL); 1564 + if (!acpi_desc) 1565 + return -ENOMEM; 1566 + *acpi_desc = (struct acpi_nfit_desc) { 1567 + .nd_desc = { 1568 + .cmd_mask = 1UL << ND_CMD_ARS_CAP 1569 + | 1UL << ND_CMD_ARS_START 1570 + | 1UL << ND_CMD_ARS_STATUS 1571 + | 1UL << ND_CMD_CLEAR_ERROR, 1572 + .module = THIS_MODULE, 1573 + .provider_name = "ACPI.NFIT", 1574 + .ndctl = acpi_nfit_ctl, 1575 + }, 1576 + .dev = &adev->dev, 1577 + }; 1578 + 1579 + nfit_mem = devm_kzalloc(dev, sizeof(*nfit_mem), GFP_KERNEL); 1580 + if (!nfit_mem) 1581 + return -ENOMEM; 1582 + 1583 + mask = 1UL << ND_CMD_SMART | 1UL << ND_CMD_SMART_THRESHOLD 1584 + | 1UL << ND_CMD_DIMM_FLAGS | 1UL << ND_CMD_GET_CONFIG_SIZE 1585 + | 1UL << ND_CMD_GET_CONFIG_DATA | 1UL << ND_CMD_SET_CONFIG_DATA 1586 + | 1UL << ND_CMD_VENDOR; 1587 + *nfit_mem = (struct nfit_mem) { 1588 + .adev = adev, 1589 + .family = NVDIMM_FAMILY_INTEL, 1590 + .dsm_mask = mask, 1591 + }; 1592 + 1593 + nvdimm = devm_kzalloc(dev, sizeof(*nvdimm), GFP_KERNEL); 1594 + if (!nvdimm) 1595 + return -ENOMEM; 1596 + *nvdimm = (struct nvdimm) { 1597 + .provider_data = nfit_mem, 1598 + .cmd_mask = mask, 1599 + .dev = { 1600 + .init_name = "test-dimm", 1601 + }, 1602 + }; 1603 + 1604 + 1605 + /* basic checkout of a typical 'get config size' command */ 1606 + cmd_size = sizeof(cmds.cfg_size); 1607 + cmds.cfg_size = (struct nd_cmd_get_config_size) { 1608 + .status = 0, 1609 + .config_size = SZ_128K, 1610 + .max_xfer = SZ_4K, 1611 + }; 1612 + rc = setup_result(cmds.buf, cmd_size); 1613 + if (rc) 1614 + return rc; 1615 + rc = acpi_nfit_ctl(&acpi_desc->nd_desc, nvdimm, ND_CMD_GET_CONFIG_SIZE, 1616 + cmds.buf, cmd_size, &cmd_rc); 1617 + 1618 + if (rc < 0 || cmd_rc || cmds.cfg_size.status != 0 1619 + || cmds.cfg_size.config_size != SZ_128K 1620 + || cmds.cfg_size.max_xfer != SZ_4K) { 1621 + dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n", 1622 + __func__, __LINE__, rc, cmd_rc); 1623 + return -EIO; 1624 + } 1625 + 1626 + 1627 + /* test ars_status with zero output */ 1628 + cmd_size = offsetof(struct nd_cmd_ars_status, address); 1629 + cmds.ars_stat = (struct nd_cmd_ars_status) { 1630 + .out_length = 0, 1631 + }; 1632 + rc = setup_result(cmds.buf, cmd_size); 1633 + if (rc) 1634 + return rc; 1635 + rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_ARS_STATUS, 1636 + cmds.buf, cmd_size, &cmd_rc); 1637 + 1638 + if (rc < 0 || cmd_rc) { 1639 + dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n", 1640 + __func__, __LINE__, rc, cmd_rc); 1641 + return -EIO; 1642 + } 1643 + 1644 + 1645 + /* test ars_cap with benign extended status */ 1646 + cmd_size = sizeof(cmds.ars_cap); 1647 + cmds.ars_cap = (struct nd_cmd_ars_cap) { 1648 + .status = ND_ARS_PERSISTENT << 16, 1649 + }; 1650 + offset = offsetof(struct nd_cmd_ars_cap, status); 1651 + rc = setup_result(cmds.buf + offset, cmd_size - offset); 1652 + if (rc) 1653 + return rc; 1654 + rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_ARS_CAP, 1655 + cmds.buf, cmd_size, &cmd_rc); 1656 + 1657 + if (rc < 0 || cmd_rc) { 1658 + dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n", 1659 + __func__, __LINE__, rc, cmd_rc); 1660 + return -EIO; 1661 + } 1662 + 1663 + 1664 + /* test ars_status with 'status' trimmed from 'out_length' */ 1665 + cmd_size = sizeof(cmds.ars_stat) + sizeof(struct nd_ars_record); 1666 + cmds.ars_stat = (struct nd_cmd_ars_status) { 1667 + .out_length = cmd_size - 4, 1668 + }; 1669 + record = &cmds.ars_stat.records[0]; 1670 + *record = (struct nd_ars_record) { 1671 + .length = test_val, 1672 + }; 1673 + rc = setup_result(cmds.buf, cmd_size); 1674 + if (rc) 1675 + return rc; 1676 + rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_ARS_STATUS, 1677 + cmds.buf, cmd_size, &cmd_rc); 1678 + 1679 + if (rc < 0 || cmd_rc || record->length != test_val) { 1680 + dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n", 1681 + __func__, __LINE__, rc, cmd_rc); 1682 + return -EIO; 1683 + } 1684 + 1685 + 1686 + /* test ars_status with 'Output (Size)' including 'status' */ 1687 + cmd_size = sizeof(cmds.ars_stat) + sizeof(struct nd_ars_record); 1688 + cmds.ars_stat = (struct nd_cmd_ars_status) { 1689 + .out_length = cmd_size, 1690 + }; 1691 + record = &cmds.ars_stat.records[0]; 1692 + *record = (struct nd_ars_record) { 1693 + .length = test_val, 1694 + }; 1695 + rc = setup_result(cmds.buf, cmd_size); 1696 + if (rc) 1697 + return rc; 1698 + rc = acpi_nfit_ctl(&acpi_desc->nd_desc, NULL, ND_CMD_ARS_STATUS, 1699 + cmds.buf, cmd_size, &cmd_rc); 1700 + 1701 + if (rc < 0 || cmd_rc || record->length != test_val) { 1702 + dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n", 1703 + __func__, __LINE__, rc, cmd_rc); 1704 + return -EIO; 1705 + } 1706 + 1707 + 1708 + /* test extended status for get_config_size results in failure */ 1709 + cmd_size = sizeof(cmds.cfg_size); 1710 + cmds.cfg_size = (struct nd_cmd_get_config_size) { 1711 + .status = 1 << 16, 1712 + }; 1713 + rc = setup_result(cmds.buf, cmd_size); 1714 + if (rc) 1715 + return rc; 1716 + rc = acpi_nfit_ctl(&acpi_desc->nd_desc, nvdimm, ND_CMD_GET_CONFIG_SIZE, 1717 + cmds.buf, cmd_size, &cmd_rc); 1718 + 1719 + if (rc < 0 || cmd_rc >= 0) { 1720 + dev_dbg(dev, "%s: failed at: %d rc: %d cmd_rc: %d\n", 1721 + __func__, __LINE__, rc, cmd_rc); 1722 + return -EIO; 1723 + } 1724 + 1725 + return 0; 1726 + } 1727 + 1510 1728 static int nfit_test_probe(struct platform_device *pdev) 1511 1729 { 1512 1730 struct nvdimm_bus_descriptor *nd_desc; ··· 1735 1515 struct nfit_mem *nfit_mem; 1736 1516 union acpi_object *obj; 1737 1517 int rc; 1518 + 1519 + if (strcmp(dev_name(&pdev->dev), "nfit_test.0") == 0) { 1520 + rc = nfit_ctl_test(&pdev->dev); 1521 + if (rc) 1522 + return rc; 1523 + } 1738 1524 1739 1525 nfit_test = to_nfit_test(&pdev->dev); 1740 1526 ··· 1865 1639 { 1866 1640 int rc, i; 1867 1641 1868 - nfit_test_dimm = class_create(THIS_MODULE, "nfit_test_dimm"); 1869 - if (IS_ERR(nfit_test_dimm)) 1870 - return PTR_ERR(nfit_test_dimm); 1642 + nfit_test_setup(nfit_test_lookup, nfit_test_evaluate_dsm); 1871 1643 1872 - nfit_test_setup(nfit_test_lookup); 1644 + nfit_test_dimm = class_create(THIS_MODULE, "nfit_test_dimm"); 1645 + if (IS_ERR(nfit_test_dimm)) { 1646 + rc = PTR_ERR(nfit_test_dimm); 1647 + goto err_register; 1648 + } 1873 1649 1874 1650 for (i = 0; i < NUM_NFITS; i++) { 1875 1651 struct nfit_test *nfit_test;
+7 -1
tools/testing/nvdimm/test/nfit_test.h
··· 31 31 void *buf; 32 32 }; 33 33 34 + union acpi_object; 35 + typedef void *acpi_handle; 36 + 34 37 typedef struct nfit_test_resource *(*nfit_test_lookup_fn)(resource_size_t); 38 + typedef union acpi_object *(*nfit_test_evaluate_dsm_fn)(acpi_handle handle, 39 + const u8 *uuid, u64 rev, u64 func, union acpi_object *argv4); 35 40 void __iomem *__wrap_ioremap_nocache(resource_size_t offset, 36 41 unsigned long size); 37 42 void __wrap_iounmap(volatile void __iomem *addr); 38 - void nfit_test_setup(nfit_test_lookup_fn lookup); 43 + void nfit_test_setup(nfit_test_lookup_fn lookup, 44 + nfit_test_evaluate_dsm_fn evaluate); 39 45 void nfit_test_teardown(void); 40 46 struct nfit_test_resource *get_nfit_res(resource_size_t resource); 41 47 #endif