diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-02-25 21:54:53 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-02-25 21:54:53 -0500 |
commit | 3d7b365490d5f2f8ac1aaaf6cce775e6a8b7f570 (patch) | |
tree | 416a123b9eb6ae0dc9ad6df3bbbfc0c130edf195 | |
parent | 1ebe3839e66ae85e065157ba9d6f7923ad8d8fbf (diff) | |
parent | c45442055dfdeb265cc20c9eeaa9fd11a75fbf51 (diff) |
Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm fixes from Dan Williams:
- Two fixes for compatibility with the ACPI 6.1 specification.
Without these fixes multi-interface DIMMs will fail to be probed, and
address range scrub commands to find memory errors will give results
that the kernel will mis-interpret. For multi-interface DIMMs Linux
will accept either the original 6.0 implementation or 6.1.
For address range scrub we'll only support 6.1 since ACPI formalized
this DSM differently than the original example [1] implemented in
v4.2. The expectation is that production systems will only ever ship
the ACPI 6.1 address range scrub command definition.
- The wider async address range scrub work targeting 4.6 discovered
that the original synchronous implementation in 4.5 is not sizing its
return buffer correctly.
- Arnd caught that my recent fix to the size of the pfn_t flags missed
updating the flags variable used in the pmem driver.
- Toshi found that we mishandle the memremap() return value in
devm_memremap().
* 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
nvdimm: use 'u64' for pfn flags
devm_memremap: Fix error value when memremap failed
nfit: update address range scrub commands to the acpi 6.1 format
libnvdimm, tools/testing/nvdimm: fix 'ars_status' output buffer sizing
nfit: fix multi-interface dimm handling, acpi6.1 compatibility
-rw-r--r-- | drivers/acpi/nfit.c | 90 | ||||
-rw-r--r-- | drivers/nvdimm/bus.c | 20 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 2 | ||||
-rw-r--r-- | include/linux/libnvdimm.h | 3 | ||||
-rw-r--r-- | include/uapi/linux/ndctl.h | 11 | ||||
-rw-r--r-- | kernel/memremap.c | 4 | ||||
-rw-r--r-- | tools/testing/nvdimm/test/nfit.c | 8 |
7 files changed, 75 insertions, 63 deletions
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index ad6d8c6b777e..fb53db187854 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c | |||
@@ -469,37 +469,16 @@ static void nfit_mem_find_spa_bdw(struct acpi_nfit_desc *acpi_desc, | |||
469 | nfit_mem->bdw = NULL; | 469 | nfit_mem->bdw = NULL; |
470 | } | 470 | } |
471 | 471 | ||
472 | static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, | 472 | static void nfit_mem_init_bdw(struct acpi_nfit_desc *acpi_desc, |
473 | struct nfit_mem *nfit_mem, struct acpi_nfit_system_address *spa) | 473 | struct nfit_mem *nfit_mem, struct acpi_nfit_system_address *spa) |
474 | { | 474 | { |
475 | u16 dcr = __to_nfit_memdev(nfit_mem)->region_index; | 475 | u16 dcr = __to_nfit_memdev(nfit_mem)->region_index; |
476 | struct nfit_memdev *nfit_memdev; | 476 | struct nfit_memdev *nfit_memdev; |
477 | struct nfit_flush *nfit_flush; | 477 | struct nfit_flush *nfit_flush; |
478 | struct nfit_dcr *nfit_dcr; | ||
479 | struct nfit_bdw *nfit_bdw; | 478 | struct nfit_bdw *nfit_bdw; |
480 | struct nfit_idt *nfit_idt; | 479 | struct nfit_idt *nfit_idt; |
481 | u16 idt_idx, range_index; | 480 | u16 idt_idx, range_index; |
482 | 481 | ||
483 | list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) { | ||
484 | if (nfit_dcr->dcr->region_index != dcr) | ||
485 | continue; | ||
486 | nfit_mem->dcr = nfit_dcr->dcr; | ||
487 | break; | ||
488 | } | ||
489 | |||
490 | if (!nfit_mem->dcr) { | ||
491 | dev_dbg(acpi_desc->dev, "SPA %d missing:%s%s\n", | ||
492 | spa->range_index, __to_nfit_memdev(nfit_mem) | ||
493 | ? "" : " MEMDEV", nfit_mem->dcr ? "" : " DCR"); | ||
494 | return -ENODEV; | ||
495 | } | ||
496 | |||
497 | /* | ||
498 | * We've found enough to create an nvdimm, optionally | ||
499 | * find an associated BDW | ||
500 | */ | ||
501 | list_add(&nfit_mem->list, &acpi_desc->dimms); | ||
502 | |||
503 | list_for_each_entry(nfit_bdw, &acpi_desc->bdws, list) { | 482 | list_for_each_entry(nfit_bdw, &acpi_desc->bdws, list) { |
504 | if (nfit_bdw->bdw->region_index != dcr) | 483 | if (nfit_bdw->bdw->region_index != dcr) |
505 | continue; | 484 | continue; |
@@ -508,12 +487,12 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, | |||
508 | } | 487 | } |
509 | 488 | ||
510 | if (!nfit_mem->bdw) | 489 | if (!nfit_mem->bdw) |
511 | return 0; | 490 | return; |
512 | 491 | ||
513 | nfit_mem_find_spa_bdw(acpi_desc, nfit_mem); | 492 | nfit_mem_find_spa_bdw(acpi_desc, nfit_mem); |
514 | 493 | ||
515 | if (!nfit_mem->spa_bdw) | 494 | if (!nfit_mem->spa_bdw) |
516 | return 0; | 495 | return; |
517 | 496 | ||
518 | range_index = nfit_mem->spa_bdw->range_index; | 497 | range_index = nfit_mem->spa_bdw->range_index; |
519 | list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) { | 498 | list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) { |
@@ -538,8 +517,6 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, | |||
538 | } | 517 | } |
539 | break; | 518 | break; |
540 | } | 519 | } |
541 | |||
542 | return 0; | ||
543 | } | 520 | } |
544 | 521 | ||
545 | static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, | 522 | static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, |
@@ -548,7 +525,6 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, | |||
548 | struct nfit_mem *nfit_mem, *found; | 525 | struct nfit_mem *nfit_mem, *found; |
549 | struct nfit_memdev *nfit_memdev; | 526 | struct nfit_memdev *nfit_memdev; |
550 | int type = nfit_spa_type(spa); | 527 | int type = nfit_spa_type(spa); |
551 | u16 dcr; | ||
552 | 528 | ||
553 | switch (type) { | 529 | switch (type) { |
554 | case NFIT_SPA_DCR: | 530 | case NFIT_SPA_DCR: |
@@ -559,14 +535,18 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, | |||
559 | } | 535 | } |
560 | 536 | ||
561 | list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) { | 537 | list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) { |
562 | int rc; | 538 | struct nfit_dcr *nfit_dcr; |
539 | u32 device_handle; | ||
540 | u16 dcr; | ||
563 | 541 | ||
564 | if (nfit_memdev->memdev->range_index != spa->range_index) | 542 | if (nfit_memdev->memdev->range_index != spa->range_index) |
565 | continue; | 543 | continue; |
566 | found = NULL; | 544 | found = NULL; |
567 | dcr = nfit_memdev->memdev->region_index; | 545 | dcr = nfit_memdev->memdev->region_index; |
546 | device_handle = nfit_memdev->memdev->device_handle; | ||
568 | list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) | 547 | list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) |
569 | if (__to_nfit_memdev(nfit_mem)->region_index == dcr) { | 548 | if (__to_nfit_memdev(nfit_mem)->device_handle |
549 | == device_handle) { | ||
570 | found = nfit_mem; | 550 | found = nfit_mem; |
571 | break; | 551 | break; |
572 | } | 552 | } |
@@ -579,6 +559,31 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, | |||
579 | if (!nfit_mem) | 559 | if (!nfit_mem) |
580 | return -ENOMEM; | 560 | return -ENOMEM; |
581 | INIT_LIST_HEAD(&nfit_mem->list); | 561 | INIT_LIST_HEAD(&nfit_mem->list); |
562 | list_add(&nfit_mem->list, &acpi_desc->dimms); | ||
563 | } | ||
564 | |||
565 | list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) { | ||
566 | if (nfit_dcr->dcr->region_index != dcr) | ||
567 | continue; | ||
568 | /* | ||
569 | * Record the control region for the dimm. For | ||
570 | * the ACPI 6.1 case, where there are separate | ||
571 | * control regions for the pmem vs blk | ||
572 | * interfaces, be sure to record the extended | ||
573 | * blk details. | ||
574 | */ | ||
575 | if (!nfit_mem->dcr) | ||
576 | nfit_mem->dcr = nfit_dcr->dcr; | ||
577 | else if (nfit_mem->dcr->windows == 0 | ||
578 | && nfit_dcr->dcr->windows) | ||
579 | nfit_mem->dcr = nfit_dcr->dcr; | ||
580 | break; | ||
581 | } | ||
582 | |||
583 | if (dcr && !nfit_mem->dcr) { | ||
584 | dev_err(acpi_desc->dev, "SPA %d missing DCR %d\n", | ||
585 | spa->range_index, dcr); | ||
586 | return -ENODEV; | ||
582 | } | 587 | } |
583 | 588 | ||
584 | if (type == NFIT_SPA_DCR) { | 589 | if (type == NFIT_SPA_DCR) { |
@@ -595,6 +600,7 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, | |||
595 | nfit_mem->idt_dcr = nfit_idt->idt; | 600 | nfit_mem->idt_dcr = nfit_idt->idt; |
596 | break; | 601 | break; |
597 | } | 602 | } |
603 | nfit_mem_init_bdw(acpi_desc, nfit_mem, spa); | ||
598 | } else { | 604 | } else { |
599 | /* | 605 | /* |
600 | * A single dimm may belong to multiple SPA-PM | 606 | * A single dimm may belong to multiple SPA-PM |
@@ -603,13 +609,6 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, | |||
603 | */ | 609 | */ |
604 | nfit_mem->memdev_pmem = nfit_memdev->memdev; | 610 | nfit_mem->memdev_pmem = nfit_memdev->memdev; |
605 | } | 611 | } |
606 | |||
607 | if (found) | ||
608 | continue; | ||
609 | |||
610 | rc = nfit_mem_add(acpi_desc, nfit_mem, spa); | ||
611 | if (rc) | ||
612 | return rc; | ||
613 | } | 612 | } |
614 | 613 | ||
615 | return 0; | 614 | return 0; |
@@ -1504,9 +1503,7 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc, | |||
1504 | case 1: | 1503 | case 1: |
1505 | /* ARS unsupported, but we should never get here */ | 1504 | /* ARS unsupported, but we should never get here */ |
1506 | return 0; | 1505 | return 0; |
1507 | case 2: | 1506 | case 6: |
1508 | return -EINVAL; | ||
1509 | case 3: | ||
1510 | /* ARS is in progress */ | 1507 | /* ARS is in progress */ |
1511 | msleep(1000); | 1508 | msleep(1000); |
1512 | break; | 1509 | break; |
@@ -1517,13 +1514,13 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc, | |||
1517 | } | 1514 | } |
1518 | 1515 | ||
1519 | static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc, | 1516 | static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc, |
1520 | struct nd_cmd_ars_status *cmd) | 1517 | struct nd_cmd_ars_status *cmd, u32 size) |
1521 | { | 1518 | { |
1522 | int rc; | 1519 | int rc; |
1523 | 1520 | ||
1524 | while (1) { | 1521 | while (1) { |
1525 | rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, cmd, | 1522 | rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, cmd, |
1526 | sizeof(*cmd)); | 1523 | size); |
1527 | if (rc || cmd->status & 0xffff) | 1524 | if (rc || cmd->status & 0xffff) |
1528 | return -ENXIO; | 1525 | return -ENXIO; |
1529 | 1526 | ||
@@ -1538,6 +1535,8 @@ static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc, | |||
1538 | case 2: | 1535 | case 2: |
1539 | /* No ARS performed for the current boot */ | 1536 | /* No ARS performed for the current boot */ |
1540 | return 0; | 1537 | return 0; |
1538 | case 3: | ||
1539 | /* TODO: error list overflow support */ | ||
1541 | default: | 1540 | default: |
1542 | return -ENXIO; | 1541 | return -ENXIO; |
1543 | } | 1542 | } |
@@ -1581,6 +1580,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc, | |||
1581 | struct nd_cmd_ars_start *ars_start = NULL; | 1580 | struct nd_cmd_ars_start *ars_start = NULL; |
1582 | struct nd_cmd_ars_cap *ars_cap = NULL; | 1581 | struct nd_cmd_ars_cap *ars_cap = NULL; |
1583 | u64 start, len, cur, remaining; | 1582 | u64 start, len, cur, remaining; |
1583 | u32 ars_status_size; | ||
1584 | int rc; | 1584 | int rc; |
1585 | 1585 | ||
1586 | ars_cap = kzalloc(sizeof(*ars_cap), GFP_KERNEL); | 1586 | ars_cap = kzalloc(sizeof(*ars_cap), GFP_KERNEL); |
@@ -1610,14 +1610,14 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc, | |||
1610 | * Check if a full-range ARS has been run. If so, use those results | 1610 | * Check if a full-range ARS has been run. If so, use those results |
1611 | * without having to start a new ARS. | 1611 | * without having to start a new ARS. |
1612 | */ | 1612 | */ |
1613 | ars_status = kzalloc(ars_cap->max_ars_out + sizeof(*ars_status), | 1613 | ars_status_size = ars_cap->max_ars_out; |
1614 | GFP_KERNEL); | 1614 | ars_status = kzalloc(ars_status_size, GFP_KERNEL); |
1615 | if (!ars_status) { | 1615 | if (!ars_status) { |
1616 | rc = -ENOMEM; | 1616 | rc = -ENOMEM; |
1617 | goto out; | 1617 | goto out; |
1618 | } | 1618 | } |
1619 | 1619 | ||
1620 | rc = ars_get_status(nd_desc, ars_status); | 1620 | rc = ars_get_status(nd_desc, ars_status, ars_status_size); |
1621 | if (rc) | 1621 | if (rc) |
1622 | goto out; | 1622 | goto out; |
1623 | 1623 | ||
@@ -1647,7 +1647,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc, | |||
1647 | if (rc) | 1647 | if (rc) |
1648 | goto out; | 1648 | goto out; |
1649 | 1649 | ||
1650 | rc = ars_get_status(nd_desc, ars_status); | 1650 | rc = ars_get_status(nd_desc, ars_status, ars_status_size); |
1651 | if (rc) | 1651 | if (rc) |
1652 | goto out; | 1652 | goto out; |
1653 | 1653 | ||
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 7e2c43f701bc..5d28e9405f32 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c | |||
@@ -382,18 +382,18 @@ static const struct nd_cmd_desc __nd_cmd_bus_descs[] = { | |||
382 | [ND_CMD_ARS_CAP] = { | 382 | [ND_CMD_ARS_CAP] = { |
383 | .in_num = 2, | 383 | .in_num = 2, |
384 | .in_sizes = { 8, 8, }, | 384 | .in_sizes = { 8, 8, }, |
385 | .out_num = 2, | 385 | .out_num = 4, |
386 | .out_sizes = { 4, 4, }, | 386 | .out_sizes = { 4, 4, 4, 4, }, |
387 | }, | 387 | }, |
388 | [ND_CMD_ARS_START] = { | 388 | [ND_CMD_ARS_START] = { |
389 | .in_num = 4, | 389 | .in_num = 5, |
390 | .in_sizes = { 8, 8, 2, 6, }, | 390 | .in_sizes = { 8, 8, 2, 1, 5, }, |
391 | .out_num = 1, | 391 | .out_num = 2, |
392 | .out_sizes = { 4, }, | 392 | .out_sizes = { 4, 4, }, |
393 | }, | 393 | }, |
394 | [ND_CMD_ARS_STATUS] = { | 394 | [ND_CMD_ARS_STATUS] = { |
395 | .out_num = 2, | 395 | .out_num = 3, |
396 | .out_sizes = { 4, UINT_MAX, }, | 396 | .out_sizes = { 4, 4, UINT_MAX, }, |
397 | }, | 397 | }, |
398 | }; | 398 | }; |
399 | 399 | ||
@@ -442,8 +442,8 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd, | |||
442 | return in_field[1]; | 442 | return in_field[1]; |
443 | else if (nvdimm && cmd == ND_CMD_VENDOR && idx == 2) | 443 | else if (nvdimm && cmd == ND_CMD_VENDOR && idx == 2) |
444 | return out_field[1]; | 444 | return out_field[1]; |
445 | else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 1) | 445 | else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2) |
446 | return ND_CMD_ARS_STATUS_MAX; | 446 | return out_field[1] - 8; |
447 | 447 | ||
448 | return UINT_MAX; | 448 | return UINT_MAX; |
449 | } | 449 | } |
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 7edf31671dab..8d0b54670184 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c | |||
@@ -41,7 +41,7 @@ struct pmem_device { | |||
41 | phys_addr_t phys_addr; | 41 | phys_addr_t phys_addr; |
42 | /* when non-zero this device is hosting a 'pfn' instance */ | 42 | /* when non-zero this device is hosting a 'pfn' instance */ |
43 | phys_addr_t data_offset; | 43 | phys_addr_t data_offset; |
44 | unsigned long pfn_flags; | 44 | u64 pfn_flags; |
45 | void __pmem *virt_addr; | 45 | void __pmem *virt_addr; |
46 | size_t size; | 46 | size_t size; |
47 | struct badblocks bb; | 47 | struct badblocks bb; |
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h index bed40dff0e86..141ffdd59960 100644 --- a/include/linux/libnvdimm.h +++ b/include/linux/libnvdimm.h | |||
@@ -26,9 +26,8 @@ enum { | |||
26 | 26 | ||
27 | /* need to set a limit somewhere, but yes, this is likely overkill */ | 27 | /* need to set a limit somewhere, but yes, this is likely overkill */ |
28 | ND_IOCTL_MAX_BUFLEN = SZ_4M, | 28 | ND_IOCTL_MAX_BUFLEN = SZ_4M, |
29 | ND_CMD_MAX_ELEM = 4, | 29 | ND_CMD_MAX_ELEM = 5, |
30 | ND_CMD_MAX_ENVELOPE = 16, | 30 | ND_CMD_MAX_ENVELOPE = 16, |
31 | ND_CMD_ARS_STATUS_MAX = SZ_4K, | ||
32 | ND_MAX_MAPPINGS = 32, | 31 | ND_MAX_MAPPINGS = 32, |
33 | 32 | ||
34 | /* region flag indicating to direct-map persistent memory by default */ | 33 | /* region flag indicating to direct-map persistent memory by default */ |
diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h index 5b4a4be06e2b..cc68b92124d4 100644 --- a/include/uapi/linux/ndctl.h +++ b/include/uapi/linux/ndctl.h | |||
@@ -66,14 +66,18 @@ struct nd_cmd_ars_cap { | |||
66 | __u64 length; | 66 | __u64 length; |
67 | __u32 status; | 67 | __u32 status; |
68 | __u32 max_ars_out; | 68 | __u32 max_ars_out; |
69 | __u32 clear_err_unit; | ||
70 | __u32 reserved; | ||
69 | } __packed; | 71 | } __packed; |
70 | 72 | ||
71 | struct nd_cmd_ars_start { | 73 | struct nd_cmd_ars_start { |
72 | __u64 address; | 74 | __u64 address; |
73 | __u64 length; | 75 | __u64 length; |
74 | __u16 type; | 76 | __u16 type; |
75 | __u8 reserved[6]; | 77 | __u8 flags; |
78 | __u8 reserved[5]; | ||
76 | __u32 status; | 79 | __u32 status; |
80 | __u32 scrub_time; | ||
77 | } __packed; | 81 | } __packed; |
78 | 82 | ||
79 | struct nd_cmd_ars_status { | 83 | struct nd_cmd_ars_status { |
@@ -81,11 +85,14 @@ struct nd_cmd_ars_status { | |||
81 | __u32 out_length; | 85 | __u32 out_length; |
82 | __u64 address; | 86 | __u64 address; |
83 | __u64 length; | 87 | __u64 length; |
88 | __u64 restart_address; | ||
89 | __u64 restart_length; | ||
84 | __u16 type; | 90 | __u16 type; |
91 | __u16 flags; | ||
85 | __u32 num_records; | 92 | __u32 num_records; |
86 | struct nd_ars_record { | 93 | struct nd_ars_record { |
87 | __u32 handle; | 94 | __u32 handle; |
88 | __u32 flags; | 95 | __u32 reserved; |
89 | __u64 err_address; | 96 | __u64 err_address; |
90 | __u64 length; | 97 | __u64 length; |
91 | } __packed records[0]; | 98 | } __packed records[0]; |
diff --git a/kernel/memremap.c b/kernel/memremap.c index 7a1b5c3ef14e..b981a7b023f0 100644 --- a/kernel/memremap.c +++ b/kernel/memremap.c | |||
@@ -136,8 +136,10 @@ void *devm_memremap(struct device *dev, resource_size_t offset, | |||
136 | if (addr) { | 136 | if (addr) { |
137 | *ptr = addr; | 137 | *ptr = addr; |
138 | devres_add(dev, ptr); | 138 | devres_add(dev, ptr); |
139 | } else | 139 | } else { |
140 | devres_free(ptr); | 140 | devres_free(ptr); |
141 | return ERR_PTR(-ENXIO); | ||
142 | } | ||
141 | 143 | ||
142 | return addr; | 144 | return addr; |
143 | } | 145 | } |
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 90bd2ea41032..b3281dcd4a5d 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
@@ -217,13 +217,16 @@ static int nfit_test_cmd_set_config_data(struct nd_cmd_set_config_hdr *nd_cmd, | |||
217 | return rc; | 217 | return rc; |
218 | } | 218 | } |
219 | 219 | ||
220 | #define NFIT_TEST_ARS_RECORDS 4 | ||
221 | |||
220 | static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd, | 222 | static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd, |
221 | unsigned int buf_len) | 223 | unsigned int buf_len) |
222 | { | 224 | { |
223 | if (buf_len < sizeof(*nd_cmd)) | 225 | if (buf_len < sizeof(*nd_cmd)) |
224 | return -EINVAL; | 226 | return -EINVAL; |
225 | 227 | ||
226 | nd_cmd->max_ars_out = 256; | 228 | nd_cmd->max_ars_out = sizeof(struct nd_cmd_ars_status) |
229 | + NFIT_TEST_ARS_RECORDS * sizeof(struct nd_ars_record); | ||
227 | nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16; | 230 | nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16; |
228 | 231 | ||
229 | return 0; | 232 | return 0; |
@@ -246,7 +249,8 @@ static int nfit_test_cmd_ars_status(struct nd_cmd_ars_status *nd_cmd, | |||
246 | if (buf_len < sizeof(*nd_cmd)) | 249 | if (buf_len < sizeof(*nd_cmd)) |
247 | return -EINVAL; | 250 | return -EINVAL; |
248 | 251 | ||
249 | nd_cmd->out_length = 256; | 252 | nd_cmd->out_length = sizeof(struct nd_cmd_ars_status); |
253 | /* TODO: emit error records */ | ||
250 | nd_cmd->num_records = 0; | 254 | nd_cmd->num_records = 0; |
251 | nd_cmd->address = 0; | 255 | nd_cmd->address = 0; |
252 | nd_cmd->length = -1ULL; | 256 | nd_cmd->length = -1ULL; |