From c33377082dd9ede1e998f7ce416077e4b1c2276c Mon Sep 17 00:00:00 2001 From: Guo Chao Date: Thu, 3 Jul 2014 18:30:29 -0600 Subject: PCI: Keep original resource if we fail to expand it If we have space assigned to a resource, we try to expand the resource (e.g., to accommodate SR-IOV resources), and the expansion attempt fails, we should keep the original assignment. After bd064f0a231a ("PCI: Mark resources as IORESOURCE_UNSET if we can't assign them"), we left the resource marked IORESOURCE_UNSET when the expansion failed, even if it had originally been set. That caused errors like this: pci 0003:00:00.0: can't enable device: BAR 15 [mem size 0x0c000000 64bit pref] not assigned pci 0003:00:00.0: Error enabling bridge (-22), continuing Fix this by restoring the original flags when reassignment fails. [bhelgaas: reworked to simplify, changelog] Fixes: bd064f0a231a ("PCI: Mark resources as IORESOURCE_UNSET if we can't assign them") Signed-off-by: Guo Chao Signed-off-by: Bjorn Helgaas CC: stable@vger.kernel.org # v3.15+ --- drivers/pci/setup-res.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/pci/setup-res.c') diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index caed1ce6fac..481c4e18693 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -320,9 +320,11 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz resource_size_t min_align) { struct resource *res = dev->resource + resno; + unsigned long flags; resource_size_t new_size; int ret; + flags = res->flags; res->flags |= IORESOURCE_UNSET; if (!res->parent) { dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR\n", @@ -339,7 +341,12 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res); if (resno < PCI_BRIDGE_RESOURCES) pci_update_resource(dev, resno); + } else { + res->flags = flags; + dev_info(&dev->dev, "BAR %d: %pR (failed to expand by %#llx)\n", + resno, res, (unsigned long long) addsize); } + return ret; } -- cgit v1.2.3-70-g09d2 From 28f6dbe2c669c6a02c04c8ece21cafbcb20370ab Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 4 Jul 2014 15:58:15 -0600 Subject: PCI: Cleanup control flow Return errors immediately so the straightline path is the normal, no-error path. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-res.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/pci/setup-res.c') diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 481c4e18693..532dc540dc5 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -305,14 +305,16 @@ int pci_assign_resource(struct pci_dev *dev, int resno) if (ret < 0) ret = pci_revert_fw_address(res, dev, resno, size); - if (!ret) { - res->flags &= ~IORESOURCE_UNSET; - res->flags &= ~IORESOURCE_STARTALIGN; - dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); - if (resno < PCI_BRIDGE_RESOURCES) - pci_update_resource(dev, resno); - } - return ret; + if (ret) + return ret; + + res->flags &= ~IORESOURCE_UNSET; + res->flags &= ~IORESOURCE_STARTALIGN; + dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); + if (resno < PCI_BRIDGE_RESOURCES) + pci_update_resource(dev, resno); + + return 0; } EXPORT_SYMBOL(pci_assign_resource); @@ -335,19 +337,20 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz /* already aligned with min_align */ new_size = resource_size(res) + addsize; ret = _pci_assign_resource(dev, resno, new_size, min_align); - if (!ret) { - res->flags &= ~IORESOURCE_UNSET; - res->flags &= ~IORESOURCE_STARTALIGN; - dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res); - if (resno < PCI_BRIDGE_RESOURCES) - pci_update_resource(dev, resno); - } else { + if (ret) { res->flags = flags; dev_info(&dev->dev, "BAR %d: %pR (failed to expand by %#llx)\n", resno, res, (unsigned long long) addsize); + return ret; } - return ret; + res->flags &= ~IORESOURCE_UNSET; + res->flags &= ~IORESOURCE_STARTALIGN; + dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res); + if (resno < PCI_BRIDGE_RESOURCES) + pci_update_resource(dev, resno); + + return 0; } int pci_enable_resources(struct pci_dev *dev, int mask) -- cgit v1.2.3-70-g09d2 From 947788359527d9598356c274c50522e0f6d0ad0f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 8 Jul 2014 16:00:42 -0600 Subject: PCI: Return conventional error values from pci_revert_fw_address() Previously we returned zero for success or 1 for failure. This changes that so we return zero for success or a negative errno for failure. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-res.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/pci/setup-res.c') diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 532dc540dc5..74eb6febdf8 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -166,11 +166,10 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, { struct resource *root, *conflict; resource_size_t fw_addr, start, end; - int ret = 0; fw_addr = pcibios_retrieve_fw_addr(dev, resno); if (!fw_addr) - return 1; + return -ENOMEM; start = res->start; end = res->end; @@ -189,14 +188,13 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, resno, res); conflict = request_resource_conflict(root, res); if (conflict) { - dev_info(&dev->dev, - "BAR %d: %pR conflicts with %s %pR\n", resno, - res, conflict->name, conflict); + dev_info(&dev->dev, "BAR %d: %pR conflicts with %s %pR\n", + resno, res, conflict->name, conflict); res->start = start; res->end = end; - ret = 1; + return -EBUSY; } - return ret; + return 0; } static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, @@ -305,7 +303,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno) if (ret < 0) ret = pci_revert_fw_address(res, dev, resno, size); - if (ret) + if (ret < 0) return ret; res->flags &= ~IORESOURCE_UNSET; -- cgit v1.2.3-70-g09d2 From 64da465e9841f93183744a9dadf992f938ac3910 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 8 Jul 2014 16:04:22 -0600 Subject: PCI: Tidy resource assignment messages Print messages about failures in pci_assign_resource(). We can drop the "by-hand" message from _pci_assign_resource() because %pR now prints the size rather than the address if the resource hasn't been assigned. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-res.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'drivers/pci/setup-res.c') diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 74eb6febdf8..b7c3a5ea1fc 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -248,10 +248,8 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, static int _pci_assign_resource(struct pci_dev *dev, int resno, resource_size_t size, resource_size_t min_align) { - struct resource *res = dev->resource + resno; struct pci_bus *bus; int ret; - char *type; bus = dev->bus; while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) { @@ -260,21 +258,6 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno, bus = bus->parent; } - if (ret) { - if (res->flags & IORESOURCE_MEM) - if (res->flags & IORESOURCE_PREFETCH) - type = "mem pref"; - else - type = "mem"; - else if (res->flags & IORESOURCE_IO) - type = "io"; - else - type = "unknown"; - dev_info(&dev->dev, - "BAR %d: can't assign %s (size %#llx)\n", - resno, type, (unsigned long long) resource_size(res)); - } - return ret; } @@ -300,11 +283,16 @@ int pci_assign_resource(struct pci_dev *dev, int resno) * where firmware left it. That at least has a chance of * working, which is better than just leaving it disabled. */ - if (ret < 0) + if (ret < 0) { + dev_info(&dev->dev, "BAR %d: no space for %pR\n", resno, res); ret = pci_revert_fw_address(res, dev, resno, size); + } - if (ret < 0) + if (ret < 0) { + dev_info(&dev->dev, "BAR %d: failed to assign %pR\n", resno, + res); return ret; + } res->flags &= ~IORESOURCE_UNSET; res->flags &= ~IORESOURCE_STARTALIGN; @@ -344,7 +332,8 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz res->flags &= ~IORESOURCE_UNSET; res->flags &= ~IORESOURCE_STARTALIGN; - dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res); + dev_info(&dev->dev, "BAR %d: reassigned %pR (expanded by %#llx)\n", + resno, res, (unsigned long long) addsize); if (resno < PCI_BRIDGE_RESOURCES) pci_update_resource(dev, resno); -- cgit v1.2.3-70-g09d2