1*ed7fb7aeSJayanth Othayoth /**
2*ed7fb7aeSJayanth Othayoth  * Copyright © 2022 IBM Corporation
3*ed7fb7aeSJayanth Othayoth  *
4*ed7fb7aeSJayanth Othayoth  * Licensed under the Apache License, Version 2.0 (the "License");
5*ed7fb7aeSJayanth Othayoth  * you may not use this file except in compliance with the License.
6*ed7fb7aeSJayanth Othayoth  * You may obtain a copy of the License at
7*ed7fb7aeSJayanth Othayoth  *
8*ed7fb7aeSJayanth Othayoth  *     http://www.apache.org/licenses/LICENSE-2.0
9*ed7fb7aeSJayanth Othayoth  *
10*ed7fb7aeSJayanth Othayoth  * Unless required by applicable law or agreed to in writing, software
11*ed7fb7aeSJayanth Othayoth  * distributed under the License is distributed on an "AS IS" BASIS,
12*ed7fb7aeSJayanth Othayoth  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ed7fb7aeSJayanth Othayoth  * See the License for the specific language governing permissions and
14*ed7fb7aeSJayanth Othayoth  * limitations under the License.
15*ed7fb7aeSJayanth Othayoth  */
16*ed7fb7aeSJayanth Othayoth 
17*ed7fb7aeSJayanth Othayoth #include "extensions/phal/clock_logger.hpp"
18*ed7fb7aeSJayanth Othayoth 
19*ed7fb7aeSJayanth Othayoth #include "util.hpp"
20*ed7fb7aeSJayanth Othayoth 
21*ed7fb7aeSJayanth Othayoth #include <attributes_info.H>
22*ed7fb7aeSJayanth Othayoth #include <libphal.H>
23*ed7fb7aeSJayanth Othayoth 
24*ed7fb7aeSJayanth Othayoth #include <phosphor-logging/lg2.hpp>
25*ed7fb7aeSJayanth Othayoth #include <sdeventplus/event.hpp>
26*ed7fb7aeSJayanth Othayoth #include <sdeventplus/utility/timer.hpp>
27*ed7fb7aeSJayanth Othayoth 
28*ed7fb7aeSJayanth Othayoth #include <chrono>
29*ed7fb7aeSJayanth Othayoth 
30*ed7fb7aeSJayanth Othayoth using namespace openpower::pel;
31*ed7fb7aeSJayanth Othayoth 
32*ed7fb7aeSJayanth Othayoth PHOSPHOR_LOG2_USING;
33*ed7fb7aeSJayanth Othayoth 
34*ed7fb7aeSJayanth Othayoth namespace openpower::phal::clock
35*ed7fb7aeSJayanth Othayoth {
36*ed7fb7aeSJayanth Othayoth constexpr auto CLOCK_DAILY_LOGGER_TIMEOUT_IN_HOUR = 24;
37*ed7fb7aeSJayanth Othayoth 
38*ed7fb7aeSJayanth Othayoth Manager::Manager(const sdeventplus::Event& event) :
39*ed7fb7aeSJayanth Othayoth     _event(event), timer(event, std::bind(&Manager::timerExpired, this))
40*ed7fb7aeSJayanth Othayoth 
41*ed7fb7aeSJayanth Othayoth {
42*ed7fb7aeSJayanth Othayoth     try
43*ed7fb7aeSJayanth Othayoth     {
44*ed7fb7aeSJayanth Othayoth         // pdbg initialisation
45*ed7fb7aeSJayanth Othayoth         openpower::phal::pdbg::init();
46*ed7fb7aeSJayanth Othayoth 
47*ed7fb7aeSJayanth Othayoth         // Create clock data log.
48*ed7fb7aeSJayanth Othayoth         createClockDataLog();
49*ed7fb7aeSJayanth Othayoth     }
50*ed7fb7aeSJayanth Othayoth     catch (const std::exception& e)
51*ed7fb7aeSJayanth Othayoth     {
52*ed7fb7aeSJayanth Othayoth         error("Clock Data Log exception ({ERROR})", "ERROR", e);
53*ed7fb7aeSJayanth Othayoth     }
54*ed7fb7aeSJayanth Othayoth 
55*ed7fb7aeSJayanth Othayoth     addTimer();
56*ed7fb7aeSJayanth Othayoth }
57*ed7fb7aeSJayanth Othayoth 
58*ed7fb7aeSJayanth Othayoth void Manager::addTimer()
59*ed7fb7aeSJayanth Othayoth {
60*ed7fb7aeSJayanth Othayoth     // Set timer for 24 hours.
61*ed7fb7aeSJayanth Othayoth     timer.restart(std::chrono::hours(CLOCK_DAILY_LOGGER_TIMEOUT_IN_HOUR));
62*ed7fb7aeSJayanth Othayoth }
63*ed7fb7aeSJayanth Othayoth 
64*ed7fb7aeSJayanth Othayoth void Manager::timerExpired()
65*ed7fb7aeSJayanth Othayoth {
66*ed7fb7aeSJayanth Othayoth     info("Clock daily logging started");
67*ed7fb7aeSJayanth Othayoth 
68*ed7fb7aeSJayanth Othayoth     try
69*ed7fb7aeSJayanth Othayoth     {
70*ed7fb7aeSJayanth Othayoth         // Create clock data log.
71*ed7fb7aeSJayanth Othayoth         createClockDataLog();
72*ed7fb7aeSJayanth Othayoth     }
73*ed7fb7aeSJayanth Othayoth     catch (const std::exception& e)
74*ed7fb7aeSJayanth Othayoth     {
75*ed7fb7aeSJayanth Othayoth         error("createClockDataLog exception ({ERROR})", "ERROR", e);
76*ed7fb7aeSJayanth Othayoth     }
77*ed7fb7aeSJayanth Othayoth }
78*ed7fb7aeSJayanth Othayoth 
79*ed7fb7aeSJayanth Othayoth void Manager::createClockDataLog()
80*ed7fb7aeSJayanth Othayoth {
81*ed7fb7aeSJayanth Othayoth     // check chassis power state.
82*ed7fb7aeSJayanth Othayoth     auto powerState = openpower::util::getChassisPowerState();
83*ed7fb7aeSJayanth Othayoth 
84*ed7fb7aeSJayanth Othayoth     if (powerState != "xyz.openbmc_project.State.Chassis.PowerState.On")
85*ed7fb7aeSJayanth Othayoth     {
86*ed7fb7aeSJayanth Othayoth         warning("The chassis power state({POWERSTATE}) is not ON, Skipping "
87*ed7fb7aeSJayanth Othayoth                 "clock data "
88*ed7fb7aeSJayanth Othayoth                 "logging",
89*ed7fb7aeSJayanth Othayoth                 "POWERSTATE", powerState);
90*ed7fb7aeSJayanth Othayoth         return;
91*ed7fb7aeSJayanth Othayoth     }
92*ed7fb7aeSJayanth Othayoth 
93*ed7fb7aeSJayanth Othayoth     // Data logger storage
94*ed7fb7aeSJayanth Othayoth     FFDCData clockDataLog;
95*ed7fb7aeSJayanth Othayoth 
96*ed7fb7aeSJayanth Othayoth     struct pdbg_target* procTarget;
97*ed7fb7aeSJayanth Othayoth     ATTR_HWAS_STATE_Type hwasState;
98*ed7fb7aeSJayanth Othayoth     pdbg_for_each_class_target("proc", procTarget)
99*ed7fb7aeSJayanth Othayoth     {
100*ed7fb7aeSJayanth Othayoth         if (DT_GET_PROP(ATTR_HWAS_STATE, procTarget, hwasState))
101*ed7fb7aeSJayanth Othayoth         {
102*ed7fb7aeSJayanth Othayoth             error("{TARGET} Could not read HWAS_STATE attribute", "TARGET",
103*ed7fb7aeSJayanth Othayoth                   pdbg_target_path(procTarget));
104*ed7fb7aeSJayanth Othayoth             continue;
105*ed7fb7aeSJayanth Othayoth         }
106*ed7fb7aeSJayanth Othayoth         if (!hwasState.present)
107*ed7fb7aeSJayanth Othayoth         {
108*ed7fb7aeSJayanth Othayoth             continue;
109*ed7fb7aeSJayanth Othayoth         }
110*ed7fb7aeSJayanth Othayoth 
111*ed7fb7aeSJayanth Othayoth         auto index = std::to_string(pdbg_target_index(procTarget));
112*ed7fb7aeSJayanth Othayoth 
113*ed7fb7aeSJayanth Othayoth         // update functional State
114*ed7fb7aeSJayanth Othayoth         std::string funState = "Non Functional";
115*ed7fb7aeSJayanth Othayoth 
116*ed7fb7aeSJayanth Othayoth         if (hwasState.functional)
117*ed7fb7aeSJayanth Othayoth         {
118*ed7fb7aeSJayanth Othayoth             funState = "Functional";
119*ed7fb7aeSJayanth Othayoth         }
120*ed7fb7aeSJayanth Othayoth         std::stringstream ssState;
121*ed7fb7aeSJayanth Othayoth         ssState << "Proc" << index;
122*ed7fb7aeSJayanth Othayoth         clockDataLog.push_back(std::make_pair(ssState.str(), funState));
123*ed7fb7aeSJayanth Othayoth 
124*ed7fb7aeSJayanth Othayoth         // update location code information
125*ed7fb7aeSJayanth Othayoth         ATTR_LOCATION_CODE_Type locationCode;
126*ed7fb7aeSJayanth Othayoth         memset(&locationCode, '\0', sizeof(locationCode));
127*ed7fb7aeSJayanth Othayoth         try
128*ed7fb7aeSJayanth Othayoth         {
129*ed7fb7aeSJayanth Othayoth             openpower::phal::pdbg::getLocationCode(procTarget, locationCode);
130*ed7fb7aeSJayanth Othayoth         }
131*ed7fb7aeSJayanth Othayoth         catch (const std::exception& e)
132*ed7fb7aeSJayanth Othayoth         {
133*ed7fb7aeSJayanth Othayoth             error("getLocationCode on {TARGET} thrown exception ({ERROR})",
134*ed7fb7aeSJayanth Othayoth                   "TARGET", pdbg_target_path(procTarget), "ERROR", e);
135*ed7fb7aeSJayanth Othayoth         }
136*ed7fb7aeSJayanth Othayoth         std::stringstream ssLoc;
137*ed7fb7aeSJayanth Othayoth         ssLoc << "Proc" << index << " Location Code";
138*ed7fb7aeSJayanth Othayoth         clockDataLog.push_back(std::make_pair(ssLoc.str(), locationCode));
139*ed7fb7aeSJayanth Othayoth 
140*ed7fb7aeSJayanth Othayoth         // Update Processor EC level
141*ed7fb7aeSJayanth Othayoth         ATTR_EC_Type ecVal = 0;
142*ed7fb7aeSJayanth Othayoth         if (DT_GET_PROP(ATTR_EC, procTarget, ecVal))
143*ed7fb7aeSJayanth Othayoth         {
144*ed7fb7aeSJayanth Othayoth             error("Could not read ATTR_EC  attribute");
145*ed7fb7aeSJayanth Othayoth         }
146*ed7fb7aeSJayanth Othayoth         std::stringstream ssEC;
147*ed7fb7aeSJayanth Othayoth         ssEC << "Proc" << index << " EC";
148*ed7fb7aeSJayanth Othayoth 
149*ed7fb7aeSJayanth Othayoth         std::stringstream ssECVal;
150*ed7fb7aeSJayanth Othayoth         ssECVal << "0x" << std::setfill('0') << std::setw(10) << std::hex
151*ed7fb7aeSJayanth Othayoth                 << (uint16_t)ecVal;
152*ed7fb7aeSJayanth Othayoth         clockDataLog.push_back(std::make_pair(ssEC.str(), ssECVal.str()));
153*ed7fb7aeSJayanth Othayoth     }
154*ed7fb7aeSJayanth Othayoth 
155*ed7fb7aeSJayanth Othayoth     openpower::pel::createPEL("org.open_power.PHAL.Info.ClockDailyLog",
156*ed7fb7aeSJayanth Othayoth                               clockDataLog);
157*ed7fb7aeSJayanth Othayoth }
158*ed7fb7aeSJayanth Othayoth 
159*ed7fb7aeSJayanth Othayoth } // namespace openpower::phal::clock
160