From patchwork Tue Feb 9 14:30:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 580868 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 9667514031D for ; Wed, 10 Feb 2016 01:30:55 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=d9f/YFbC; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753120AbcBIOay (ORCPT ); Tue, 9 Feb 2016 09:30:54 -0500 Received: from mail-wm0-f45.google.com ([74.125.82.45]:37165 "EHLO mail-wm0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932328AbcBIOax (ORCPT ); Tue, 9 Feb 2016 09:30:53 -0500 Received: by mail-wm0-f45.google.com with SMTP id g62so25870973wme.0; Tue, 09 Feb 2016 06:30:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=RZL3TrsWEBMK3ueTWz2OT21WPEVx+VlxVM8AqVGb50g=; b=d9f/YFbC57KZYOIhC+RLm3j7k0QSrdLfvqY6HVjT1aq2PzkFdcSvqayb92/WcNlGZd 2l65uAouEit5wRhl5PCxlEWu01QR7ugEyfga7BMdGqpsgovogGpPbiboFevxkYtNhSIU iD+TtZ+Mh+SHtI0hNnSstgg8ruJ8zrrffotY0McOjAO04SCom1HAF8TZY2Uu3Rht6mDm f26Q9FTeH1yfBWfc+MpL2swCciyQMyk3ny4nuhnJzuYrgzKTqUIZNoWx0IcuUJFxflgX Jgzjeui0hPg21ZHNQSFN+xCZxSrsjaFMnnzXr9E1wJ/x3xBdIz+8/IMLibOkqqkUcZll KWlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=RZL3TrsWEBMK3ueTWz2OT21WPEVx+VlxVM8AqVGb50g=; b=hLyN3FpXIpjYiX5LqrxxAT8Y6k5d1zz06wrQ4/WvuLwvXGcyMYLCwQ+EAC7F+Gdt44 hVd+fMvf4NB0zZv6uJ6vkrMlPGKH+8ufxE1yW4wD0Z3JpBucM7c0sTY9eAHjbIVZdeBY 3hAMeBzpacmBhsMWf6H4sHyy4+hWSl73mEMHym1G69FVsHhfJCfonrnxf0Y9BfzZUsS3 EAdrLGFUtunXpTbgrpl7PAqUAySWx/MbzaJi9BpkpMAYzea2o7J4Eyadm7v7XxMYobnm 1MwVW1elahGZ+E65dCiM8v9axPOTP3tw9R/k95gR+T0af0RdDSiXRcRhKB2IssskJKJ7 LxwQ== X-Gm-Message-State: AG10YOQbFstWVFBCzf7G9eFuShARbsVowXmc0tPJy7wxippJi4Jz86fM41uOmDV/lQJjew== X-Received: by 10.28.95.6 with SMTP id t6mr4936285wmb.59.1455028251804; Tue, 09 Feb 2016 06:30:51 -0800 (PST) Received: from localhost (port-17172.pppoe.wtnet.de. [46.59.128.173]) by smtp.gmail.com with ESMTPSA id et11sm3741890wjc.30.2016.02.09.06.30.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Feb 2016 06:30:50 -0800 (PST) From: Thierry Reding To: Bjorn Helgaas Cc: Stephen Warren , Alexandre Courbot , linux-pci@vger.kernel.org, linux-tegra@vger.kernel.org Subject: [PATCH v2 2/2] PCI: tegra: Implement ->{add, remove}_bus() callbacks Date: Tue, 9 Feb 2016 15:30:48 +0100 Message-Id: <1455028248-1950-2-git-send-email-thierry.reding@gmail.com> X-Mailer: git-send-email 2.7.1 In-Reply-To: <1455028248-1950-1-git-send-email-thierry.reding@gmail.com> References: <1455028248-1950-1-git-send-email-thierry.reding@gmail.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Thierry Reding The configuration space mapping on Tegra is somewhat special, and in order to avoid wasting virtual address space the configuration space for each bus needs to be stitched together from several blocks which form a single continuous virtual address range for accessors. Currently the configuration space is mapped upon the first access to one of its registers. However, the mapping operation may sleep under certain circumstances, so doing it from the configuration space accessors (they are protected by a spin lock) will trigger a warning. To avoid the warning, use the ->add_bus() callback to perform the mapping at enumeration time when the operation is allowed to sleep. Also add an implementation of ->remove_bus() that undoes the mapping established by the ->add_bus() callback. While it isn't currently possible to unload the module, there is work underway to remedy this, and this code will come in handy when that happens. Signed-off-by: Thierry Reding --- Changes in v2: - add ->remove_bus() callback implementation drivers/pci/host/pci-tegra.c | 54 ++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 30323114c53c..75c55265ca73 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -426,31 +426,38 @@ free: return ERR_PTR(err); } -/* - * Look up a virtual address mapping for the specified bus number. If no such - * mapping exists, try to create one. - */ -static void __iomem *tegra_pcie_bus_map(struct tegra_pcie *pcie, - unsigned int busnr) +static int tegra_pcie_add_bus(struct pci_bus *bus) { - struct tegra_pcie_bus *bus; + struct tegra_pcie *pcie = sys_to_pcie(bus->sysdata); + struct tegra_pcie_bus *b; - list_for_each_entry(bus, &pcie->buses, list) - if (bus->nr == busnr) - return (void __iomem *)bus->area->addr; + b = tegra_pcie_bus_alloc(pcie, bus->number); + if (IS_ERR(b)) + return PTR_ERR(b); - bus = tegra_pcie_bus_alloc(pcie, busnr); - if (IS_ERR(bus)) - return NULL; + list_add_tail(&b->list, &pcie->buses); - list_add_tail(&bus->list, &pcie->buses); + return 0; +} - return (void __iomem *)bus->area->addr; +static void tegra_pcie_remove_bus(struct pci_bus *child) +{ + struct tegra_pcie *pcie = sys_to_pcie(child->sysdata); + struct tegra_pcie_bus *bus, *tmp; + + list_for_each_entry_safe(bus, tmp, &pcie->buses, list) { + if (bus->nr == child->number) { + vunmap(bus->area->addr); + list_del(&bus->list); + kfree(bus); + break; + } + } } -static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus, - unsigned int devfn, - int where) +static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus, + unsigned int devfn, + int where) { struct tegra_pcie *pcie = sys_to_pcie(bus->sysdata); void __iomem *addr = NULL; @@ -466,7 +473,12 @@ static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus, } } } else { - addr = tegra_pcie_bus_map(pcie, bus->number); + struct tegra_pcie_bus *b; + + list_for_each_entry(b, &pcie->buses, list) + if (b->nr == bus->number) + addr = (void __iomem *)b->area->addr; + if (!addr) { dev_err(pcie->dev, "failed to map cfg. space for bus %u\n", @@ -481,7 +493,9 @@ static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus, } static struct pci_ops tegra_pcie_ops = { - .map_bus = tegra_pcie_conf_address, + .add_bus = tegra_pcie_add_bus, + .remove_bus = tegra_pcie_remove_bus, + .map_bus = tegra_pcie_map_bus, .read = pci_generic_config_read32, .write = pci_generic_config_write32, };