Blob Blame History Raw
From f1cd42c0c6f434e15ba322970cfa4519ee1f523d Mon Sep 17 00:00:00 2001
From: Jack Miller <jack@codezen.org>
Date: Tue, 16 Aug 2016 15:08:51 -0500
Subject: [PATCH 38/43] devtree: Report memory info for BMC based Power System

Some variants of Power System (BMC service processor system) device tree
contains SPD information. Also it has memory-buffer representation in
device tree.

This patch adds support to display memory information on this system.

Sample output;
        *-bank:1
             description: RDIMM DDR3 1600 MHz (0.6ns)
             product: HMT42GR7BFR4A-PB
             vendor: Hynix Semiconductor (Hyundai Electronics)
             physical id: 1
             version: 5438,15 33,01
             serial: 0x10c0af2c
             slot: Physical:/Sys0/Node0/DIMM11
             size: 16GiB
             clock: 1333MHz (0.8ns)
             capabilities: ecc spd-1.3
             configuration: errordetection=ecc

Signed-off-by: Jack Miller <jack@codezen.org>
[Updated description, fixed minor issues - Vasant]
Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
---
 src/core/device-tree.cc | 71 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 66 insertions(+), 5 deletions(-)

diff --git a/src/core/device-tree.cc b/src/core/device-tree.cc
index 41034e5..b7d0d57 100644
--- a/src/core/device-tree.cc
+++ b/src/core/device-tree.cc
@@ -753,6 +753,57 @@ static void scan_devtree_cpu_power(hwNode & core)
     delete it->second;
 }
 
+static bool add_memory_bank_mba_dimm(string path,
+				     unsigned long serial, hwNode & bank)
+{
+  bool found = false;
+  int n;
+  struct dirent **namelist;
+
+  pushd(path);
+  n = scandir(".", &namelist, selectdir, alphasort);
+  popd();
+
+  if (n < 0)
+    return found;
+
+  for (int i = 0; i < n; i++)
+  {
+    string sname = string(namelist[i]->d_name);
+    string fullpath = path + "/" + sname;
+
+    if (found)
+    {
+      free(namelist[i]);
+      continue;
+    }
+
+    if (sname.substr(0, 13) == "memory-buffer")
+    {
+      if (exists(fullpath + "/frequency-mhz"))
+      {
+        int hz = get_u32(fullpath + "/frequency-mhz") * 1000000;
+        bank.setClock(hz);
+      }
+      found = add_memory_bank_mba_dimm(fullpath, serial, bank);
+    } else if (sname.substr(0, 3) == "mba") {
+      found = add_memory_bank_mba_dimm(fullpath, serial, bank);
+    } else if ((sname.substr(0, 4) == "dimm") &&
+	       (get_u32(fullpath + "/serial-number") == serial)) {
+      vector < reg_entry > regs = get_reg_property(fullpath);
+      bank.setSize(regs[0].size);
+
+      bank.setSlot(hw::strip(get_string(fullpath + "/ibm,slot-location-code")));
+      found = true;
+    }
+    free(namelist[i]);
+  }
+
+  free(namelist);
+  return found;
+}
+
+
 static void add_memory_bank_spd(string path, hwNode & bank)
 {
   char dimmversion[20];
@@ -885,6 +936,8 @@ static void add_memory_bank_spd(string path, hwNode & bank)
   snprintf(buff, sizeof(buff), "0x%lx", serial);
   bank.setSerial(buff);
 
+  add_memory_bank_mba_dimm(DEVICETREE, serial, bank);
+
   snprintf(buff, sizeof(buff), "spd-%d.%d", (version & 0xF0) >> 4, version & 0x0F);
   bank.addCapability(buff);
 }
@@ -895,18 +948,17 @@ static void add_memory_bank(string name, string path, hwNode & core)
   string product;
   int n;
 
+  hwNode *memory = core.getChild("memory");
+  if(!memory)
+    memory = core.addChild(hwNode("memory", hw::memory));
+
   pushd(path + name);
   if(name.substr(0, 7) == "ms-dimm")
   {
-    hwNode *memory = core.getChild("memory");
-
     hwNode bank("bank", hw::memory);
     bank.claim(true);
     bank.addHint("icon", string("memory"));
 
-    if(!memory)
-      memory = core.addChild(hwNode("memory", hw::memory));
-
     if(exists("serial-number"))
       bank.setSerial(hw::strip(get_string("serial-number")));
 
@@ -926,6 +978,15 @@ static void add_memory_bank(string name, string path, hwNode & core)
       bank.setSize(size*1024*1024);
 
     memory->addChild(bank);
+  } else if(name.substr(0, 4) == "dimm") {
+    hwNode bank("bank", hw::memory);
+    bank.claim(true);
+    bank.addHint("icon", string("memory"));
+
+    // Parse Memory SPD data
+    add_memory_bank_spd(path + name + "/spd", bank);
+
+    memory->addChild(bank);
   }
 
   n = scandir(".", &dirlist, selectdir, alphasort);
-- 
2.10.2