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