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:

- NFIT parsing regression fixes from Linda. The nvdimm hot-add
implementation merged in 4.4-rc1 interpreted the specification in a
way that breaks actual HPE platforms. We are also closing the loop
with the ACPI Working Group to get this clarification added to the
spec.

- Andy pointed out that his laptop without nvdimm resources is loading
the e820-nvdimm module by default, fix that up to only load the
module when an e820-type-12 range is present.

* 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
nfit: Adjust for different _FIT and NFIT headers
nfit: Fix the check for a successful NFIT merge
nfit: Account for table size length variation
libnvdimm, e820: skip module loading when no type-12

+76 -53
+12
arch/x86/kernel/pmem.c
··· 4 4 */ 5 5 #include <linux/platform_device.h> 6 6 #include <linux/module.h> 7 + #include <linux/ioport.h> 8 + 9 + static int found(u64 start, u64 end, void *data) 10 + { 11 + return 1; 12 + } 7 13 8 14 static __init int register_e820_pmem(void) 9 15 { 16 + char *pmem = "Persistent Memory (legacy)"; 10 17 struct platform_device *pdev; 18 + int rc; 19 + 20 + rc = walk_iomem_res(pmem, IORESOURCE_MEM, 0, -1, NULL, found); 21 + if (rc <= 0) 22 + return 0; 11 23 12 24 /* 13 25 * See drivers/nvdimm/e820.c for the implementation, this is
+47 -18
drivers/acpi/nfit.c
··· 233 233 struct nfit_table_prev *prev, 234 234 struct acpi_nfit_system_address *spa) 235 235 { 236 + size_t length = min_t(size_t, sizeof(*spa), spa->header.length); 236 237 struct device *dev = acpi_desc->dev; 237 238 struct nfit_spa *nfit_spa; 238 239 239 240 list_for_each_entry(nfit_spa, &prev->spas, list) { 240 - if (memcmp(nfit_spa->spa, spa, sizeof(*spa)) == 0) { 241 + if (memcmp(nfit_spa->spa, spa, length) == 0) { 241 242 list_move_tail(&nfit_spa->list, &acpi_desc->spas); 242 243 return true; 243 244 } ··· 260 259 struct nfit_table_prev *prev, 261 260 struct acpi_nfit_memory_map *memdev) 262 261 { 262 + size_t length = min_t(size_t, sizeof(*memdev), memdev->header.length); 263 263 struct device *dev = acpi_desc->dev; 264 264 struct nfit_memdev *nfit_memdev; 265 265 266 266 list_for_each_entry(nfit_memdev, &prev->memdevs, list) 267 - if (memcmp(nfit_memdev->memdev, memdev, sizeof(*memdev)) == 0) { 267 + if (memcmp(nfit_memdev->memdev, memdev, length) == 0) { 268 268 list_move_tail(&nfit_memdev->list, &acpi_desc->memdevs); 269 269 return true; 270 270 } ··· 286 284 struct nfit_table_prev *prev, 287 285 struct acpi_nfit_control_region *dcr) 288 286 { 287 + size_t length = min_t(size_t, sizeof(*dcr), dcr->header.length); 289 288 struct device *dev = acpi_desc->dev; 290 289 struct nfit_dcr *nfit_dcr; 291 290 292 291 list_for_each_entry(nfit_dcr, &prev->dcrs, list) 293 - if (memcmp(nfit_dcr->dcr, dcr, sizeof(*dcr)) == 0) { 292 + if (memcmp(nfit_dcr->dcr, dcr, length) == 0) { 294 293 list_move_tail(&nfit_dcr->list, &acpi_desc->dcrs); 295 294 return true; 296 295 } ··· 311 308 struct nfit_table_prev *prev, 312 309 struct acpi_nfit_data_region *bdw) 313 310 { 311 + size_t length = min_t(size_t, sizeof(*bdw), bdw->header.length); 314 312 struct device *dev = acpi_desc->dev; 315 313 struct nfit_bdw *nfit_bdw; 316 314 317 315 list_for_each_entry(nfit_bdw, &prev->bdws, list) 318 - if (memcmp(nfit_bdw->bdw, bdw, sizeof(*bdw)) == 0) { 316 + if (memcmp(nfit_bdw->bdw, bdw, length) == 0) { 319 317 list_move_tail(&nfit_bdw->list, &acpi_desc->bdws); 320 318 return true; 321 319 } ··· 336 332 struct nfit_table_prev *prev, 337 333 struct acpi_nfit_interleave *idt) 338 334 { 335 + size_t length = min_t(size_t, sizeof(*idt), idt->header.length); 339 336 struct device *dev = acpi_desc->dev; 340 337 struct nfit_idt *nfit_idt; 341 338 342 339 list_for_each_entry(nfit_idt, &prev->idts, list) 343 - if (memcmp(nfit_idt->idt, idt, sizeof(*idt)) == 0) { 340 + if (memcmp(nfit_idt->idt, idt, length) == 0) { 344 341 list_move_tail(&nfit_idt->list, &acpi_desc->idts); 345 342 return true; 346 343 } ··· 361 356 struct nfit_table_prev *prev, 362 357 struct acpi_nfit_flush_address *flush) 363 358 { 359 + size_t length = min_t(size_t, sizeof(*flush), flush->header.length); 364 360 struct device *dev = acpi_desc->dev; 365 361 struct nfit_flush *nfit_flush; 366 362 367 363 list_for_each_entry(nfit_flush, &prev->flushes, list) 368 - if (memcmp(nfit_flush->flush, flush, sizeof(*flush)) == 0) { 364 + if (memcmp(nfit_flush->flush, flush, length) == 0) { 369 365 list_move_tail(&nfit_flush->list, &acpi_desc->flushes); 370 366 return true; 371 367 } ··· 661 655 struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus); 662 656 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); 663 657 664 - return sprintf(buf, "%d\n", acpi_desc->nfit->header.revision); 658 + return sprintf(buf, "%d\n", acpi_desc->acpi_header.revision); 665 659 } 666 660 static DEVICE_ATTR_RO(revision); 667 661 ··· 1658 1652 1659 1653 data = (u8 *) acpi_desc->nfit; 1660 1654 end = data + sz; 1661 - data += sizeof(struct acpi_table_nfit); 1662 1655 while (!IS_ERR_OR_NULL(data)) 1663 1656 data = add_table(acpi_desc, &prev, data, end); 1664 1657 ··· 1753 1748 return PTR_ERR(acpi_desc); 1754 1749 } 1755 1750 1756 - acpi_desc->nfit = (struct acpi_table_nfit *) tbl; 1751 + /* 1752 + * Save the acpi header for later and then skip it, 1753 + * making nfit point to the first nfit table header. 1754 + */ 1755 + acpi_desc->acpi_header = *tbl; 1756 + acpi_desc->nfit = (void *) tbl + sizeof(struct acpi_table_nfit); 1757 + sz -= sizeof(struct acpi_table_nfit); 1757 1758 1758 1759 /* Evaluate _FIT and override with that if present */ 1759 1760 status = acpi_evaluate_object(adev->handle, "_FIT", NULL, &buf); 1760 1761 if (ACPI_SUCCESS(status) && buf.length > 0) { 1761 - acpi_desc->nfit = (struct acpi_table_nfit *)buf.pointer; 1762 - sz = buf.length; 1762 + union acpi_object *obj; 1763 + /* 1764 + * Adjust for the acpi_object header of the _FIT 1765 + */ 1766 + obj = buf.pointer; 1767 + if (obj->type == ACPI_TYPE_BUFFER) { 1768 + acpi_desc->nfit = 1769 + (struct acpi_nfit_header *)obj->buffer.pointer; 1770 + sz = obj->buffer.length; 1771 + } else 1772 + dev_dbg(dev, "%s invalid type %d, ignoring _FIT\n", 1773 + __func__, (int) obj->type); 1763 1774 } 1764 1775 1765 1776 rc = acpi_nfit_init(acpi_desc, sz); ··· 1798 1777 { 1799 1778 struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(&adev->dev); 1800 1779 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 1801 - struct acpi_table_nfit *nfit_saved; 1780 + struct acpi_nfit_header *nfit_saved; 1781 + union acpi_object *obj; 1802 1782 struct device *dev = &adev->dev; 1803 1783 acpi_status status; 1804 1784 int ret; ··· 1830 1808 } 1831 1809 1832 1810 nfit_saved = acpi_desc->nfit; 1833 - acpi_desc->nfit = (struct acpi_table_nfit *)buf.pointer; 1834 - ret = acpi_nfit_init(acpi_desc, buf.length); 1835 - if (!ret) { 1836 - /* Merge failed, restore old nfit, and exit */ 1837 - acpi_desc->nfit = nfit_saved; 1838 - dev_err(dev, "failed to merge updated NFIT\n"); 1811 + obj = buf.pointer; 1812 + if (obj->type == ACPI_TYPE_BUFFER) { 1813 + acpi_desc->nfit = 1814 + (struct acpi_nfit_header *)obj->buffer.pointer; 1815 + ret = acpi_nfit_init(acpi_desc, obj->buffer.length); 1816 + if (ret) { 1817 + /* Merge failed, restore old nfit, and exit */ 1818 + acpi_desc->nfit = nfit_saved; 1819 + dev_err(dev, "failed to merge updated NFIT\n"); 1820 + } 1821 + } else { 1822 + /* Bad _FIT, restore old nfit */ 1823 + dev_err(dev, "Invalid _FIT\n"); 1839 1824 } 1840 1825 kfree(buf.pointer); 1841 1826
+2 -1
drivers/acpi/nfit.h
··· 96 96 97 97 struct acpi_nfit_desc { 98 98 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; 100 101 struct mutex spa_map_mutex; 101 102 struct mutex init_mutex; 102 103 struct list_head spa_maps;
+15 -34
tools/testing/nvdimm/test/nfit.c
··· 420 420 421 421 static int nfit_test0_alloc(struct nfit_test *t) 422 422 { 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 425 424 + sizeof(struct acpi_nfit_memory_map) * NUM_MEM 426 425 + sizeof(struct acpi_nfit_control_region) * NUM_DCR 427 426 + sizeof(struct acpi_nfit_data_region) * NUM_BDW ··· 470 471 471 472 static int nfit_test1_alloc(struct nfit_test *t) 472 473 { 473 - size_t nfit_size = sizeof(struct acpi_table_nfit) 474 - + sizeof(struct acpi_nfit_system_address) 474 + size_t nfit_size = sizeof(struct acpi_nfit_system_address) 475 475 + sizeof(struct acpi_nfit_memory_map) 476 476 + sizeof(struct acpi_nfit_control_region); 477 477 ··· 486 488 return 0; 487 489 } 488 490 489 - static void nfit_test_init_header(struct acpi_table_nfit *nfit, size_t size) 490 - { 491 - memcpy(nfit->header.signature, ACPI_SIG_NFIT, 4); 492 - nfit->header.length = size; 493 - nfit->header.revision = 1; 494 - memcpy(nfit->header.oem_id, "LIBND", 6); 495 - memcpy(nfit->header.oem_table_id, "TEST", 5); 496 - nfit->header.oem_revision = 1; 497 - memcpy(nfit->header.asl_compiler_id, "TST", 4); 498 - nfit->header.asl_compiler_revision = 1; 499 - } 500 - 501 491 static void nfit_test0_setup(struct nfit_test *t) 502 492 { 503 493 struct nvdimm_bus_descriptor *nd_desc; 504 494 struct acpi_nfit_desc *acpi_desc; 505 495 struct acpi_nfit_memory_map *memdev; 506 496 void *nfit_buf = t->nfit_buf; 507 - size_t size = t->nfit_size; 508 497 struct acpi_nfit_system_address *spa; 509 498 struct acpi_nfit_control_region *dcr; 510 499 struct acpi_nfit_data_region *bdw; 511 500 struct acpi_nfit_flush_address *flush; 512 501 unsigned int offset; 513 502 514 - nfit_test_init_header(nfit_buf, size); 515 - 516 503 /* 517 504 * spa0 (interleave first half of dimm0 and dimm1, note storage 518 505 * does not actually alias the related block-data-window 519 506 * regions) 520 507 */ 521 - spa = nfit_buf + sizeof(struct acpi_table_nfit); 508 + spa = nfit_buf; 522 509 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 523 510 spa->header.length = sizeof(*spa); 524 511 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16); ··· 516 533 * does not actually alias the related block-data-window 517 534 * regions) 518 535 */ 519 - spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa); 536 + spa = nfit_buf + sizeof(*spa); 520 537 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 521 538 spa->header.length = sizeof(*spa); 522 539 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16); ··· 525 542 spa->length = SPA1_SIZE; 526 543 527 544 /* spa2 (dcr0) dimm0 */ 528 - spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 2; 545 + spa = nfit_buf + sizeof(*spa) * 2; 529 546 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 530 547 spa->header.length = sizeof(*spa); 531 548 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16); ··· 534 551 spa->length = DCR_SIZE; 535 552 536 553 /* spa3 (dcr1) dimm1 */ 537 - spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 3; 554 + spa = nfit_buf + sizeof(*spa) * 3; 538 555 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 539 556 spa->header.length = sizeof(*spa); 540 557 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16); ··· 543 560 spa->length = DCR_SIZE; 544 561 545 562 /* spa4 (dcr2) dimm2 */ 546 - spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 4; 563 + spa = nfit_buf + sizeof(*spa) * 4; 547 564 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 548 565 spa->header.length = sizeof(*spa); 549 566 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16); ··· 552 569 spa->length = DCR_SIZE; 553 570 554 571 /* spa5 (dcr3) dimm3 */ 555 - spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 5; 572 + spa = nfit_buf + sizeof(*spa) * 5; 556 573 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 557 574 spa->header.length = sizeof(*spa); 558 575 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16); ··· 561 578 spa->length = DCR_SIZE; 562 579 563 580 /* spa6 (bdw for dcr0) dimm0 */ 564 - spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 6; 581 + spa = nfit_buf + sizeof(*spa) * 6; 565 582 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 566 583 spa->header.length = sizeof(*spa); 567 584 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16); ··· 570 587 spa->length = DIMM_SIZE; 571 588 572 589 /* spa7 (bdw for dcr1) dimm1 */ 573 - spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 7; 590 + spa = nfit_buf + sizeof(*spa) * 7; 574 591 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 575 592 spa->header.length = sizeof(*spa); 576 593 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16); ··· 579 596 spa->length = DIMM_SIZE; 580 597 581 598 /* spa8 (bdw for dcr2) dimm2 */ 582 - spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 8; 599 + spa = nfit_buf + sizeof(*spa) * 8; 583 600 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 584 601 spa->header.length = sizeof(*spa); 585 602 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16); ··· 588 605 spa->length = DIMM_SIZE; 589 606 590 607 /* spa9 (bdw for dcr3) dimm3 */ 591 - spa = nfit_buf + sizeof(struct acpi_table_nfit) + sizeof(*spa) * 9; 608 + spa = nfit_buf + sizeof(*spa) * 9; 592 609 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; 593 610 spa->header.length = sizeof(*spa); 594 611 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16); ··· 596 613 spa->address = t->dimm_dma[3]; 597 614 spa->length = DIMM_SIZE; 598 615 599 - offset = sizeof(struct acpi_table_nfit) + sizeof(*spa) * 10; 616 + offset = sizeof(*spa) * 10; 600 617 /* mem-region0 (spa0, dimm0) */ 601 618 memdev = nfit_buf + offset; 602 619 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; ··· 1083 1100 1084 1101 static void nfit_test1_setup(struct nfit_test *t) 1085 1102 { 1086 - size_t size = t->nfit_size, offset; 1103 + size_t offset; 1087 1104 void *nfit_buf = t->nfit_buf; 1088 1105 struct acpi_nfit_memory_map *memdev; 1089 1106 struct acpi_nfit_control_region *dcr; 1090 1107 struct acpi_nfit_system_address *spa; 1091 1108 1092 - nfit_test_init_header(nfit_buf, size); 1093 - 1094 - offset = sizeof(struct acpi_table_nfit); 1109 + offset = 0; 1095 1110 /* spa0 (flat range with no bdw aliasing) */ 1096 1111 spa = nfit_buf + offset; 1097 1112 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;