From patchwork Fri Jul 1 01:10:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laszlo Ersek X-Patchwork-Id: 71276 Delivered-To: patch@linaro.org Received: by 10.140.28.4 with SMTP id 4csp44128qgy; Thu, 30 Jun 2016 18:11:11 -0700 (PDT) X-Received: by 10.98.72.150 with SMTP id q22mr26728465pfi.122.1467335471282; Thu, 30 Jun 2016 18:11:11 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [2001:19d0:306:5::1]) by mx.google.com with ESMTPS id vn13si1220239pab.242.2016.06.30.18.11.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 30 Jun 2016 18:11:11 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) client-ip=2001:19d0:306:5::1; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 053A21A1E3A; Thu, 30 Jun 2016 18:11:47 -0700 (PDT) X-Original-To: edk2-devel@ml01.01.org Delivered-To: edk2-devel@ml01.01.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (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 B02071A1E31 for ; Thu, 30 Jun 2016 18:11:45 -0700 (PDT) Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A311A63171; Fri, 1 Jul 2016 01:11:08 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-60.phx2.redhat.com [10.3.116.60]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u611Av23009843; Thu, 30 Jun 2016 21:11:06 -0400 From: Laszlo Ersek To: edk2-devel-01 Date: Fri, 1 Jul 2016 03:10:52 +0200 Message-Id: <1467335453-25967-4-git-send-email-lersek@redhat.com> In-Reply-To: <1467335453-25967-1-git-send-email-lersek@redhat.com> References: <1467335453-25967-1-git-send-email-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 01 Jul 2016 01:11:08 +0000 (UTC) Subject: [edk2] [PATCH 3/4] MdeModulePkg/PciBusDxe: recognize hotplug-capable PCIe ports X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Ruiyu Ni , Feng Tian , "Johnson, Brian J." , Andrew Fish , Jordan Justen , Marcel Apfelbaum , Star Zeng MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" Section 7.8.2 of the PCI Express specification (r4.0 v0.3), entitled "PCI Express Capabilities Register (Offset 02h)", describes the conditions when a PCIe port should be considered "supporting hotplug": - it should be a root complex port or a switch downstream port, and - it should have the "Slot Implemented" bit set. This logic is already implemented in at least two open source projects I could find: - in SeaBIOS by Marcel Apfelbaum: "hw/pci: reserve IO and mem for pci express downstream ports with no devices attached" , - in edk2 itself, in the implementation of the "PCI" UEFI Shell command: see the "PcieExplainTypeSlot" case label in function PciExplainPciExpress(), file "ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c". PciBusDxe recognizes such PCIe ports as bridges, but it doesn't realize they support hotplug. In turn PciBusDxe omits getting any resource padding information from the platform's EFI_PCI_HOT_PLUG_INIT_PROTOCOL for these bridges: GatherPpbInfo() [PciEnumeratorSupport.c] GetResourcePaddingPpb() [PciResourceSupport.c] GetResourcePaddingForHpb() [PciHotPlugSupport.c] IsPciHotPlugBus() [PciHotPlugSupport.c] // // returns FALSE // // // the following is not reached: // gPciHotPlugInit->GetResourcePadding() Implement a function called SupportsPcieHotplug() for identifying such ports, and call it from IsPciHotPlugBus() (after the call to IsSHPC()). Cc: "Johnson, Brian J." Cc: Alex Williamson Cc: Andrew Fish Cc: Feng Tian Cc: Jordan Justen Cc: Marcel Apfelbaum Cc: Ruiyu Ni Cc: Star Zeng Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek --- MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h | 19 ++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c | 71 ++++++++++++++++++++ 2 files changed, 90 insertions(+) -- 1.8.3.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h index 1fb9ba972091..6e02b8b98bf0 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h @@ -177,6 +177,25 @@ IsSHPC ( ); /** + Check whether PciIoDevice supports PCIe hotplug. + + This is equivalent to the following condition: + - the device is either a PCIe switch downstream port or a root port, + - and the device has the SlotImplemented bit set in its PCIe capability + register. + + @param[in] PciIoDevice The device being checked. + + @retval TRUE PciIoDevice is a PCIe port that accepts a hotplugged device. + @retval FALSE Otherwise. + +**/ +BOOLEAN +SupportsPcieHotplug ( + IN PCI_IO_DEVICE *PciIoDevice + ); + +/** Get resource padding if the specified PCI bridge is a hot plug bus. @param PciIoDevice PCI bridge instance. diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c index ca8766869ae7..19dd97a4528d 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c @@ -317,6 +317,69 @@ IsSHPC ( } /** + Check whether PciIoDevice supports PCIe hotplug. + + This is equivalent to the following condition: + - the device is either a PCIe switch downstream port or a root port, + - and the device has the SlotImplemented bit set in its PCIe capability + register. + + @param[in] PciIoDevice The device being checked. + + @retval TRUE PciIoDevice is a PCIe port that accepts a hotplugged device. + @retval FALSE Otherwise. + +**/ +BOOLEAN +SupportsPcieHotplug ( + IN PCI_IO_DEVICE *PciIoDevice + ) +{ + UINT32 Offset; + EFI_STATUS Status; + PCI_REG_PCIE_CAPABILITY Capability; + + if (PciIoDevice == NULL) { + return FALSE; + } + + // + // Read the PCI Express Capabilities Register + // + if (!PciIoDevice->IsPciExp) { + return FALSE; + } + Offset = PciIoDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, Capability); + + Status = PciIoDevice->PciIo.Pci.Read ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &Capability + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Check the contents of the register + // + switch (Capability.Bits.DevicePortType) { + case PCIE_DEVICE_PORT_TYPE_ROOT_PORT: + case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT: + break; + default: + return FALSE; + } + if (Capability.Bits.SlotImplemented) { + return TRUE; + } + return FALSE; +} + +/** Get resource padding if the specified PCI bridge is a hot plug bus. @param PciIoDevice PCI bridge instance. @@ -382,6 +445,14 @@ IsPciHotPlugBus ( return TRUE; } + if (SupportsPcieHotplug (PciIoDevice)) { + // + // If the PPB is a PCIe root complex port or a switch downstream port, and + // implements a slot, then also return TRUE. + // + return TRUE; + } + // // Otherwise, see if it is a Root HPC //