summaryrefslogtreecommitdiffstats
path: root/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C')
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C506
1 files changed, 488 insertions, 18 deletions
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C b/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C
index 41b0de3ea..40653ee09 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2017,2018 */
+/* Contributors Listed Below - COPYRIGHT 2017,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -64,7 +64,7 @@ bool isEnabled()
!isMfgAvpEnabled() && !isMfgHdatAvpEnabled() );
}
-int32_t __getAddrConfig( ExtensibleChip * i_mcaChip, uint8_t i_dslct,
+int32_t __getAddrConfig( ExtensibleChip * i_chip, uint8_t i_dslct,
bool & o_twoDimmConfig, uint8_t & o_mrnkBits,
uint8_t & o_srnkBits, uint8_t & o_extraRowBits )
{
@@ -72,12 +72,12 @@ int32_t __getAddrConfig( ExtensibleChip * i_mcaChip, uint8_t i_dslct,
int32_t o_rc = SUCCESS;
- SCAN_COMM_REGISTER_CLASS * reg = i_mcaChip->getRegister( "MC_ADDR_TRANS" );
+ SCAN_COMM_REGISTER_CLASS * reg = i_chip->getRegister( "MC_ADDR_TRANS" );
o_rc = reg->Read();
if ( SUCCESS != o_rc )
{
- PRDF_ERR( PRDF_FUNC "Read failed on MC_ADDR_TRANS: i_mcaChip=0x%08x",
- i_mcaChip->getHuid() );
+ PRDF_ERR( PRDF_FUNC "Read failed on MC_ADDR_TRANS: i_chip=0x%08x",
+ i_chip->getHuid() );
return o_rc;
}
@@ -98,8 +98,8 @@ int32_t __getAddrConfig( ExtensibleChip * i_mcaChip, uint8_t i_dslct,
// for some reason B2 is valid, there is definitely a bug.
if ( reg->IsBitSet(i_dslct ? 28:12) )
{
- PRDF_ERR( PRDF_FUNC "B2 enabled in MC_ADDR_TRANS: i_mcaChip=0x%08x "
- "i_dslct=%d", i_mcaChip->getHuid(), i_dslct );
+ PRDF_ERR( PRDF_FUNC "B2 enabled in MC_ADDR_TRANS: i_chip=0x%08x "
+ "i_dslct=%d", i_chip->getHuid(), i_dslct );
return FAIL;
}
@@ -386,7 +386,7 @@ int32_t __getPortAddr<TYPE_MCA>( ExtensibleChip * i_chip, MemAddr i_addr,
// Local vars for address fields
uint64_t col = reverseBits(i_addr.getCol(), 7); // C9 C8 C7 C6 C5 C4 C3
uint64_t row = reverseBits(i_addr.getRow(), 18); // R17 R16 R15 .. R1 R0
- uint64_t bnk = i_addr.getBank(); // BG0 BG1 B0 B1 B2
+ uint64_t bnk = i_addr.getBank(); // B0 B1 B2 BG0 BG1
uint64_t srnk = i_addr.getRank().getSlave(); // S0 S1 S2
uint64_t mrnk = i_addr.getRank().getRankSlct(); // M0 M1
uint64_t dslct = i_addr.getRank().getDimmSlct(); // D
@@ -473,6 +473,266 @@ int32_t __getPortAddr<TYPE_MCA>( ExtensibleChip * i_chip, MemAddr i_addr,
return o_rc;
}
+void __adjustCapiAddrBitPos( uint8_t & io_bitPos )
+{
+ // Note: the translation bitmaps are all 5 bits that are defined
+ // consistently as:
+ // 00000 = CAPI_Address(5)
+ // 00001 = CAPI_Address(6)
+ // 00010 = CAPI_Address(7)
+ // ...
+ // 01010 = CAPI_Address(15)
+ // 01011 = CAPI_Address(31)
+ // 01100 = CAPI_Address(32)
+ // ...
+ // 10011 = CAPI_Address(39)
+ // So the value from the regs can be converted to the CAPI address bit pos
+ // by adding 5 if the value is less than or equal to 10, or by adding 20
+ // if it is above 10.
+
+ if ( io_bitPos <= 10 )
+ {
+ io_bitPos += 5;
+ }
+ else
+ {
+ io_bitPos += 20;
+ }
+}
+
+template <>
+int32_t __getPortAddr<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip, MemAddr i_addr,
+ uint64_t & o_addr )
+{
+ #define PRDF_FUNC "[MemDealloc::__getPortAddr<TYPE_OCMB_CHIP>] "
+
+ int32_t o_rc = SUCCESS;
+
+ o_addr = 0;
+
+ // Local vars for address fields
+ uint64_t col = reverseBits(i_addr.getCol(), 7); // C9 C8 C7 C6 C5 C4 C3
+ uint64_t row = reverseBits(i_addr.getRow(), 18); // R17 R16 R15 .. R1 R0
+ uint64_t bnk = i_addr.getBank(); // B0 B1 B2 BG0 BG1
+ uint64_t srnk = i_addr.getRank().getSlave(); // S0 S1 S2
+ uint64_t mrnk = i_addr.getRank().getRankSlct(); // M0 M1
+ uint64_t dslct = i_addr.getRank().getDimmSlct(); // D
+
+ // Determine if a two DIMM config is used. Also, determine how many
+ // mrank (M0-M1), srnk (S0-S2), or extra row (R17-R15) bits are used.
+ bool twoDimmConfig;
+ uint8_t mrnkBits, srnkBits, extraRowBits;
+ o_rc = __getAddrConfig( i_chip, dslct, twoDimmConfig, mrnkBits, srnkBits,
+ extraRowBits );
+ if ( SUCCESS != o_rc ) return o_rc;
+
+ // Mask off the non-configured bits. If this address came from hardware,
+ // this would not be a problem. However, the get_mrank_range() and
+ // get_srank_range() HWPS got lazy just set the entire fields and did not
+ // take into account the actual bit ranges.
+ mrnk = __maskBits( mrnk, mrnkBits );
+ srnk = __maskBits( srnk, srnkBits );
+ row = __maskBits( row, 15 + extraRowBits );
+
+ // Insert the needed bits based on the config defined in the MC Address
+ // Translation Registers.
+
+ uint8_t bitPos = 0;
+
+ // Split the row into its components.
+ uint8_t r17 = (row & 0x20000) >> 17;
+ uint8_t r16 = (row & 0x10000) >> 16;
+ uint8_t r15 = (row & 0x08000) >> 15;
+ uint16_t r14_r0 = (row & 0x07fff);
+
+ // Split the master rank and slave rank into their components
+ uint8_t m0 = (mrnk & 0x2) >> 1;
+ uint8_t m1 = (mrnk & 0x1);
+
+ uint8_t s0 = (srnk & 0x4) >> 2;
+ uint8_t s1 = (srnk & 0x2) >> 1;
+ uint8_t s2 = (srnk & 0x1);
+
+ // Split the column into its components
+ uint8_t c9 = (col & 0x40) >> 6;
+ uint8_t c8 = (col & 0x20) >> 5;
+ uint8_t c7 = (col & 0x10) >> 4;
+ uint8_t c6 = (col & 0x08) >> 3;
+ uint8_t c5 = (col & 0x04) >> 2;
+ uint8_t c4 = (col & 0x02) >> 1;
+ uint8_t c3 = (col & 0x01);
+
+ // Split the bank and bank group into their components
+ // Note: B2 is not used for OCMB
+ uint8_t b0 = (bnk & 0x10) >> 4;
+ uint8_t b1 = (bnk & 0x08) >> 3;
+
+ uint8_t bg0 = (bnk & 0x2) >> 1;
+ uint8_t bg1 = (bnk & 0x1);
+
+ // Row bits 14:0 are always at CAPI addr position 30:16
+ o_addr |= (r14_r0 << 16);
+
+ // Check MC_ADDR_TRANS0 register for bit positions
+ SCAN_COMM_REGISTER_CLASS * reg = i_chip->getRegister( "MC_ADDR_TRANS" );
+ o_rc = reg->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read failed on MC_ADDR_TRANS: i_chip=0x%08x",
+ i_chip->getHuid() );
+ return o_rc;
+ }
+
+ // If the DIMM select is valid, insert that bit
+ if ( twoDimmConfig )
+ {
+ // DIMM bitmap: MC_ADDR_TRANS0[33:37]
+ bitPos = reg->GetBitFieldJustified( 33, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (dslct << bitPos);
+ }
+
+ // Insert any of the master rank bits that are valid
+ switch( mrnkBits )
+ {
+ case 2:
+ // Master rank 0 bitmap: MC_ADDR_TRANS0[38:42]
+ bitPos = reg->GetBitFieldJustified( 38, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (m0 << bitPos);
+ case 1:
+ // Master rank 1 bitmap: MC_ADDR_TRANS0[43:47]
+ bitPos = reg->GetBitFieldJustified( 43, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (m1 << bitPos);
+ break;
+ }
+
+ // Insert any extra row bits (17:15) that are valid
+ switch ( extraRowBits )
+ {
+ case 3:
+ // Row 17 bitmap: MC_ADDR_TRANS0[49:53]
+ bitPos = reg->GetBitFieldJustified( 49, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (r17 << bitPos);
+ case 2:
+ // Row 16 bitmap: MC_ADDR_TRANS0[54:58]
+ bitPos = reg->GetBitFieldJustified( 54, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (r16 << bitPos);
+ case 1:
+ // Row 15 bitmap: MC_ADDR_TRANS0[59:63]
+ bitPos = reg->GetBitFieldJustified( 59, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (r15 << bitPos);
+ break;
+ }
+
+ // Check MC_ADDR_TRANS1 register for bit positions
+ reg = i_chip->getRegister( "MC_ADDR_TRANS1" );
+ o_rc = reg->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read failed on MC_ADDR_TRANS1: i_chip=0x%08x",
+ i_chip->getHuid() );
+ return o_rc;
+ }
+
+ // Insert any of the slave rank bits that are valid
+ switch ( srnkBits )
+ {
+ case 3:
+ // Slave rank 0 bitmap: MC_ADDR_TRANS1[3:7]
+ bitPos = reg->GetBitFieldJustified( 3, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (s0 << bitPos);
+ case 2:
+ // Slave rank 1 bitmap: MC_ADDR_TRANS1[11:15]
+ bitPos = reg->GetBitFieldJustified( 11, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (s1 << bitPos);
+ case 1:
+ // Slave rank 2 bitmap: MC_ADDR_TRANS1[19:23]
+ bitPos = reg->GetBitFieldJustified( 19, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (s2 << bitPos);
+ break;
+ }
+
+ // Column 3 bitmap: MC_ADDR_TRANS1[30:34]
+ bitPos = reg->GetBitFieldJustified( 30, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (c3 << bitPos);
+
+ // Column 4 bitmap: MC_ADDR_TRANS1[35:39]
+ bitPos = reg->GetBitFieldJustified( 35, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (c4 << bitPos);
+
+ // Column 5 bitmap: MC_ADDR_TRANS1[43:47]
+ bitPos = reg->GetBitFieldJustified( 43, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (c5 << bitPos);
+
+ // Column 6 bitmap: MC_ADDR_TRANS1[51:55]
+ bitPos = reg->GetBitFieldJustified( 51, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (c6 << bitPos);
+
+ // Column 7 bitmap: MC_ADDR_TRANS1[59:63]
+ bitPos = reg->GetBitFieldJustified( 59, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (c7 << bitPos);
+
+ // Check MC_ADDR_TRANS2 register for bit positions
+ reg = i_chip->getRegister( "MC_ADDR_TRANS2" );
+ o_rc = reg->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read failed on MC_ADDR_TRANS2: i_chip=0x%08x",
+ i_chip->getHuid() );
+ return o_rc;
+ }
+
+ // Column 8 bitmap: MC_ADDR_TRANS2[3:7]
+ bitPos = reg->GetBitFieldJustified( 3, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (c8 << bitPos);
+
+ // Column 9 bitmap: MC_ADDR_TRANS2[11:15]
+ bitPos = reg->GetBitFieldJustified( 11, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (c9 << bitPos);
+
+ // Bank 0 bitmap: MC_ADDR_TRANS2[19:23]
+ bitPos = reg->GetBitFieldJustified( 19, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (b0 << bitPos );
+
+ // Bank 1 bitmap: MC_ADDR_TRANS2[27:31]
+ bitPos = reg->GetBitFieldJustified( 27, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (b1 << bitPos);
+
+ // Bank 2 bitmap: MC_ADDR_TRANS2[35:39]
+ // Note: Bank2 not used for OCMB
+
+ // Bank group 0 bitmap: MC_ADDR_TRANS2[43:47]
+ bitPos = reg->GetBitFieldJustified( 43, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (bg0 << bitPos);
+
+ // Bank group 1 bitmap: MC_ADDR_TRANS2[51:55]
+ bitPos = reg->GetBitFieldJustified( 51, 5 );
+ __adjustCapiAddrBitPos( bitPos );
+ o_addr |= (bg1 << bitPos);
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
template <>
int32_t __getPortAddr<TYPE_MBA>( ExtensibleChip * i_chip, MemAddr i_addr,
uint64_t & o_addr )
@@ -566,12 +826,12 @@ int32_t __getPortAddr<TYPE_MBA>( ExtensibleChip * i_chip, MemAddr i_addr,
//------------------------------------------------------------------------------
template<TYPE T>
-void __getGrpPrms( ExtensibleChip * i_chip, uint8_t o_portPos,
+void __getGrpPrms( ExtensibleChip * i_chip, uint8_t & o_portPos,
SCAN_COMM_REGISTER_CLASS * &o_mcfgp,
SCAN_COMM_REGISTER_CLASS * &o_mcfgpm );
template<>
-void __getGrpPrms<TYPE_MCA>( ExtensibleChip * i_chip, uint8_t o_portPos,
+void __getGrpPrms<TYPE_MCA>( ExtensibleChip * i_chip, uint8_t & o_portPos,
SCAN_COMM_REGISTER_CLASS * &o_mcfgp,
SCAN_COMM_REGISTER_CLASS * &o_mcfgpm )
{
@@ -585,7 +845,33 @@ void __getGrpPrms<TYPE_MCA>( ExtensibleChip * i_chip, uint8_t o_portPos,
}
template<>
-void __getGrpPrms<TYPE_MBA>( ExtensibleChip * i_chip, uint8_t o_portPos,
+void __getGrpPrms<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip, uint8_t & o_portPos,
+ SCAN_COMM_REGISTER_CLASS * &o_mcfgp,
+ SCAN_COMM_REGISTER_CLASS * &o_mcfgpm )
+{
+ // Get the connected parent MI;
+ ExtensibleChip * mcc = getConnectedParent( i_chip, TYPE_MCC );
+ ExtensibleChip * mi = getConnectedParent( mcc, TYPE_MI );
+
+ // TODO RTC 210072 - support for multiple ports
+ o_portPos = 0;
+
+ // Get the position of the MCC relative to the MI (0:1)
+ uint8_t chnlPos = mcc->getPos() % MAX_MCC_PER_MI;
+
+ char mcfgpName[64];
+ sprintf( mcfgpName, "MCFGP%d", chnlPos );
+
+ char mcfgpmName[64];
+ sprintf( mcfgpmName, "MCFGPM%d", chnlPos );
+
+ o_mcfgp = mi->getRegister( mcfgpName );
+ o_mcfgpm = mi->getRegister( mcfgpmName );
+
+}
+
+template<>
+void __getGrpPrms<TYPE_MBA>( ExtensibleChip * i_chip, uint8_t & o_portPos,
SCAN_COMM_REGISTER_CLASS * &o_mcfgp,
SCAN_COMM_REGISTER_CLASS * &o_mcfgpm )
{
@@ -686,12 +972,67 @@ uint32_t __getGrpInfo( ExtensibleChip * i_chip, uint64_t & o_grpChnls,
#undef PRDF_FUNC
}
+template<>
+uint32_t __getGrpInfo<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ uint64_t & o_grpChnls,
+ uint64_t & o_grpId, uint64_t & o_grpSize,
+ uint64_t & o_grpBar )
+{
+ #define PRDF_FUNC "[MemDealloc::__getGrpInfo] "
+
+ uint32_t o_rc = SUCCESS;
+
+ do
+ {
+ // Get portPos and MCFGP/M registers
+ uint8_t portPos = 0xFF;
+ SCAN_COMM_REGISTER_CLASS * mcfgp = nullptr;
+ SCAN_COMM_REGISTER_CLASS * mcfgpm = nullptr;
+ __getGrpPrms<TYPE_OCMB_CHIP>( i_chip, portPos, mcfgp, mcfgpm );
+
+ o_rc = mcfgp->Read(); if ( SUCCESS != o_rc ) break;
+
+ // Get the number of channels in this group: MCFGP[40:42]
+ uint8_t mcGrpCnfg = mcfgp->GetBitFieldJustified( 40, 3 );
+ switch ( mcGrpCnfg )
+ {
+ case 0: o_grpChnls = 8; break; // 8MCS
+ case 1: o_grpChnls = 1; break; // 1MCS
+ case 2: o_grpChnls = 2; break; // 2MCS
+ case 3: o_grpChnls = 3; break; // 3MCS
+ case 4: o_grpChnls = 4; break; // 4MCS
+ case 5: o_grpChnls = 6; break; // 6MCS
+ default:
+ PRDF_ERR( PRDF_FUNC "Invalid MC channels per group value: 0x%x "
+ "on 0x%08x", mcGrpCnfg, i_chip->getHuid() );
+ o_rc = FAIL;
+ }
+ if ( SUCCESS != o_rc ) break;
+
+ // Get the group ID and group size.
+ o_grpId = mcfgp->GetBitFieldJustified( 43, 3 ); // MCFGP[43:45]
+ o_grpSize = mcfgp->GetBitFieldJustified( 25, 15 ); // MCFGP[25:39]
+
+ // TODO RTC 210072 - support for multiple ports, see generic handling
+
+ // Get the base address (BAR).
+ // Channel 0 is always from the MCFGP.
+ o_grpBar = mcfgp->GetBitFieldJustified(1, 24); // MCFGP[1:24]
+
+ } while (0);
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//------------------------------------------------------------------------------
-uint32_t __insertGrpId( uint64_t & io_addr, uint64_t i_grpChnls,
- uint64_t i_grpId )
+template <TYPE T>
+uint32_t __insertGrpId( ExtensibleChip * i_chip, uint64_t & io_addr,
+ uint64_t i_grpChnls, uint64_t i_grpId )
{
- #define PRDF_FUNC "[MemDealloc::__insertGrpId] "
+ #define PRDF_FUNC "[MemDealloc::__insertGrpId<T>] "
uint32_t o_rc = SUCCESS;
@@ -742,6 +1083,108 @@ uint32_t __insertGrpId( uint64_t & io_addr, uint64_t i_grpChnls,
#undef PRDF_FUNC
}
+template<>
+uint32_t __insertGrpId<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ uint64_t & io_addr, uint64_t i_grpChnls,
+ uint64_t i_grpId )
+{
+ #define PRDF_FUNC "[MemDealloc::__insertGrpId<TYPE_OCMB_CHIP>] "
+
+ uint32_t o_rc = SUCCESS;
+
+ uint64_t upper33 = io_addr & 0xFFFFFFFF80ull;
+ uint64_t lower7 = io_addr & 0x000000007full;
+
+ bool subChanAEnable = false;
+ bool subChanBEnable = false;
+ bool bothSubChansEnabled = false;
+
+ ExtensibleChip * mcc = getConnectedParent( i_chip, TYPE_MCC );
+
+ // Check both subchannels whether we can get the connected OCMB to
+ // determine whether they are enabled.
+ // Check for subchannel A
+ ExtensibleChip * subchanA = getConnectedChild( mcc, TYPE_OCMB_CHIP, 0 );
+ if ( nullptr != subchanA ) subChanAEnable = true;
+
+ // Check for subchannel B
+ ExtensibleChip * subchanB = getConnectedChild( mcc, TYPE_OCMB_CHIP, 1 );
+ if ( nullptr != subchanB ) subChanBEnable = true;
+
+ // Check if both subchannels were enabled
+ if ( subChanAEnable && subChanBEnable ) bothSubChansEnabled = true;
+
+ // If both subchannels are enabled, bit 56 of the address will contain the
+ // subchannel select bit.
+ if ( bothSubChansEnabled )
+ {
+ uint8_t ocmbChnl = i_chip->getPos() % MAX_OCMB_PER_MCC; // 0:1
+ uint8_t bitInsert = 0;
+
+ switch ( i_grpChnls )
+ {
+ case 1: // insert 1 bit for subchannel select
+ case 3:
+ case 6:
+ bitInsert = ( ocmbChnl & 0x1 );
+ io_addr = (upper33 << 1) | (bitInsert << 7) | lower7;
+ break;
+
+ case 2: // insert 1 bit for subchannel select and 1 bit for grpId
+ bitInsert = ( ((i_grpId & 0x1) << 1) | (ocmbChnl & 0x1) );
+ io_addr = (upper33 << 2) | (bitInsert << 7) | lower7;
+ break;
+
+ case 4: // insert 1 bit for subchannel select and 2 bits for grpId
+ bitInsert = ( ((i_grpId & 0x3) << 1) | (ocmbChnl & 0x1) );
+ io_addr = (upper33 << 3) | (bitInsert << 7) | lower7;
+ break;
+
+ case 8: // insert 1 bit for subchannel select and 3 bits for grpId
+ bitInsert = ( ((i_grpId & 0x7) << 1) | (ocmbChnl & 0x1) );
+ io_addr = (upper33 << 4) | (bitInsert << 7) | lower7;
+ break;
+
+ default:
+ PRDF_ERR( PRDF_FUNC "Invalid MC channels per group value %d",
+ i_grpChnls );
+ o_rc = FAIL;
+ }
+ }
+ else
+ {
+ switch ( i_grpChnls )
+ {
+ case 1: // no shifting
+ case 3:
+ case 6:
+ break;
+
+ case 2: // insert 1 bit
+ io_addr = (upper33 << 1) | ((i_grpId & 0x1) << 7) | lower7;
+ break;
+
+ case 4: // insert 2 bits
+ io_addr = (upper33 << 2) | ((i_grpId & 0x3) << 7) | lower7;
+ break;
+
+ case 8: // insert 3 bits
+ io_addr = (upper33 << 3) | ((i_grpId & 0x7) << 7) | lower7;
+ break;
+
+ default:
+ PRDF_ERR( PRDF_FUNC "Invalid MC channels per group value %d",
+ i_grpChnls );
+ o_rc = FAIL;
+ }
+ }
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+
+}
+
//------------------------------------------------------------------------------
// The hardware uses a mod3 hashing algorithm to calculate which memory channel
@@ -849,7 +1292,7 @@ void __addBar( uint64_t & io_addr, uint64_t i_grpBar )
template<TYPE T>
uint32_t getSystemAddr( ExtensibleChip * i_chip, MemAddr i_addr,
- uint64_t & o_addr )
+ uint64_t & o_addr )
{
#define PRDF_FUNC "[MemDealloc::getSystemAddr] "
@@ -867,7 +1310,7 @@ uint32_t getSystemAddr( ExtensibleChip * i_chip, MemAddr i_addr,
if ( SUCCESS != o_rc ) break;
// Insert the group ID.
- o_rc = __insertGrpId( o_addr, grpChnls, grpId );
+ o_rc = __insertGrpId<T>( i_chip, o_addr, grpChnls, grpId );
if ( SUCCESS != o_rc ) break;
// Notes on 3 and 6 channel per group configs:
@@ -915,8 +1358,8 @@ uint32_t getSystemAddrRange( ExtensibleChip * i_chip,
if ( SUCCESS != o_rc ) break;
// Insert the group ID.
- o_rc = __insertGrpId( o_saddr, grpChnls, grpId );
- o_rc |= __insertGrpId( o_eaddr, grpChnls, grpId );
+ o_rc = __insertGrpId<T>( i_chip, o_saddr, grpChnls, grpId );
+ o_rc |= __insertGrpId<T>( i_chip, o_eaddr, grpChnls, grpId );
if ( SUCCESS != o_rc ) break;
// Notes on 3 and 6 channel per group configs:
@@ -975,6 +1418,7 @@ int32_t page( ExtensibleChip * i_chip, MemAddr i_addr )
}
template int32_t page<TYPE_MCA>( ExtensibleChip * i_chip, MemAddr i_addr );
template int32_t page<TYPE_MBA>( ExtensibleChip * i_chip, MemAddr i_addr );
+template int32_t page<TYPE_OCMB_CHIP>(ExtensibleChip * i_chip, MemAddr i_addr);
//------------------------------------------------------------------------------
@@ -1025,6 +1469,7 @@ int32_t rank( ExtensibleChip * i_chip, MemRank i_rank )
}
template int32_t rank<TYPE_MCA>( ExtensibleChip * i_chip, MemRank i_rank );
template int32_t rank<TYPE_MBA>( ExtensibleChip * i_chip, MemRank i_rank );
+template int32_t rank<TYPE_OCMB_CHIP>(ExtensibleChip * i_chip, MemRank i_rank);
//------------------------------------------------------------------------------
@@ -1074,6 +1519,7 @@ int32_t port( ExtensibleChip * i_chip )
}
template int32_t port<TYPE_MCA>( ExtensibleChip * i_chip );
template int32_t port<TYPE_MBA>( ExtensibleChip * i_chip );
+template int32_t port<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip );
//------------------------------------------------------------------------------
@@ -1236,6 +1682,22 @@ int32_t dimmList( TargetHandleList & i_dimmList )
sendPredDeallocRequest( ssAddr, seAddr );
PRDF_TRAC( PRDF_FUNC "Predictive dealloc for start addr: 0x%016llx "
"end addr: 0x%016llx", ssAddr, seAddr );
+
+ #ifdef CONFIG_NVDIMM
+ // If the DIMM is an NVDIMM, send a message to PHYP that a save/restore
+ // may work.
+ if ( isNVDIMM(*it) )
+ {
+ uint32_t l_rc = PlatServices::nvdimmNotifyProtChange( *it,
+ NVDIMM::NVDIMM_RISKY_HW_ERROR );
+ if ( SUCCESS != l_rc )
+ {
+ PRDF_TRAC( PRDF_FUNC "nvdimmNotifyProtChange(0x%08x) "
+ "failed.", getHuid(*it) );
+ continue;
+ }
+ }
+ #endif
}
return o_rc;
@@ -1278,6 +1740,14 @@ int32_t dimmList( TargetHandleList & i_dimmList )
break;
}
+ // Third, check for OCMBs.
+ list = getConnected( dimmTrgt, TYPE_OCMB_CHIP );
+ if ( !list.empty() )
+ {
+ o_rc = dimmList<TYPE_OCMB_CHIP>( i_dimmList );
+ break;
+ }
+
// If we get here we did not find a supported target.
PRDF_ERR( PRDF_FUNC "Unsupported connected parent to dimm 0x%08x",
getHuid(dimmTrgt) );
OpenPOWER on IntegriCloud