From patchwork Mon Nov 17 10:21:42 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: wangyijing X-Patchwork-Id: 40895 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wg0-f70.google.com (mail-wg0-f70.google.com [74.125.82.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 9EC8D24035 for ; Mon, 17 Nov 2014 09:44:37 +0000 (UTC) Received: by mail-wg0-f70.google.com with SMTP id x13sf11088517wgg.9 for ; Mon, 17 Nov 2014 01:44:36 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe:content-type; bh=lOr2QyCSyfgZ8ajttxn7FaKUcgsfRbvqskYHuyee5Aw=; b=cGnE6DP0jsOrWVhfnwaqmIeG2ddLrmwxuu/phq8F48h+dvOwJwH5WejeQ4pXo/9pqE qLGdRi9d2FNg+xkW6k+wQMhyY2PF4UW5RwVubfS3nr0s3l+YthYpzM1n/JBSM2Cvg62O LDeAft6ztdLuFZV547utuWlJwNgDhsqBQu2bTzpxPsJSXKJ7KBiRRHwsu7aW8yI5KeZn QINfljZc68QbXSZQJ0CpdMojhsJIATHOR5+2rYdCnBfO01ys8cqf4pVRG3Uf+XUOvYv9 cAo1S51nI5I0kWn3gvey3c0C4HFJK4jx2u5T4fEDb4gkaN5U+CnqLycZCnLx4jF2q16j h7vQ== X-Gm-Message-State: ALoCoQmHJbqW3NDjeD9wkF7XS+wdXjXcfGcqBFELRCcXYEP7DJtR1K4fsRSOCRQFrPBpA9MaLDqP X-Received: by 10.112.50.243 with SMTP id f19mr2638817lbo.1.1416217476252; Mon, 17 Nov 2014 01:44:36 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.26.228 with SMTP id o4ls1037907lag.66.gmail; Mon, 17 Nov 2014 01:44:36 -0800 (PST) X-Received: by 10.152.27.38 with SMTP id q6mr8716790lag.92.1416217476047; Mon, 17 Nov 2014 01:44:36 -0800 (PST) Received: from mail-lb0-f174.google.com (mail-lb0-f174.google.com. [209.85.217.174]) by mx.google.com with ESMTPS id b9si25708225lah.61.2014.11.17.01.44.35 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 17 Nov 2014 01:44:35 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.174 as permitted sender) client-ip=209.85.217.174; Received: by mail-lb0-f174.google.com with SMTP id w7so6982477lbi.19 for ; Mon, 17 Nov 2014 01:44:35 -0800 (PST) X-Received: by 10.112.138.137 with SMTP id qq9mr8748785lbb.80.1416217475616; Mon, 17 Nov 2014 01:44:35 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.184.201 with SMTP id ew9csp1127454lbc; Mon, 17 Nov 2014 01:44:34 -0800 (PST) X-Received: by 10.66.182.200 with SMTP id eg8mr28582985pac.53.1416217473834; Mon, 17 Nov 2014 01:44:33 -0800 (PST) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id bb10si34640379pbd.144.2014.11.17.01.44.33 for ; Mon, 17 Nov 2014 01:44:33 -0800 (PST) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752532AbaKQJnp (ORCPT + 26 others); Mon, 17 Nov 2014 04:43:45 -0500 Received: from szxga01-in.huawei.com ([119.145.14.64]:43150 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751626AbaKQJkw (ORCPT ); Mon, 17 Nov 2014 04:40:52 -0500 Received: from 172.24.2.119 (EHLO szxeml462-hub.china.huawei.com) ([172.24.2.119]) by szxrg01-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id CEO10151; Mon, 17 Nov 2014 17:40:46 +0800 (CST) Received: from localhost.localdomain (10.175.100.166) by szxeml462-hub.china.huawei.com (10.82.67.205) with Microsoft SMTP Server id 14.3.158.1; Mon, 17 Nov 2014 17:40:34 +0800 From: Yijing Wang To: Bjorn Helgaas CC: , , Xinwei Hu , Wuyun , , Russell King , , Thomas Gleixner , Benjamin Herrenschmidt , , Tony Luck , , Thierry Reding , Liviu Dudau , , Yijing Wang , Yijing Wang Subject: [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info Date: Mon, 17 Nov 2014 18:21:42 +0800 Message-ID: <1416219710-26088-9-git-send-email-wangyijing@huawei.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com> References: <1416219710-26088-1-git-send-email-wangyijing@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.175.100.166] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: wangyijing@huawei.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.174 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Yijing Wang Now pci_host_bridge has been ripped out from pci root bus creation. Currently pci_scan_root_bus() lacks scalability, so platform host drivers have no proper way to configure pci_host_bridge. E.g we should assign msi_controller to pci_host_bridge, add argument for pci_scan_root_bus() is not a good idea, it has already five, so introudce struct pci_host_info to make pci scan interfaces more scalable. Because almost all host drivers need to configure host resources, so we put .init_res() in it first, and add other hooks when need. Signed-off-by: Yijing Wang --- drivers/pci/host-bridge.c | 27 +++++++++------- drivers/pci/probe.c | 73 ++++++++++++++++++++++++++++++++++++++++++-- include/linux/pci.h | 20 ++++++++++++- 3 files changed, 103 insertions(+), 17 deletions(-) diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c index e31604f..49b6c21 100644 --- a/drivers/pci/host-bridge.c +++ b/drivers/pci/host-bridge.c @@ -8,9 +8,6 @@ #include "pci.h" -LIST_HEAD(pci_host_bridge_list); -DECLARE_RWSEM(pci_host_bridge_sem); - static struct resource busn_resource = { .name = "PCI busn", .start = 0, @@ -18,6 +15,9 @@ static struct resource busn_resource = { .flags = IORESOURCE_BUS, }; +LIST_HEAD(pci_host_bridge_list); +DECLARE_RWSEM(pci_host_bridge_sem); + static void pci_release_host_bridge_dev(struct device *dev) { struct pci_host_bridge *bridge = to_pci_host_bridge(dev); @@ -29,14 +29,12 @@ static void pci_release_host_bridge_dev(struct device *dev) } struct pci_host_bridge *pci_create_host_bridge( - struct device *parent, u32 db, - struct pci_ops *ops, void *sysdata, - struct list_head *resources) + struct device *parent, u32 db, struct pci_ops *ops, + struct pci_host_info *info) { int error; struct pci_bus *b; struct pci_host_bridge *host, *h; - struct pci_host_bridge_window *window, *n; down_read(&pci_host_bridge_sem); list_for_each_entry(h, &pci_host_bridge_list, list) { @@ -53,7 +51,7 @@ struct pci_host_bridge *pci_create_host_bridge( if (!host) return NULL; - host->sysdata = sysdata; + host->sysdata = info->arg; host->busnum = PCI_BUSNUM(db); host->domain = PCI_DOMAIN(db); host->ops = ops; @@ -63,18 +61,23 @@ struct pci_host_bridge *pci_create_host_bridge( /* this is hack, just for build, will be removed later*/ b = kzalloc(sizeof(*b), GFP_KERNEL); - b->sysdata = sysdata; + b->sysdata = host->sysdata; pci_bus_assign_domain_nr(b, parent); host->domain = pci_domain_nr(b); + kfree(b); - if (!resources) { + if (info->res_type == PCI_HOST_RES_DEFAULT) { /* Use default IO/MEM/BUS resources*/ pci_add_resource(&host->windows, &ioport_resource); pci_add_resource(&host->windows, &iomem_resource); pci_add_resource(&host->windows, &busn_resource); } else { - list_for_each_entry_safe(window, n, resources, list) - list_move_tail(&window->list, &host->windows); + if (!info->init_res || info->init_res(host, info)) { + pr_err("pci host %04x:%02x init resources fail\n", + host->domain, host->busnum); + kfree(host); + return NULL; + } } dev_set_name(&host->dev, "pci%04x:%02x", host->domain, diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index d472da4..42158fd 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1863,6 +1863,21 @@ void __weak pcibios_remove_bus(struct pci_bus *bus) { } +static int pci_default_init_res(struct pci_host_bridge *host, + struct pci_host_info *info) +{ + struct pci_host_bridge_window *window, *n; + + if (info->res_type != PCI_HOST_RES_DEFAULT) + list_for_each_entry_safe(window, n, info->resources, + list) + list_move_tail(&window->list, &host->windows); + else + info->res_type = PCI_HOST_RES_DEFAULT; + + return 0; +} + struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge) { int error; @@ -1949,13 +1964,17 @@ err_out: return NULL; } -struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus, +struct pci_bus *pci_create_root_bus(struct device *parent, u32 db, struct pci_ops *ops, void *sysdata, struct list_head *resources) { struct pci_host_bridge *host; + struct pci_host_info info; + + info.arg= sysdata; + info.resources = resources; + info.init_res = pci_default_init_res; - host = pci_create_host_bridge(parent, bus, ops, - sysdata ,resources); + host = pci_create_host_bridge(parent, db, ops, &info); if (!host) return NULL; @@ -2038,8 +2057,13 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db, bool found = false; struct pci_host_bridge *host; int max; + struct pci_host_info info; + + info.arg = sysdata; + info.resources = resources; + info.init_res = pci_default_init_res; - host = pci_create_host_bridge(parent, db, ops, sysdata, resources); + host = pci_create_host_bridge(parent, db, ops, &info); if (!host) return NULL; @@ -2070,6 +2094,47 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db, } EXPORT_SYMBOL(pci_scan_root_bus); +struct pci_host_bridge *pci_scan_host_bridge( + struct device *parent, u32 db, struct pci_ops *ops, + struct pci_host_info *info) +{ + struct pci_host_bridge_window *window; + bool found = false; + struct pci_host_bridge *host; + int max; + + host = pci_create_host_bridge(parent, db, ops, info); + if (!host) + return NULL; + + list_for_each_entry(window, &host->windows, list) + if (window->res->flags & IORESOURCE_BUS) { + found = true; + break; + } + + host->bus = __pci_create_root_bus(host); + if (!host->bus) { + pci_free_host_bridge(host); + return NULL; + } + + if (!found) { + dev_info(&host->bus->dev, + "No busn resource found for root bus, will use [bus %02x-ff]\n", + host->busnum); + pci_bus_insert_busn_res(host->bus, host->busnum, 255); + } + + max = pci_scan_child_bus(host->bus); + if (!found) + pci_bus_update_busn_res_end(host->bus, max); + + return host; + +} +EXPORT_SYMBOL(pci_scan_host_bridge); + /** * pci_rescan_bus_bridge_resize - scan a PCI bus for devices. * @bridge: PCI bridge for the bus to scan diff --git a/include/linux/pci.h b/include/linux/pci.h index daa7f40..a51f5f5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -412,6 +412,21 @@ struct pci_host_bridge { void *release_data; }; +struct pci_host_info { + u8 res_type; + void *arg; + struct list_head *resources; /*just for build, will clean up later */ + int (*init_res)(struct pci_host_bridge *host, + struct pci_host_info *info); +}; + +static inline void init_pci_host_info(struct pci_host_info *info) +{ + memset(info, 0 , sizeof(*info)); +} + +#define PCI_HOST_RES_DEFAULT 0x2 + #define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev) void pci_set_host_bridge_release(struct pci_host_bridge *bridge, void (*release_fn)(struct pci_host_bridge *), @@ -420,7 +435,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge, int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge); struct pci_host_bridge *pci_create_host_bridge( struct device *parent, u32 db, struct pci_ops *ops, - void *sys, struct list_head *resources); + struct pci_host_info *info); /* * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond * to P2P or CardBus bridge windows) go in a table. Additional ones (for @@ -785,6 +800,9 @@ void pci_bus_release_busn_res(struct pci_bus *b); struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus, struct pci_ops *ops, void *sysdata, struct list_head *resources); +struct pci_host_bridge *pci_scan_host_bridge(struct device *parent, + u32 db, struct pci_ops *ops, + struct pci_host_info *info); struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr); void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);