1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * pseries Memory Hotplug infrastructure. 4 * 5 * Copyright (C) 2008 Badari Pulavarty, IBM Corporation 6 */ 7 8 #define pr_fmt(fmt) "pseries-hotplug-mem: " fmt 9 10 #include <linux/of.h> 11 #include <linux/of_address.h> 12 #include <linux/memblock.h> 13 #include <linux/memory.h> 14 #include <linux/memory_hotplug.h> 15 #include <linux/slab.h> 16 17 #include <asm/firmware.h> 18 #include <asm/machdep.h> 19 #include <asm/sparsemem.h> 20 #include <asm/fadump.h> 21 #include <asm/drmem.h> 22 #include "pseries.h" 23 24 static void dlpar_free_property(struct property *prop) 25 { 26 kfree(prop->name); 27 kfree(prop->value); 28 kfree(prop); 29 } 30 31 static struct property *dlpar_clone_property(struct property *prop, 32 u32 prop_size) 33 { 34 struct property *new_prop; 35 36 new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL); 37 if (!new_prop) 38 return NULL; 39 40 new_prop->name = kstrdup(prop->name, GFP_KERNEL); 41 new_prop->value = kzalloc(prop_size, GFP_KERNEL); 42 if (!new_prop->name || !new_prop->value) { 43 dlpar_free_property(new_prop); 44 return NULL; 45 } 46 47 memcpy(new_prop->value, prop->value, prop->length); 48 new_prop->length = prop_size; 49 50 of_property_set_flag(new_prop, OF_DYNAMIC); 51 return new_prop; 52 } 53 54 static bool find_aa_index(struct device_node *dr_node, 55 struct property *ala_prop, 56 const u32 *lmb_assoc, u32 *aa_index) 57 { 58 u32 *assoc_arrays, new_prop_size; 59 struct property *new_prop; 60 int aa_arrays, aa_array_entries, aa_array_sz; 61 int i, index; 62 63 /* 64 * The ibm,associativity-lookup-arrays property is defined to be 65 * a 32-bit value specifying the number of associativity arrays 66 * followed by a 32-bitvalue specifying the number of entries per 67 * array, followed by the associativity arrays. 68 */ 69 assoc_arrays = ala_prop->value; 70 71 aa_arrays = be32_to_cpu(assoc_arrays[0]); 72 aa_array_entries = be32_to_cpu(assoc_arrays[1]); 73 aa_array_sz = aa_array_entries * sizeof(u32); 74 75 for (i = 0; i < aa_arrays; i++) { 76 index = (i * aa_array_entries) + 2; 77 78 if (memcmp(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz)) 79 continue; 80 81 *aa_index = i; 82 return true; 83 } 84 85 new_prop_size = ala_prop->length + aa_array_sz; 86 new_prop = dlpar_clone_property(ala_prop, new_prop_size); 87 if (!new_prop) 88 return false; 89 90 assoc_arrays = new_prop->value; 91 92 /* increment the number of entries in the lookup array */ 93 assoc_arrays[0] = cpu_to_be32(aa_arrays + 1); 94 95 /* copy the new associativity into the lookup array */ 96 index = aa_arrays * aa_array_entries + 2; 97 memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz); 98 99 of_update_property(dr_node, new_prop); 100 101 /* 102 * The associativity lookup array index for this lmb is 103 * number of entries - 1 since we added its associativity 104 * to the end of the lookup array. 105 */ 106 *aa_index = be32_to_cpu(assoc_arrays[0]) - 1; 107 return true; 108 } 109 110 static int update_lmb_associativity_index(struct drmem_lmb *lmb) 111 { 112 struct device_node *parent, *lmb_node, *dr_node; 113 struct property *ala_prop; 114 const u32 *lmb_assoc; 115 u32 aa_index; 116 bool found; 117 118 parent = of_find_node_by_path("/"); 119 if (!parent) 120 return -ENODEV; 121 122 lmb_node = dlpar_configure_connector(cpu_to_be32(lmb->drc_index), 123 parent); 124 of_node_put(parent); 125 if (!lmb_node) 126 return -EINVAL; 127 128 lmb_assoc = of_get_property(lmb_node, "ibm,associativity", NULL); 129 if (!lmb_assoc) { 130 dlpar_free_cc_nodes(lmb_node); 131 return -ENODEV; 132 } 133 134 update_numa_distance(lmb_node); 135 136 dr_node = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); 137 if (!dr_node) { 138 dlpar_free_cc_nodes(lmb_node); 139 return -ENODEV; 140 } 141 142 ala_prop = of_find_property(dr_node, "ibm,associativity-lookup-arrays", 143 NULL); 144 if (!ala_prop) { 145 of_node_put(dr_node); 146 dlpar_free_cc_nodes(lmb_node); 147 return -ENODEV; 148 } 149 150 found = find_aa_index(dr_node, ala_prop, lmb_assoc, &aa_index); 151 152 of_node_put(dr_node); 153 dlpar_free_cc_nodes(lmb_node); 154 155 if (!found) { 156 pr_err("Could not find LMB associativity\n"); 157 return -1; 158 } 159 160 lmb->aa_index = aa_index; 161 return 0; 162 } 163 164 static struct memory_block *lmb_to_memblock(struct drmem_lmb *lmb) 165 { 166 unsigned long section_nr; 167 struct memory_block *mem_block; 168 169 section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr)); 170 171 mem_block = find_memory_block(section_nr); 172 return mem_block; 173 } 174 175 static int get_lmb_range(u32 drc_index, int n_lmbs, 176 struct drmem_lmb **start_lmb, 177 struct drmem_lmb **end_lmb) 178 { 179 struct drmem_lmb *lmb, *start, *end; 180 struct drmem_lmb *limit; 181 182 start = NULL; 183 for_each_drmem_lmb(lmb) { 184 if (lmb->drc_index == drc_index) { 185 start = lmb; 186 break; 187 } 188 } 189 190 if (!start) 191 return -EINVAL; 192 193 end = &start[n_lmbs]; 194 195 limit = &drmem_info->lmbs[drmem_info->n_lmbs]; 196 if (end > limit) 197 return -EINVAL; 198 199 *start_lmb = start; 200 *end_lmb = end; 201 return 0; 202 } 203 204 static int dlpar_change_lmb_state(struct drmem_lmb *lmb, bool online) 205 { 206 struct memory_block *mem_block; 207 int rc; 208 209 mem_block = lmb_to_memblock(lmb); 210 if (!mem_block) 211 return -EINVAL; 212 213 if (online && mem_block->dev.offline) 214 rc = device_online(&mem_block->dev); 215 else if (!online && !mem_block->dev.offline) 216 rc = device_offline(&mem_block->dev); 217 else 218 rc = 0; 219 220 put_device(&mem_block->dev); 221 222 return rc; 223 } 224 225 static int dlpar_online_lmb(struct drmem_lmb *lmb) 226 { 227 return dlpar_change_lmb_state(lmb, true); 228 } 229 230 #ifdef CONFIG_MEMORY_HOTREMOVE 231 static int dlpar_offline_lmb(struct drmem_lmb *lmb) 232 { 233 return dlpar_change_lmb_state(lmb, false); 234 } 235 236 static int pseries_remove_memblock(unsigned long base, unsigned long memblock_size) 237 { 238 unsigned long start_pfn; 239 int sections_per_block; 240 int i; 241 242 start_pfn = base >> PAGE_SHIFT; 243 244 lock_device_hotplug(); 245 246 if (!pfn_valid(start_pfn)) 247 goto out; 248 249 sections_per_block = memory_block_size / MIN_MEMORY_BLOCK_SIZE; 250 251 for (i = 0; i < sections_per_block; i++) { 252 __remove_memory(base, MIN_MEMORY_BLOCK_SIZE); 253 base += MIN_MEMORY_BLOCK_SIZE; 254 } 255 256 out: 257 /* Update memory regions for memory remove */ 258 memblock_remove(base, memblock_size); 259 unlock_device_hotplug(); 260 return 0; 261 } 262 263 static int pseries_remove_mem_node(struct device_node *np) 264 { 265 int ret; 266 struct resource res; 267 268 /* 269 * Check to see if we are actually removing memory 270 */ 271 if (!of_node_is_type(np, "memory")) 272 return 0; 273 274 /* 275 * Find the base address and size of the memblock 276 */ 277 ret = of_address_to_resource(np, 0, &res); 278 if (ret) 279 return ret; 280 281 pseries_remove_memblock(res.start, resource_size(&res)); 282 return 0; 283 } 284 285 static bool lmb_is_removable(struct drmem_lmb *lmb) 286 { 287 if ((lmb->flags & DRCONF_MEM_RESERVED) || 288 !(lmb->flags & DRCONF_MEM_ASSIGNED)) 289 return false; 290 291 #ifdef CONFIG_FA_DUMP 292 /* 293 * Don't hot-remove memory that falls in fadump boot memory area 294 * and memory that is reserved for capturing old kernel memory. 295 */ 296 if (is_fadump_memory_area(lmb->base_addr, memory_block_size_bytes())) 297 return false; 298 #endif 299 /* device_offline() will determine if we can actually remove this lmb */ 300 return true; 301 } 302 303 static int dlpar_add_lmb(struct drmem_lmb *); 304 305 static int dlpar_remove_lmb(struct drmem_lmb *lmb) 306 { 307 struct memory_block *mem_block; 308 int rc; 309 310 if (!lmb_is_removable(lmb)) 311 return -EINVAL; 312 313 mem_block = lmb_to_memblock(lmb); 314 if (mem_block == NULL) 315 return -EINVAL; 316 317 rc = dlpar_offline_lmb(lmb); 318 if (rc) { 319 put_device(&mem_block->dev); 320 return rc; 321 } 322 323 __remove_memory(lmb->base_addr, memory_block_size); 324 put_device(&mem_block->dev); 325 326 /* Update memory regions for memory remove */ 327 memblock_remove(lmb->base_addr, memory_block_size); 328 329 invalidate_lmb_associativity_index(lmb); 330 lmb->flags &= ~DRCONF_MEM_ASSIGNED; 331 332 return 0; 333 } 334 335 static int dlpar_memory_remove_by_count(u32 lmbs_to_remove) 336 { 337 struct drmem_lmb *lmb; 338 int lmbs_reserved = 0; 339 int lmbs_available = 0; 340 int rc; 341 342 pr_info("Attempting to hot-remove %d LMB(s)\n", lmbs_to_remove); 343 344 if (lmbs_to_remove == 0) 345 return -EINVAL; 346 347 /* Validate that there are enough LMBs to satisfy the request */ 348 for_each_drmem_lmb(lmb) { 349 if (lmb_is_removable(lmb)) 350 lmbs_available++; 351 352 if (lmbs_available == lmbs_to_remove) 353 break; 354 } 355 356 if (lmbs_available < lmbs_to_remove) { 357 pr_info("Not enough LMBs available (%d of %d) to satisfy request\n", 358 lmbs_available, lmbs_to_remove); 359 return -EINVAL; 360 } 361 362 for_each_drmem_lmb(lmb) { 363 rc = dlpar_remove_lmb(lmb); 364 if (rc) 365 continue; 366 367 /* Mark this lmb so we can add it later if all of the 368 * requested LMBs cannot be removed. 369 */ 370 drmem_mark_lmb_reserved(lmb); 371 372 lmbs_reserved++; 373 if (lmbs_reserved == lmbs_to_remove) 374 break; 375 } 376 377 if (lmbs_reserved != lmbs_to_remove) { 378 pr_err("Memory hot-remove failed, adding LMB's back\n"); 379 380 for_each_drmem_lmb(lmb) { 381 if (!drmem_lmb_reserved(lmb)) 382 continue; 383 384 rc = dlpar_add_lmb(lmb); 385 if (rc) 386 pr_err("Failed to add LMB back, drc index %x\n", 387 lmb->drc_index); 388 389 drmem_remove_lmb_reservation(lmb); 390 391 lmbs_reserved--; 392 if (lmbs_reserved == 0) 393 break; 394 } 395 396 rc = -EINVAL; 397 } else { 398 for_each_drmem_lmb(lmb) { 399 if (!drmem_lmb_reserved(lmb)) 400 continue; 401 402 dlpar_release_drc(lmb->drc_index); 403 pr_info("Memory at %llx was hot-removed\n", 404 lmb->base_addr); 405 406 drmem_remove_lmb_reservation(lmb); 407 408 lmbs_reserved--; 409 if (lmbs_reserved == 0) 410 break; 411 } 412 rc = 0; 413 } 414 415 return rc; 416 } 417 418 static int dlpar_memory_remove_by_index(u32 drc_index) 419 { 420 struct drmem_lmb *lmb; 421 int lmb_found; 422 int rc; 423 424 pr_debug("Attempting to hot-remove LMB, drc index %x\n", drc_index); 425 426 lmb_found = 0; 427 for_each_drmem_lmb(lmb) { 428 if (lmb->drc_index == drc_index) { 429 lmb_found = 1; 430 rc = dlpar_remove_lmb(lmb); 431 if (!rc) 432 dlpar_release_drc(lmb->drc_index); 433 434 break; 435 } 436 } 437 438 if (!lmb_found) 439 rc = -EINVAL; 440 441 if (rc) 442 pr_debug("Failed to hot-remove memory at %llx\n", 443 lmb->base_addr); 444 else 445 pr_debug("Memory at %llx was hot-removed\n", lmb->base_addr); 446 447 return rc; 448 } 449 450 static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index) 451 { 452 struct drmem_lmb *lmb, *start_lmb, *end_lmb; 453 int rc; 454 455 pr_info("Attempting to hot-remove %u LMB(s) at %x\n", 456 lmbs_to_remove, drc_index); 457 458 if (lmbs_to_remove == 0) 459 return -EINVAL; 460 461 rc = get_lmb_range(drc_index, lmbs_to_remove, &start_lmb, &end_lmb); 462 if (rc) 463 return -EINVAL; 464 465 /* 466 * Validate that all LMBs in range are not reserved. Note that it 467 * is ok if they are !ASSIGNED since our goal here is to remove the 468 * LMB range, regardless of whether some LMBs were already removed 469 * by any other reason. 470 * 471 * This is a contrast to what is done in remove_by_count() where we 472 * check for both RESERVED and !ASSIGNED (via lmb_is_removable()), 473 * because we want to remove a fixed amount of LMBs in that function. 474 */ 475 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) { 476 if (lmb->flags & DRCONF_MEM_RESERVED) { 477 pr_err("Memory at %llx (drc index %x) is reserved\n", 478 lmb->base_addr, lmb->drc_index); 479 return -EINVAL; 480 } 481 } 482 483 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) { 484 /* 485 * dlpar_remove_lmb() will error out if the LMB is already 486 * !ASSIGNED, but this case is a no-op for us. 487 */ 488 if (!(lmb->flags & DRCONF_MEM_ASSIGNED)) 489 continue; 490 491 rc = dlpar_remove_lmb(lmb); 492 if (rc) 493 break; 494 495 drmem_mark_lmb_reserved(lmb); 496 } 497 498 if (rc) { 499 pr_err("Memory indexed-count-remove failed, adding any removed LMBs\n"); 500 501 502 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) { 503 if (!drmem_lmb_reserved(lmb)) 504 continue; 505 506 /* 507 * Setting the isolation state of an UNISOLATED/CONFIGURED 508 * device to UNISOLATE is a no-op, but the hypervisor can 509 * use it as a hint that the LMB removal failed. 510 */ 511 dlpar_unisolate_drc(lmb->drc_index); 512 513 rc = dlpar_add_lmb(lmb); 514 if (rc) 515 pr_err("Failed to add LMB, drc index %x\n", 516 lmb->drc_index); 517 518 drmem_remove_lmb_reservation(lmb); 519 } 520 rc = -EINVAL; 521 } else { 522 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) { 523 if (!drmem_lmb_reserved(lmb)) 524 continue; 525 526 dlpar_release_drc(lmb->drc_index); 527 pr_info("Memory at %llx (drc index %x) was hot-removed\n", 528 lmb->base_addr, lmb->drc_index); 529 530 drmem_remove_lmb_reservation(lmb); 531 } 532 } 533 534 return rc; 535 } 536 537 #else 538 static inline int pseries_remove_memblock(unsigned long base, 539 unsigned long memblock_size) 540 { 541 return -EOPNOTSUPP; 542 } 543 static inline int pseries_remove_mem_node(struct device_node *np) 544 { 545 return 0; 546 } 547 static int dlpar_remove_lmb(struct drmem_lmb *lmb) 548 { 549 return -EOPNOTSUPP; 550 } 551 static int dlpar_memory_remove_by_count(u32 lmbs_to_remove) 552 { 553 return -EOPNOTSUPP; 554 } 555 static int dlpar_memory_remove_by_index(u32 drc_index) 556 { 557 return -EOPNOTSUPP; 558 } 559 560 static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index) 561 { 562 return -EOPNOTSUPP; 563 } 564 #endif /* CONFIG_MEMORY_HOTREMOVE */ 565 566 static int dlpar_add_lmb(struct drmem_lmb *lmb) 567 { 568 unsigned long block_sz; 569 int nid, rc; 570 571 if (lmb->flags & DRCONF_MEM_ASSIGNED) 572 return -EINVAL; 573 574 rc = update_lmb_associativity_index(lmb); 575 if (rc) { 576 dlpar_release_drc(lmb->drc_index); 577 return rc; 578 } 579 580 block_sz = memory_block_size_bytes(); 581 582 /* Find the node id for this LMB. Fake one if necessary. */ 583 nid = of_drconf_to_nid_single(lmb); 584 if (nid < 0 || !node_possible(nid)) 585 nid = first_online_node; 586 587 /* Add the memory */ 588 rc = __add_memory(nid, lmb->base_addr, block_sz, MHP_MEMMAP_ON_MEMORY); 589 if (rc) { 590 invalidate_lmb_associativity_index(lmb); 591 return rc; 592 } 593 594 rc = dlpar_online_lmb(lmb); 595 if (rc) { 596 __remove_memory(lmb->base_addr, block_sz); 597 invalidate_lmb_associativity_index(lmb); 598 } else { 599 lmb->flags |= DRCONF_MEM_ASSIGNED; 600 } 601 602 return rc; 603 } 604 605 static int dlpar_memory_add_by_count(u32 lmbs_to_add) 606 { 607 struct drmem_lmb *lmb; 608 int lmbs_available = 0; 609 int lmbs_reserved = 0; 610 int rc; 611 612 pr_info("Attempting to hot-add %d LMB(s)\n", lmbs_to_add); 613 614 if (lmbs_to_add == 0) 615 return -EINVAL; 616 617 /* Validate that there are enough LMBs to satisfy the request */ 618 for_each_drmem_lmb(lmb) { 619 if (lmb->flags & DRCONF_MEM_RESERVED) 620 continue; 621 622 if (!(lmb->flags & DRCONF_MEM_ASSIGNED)) 623 lmbs_available++; 624 625 if (lmbs_available == lmbs_to_add) 626 break; 627 } 628 629 if (lmbs_available < lmbs_to_add) 630 return -EINVAL; 631 632 for_each_drmem_lmb(lmb) { 633 if (lmb->flags & DRCONF_MEM_ASSIGNED) 634 continue; 635 636 rc = dlpar_acquire_drc(lmb->drc_index); 637 if (rc) 638 continue; 639 640 rc = dlpar_add_lmb(lmb); 641 if (rc) { 642 dlpar_release_drc(lmb->drc_index); 643 continue; 644 } 645 646 /* Mark this lmb so we can remove it later if all of the 647 * requested LMBs cannot be added. 648 */ 649 drmem_mark_lmb_reserved(lmb); 650 lmbs_reserved++; 651 if (lmbs_reserved == lmbs_to_add) 652 break; 653 } 654 655 if (lmbs_reserved != lmbs_to_add) { 656 pr_err("Memory hot-add failed, removing any added LMBs\n"); 657 658 for_each_drmem_lmb(lmb) { 659 if (!drmem_lmb_reserved(lmb)) 660 continue; 661 662 rc = dlpar_remove_lmb(lmb); 663 if (rc) 664 pr_err("Failed to remove LMB, drc index %x\n", 665 lmb->drc_index); 666 else 667 dlpar_release_drc(lmb->drc_index); 668 669 drmem_remove_lmb_reservation(lmb); 670 lmbs_reserved--; 671 672 if (lmbs_reserved == 0) 673 break; 674 } 675 rc = -EINVAL; 676 } else { 677 for_each_drmem_lmb(lmb) { 678 if (!drmem_lmb_reserved(lmb)) 679 continue; 680 681 pr_debug("Memory at %llx (drc index %x) was hot-added\n", 682 lmb->base_addr, lmb->drc_index); 683 drmem_remove_lmb_reservation(lmb); 684 lmbs_reserved--; 685 686 if (lmbs_reserved == 0) 687 break; 688 } 689 rc = 0; 690 } 691 692 return rc; 693 } 694 695 static int dlpar_memory_add_by_index(u32 drc_index) 696 { 697 struct drmem_lmb *lmb; 698 int rc, lmb_found; 699 700 pr_info("Attempting to hot-add LMB, drc index %x\n", drc_index); 701 702 lmb_found = 0; 703 for_each_drmem_lmb(lmb) { 704 if (lmb->drc_index == drc_index) { 705 lmb_found = 1; 706 rc = dlpar_acquire_drc(lmb->drc_index); 707 if (!rc) { 708 rc = dlpar_add_lmb(lmb); 709 if (rc) 710 dlpar_release_drc(lmb->drc_index); 711 } 712 713 break; 714 } 715 } 716 717 if (!lmb_found) 718 rc = -EINVAL; 719 720 if (rc) 721 pr_info("Failed to hot-add memory, drc index %x\n", drc_index); 722 else 723 pr_info("Memory at %llx (drc index %x) was hot-added\n", 724 lmb->base_addr, drc_index); 725 726 return rc; 727 } 728 729 static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index) 730 { 731 struct drmem_lmb *lmb, *start_lmb, *end_lmb; 732 int rc; 733 734 pr_info("Attempting to hot-add %u LMB(s) at index %x\n", 735 lmbs_to_add, drc_index); 736 737 if (lmbs_to_add == 0) 738 return -EINVAL; 739 740 rc = get_lmb_range(drc_index, lmbs_to_add, &start_lmb, &end_lmb); 741 if (rc) 742 return -EINVAL; 743 744 /* Validate that the LMBs in this range are not reserved */ 745 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) { 746 /* Fail immediately if the whole range can't be hot-added */ 747 if (lmb->flags & DRCONF_MEM_RESERVED) { 748 pr_err("Memory at %llx (drc index %x) is reserved\n", 749 lmb->base_addr, lmb->drc_index); 750 return -EINVAL; 751 } 752 } 753 754 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) { 755 if (lmb->flags & DRCONF_MEM_ASSIGNED) 756 continue; 757 758 rc = dlpar_acquire_drc(lmb->drc_index); 759 if (rc) 760 break; 761 762 rc = dlpar_add_lmb(lmb); 763 if (rc) { 764 dlpar_release_drc(lmb->drc_index); 765 break; 766 } 767 768 drmem_mark_lmb_reserved(lmb); 769 } 770 771 if (rc) { 772 pr_err("Memory indexed-count-add failed, removing any added LMBs\n"); 773 774 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) { 775 if (!drmem_lmb_reserved(lmb)) 776 continue; 777 778 rc = dlpar_remove_lmb(lmb); 779 if (rc) 780 pr_err("Failed to remove LMB, drc index %x\n", 781 lmb->drc_index); 782 else 783 dlpar_release_drc(lmb->drc_index); 784 785 drmem_remove_lmb_reservation(lmb); 786 } 787 rc = -EINVAL; 788 } else { 789 for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) { 790 if (!drmem_lmb_reserved(lmb)) 791 continue; 792 793 pr_info("Memory at %llx (drc index %x) was hot-added\n", 794 lmb->base_addr, lmb->drc_index); 795 drmem_remove_lmb_reservation(lmb); 796 } 797 } 798 799 return rc; 800 } 801 802 int dlpar_memory(struct pseries_hp_errorlog *hp_elog) 803 { 804 u32 count, drc_index; 805 int rc; 806 807 lock_device_hotplug(); 808 809 switch (hp_elog->action) { 810 case PSERIES_HP_ELOG_ACTION_ADD: 811 switch (hp_elog->id_type) { 812 case PSERIES_HP_ELOG_ID_DRC_COUNT: 813 count = hp_elog->_drc_u.drc_count; 814 rc = dlpar_memory_add_by_count(count); 815 break; 816 case PSERIES_HP_ELOG_ID_DRC_INDEX: 817 drc_index = hp_elog->_drc_u.drc_index; 818 rc = dlpar_memory_add_by_index(drc_index); 819 break; 820 case PSERIES_HP_ELOG_ID_DRC_IC: 821 count = hp_elog->_drc_u.ic.count; 822 drc_index = hp_elog->_drc_u.ic.index; 823 rc = dlpar_memory_add_by_ic(count, drc_index); 824 break; 825 default: 826 rc = -EINVAL; 827 break; 828 } 829 830 break; 831 case PSERIES_HP_ELOG_ACTION_REMOVE: 832 switch (hp_elog->id_type) { 833 case PSERIES_HP_ELOG_ID_DRC_COUNT: 834 count = hp_elog->_drc_u.drc_count; 835 rc = dlpar_memory_remove_by_count(count); 836 break; 837 case PSERIES_HP_ELOG_ID_DRC_INDEX: 838 drc_index = hp_elog->_drc_u.drc_index; 839 rc = dlpar_memory_remove_by_index(drc_index); 840 break; 841 case PSERIES_HP_ELOG_ID_DRC_IC: 842 count = hp_elog->_drc_u.ic.count; 843 drc_index = hp_elog->_drc_u.ic.index; 844 rc = dlpar_memory_remove_by_ic(count, drc_index); 845 break; 846 default: 847 rc = -EINVAL; 848 break; 849 } 850 851 break; 852 default: 853 pr_err("Invalid action (%d) specified\n", hp_elog->action); 854 rc = -EINVAL; 855 break; 856 } 857 858 if (!rc) 859 rc = drmem_update_dt(); 860 861 unlock_device_hotplug(); 862 return rc; 863 } 864 865 static int pseries_add_mem_node(struct device_node *np) 866 { 867 int ret; 868 struct resource res; 869 870 /* 871 * Check to see if we are actually adding memory 872 */ 873 if (!of_node_is_type(np, "memory")) 874 return 0; 875 876 /* 877 * Find the base and size of the memblock 878 */ 879 ret = of_address_to_resource(np, 0, &res); 880 if (ret) 881 return ret; 882 883 /* 884 * Update memory region to represent the memory add 885 */ 886 ret = memblock_add(res.start, resource_size(&res)); 887 return (ret < 0) ? -EINVAL : 0; 888 } 889 890 static int pseries_memory_notifier(struct notifier_block *nb, 891 unsigned long action, void *data) 892 { 893 struct of_reconfig_data *rd = data; 894 int err = 0; 895 896 switch (action) { 897 case OF_RECONFIG_ATTACH_NODE: 898 err = pseries_add_mem_node(rd->dn); 899 break; 900 case OF_RECONFIG_DETACH_NODE: 901 err = pseries_remove_mem_node(rd->dn); 902 break; 903 case OF_RECONFIG_UPDATE_PROPERTY: 904 if (!strcmp(rd->dn->name, 905 "ibm,dynamic-reconfiguration-memory")) 906 drmem_update_lmbs(rd->prop); 907 } 908 return notifier_from_errno(err); 909 } 910 911 static struct notifier_block pseries_mem_nb = { 912 .notifier_call = pseries_memory_notifier, 913 }; 914 915 static int __init pseries_memory_hotplug_init(void) 916 { 917 if (firmware_has_feature(FW_FEATURE_LPAR)) 918 of_reconfig_notifier_register(&pseries_mem_nb); 919 920 return 0; 921 } 922 machine_device_initcall(pseries, pseries_memory_hotplug_init); 923