diff options
Diffstat (limited to 'drivers/pci/setup-res.c')
| -rw-r--r-- | drivers/pci/setup-res.c | 184 |
1 files changed, 72 insertions, 112 deletions
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index b492e67c3d87..e5fcadfc58b0 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -29,7 +29,8 @@ static void pci_std_update_resource(struct pci_dev *dev, int resno) u16 cmd; u32 new, check, mask; int reg; - struct resource *res = dev->resource + resno; + struct resource *res = pci_resource_n(dev, resno); + const char *res_name = pci_resource_name(dev, resno); /* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */ if (dev->is_virtfn) @@ -104,8 +105,8 @@ static void pci_std_update_resource(struct pci_dev *dev, int resno) pci_read_config_dword(dev, reg, &check); if ((new ^ check) & mask) { - pci_err(dev, "BAR %d: error updating (%#08x != %#08x)\n", - resno, new, check); + pci_err(dev, "%s: error updating (%#010x != %#010x)\n", + res_name, new, check); } if (res->flags & IORESOURCE_MEM_64) { @@ -113,8 +114,8 @@ static void pci_std_update_resource(struct pci_dev *dev, int resno) pci_write_config_dword(dev, reg + 4, new); pci_read_config_dword(dev, reg + 4, &check); if (check != new) { - pci_err(dev, "BAR %d: error updating (high %#08x != %#08x)\n", - resno, new, check); + pci_err(dev, "%s: error updating (high %#010x != %#010x)\n", + res_name, new, check); } } @@ -126,20 +127,19 @@ void pci_update_resource(struct pci_dev *dev, int resno) { if (resno <= PCI_ROM_RESOURCE) pci_std_update_resource(dev, resno); -#ifdef CONFIG_PCI_IOV - else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END) + else if (pci_resource_is_iov(resno)) pci_iov_update_resource(dev, resno); -#endif } int pci_claim_resource(struct pci_dev *dev, int resource) { struct resource *res = &dev->resource[resource]; + const char *res_name = pci_resource_name(dev, resource); struct resource *root, *conflict; if (res->flags & IORESOURCE_UNSET) { - pci_info(dev, "can't claim BAR %d %pR: no address assigned\n", - resource, res); + pci_info(dev, "%s %pR: can't claim; no address assigned\n", + res_name, res); return -EINVAL; } @@ -153,16 +153,16 @@ int pci_claim_resource(struct pci_dev *dev, int resource) root = pci_find_parent_resource(dev, res); if (!root) { - pci_info(dev, "can't claim BAR %d %pR: no compatible bridge window\n", - resource, res); + pci_info(dev, "%s %pR: can't claim; no compatible bridge window\n", + res_name, res); res->flags |= IORESOURCE_UNSET; return -EINVAL; } conflict = request_resource_conflict(root, res); if (conflict) { - pci_info(dev, "can't claim BAR %d %pR: address conflict with %s %pR\n", - resource, res, conflict->name, conflict); + pci_info(dev, "%s %pR: can't claim; address conflict with %s %pR\n", + res_name, res, conflict->name, conflict); res->flags |= IORESOURCE_UNSET; return -EBUSY; } @@ -201,6 +201,7 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, { struct resource *root, *conflict; resource_size_t fw_addr, start, end; + const char *res_name = pci_resource_name(dev, resno); fw_addr = pcibios_retrieve_fw_addr(dev, resno); if (!fw_addr) @@ -208,8 +209,7 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, start = res->start; end = res->end; - res->start = fw_addr; - res->end = res->start + size - 1; + resource_set_range(res, fw_addr, size); res->flags &= ~IORESOURCE_UNSET; root = pci_find_parent_resource(dev, res); @@ -231,12 +231,11 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, root = &iomem_resource; } - pci_info(dev, "BAR %d: trying firmware assignment %pR\n", - resno, res); + pci_info(dev, "%s: trying firmware assignment %pR\n", res_name, res); conflict = request_resource_conflict(root, res); if (conflict) { - pci_info(dev, "BAR %d: %pR conflicts with %s %pR\n", - resno, res, conflict->name, conflict); + pci_info(dev, "%s %pR: conflicts with %s %pR\n", res_name, res, + conflict->name, conflict); res->start = start; res->end = end; res->flags |= IORESOURCE_UNSET; @@ -261,7 +260,7 @@ resource_size_t __weak pcibios_align_resource(void *data, static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, int resno, resource_size_t size, resource_size_t align) { - struct resource *res = dev->resource + resno; + struct resource *res = pci_resource_n(dev, resno); resource_size_t min; int ret; @@ -324,7 +323,8 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno, int pci_assign_resource(struct pci_dev *dev, int resno) { - struct resource *res = dev->resource + resno; + struct resource *res = pci_resource_n(dev, resno); + const char *res_name = pci_resource_name(dev, resno); resource_size_t align, size; int ret; @@ -334,8 +334,8 @@ int pci_assign_resource(struct pci_dev *dev, int resno) res->flags |= IORESOURCE_UNSET; align = pci_resource_alignment(dev, res); if (!align) { - pci_info(dev, "BAR %d: can't assign %pR (bogus alignment)\n", - resno, res); + pci_info(dev, "%s %pR: can't assign; bogus alignment\n", + res_name, res); return -EINVAL; } @@ -348,18 +348,21 @@ int pci_assign_resource(struct pci_dev *dev, int resno) * working, which is better than just leaving it disabled. */ if (ret < 0) { - pci_info(dev, "BAR %d: no space for %pR\n", resno, res); + pci_info(dev, "%s %pR: can't assign; no space\n", res_name, res); ret = pci_revert_fw_address(res, dev, resno, size); } if (ret < 0) { - pci_info(dev, "BAR %d: failed to assign %pR\n", resno, res); + pci_info(dev, "%s %pR: failed to assign\n", res_name, res); return ret; } res->flags &= ~IORESOURCE_UNSET; res->flags &= ~IORESOURCE_STARTALIGN; - pci_info(dev, "BAR %d: assigned %pR\n", resno, res); + if (resno >= PCI_BRIDGE_RESOURCES && resno <= PCI_BRIDGE_RESOURCE_END) + res->flags &= ~IORESOURCE_DISABLED; + + pci_info(dev, "%s %pR: assigned\n", res_name, res); if (resno < PCI_BRIDGE_RESOURCES) pci_update_resource(dev, resno); @@ -367,10 +370,11 @@ int pci_assign_resource(struct pci_dev *dev, int resno) } EXPORT_SYMBOL(pci_assign_resource); -int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize, - resource_size_t min_align) +int pci_reassign_resource(struct pci_dev *dev, int resno, + resource_size_t addsize, resource_size_t min_align) { - struct resource *res = dev->resource + resno; + struct resource *res = pci_resource_n(dev, resno); + const char *res_name = pci_resource_name(dev, resno); unsigned long flags; resource_size_t new_size; int ret; @@ -381,137 +385,93 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz flags = res->flags; res->flags |= IORESOURCE_UNSET; if (!res->parent) { - pci_info(dev, "BAR %d: can't reassign an unassigned resource %pR\n", - resno, res); + pci_info(dev, "%s %pR: can't reassign; unassigned resource\n", + res_name, res); return -EINVAL; } - /* 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 = flags; - pci_info(dev, "BAR %d: %pR (failed to expand by %#llx)\n", - resno, res, (unsigned long long) addsize); + pci_info(dev, "%s %pR: failed to expand by %#llx\n", + res_name, res, (unsigned long long) addsize); return ret; } res->flags &= ~IORESOURCE_UNSET; res->flags &= ~IORESOURCE_STARTALIGN; - pci_info(dev, "BAR %d: reassigned %pR (expanded by %#llx)\n", - resno, res, (unsigned long long) addsize); + pci_info(dev, "%s %pR: reassigned; expanded by %#llx\n", + res_name, res, (unsigned long long) addsize); if (resno < PCI_BRIDGE_RESOURCES) pci_update_resource(dev, resno); return 0; } -void pci_release_resource(struct pci_dev *dev, int resno) +int pci_release_resource(struct pci_dev *dev, int resno) { - struct resource *res = dev->resource + resno; - - pci_info(dev, "BAR %d: releasing %pR\n", resno, res); + struct resource *res = pci_resource_n(dev, resno); + const char *res_name = pci_resource_name(dev, resno); + int ret; if (!res->parent) - return; - - release_resource(res); - res->end = resource_size(res) - 1; - res->start = 0; - res->flags |= IORESOURCE_UNSET; -} -EXPORT_SYMBOL(pci_release_resource); - -int pci_resize_resource(struct pci_dev *dev, int resno, int size) -{ - struct resource *res = dev->resource + resno; - struct pci_host_bridge *host; - int old, ret; - u32 sizes; - u16 cmd; - - /* Check if we must preserve the firmware's resource assignment */ - host = pci_find_host_bridge(dev->bus); - if (host->preserve_config) - return -ENOTSUPP; - - /* Make sure the resource isn't assigned before resizing it. */ - if (!(res->flags & IORESOURCE_UNSET)) - return -EBUSY; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - if (cmd & PCI_COMMAND_MEMORY) - return -EBUSY; - - sizes = pci_rebar_get_possible_sizes(dev, resno); - if (!sizes) - return -ENOTSUPP; - - if (!(sizes & BIT(size))) - return -EINVAL; + return 0; - old = pci_rebar_get_current_size(dev, resno); - if (old < 0) - return old; + pci_info(dev, "%s %pR: releasing\n", res_name, res); - ret = pci_rebar_set_size(dev, resno, size); + ret = release_resource(res); if (ret) return ret; + res->end = resource_size(res) - 1; + res->start = 0; + res->flags |= IORESOURCE_UNSET; - res->end = res->start + pci_rebar_size_to_bytes(size) - 1; - - /* Check if the new config works by trying to assign everything. */ - if (dev->bus->self) { - ret = pci_reassign_bridge_resources(dev->bus->self, res->flags); - if (ret) - goto error_resize; - } return 0; - -error_resize: - pci_rebar_set_size(dev, resno, old); - res->end = res->start + pci_rebar_size_to_bytes(old) - 1; - return ret; } -EXPORT_SYMBOL(pci_resize_resource); +EXPORT_SYMBOL(pci_release_resource); int pci_enable_resources(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; int i; struct resource *r; + const char *r_name; pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { + pci_dev_for_each_resource(dev, r, i) { if (!(mask & (1 << i))) continue; - r = &dev->resource[i]; + r_name = pci_resource_name(dev, i); if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM))) continue; - if ((i == PCI_ROM_RESOURCE) && - (!(r->flags & IORESOURCE_ROM_ENABLE))) + if (pci_resource_is_optional(dev, i)) continue; - if (r->flags & IORESOURCE_UNSET) { - pci_err(dev, "can't enable device: BAR %d %pR not assigned\n", - i, r); - return -EINVAL; + if (i < PCI_BRIDGE_RESOURCES) { + if (r->flags & IORESOURCE_UNSET) { + pci_err(dev, "%s %pR: not assigned; can't enable device\n", + r_name, r); + return -EINVAL; + } + + if (!r->parent) { + pci_err(dev, "%s %pR: not claimed; can't enable device\n", + r_name, r); + return -EINVAL; + } } - if (!r->parent) { - pci_err(dev, "can't enable device: BAR %d %pR not claimed\n", - i, r); - return -EINVAL; + if (r->parent) { + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; } - - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; } if (cmd != old_cmd) { |
