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