From patchwork Sat Jul 12 01:22:08 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yinghai Lu X-Patchwork-Id: 4538541 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id D5325C0514 for ; Sat, 12 Jul 2014 01:22:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 497BB20274 for ; Sat, 12 Jul 2014 01:22:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 796AA2025B for ; Sat, 12 Jul 2014 01:22:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753548AbaGLBWK (ORCPT ); Fri, 11 Jul 2014 21:22:10 -0400 Received: from mail-ig0-f171.google.com ([209.85.213.171]:49055 "EHLO mail-ig0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753170AbaGLBWJ (ORCPT ); Fri, 11 Jul 2014 21:22:09 -0400 Received: by mail-ig0-f171.google.com with SMTP id l13so59973iga.4 for ; Fri, 11 Jul 2014 18:22:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; bh=snRGuitEFVFz6gkyPaAQj+O/9OKETuL/ipT/ZrvLRN8=; b=sk9t/c91kJ3rEMmqFp/0KpJNIm2U3875OobPy/xeeiWcex3dBnJPP3jr22hcb5KFJp gS9Yi5KfecTbmJuRCMH8Vup//vrt51cw/37YETKUthc1yR2nM6av9qfgDbHirtxuAgMc SsEDxdvjDToJ20317ygw/k66vvuVlhwr6cNMlTAvmI2CdgpMq83GlGwMcQutoBe3E711 m7H5u5eWR9R0U6Tx7bHy/Ya/pD4nk1PhF+27ErgTYrz64KyZ1VCIgX4OSzfc1Lmwhca7 BSLxue5z/ifvLiB5q7JpP9n/AZrFxaCGmB2C+JAbwwGA9vHavB7MzPtuziOH4cAXJ5V7 aPSg== MIME-Version: 1.0 X-Received: by 10.42.93.84 with SMTP id w20mr8316055icm.49.1405128128358; Fri, 11 Jul 2014 18:22:08 -0700 (PDT) Received: by 10.64.251.73 with HTTP; Fri, 11 Jul 2014 18:22:08 -0700 (PDT) In-Reply-To: References: <20140611060118.GB3169@yanx> <20140702210736.GB28852@google.com> <20140703131526.GG28852@google.com> <20140703221152.GH28852@google.com> Date: Fri, 11 Jul 2014 18:22:08 -0700 X-Google-Sender-Auth: s1olBKJlLQN_lJikBfwdPdgxjzM Message-ID: Subject: Re: [PATCH] pci: Allow very large resource windows From: Yinghai Lu To: Bjorn Helgaas Cc: Linus Torvalds , Greg Kroah-Hartman , Guo Chao , "linux-pci@vger.kernel.org" Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,T_TVD_MIME_EPI, 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 On Fri, Jul 11, 2014 at 11:40 AM, Bjorn Helgaas wrote: > On Fri, Jul 11, 2014 at 12:21 PM, Linus Torvalds > wrote: >> On Fri, Jul 11, 2014 at 11:09 AM, Yinghai Lu wrote: >>> >>> If the BAR have all 0, cpu can not access it as hw will forward access to ram >>> controller according to routing table. >> >> On PC's, yes (also likely with many devices - there are definitely >> devices out there were setting the BAR to zero disables it). > > Ooh, we might trip over this some day on a platform with host bridge > address translation that maps to PCI bus address 0. I don't think we > have anything in the allocator that avoids bus address 0 in that case. Anyway, I draft RFC one that replace flags = 0 with flags |= IORESOURCE_UNSET | IORESOURCE_DISABLEd. Let's see how many drivers will fail. Yinghai Subject: [RFC PATCH] PCI: don't set flags to 0 when assign resource fail make flags take IORESOURCE_UNSET | IORESOURCE_DISABLE instead. Signed-off-by: Yinghai Lu --- drivers/pci/setup-bus.c | 49 ++++++++++++++++++++++++------------------------ drivers/pci/setup-res.c | 11 ++++++++++ 2 files changed, 36 insertions(+), 24 deletions(-) Index: linux-2.6/drivers/pci/setup-bus.c =================================================================== --- linux-2.6.orig/drivers/pci/setup-bus.c +++ linux-2.6/drivers/pci/setup-bus.c @@ -136,7 +136,8 @@ static void pdev_sort_resources(struct p if (r->flags & IORESOURCE_PCI_FIXED) continue; - if (!(r->flags) || r->parent) + if (!(r->flags) || r->parent || + (r->flags & IORESOURCE_DISABLED)) continue; r_align = pci_resource_alignment(dev, r); @@ -190,13 +191,6 @@ static void __dev_sort_resources(struct pdev_sort_resources(dev, head); } -static inline void reset_resource(struct resource *res) -{ - res->start = 0; - res->end = 0; - res->flags = 0; -} - /** * reassign_resources_sorted() - satisfy any additional resource requests * @@ -242,7 +236,7 @@ static void reassign_resources_sorted(st res->start = add_res->start; res->end = res->start + add_size - 1; if (pci_assign_resource(add_res->dev, idx)) - reset_resource(res); + res->flags |= IORESOURCE_DISABLED; } else { resource_size_t align = add_res->min_align; res->flags |= add_res->flags & @@ -294,7 +288,7 @@ static void assign_requested_resources_s 0 /* don't care */, 0 /* don't care */); } - reset_resource(res); + res->flags |= IORESOURCE_DISABLED; } } } @@ -547,7 +541,7 @@ static void pci_setup_bridge_io(struct p /* Set up the top and bottom of the PCI I/O segment for this bus. */ res = bus->resource[0]; pcibios_resource_to_bus(bridge->bus, ®ion, res); - if (res->flags & IORESOURCE_IO) { + if ((res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_UNSET)) { pci_read_config_word(bridge, PCI_IO_BASE, &l); io_base_lo = (region.start >> 8) & io_mask; io_limit_lo = (region.end >> 8) & io_mask; @@ -578,7 +572,8 @@ static void pci_setup_bridge_mmio(struct /* Set up the top and bottom of the PCI Memory segment for this bus. */ res = bus->resource[1]; pcibios_resource_to_bus(bridge->bus, ®ion, res); - if (res->flags & IORESOURCE_MEM) { + if ((res->flags & IORESOURCE_MEM) && + !(res->flags & IORESOURCE_UNSET)) { l = (region.start >> 16) & 0xfff0; l |= region.end & 0xfff00000; dev_info(&bridge->dev, " bridge window %pR\n", res); @@ -604,7 +599,8 @@ static void pci_setup_bridge_mmio_pref(s bu = lu = 0; res = bus->resource[2]; pcibios_resource_to_bus(bridge->bus, ®ion, res); - if (res->flags & IORESOURCE_PREFETCH) { + if ((res->flags & IORESOURCE_PREFETCH) && + !(res->flags & IORESOURCE_UNSET)) { l = (region.start >> 16) & 0xfff0; l |= region.end & 0xfff00000; if (res->flags & IORESOURCE_MEM_64) { @@ -661,6 +657,7 @@ static void pci_bridge_check_ranges(stru b_res = &bridge->resource[PCI_BRIDGE_RESOURCES]; b_res[1].flags |= IORESOURCE_MEM; + b_res[1].flags &= ~IORESOURCE_DISABLED; pci_read_config_word(bridge, PCI_IO_BASE, &io); if (!io) { @@ -668,8 +665,10 @@ static void pci_bridge_check_ranges(stru pci_read_config_word(bridge, PCI_IO_BASE, &io); pci_write_config_word(bridge, PCI_IO_BASE, 0x0); } - if (io) + if (io) { b_res[0].flags |= IORESOURCE_IO; + b_res[0].flags &= ~IORESOURCE_DISABLED; + } /* DECchip 21050 pass 2 errata: the bridge may miss an address disconnect boundary by one PCI data phase. @@ -686,6 +685,7 @@ static void pci_bridge_check_ranges(stru } if (pmem) { b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; + b_res[2].flags &= ~IORESOURCE_DISABLED; if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { b_res[2].flags |= IORESOURCE_MEM_64; @@ -830,8 +830,10 @@ static void pbus_size_io(struct pci_bus struct resource *r = &dev->resource[i]; unsigned long r_size; - if (r->parent || !(r->flags & IORESOURCE_IO)) + if (r->parent || !(r->flags & IORESOURCE_IO) || + (r->flags & IORESOURCE_DISABLED)) continue; + r_size = resource_size(r); if (r_size < 0x400) @@ -860,7 +862,7 @@ static void pbus_size_io(struct pci_bus if (b_res->start || b_res->end) dev_info(&bus->self->dev, "disabling bridge window %pR to %pR (unused)\n", b_res, &bus->busn_res); - b_res->flags = 0; + b_res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; return; } @@ -947,8 +949,10 @@ static int pbus_size_mem(struct pci_bus if (r->parent || ((r->flags & mask) != type && (r->flags & mask) != type2 && - (r->flags & mask) != type3)) + (r->flags & mask) != type3) || + (r->flags & IORESOURCE_DISABLED)) continue; + r_size = resource_size(r); #ifdef CONFIG_PCI_IOV /* put SRIOV requested res to the optional list */ @@ -973,7 +977,8 @@ static int pbus_size_mem(struct pci_bus if (order >= ARRAY_SIZE(aligns)) { dev_warn(&dev->dev, "disabling BAR %d: %pR (bad alignment %#llx)\n", i, r, (unsigned long long) align); - r->flags = 0; + r->flags |= IORESOURCE_UNSET | + IORESOURCE_DISABLED; continue; } size += r_size; @@ -1001,7 +1006,7 @@ static int pbus_size_mem(struct pci_bus if (b_res->start || b_res->end) dev_info(&bus->self->dev, "disabling bridge window %pR to %pR (unused)\n", b_res, &bus->busn_res); - b_res->flags = 0; + b_res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; return 0; } b_res->start = min_align; @@ -1367,7 +1372,7 @@ static void pci_bridge_release_resources /* keep the old size */ r->end = resource_size(r) - 1; r->start = 0; - r->flags = 0; + r->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; /* avoiding touch the one without PREF */ if (type & IORESOURCE_PREFETCH) @@ -1622,8 +1627,6 @@ again: res->start = fail_res->start; res->end = fail_res->end; res->flags = fail_res->flags; - if (fail_res->dev->subordinate) - res->flags = 0; } free_list(&fail_head); @@ -1688,8 +1691,6 @@ again: res->start = fail_res->start; res->end = fail_res->end; res->flags = fail_res->flags; - if (fail_res->dev->subordinate) - res->flags = 0; } free_list(&fail_head); Index: linux-2.6/drivers/pci/setup-res.c =================================================================== --- linux-2.6.orig/drivers/pci/setup-res.c +++ linux-2.6/drivers/pci/setup-res.c @@ -362,6 +362,17 @@ int pci_enable_resources(struct pci_dev continue; if (r->flags & IORESOURCE_UNSET) { + /* bridge BAR could be disabled one by one */ + if (dev->subordinate && i >= PCI_BRIDGE_RESOURCES && + i <= PCI_BRIDGE_RESOURCE_END) + continue; + +#ifdef CONFIG_PCI_IOV + /* SRIOV ? */ + if (i >= PCI_IOV_RESOURCES && i <= PCI_IOV_RESOURCE_END) + continue; +#endif + dev_err(&dev->dev, "can't enable device: BAR %d %pR not assigned\n", i, r); return -EINVAL;