1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 1993-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 
25 /***************************** HW State Routines ***************************\
26 *         Core Logic Object Function Definitions.                           *
27 \***************************************************************************/
28 
29 #include "core/system.h"
30 #include "platform/chipset/chipset.h"
31 #include "platform/platform.h"
32 #include "platform/chipset/chipset_info.h"
33 #include "os/os.h"
34 #include "nvRmReg.h"
35 #include "nvpcie.h"
36 #include "nv_ref.h"
37 #include "kernel/gpu/bif/kernel_bif.h"
38 #include "gpu_mgr/gpu_mgr.h"
39 #include "gpu/gsp/gsp_static_config.h"
40 #include "ctrl/ctrl2080/ctrl2080bus.h"
41 
42 // local static funcs
43 static void clDestructHWBC(OBJHWBC *pHWBC);
44 
45 NV_STATUS
46 clConstruct_IMPL(OBJCL *pCl)
47 {
48     // Used to track when the link has gone into Recovery, which can cause CEs.
49     pCl->EnteredRecoverySinceErrorsLastChecked = NV_FALSE;
50 
51     pCl->pPcieConfigSpaceBase = NULL;
52 
53     //
54     // We set this property by default.
55     // Chipset setup function can override this.
56     // Right now only Tegra chipsets overide this setting.
57     //
58     pCl->setProperty(pCl, PDB_PROP_CL_IS_CHIPSET_IO_COHERENT, NV_TRUE);
59 
60     return NV_OK;
61 }
62 
63 
64 void
65 clInitPropertiesFromRegistry_IMPL(OBJGPU *pGpu, OBJCL *pCl)
66 {
67     NvU32  data32;
68     OBJSYS *pSys = SYS_GET_INSTANCE();
69     OBJOS *pOS = SYS_GET_OS(pSys);
70 
71     if (osReadRegistryDword(pGpu, NV_REG_STR_RM_DISABLE_BR03_FLOW_CONTROL, &data32) == NV_OK
72             && data32)
73     {
74         pCl->setProperty(pCl, PDB_PROP_CL_DISABLE_BR03_FLOW_CONTROL, NV_TRUE);
75     }
76 
77     if (osReadRegistryDword(pGpu, NV_REG_STR_RM_FORCE_ENABLE_GEN2, &data32) == NV_OK)
78     {
79         if (NV_REG_STR_RM_FORCE_ENABLE_GEN2_YES == data32)
80         {
81             pCl->setProperty(pCl, PDB_PROP_CL_PCIE_FORCE_GEN2_ENABLE, NV_TRUE);
82         }
83     }
84 
85     pOS->osQADbgRegistryInit(pOS);
86 }
87 
88 static void
89 clDestructHWBC(OBJHWBC *pHWBC)
90 {
91     if (pHWBC->pSibling)
92     {
93         clDestructHWBC(pHWBC->pSibling);
94         pHWBC->pSibling = NULL;
95     }
96     if (pHWBC->pFirstChild)
97     {
98         clDestructHWBC(pHWBC->pFirstChild);
99         pHWBC->pFirstChild = NULL;
100     }
101 
102     portMemFree(pHWBC);
103 }
104 
105 void
106 clDestruct_IMPL(OBJCL *pCl)
107 {
108     if (pCl->pHWBC)
109     {
110         clDestructHWBC(pCl->pHWBC);
111         pCl->pHWBC = NULL;
112     }
113 
114     clFreeBusTopologyCache(pCl);
115 
116     clFreePcieConfigSpaceBase(pCl);
117 }
118 
119 //
120 // Find our NV device on the PCI bus and save it's pci bus/device address.
121 //
122 NvU32
123 clInitMappingPciBusDevice_IMPL
124 (
125     OBJGPU       *pGpu,
126     OBJCL        *pCl
127 )
128 {
129     void *handle;
130     NvU32 domain;
131     NvU16 bus;
132     NvU8 device;
133     NvU16 vendorID, deviceID;
134     NvBool bFoundDevice = NV_FALSE;
135 
136     if (IsT194(pGpu) || IsT234(pGpu))
137         return NV0000_CTRL_GPU_INVALID_ID;
138 
139     // do we already know our domain/bus/device?
140     if (gpuGetDBDF(pGpu) == 0)
141     {
142         // we're checking all the device/funcs for the first 10 buses!
143         // Note that we give up the enumeration once we find our first
144         // or in the Multichip case our second device.
145         for (domain = 0; (domain < PCI_MAX_DOMAINS) && !bFoundDevice; domain++)
146         {
147             for (bus = 0; (bus < PCI_MAX_BUSES) && !bFoundDevice; bus++)
148             {
149                 for (device = 0; device < PCI_MAX_DEVICES; device++)
150                 {
151                     // read at domain, bus, device (we're always function 0)
152                     handle = osPciInitHandle(domain, (NvU8) bus, device, 0, &vendorID, &deviceID);
153                     if (!handle)
154                         continue;
155 
156                     if (vendorID != NV_CONFIG_PCI_NV_0_VENDOR_ID_NVIDIA)
157                         continue;
158 
159                     // make sure we're a VGA device class
160                     if ((osPciReadByte(handle, 0xB)) != PCI_CLASS_DISPLAY_DEV)
161                         continue;
162 
163                     // if the BAR0 matches our PhysAddr, it's the correct device
164                     if ((osPciReadDword(handle, PCI_BASE_ADDRESS_0)) !=
165                         pGpu->busInfo.gpuPhysAddr)
166                         continue;
167 
168                     // save our domain/bus/device/function
169                     pGpu->busInfo.nvDomainBusDeviceFunc = gpuEncodeDomainBusDevice(domain, (NvU8)bus, device);
170 
171                     bFoundDevice = NV_TRUE;
172 
173                     if (!(IS_SIMULATION(pGpu) || IS_SIM_MODS(GPU_GET_OS(pGpu))))
174                     {
175                         NV_ASSERT(gpuGetDBDF(pGpu) != 0);
176                     }
177                                                         // On the HP "Wilson's Peak"/McKinley system
178                                                         // the graphics is located at
179                                                         // domain==0, bus==0, device==0.
180                                                         // Why should this be invalid?
181                     // In simulation, the fmodel can put this at bus==0, device==0
182                     break;
183                 }
184             }
185         }
186     }
187 
188     domain = gpuGetDomain(pGpu);
189     bus = gpuGetBus(pGpu);
190     device = gpuGetDevice(pGpu);
191 
192     if (gpuGetDBDF(pGpu) == 0)
193     {
194         if (!(IS_SIMULATION(pGpu)|| IS_SIM_MODS(GPU_GET_OS(pGpu)))
195                || (bFoundDevice == NV_FALSE))
196         {
197             NV_PRINTF(LEVEL_ERROR,
198                     "NVRM initMappingPciBusDevice: can't find a device!\n");
199             return NV0000_CTRL_GPU_INVALID_ID;    // couldn't find it
200         }
201     }
202 
203     return gpuGenerate32BitId(domain, (NvU8)bus, device);
204 }
205 
206 //
207 // Walk the PCIE Capabilities and if the subsystem ID is found then return
208 // the subvendorID and subdeviceID
209 //
210 static void getSubsystemFromPCIECapabilities
211 (
212     NvU32 domain,
213     NvU8 bus,
214     NvU8 device,
215     NvU8 func,
216     NvU16 *subvendorID,
217     NvU16 *subdeviceID
218 )
219 {
220     void *handle;
221     NvU32 PCIECapPtr;
222     NvU32 PCIECap;
223     NvU32 PCIECapNext;
224 
225     handle = osPciInitHandle(domain, bus, device, func, NULL, NULL);
226 
227     // We start from Cap. List and search for Subsystem ID Capability
228     PCIECapNext = osPciReadByte(handle, PCI_CAPABILITY_LIST);
229     if (PCIECapNext)
230     {
231         do
232         {
233             PCIECapPtr = PCIECapNext;
234             PCIECap = osPciReadDword(handle, CL_PCIE_CAP - CL_PCIE_BEGIN + PCIECapPtr);
235             PCIECapNext = (NvU8)((PCIECap >> 8) & 0xFF);
236         } while ((PCIECapNext != 0) &&
237                  ((PCIECap & CAP_ID_MASK) != CAP_ID_SUBSYSTEM_ID));
238 
239         if ((PCIECap & CAP_ID_MASK) == CAP_ID_SUBSYSTEM_ID)
240         {
241             if (subvendorID)
242             {
243                 *subvendorID = osPciReadWord(handle, CL_PCIE_CAP - CL_PCIE_BEGIN + PCIECapPtr + 4);
244             }
245             if (subdeviceID)
246             {
247                 *subdeviceID = osPciReadWord(handle, CL_PCIE_CAP - CL_PCIE_BEGIN + PCIECapPtr + 6);
248             }
249         }
250     }
251 }
252 
253 //
254 // PCI Express Support
255 // Find first host bridge's domain, bus, device, function, if not already found
256 //
257 
258 NV_STATUS
259 clFindFHBAndGetChipsetInfoIndex_IMPL
260 (
261     OBJCL *pCl,
262     NvU16 *pChipsetInfoIndex
263 )
264 {
265     void     *handle;
266     NvU32     domain;
267     NvU8      revisionID = 0;
268     NvU32     i;
269     NvBool    matchFound = NV_FALSE;
270     NvU16     bus;
271     NvU8      device, func;
272     NvU16     vendorID, deviceID, subvendorID, subdeviceID;
273     PBUSTOPOLOGYINFO pBusTopologyInfo;
274     //
275     // PC motherboards have a host bridge to connect PCIE root complex to rest of the system.
276     // However, Tegra devices only have a PCI-to-PCI bridge.
277     // So allow Tegra chipset initialization, even if a host bridge is not found.
278     // See bug 1547160 comment#17 for more details.
279     //
280     NvU16    pciSubBaseClass[2] = {PCI_COMMON_CLASS_SUBBASECLASS_HOST, PCI_COMMON_CLASS_SUBBASECLASS_P2P};
281 
282     // return it, if we've got it already
283     if (pCl->chipsetIDBusAddr.valid)
284         return NV_OK;
285 
286     // Initialize to 0
287     pCl->chipsetIDBusAddr.domain = 0x0;
288     pCl->chipsetIDBusAddr.bus    = 0x0;
289     pCl->chipsetIDBusAddr.device = 0x0;
290     pCl->chipsetIDBusAddr.func   = 0x0;
291     pCl->chipsetIDBusAddr.valid  = 0x0;
292     pCl->chipsetIDBusAddr.handle = NULL;
293     pCl->chipsetIDInfo.deviceID    = PCI_INVALID_DEVICEID;
294     pCl->chipsetIDInfo.vendorID    = PCI_INVALID_VENDORID;
295     pCl->chipsetIDInfo.subdeviceID = PCI_INVALID_SUBDEVICEID;
296     pCl->chipsetIDInfo.subvendorID = PCI_INVALID_SUBVENDORID;
297 
298     for (i = 0; chipsetInfo[i].vendorID; i++)
299     {
300         pBusTopologyInfo = pCl->pBusTopologyInfo;
301         while (pBusTopologyInfo)
302         {
303             if ((pBusTopologyInfo->busInfo.vendorID == chipsetInfo[i].vendorID) &&
304                 (pBusTopologyInfo->busInfo.deviceID == chipsetInfo[i].deviceID))
305             {
306                 matchFound = NV_TRUE;
307                 break;
308             }
309             pBusTopologyInfo = pBusTopologyInfo->next;
310         }
311 
312         if (matchFound)
313         {
314             if  (pChipsetInfoIndex != NULL)
315             {
316                 *pChipsetInfoIndex = (NvU16) i;
317             }
318 
319             //
320             // IBM Wildhorse system has NV chipset attached to secondary K8 at bus 0x80
321             // (bug 227308).
322             // Do not change the algorithm for older chipsets where the devcie at bus%0x40 ==0, 0, 0 is
323             // considered as a host bridge.
324             //
325             if (((pBusTopologyInfo->pciSubBaseClass & 0xFF) == PCI_SUBCLASS_BR_HOST) ||
326                 (!(pBusTopologyInfo->bus % 0x40) && !pBusTopologyInfo->device && !pBusTopologyInfo->func))
327             {
328                 pCl->FHBAddr.domain = pBusTopologyInfo->domain;
329                 pCl->FHBAddr.bus    = pBusTopologyInfo->bus;
330                 pCl->FHBAddr.device = pBusTopologyInfo->device;
331                 pCl->FHBAddr.func   = pBusTopologyInfo->func;
332                 pCl->FHBAddr.valid  = 0x1;
333                 pCl->FHBAddr.handle = pBusTopologyInfo->handle;
334 
335                 // Store a copy of deviceID,  vendorID, subdeviceID and subvendorID;
336                 pCl->FHBBusInfo.deviceID    = pBusTopologyInfo->busInfo.deviceID;
337                 pCl->FHBBusInfo.vendorID    = pBusTopologyInfo->busInfo.vendorID;
338                 pCl->FHBBusInfo.subdeviceID = pBusTopologyInfo->busInfo.subdeviceID;
339                 pCl->FHBBusInfo.subvendorID = pBusTopologyInfo->busInfo.subvendorID;
340                 pCl->FHBBusInfo.revisionID  = pBusTopologyInfo->busInfo.revisionID;
341 
342                 pCl->chipsetIDBusAddr.domain = pBusTopologyInfo->domain;
343                 pCl->chipsetIDBusAddr.bus    = pBusTopologyInfo->bus;
344                 pCl->chipsetIDBusAddr.device = pBusTopologyInfo->device;
345                 pCl->chipsetIDBusAddr.func   = pBusTopologyInfo->func;
346                 pCl->chipsetIDBusAddr.valid  = 0x1;
347                 pCl->chipsetIDBusAddr.handle = pBusTopologyInfo->handle;
348 
349                 // Store a copy of deviceID,  vendorID, subdeviceID and subvendorID;
350                 pCl->chipsetIDInfo.deviceID    = pBusTopologyInfo->busInfo.deviceID;
351                 pCl->chipsetIDInfo.vendorID    = pBusTopologyInfo->busInfo.vendorID;
352                 pCl->chipsetIDInfo.subdeviceID = pBusTopologyInfo->busInfo.subdeviceID;
353                 pCl->chipsetIDInfo.subvendorID = pBusTopologyInfo->busInfo.subvendorID;
354                 return NV_OK;
355             }
356             else
357             {
358                 pCl->chipsetIDBusAddr.domain = pBusTopologyInfo->domain;
359                 pCl->chipsetIDBusAddr.bus    = pBusTopologyInfo->bus;
360                 pCl->chipsetIDBusAddr.device = pBusTopologyInfo->device;
361                 pCl->chipsetIDBusAddr.func   = pBusTopologyInfo->func;
362                 pCl->chipsetIDBusAddr.valid  = 0x1;
363                 pCl->chipsetIDBusAddr.handle = pBusTopologyInfo->handle;
364 
365                 // Store a copy of deviceID,  vendorID, subdeviceID and subvendorID;
366                 pCl->chipsetIDInfo.deviceID    = pBusTopologyInfo->busInfo.deviceID;
367                 pCl->chipsetIDInfo.vendorID    = pBusTopologyInfo->busInfo.vendorID;
368                 pCl->chipsetIDInfo.subdeviceID = pBusTopologyInfo->busInfo.subdeviceID;
369                 pCl->chipsetIDInfo.subvendorID = pBusTopologyInfo->busInfo.subvendorID;
370 
371                 if (pCl->chipsetIDInfo.subvendorID == 0)
372                 {
373                     getSubsystemFromPCIECapabilities(pCl->chipsetIDBusAddr.domain,
374                                                      pCl->chipsetIDBusAddr.bus,
375                                                      pCl->chipsetIDBusAddr.device,
376                                                      pCl->chipsetIDBusAddr.func,
377                                                      &pCl->chipsetIDInfo.subvendorID,
378                                                      &pCl->chipsetIDInfo.subdeviceID);
379                 }
380                 break;
381             }
382         }
383     }
384 
385     if ((!matchFound) && (pChipsetInfoIndex != NULL))
386     {
387         // This should be the entry with NULL information
388         NV_ASSERT(chipsetInfo[i].vendorID == 0);
389         *pChipsetInfoIndex = (NvU16) i;
390     }
391 
392     //
393     // We are here because VendorId and deviceId in chipsetInfo table does not
394     // match with Host Bridge ID. In that case we need to find FHB either in
395     // cached bus topology or need to loop through PCI bus to find the FHB.
396     //
397     for (i = 0; i < 2; i++)
398     {
399     pBusTopologyInfo = pCl->pBusTopologyInfo;
400     while (pBusTopologyInfo)
401     {
402         if (pBusTopologyInfo->pciSubBaseClass == pciSubBaseClass[i])
403         {
404             pCl->FHBAddr.domain = pBusTopologyInfo->domain;
405             pCl->FHBAddr.bus    = pBusTopologyInfo->bus;
406             pCl->FHBAddr.device = pBusTopologyInfo->device;
407             pCl->FHBAddr.func   = pBusTopologyInfo->func;
408             pCl->FHBAddr.valid  = 0x1;
409             pCl->FHBAddr.handle = pBusTopologyInfo->handle;
410 
411             // Store a copy of deviceID,  vendorID, subdeviceID and subvendorID;
412             pCl->FHBBusInfo.deviceID    = pBusTopologyInfo->busInfo.deviceID;
413             pCl->FHBBusInfo.vendorID    = pBusTopologyInfo->busInfo.vendorID;
414             pCl->FHBBusInfo.subdeviceID = pBusTopologyInfo->busInfo.subdeviceID;
415             pCl->FHBBusInfo.subvendorID = pBusTopologyInfo->busInfo.subvendorID;
416             pCl->FHBBusInfo.revisionID  = pBusTopologyInfo->busInfo.revisionID;
417 
418             if (!matchFound)
419             {
420                 pCl->chipsetIDBusAddr.domain = pBusTopologyInfo->domain;
421                 pCl->chipsetIDBusAddr.bus    = pBusTopologyInfo->bus;
422                 pCl->chipsetIDBusAddr.device = pBusTopologyInfo->device;
423                 pCl->chipsetIDBusAddr.func   = pBusTopologyInfo->func;
424                 pCl->chipsetIDBusAddr.valid  = 0x1;
425                 pCl->chipsetIDBusAddr.handle = pBusTopologyInfo->handle;
426 
427                 // Store a copy of deviceID,  vendorID, subdeviceID and subvendorID;
428                 pCl->chipsetIDInfo.deviceID    = pBusTopologyInfo->busInfo.deviceID;
429                 pCl->chipsetIDInfo.vendorID    = pBusTopologyInfo->busInfo.vendorID;
430                 pCl->chipsetIDInfo.subdeviceID = pBusTopologyInfo->busInfo.subdeviceID;
431                 pCl->chipsetIDInfo.subvendorID = pBusTopologyInfo->busInfo.subvendorID;
432 
433                 if (pCl->chipsetIDInfo.subvendorID == 0)
434                 {
435                     getSubsystemFromPCIECapabilities(pCl->chipsetIDBusAddr.domain,
436                                                      pCl->chipsetIDBusAddr.bus,
437                                                      pCl->chipsetIDBusAddr.device,
438                                                      pCl->chipsetIDBusAddr.func,
439                                                      &pCl->chipsetIDInfo.subvendorID,
440                                                      &pCl->chipsetIDInfo.subdeviceID);
441                 }
442             }
443             return NV_OK;
444         }
445         pBusTopologyInfo = pBusTopologyInfo->next;
446     }
447 
448         NV_PRINTF(LEVEL_INFO,
449                   "NVRM : Host bridge device not found. Looking for a PCI-to-PCI bridge device!!!\n");
450     }
451 
452     NV_PRINTF(LEVEL_ERROR,
453               "NVRM : This is Bad. FHB not found in cached bus topology!!!\n");
454 
455     // HB is not present in cached bus topology.
456     NV_ASSERT(0);
457 
458     //
459     // Don't bother scanning all domains, which takes approximately forever.
460     // If we can't find it in domain 0, we're probably not going to anyway
461     // (and something is already wrong).
462     //
463     domain = 0;
464 
465     for (bus = 0; bus < PCI_MAX_BUSES; bus++)
466     {
467         for (device = 0; device < PCI_MAX_DEVICES; device++)
468         {
469             for (func = 0; func < PCI_MAX_FUNCTION; func++)
470             {
471                 // read at domain, bus, device, func
472                 handle = osPciInitHandle(domain, (NvU8)bus, device, func, &vendorID, &deviceID);
473                 if (!handle)
474                 {
475                     if (func == 0)
476                     {
477                         // If a read to function zero of a specified bus/device master aborts,
478                         // then it is assumed that no such device exists on the bus since
479                         // devices are required to implement function number zero.
480                         // In this case reads to the remaining functions are not necessary.
481                         break;
482                     }
483                     else
484                     {
485                         continue;
486                     }
487                 }
488 
489                 if (!PCI_IS_VENDORID_VALID(vendorID))
490                     break;           // skip to the next device
491 
492                 if ((osPciReadByte(handle, PCI_HEADER_TYPE0_BASECLASS)) != PCI_CLASS_BRIDGE_DEV)
493                     break;           // not a bridge device
494 
495                 if ((osPciReadByte(handle, PCI_HEADER_TYPE0_SUBCLASS))  != PCI_SUBCLASS_BR_HOST)
496                     break;           // not a host bridge
497 
498                 subdeviceID = osPciReadWord(handle, PCI_HEADER_TYPE0_SUBSYS_ID);
499                 subvendorID = osPciReadWord(handle, PCI_HEADER_TYPE0_SUBSYS_VEN_ID);
500                 revisionID  = osPciReadByte(handle, PCI_HEADER_TYPE0_REVISION_ID);
501 
502                 // Found it
503                 pCl->FHBAddr.domain = domain;
504                 pCl->FHBAddr.bus    = (NvU8)bus;
505                 pCl->FHBAddr.device = device;
506                 pCl->FHBAddr.func   = func;
507                 pCl->FHBAddr.valid  = 0x1;
508                 pCl->FHBAddr.handle = handle;
509 
510                 // Store a copy of deviceID,  vendorID, subdeviceID and subvendorID;
511                 pCl->FHBBusInfo.deviceID    = deviceID;
512                 pCl->FHBBusInfo.vendorID    = vendorID;
513                 pCl->FHBBusInfo.subdeviceID = subdeviceID;
514                 pCl->FHBBusInfo.subvendorID = subvendorID;
515                 pCl->FHBBusInfo.revisionID  = revisionID;
516 
517                 if (!matchFound)
518                 {
519                     pCl->chipsetIDBusAddr.domain = domain;
520                     pCl->chipsetIDBusAddr.bus    = (NvU8)bus;
521                     pCl->chipsetIDBusAddr.device = device;
522                     pCl->chipsetIDBusAddr.func   = func;
523                     pCl->chipsetIDBusAddr.valid  = 0x1;
524                     pCl->chipsetIDBusAddr.handle = handle;
525 
526                     // Store a copy of deviceID,  vendorID, subdeviceID and subvendorID;
527                     pCl->chipsetIDInfo.deviceID    = deviceID;
528                     pCl->chipsetIDInfo.vendorID    = vendorID;
529                     pCl->chipsetIDInfo.subdeviceID = subdeviceID;
530                     pCl->chipsetIDInfo.subvendorID = subvendorID;
531                 }
532                 return NV_OK;
533             }
534         }
535     }
536 
537     // This is bad, we didn't find the First Host Bridge device (assume domain0/bus0/device0/func0)
538     pCl->FHBAddr.domain = 0x0;
539     pCl->FHBAddr.bus    = 0x0;
540     pCl->FHBAddr.device = 0x0;
541     pCl->FHBAddr.func   = 0x0;
542     pCl->FHBAddr.valid  = 0x1;
543     pCl->FHBAddr.handle = NULL;
544     pCl->FHBBusInfo.deviceID    = PCI_INVALID_DEVICEID;
545     pCl->FHBBusInfo.vendorID    = PCI_INVALID_VENDORID;
546     pCl->FHBBusInfo.subdeviceID = PCI_INVALID_SUBDEVICEID;
547     pCl->FHBBusInfo.subvendorID = PCI_INVALID_SUBVENDORID;
548 
549     DBG_BREAKPOINT();
550 
551     NV_ASSERT(0); //We can't find a host bridge, bad!
552 
553 
554     return NV_ERR_NOT_SUPPORTED;
555 }
556 
557 NvBool
558 clIsL1MaskEnabledForUpstreamPort_IMPL
559 (
560     OBJGPU *pGpu,
561     OBJCL  *pCl
562 )
563 {
564     NvU32  linkCtrl;
565     NvBool bEnable = NV_FALSE;
566 
567     if (!pGpu->gpuClData.upstreamPort.addr.valid)
568     {
569         if (!pGpu->gpuClData.rootPort.addr.valid)
570         {
571             bEnable = NV_TRUE;
572         }
573         else
574         {
575             if (clPcieReadPortConfigReg(pGpu, pCl, &pGpu->gpuClData.rootPort,
576                 CL_PCIE_LINK_CTRL_STATUS, &linkCtrl) != NV_OK)
577             {
578                 bEnable = NV_TRUE;
579             }
580             else
581             {
582                 if (!(linkCtrl & CL_PCIE_LINK_CTRL_STATUS_ASPM_L1_BIT))
583                 {
584                     bEnable = NV_TRUE;
585                 }
586             }
587         }
588     }
589     else
590     {
591         if (clPcieReadPortConfigReg(pGpu, pCl, &pGpu->gpuClData.upstreamPort,
592             CL_PCIE_LINK_CTRL_STATUS, &linkCtrl) != NV_OK)
593         {
594             bEnable = NV_TRUE;
595         }
596         else
597         {
598             if (!(linkCtrl & CL_PCIE_LINK_CTRL_STATUS_ASPM_L1_BIT))
599             {
600                 bEnable = NV_TRUE;
601             }
602         }
603     }
604 
605     return bEnable;
606 }
607 
608 /*!
609  * @brief Check if L0s mask is enabled for upstream component
610  *
611  * @param[in] pGpu GPU object pointer
612  * @param[in] pCl  CL  object pointer
613  *
614  * @return NV_TRUE if mask is enabled (implies L0s is disabled)
615  */
616 NvBool
617 clIsL0sMaskEnabledForUpstreamPort_IMPL
618 (
619     OBJGPU *pGpu,
620     OBJCL  *pCl
621 )
622 {
623     NvU32  linkCtrl;
624     NvBool bEnable = NV_FALSE;
625 
626     if (!pGpu->gpuClData.upstreamPort.addr.valid)
627     {
628         if (!pGpu->gpuClData.rootPort.addr.valid)
629         {
630             bEnable = NV_TRUE;
631         }
632         else
633         {
634             if (clPcieReadPortConfigReg(pGpu, pCl, &pGpu->gpuClData.rootPort,
635                 CL_PCIE_LINK_CTRL_STATUS, &linkCtrl) != NV_OK)
636             {
637                 bEnable = NV_TRUE;
638             }
639             else
640             {
641                 if (!(linkCtrl & CL_PCIE_LINK_CTRL_STATUS_ASPM_L0S_BIT))
642                 {
643                     bEnable = NV_TRUE;
644                 }
645             }
646         }
647     }
648     else
649     {
650         if (clPcieReadPortConfigReg(pGpu, pCl, &pGpu->gpuClData.upstreamPort,
651             CL_PCIE_LINK_CTRL_STATUS, &linkCtrl) != NV_OK)
652         {
653             bEnable = NV_TRUE;
654         }
655         else
656         {
657             if (!(linkCtrl & CL_PCIE_LINK_CTRL_STATUS_ASPM_L0S_BIT))
658             {
659                 bEnable = NV_TRUE;
660             }
661         }
662     }
663 
664     return bEnable;
665 }
666 
667 NV_STATUS
668 clInit_IMPL(
669     OBJGPU *pGpu,
670     OBJCL  *pCl
671 )
672 {
673     //
674     // Common code for all buses
675     //
676     (void)clInitMappingPciBusDevice(pGpu, pCl);
677 
678     if (kbifGetBusIntfType_HAL(GPU_GET_KERNEL_BIF(pGpu)) ==
679         NV2080_CTRL_BUS_INFO_TYPE_PCI_EXPRESS)
680     {
681         return clInitPcie(pGpu, pCl);
682     }
683 
684     return NV_OK; // no Init is needed for PCI
685 }
686 
687 void
688 clUpdateConfig_IMPL
689 (
690     OBJGPU *pGpu,
691     OBJCL  *pCl
692 )
693 {
694     // Common code for all buses
695     clInitMappingPciBusDevice(pGpu, pCl);
696 
697     if (kbifGetBusIntfType_HAL(GPU_GET_KERNEL_BIF(pGpu)) ==
698         NV2080_CTRL_BUS_INFO_TYPE_PCI_EXPRESS)
699     {
700         clUpdatePcieConfig(pGpu, pCl);
701         return;
702     }
703 
704     return; // no Update is needed for PCI
705 }
706 
707 NV_STATUS
708 clTeardown_IMPL(
709     OBJGPU *pGpu,
710     OBJCL  *pCl
711 )
712 {
713     KernelBif *pKernelBif = GPU_GET_KERNEL_BIF(pGpu);
714 
715     if (pKernelBif == NULL)
716     {
717         return NV_ERR_NOT_SUPPORTED;
718     }
719 
720     clFreeBusTopologyCache(pCl);
721 
722     switch (kbifGetBusIntfType_HAL(pKernelBif))
723     {
724         case NV2080_CTRL_BUS_INFO_TYPE_PCI_EXPRESS:
725             return clTeardownPcie(pGpu, pCl);
726 
727         case NV2080_CTRL_BUS_INFO_TYPE_PCI:
728         case NV2080_CTRL_BUS_INFO_TYPE_FPCI:
729             return NV_OK;
730 
731         default:
732             return NV_ERR_GENERIC;
733     }
734 }
735 
736 NV_STATUS
737 subdeviceCtrlCmdBusGetBFD_IMPL
738 (
739     Subdevice *pSubdevice,
740     NV2080_CTRL_BUS_GET_BFD_PARAMSARR *pBusGetBFDParams
741 )
742 {
743     OBJSYS *pSys = SYS_GET_INSTANCE();
744     OBJCL  *pCl = SYS_GET_CL(pSys);
745     BUSTOPOLOGYINFO *pBusTopologyInfo = pCl->pBusTopologyInfo;
746     NvU32 i = 0;
747 
748     while(pBusTopologyInfo && i < 32)
749     {
750         pBusGetBFDParams->params[i].valid    = NV_TRUE;
751         pBusGetBFDParams->params[i].deviceID = pBusTopologyInfo->busInfo.deviceID;
752         pBusGetBFDParams->params[i].vendorID = pBusTopologyInfo->busInfo.vendorID;
753         pBusGetBFDParams->params[i].domain   = pBusTopologyInfo->domain;
754         pBusGetBFDParams->params[i].bus      = (NvU16)pBusTopologyInfo->bus;
755         pBusGetBFDParams->params[i].device   = (NvU16)pBusTopologyInfo->device;
756         pBusGetBFDParams->params[i].function = (NvU8)pBusTopologyInfo->func;
757         i++;
758         pBusTopologyInfo = pBusTopologyInfo->next;
759     }
760     if(i < 32)
761     {
762         pBusGetBFDParams->params[i].valid = NV_FALSE;
763     }
764 
765     pBusTopologyInfo = pCl->pBusTopologyInfo;
766     return NV_OK;
767 }
768 
769 void clSyncWithGsp_IMPL(OBJCL *pCl, GspSystemInfo *pGSI)
770 {
771     NvU32 idx = 0;
772 #define CL_SYNC_PDB(prop)                                                       \
773     do {                                                                        \
774         pGSI->clPdbProperties |= pCl->getProperty(pCl, prop) ? NVBIT64(idx) : 0;\
775         idx++;                                                                  \
776     } while (0)
777 
778     CL_SYNC_PDB(PDB_PROP_CL_PCIE_CONFIG_ACCESSIBLE);
779     CL_SYNC_PDB(PDB_PROP_CL_FORCE_SNOOP_READS_AND_WRITES_WAR_BUG_410390);
780     CL_SYNC_PDB(PDB_PROP_CL_DISABLE_BR03_FLOW_CONTROL);
781     CL_SYNC_PDB(PDB_PROP_CL_ASLM_SUPPORTS_NV_LINK_UPGRADE);
782     CL_SYNC_PDB(PDB_PROP_CL_ASLM_SUPPORTS_FAST_LINK_UPGRADE);
783     CL_SYNC_PDB(PDB_PROP_CL_ASLM_SUPPORTS_HOT_RESET);
784     CL_SYNC_PDB(PDB_PROP_CL_ASLM_SUPPORTS_GEN2_LINK_UPGRADE);
785     CL_SYNC_PDB(PDB_PROP_CL_IS_CHIPSET_IN_ASPM_POR_LIST);
786     CL_SYNC_PDB(PDB_PROP_CL_ASPM_L0S_CHIPSET_DISABLED);
787     CL_SYNC_PDB(PDB_PROP_CL_ASPM_L1_CHIPSET_DISABLED);
788     CL_SYNC_PDB(PDB_PROP_CL_ASPM_L0S_CHIPSET_ENABLED_MOBILE_ONLY);
789     CL_SYNC_PDB(PDB_PROP_CL_ASPM_L1_CHIPSET_ENABLED_MOBILE_ONLY);
790     CL_SYNC_PDB(PDB_PROP_CL_ASPM_UPSTREAM_PORT_L1_MASK_ENABLED);
791     CL_SYNC_PDB(PDB_PROP_CL_PCIE_GEN1_GEN2_SWITCH_CHIPSET_DISABLED);
792     CL_SYNC_PDB(PDB_PROP_CL_PCIE_GEN1_GEN2_SWITCH_CHIPSET_DISABLED_GEFORCE);
793     CL_SYNC_PDB(PDB_PROP_CL_EXTENDED_TAG_FIELD_NOT_CAPABLE);
794     CL_SYNC_PDB(PDB_PROP_CL_NOSNOOP_NOT_CAPABLE);
795     CL_SYNC_PDB(PDB_PROP_CL_RELAXED_ORDERING_NOT_CAPABLE);
796     CL_SYNC_PDB(PDB_PROP_CL_PCIE_FORCE_GEN2_ENABLE);
797     CL_SYNC_PDB(PDB_PROP_CL_PCIE_GEN2_AT_LESS_THAN_X16_DISABLED);
798     CL_SYNC_PDB(PDB_PROP_CL_ROOTPORT_NEEDS_NOSNOOP_WAR);
799     CL_SYNC_PDB(PDB_PROP_CL_INTEL_CPU_ROOTPORT1_NEEDS_H57_WAR);
800     CL_SYNC_PDB(PDB_PROP_CL_PCIE_CONFIG_SKIP_MCFG_READ);
801     CL_SYNC_PDB(PDB_PROP_CL_ON_PCIE_GEN3_PATSBURG);
802     CL_SYNC_PDB(PDB_PROP_CL_ALLOW_PCIE_GEN3_ON_PATSBURG_WITH_IVBE_CPU);
803     CL_SYNC_PDB(PDB_PROP_CL_BUG_999673_P2P_ARBITRARY_SPLIT_WAR);
804     CL_SYNC_PDB(PDB_PROP_CL_UPSTREAM_LTR_SUPPORTED);
805     CL_SYNC_PDB(PDB_PROP_CL_BUG_1340801_DISABLE_GEN3_ON_GIGABYTE_SNIPER_3);
806     CL_SYNC_PDB(PDB_PROP_CL_BUG_1681803_WAR_DISABLE_MSCG);
807     CL_SYNC_PDB(PDB_PROP_CL_ON_HASWELL_HOST_BRIDGE);
808     CL_SYNC_PDB(PDB_PROP_CL_PCIE_NON_COHERENT_USE_TC0_ONLY);
809     CL_SYNC_PDB(PDB_PROP_CL_UNSUPPORTED_CHIPSET);
810     CL_SYNC_PDB(PDB_PROP_CL_IS_CHIPSET_IO_COHERENT);
811     CL_SYNC_PDB(PDB_PROP_CL_DISABLE_IOMAP_WC);
812     CL_SYNC_PDB(PDB_PROP_CL_HAS_RESIZABLE_BAR_ISSUE);
813     CL_SYNC_PDB(PDB_PROP_CL_IS_EXTERNAL_GPU);
814     CL_SYNC_PDB(PDB_PROP_CL_BUG_3751839_GEN_SPEED_WAR);
815     CL_SYNC_PDB(PDB_PROP_CL_BUG_3562968_WAR_ALLOW_PCIE_ATOMICS);
816 
817 #undef CL_SYNC_PDB
818 
819     NV_ASSERT(idx < (sizeof(pGSI->clPdbProperties) * 8));
820 
821     pGSI->Chipset = pCl->Chipset;
822     pGSI->FHBBusInfo = pCl->FHBBusInfo;
823     pGSI->chipsetIDInfo = pCl->chipsetIDInfo;
824 
825 }
826