summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C
blob: 299cb452612dfe1b5e139e026620faa804f4239e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: chips/p9/procedures/hwp/memory/lib/freq/sync.C $              */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* EKB Project                                                            */
/*                                                                        */
/* COPYRIGHT 2016                                                         */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file sync.C
/// @brief Synchronous function implementations
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: HB:FSP
#include  <vector>
#include <map>

#include <fapi2.H>
#include <mss.H>
#include <lib/freq/sync.H>
#include <lib/utils/find.H>

using fapi2::TARGET_TYPE_DIMM;
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_SYSTEM;

namespace mss
{

///
/// @brief Retrieves a mapping of MSS frequency values per mcbist target
/// @param[in] i_targets vector of controller targets
/// @param[out] o_freq_map dimm speed map <key, value> = (mcbist target, frequency)
/// @param[out] o_is_speed_equal true if all map dimm speeds are the same
/// @return FAPI2_RC_SUCCESS iff successful
///
fapi2::ReturnCode dimm_speed_map(const std::vector< fapi2::Target<TARGET_TYPE_MCBIST> >& i_targets,
                                 std::map< fapi2::Target<TARGET_TYPE_MCBIST>, uint64_t >& o_freq_map,
                                 speed_equality& o_is_speed_equal)
{
    FAPI_INF("---- In dimm_speed_pairs ----");

    if(i_targets.empty())
    {
        FAPI_ERR("Empty target vector found when constructing dimm speed mapping!");
        return fapi2::FAPI2_RC_INVALID_PARAMETER;
    }

    // Getting a sample freq value from an arbitrary target (first one)
    // to compare against all other target freq values
    uint64_t l_comparator = 0;
    FAPI_TRY( mss::freq(i_targets[0], l_comparator), "Failed accessor to mss_freq" );

    o_is_speed_equal = speed_equality::EQUAL_DIMM_SPEEDS;

    // Loop through all MCSBISTs and store dimm speeds
    for (const auto& l_mcbist : i_targets)
    {
        uint64_t l_dimm_speed = 0;
        FAPI_TRY( mss::freq(l_mcbist, l_dimm_speed), "Failed accessor to mss_freq" );

        if(l_comparator != l_dimm_speed)
        {
            o_is_speed_equal = speed_equality::NOT_EQUAL_DIMM_SPEEDS;
        }

        FAPI_INF("%s: Dimm speed %d MT/s", c_str(l_mcbist), l_dimm_speed);
        o_freq_map.emplace( std::make_pair(l_mcbist, l_dimm_speed) );
    }

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Deconfigures MCS targets connected to MCBIST
/// @param[in] i_target the controller target
/// @param[in] i_dimm_speed dimm speed in MT/s
/// @param[in] i_nest_freq nest freq in MHz
/// @return true if hardware was deconfigured
///
bool deconfigure(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
                 const uint64_t i_dimm_speed,
                 const uint32_t i_nest_freq)
{
    FAPI_INF("---- In deconfigure ----");
    bool l_is_hw_deconfigured = false;

    // TODO - RTC 155347 fix dimm speed & nest comparison if needed
    if(i_dimm_speed != i_nest_freq)
    {
        // Deconfigure MCSes
        for( const auto& l_mcs : mss::find_targets<TARGET_TYPE_MCS>(i_target) )
        {
            l_is_hw_deconfigured = true;

            PLAT_FAPI_ASSERT_NOEXIT(false,
                                    fapi2::MSS_FREQ_NOT_EQUAL_NEST_FREQ()
                                    .set_MSS_FREQ(i_dimm_speed)
                                    .set_NEST_FREQ(i_nest_freq)
                                    .set_MCS_TARGET(l_mcs),
                                    "Deconfiguring %s",
                                    mss::c_str(l_mcs) );
        }// end for
    }// end if

    return l_is_hw_deconfigured;
}

///
/// @brief Selects synchronous mode and performs requirements enforced by ATTR_REQUIRED_SYNCH_MODE
/// @param[in] i_freq_map dimm speed mapping
/// @param[in] i_equal_dimm_speed tracks whether map has equal dimm speeds
/// @param[in] i_nest_freq nest frequency
/// @param[in] i_required_sync_mode system policy to enforce synchronous mode
/// @param[out] o_selected_sync_mode final synchronous mode
/// @return FAPI2_RC_SUCCESS iff successful
///
fapi2::ReturnCode select_sync_mode(const std::map< fapi2::Target<TARGET_TYPE_MCBIST>, uint64_t >& i_freq_map,
                                   const speed_equality i_equal_dimm_speed,
                                   const uint32_t i_nest_freq,
                                   const uint8_t i_required_sync_mode,
                                   sync_mode& o_selected_sync_mode)
{
    FAPI_INF("---- In select_sync_mode ----");

    // Implementing frequency handling discussion:
    // https://w3-connections.ibm.com/forums/html/topic?id=1222318f-5992-4342-a858-b75594df1be3&ps=
    // Summary: We will always use async mode if we don't see a perfect match of dimm frequencies that match the nest
    switch(i_equal_dimm_speed)
    {
        case speed_equality::EQUAL_DIMM_SPEEDS:

            // Do not run synchronously, even if the frequencies match
            if (i_required_sync_mode == fapi2::ENUM_ATTR_REQUIRED_SYNCH_MODE_NEVER)
            {
                o_selected_sync_mode = sync_mode::MC_NOT_IN_SYNC;
                break;
            }

            // Run synchronously if the dimm and nest freq matches
            // Implicitly covers case when ATTR_REQUIRED_SYNCH_MODE is
            // ALWAYS and UNDETERMINED
            if( i_freq_map.begin()->second  == i_nest_freq)
            {
                o_selected_sync_mode = sync_mode::MC_IN_SYNC;
            }
            else
            {
                o_selected_sync_mode =  sync_mode::MC_NOT_IN_SYNC;
            }

            break;

        case speed_equality::NOT_EQUAL_DIMM_SPEEDS:

            // Require matching frequencies and deconfigure memory that does not match the nest
            if( i_required_sync_mode == fapi2::ENUM_ATTR_REQUIRED_SYNCH_MODE_ALWAYS )
            {
                for(const auto& l_it : i_freq_map)
                {
                    // This can be refactored to return info people might
                    // need.  Until then this returns true if hw was deconfigured
                    // FFDC prints out location
                    deconfigure(l_it.first, l_it.second, i_nest_freq);

                }// end for
            }// end if

            // Implicitly covers case when ATTR_REQUIRED_SYNCH_MODE is
            // NEVER, ALWAYS, and UNDETERMINED
            o_selected_sync_mode = sync_mode::MC_NOT_IN_SYNC;

            break;

        default:
            FAPI_ERR("Invalid speed_equality parameter!");
            return fapi2::FAPI2_RC_INVALID_PARAMETER;
            break;
    }// end switch

    return fapi2::FAPI2_RC_SUCCESS;
}

}// mss
OpenPOWER on IntegriCloud