5 * Traffic Distribution Routines.
7 * Contains routines for traffic distribution
9 * @xrefitem bom "File Content Label" "Release Content"
11 * @e sub-project: HyperTransport
12 * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
16 *****************************************************************************
18 * Copyright (C) 2012 Advanced Micro Devices, Inc.
19 * All rights reserved.
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 * ***************************************************************************
48 *----------------------------------------------------------------------------
51 *----------------------------------------------------------------------------
61 #include "htInterface.h"
64 #include "htFeatTrafficDistribution.h"
69 #define FILECODE PROC_HT_FEATURES_HTFEATTRAFFICDISTRIBUTION_FILECODE
70 /*----------------------------------------------------------------------------
71 * DEFINITIONS AND MACROS
73 *----------------------------------------------------------------------------
75 /// Enum for the possible link connection status
77 Unconnected = 0, ///< Nodes have not connected link.
78 UngangedLink, ///< Nodes are connected with one unganged link.
79 Redundant, ///< Nodes are connected with multi-unganged link.
80 GangedLink, ///< Nodes are connected with one or mutiple ganged link.
81 MaxLink ///< Max links status.
84 /// Local port connection state data structure
86 LINK_STATUS ConnectionState; /**< The link connection state. */
87 UINT8 BigLinkPort; /**< The Port number for ganged Link */
88 } PORT_CONNECTION_STATE;
90 /// Local ganged link for Victim Distribution data structure
92 UINT8 NodeA; ///< Source Node from Node A To Node B and DstNode from Node A To Node B.
93 UINT8 NodeB; ///< Source Node from Node B To Node A and DstNode from Node A To Node B.
94 UINT8 VictimedLinkFromNodeAToNodeB; ///< Victimed Link from Node A To Node B.
95 UINT8 VictimedLinkFromNodeBToNodeA; ///< Victimed Link from Node B To Node A.
98 /*----------------------------------------------------------------------------
99 * TYPEDEFS AND STRUCTURES
101 *----------------------------------------------------------------------------
104 /*----------------------------------------------------------------------------
105 * PROTOTYPES OF LOCAL FUNCTIONS
107 *----------------------------------------------------------------------------
110 /*----------------------------------------------------------------------------
113 *----------------------------------------------------------------------------
116 /*----------------------------------------------------------------------------
119 *----------------------------------------------------------------------------
122 /*----------------------------------------------------------------------------------------*/
124 * Identify Links which can have traffic distribution.
126 * @HtFeatMethod{::F_TRAFFIC_DISTRIBUTION}
128 * If there are redundant links between any nodes, traffic distribution allows the
129 * redundant links to be used to improve performance.
131 * There are three types of traffic distribution. Their use is mutually exclusive, all
132 * can not be used at once.
134 * Coherent Traffic Distribution is for systems of exactly two nodes only. All links must
135 * be symmetrical (the same width). As many links as are connected can be distributed over.
137 * Victim Distribution is a way to direct victim traffic on to ganged links and away from unganged links
138 * as a way to reduce unganged link congestion for a system only if 2 processor (4 node) G34 system.
139 * A node can enables victim distribution mode only if the node connects to another node directly with
140 * only 1 unganged link hop and indirectly through 2 ganged link hops.
142 * Link Pair Traffic Distribution works with redundant pairs of links between any two nodes,
143 * it does not matter how many nodes are in the system or how many have a redundant link pair.
144 * A node can have redundant link pairs with more than one other node.
145 * The link pair can be asymmetric, the largest link must be used as the master. However,
146 * between any pair of nodes there is only one pair of redundant links, and there is a limit
147 * to the total number of pairs each node can have. So not all links will necessarily be
150 * @param[in] State port list data
153 TrafficDistribution (
162 UINT8 UngandLinkCount;
163 UINT8 VictimedRouteCount;
166 BOOLEAN IsAsymmetric;
167 BOOLEAN IsVictimedRouteFound;
168 UINT8 RedundantLinkCount[MAX_NODES][MAX_NODES];
169 UINT8 MasterLinkPort[MAX_NODES][MAX_NODES];
170 UINT8 AlternateLinkPort[MAX_NODES][MAX_NODES];
174 VICTIM_ROUTED_LINK VictimRoutedLink[MAX_NODES];
175 PORT_CONNECTION_STATE GangedLinkPort[MAX_NODES][MAX_NODES];
178 IsAsymmetric = FALSE;
180 // Traffic Distribution is only used when there are exactly two Nodes in the system
181 // and when all the links are symmetric, same width.
182 if ((State->NodesDiscovered + 1) == 2) {
186 for (i = 0; i < (State->TotalLinks * 2); i += 2) {
187 if (((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) &&
188 ((*State->PortList)[i + 1].Type == PORTLIST_TYPE_CPU)) {
189 if ((LastLink != 0xFF) &&
190 ((*State->PortList)[i].SelWidthOut != (*State->PortList)[LastLink].SelWidthOut) &&
191 ((*State->PortList)[i + 1].SelWidthOut != (*State->PortList)[LastLink + 1].SelWidthOut)) {
195 Links01 |= (UINT32)1 << (*State->PortList)[i].Link;
196 Links10 |= (UINT32)1 << (*State->PortList)[i + 1].Link;
201 ASSERT (LinkCount != 0);
202 // Don't setup Traffic Distribution if only one Link is being used or there were asymmetric widths
203 if ((LinkCount != 1) && !IsAsymmetric) {
204 IDS_HDT_CONSOLE (HT_TRACE, "Applying coherent traffic distribution.\n");
205 State->Nb->WriteTrafficDistribution (Links01, Links10, State->Nb);
206 // If we did Traffic Distribution, we must not do Link Pair, so get out of here.
211 // Victim Distribution is only used when there are exactly two processor (4 node) system
212 // and the node connects to another node directly with only 1 unganged link hop and indirectly
213 // through 2 ganged link hops.
214 if ((State->NodesDiscovered + 1) == 4) {
217 // Initialize the ganged link state data structures
218 for (NodeA = 0; NodeA < MAX_NODES; NodeA++) {
219 for (NodeB = 0; NodeB < MAX_NODES; NodeB++) {
220 GangedLinkPort[NodeA][NodeB].ConnectionState = 0;
221 GangedLinkPort[NodeA][NodeB].BigLinkPort = 0;
225 for (i = 0; i < (State->TotalLinks * 2); i += 2) {
226 if (((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) &&
227 ((*State->PortList)[i + 1].Type == PORTLIST_TYPE_CPU)) {
228 NodeA = (*State->PortList)[i].NodeID;
229 NodeB = (*State->PortList)[i + 1].NodeID;
230 if ((((*State->PortList)[i].SelRegang == TRUE) &&
231 ((*State->PortList)[i].PrvWidthOutCap == HT_WIDTH_16_BITS)) ||
232 ((*State->PortList)[i].SelWidthOut == HT_WIDTH_16_BITS)) {
233 if (GangedLinkPort[NodeA][NodeB].ConnectionState <= Redundant) {
234 // Record it if it is the first ganged link connecting two nodes.
235 GangedLinkPort[NodeA][NodeB].BigLinkPort = (*State->PortList)[i].Link;
236 GangedLinkPort[NodeB][NodeA].BigLinkPort = (*State->PortList)[i + 1].Link;
237 GangedLinkPort[NodeA][NodeB].ConnectionState = GangedLink;
238 GangedLinkPort[NodeB][NodeA].ConnectionState = GangedLink;
241 if (GangedLinkPort[NodeA][NodeB].ConnectionState == Unconnected) {
242 // Save it if it is firstly unganged link and also does no exist ganged link between node A and node B.
243 GangedLinkPort[NodeA][NodeB].ConnectionState = UngangedLink;
244 GangedLinkPort[NodeB][NodeA].ConnectionState = UngangedLink;
247 } else if (GangedLinkPort[NodeA][NodeB].ConnectionState == UngangedLink) {
248 // Ignore it if there are multi-unganged links between node A and node B.
249 GangedLinkPort[NodeA][NodeB].ConnectionState = Redundant;
250 GangedLinkPort[NodeB][NodeA].ConnectionState = Redundant;
252 // Adjust the count because had it recorded once.
259 if (UngandLinkCount != 0) {
260 VictimedRouteCount = 0;
262 // Check Link by Link if one unganged link can direct victim traffic on to indirectly 2 ganged link hops
263 for (NodeA = 0; NodeA <= (State->NodesDiscovered); NodeA++) {
264 for (NodeB = NodeA +1; NodeB <= (State->NodesDiscovered); NodeB++) {
265 if (GangedLinkPort[NodeA][NodeB].ConnectionState == UngangedLink) {
266 // This is unganged link connecting two nodes
267 IsVictimedRouteFound = FALSE;
269 for (i = 0; i <= (State->NodesDiscovered); i++) {
270 if ((i != NodeA) && (i != NodeB) && (GangedLinkPort[NodeA][i].ConnectionState == GangedLink)) {
271 // This is the first ganged link hop to Destined Node
272 VictimRoutedLink[VictimedRouteCount].NodeA = NodeA;
273 VictimRoutedLink[VictimedRouteCount].VictimedLinkFromNodeAToNodeB = GangedLinkPort[NodeA][i].BigLinkPort;
274 if (GangedLinkPort[i][NodeB].ConnectionState == GangedLink) {
275 // This is the second ganged link hop to Destined Node
276 // Save the Destined Node and the Reversed Destination Link
277 VictimRoutedLink[VictimedRouteCount].NodeB = NodeB;
278 VictimRoutedLink[VictimedRouteCount].VictimedLinkFromNodeBToNodeA = GangedLinkPort[NodeB][i].BigLinkPort;
279 if (!IsVictimedRouteFound) {
280 VictimedRouteCount++;
282 // This is first victimed route where there are indirectly 2 ganged link hops to Destined Node
283 IsVictimedRouteFound = TRUE;
285 // This is second victimed route, so we need to replace to the new Reversed Destination Link
286 VictimRoutedLink[VictimedRouteCount - 1].VictimedLinkFromNodeBToNodeA = GangedLinkPort[NodeB][i].BigLinkPort;
295 // Setup Victim Distribution Mode
296 if (VictimedRouteCount != 0) {
297 IDS_HDT_CONSOLE (HT_TRACE, "Applying coherent Victim distribution.\n");
300 for (i = 0; i < VictimedRouteCount; i++) {
301 LinksAB = (UINT32)1 << VictimRoutedLink[i].VictimedLinkFromNodeAToNodeB;
302 LinksBA = (UINT32)1 << VictimRoutedLink[i].VictimedLinkFromNodeBToNodeA;
303 State->Nb->WriteVictimDistribution (
304 VictimRoutedLink[i].NodeA,
305 VictimRoutedLink[i].NodeB,
311 // If we did Victim Distribution, we must not do Link Pair when there are more than two nodes, so exit here.
317 // Either there are more than two nodes, Asymmetric links, or no redundant links.
318 // See if we can use Link Pair Traffic Distribution
319 LibAmdMemFill (&RedundantLinkCount, 0, (MAX_NODES * MAX_NODES), State->ConfigHandle);
320 for (i = 0; i < (State->TotalLinks * 2); i += 2) {
321 if (((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) &&
322 ((*State->PortList)[i + 1].Type == PORTLIST_TYPE_CPU)) {
323 NodeA = (*State->PortList)[i].NodeID;
324 NodeB = (*State->PortList)[i + 1].NodeID;
325 if (RedundantLinkCount[NodeA][NodeB] == 0) {
326 // This is the first link connecting two nodes
327 ASSERT (RedundantLinkCount[NodeB][NodeA] == 0);
328 MasterLinkPort[NodeA][NodeB] = i;
329 MasterLinkPort[NodeB][NodeA] = i + 1;
331 // This is a redundant link. If it is larger than the current master link,
332 // make it the new master link.
334 if (((*State->PortList)[MasterLinkPort[NodeA][NodeB]].SelWidthOut < (*State->PortList)[i].SelWidthOut) &&
335 ((*State->PortList)[MasterLinkPort[NodeB][NodeA]].SelWidthOut < (*State->PortList)[i + 1].SelWidthOut)) {
336 // Make the old master link the alternate, we don't need to check, it is bigger.
337 AlternateLinkPort[NodeA][NodeB] = MasterLinkPort[NodeA][NodeB];
338 AlternateLinkPort[NodeB][NodeA] = MasterLinkPort[NodeB][NodeA];
339 MasterLinkPort[NodeA][NodeB] = i;
340 MasterLinkPort[NodeB][NodeA] = i + 1;
342 // Since the new link isn't bigger than the Master, check if it is bigger than the alternate,
343 // if we have an alternate. If we don't have an alternate yet, make this link the alternate.
344 if (RedundantLinkCount[NodeA][NodeB] == 1) {
345 AlternateLinkPort[NodeA][NodeB] = i;
346 AlternateLinkPort[NodeB][NodeA] = i + 1;
348 if (((*State->PortList)[AlternateLinkPort[NodeA][NodeB]].SelWidthOut < (*State->PortList)[i].SelWidthOut) &&
349 ((*State->PortList)[AlternateLinkPort[NodeB][NodeA]].SelWidthOut < (*State->PortList)[i + 1].SelWidthOut)) {
350 // Warning: the alternate link is an unusable redundant link
351 // Then make the new link the alternate link.
352 NotifyWarningOptUnusedLinks (
354 (*State->PortList)[AlternateLinkPort[NodeA][NodeB]].Link,
356 (*State->PortList)[AlternateLinkPort[NodeB][NodeA]].Link,
359 ASSERT (RedundantLinkCount[NodeB][NodeA] > 1);
360 AlternateLinkPort[NodeA][NodeB] = i;
361 AlternateLinkPort[NodeB][NodeA] = i + 1;
363 // Warning the current link is an unusable redundant link
364 NotifyWarningOptUnusedLinks (NodeA, (*State->PortList)[i].Link, NodeB, (*State->PortList)[i].Link, State);
369 RedundantLinkCount[NodeA][NodeB]++;
370 RedundantLinkCount[NodeB][NodeA]++;
373 // If we found any, now apply up to 4 per node
374 for (NodeA = 0; NodeA < MAX_NODES; NodeA++) {
376 for (NodeB = 0; NodeB < MAX_NODES; NodeB++) {
377 if (RedundantLinkCount[NodeA][NodeB] > 1) {
378 // Then there is a pair of links (at least, but we only care about the pair not the extras)
379 if (PairCount < MAX_LINK_PAIRS) {
381 if ((*State->PortList)[MasterLinkPort[NodeA][NodeB]].SelWidthOut
382 != (*State->PortList)[AlternateLinkPort[NodeA][NodeB]].SelWidthOut) {
385 IsAsymmetric = FALSE;
387 State->Nb->WriteLinkPairDistribution (
392 (*State->PortList)[MasterLinkPort[NodeA][NodeB]].Link,
393 (*State->PortList)[AlternateLinkPort[NodeA][NodeB]].Link,
398 // Warning: More link pairs than can be distributed
399 NotifyWarningOptLinkPairExceed (
401 (*State->PortList)[MasterLinkPort[NodeA][NodeB]].Link,
402 (*State->PortList)[AlternateLinkPort[NodeA][NodeB]].Link,
404 // Disable the link pair from the other node, the analysis loop made sure there
405 // can only be a single link pair between a pair of nodes.
406 RedundantLinkCount[NodeB][NodeA] = 1;
413 "Node %d applying %d link pair distributions.\n" :