|
18 | 18 | #include "level_zero/core/source/driver/driver_handle_imp.h"
|
19 | 19 | #include "level_zero/tools/source/sysman/firmware_util/firmware_util.h"
|
20 | 20 | #include "level_zero/tools/source/sysman/linux/fs_access.h"
|
| 21 | +#include "level_zero/tools/source/sysman/pci/linux/os_pci_imp.h" |
21 | 22 |
|
22 | 23 | namespace L0 {
|
23 | 24 |
|
@@ -377,6 +378,56 @@ void LinuxSysmanImp::clearHPIE(int fd) {
|
377 | 378 | NEO::sleep(std::chrono::seconds(10)); // Sleep for 10seconds just to make sure the change is propagated.
|
378 | 379 | }
|
379 | 380 |
|
| 381 | +// Function to adjust VF BAR size i.e Modify VF BAR Control register. |
| 382 | +// size param is an encoded value described as follows: |
| 383 | +// 0 - 1 MB (2^20 bytes) |
| 384 | +// 1 - 2 MB (2^21 bytes) |
| 385 | +// 2 - 4 MB (2^22 bytes) |
| 386 | +// 3 - 8 MB (2^23 bytes) |
| 387 | +// . |
| 388 | +// . |
| 389 | +// . |
| 390 | +// b - 2 GB (2^31 bytes) |
| 391 | +// 43 - 8 EB (2^63 bytes) |
| 392 | +ze_result_t LinuxSysmanImp::resizeVfBar(uint8_t size) { |
| 393 | + std::string pciConfigNode; |
| 394 | + pciConfigNode = gtDevicePath + "/config"; |
| 395 | + |
| 396 | + int fdConfig = -1; |
| 397 | + fdConfig = this->openFunction(pciConfigNode.c_str(), O_RDWR); |
| 398 | + if (fdConfig < 0) { |
| 399 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stdout, |
| 400 | + "Config node open failed\n"); |
| 401 | + return ZE_RESULT_ERROR_UNKNOWN; |
| 402 | + } |
| 403 | + std::unique_ptr<uint8_t[]> configMemory = std::make_unique<uint8_t[]>(PCI_CFG_SPACE_EXP_SIZE); |
| 404 | + memset(configMemory.get(), 0, PCI_CFG_SPACE_EXP_SIZE); |
| 405 | + if (this->preadFunction(fdConfig, configMemory.get(), PCI_CFG_SPACE_EXP_SIZE, 0) < 0) { |
| 406 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stdout, |
| 407 | + "Read to get config space failed\n"); |
| 408 | + return ZE_RESULT_ERROR_UNKNOWN; |
| 409 | + } |
| 410 | + auto reBarCapPos = L0::LinuxPciImp::getRebarCapabilityPos(configMemory.get(), true); |
| 411 | + if (!reBarCapPos) { |
| 412 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stdout, |
| 413 | + "VF BAR capability not found\n"); |
| 414 | + return ZE_RESULT_ERROR_UNKNOWN; |
| 415 | + } |
| 416 | + |
| 417 | + auto barSizePos = reBarCapPos + PCI_REBAR_CTRL + 1; // position of VF(0) BAR SIZE. |
| 418 | + if (this->pwriteFunction(fdConfig, &size, 0x01, barSizePos) < 0) { |
| 419 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stdout, |
| 420 | + "Write to change VF bar size failed\n"); |
| 421 | + return ZE_RESULT_ERROR_UNKNOWN; |
| 422 | + } |
| 423 | + if (this->closeFunction(fdConfig) < 0) { |
| 424 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stdout, |
| 425 | + "Config node close failed\n"); |
| 426 | + return ZE_RESULT_ERROR_UNKNOWN; |
| 427 | + } |
| 428 | + return ZE_RESULT_SUCCESS; |
| 429 | +} |
| 430 | + |
380 | 431 | // A 'warm reset' is a conventional reset that is triggered across a PCI express link.
|
381 | 432 | // A warm reset is triggered either when a link is forced into electrical idle or
|
382 | 433 | // by sending TS1 and TS2 ordered sets with the hot reset bit set.
|
@@ -432,6 +483,31 @@ ze_result_t LinuxSysmanImp::osWarmReset() {
|
432 | 483 | return ZE_RESULT_ERROR_UNKNOWN;
|
433 | 484 | }
|
434 | 485 |
|
| 486 | + // PCIe port driver uses the BIOS allocated VF bars on bootup. A known bug exists in pcie port driver |
| 487 | + // and is causing VF bar allocation failure in PCIe port driver after an SBR - https://bugzilla.kernel.org/show_bug.cgi?id=216795 |
| 488 | + |
| 489 | + // WA to adjust VF bar size to 2GB. The default VF bar size is 8GB and for 63VFs, 504GB need to be allocated which is failing on SBR. |
| 490 | + // When configured VF bar size to 2GB, an allocation of 126GB is successful. This WA resizes VF0 bar to 2GB. Once pcie port driver |
| 491 | + // issue is resolved, this WA may not be necessary. Description for 0xb is explained at function definition - resizeVfVar. |
| 492 | + if (NEO::DebugManager.flags.VfBarResourceAllocationWa.get()) { |
| 493 | + if (ZE_RESULT_SUCCESS != (result = resizeVfBar(0xb))) { |
| 494 | + return result; |
| 495 | + } |
| 496 | + |
| 497 | + result = pFsAccess->write(cardBusPath + '/' + "remove", "1"); |
| 498 | + if (ZE_RESULT_SUCCESS != result) { |
| 499 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stdout, |
| 500 | + "Card Bus remove after resizing VF bar failed\n"); |
| 501 | + return result; |
| 502 | + } |
| 503 | + |
| 504 | + result = pFsAccess->write(rootPortPath + '/' + "rescan", "1"); |
| 505 | + if (ZE_RESULT_SUCCESS != result) { |
| 506 | + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stdout, |
| 507 | + "Rescanning root port failed after resizing VF bar failed\n"); |
| 508 | + return result; |
| 509 | + } |
| 510 | + } |
435 | 511 | return result;
|
436 | 512 | }
|
437 | 513 |
|
|
0 commit comments