Skip to content

Commit 6b577c9

Browse files
Linda Knippersdjbw
authored andcommitted
nfit: Adjust for different _FIT and NFIT headers
When support for _FIT was added, the code presumed that the data returned by the _FIT method is identical to the NFIT table, which starts with an acpi_table_header. However, the _FIT is defined to return a data in the format of a series of NFIT type structure entries and as a method, has an acpi_object header rather tahn an acpi_table_header. To address the differences, explicitly save the acpi_table_header from the NFIT, since it is accessible through /sys, and change the nfit pointer in the acpi_desc structure to point to the table entries rather than the headers. Reported-by: Jeff Moyer (jmoyer@redhat.com> Signed-off-by: Linda Knippers <linda.knippers@hpe.com> Acked-by: Vishal Verma <vishal.l.verma@intel.com> [vishal: fix up unit test for new header assumptions] Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent ff5a55f commit 6b577c9

3 files changed

Lines changed: 52 additions & 47 deletions

File tree

drivers/acpi/nfit.c

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ static ssize_t revision_show(struct device *dev,
661661
struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
662662
struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
663663

664-
return sprintf(buf, "%d\n", acpi_desc->nfit->header.revision);
664+
return sprintf(buf, "%d\n", acpi_desc->acpi_header.revision);
665665
}
666666
static DEVICE_ATTR_RO(revision);
667667

@@ -1658,7 +1658,6 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz)
16581658

16591659
data = (u8 *) acpi_desc->nfit;
16601660
end = data + sz;
1661-
data += sizeof(struct acpi_table_nfit);
16621661
while (!IS_ERR_OR_NULL(data))
16631662
data = add_table(acpi_desc, &prev, data, end);
16641663

@@ -1754,13 +1753,29 @@ static int acpi_nfit_add(struct acpi_device *adev)
17541753
return PTR_ERR(acpi_desc);
17551754
}
17561755

1757-
acpi_desc->nfit = (struct acpi_table_nfit *) tbl;
1756+
/*
1757+
* Save the acpi header for later and then skip it,
1758+
* making nfit point to the first nfit table header.
1759+
*/
1760+
acpi_desc->acpi_header = *tbl;
1761+
acpi_desc->nfit = (void *) tbl + sizeof(struct acpi_table_nfit);
1762+
sz -= sizeof(struct acpi_table_nfit);
17581763

17591764
/* Evaluate _FIT and override with that if present */
17601765
status = acpi_evaluate_object(adev->handle, "_FIT", NULL, &buf);
17611766
if (ACPI_SUCCESS(status) && buf.length > 0) {
1762-
acpi_desc->nfit = (struct acpi_table_nfit *)buf.pointer;
1763-
sz = buf.length;
1767+
union acpi_object *obj;
1768+
/*
1769+
* Adjust for the acpi_object header of the _FIT
1770+
*/
1771+
obj = buf.pointer;
1772+
if (obj->type == ACPI_TYPE_BUFFER) {
1773+
acpi_desc->nfit =
1774+
(struct acpi_nfit_header *)obj->buffer.pointer;
1775+
sz = obj->buffer.length;
1776+
} else
1777+
dev_dbg(dev, "%s invalid type %d, ignoring _FIT\n",
1778+
__func__, (int) obj->type);
17641779
}
17651780

17661781
rc = acpi_nfit_init(acpi_desc, sz);
@@ -1783,7 +1798,8 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
17831798
{
17841799
struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(&adev->dev);
17851800
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
1786-
struct acpi_table_nfit *nfit_saved;
1801+
struct acpi_nfit_header *nfit_saved;
1802+
union acpi_object *obj;
17871803
struct device *dev = &adev->dev;
17881804
acpi_status status;
17891805
int ret;
@@ -1814,12 +1830,19 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
18141830
}
18151831

18161832
nfit_saved = acpi_desc->nfit;
1817-
acpi_desc->nfit = (struct acpi_table_nfit *)buf.pointer;
1818-
ret = acpi_nfit_init(acpi_desc, buf.length);
1819-
if (ret) {
1820-
/* Merge failed, restore old nfit, and exit */
1821-
acpi_desc->nfit = nfit_saved;
1822-
dev_err(dev, "failed to merge updated NFIT\n");
1833+
obj = buf.pointer;
1834+
if (obj->type == ACPI_TYPE_BUFFER) {
1835+
acpi_desc->nfit =
1836+
(struct acpi_nfit_header *)obj->buffer.pointer;
1837+
ret = acpi_nfit_init(acpi_desc, obj->buffer.length);
1838+
if (ret) {
1839+
/* Merge failed, restore old nfit, and exit */
1840+
acpi_desc->nfit = nfit_saved;
1841+
dev_err(dev, "failed to merge updated NFIT\n");
1842+
}
1843+
} else {
1844+
/* Bad _FIT, restore old nfit */
1845+
dev_err(dev, "Invalid _FIT\n");
18231846
}
18241847
kfree(buf.pointer);
18251848

drivers/acpi/nfit.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ struct nfit_mem {
9696

9797
struct acpi_nfit_desc {
9898
struct nvdimm_bus_descriptor nd_desc;
99-
struct acpi_table_nfit *nfit;
99+
struct acpi_table_header acpi_header;
100+
struct acpi_nfit_header *nfit;
100101
struct mutex spa_map_mutex;
101102
struct mutex init_mutex;
102103
struct list_head spa_maps;

tools/testing/nvdimm/test/nfit.c

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,7 @@ static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr)
420420

421421
static int nfit_test0_alloc(struct nfit_test *t)
422422
{
423-
size_t nfit_size = sizeof(struct acpi_table_nfit)
424-
+ sizeof(struct acpi_nfit_system_address) * NUM_SPA
423+
size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA
425424
+ sizeof(struct acpi_nfit_memory_map) * NUM_MEM
426425
+ sizeof(struct acpi_nfit_control_region) * NUM_DCR
427426
+ sizeof(struct acpi_nfit_data_region) * NUM_BDW
@@ -471,8 +470,7 @@ static int nfit_test0_alloc(struct nfit_test *t)
471470

472471
static int nfit_test1_alloc(struct nfit_test *t)
473472
{
474-
size_t nfit_size = sizeof(struct acpi_table_nfit)
475-
+ sizeof(struct acpi_nfit_system_address)
473+
size_t nfit_size = sizeof(struct acpi_nfit_system_address)
476474
+ sizeof(struct acpi_nfit_memory_map)
477475
+ sizeof(struct acpi_nfit_control_region);
478476

@@ -488,39 +486,24 @@ static int nfit_test1_alloc(struct nfit_test *t)
488486
return 0;
489487
}
490488

491-
static void nfit_test_init_header(struct acpi_table_nfit *nfit, size_t size)
492-
{
493-
memcpy(nfit->header.signature, ACPI_SIG_NFIT, 4);
494-
nfit->header.length = size;
495-
nfit->header.revision = 1;
496-
memcpy(nfit->header.oem_id, "LIBND", 6);
497-
memcpy(nfit->header.oem_table_id, "TEST", 5);
498-
nfit->header.oem_revision = 1;
499-
memcpy(nfit->header.asl_compiler_id, "TST", 4);
500-
nfit->header.asl_compiler_revision = 1;
501-
}
502-
503489
static void nfit_test0_setup(struct nfit_test *t)
504490
{
505491
struct nvdimm_bus_descriptor *nd_desc;
506492
struct acpi_nfit_desc *acpi_desc;
507493
struct acpi_nfit_memory_map *memdev;
508494
void *nfit_buf = t->nfit_buf;
509-
size_t size = t->nfit_size;
510495
struct acpi_nfit_system_address *spa;
511496
struct acpi_nfit_control_region *dcr;
512497
struct acpi_nfit_data_region *bdw;
513498
struct acpi_nfit_flush_address *flush;
514499
unsigned int offset;
515500

516-
nfit_test_init_header(nfit_buf, size);
517-
518501
/*
519502
* spa0 (interleave first half of dimm0 and dimm1, note storage
520503
* does not actually alias the related block-data-window
521504
* regions)
522505
*/
523-
spa = nfit_buf + sizeof(struct acpi_table_nfit);
506+
spa = nfit_buf;
524507
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
525508
spa->header.length = sizeof(*spa);
526509
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16);
@@ -533,7 +516,7 @@ static void nfit_test0_setup(struct nfit_test *t)
533516
* does not actually alias the related block-data-window
534517
* regions)
535518
*/
536-
spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa);
519+
spa = nfit_buf + sizeof(*spa);
537520
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
538521
spa->header.length = sizeof(*spa);
539522
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16);
@@ -542,7 +525,7 @@ static void nfit_test0_setup(struct nfit_test *t)
542525
spa->length = SPA1_SIZE;
543526

544527
/* spa2 (dcr0) dimm0 */
545-
spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 2;
528+
spa = nfit_buf + sizeof(*spa) * 2;
546529
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
547530
spa->header.length = sizeof(*spa);
548531
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
@@ -551,7 +534,7 @@ static void nfit_test0_setup(struct nfit_test *t)
551534
spa->length = DCR_SIZE;
552535

553536
/* spa3 (dcr1) dimm1 */
554-
spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 3;
537+
spa = nfit_buf + sizeof(*spa) * 3;
555538
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
556539
spa->header.length = sizeof(*spa);
557540
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
@@ -560,7 +543,7 @@ static void nfit_test0_setup(struct nfit_test *t)
560543
spa->length = DCR_SIZE;
561544

562545
/* spa4 (dcr2) dimm2 */
563-
spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 4;
546+
spa = nfit_buf + sizeof(*spa) * 4;
564547
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
565548
spa->header.length = sizeof(*spa);
566549
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
@@ -569,7 +552,7 @@ static void nfit_test0_setup(struct nfit_test *t)
569552
spa->length = DCR_SIZE;
570553

571554
/* spa5 (dcr3) dimm3 */
572-
spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 5;
555+
spa = nfit_buf + sizeof(*spa) * 5;
573556
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
574557
spa->header.length = sizeof(*spa);
575558
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
@@ -578,7 +561,7 @@ static void nfit_test0_setup(struct nfit_test *t)
578561
spa->length = DCR_SIZE;
579562

580563
/* spa6 (bdw for dcr0) dimm0 */
581-
spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 6;
564+
spa = nfit_buf + sizeof(*spa) * 6;
582565
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
583566
spa->header.length = sizeof(*spa);
584567
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
@@ -587,7 +570,7 @@ static void nfit_test0_setup(struct nfit_test *t)
587570
spa->length = DIMM_SIZE;
588571

589572
/* spa7 (bdw for dcr1) dimm1 */
590-
spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 7;
573+
spa = nfit_buf + sizeof(*spa) * 7;
591574
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
592575
spa->header.length = sizeof(*spa);
593576
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
@@ -596,7 +579,7 @@ static void nfit_test0_setup(struct nfit_test *t)
596579
spa->length = DIMM_SIZE;
597580

598581
/* spa8 (bdw for dcr2) dimm2 */
599-
spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 8;
582+
spa = nfit_buf + sizeof(*spa) * 8;
600583
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
601584
spa->header.length = sizeof(*spa);
602585
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
@@ -605,15 +588,15 @@ static void nfit_test0_setup(struct nfit_test *t)
605588
spa->length = DIMM_SIZE;
606589

607590
/* spa9 (bdw for dcr3) dimm3 */
608-
spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 9;
591+
spa = nfit_buf + sizeof(*spa) * 9;
609592
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
610593
spa->header.length = sizeof(*spa);
611594
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
612595
spa->range_index = 9+1;
613596
spa->address = t->dimm_dma[3];
614597
spa->length = DIMM_SIZE;
615598

616-
offset = sizeof(struct acpi_table_nfit) + sizeof(*spa) * 10;
599+
offset = sizeof(*spa) * 10;
617600
/* mem-region0 (spa0, dimm0) */
618601
memdev = nfit_buf + offset;
619602
memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
@@ -1100,15 +1083,13 @@ static void nfit_test0_setup(struct nfit_test *t)
11001083

11011084
static void nfit_test1_setup(struct nfit_test *t)
11021085
{
1103-
size_t size = t->nfit_size, offset;
1086+
size_t offset;
11041087
void *nfit_buf = t->nfit_buf;
11051088
struct acpi_nfit_memory_map *memdev;
11061089
struct acpi_nfit_control_region *dcr;
11071090
struct acpi_nfit_system_address *spa;
11081091

1109-
nfit_test_init_header(nfit_buf, size);
1110-
1111-
offset = sizeof(struct acpi_table_nfit);
1092+
offset = 0;
11121093
/* spa0 (flat range with no bdw aliasing) */
11131094
spa = nfit_buf + offset;
11141095
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;

0 commit comments

Comments
 (0)