blob: 88ea59c7e8cece019d8b4d6a67c0ebf1d801aeb8 [file] [log] [blame]
Siyuan Wangaffe85f2013-07-25 15:14:15 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * Configure Max Payload
6 *
7 *
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: GNB
12 * @e \$Revision:
13 *
14 */
15/*
16*****************************************************************************
17*
18 * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
19 * All rights reserved.
20 *
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.
31 *
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.
42* ***************************************************************************
43*
44*/
45
46/*----------------------------------------------------------------------------------------
47 * M O D U L E S U S E D
48 *----------------------------------------------------------------------------------------
49 */
50#include "AGESA.h"
51#include "Ids.h"
52#include "amdlib.h"
53#include "Gnb.h"
54#include "GnbPcie.h"
55#include "GnbCommonLib.h"
56#include "GnbPcieConfig.h"
57#include "PcieMaxPayload.h"
58#include "OptionGnb.h"
59#include "GnbFamServices.h"
60#include "Filecode.h"
61#define FILECODE PROC_GNB_MODULES_GNBPCIEMAXPAYLOAD_PCIEMAXPAYLOAD_FILECODE
62
63/*----------------------------------------------------------------------------------------
64 * D E F I N I T I O N S A N D M A C R O S
65 *----------------------------------------------------------------------------------------
66 */
67extern GNB_BUILD_OPTIONS GnbBuildOptions;
68
69
70/*----------------------------------------------------------------------------------------
71 * T Y P E D E F S A N D S T R U C T U R E S
72 *----------------------------------------------------------------------------------------
73 */
74typedef struct {
75 GNB_PCI_SCAN_DATA ScanData;
76 UINT8 MaxPayload;
77} PCIE_MAX_PAYLOAD_DATA;
78
79
80/*----------------------------------------------------------------------------------------
81 * P R O T O T Y P E S O F L O C A L F U N C T I O N S
82 *----------------------------------------------------------------------------------------
83 */
84
85
86SCAN_STATUS
87PcieGetMaxPayloadCallback (
88 IN PCI_ADDR Device,
89 IN OUT GNB_PCI_SCAN_DATA *ScanData
90 );
91
92SCAN_STATUS
93PcieSetMaxPayloadCallback (
94 IN PCI_ADDR Device,
95 IN OUT GNB_PCI_SCAN_DATA *ScanData
96 );
97
98AGESA_STATUS
99PciePayloadBlackListFeature (
100 IN PCI_ADDR Device,
101 IN UINT8 *MaxPayload,
102 IN AMD_CONFIG_PARAMS *StdHeader
103 );
104
105AGESA_STATUS
106PcieMaxPayloadInterface (
107 IN AMD_CONFIG_PARAMS *StdHeader
108 );
109
110/*----------------------------------------------------------------------------------------*/
111/**
112 * Determine maximum payload size for PCIe segment
113 *
114 * Scan through all link in segment to determine maximum payload by EPs.
115 *
116 * @param[in] DownstreamPort PCI address of PCIe port
117 * @param[in] EngineMaxPayload MaxPayload supported by the engine
118 * @param[in] StdHeader Standard configuration header
119 *
120 */
121
122VOID
123PcieSetMaxPayload (
124 IN PCI_ADDR DownstreamPort,
125 IN UINT8 EngineMaxPayload,
126 IN AMD_CONFIG_PARAMS *StdHeader
127 )
128{
129 PCIE_MAX_PAYLOAD_DATA PcieMaxPayloadData;
130
131 IDS_HDT_CONSOLE (GNB_TRACE, " PcieSetMaxPayload for Device = %d:%d:%d\n",
132 DownstreamPort.Address.Bus,
133 DownstreamPort.Address.Device,
134 DownstreamPort.Address.Function
135 );
136 PcieMaxPayloadData.MaxPayload = EngineMaxPayload;
137 PcieMaxPayloadData.ScanData.StdHeader = StdHeader;
138 PcieMaxPayloadData.ScanData.GnbScanCallback = PcieGetMaxPayloadCallback;
139 GnbLibPciScan (DownstreamPort, DownstreamPort, &PcieMaxPayloadData.ScanData);
140 PcieMaxPayloadData.ScanData.GnbScanCallback = PcieSetMaxPayloadCallback;
141 GnbLibPciScan (DownstreamPort, DownstreamPort, &PcieMaxPayloadData.ScanData);
142 IDS_HDT_CONSOLE (GNB_TRACE, " PcieSetMaxPayloadExit\n");
143}
144
145/*----------------------------------------------------------------------------------------*/
146/**
147 * Evaluate device Max Payload - save SMALLEST Max Payload for PCIe Segment
148 *
149 *
150 *
151 * @param[in] Device PCI Address
152 * @param[in,out] ScanData Scan configuration data
153 * @retval Scan Status of 0
154 */
155
156SCAN_STATUS
157PcieGetMaxPayloadCallback (
158 IN PCI_ADDR Device,
159 IN OUT GNB_PCI_SCAN_DATA *ScanData
160 )
161{
162 SCAN_STATUS ScanStatus;
163 PCIE_MAX_PAYLOAD_DATA *PcieMaxPayloadData;
164 PCIE_DEVICE_TYPE DeviceType;
165 UINT32 Value;
166 UINT8 PcieCapPtr;
167 UINT8 DeviceMaxPayload;
168
169 PcieMaxPayloadData = (PCIE_MAX_PAYLOAD_DATA*) ScanData;
170 ScanStatus = SCAN_SUCCESS;
171 IDS_HDT_CONSOLE (GNB_TRACE, " PcieGetMaxPayloadCallback for Device = %d:%d:%d\n",
172 Device.Address.Bus,
173 Device.Address.Device,
174 Device.Address.Function
175 );
176 PcieCapPtr = GnbLibFindPciCapability (Device.AddressValue, PCIE_CAP_ID, ScanData->StdHeader);
177 if (PcieCapPtr != 0) {
178 GnbLibPciRead (
179 Device.AddressValue | (PcieCapPtr + PCIE_DEVICE_CAP_REGISTER),
180 AccessWidth32,
181 &Value,
182 ScanData->StdHeader
183 );
184 DeviceMaxPayload = (UINT8) (Value & 0x7);
185 PciePayloadBlackListFeature (Device, &DeviceMaxPayload, ScanData->StdHeader);
186 IDS_HDT_CONSOLE (GNB_TRACE, " Found DeviceMaxPayload as %d (Value = %x\n", DeviceMaxPayload, Value);
187 if (DeviceMaxPayload < PcieMaxPayloadData->MaxPayload) {
188 PcieMaxPayloadData->MaxPayload = DeviceMaxPayload;
189 }
190 }
191 DeviceType = GnbLibGetPcieDeviceType (Device, ScanData->StdHeader);
192 switch (DeviceType) {
193 case PcieDeviceRootComplex:
194 case PcieDeviceDownstreamPort:
195 case PcieDeviceUpstreamPort:
196 GnbLibPciScanSecondaryBus (Device, &PcieMaxPayloadData->ScanData);
197 break;
198 case PcieDeviceEndPoint:
199 case PcieDeviceLegacyEndPoint:
200 break;
201 default:
202 break;
203 }
204 return SCAN_SUCCESS;
205}
206
207/*----------------------------------------------------------------------------------------*/
208/**
209 * Configure the Max Payload setting to all devices in the PCIe Segment
210 *
211 *
212 *
213 * @param[in] Device PCI Address
214 * @param[in,out] ScanData Scan configuration data
215 * @retval Scan Status of 0
216 */
217
218SCAN_STATUS
219PcieSetMaxPayloadCallback (
220 IN PCI_ADDR Device,
221 IN OUT GNB_PCI_SCAN_DATA *ScanData
222 )
223{
224 SCAN_STATUS ScanStatus;
225 PCIE_MAX_PAYLOAD_DATA *PcieMaxPayloadData;
226 PCIE_DEVICE_TYPE DeviceType;
227 UINT8 PcieCapPtr;
228
229 PcieMaxPayloadData = (PCIE_MAX_PAYLOAD_DATA*) ScanData;
230 ScanStatus = SCAN_SUCCESS;
231 IDS_HDT_CONSOLE (GNB_TRACE, " PcieSetMaxPayloadCallback for Device = %d:%d:%d to %d\n",
232 Device.Address.Bus,
233 Device.Address.Device,
234 Device.Address.Function,
235 PcieMaxPayloadData->MaxPayload
236 );
237 PcieCapPtr = GnbLibFindPciCapability (Device.AddressValue, PCIE_CAP_ID, ScanData->StdHeader);
238 if (PcieCapPtr != 0) {
239 GnbLibPciRMW (
240 Device.AddressValue | (PcieCapPtr + PCIE_DEVICE_CTRL_REGISTER),
241 AccessWidth32,
242 ~(UINT32) (0x7 << 5),
243 ((UINT32)PcieMaxPayloadData->MaxPayload << 5),
244 ScanData->StdHeader
245 );
246 }
247 DeviceType = GnbLibGetPcieDeviceType (Device, ScanData->StdHeader);
248 switch (DeviceType) {
249 case PcieDeviceRootComplex:
250 case PcieDeviceDownstreamPort:
251 case PcieDeviceUpstreamPort:
252 GnbLibPciScanSecondaryBus (Device, &PcieMaxPayloadData->ScanData);
253 break;
254 case PcieDeviceEndPoint:
255 case PcieDeviceLegacyEndPoint:
256 break;
257 default:
258 break;
259 }
260 return SCAN_SUCCESS;
261}
262
263UINT16 PayloadBlacklistDeviceTable[] = {
264 0x1969, 0x1083, (UINT16) MAX_PAYLOAD_128
265};
266
267/*----------------------------------------------------------------------------------------*/
268/**
269 * Pcie Max_Payload_Size Black List
270 *
271 *
272 *
273 * @param[in] Device PCI_ADDR of PCIe Device to evaluate
274 * @param[in] MaxPayload Pointer to Max_Payload_Size value
275 * @param[in] StdHeader Standard configuration header
276 * @retval AGESA_STATUS
277 */
278
279AGESA_STATUS
280PciePayloadBlackListFeature (
281 IN PCI_ADDR Device,
282 IN UINT8 *MaxPayload,
283 IN AMD_CONFIG_PARAMS *StdHeader
284 )
285{
286 UINT32 TargetDeviceId;
287 UINTN i;
288 UINT32 DeviceId;
289 UINT32 VendorId;
290
291 GnbLibPciRead (Device.AddressValue, AccessWidth32, &TargetDeviceId, StdHeader);
Patrick Georgi6b688f52021-02-12 13:49:11 +0100292 for (i = 0; i < ARRAY_SIZE(PayloadBlacklistDeviceTable); i = i + 3) {
Siyuan Wangaffe85f2013-07-25 15:14:15 +0800293 VendorId = PayloadBlacklistDeviceTable[i];
294 DeviceId = PayloadBlacklistDeviceTable[i + 1];
295 if (VendorId == (UINT16)TargetDeviceId) {
296 if (DeviceId == 0xFFFF || DeviceId == (TargetDeviceId >> 16)) {
297 *MaxPayload = (UINT8) PayloadBlacklistDeviceTable[i + 2];
298 }
299 }
300 }
301 return AGESA_SUCCESS;
302}
303
304/*----------------------------------------------------------------------------------------*/
305/**
306 * Callback to init various features on all active ports
307 *
308 *
309 *
310 *
311 * @param[in] Engine Pointer to engine config descriptor
312 * @param[in, out] Buffer Not used
313 * @param[in] Pcie Pointer to global PCIe configuration
314 *
315 */
316
317VOID
318STATIC
319PcieMaxPayloadInitCallback (
320 IN PCIe_ENGINE_CONFIG *Engine,
321 IN OUT VOID *Buffer,
322 IN PCIe_PLATFORM_CONFIG *Pcie
323 )
324{
325 PCIE_MAXPAYLOAD_SERVICE *PcieMaxPayloadProtocol;
326 UINT8 EngineMaxPayload;
327 AGESA_STATUS Status;
328 PCIe_COMPLEX_CONFIG *Complex;
329
330
331
332 if ((GnbBuildOptions.CfgMaxPayloadEnable != 0) &&
333 (!PcieConfigIsSbPcieEngine (Engine)) &&
334 (PcieConfigCheckPortStatus (Engine, INIT_STATUS_PCIE_TRAINING_SUCCESS))) {
335 EngineMaxPayload = MAX_PAYLOAD;
336 Complex = (PCIe_COMPLEX_CONFIG *) PcieConfigGetParent (DESCRIPTOR_COMPLEX, &Engine->Header);
Arthur Heymansb80de182022-05-16 15:29:53 +0200337 Status = GnbLibLocateService (GnbPcieMaxPayloadService, Complex->SocketId, (CONST VOID **)&PcieMaxPayloadProtocol, GnbLibGetHeader (Pcie));
Siyuan Wangaffe85f2013-07-25 15:14:15 +0800338 if (Status == AGESA_SUCCESS) {
339 EngineMaxPayload = PcieMaxPayloadProtocol->SetMaxPayload (Engine);
340 }
341 PcieSetMaxPayload (Engine->Type.Port.Address, EngineMaxPayload, GnbLibGetHeader (Pcie));
342 }
343}
344
345/**----------------------------------------------------------------------------------------*/
346/**
347 * Interface to configure MaxPayloadSize on PCIE interface
348 *
349 *
350 *
351 * @param[in] StdHeader Standard configuration header
352 *
353 * @retval AGESA_STATUS
354 */
355 /*----------------------------------------------------------------------------------------*/
356AGESA_STATUS
357PcieMaxPayloadInterface (
358 IN AMD_CONFIG_PARAMS *StdHeader
359 )
360{
361 AGESA_STATUS AgesaStatus;
362 PCIe_PLATFORM_CONFIG *Pcie;
363 IDS_HDT_CONSOLE (GNB_TRACE, "PcieMaxPayloadInterface Enter\n");
364 AgesaStatus = PcieLocateConfigurationData (StdHeader, &Pcie);
365 if (AgesaStatus == AGESA_SUCCESS) {
366 PcieConfigRunProcForAllEngines (
367 DESCRIPTOR_ALLOCATED | DESCRIPTOR_PCIE_ENGINE,
368 PcieMaxPayloadInitCallback,
369 NULL,
370 Pcie
371 );
372 }
373 IDS_HDT_CONSOLE (GNB_TRACE, "PcieMaxPayloadInterface Exit [0x%x]\n", AgesaStatus);
374 return AgesaStatus;
375}