Blob Blame History Raw
From d0791b8831e2eee3e6942dbcbe716021576a72bd Mon Sep 17 00:00:00 2001
From: Jack Miller <jack@codezen.org>
Date: Thu, 20 Oct 2016 16:43:22 +0530
Subject: [PATCH 25/43] devtree: Add VPD info for BMC based IBM Power System

Power Systems supports various environment and various service
processor types (like IBM FSP, industry standard BMC, etc).

We have processor chip level VPD (part number, serial number etc)
and all cores under chip shares this information.

BMC based Power Systems provides chip VPD information under xscom
node. This patch adds support for adding VPD information for CPU
nodes on BMC based system.

Sample output:
     *-cpu:0
         description: POWER8 (raw), altivec supported
         product: 00UM003
         vendor: PROCESSOR
         physical id: 16
         bus info: cpu@0
         version: 2.0 (pvr 004d 0200)
         serial: YA1932579651
         size: 2061MHz
         capacity: 3491MHz
         capabilities: performance-monitor cpufreq
         configuration: threads=8

Signed-off-by: Jack Miller <jack@codezen.org>
[Reorganized code, updated description - Vasant]
Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
---
 src/core/device-tree.cc | 58 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 56 insertions(+), 2 deletions(-)

diff --git a/src/core/device-tree.cc b/src/core/device-tree.cc
index 16406fd..d61347b 100644
--- a/src/core/device-tree.cc
+++ b/src/core/device-tree.cc
@@ -443,16 +443,19 @@ static void scan_chip_vpd(map <uint32_t, chip_vpd_data *> & vpd)
 
 
 static void fill_core_vpd(hwNode & cpu, string & basepath,
-			  map <uint32_t, chip_vpd_data *> & chip_vpd)
+			  map <uint32_t, chip_vpd_data *> & chip_vpd,
+			  map <uint32_t, string> & xscoms)
 {
   uint32_t chip_id;
   chip_vpd_data *data;
+  string xscom_path;
 
   if (!exists(basepath + "/ibm,chip-id"))
     return;
 
   chip_id = get_u32(basepath + "/ibm,chip-id");
   data = chip_vpd[chip_id];
+  xscom_path = xscoms[chip_id];
 
   if (data)
   {
@@ -460,6 +463,25 @@ static void fill_core_vpd(hwNode & cpu, string & basepath,
     cpu.setSerial(data->serial);
     cpu.setSlot(data->slot);
   }
+
+  if (xscom_path != "")
+  {
+    vector <string> board_pieces;
+
+    splitlines(hw::strip(get_string(xscom_path + "/board-info")),
+	       board_pieces, ' ');
+    if (board_pieces.size() > 0)
+      cpu.setVendor(board_pieces[0]);
+
+    if (exists(xscom_path + "/serial-number"))
+      cpu.setSerial(hw::strip(get_string(xscom_path + "/serial-number")));
+
+    if (exists(xscom_path + "/ibm,slot-location-code"))
+      cpu.setSlot(hw::strip(get_string(xscom_path + "/ibm,slot-location-code")));
+
+    if (exists(xscom_path + "/part-number"))
+      cpu.setProduct(hw::strip(get_string(xscom_path + "/part-number")));
+  }
 }
 
 static void set_cpu_config_threads(hwNode & cpu, const string & basepath)
@@ -488,6 +510,34 @@ static void set_cpu_config_threads(hwNode & cpu, const string & basepath)
 }
 
 
+static void scan_xscom_node(map <uint32_t, string> & xscoms)
+{
+  int n;
+  struct dirent **namelist;
+
+  pushd(DEVICETREE);
+  n = scandir(".", &namelist, selectdir, alphasort);
+  popd();
+
+  if (n <= 0)
+    return;
+
+  for (int i = 0; i < n; i++) {
+    string sname = string(namelist[i]->d_name);
+    string fullpath = "";
+    int chip_id = 0;
+
+    if (sname.substr(0,5) == "xscom") {
+      fullpath = string(DEVICETREE) + "/" + sname;
+      chip_id = get_u32(fullpath + "/ibm,chip-id");
+      xscoms.insert(std::pair<uint32_t, string>(chip_id, fullpath));
+    }
+
+    free(namelist[i]);
+  }
+  free(namelist);
+}
+
 static void scan_devtree_cpu_power(hwNode & core)
 {
   int n;
@@ -496,6 +546,7 @@ static void scan_devtree_cpu_power(hwNode & core)
   map <uint32_t, pair<uint32_t, vector <hwNode> > > l2_caches;
   map <uint32_t, vector <hwNode> > l3_caches;
   map <uint32_t, chip_vpd_data *> chip_vpd;
+  map <uint32_t, string> xscoms;
 
   pushd(DEVICETREE "/cpus");
   n = scandir(".", &namelist, selectdir, alphasort);
@@ -578,6 +629,9 @@ static void scan_devtree_cpu_power(hwNode & core)
    */
   scan_chip_vpd(chip_vpd);
 
+  // List all xscom nodes under DT
+  scan_xscom_node(xscoms);
+
   for (int i = 0; i < n; i++) //second and final pass
   {
     uint32_t l2_key = 0;
@@ -608,7 +662,7 @@ static void scan_devtree_cpu_power(hwNode & core)
     if (version != 0)
       cpu.setVersion(tostring(version));
 
-    fill_core_vpd(cpu, basepath, chip_vpd);
+    fill_core_vpd(cpu, basepath, chip_vpd, xscoms);
 
     if (hw::strip(get_string(basepath + "/status")) != "okay")
       cpu.disable();
-- 
2.10.2