summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/accessors/p9_get_mem_vpd_keyword.C
blob: 4b392e6829efa63b35fee1d8056083c5fc2770df (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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/accessors/p9_get_mem_vpd_keyword.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016                             */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_get_mem_vpd_keyword.C
/// @brief Return mem vpd keyword based on VDPInfo
///
// *HWP HWP Owner: Dan Crowell <dcrowell@us.ibm.com>
// *HWP HWP Backup: Matt Light <mklight@us.ibm.com>
// *HWP FW Owner: Dan Crowell <dcrowell@us.ibm.com>
// *HWP Team:
// *HWP Level: 3
// *HWP Consumed by: Cronus, FSP, HB

#include <stdint.h>
#include <fapi2.H>
#include <p9_get_mem_vpd_keyword.H>

using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_SYSTEM;
using fapi2::FAPI2_RC_SUCCESS;

//remove the following comments for unit testing
//#undef FAPI_DBG
//#define FAPI_DBG(args...) FAPI_INF(args)

/// Local declartions

/// Structure for the layout of the MR and MT mapping keyword
enum mappingKeywordEnum
{
    MAPPING_LAYOUT_VERSION  = 1,
    MAPPING_LAYOUT_INVALID  = 0xff,
    MAPPING_LAYOUT_LAST     = 0x00,
    MAPPING_LAYOUT_MAXROWS  = 36,  //0..9,A..Z

    MAPPING_LAYOUT_MCS_0        = 0x8000, //mcs position 0
    MAPPING_LAYOUT_MCS_15       = 0x0001, //mcs position 15

    MAPPING_LAYOUT_RANKPAIR_00  = 0x8000, //Rank pair 0x00
    MAPPING_LAYOUT_RANKPAIR_01  = 0x4000, //Rank pair 0x01
    MAPPING_LAYOUT_RANKPAIR_02  = 0x2000, //Rank pair 0x02
    MAPPING_LAYOUT_RANKPAIR_04  = 0x1000, //Rank pair 0x04
    MAPPING_LAYOUT_RANKPAIR_10  = 0x0800, //Rank pair 0x10
    MAPPING_LAYOUT_RANKPAIR_11  = 0x0400, //Rank pair 0x11
    MAPPING_LAYOUT_RANKPAIR_12  = 0x0200, //Rank pair 0x12
    MAPPING_LAYOUT_RANKPAIR_14  = 0x0100, //Rank pair 0x14
    MAPPING_LAYOUT_RANKPAIR_20  = 0x0080, //Rank pair 0x20
    MAPPING_LAYOUT_RANKPAIR_21  = 0x0040, //Rank pair 0x21
    MAPPING_LAYOUT_RANKPAIR_22  = 0x0020, //Rank pair 0x22
    MAPPING_LAYOUT_RANKPAIR_24  = 0x0010, //Rank pair 0x24
    MAPPING_LAYOUT_RANKPAIR_40  = 0x0008, //Rank pair 0x40
    MAPPING_LAYOUT_RANKPAIR_41  = 0x0004, //Rank pair 0x41
    MAPPING_LAYOUT_RANKPAIR_42  = 0x0002, //Rank pair 0x42
    MAPPING_LAYOUT_RANKPAIR_44  = 0x0001, //Rank pair 0x44

    MAPPING_LAYOUT_FREQ_0       = 0x80,   //Frequency index 0 - 1866
    MAPPING_LAYOUT_FREQ_1       = 0x40,   //Frequency index 1 - 2133
    MAPPING_LAYOUT_FREQ_2       = 0x20,   //Frequency index 2 - 2400
    MAPPING_LAYOUT_FREQ_3       = 0x10,   //Frequency index 3 - 2666
};

struct mappingHeader_t //header is first in mapping keyword
{
    uint8_t layoutVersion;  // decode version
    uint8_t numEntries;     // number of criteria mapping entries
    uint8_t reserved;       // reserved
} __attribute__((packed));

// header for Q0 and CK keywords
struct mappingHeader2_t //header is first in mapping keyword
{
    uint8_t layoutVersion;  // decode version
    uint8_t numEntries;     // number of criteria mapping entries (DQ = # of map entries)
    uint8_t blobSize;       // # bytes in each data entry
    uint8_t reserved;
} __attribute__((packed));

struct mappingKeywordRow_t //criteria mapping entries follow header
{
    uint8_t mcsMaskMSB;  // mcs mask high order byte
    uint8_t mcsMaskLSB;  // mcs mask low order byte
    uint8_t rankMaskMSB; // rank mask high order byte
    uint8_t rankMaskLSB; // rank mask low order byte
    uint8_t freqMask;    // low nibble reserved
    char    keywordChar; // 0..9,A..Z
} __attribute__((packed));

struct mappingDqRow_t // DQ map entries following header
{
    fapi2::ATTR_MEMVPD_POS_Type qPosition;
    uint8_t qNum;
} __attribute__((packed));

const size_t DQ_MAP_SIZE    = 36;
const size_t DQ_BLOB_SIZE   = 160;


extern "C"
{

/// @brief Return VPD keyword based on MCS, VPDInfo, and MR/MT mapping
/// The MR and MT keyword contains a header followed by a table.
/// Each row in the table has criteria to select a vpd keyword.
/// DQ keyword uses Q0 as a map to Q1-Q8 keywords.  Q0 and CK have a header.
///
/// @param[in]  i_target, the MCS
/// @param[in]  i_vpd_info, vpd criteria
/// @param[in]  i_pMapping, MR, MT, Q0, or CK keyword data
/// @param[in]  i_mappingSize, size of i_pMapping buffer
/// @param[out] o_keywordInfo, keyword with its vpd information
/// @return FAPI2_RC_SUCCESS iff ok
    fapi2::ReturnCode p9_get_mem_vpd_keyword(
        const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
        const fapi2::VPDInfo<fapi2::TARGET_TYPE_MCS>& i_vpd_info,
        const uint8_t*         i_pMapping,
        const size_t           i_mappingSize,
        fapi2::keywordInfo_t& o_keywordInfo)
    {
        char l_first  = 0;  //first character of return keyword name
        char l_second = MAPPING_LAYOUT_INVALID;  //second character of return keyword name
        fapi2::ATTR_MEMVPD_POS_Type l_mcsPos = 0;
        uint16_t l_mcsMask   = 0;
        uint16_t l_rankMask  = 0;
        uint8_t  l_rankShift = 0;
        uint8_t  l_freqMask  = 0;
        uint32_t l_freqTableIndex = 0;
        constexpr uint32_t l_freqTable[] = {1866, 2133, 2400, 2666};
        uint32_t l_freqTableCnt = sizeof(l_freqTable) / sizeof(l_freqTable[0]);
        uint32_t l_index = 0; //start with first criteria row
        uint32_t l_indexMax = MAPPING_LAYOUT_MAXROWS;
        o_keywordInfo.kwBlobIndex = 0; // default blob is entire keyword data
        o_keywordInfo.kwBlobSize = i_mappingSize;

        const mappingHeader_t* l_mappingHeader = //pointer to header
            reinterpret_cast<const mappingHeader_t*>(i_pMapping);
        const mappingHeader2_t* l_mappingHeader2 = //pointer to header2 (used for DQ and CK)
            reinterpret_cast<const mappingHeader2_t*>(i_pMapping);

        const mappingKeywordRow_t* l_mapping =   //pointer to first criteria row
            reinterpret_cast<const mappingKeywordRow_t*>(i_pMapping +
                    sizeof(mappingHeader_t));

        FAPI_DBG("p9_get_mem_vpd_keyword: enter");

        size_t l_mapping_layout_maxsize;
        uint8_t l_mapping_layout_version;

        // Fill in a data buffer for FFDC purposes
        uint64_t l_ffdc_MAPROW[MAPPING_LAYOUT_MAXROWS];
        memset( l_ffdc_MAPROW, 0, sizeof(l_ffdc_MAPROW) );

        // Validate vpd type and set first keyword name character based on type
        switch (i_vpd_info.iv_vpd_type)
        {
            case fapi2::MT:
                l_first = 'X';  //MT vpd keyword name X0..X9,XA..XZ
                l_mapping_layout_version = MAPPING_LAYOUT_VERSION;
                l_mapping_layout_maxsize = sizeof(mappingHeader_t) +
                                           size_t(sizeof(mappingKeywordRow_t) * MAPPING_LAYOUT_MAXROWS);
                break;

            case fapi2::MR:
                l_first = 'J';  //MR vpd keyword name J0..J9,JA..JZ
                l_mapping_layout_version = MAPPING_LAYOUT_VERSION;
                l_mapping_layout_maxsize = sizeof(mappingHeader_t) +
                                           size_t(sizeof(mappingKeywordRow_t) * MAPPING_LAYOUT_MAXROWS);
                break;

            case fapi2::DQ:
                l_first = 'Q';  //DQ vpd keyword name Q1...Q8
                l_mapping_layout_version = MAPPING_LAYOUT_VERSION;
                l_mapping_layout_maxsize = DQ_MAP_SIZE;
                break;

            case fapi2::CK:
                l_first = 'C';  //CKE vpd keyword name CK
                l_mapping_layout_version = MAPPING_LAYOUT_VERSION;
                l_mapping_layout_maxsize = sizeof(mappingHeader2_t) +
                                           (l_mappingHeader2->numEntries * l_mappingHeader2->blobSize);
                break;

            default:
                FAPI_ASSERT(false,
                            fapi2::GET_MEM_VPD_UNSUPPORTED_TYPE().
                            set_TARGET(i_target).
                            set_VPDTYPE(i_vpd_info.iv_vpd_type),
                            "Invalid vpd type = %d",
                            i_vpd_info.iv_vpd_type);
                break;
        }

        // Validate size of mapping to be at least large enough for biggest
        // mapping table expected.
        FAPI_ASSERT(l_mapping_layout_maxsize <= i_mappingSize,
                    fapi2::GET_MEM_VPD_MAPPING_TOO_SMALL().
                    set_SIZE(size_t(i_mappingSize)).
                    set_EXPECTED(l_mapping_layout_maxsize).
                    set_TARGET(i_target).
                    set_VPDTYPE(i_vpd_info.iv_vpd_type),
                    "Mapping keyword size %d less than min %d expected",
                    i_mappingSize,
                    l_mapping_layout_maxsize);

        // Validate mapping keyword version supported
        FAPI_ASSERT(l_mapping_layout_version == l_mappingHeader->layoutVersion,
                    fapi2::GET_MEM_VPD_UNSUPPORTED_VERSION().
                    set_VERSION(uint8_t(l_mappingHeader->layoutVersion)).
                    set_EXPECTED(uint8_t(l_mapping_layout_version)).
                    set_TARGET(i_target).
                    set_VPDTYPE(i_vpd_info.iv_vpd_type),
                    "Header version %d not supported % expected",
                    l_mappingHeader->layoutVersion,
                    l_mapping_layout_version);

        // Get the MCS position and calculate mask
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MEMVPD_POS,
                               i_target,
                               l_mcsPos),
                 "p9_get_mem_vpd_keyword: get ATTR_MEMVPD_POS failed");
        l_mcsMask = (MAPPING_LAYOUT_MCS_0 >> l_mcsPos); //zero based
        FAPI_DBG ("p9_get_mem_vpd_keyword: mca position = %d mask=0x%04x",
                  l_mcsPos, l_mcsMask);

        if (i_vpd_info.iv_vpd_type == fapi2::CK)
        {
            // verify data index will be valid
            FAPI_ASSERT(l_mcsPos < l_mappingHeader2->numEntries,
                        fapi2::GET_MEM_VPD_ENTRY_NOT_FOUND().
                        set_ENTRY(l_mcsPos).
                        set_MAX_ENTRIES(uint8_t(l_mappingHeader2->numEntries)).
                        set_VERSION(uint8_t(l_mappingHeader2->layoutVersion)).
                        set_TARGET(i_target).
                        set_VPDTYPE(i_vpd_info.iv_vpd_type),
                        "Unsupported entry (%d), max entries (%d)",
                        l_mcsPos,
                        uint8_t(l_mappingHeader2->numEntries));

            o_keywordInfo.kwBlobSize = l_mappingHeader2->blobSize;

            // Setup index to CK section data (ordered by memvpd pos)
            o_keywordInfo.kwBlobIndex = (l_mcsPos * o_keywordInfo.kwBlobSize) +
                                        sizeof(mappingHeader2_t);

            l_second = 'K';
        }
        else if (i_vpd_info.iv_vpd_type == fapi2::DQ)
        {
            // Find which Q# i_target is in
            const mappingDqRow_t* l_dqmapping =   //pointer to first criteria row
                reinterpret_cast<const mappingDqRow_t*>(i_pMapping +
                        sizeof(mappingHeader2_t));

            for (uint8_t i = 0; i < l_mappingHeader->numEntries; i++)
            {
                // Copy data into FFDC buffer
                memcpy( &(l_ffdc_MAPROW[i]),
                        &(l_dqmapping[i]),
                        sizeof(l_dqmapping[i]) );

                if (l_dqmapping[i].qPosition == l_mcsPos)
                {
                    l_second = l_dqmapping[i].qNum;
                    o_keywordInfo.kwBlobSize = DQ_BLOB_SIZE;
                    break;
                }
            }

            FAPI_DBG ("p9_get_mem_vpd_keyword: mcsPos %d -> Q%c keyword data",
                      l_mcsPos, l_second);
        }
        else
        {
            // Get the frequency index and calculate mask
            for (; l_freqTableIndex < l_freqTableCnt; l_freqTableIndex++)
            {
                if (i_vpd_info.iv_freq_mhz == l_freqTable[l_freqTableIndex])
                {
                    break; // found it
                }
            }

            FAPI_ASSERT(l_freqTableIndex < l_freqTableCnt,
                        fapi2::GET_MEM_VPD_UNSUPPORTED_FREQUENCY().
                        set_UNSUPPORTEDFREQ(uint32_t(i_vpd_info.iv_freq_mhz)).
                        set_MEMVPDFREQ0(uint32_t(l_freqTable[0])).
                        set_MEMVPDFREQ1(uint32_t(l_freqTable[1])).
                        set_MEMVPDFREQ2(uint32_t(l_freqTable[2])).
                        set_MEMVPDFREQ3(uint32_t(l_freqTable[3])).
                        set_TARGET(i_target).
                        set_VPDTYPE(i_vpd_info.iv_vpd_type),
                        "Frequency %d not supported by Nimbus",
                        i_vpd_info.iv_freq_mhz);
            l_freqMask = (MAPPING_LAYOUT_FREQ_0 >> l_freqTableIndex); //zero based
            FAPI_DBG ("p9_get_mem_vpd_keyword: frequency index = %d mask=0x%02x",
                      l_freqTableIndex, l_freqMask);

            // Calculate rank count mask. Valid rank counts are 0,1,2 or 4.
            // The mask has a bit for each of the 16 rank pairs of
            // dimm0 rank count by dimm1 count rank.
            // This notation is used by genMemVpd.pl to specify pairs.
            // Order= 0x00, 0x01, 0x02, 0x04, 0x11, 0x12, ... 0x42, 0x44
            switch (i_vpd_info.iv_rank_count_dimm_0)
            {
                case 0: //index into pair order by multiplying by 4
                case 1:
                case 2:
                    l_rankShift =  i_vpd_info.iv_rank_count_dimm_0 * 4;
                    break;

                case 4: // need to use value 3 for rank count 4
                    l_rankShift = 3 * 4;
                    break;

                default:
                    FAPI_ASSERT(false,
                                fapi2::GET_MEM_VPD_UNSUPPORTED_RANK().
                                set_RANK(uint64_t(i_vpd_info.iv_rank_count_dimm_0)).
                                set_TARGET(i_target).
                                set_VPDTYPE(i_vpd_info.iv_vpd_type),
                                "Unsupported rank = %d should be 0,1,2, or 4",
                                i_vpd_info.iv_rank_count_dimm_0);
            }

            switch (i_vpd_info.iv_rank_count_dimm_1)
            {
                case 0: //add in dimm 1 rank count index
                case 1:
                case 2:
                    l_rankShift +=  i_vpd_info.iv_rank_count_dimm_1;
                    break;

                case 4: // need to use value 3 for rank count 4
                    l_rankShift += 3;
                    break;

                default:
                    FAPI_ASSERT(false,
                                fapi2::GET_MEM_VPD_UNSUPPORTED_RANK().
                                set_RANK(uint64_t(i_vpd_info.iv_rank_count_dimm_1)).
                                set_TARGET(i_target).
                                set_VPDTYPE(i_vpd_info.iv_vpd_type),
                                "Unsupported rank = %d should be 0,1,2, or 4",
                                i_vpd_info.iv_rank_count_dimm_1);
            }

            l_rankMask = (MAPPING_LAYOUT_RANKPAIR_00 >> l_rankShift);
            FAPI_DBG("p9_get_mem_vpd_keyword: rank0=%d rank1=%d mask=0x%04x",
                     i_vpd_info.iv_rank_count_dimm_0,
                     i_vpd_info.iv_rank_count_dimm_1,
                     l_rankMask);

            // Use mapping data to find the second vpd keyword character.
            // Select the row where the MCS, Frequency, and rank count pair
            // bit are on in the criteria row in the mapping keyword.
            if (MAPPING_LAYOUT_MAXROWS > l_mappingHeader->numEntries)
            {
                l_indexMax = l_mappingHeader->numEntries;
            }

            // Loop through all of the rows until we find a match
            for (l_index = 0; l_index < l_indexMax; l_index++)
            {
                if (MAPPING_LAYOUT_LAST == l_mapping[l_index].keywordChar)
                {
                    break; //Hit end of table (not expected, but being careful.
                    //The keyword is zero padded by genMemVpd.pl
                }

                // Copy data into FFDC buffer
                memcpy( &(l_ffdc_MAPROW[l_index]),
                        &(l_mapping[l_index]),
                        sizeof(l_mapping[l_index]) );

                // Look for a match
                if ( (l_mcsMask  &
                      (((l_mapping[l_index].mcsMaskMSB) << 8) | //endian sensitive
                       l_mapping[l_index].mcsMaskLSB))  &&
                     (l_rankMask &
                      (((l_mapping[l_index].rankMaskMSB) << 8) | //endian sensitive
                       l_mapping[l_index].rankMaskLSB)) &&
                     (l_freqMask & l_mapping[l_index].freqMask) )
                {
                    // This row covers mca, ranks, and freq
                    l_second = l_mapping[l_index].keywordChar;
                    break;
                }
            }
        }

        //Was a matching row found?
        FAPI_ASSERT(0 != l_second,
                    fapi2::GET_MEM_VPD_NO_MATCH_FOUND().
                    set_MCS(fapi2::ATTR_MEMVPD_POS_Type(l_mcsPos)).
                    set_FREQ(uint32_t(i_vpd_info.iv_freq_mhz)).
                    set_DIMM0RANK(uint64_t(i_vpd_info.iv_rank_count_dimm_0)).
                    set_DIMM1RANK(uint64_t(i_vpd_info.iv_rank_count_dimm_1)).
                    set_HEADER(mappingHeader_t(*l_mappingHeader)).
                    set_TARGET(i_target).
                    set_VPDTYPE(i_vpd_info.iv_vpd_type).
                    set_MAPROW0(l_ffdc_MAPROW[0]).
                    set_MAPROW1(l_ffdc_MAPROW[1]).
                    set_MAPROW2(l_ffdc_MAPROW[2]).
                    set_MAPROW3(l_ffdc_MAPROW[3]).
                    set_MAPROW4(l_ffdc_MAPROW[4]).
                    set_MAPROW5(l_ffdc_MAPROW[5]).
                    set_MAPROW6(l_ffdc_MAPROW[6]).
                    set_MAPROW7(l_ffdc_MAPROW[7]).
                    set_MAPROW8(l_ffdc_MAPROW[8]).
                    set_MAPROW9(l_ffdc_MAPROW[9]),
                    "No match in mapping table");

        //Was a valid keyword name found?
        // Cast needed due to implicit int of enums
        FAPI_ASSERT( static_cast<char>(MAPPING_LAYOUT_INVALID) != l_second,
                     fapi2::GET_MEM_VPD_UNSUPPORTED_CONFIGURATION().
                     set_MCS(fapi2::ATTR_MEMVPD_POS_Type(l_mcsPos)).
                     set_FREQ(uint32_t(i_vpd_info.iv_freq_mhz)).
                     set_DIMM0RANK(uint64_t(i_vpd_info.iv_rank_count_dimm_0)).
                     set_DIMM1RANK(uint64_t(i_vpd_info.iv_rank_count_dimm_1)).
                     set_VPDMCSMASK(uint16_t(((l_mapping[l_index].mcsMaskMSB) << 8) |
                                             l_mapping[l_index].mcsMaskLSB)).
                     set_VPDFREQMASK(uint8_t(l_mapping[l_index].freqMask)).
                     set_VPDRANKMASK(uint8_t(((l_mapping[l_index].rankMaskMSB) << 8) |
                                             l_mapping[l_index].rankMaskLSB)).
                     set_TARGET(i_target).
                     set_VPDTYPE(i_vpd_info.iv_vpd_type),
                     "Unsupported configuration");

        // build the keyword name
        o_keywordInfo.kwName[0] = l_first;
        o_keywordInfo.kwName[1] = l_second;
        o_keywordInfo.kwName[2] = 0;
        FAPI_DBG("p9_get_mem_vpd_keyword: keyword name = %s",
                 o_keywordInfo.kwName);
    fapi_try_exit:

        FAPI_DBG("p9_get_mem_vpd_keyword: exit");
        return fapi2::current_err;
    }

} //extern C
OpenPOWER on IntegriCloud