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