| /* $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: 44324 $ @e \$Date: 2010-12-22 17:16:51 +0800 (Wed, 22 Dec 2010) $ |
| * |
| */ |
| /* |
| ***************************************************************************** |
| * |
| * Copyright (c) 2011, 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 (G1_PEICC) |
| |
| #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] |
| } |
| } |
| } |