1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright (c) 2018, Joyent, Inc. 26 */ 27 28 /* 29 * This plugin creates memory configuration nodes and properties in the 30 * PICL tree for Cheetah platforms. 31 * 32 * Subtree of memory-controller in the physical aspect. 33 * memory-controller --- memory-module-group --- memory-module 34 * 35 * Subtree of memory in the logical aspect. 36 * memory --- memory-segment --- memory-bank 37 * Add property _memory-module-group_ at memory-segment referring to the 38 * memory-module-group if InterleaveFactor is one, or at memory-bank 39 * if InterleaveFactor is greater than one. 40 * 41 * Undo strategy: 42 * Create all nodes and properties, or none if it fails in physical and 43 * logical memory tree respectively. It keeps on creating logic 44 * memory tree although it falis on physical logic tree, but no link to 45 * memory module group. 46 * 47 * NOTE: 48 * It depends on PICL devtree plugin and currently 49 * there is no refresh routine for DR. 50 */ 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <unistd.h> 55 #include <alloca.h> 56 #include <syslog.h> 57 #include <string.h> 58 #include <libintl.h> 59 #include <picl.h> 60 #include <picltree.h> 61 #include <fcntl.h> 62 #include <errno.h> 63 #include <sys/types.h> 64 #include <dirent.h> 65 #include <sys/stat.h> 66 #include <mc.h> 67 #include <libnvpair.h> 68 #include <limits.h> 69 #include "piclmemcfg.h" 70 71 /* 72 * Plugin registration entry points 73 */ 74 static void piclmemcfg_register(void); 75 static void piclmemcfg_init(void); 76 static void piclmemcfg_fini(void); 77 78 /* 79 * PICL event handler 80 */ 81 static void piclmemcfg_evhandler(const char *ename, const void *earg, 82 size_t size, void *cookie); 83 84 #pragma init(piclmemcfg_register) 85 86 static picld_plugin_reg_t my_reg_info = { 87 PICLD_PLUGIN_VERSION_1, 88 PICLD_PLUGIN_NON_CRITICAL, 89 "SUNW_piclmemcfg", 90 piclmemcfg_init, 91 piclmemcfg_fini 92 }; 93 94 /* 95 * Log message texts 96 */ 97 #define EM_INIT_FAILED gettext("SUNW_piclmemcfg init failed!\n") 98 #define EM_PHYSIC_MEM_TREE_FAILED \ 99 gettext("SUNW_piclmemcfg physical memory tree failed!\n") 100 #define EM_LOGIC_MEM_TREE_FAILED \ 101 gettext("SUNW_piclmemcfg logical memory tree failed!\n") 102 103 #define EM_INIT_MC_FAILED \ 104 gettext("SUNW_piclmemcfg init mc failed!\n") 105 106 /* 107 * Global variables for Memory Controllers 108 */ 109 #define MC_DIR "/dev/mc/" 110 111 static int nsegments; /* The number of memory segments */ 112 static int nbanks; /* The max. number of banks per segment */ 113 static int ndevgrps; /* The max. number of device groups per mc */ 114 static int ndevs; /* The max. number of devices per dev group */ 115 static int transfersize; 116 117 static picl_nodehdl_t *msegh_info; 118 119 /* 120 * Memory-module-group node handle list, a singal linking list, where 121 * memory module group id is the key to match. 122 * 123 * It is allocated and added to the head of list, and freed as well. 124 * The mmgh field is cleared if failure is encountered in the physical 125 * memory tree. 126 * 127 * This list is accessed in the logical memory tree, and allocated memory 128 * is released at the end of plugin. 129 */ 130 typedef struct memmodgrp_info { 131 int mmgid; 132 struct memmodgrp_info *next; 133 picl_nodehdl_t mmgh; 134 picl_nodehdl_t mch; 135 } mmodgrp_info_t; 136 137 static mmodgrp_info_t *head2mmodgrp; 138 139 /* 140 * Release the allocated memory of mmodgrp_info 141 */ 142 static void 143 free_allocated_mem(void) 144 { 145 mmodgrp_info_t *mmghdl, *currmmghdl; 146 147 mmghdl = head2mmodgrp; 148 149 while (mmghdl) { 150 currmmghdl = mmghdl; 151 mmghdl = mmghdl->next; 152 free(currmmghdl); 153 } 154 155 head2mmodgrp = NULL; 156 } 157 158 /* 159 * Delete nodes whose MC is gone at mmodgrp_info 160 */ 161 static void 162 del_plugout_mmodgrp(picl_nodehdl_t mch) 163 { 164 mmodgrp_info_t *mmghdl, *prevmmghdl, *nextmmghdl; 165 166 for (mmghdl = head2mmodgrp, prevmmghdl = NULL; mmghdl != NULL; 167 mmghdl = nextmmghdl) { 168 nextmmghdl = mmghdl->next; 169 if (mmghdl->mch == mch) { 170 if (prevmmghdl == NULL) 171 /* we are at the head */ 172 head2mmodgrp = nextmmghdl; 173 else 174 prevmmghdl->next = nextmmghdl; 175 free(mmghdl); 176 } else 177 prevmmghdl = mmghdl; 178 } 179 } 180 181 /* 182 * Search the memory module group node in the mmodgrp_info by global id. 183 * The matched memory-module-group node handle will be assigned to 184 * the second parameter. 185 */ 186 static int 187 find_mem_mod_grp_hdl(int id, picl_nodehdl_t *mmodgrph) 188 { 189 mmodgrp_info_t *mmghdl; 190 int err = PICL_FAILURE; 191 192 mmghdl = head2mmodgrp; 193 194 while (mmghdl) { 195 if ((mmghdl->mmgh) && (mmghdl->mmgid == id)) { 196 *mmodgrph = mmghdl->mmgh; 197 err = PICL_SUCCESS; 198 break; 199 } 200 mmghdl = mmghdl->next; 201 } 202 203 return (err); 204 } 205 206 /* 207 * Delete nodes and properties created in the physical memory tree. 208 */ 209 static void 210 undo_phymem_tree(void) 211 { 212 mmodgrp_info_t *mmghdl; 213 214 mmghdl = head2mmodgrp; 215 216 while (mmghdl) { 217 /* 218 * Delete nodes and properties of memory-module-group(s) 219 */ 220 if (mmghdl->mmgh == NULL) 221 continue; 222 223 (void) ptree_delete_node(mmghdl->mmgh); 224 (void) ptree_destroy_node(mmghdl->mmgh); 225 226 /* 227 * Clear out the saved node handle of memory module group 228 * so that logic memory tree won't link to it. 229 */ 230 mmghdl->mch = mmghdl->mmgh = NULL; 231 mmghdl = mmghdl->next; 232 } 233 } 234 235 /* 236 * Create all memory-banks under the given memory-segment. 237 */ 238 static int 239 add_mem_banks(picl_nodehdl_t msegh, int fd, struct mc_segment *mcseg) 240 { 241 int i; 242 int err = PICL_SUCCESS; 243 static picl_nodehdl_t mmodgrph; 244 picl_prophdl_t bankh; 245 ptree_propinfo_t propinfo; 246 struct mc_bank mcbank; 247 char propname[PICL_CLASSNAMELEN_MAX]; 248 249 /* 250 * Get all bank information via ioctl 251 */ 252 for (i = 0; i < mcseg->nbanks; i++) { 253 mcbank.id = mcseg->bankids[i].globalid; 254 if (ioctl(fd, MCIOC_BANK, &mcbank) == -1) 255 return (PICL_FAILURE); 256 257 /* 258 * Create memory-bank node under memory-segment node 259 */ 260 err = ptree_create_and_add_node(msegh, PICL_NAME_MEMORY_BANK, 261 PICL_CLASS_MEMORY_BANK, &bankh); 262 if (err != PICL_SUCCESS) 263 break; 264 265 /* 266 * Add property, Size to memory-bank node 267 */ 268 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 269 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcbank.size), 270 PICL_PROP_SIZE, NULL, NULL); 271 if (err != PICL_SUCCESS) 272 break; 273 274 err = ptree_create_and_add_prop(bankh, &propinfo, &mcbank.size, 275 NULL); 276 if (err != PICL_SUCCESS) 277 break; 278 279 /* 280 * Add property, AddressMask to memory-bank node 281 */ 282 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 283 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcbank.mask), 284 PICL_PROP_ADDRESSMASK, NULL, NULL); 285 if (err != PICL_SUCCESS) 286 break; 287 288 err = ptree_create_and_add_prop(bankh, &propinfo, &mcbank.mask, 289 NULL); 290 if (err != PICL_SUCCESS) 291 break; 292 293 /* 294 * Add property, AddressMatch to memory-bank node 295 */ 296 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 297 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcbank.match), 298 PICL_PROP_ADDRESSMATCH, NULL, NULL); 299 if (err != PICL_SUCCESS) 300 break; 301 302 err = ptree_create_and_add_prop(bankh, &propinfo, 303 &mcbank.match, NULL); 304 if (err != PICL_SUCCESS) 305 break; 306 307 /* 308 * Add global id of bank to property, ID memory-bank node 309 */ 310 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 311 PICL_PTYPE_INT, PICL_READ, sizeof (mcbank.id), PICL_PROP_ID, 312 NULL, NULL); 313 if (err != PICL_SUCCESS) 314 break; 315 316 err = ptree_create_and_add_prop(bankh, &propinfo, &mcbank.id, 317 NULL); 318 if (err != PICL_SUCCESS) 319 break; 320 321 /* 322 * Add property, _memory-module-group_ to memory-bank node 323 */ 324 if ((find_mem_mod_grp_hdl(mcbank.devgrpid.globalid, 325 &mmodgrph)) != PICL_SUCCESS) 326 continue; 327 328 /* 329 * The number of memory modules > 1 means there needs 330 * memory module group, and then refers to it. Otherwise, 331 * it refers to memory module node handle instead. 332 */ 333 (void) strlcpy(propname, (ndevs > 1 ? 334 PICL_REFPROP_MEMORY_MODULE_GROUP : 335 PICL_REFPROP_MEMORY_MODULE), PICL_CLASSNAMELEN_MAX); 336 337 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 338 PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t), 339 propname, NULL, NULL); 340 if (err != PICL_SUCCESS) 341 break; 342 343 err = ptree_create_and_add_prop(bankh, &propinfo, &mmodgrph, 344 NULL); 345 if (err != PICL_SUCCESS) 346 break; 347 } 348 return (PICL_SUCCESS); 349 } 350 351 static void 352 undo_logical_tree(int nsegments) 353 { 354 int i; 355 /* 356 * Undo in the logical memory tree 357 */ 358 for (i = 0; i < nsegments; i++) { 359 (void) ptree_delete_node(msegh_info[i]); 360 (void) ptree_destroy_node(msegh_info[i]); 361 } 362 } 363 364 /* 365 * Create logical memory tree 366 * memory --- memory-segment --- memory-bank 367 * Get information via ioctl of memory control driver 368 */ 369 static int 370 create_logical_tree(picl_nodehdl_t memh, int fd) 371 { 372 int i; 373 int err = PICL_SUCCESS; 374 picl_nodehdl_t msegh; 375 ptree_propinfo_t propinfo; 376 struct mc_memory *mcmem; 377 struct mc_segment *mcseg; 378 picl_prophdl_t proph; 379 uint64_t memsize = 0; 380 381 /* 382 * allocate memory for mc_memory where nsegmentids are various 383 */ 384 if ((mcmem = alloca((nsegments - 1) * sizeof (mcmem->segmentids[0]) + 385 sizeof (*mcmem))) == NULL) 386 return (PICL_FAILURE); 387 388 mcmem->nsegments = nsegments; 389 390 /* 391 * Get logical memory information 392 */ 393 if (ioctl(fd, MCIOC_MEM, mcmem) == -1) 394 return (PICL_FAILURE); 395 396 /* 397 * allocate memory for mc_segment where nbanks are various 398 */ 399 if ((mcseg = alloca((nbanks - 1) * sizeof (mcseg->bankids[0]) + 400 sizeof (*mcseg))) == NULL) 401 return (PICL_FAILURE); 402 403 /* 404 * Get all segments to create memory-segment nodes and 405 * add properties. 406 */ 407 for (i = 0; i < nsegments; i++) { 408 mcseg->id = mcmem->segmentids[i].globalid; 409 mcseg->nbanks = nbanks; 410 411 if (ioctl(fd, MCIOC_SEG, mcseg) == -1) 412 break; 413 414 /* 415 * Create memory-segment node under memory node 416 */ 417 err = ptree_create_and_add_node(memh, PICL_NAME_MEMORY_SEGMENT, 418 PICL_CLASS_MEMORY_SEGMENT, &msegh); 419 if (err != PICL_SUCCESS) 420 break; 421 422 msegh_info[i] = msegh; 423 424 /* 425 * Add property, Size to memory-segment node 426 */ 427 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 428 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcseg->size), 429 PICL_PROP_SIZE, NULL, NULL); 430 if (err != PICL_SUCCESS) 431 break; 432 433 memsize += mcseg->size; 434 err = ptree_create_and_add_prop(msegh, &propinfo, &mcseg->size, 435 NULL); 436 if (err != PICL_SUCCESS) 437 break; 438 439 /* 440 * Add property, BaseAddress to memory-segment node 441 */ 442 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 443 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcseg->base), 444 PICL_PROP_BASEADDRESS, NULL, NULL); 445 if (err != PICL_SUCCESS) 446 break; 447 448 err = ptree_create_and_add_prop(msegh, &propinfo, &mcseg->base, 449 NULL); 450 if (err != PICL_SUCCESS) 451 break; 452 453 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 454 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcseg->ifactor), 455 PICL_PROP_INTERLEAVE_FACTOR, NULL, NULL); 456 if (err != PICL_SUCCESS) 457 break; 458 459 err = ptree_create_and_add_prop(msegh, &propinfo, 460 &mcseg->ifactor, NULL); 461 if (err != PICL_SUCCESS) 462 break; 463 464 err = add_mem_banks(msegh, fd, mcseg); 465 if (err != PICL_SUCCESS) 466 break; 467 } 468 469 if (err != PICL_SUCCESS) { 470 undo_logical_tree(nsegments); 471 return (err); 472 } 473 474 err = ptree_get_prop_by_name(memh, PICL_PROP_SIZE, &proph); 475 if (err == PICL_SUCCESS) { /* update the value */ 476 err = ptree_update_propval(proph, &memsize, sizeof (memsize)); 477 return (err); 478 } 479 480 /* 481 * Add the size property 482 */ 483 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 484 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (memsize), 485 PICL_PROP_SIZE, NULL, NULL); 486 err = ptree_create_and_add_prop(memh, &propinfo, &memsize, NULL); 487 488 return (err); 489 } 490 491 /* 492 * Add memory-module nodes and properties at each enabled memory-module-group. 493 * The formula of unique id is (id of the given memory module group * 494 * max number of memory modules per memory module group) + index 495 * of memory modules in this memory module group 496 */ 497 static int 498 add_mem_modules(picl_nodehdl_t mmodgrph, struct mc_devgrp *mcdevgrp) 499 { 500 uint64_t size; 501 picl_nodehdl_t dimmh; 502 ptree_propinfo_t propinfo; 503 int i; 504 int err = PICL_SUCCESS; 505 506 size = mcdevgrp->size / mcdevgrp->ndevices; 507 508 /* 509 * Get all memory-modules of the given memory-module-group 510 */ 511 for (i = 0; i < mcdevgrp->ndevices; i++) { 512 /* 513 * Create memory-module node under memory-module-group 514 */ 515 err = ptree_create_and_add_node(mmodgrph, 516 PICL_NAME_MEMORY_MODULE, PICL_CLASS_MEMORY_MODULE, &dimmh); 517 if (err != PICL_SUCCESS) 518 break; 519 520 /* 521 * Add property, Size to memory-module-group node 522 */ 523 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 524 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (size), 525 PICL_PROP_SIZE, NULL, NULL); 526 if (err != PICL_SUCCESS) 527 break; 528 529 err = ptree_create_and_add_prop(dimmh, &propinfo, &size, NULL); 530 if (err != PICL_SUCCESS) 531 break; 532 533 /* 534 * Add property, ID to memory-module-group node 535 */ 536 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 537 PICL_PTYPE_INT, PICL_READ, sizeof (i), PICL_PROP_ID, 538 NULL, NULL); 539 if (err != PICL_SUCCESS) 540 break; 541 542 err = ptree_create_and_add_prop(dimmh, &propinfo, &i, 543 NULL); 544 if (err != PICL_SUCCESS) 545 break; 546 } 547 return (err); 548 } 549 550 /* 551 * Create the subtree at every enabled Memory Controller where size of 552 * memory module group is greater than zero. 553 * Get information via ioctl of memory control driver 554 */ 555 static int 556 create_physical_tree(picl_nodehdl_t mch, void *args) 557 { 558 int i, portid; 559 int err = PICL_SUCCESS; 560 mmodgrp_info_t *mmghdl; 561 picl_nodehdl_t mmodgrph; 562 ptree_propinfo_t propinfo; 563 struct mc_control *mccontrol; 564 struct mc_devgrp mcdevgrp; 565 int fd; 566 567 fd = (int)args; 568 /* 569 * Get portid of memory-controller as the key to get its 570 * configuration via ioctl. 571 */ 572 err = ptree_get_propval_by_name(mch, OBP_PROP_PORTID, &portid, 573 sizeof (portid)); 574 if (err != PICL_SUCCESS) 575 return (err); 576 577 if ((mccontrol = alloca((ndevgrps - 1) * 578 sizeof (mccontrol->devgrpids[0]) + sizeof (*mccontrol))) == NULL) 579 return (PICL_FAILURE); 580 581 mccontrol->id = portid; 582 mccontrol->ndevgrps = ndevgrps; 583 584 if (ioctl(fd, MCIOC_CONTROL, mccontrol) == -1) { 585 if (errno == EINVAL) 586 return (PICL_WALK_CONTINUE); 587 else 588 return (PICL_FAILURE); 589 } 590 591 /* 592 * If returned ndevgrps is zero, Memory Controller is disable, and 593 * skip it. 594 */ 595 if (mccontrol->ndevgrps == 0) 596 return (PICL_WALK_CONTINUE); 597 598 /* 599 * Get all memory module groups of the given memory controller. 600 */ 601 for (i = 0; i < mccontrol->ndevgrps; i++) { 602 int mmglocalid = mccontrol->devgrpids[i].localid; 603 604 mcdevgrp.id = mccontrol->devgrpids[i].globalid; 605 606 if (ioctl(fd, MCIOC_DEVGRP, &mcdevgrp) == -1) 607 return (PICL_FAILURE); 608 609 /* 610 * Node doesn't need to be created if size is 0, i.e. 611 * there is no memory dimm at slot. 612 */ 613 if (mcdevgrp.size == 0) 614 continue; 615 616 /* 617 * Create memory-module-group node under memory-controller 618 */ 619 err = ptree_create_and_add_node(mch, PICL_NAME_MEM_MOD_GROUP, 620 PICL_CLASS_MEMORY_MODULE_GROUP, &mmodgrph); 621 if (err != PICL_SUCCESS) 622 break; 623 624 /* 625 * Allocate space for mmodgrp_info to save the information 626 * so that it is easier to do the undo and setup of the 627 * reference property in logical memory tree. 628 */ 629 if ((mmghdl = malloc(sizeof (*mmghdl))) == NULL) 630 return (PICL_FAILURE); 631 632 /* 633 * Save the information and add it to the beginnong of list. 634 */ 635 mmghdl->mmgid = mcdevgrp.id; 636 mmghdl->mmgh = mmodgrph; 637 mmghdl->mch = mch; 638 mmghdl->next = head2mmodgrp; 639 640 head2mmodgrp = mmghdl; 641 642 /* 643 * Add property, Size to memory-module-group node 644 */ 645 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 646 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (mcdevgrp.size), 647 PICL_PROP_SIZE, NULL, NULL); 648 if (err != PICL_SUCCESS) 649 break; 650 651 err = ptree_create_and_add_prop(mmodgrph, &propinfo, 652 &mcdevgrp.size, NULL); 653 if (err != PICL_SUCCESS) 654 break; 655 656 /* 657 * Add property, ID to memory-module-group node 658 */ 659 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 660 PICL_PTYPE_INT, PICL_READ, sizeof (mmglocalid), 661 PICL_PROP_ID, NULL, NULL); 662 if (err != PICL_SUCCESS) 663 break; 664 665 err = ptree_create_and_add_prop(mmodgrph, &propinfo, 666 &mmglocalid, NULL); 667 if (err != PICL_SUCCESS) 668 break; 669 670 /* 671 * Create all memory-module nodes and properties. 672 */ 673 err = add_mem_modules(mmodgrph, &mcdevgrp); 674 if (err != PICL_SUCCESS) 675 break; 676 } 677 678 if (err == PICL_SUCCESS) 679 return (PICL_WALK_CONTINUE); 680 return (err); 681 } 682 683 /* 684 * Create physical memory tree 685 * memory-controller --- memory-module-group --- memory-module 686 * 687 * It searches all memory-controller nodes in the whole devtree. 688 * It returns failure if encountering error in physical tree. 689 */ 690 static int 691 find_mc_create_tree(picl_nodehdl_t rooth, int fd) 692 { 693 int err; 694 695 err = ptree_walk_tree_by_class(rooth, PICL_CLASS_MEMORY_CONTROLLER, 696 (void *)fd, create_physical_tree); 697 return (err); 698 } 699 700 static int 701 init_mc(void) 702 { 703 struct mc_memconf mcmemconf; 704 int fd; 705 DIR *dirp; 706 struct dirent *retp; 707 char path[PATH_MAX]; 708 int found = 0; 709 int valid_entry = 0; 710 711 /* open the directory */ 712 if ((dirp = opendir(MC_DIR)) == NULL) { 713 /* 714 * As not all platforms have mc drivers that create the 715 * /dev/mc directory, print a message only if there is 716 * an entry found on which the open failed. 717 */ 718 if (errno != ENOENT) 719 syslog(LOG_ERR, EM_INIT_MC_FAILED); 720 return (-1); 721 } 722 723 /* start searching this directory */ 724 while ((retp = readdir(dirp)) != NULL) { 725 /* skip . .. etc... */ 726 if (strcmp(retp->d_name, ".") == 0 || 727 strcmp(retp->d_name, "..") == 0) 728 continue; 729 730 (void) strcpy(path, MC_DIR); 731 (void) strcat(path, retp->d_name); 732 /* open the memory controller driver */ 733 if ((fd = open(path, O_RDONLY, 0)) != -1) { 734 found = 1; 735 break; 736 } 737 if (errno != ENOENT) 738 valid_entry = 1; 739 } 740 (void) closedir(dirp); 741 742 if (!found) { 743 if (valid_entry) 744 syslog(LOG_ERR, EM_INIT_MC_FAILED); 745 return (-1); 746 } 747 748 /* 749 * Initialize some global variables via ioctl 750 */ 751 if (ioctl(fd, MCIOC_MEMCONF, &mcmemconf) == -1) { 752 (void) close(fd); 753 return (-1); 754 } 755 756 nsegments = mcmemconf.nsegments; 757 nbanks = mcmemconf.nbanks; 758 ndevgrps = mcmemconf.ndevgrps; 759 ndevs = mcmemconf.ndevs; 760 transfersize = mcmemconf.xfer_size; 761 762 return (fd); 763 } 764 765 /* 766 * executed as part of .init when the plugin is dlopen()ed 767 */ 768 void 769 piclmemcfg_register(void) 770 { 771 (void) picld_plugin_register(&my_reg_info); 772 } 773 774 /* 775 * init entry point of the plugin 776 * Creates the PICL nodes and properties in the physical and logical aspects. 777 */ 778 void 779 piclmemcfg_init(void) 780 { 781 picl_nodehdl_t plfh; 782 picl_nodehdl_t memh; 783 ptree_propinfo_t propinfo; 784 int fd, err; 785 786 /* 787 * Initialize the header pointer of mmodgrp_info list 788 */ 789 head2mmodgrp = NULL; 790 msegh_info = NULL; 791 792 if ((fd = init_mc()) < 0) 793 return; 794 795 /* 796 * allocate memory to save memory-segment node handles. Thus, 797 * it is easier to delete them if it fails. 798 */ 799 if ((msegh_info = malloc(nsegments * sizeof (picl_nodehdl_t))) == 800 NULL) { 801 syslog(LOG_ERR, EM_INIT_FAILED); 802 (void) close(fd); 803 return; 804 } 805 806 /* 807 * find platform node 808 */ 809 if ((ptree_get_node_by_path(PLATFORM_PATH, &plfh)) != PICL_SUCCESS) { 810 syslog(LOG_ERR, EM_INIT_FAILED); 811 (void) close(fd); 812 return; 813 } 814 815 /* 816 * Find the memory node 817 */ 818 if ((ptree_get_node_by_path(MEMORY_PATH, &memh)) != PICL_SUCCESS) { 819 syslog(LOG_ERR, EM_INIT_FAILED); 820 (void) close(fd); 821 return; 822 } 823 824 /* 825 * Create subtree of memory-controller in the physical aspect. 826 * memory-controller --- memory-module-group --- memory-module 827 */ 828 err = find_mc_create_tree(plfh, fd); 829 830 if (err != PICL_SUCCESS) { 831 undo_phymem_tree(); 832 syslog(LOG_ERR, EM_PHYSIC_MEM_TREE_FAILED); 833 } 834 835 /* 836 * Add property, TransferSize to memory node 837 */ 838 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 839 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (transfersize), 840 PICL_PROP_TRANSFER_SIZE, NULL, NULL); 841 if (err != PICL_SUCCESS) { 842 (void) close(fd); 843 return; 844 } 845 846 err = ptree_create_and_add_prop(memh, &propinfo, 847 &transfersize, NULL); 848 if (err != PICL_SUCCESS) { 849 (void) close(fd); 850 return; 851 } 852 853 /* 854 * Create subtree of memory in the logical aspect. 855 * memory --- memory-segment --- memory-bank 856 */ 857 if ((create_logical_tree(memh, fd)) != PICL_SUCCESS) { 858 syslog(LOG_ERR, EM_LOGIC_MEM_TREE_FAILED); 859 undo_logical_tree(nsegments); 860 } 861 862 (void) close(fd); 863 (void) ptree_register_handler(PICLEVENT_MC_ADDED, 864 piclmemcfg_evhandler, NULL); 865 (void) ptree_register_handler(PICLEVENT_MC_REMOVED, 866 piclmemcfg_evhandler, NULL); 867 } 868 869 /* 870 * fini entry point of the plugin 871 */ 872 void 873 piclmemcfg_fini(void) 874 { 875 (void) ptree_unregister_handler(PICLEVENT_MC_ADDED, 876 piclmemcfg_evhandler, NULL); 877 (void) ptree_unregister_handler(PICLEVENT_MC_REMOVED, 878 piclmemcfg_evhandler, NULL); 879 /* 880 * Release all the allocated memory for global structures 881 */ 882 free_allocated_mem(); 883 if (msegh_info) 884 free(msegh_info); 885 } 886 887 /* 888 * Event handler of this plug-in 889 */ 890 /*ARGSUSED*/ 891 static void 892 piclmemcfg_evhandler(const char *ename, const void *earg, size_t size, 893 void *cookie) 894 { 895 int err; 896 int fd; 897 picl_nodehdl_t memh; 898 picl_nodehdl_t nodeh; 899 int old_nsegs; 900 nvlist_t *nvlp; 901 902 memh = NULL; 903 if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) 904 return; 905 906 if (nvlist_lookup_uint64(nvlp, PICLEVENTARG_NODEHANDLE, &nodeh)) { 907 nvlist_free(nvlp); 908 return; 909 } 910 nvlist_free(nvlp); 911 912 /* 913 * get the memory node 914 */ 915 err = ptree_get_node_by_path(MEMORY_PATH, &memh); 916 if (err != PICL_SUCCESS) 917 return; 918 919 /* 920 * nsegments won't be overwritten until init_mc succeeds 921 */ 922 old_nsegs = nsegments; 923 if ((fd = init_mc()) < 0) 924 return; 925 926 if (strcmp(ename, PICLEVENT_MC_ADDED) == 0) 927 (void) create_physical_tree(nodeh, (void *)fd); 928 else if (strcmp(ename, PICLEVENT_MC_REMOVED) == 0) 929 /* 930 * Delete the entry at the list only since class at PICL is 931 * deleted in devtree plugin. 932 */ 933 (void) del_plugout_mmodgrp(nodeh); 934 935 (void) undo_logical_tree(old_nsegs); 936 free(msegh_info); 937 938 /* 939 * allocate memory to save memory-segment node handles. Thus, 940 * it is easier to delete them if it fails. 941 */ 942 if ((msegh_info = malloc(nsegments * sizeof (picl_nodehdl_t))) == 943 NULL) { 944 (void) close(fd); 945 return; 946 } 947 948 (void) create_logical_tree(memh, fd); 949 950 (void) close(fd); 951 } 952