blob: 533d3768713fe266b10a50ac4398af60d0ef42c9 [file] [log] [blame]
/* $NoKeywords:$ */
/**
* @file
*
* Routines for re-ganging Links.
*
* Implement the reganging feature.
*
* @xrefitem bom "File Content Label" "Release Content"
* @e project: AGESA
* @e sub-project: HyperTransport
* @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
*
*/
/*
*****************************************************************************
*
* Copyright (C) 2012 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Advanced Micro Devices, Inc. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***************************************************************************
*
*/
/*
*----------------------------------------------------------------------------
* MODULES USED
*
*----------------------------------------------------------------------------
*/
#include "AGESA.h"
#include "amdlib.h"
#include "Ids.h"
#include "Topology.h"
#include "htFeat.h"
#include "htInterface.h"
#include "htNb.h"
#include "htFeatGanging.h"
#include "Filecode.h"
CODE_GROUP (G1_PEICC)
RDATA_GROUP (G2_PEI)
#define FILECODE PROC_HT_FEATURES_HTFEATGANGING_FILECODE
/*----------------------------------------------------------------------------
* DEFINITIONS AND MACROS
*
*----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* TYPEDEFS AND STRUCTURES
*
*----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* PROTOTYPES OF LOCAL FUNCTIONS
*
*----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* EXPORTED FUNCTIONS
*
*----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* LOCAL FUNCTIONS
*
*----------------------------------------------------------------------------
*/
/***************************************************************************
*** Link Optimization ***
***************************************************************************/
/*----------------------------------------------------------------------------------------*/
/**
* Test the subLinks of a Link to see if they qualify to be reganged.
*
* @HtFeatMethod{::F_REGANG_LINKS}
*
* If they do, update the port list data to indicate that this should be done.
* @note no actual hardware state is changed in this routine.
*
* @param[in,out] State Our global state
*/
VOID
RegangLinks (
IN OUT STATE_DATA *State
)
{
FINAL_LINK_STATE FinalLinkState;
UINT8 i;
UINT8 j;
for (i = 0; i < (State->TotalLinks * 2); i += 2) {
// Data validation
ASSERT ((*State->PortList)[i].Type < 2 && (*State->PortList)[i].Link < State->Nb->MaxLinks);
ASSERT ((*State->PortList)[i + 1].Type < 2 && (*State->PortList)[i + 1].Link < State->Nb->MaxLinks);
// Regang is false unless we pass all conditions below
(*State->PortList)[i].SelRegang = FALSE;
(*State->PortList)[i + 1].SelRegang = FALSE;
// Only process cpu to cpu Links
if ( ((*State->PortList)[i].Type != PORTLIST_TYPE_CPU) ||
((*State->PortList)[i + 1].Type != PORTLIST_TYPE_CPU)) {
continue;
}
for (j = i + 2; j < State->TotalLinks*2; j += 2) {
// Only process cpu to cpu Links
if ( ((*State->PortList)[j].Type != PORTLIST_TYPE_CPU) ||
((*State->PortList)[j + 1].Type != PORTLIST_TYPE_CPU) ) {
continue;
}
// Links must be from the same source
if ((*State->PortList)[i].NodeID != (*State->PortList)[j].NodeID) {
continue;
}
// Link must be to the same target
if ((*State->PortList)[i + 1].NodeID != (*State->PortList)[j + 1].NodeID) {
continue;
}
// Ensure same source base port
if (((*State->PortList)[i].Link & 3) != ((*State->PortList)[j].Link & 3)) {
continue;
}
// Ensure same destination base port
if (((*State->PortList)[i + 1].Link & 3) != ((*State->PortList)[j + 1].Link & 3)) {
continue;
}
// Ensure subLink0 routes to subLink0
if (((*State->PortList)[i].Link & 4) != ((*State->PortList)[i + 1].Link & 4)) {
continue;
}
// (therefore subLink1 routes to subLink1)
ASSERT (((*State->PortList)[j].Link & 4) == ((*State->PortList)[j + 1].Link & 4));
FinalLinkState = State->HtInterface->GetSkipRegang ((*State->PortList)[i].NodeID,
(*State->PortList)[i].Link & 0x03,
(*State->PortList)[i + 1].NodeID,
(*State->PortList)[i + 1].Link & 0x03,
State);
if (FinalLinkState == MATCHED) {
continue;
} else if (FinalLinkState == POWERED_OFF) {
// StopLink will be done on the sublink 1, thus OR in 4 to the link to ensure it.
State->Nb->StopLink ((*State->PortList)[i].NodeID, ((*State->PortList)[i].Link | 4), State, State->Nb);
State->Nb->StopLink ((*State->PortList)[i + 1].NodeID, ((*State->PortList)[i + 1].Link | 4), State, State->Nb);
}
//
// Create a ganged portlist entry for the two regang-able subLinks.
//
// All info will be that of subLink zero.
// (If Link discovery order was other than ascending, fix the .Pointer field too.)
//
//
if (((*State->PortList)[i].Link & 4) != 0) {
(*State->PortList)[i].Pointer = (*State->PortList)[j].Pointer;
(*State->PortList)[i + 1].Pointer = (*State->PortList)[j + 1].Pointer;
}
(*State->PortList)[i].Link &= 0x03; // Force to point to subLink0
(*State->PortList)[i + 1].Link &= 0x03;
// If powered off, sublink 1 is removed but the link is still 8 bits.
if (FinalLinkState != POWERED_OFF) {
(*State->PortList)[i].SelRegang = TRUE; // Enable Link reganging
(*State->PortList)[i + 1].SelRegang = TRUE;
(*State->PortList)[i].PrvWidthOutCap = HT_WIDTH_16_BITS;
(*State->PortList)[i + 1].PrvWidthOutCap = HT_WIDTH_16_BITS;
(*State->PortList)[i].PrvWidthInCap = HT_WIDTH_16_BITS;
(*State->PortList)[i + 1].PrvWidthInCap = HT_WIDTH_16_BITS;
}
// Delete PortList[j, j + 1], slow but easy to debug implementation
State->TotalLinks--;
LibAmdMemCopy (&((*State->PortList)[j]),
&((*State->PortList)[j + 2]),
sizeof (PORT_DESCRIPTOR)*(State->TotalLinks* 2 - j),
State->ConfigHandle);
LibAmdMemFill (&((*State->PortList)[State->TotalLinks * 2]), INVALID_LINK, (sizeof (PORT_DESCRIPTOR) * 2), State->ConfigHandle);
break; // Exit loop, advance to PortList[i + 2]
}
}
}