From patchwork Wed Jan 7 15:29:30 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 5585211 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id A69A99F665 for ; Wed, 7 Jan 2015 15:29:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B253F2026F for ; Wed, 7 Jan 2015 15:29:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C1CD0201FB for ; Wed, 7 Jan 2015 15:29:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752597AbbAGP3v (ORCPT ); Wed, 7 Jan 2015 10:29:51 -0500 Received: from foss-mx-na.foss.arm.com ([217.140.108.86]:56822 "EHLO foss-mx-na.foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752443AbbAGP3v (ORCPT ); Wed, 7 Jan 2015 10:29:51 -0500 Received: from foss-smtp-na-1.foss.arm.com (unknown [10.80.61.8]) by foss-mx-na.foss.arm.com (Postfix) with ESMTP id D55FA23C; Wed, 7 Jan 2015 09:29:46 -0600 (CST) Received: from collaborate-mta1.arm.com (highbank-bc01-b06.austin.arm.com [10.112.81.134]) by foss-smtp-na-1.foss.arm.com (Postfix) with ESMTP id 412556045D; Wed, 7 Jan 2015 09:29:44 -0600 (CST) Received: from red-moon.cambridge.arm.com (red-moon.cambridge.arm.com [10.1.203.137]) by collaborate-mta1.arm.com (Postfix) with ESMTP id E0A4613F78C; Wed, 7 Jan 2015 09:29:42 -0600 (CST) From: Lorenzo Pieralisi To: linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org Cc: Lorenzo Pieralisi , Arnd Bergmann , Liviu Dudau , Mohit Kumar , Jingoo Han , Bjorn Helgaas , Rob Herring Subject: [RFC PATCH 2/3] drivers: of: of_pci_get_host_bridge_resources() range parsing update Date: Wed, 7 Jan 2015 15:29:30 +0000 Message-Id: <1420644571-18928-3-git-send-email-lorenzo.pieralisi@arm.com> X-Mailer: git-send-email 2.2.1 In-Reply-To: <1420644571-18928-1-git-send-email-lorenzo.pieralisi@arm.com> References: <1420644571-18928-1-git-send-email-lorenzo.pieralisi@arm.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some host controllers require local bus physical addresses to programme inbound/outbound requests from the bus hierarchy to be routed properly through the PCI bus beyond the host controller. Owing to bus address size conversion, the bus local addresses may be different from the addresses as seen from the CPU (which are translated by DT core code), so the PCI range parsing function: of_pci_get_host_bridge_resources() should be augmented in order to store the range parser along with the parsed resource so that the CPU untranslated address can be retrieved by the driver from the corresponding PCI range if needed. Cc: Arnd Bergmann Cc: Liviu Dudau Cc: Bjorn Helgaas Cc: Rob Herring Signed-off-by: Lorenzo Pieralisi --- drivers/of/of_pci.c | 38 +++++++++++++++++++++++++++++--------- include/linux/of_address.h | 5 +++++ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c index 6fbfe99..f0e576f 100644 --- a/drivers/of/of_pci.c +++ b/drivers/of/of_pci.c @@ -144,6 +144,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev, struct resource *bus_range; struct of_pci_range range; struct of_pci_range_parser parser; + struct of_pci_resource *of_pci_res; char range_type[4]; int err; struct pci_host_bridge_window *window; @@ -151,12 +152,14 @@ int of_pci_get_host_bridge_resources(struct device_node *dev, if (io_base) *io_base = (resource_size_t)OF_BAD_ADDR; - bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL); - if (!bus_range) + of_pci_res = kzalloc(sizeof(*of_pci_res), GFP_KERNEL); + if (!of_pci_res) return -ENOMEM; pr_info("PCI host bridge %s ranges:\n", dev->full_name); + bus_range = &of_pci_res->res; + err = of_pci_parse_bus_range(dev, bus_range); if (err) { bus_range->start = busno; @@ -195,17 +198,29 @@ int of_pci_get_host_bridge_resources(struct device_node *dev, if (range.cpu_addr == OF_BAD_ADDR || range.size == 0) continue; - res = kzalloc(sizeof(struct resource), GFP_KERNEL); - if (!res) { + of_pci_res = kzalloc(sizeof(*of_pci_res), GFP_KERNEL); + if (!of_pci_res) { err = -ENOMEM; goto parse_failed; } + res = &of_pci_res->res; err = of_pci_range_to_resource(&range, dev, res); if (err) goto conversion_failed; - if (resource_type(res) == IORESOURCE_IO) { + /* Stash the range parser */ + of_pci_res->parser = parser; + /* + * for_each_of_pci_range increments the range pointer + * in the parser, so that it is ready to parse the + * following range while looping; rewind the range pointer + * to its current value to pass it to the drivers with its + * initial value. + */ + of_pci_res->parser.range -= parser.np; + + if (resource_type(res) == IORESOURCE_IO) { if (!io_base) { pr_err("I/O range found for %s. Please provide an io_base pointer to save CPU base address\n", dev->full_name); @@ -224,12 +239,17 @@ int of_pci_get_host_bridge_resources(struct device_node *dev, return 0; conversion_failed: - kfree(res); + kfree(of_pci_res); parse_failed: - list_for_each_entry(window, resources, list) - kfree(window->res); + list_for_each_entry(window, resources, list) { + of_pci_res = container_of(window->res, struct of_pci_resource, + res); + kfree(of_pci_res); + } pci_free_resource_list(resources); - kfree(bus_range); + of_pci_res = container_of(bus_range, struct of_pci_resource, + res); + kfree(of_pci_res); return err; } EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources); diff --git a/include/linux/of_address.h b/include/linux/of_address.h index d88e81b..e4005be 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -20,6 +20,11 @@ struct of_pci_range { u32 flags; }; +struct of_pci_resource { + struct resource res; + struct of_pci_range_parser parser; +}; + #define for_each_of_pci_range(parser, range) \ for (; of_pci_range_parser_one(parser, range);)