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