From nobody Mon Apr 29 10:54:39 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1524709445669807.4365222561706; Wed, 25 Apr 2018 19:24:05 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 3DD08202E5F09; Wed, 25 Apr 2018 19:24:02 -0700 (PDT) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 6DFC9202E5EFE for ; Wed, 25 Apr 2018 19:24:00 -0700 (PDT) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 25 Apr 2018 19:24:00 -0700 Received: from ray-dev.ccr.corp.intel.com ([10.239.9.4]) by fmsmga001.fm.intel.com with ESMTP; 25 Apr 2018 19:23:59 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.88; helo=mga01.intel.com; envelope-from=ruiyu.ni@intel.com; receiver=edk2-devel@lists.01.org X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,328,1520924400"; d="scan'208";a="50018460" From: Ruiyu Ni To: edk2-devel@lists.01.org Date: Thu, 26 Apr 2018 10:23:56 +0800 Message-Id: <20180426022356.66540-1-ruiyu.ni@intel.com> X-Mailer: git-send-email 2.16.1.windows.1 Subject: [edk2] [PATCH] MdeModulePkg/PciHostBridge: Count the (mm)io overhead when polling X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" RootBridgeIo.PollMem()/PollIo() originally don't count the IO/MMIO access overhead when delaying. The patch changes the implementation to count the access overhead so that the actually delay equals to user required delay. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ruiyu Ni Cc: Star Zeng Cc: Chasel Chiu Reviewed-by: Star Zeng if it is updated. :) --- .../Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf | 3 +- .../Bus/Pci/PciHostBridgeDxe/PciRootBridge.h | 3 +- .../Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c | 151 +++++++++++++++--= ---- 3 files changed, 115 insertions(+), 42 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf b/M= deModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf index 42bd8a23cb..2e56959a8f 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf @@ -1,7 +1,7 @@ ## @file # Generic PCI Host Bridge driver. # -# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions of the B= SD License @@ -43,6 +43,7 @@ [LibraryClasses] PciSegmentLib UefiLib PciHostBridgeLib + TimerLib =20 [Protocols] gEfiMetronomeArchProtocolGuid ## CONSUMES diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h b/MdeMod= ulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h index d3dfb57fc6..e2f651aee4 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridge.h @@ -2,7 +2,7 @@ =20 The PCI Root Bridge header file. =20 -Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
+Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD = License which accompanies this distribution. The full text of the license may be = found at @@ -36,6 +36,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER= EXPRESS OR IMPLIED. #include #include #include +#include #include "PciHostResource.h" =20 =20 diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeM= odulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c index 5764c2f49f..459e962fe7 100644 --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c @@ -2,7 +2,7 @@ =20 PCI Root Bridge Io Protocol code. =20 -Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
+Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD = License which accompanies this distribution. The full text of the license may be = found at @@ -468,6 +468,85 @@ RootBridgeIoGetMemTranslationByAddress ( return EFI_SUCCESS; } =20 +/** + Return the result of (Multiplicand * Multiplier / Divisor). + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter= is + optional and may be NULL. + + @return Multiplicand * Multiplier / Divisor. +**/ +UINT64 +MultThenDivU64x64x32 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier, + IN UINT32 Divisor, + OUT UINT32 *Remainder OPTIONAL + ) +{ + UINT64 Uint64; + UINT32 LocalRemainder; + UINT32 Uint32; + if (Multiplicand >=3D DivU64x64Remainder (MAX_UINT64, Multiplier, NULL))= { + // + // Make sure Multiplicand is the bigger one. + // + if (Multiplicand < Multiplier) { + Uint64 =3D Multiplicand; + Multiplicand =3D Multiplier; + Multiplier =3D Uint64; + } + // + // Because Multiplicand * Multiplier overflows, + // Multiplicand * Multiplier / Divisor + // =3D (2 * Multiplicand' + 1) * Multiplier / Divisor + // =3D 2 * (Multiplicand' * Multiplier / Divisor) + Multiplier / Divis= or + // + Uint64 =3D MultThenDivU64x64x32 (RShiftU64 (Multiplicand, 1), Multipli= er, Divisor, &LocalRemainder); + Uint64 =3D LShiftU64 (Uint64, 1); + Uint32 =3D 0; + if ((Multiplicand & 0x1) =3D=3D 1) { + Uint64 +=3D DivU64x32Remainder (Multiplier, Divisor, &Uint32); + } + return Uint64 + DivU64x32Remainder (Uint32 + LShiftU64 (LocalRemainder= , 1), Divisor, Remainder); + } else { + return DivU64x32Remainder (MultU64x64 (Multiplicand, Multiplier), Divi= sor, Remainder); + } +} + +/** + Return the elapsed tick count from CurrentTick. + + @param CurrentTick On input, the previous tick count. + On output, the current tick count. + @param StartTick The value the performance counter starts with when = it + rolls over. + @param EndTick The value that the performance counter ends with be= fore + it rolls over. + + @return The elapsed tick count from CurrentTick. +**/ +UINT64 +GetElapsedTick ( + UINT64 *CurrentTick, + UINT64 StartTick, + UINT64 EndTick + ) +{ + UINT64 PreviousTick; + =20 + PreviousTick =3D *CurrentTick; + *CurrentTick =3D GetPerformanceCounter(); + if (StartTick < EndTick) { + return *CurrentTick - PreviousTick; + } else { + return PreviousTick - *CurrentTick; + } +} + /** Polls an address in memory mapped I/O space until an exit condition is m= et, or a timeout occurs. @@ -517,6 +596,11 @@ RootBridgeIoPollMem ( EFI_STATUS Status; UINT64 NumberOfTicks; UINT32 Remainder; + UINT64 StartTick; + UINT64 EndTick; + UINT64 CurrentTick; + UINT64 ElapsedTick; + UINT64 Frequency; =20 if (Result =3D=3D NULL) { return EFI_INVALID_PARAMETER; @@ -542,28 +626,18 @@ RootBridgeIoPollMem ( return EFI_SUCCESS; =20 } else { - - // - // Determine the proper # of metronome ticks to wait for polling the - // location. The nuber of ticks is Roundup (Delay / - // mMetronome->TickPeriod)+1 - // The "+1" to account for the possibility of the first tick being sho= rt - // because we started in the middle of a tick. // - // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metrono= me - // protocol definition is updated. + // NumberOfTicks =3D Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1) // - NumberOfTicks =3D DivU64x32Remainder (Delay, (UINT32) mMetronome->Tick= Period, - &Remainder); - if (Remainder !=3D 0) { - NumberOfTicks +=3D 1; + Frequency =3D GetPerformanceCounterProperties (&StartTick, &EndTic= k); + NumberOfTicks =3D MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_= TIMER_PERIOD_SECONDS(1), &Remainder); + if (Remainder >=3D (UINTN)EFI_TIMER_PERIOD_SECONDS(1) / 2) { + NumberOfTicks++; } - NumberOfTicks +=3D 1; - - while (NumberOfTicks !=3D 0) { - - mMetronome->WaitForTick (mMetronome, 1); - + for ( ElapsedTick =3D 0, CurrentTick =3D GetPerformanceCounter() + ; ElapsedTick <=3D NumberOfTicks + ; ElapsedTick +=3D GetElapsedTick (&CurrentTick, StartTick, EndTic= k) + ) { Status =3D This->Mem.Read (This, Width, Address, 1, Result); if (EFI_ERROR (Status)) { return Status; @@ -572,8 +646,6 @@ RootBridgeIoPollMem ( if ((*Result & Mask) =3D=3D Value) { return EFI_SUCCESS; } - - NumberOfTicks -=3D 1; } } return EFI_TIMEOUT; @@ -626,6 +698,11 @@ RootBridgeIoPollIo ( EFI_STATUS Status; UINT64 NumberOfTicks; UINT32 Remainder; + UINT64 StartTick; + UINT64 EndTick; + UINT64 CurrentTick; + UINT64 ElapsedTick; + UINT64 Frequency; =20 // // No matter what, always do a single poll. @@ -651,25 +728,18 @@ RootBridgeIoPollIo ( return EFI_SUCCESS; =20 } else { - // - // Determine the proper # of metronome ticks to wait for polling the - // location. The number of ticks is Roundup (Delay / - // mMetronome->TickPeriod)+1 - // The "+1" to account for the possibility of the first tick being sho= rt - // because we started in the middle of a tick. + // NumberOfTicks =3D Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1) // - NumberOfTicks =3D DivU64x32Remainder (Delay, (UINT32)mMetronome->TickP= eriod, - &Remainder); - if (Remainder !=3D 0) { - NumberOfTicks +=3D 1; + Frequency =3D GetPerformanceCounterProperties (&StartTick, &EndTic= k); + NumberOfTicks =3D MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_= TIMER_PERIOD_SECONDS(1), &Remainder); + if (Remainder >=3D (UINTN)EFI_TIMER_PERIOD_SECONDS(1) / 2) { + NumberOfTicks++; } - NumberOfTicks +=3D 1; - - while (NumberOfTicks !=3D 0) { - - mMetronome->WaitForTick (mMetronome, 1); - + for ( ElapsedTick =3D 0, CurrentTick =3D GetPerformanceCounter() + ; ElapsedTick <=3D NumberOfTicks + ; ElapsedTick +=3D GetElapsedTick (&CurrentTick, StartTick, EndTic= k) + ) { Status =3D This->Io.Read (This, Width, Address, 1, Result); if (EFI_ERROR (Status)) { return Status; @@ -678,13 +748,14 @@ RootBridgeIoPollIo ( if ((*Result & Mask) =3D=3D Value) { return EFI_SUCCESS; } - - NumberOfTicks -=3D 1; } } return EFI_TIMEOUT; } =20 + + + /** Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. --=20 2.16.1.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel