Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp1594594ybv; Thu, 20 Feb 2020 23:57:54 -0800 (PST) X-Google-Smtp-Source: APXvYqwBVtKIEcplUztTCRjslCagVoBF9f2c3oQ2YGVhkFg9uwv/+cwvlnS4mfI/OHlHk6bnN1J3 X-Received: by 2002:a9d:7386:: with SMTP id j6mr26417094otk.336.1582271874633; Thu, 20 Feb 2020 23:57:54 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1582271874; cv=none; d=google.com; s=arc-20160816; b=yitMS9WlK5PTU4jnIgmHqNgGHzhd40GoL+7KhVdIh5bf5Q1i2Bo8pzZA634aev58Ge T0B3KiQtAgXWUsu6CDbkdeRzHA1q6q/Gwo42t+G2R12PsWwcMUaxFpmjiYfcUVNopYS4 8JjYQd+ZswzHhp0dd3cLhUN/t4THyng6WeRe1gV38fIqqcmDmO/8Ce9/OTqfh9HE6+PJ kTndVn59A+jttDK93dFHrNDoMakSRLn8OmuT0aMVG4QEl0U4d7dnDWCAPnOdx8HKq7BQ LUAlc0ElBpPlb6k+A5q0M2WqcXrNfZ0wdHjCJYnrV+0RYScaAGIo62gOyyot4L0I8zd3 1WwQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=ZCsPLFt3QIulc2zYiyoAS+xdlOCvU26ei3UAjXrFPJQ=; b=tOEkFjedxXF2xMjk1d9NI+ZNmHfmx3na9Z0kcBRxpDYJpM84nlwQ3ubq7hgIVg8AVP ZlhpQPL2azU7V0scBSrZFm0oMUM9YdzcwR6VNP3OpPIYimIP3q/J412Of14wjx2rRFsp LwiFCtof6XXRYZvAJGEWNIac6cZpb0vFXsWyu0GunakM2Nrk/CXOgwG9vZ3oI6mSWSc7 V+fKS7ePaWn+4apDUYycIqSPk+exFD6oBPOVHKwWZIHTht+b5nk3PMCNqbEojxTDqMhD EjQX+Pm4pNhg2miEKCTDvLJOTB+Hqt+ID6nm7cuZhgLxkrxmtkvozZFUzKU+WQ82KjG7 J94Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="j/LVxLr2"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p186si416576oih.172.2020.02.20.23.57.42; Thu, 20 Feb 2020 23:57:54 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="j/LVxLr2"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730362AbgBUH4l (ORCPT + 99 others); Fri, 21 Feb 2020 02:56:41 -0500 Received: from mail.kernel.org ([198.145.29.99]:55992 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728972AbgBUH4f (ORCPT ); Fri, 21 Feb 2020 02:56:35 -0500 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 91531222C4; Fri, 21 Feb 2020 07:56:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1582271795; bh=GiqdFSZEoNy8iXjcP7SuRT0i4X8ZFZZeuCykkBIh0EQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=j/LVxLr2BK4/HY9IVHqV12B7qAqBqdPf/O4914cozZAYn9Ci0zxYJ0tsozOkw8YCA 9Bvnc0K8qhKeqXVJreFfkgsqRBO+HPSPe0H0k2h9+Xk36xHd8nhUWfl6uI5UVI5sCT B54HixdXDhWrMvmq+/ZeVP6HSnvDmqS97H65WFTo= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Ard Biesheuvel , Saravana Kannan , Ingo Molnar , Sasha Levin Subject: [PATCH 5.5 301/399] efi/arm: Defer probe of PCIe backed efifb on DT systems Date: Fri, 21 Feb 2020 08:40:26 +0100 Message-Id: <20200221072430.971379101@linuxfoundation.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200221072402.315346745@linuxfoundation.org> References: <20200221072402.315346745@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ard Biesheuvel [ Upstream commit 64c8a0cd0a535891d5905c3a1651150f0f141439 ] The new of_devlink support breaks PCIe probing on ARM platforms booting via UEFI if the firmware exposes a EFI framebuffer that is backed by a PCI device. The reason is that the probing order gets reversed, resulting in a resource conflict on the framebuffer memory window when the PCIe probes last, causing it to give up entirely. Given that we rely on PCI quirks to deal with EFI framebuffers that get moved around in memory, we cannot simply drop the memory reservation, so instead, let's use the device link infrastructure to register this dependency, and force the probing to occur in the expected order. Co-developed-by: Saravana Kannan Signed-off-by: Ard Biesheuvel Signed-off-by: Saravana Kannan Signed-off-by: Ard Biesheuvel Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/20200113172245.27925-9-ardb@kernel.org Signed-off-by: Sasha Levin --- drivers/firmware/efi/arm-init.c | 107 ++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 904fa09e6a6b0..d99f5b0c8a090 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -10,10 +10,12 @@ #define pr_fmt(fmt) "efi: " fmt #include +#include #include #include #include #include +#include #include #include #include @@ -276,15 +278,112 @@ void __init efi_init(void) efi_memmap_unmap(); } +static bool efifb_overlaps_pci_range(const struct of_pci_range *range) +{ + u64 fb_base = screen_info.lfb_base; + + if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) + fb_base |= (u64)(unsigned long)screen_info.ext_lfb_base << 32; + + return fb_base >= range->cpu_addr && + fb_base < (range->cpu_addr + range->size); +} + +static struct device_node *find_pci_overlap_node(void) +{ + struct device_node *np; + + for_each_node_by_type(np, "pci") { + struct of_pci_range_parser parser; + struct of_pci_range range; + int err; + + err = of_pci_range_parser_init(&parser, np); + if (err) { + pr_warn("of_pci_range_parser_init() failed: %d\n", err); + continue; + } + + for_each_of_pci_range(&parser, &range) + if (efifb_overlaps_pci_range(&range)) + return np; + } + return NULL; +} + +/* + * If the efifb framebuffer is backed by a PCI graphics controller, we have + * to ensure that this relation is expressed using a device link when + * running in DT mode, or the probe order may be reversed, resulting in a + * resource reservation conflict on the memory window that the efifb + * framebuffer steals from the PCIe host bridge. + */ +static int efifb_add_links(const struct fwnode_handle *fwnode, + struct device *dev) +{ + struct device_node *sup_np; + struct device *sup_dev; + + sup_np = find_pci_overlap_node(); + + /* + * If there's no PCI graphics controller backing the efifb, we are + * done here. + */ + if (!sup_np) + return 0; + + sup_dev = get_dev_from_fwnode(&sup_np->fwnode); + of_node_put(sup_np); + + /* + * Return -ENODEV if the PCI graphics controller device hasn't been + * registered yet. This ensures that efifb isn't allowed to probe + * and this function is retried again when new devices are + * registered. + */ + if (!sup_dev) + return -ENODEV; + + /* + * If this fails, retrying this function at a later point won't + * change anything. So, don't return an error after this. + */ + if (!device_link_add(dev, sup_dev, 0)) + dev_warn(dev, "device_link_add() failed\n"); + + put_device(sup_dev); + + return 0; +} + +static const struct fwnode_operations efifb_fwnode_ops = { + .add_links = efifb_add_links, +}; + +static struct fwnode_handle efifb_fwnode = { + .ops = &efifb_fwnode_ops, +}; + static int __init register_gop_device(void) { - void *pd; + struct platform_device *pd; + int err; if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) return 0; - pd = platform_device_register_data(NULL, "efi-framebuffer", 0, - &screen_info, sizeof(screen_info)); - return PTR_ERR_OR_ZERO(pd); + pd = platform_device_alloc("efi-framebuffer", 0); + if (!pd) + return -ENOMEM; + + if (IS_ENABLED(CONFIG_PCI)) + pd->dev.fwnode = &efifb_fwnode; + + err = platform_device_add_data(pd, &screen_info, sizeof(screen_info)); + if (err) + return err; + + return platform_device_add(pd); } subsys_initcall(register_gop_device); -- 2.20.1