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
free_allocated_mem(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
del_plugout_mmodgrp(picl_nodehdl_t mch)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
find_mem_mod_grp_hdl(int id,picl_nodehdl_t * mmodgrph)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
undo_phymem_tree(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
add_mem_banks(picl_nodehdl_t msegh,int fd,struct mc_segment * mcseg)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
undo_logical_tree(int nsegments)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
create_logical_tree(picl_nodehdl_t memh,int fd)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
add_mem_modules(picl_nodehdl_t mmodgrph,struct mc_devgrp * mcdevgrp)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
create_physical_tree(picl_nodehdl_t mch,void * args)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
find_mc_create_tree(picl_nodehdl_t rooth,int fd)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
init_mc(void)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
piclmemcfg_register(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
piclmemcfg_init(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
piclmemcfg_fini(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
piclmemcfg_evhandler(const char * ename,const void * earg,size_t size,void * cookie)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