Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp154529ybl; Thu, 9 Jan 2020 19:02:25 -0800 (PST) X-Google-Smtp-Source: APXvYqw6LUhDTvhKbw++NW5HfYrORgoZ9sleqcNWtqc4USiFGIDHA/97E2DM1JvVyHfsetUv8oZc X-Received: by 2002:aca:ed57:: with SMTP id l84mr573878oih.8.1578625345404; Thu, 09 Jan 2020 19:02:25 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1578625345; cv=none; d=google.com; s=arc-20160816; b=KWw5GYLULIuuxl8q1LTjdldjBH1ryMYhJrghznAd89YhunM+NkV+UKoKoPPBmKP7g+ Ls61c/PHtVa5G4pl9RbSdIHErdqZ7u9Tx3imzrpa0KdsOjrgKUG60yETS5Ehzy2s39S5 aKx9rcXL31S8BJwcTD0ib2XUdMv0xaeFPedTmj9oeuxvz0oqOsyq0JWe0IKi01HBgLGQ 4bErvAsutENCzIHWXdinXEhVx2Yr2qGzpp837Lmf8GdG93y18/xQW3assuMqF1vSONbg ozygPRiT6stfRw0Ipu7uu9n5tLPjzEZqusCw1BuDzLXV63AM2arahybbItnvI8EGC9d/ Mg9w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:from:subject:mime-version :message-id:date:dkim-signature; bh=DnJt6kh0aGUVWb0xLd06fVCxkcizC6ZskKYdvVAtBnY=; b=Ab0vFI9i1ob85yBmkvKOXdGj3rAqJKIiM8Vn4ugFDTkeYBY8O5+c8/APD+4ELVIsUn QHFFpy3ZPmZHPqxmBpBU6YGn73cHH4hmiM9VOUtmVyiKnjUd8mFIiGv7hQPDPsdmY4HZ 2ikdm/H8kDgKImZHTurpbN5eG2kJJ0g1ls9CkZq/esZ2ML33y8apiw1jdq2Tm1pH3MU5 c1P2NOa+j9uWG7q3sb9eoWrNnaQFm3AXOolGoFD0AcCcY+v5c2rgD9108UcCkjKhiZ8D d3gSfQgPW1FDh69H5NFj381wwgTblLVGKjeio62uk+weSxabaY1/A99aHD0j+2TCErc9 qPcw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b="Gh/Tzuzj"; 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; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y22si325810oti.269.2020.01.09.19.02.13; Thu, 09 Jan 2020 19:02:25 -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=@google.com header.s=20161025 header.b="Gh/Tzuzj"; 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; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730973AbgAJDBS (ORCPT + 99 others); Thu, 9 Jan 2020 22:01:18 -0500 Received: from mail-pl1-f201.google.com ([209.85.214.201]:42331 "EHLO mail-pl1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730966AbgAJDBS (ORCPT ); Thu, 9 Jan 2020 22:01:18 -0500 Received: by mail-pl1-f201.google.com with SMTP id b4so432175plr.9 for ; Thu, 09 Jan 2020 19:01:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=DnJt6kh0aGUVWb0xLd06fVCxkcizC6ZskKYdvVAtBnY=; b=Gh/Tzuzj0IXUAC+PeJ5gpwwjiQEWvlG05ugX1k3UhhcPz+XW1JMgH4prOJQdAs2KaM HcCZRLNIUISbv5kMSxR7/Qb5v9DAhnMtgZ87s6qfnek8ayNXvEWfHDTY5ea8oYAd7ukv LrORKZUIZVMeeE/IT1I1hAZVOpnTfKCbwTl5I+n1Iq/s0NsNL7+/6qxm05JnzpsT1fUo cKWx/AC9e2iulmA2L/B9pmVpm5i4ARMGbEVOHsLV9so0/T5pWdAY5ym2fEO/YO4q6a7z rIBYjT2mkC4MUxnEcpy+eI99jDxop/5TFDHR0rnxhv/hqXFy4vYPKDnE0qJKJUaa0a6o gQnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=DnJt6kh0aGUVWb0xLd06fVCxkcizC6ZskKYdvVAtBnY=; b=T9zorHMsDyvk7Wyjcriuj1rRMVz3TEFaRRUv7Rgeo8C2NXATGwKjxuhXv5XVtvVkbx AIC17R0qQ0bzAY7/4teb1HlT1HbR7dsffUDZGsntvoxTGv2pZNS8nRXHx+Ss6CMIZ0Sy 8xRMLiPbQA5OuZuFFf+SdgNtxMLHZB9uQ4JrA+mM8eeIgtJJopqWVjEhoFCR7O3Acg6l KlwPujBUmXrtwVDpte9f1vfujVF9tbilYTMkvlQB/K/Pp8pA/gpp/mPQUMchl8GeUALs YF/whulsg4KHWGQ6nm0TmuIOY7ZeOrh8blN10zyzpTe65Jn2ZwFVjCyxeFKE8o4fmRb1 RwoQ== X-Gm-Message-State: APjAAAVZ5Wa1JvI38133pLZbsLiuGqMbTGgmnM0k9oNwtlmhAJ5kNG7T aTWelcaZUvZacMwj1SvhQLtwsZyNn+JDgw4= X-Received: by 2002:a63:1210:: with SMTP id h16mr1450210pgl.171.1578625276730; Thu, 09 Jan 2020 19:01:16 -0800 (PST) Date: Thu, 9 Jan 2020 19:01:11 -0800 Message-Id: <20200110030112.188845-1-saravanak@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.25.0.rc1.283.g88dfdc4193-goog Subject: [PATCH v3] efi: arm: defer probe of PCIe backed efifb on DT systems From: Saravana Kannan To: Ard Biesheuvel Cc: linux-arm-kernel@lists.infradead.org, will@kernel.org, bhelgaas@google.com, Greg Kroah-Hartman , Saravana Kannan , kernel-team@android.com, linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ard Biesheuvel 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. Cc: Greg Kroah-Hartman Signed-off-by: Ard Biesheuvel Co-developed-by: Saravana Kannan Signed-off-by: Saravana Kannan Reviewed-by: Ard Biesheuvel --- v1 -> v2: - Rewrote the device linking part to not depend on initcall ordering v2 -> v3: - Added const and check for CONFIG_PCI 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 904fa09e6a6b..d99f5b0c8a09 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.25.0.rc1.283.g88dfdc4193-goog