Merge branch 'pci/resource'

- Ensure relaxed tail alignment does not increase min_align when computing
  bridge window size, to fix a regression (Ilpo Järvinen)

- Fix bridge window size computation to fix a regression for devices with
  undefined PCI class, e.g., Samsung [144d:a5a5] (Ilpo Järvinen)

- Fix error handling during resource resize to fix a regression in amdgpu
  (Ilpo Järvinen)

- Align m68k pcibios_enable_device() with other arches (Ilpo Järvinen)

- Remove several sparc pcibios_enable_device() implementations that don't
  do anything beyond what pci_enable_resources() does (Ilpo Järvinen)

- Remove mips pcibios_enable_resources() and use pci_enable_resources()
  instead (Ilpo Järvinen)

- Refactor and simplify find_bus_resource_of_type() (Ilpo Järvinen)

- Claim bridge windows before setting them up (Ilpo Järvinen)

- Disable non-claimed bridge windows so the kernel's view matches the
  hardware configuration (Ilpo Järvinen)

- Use pci_release_resource() instead of release_resource() to reduce code
  duplication and increase consistency (Ilpo Järvinen)

- Enable bridges even if bridge window assignment fails (Ilpo Järvinen)

- Preserve bridge window resource type flags when assignment fails because
  we may need it later (Ilpo Järvinen)

- Add bridge window selection functions to make the selection consistent
  across the several places that do this (Ilpo Järvinen)

- Warn if bridge window cannot be released when resizing BAR (Ilpo
  Järvinen)

- Set up bridge resources before enumerating children so we can check
  whether child resources are inside bridge windows (Ilpo Järvinen)

* pci/resource:
  PCI: Set up bridge resources earlier
  PCI: Don't print stale information about resource
  PCI: Alter misleading recursion to pci_bus_release_bridge_resources()
  PCI: Pass bridge window to pci_bus_release_bridge_resources()
  PCI: Add pci_setup_one_bridge_window()
  PCI: Refactor remove_dev_resources() to use pbus_select_window()
  PCI: Refactor distributing available memory to use loops
  PCI: Use pbus_select_window_for_type() during mem window sizing
  PCI: Use pbus_select_window() in space available checker
  PCI: Rename resource variable from r to res
  PCI: Use pbus_select_window_for_type() during IO window sizing
  PCI: Use pbus_select_window() during BAR resize
  PCI: Warn if bridge window cannot be released when resizing BAR
  PCI: Fix finding bridge window in pci_reassign_bridge_resources()
  PCI: Add bridge window selection functions
  PCI: Add defines for bridge window indexing
  PCI: Preserve bridge window resource type flags
  PCI: Enable bridge even if bridge window fails to assign
  PCI: Use pci_release_resource() instead of release_resource()
  PCI: Disable non-claimed bridge window
  PCI: Always claim bridge window before its setup
  PCI: Refactor find_bus_resource_of_type() logic checks
  PCI: Move find_bus_resource_of_type() earlier
  MIPS: PCI: Use pci_enable_resources()
  sparc/PCI: Remove pcibios_enable_device() as they do nothing extra
  m68k/PCI: Use pci_enable_resources() in pcibios_enable_device()
  PCI: Fix failure detection during resource resize
  PCI: Fix pdev_resources_assignable() disparity
  PCI: Ensure relaxed tail alignment does not increase min_align
This commit is contained in:
Bjorn Helgaas 2025-10-03 12:13:12 -05:00
commit fead6a0b15
12 changed files with 552 additions and 598 deletions

View File

@ -44,41 +44,24 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
*/ */
int pcibios_enable_device(struct pci_dev *dev, int mask) int pcibios_enable_device(struct pci_dev *dev, int mask)
{ {
struct resource *r;
u16 cmd, newcmd; u16 cmd, newcmd;
int idx; int ret;
pci_read_config_word(dev, PCI_COMMAND, &cmd); ret = pci_enable_resources(dev, mask);
newcmd = cmd; if (ret < 0)
return ret;
for (idx = 0; idx < 6; idx++) {
/* Only set up the requested stuff */
if (!(mask & (1 << idx)))
continue;
r = dev->resource + idx;
if (!r->start && r->end) {
pr_err("PCI: Device %s not available because of resource collisions\n",
pci_name(dev));
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
newcmd |= PCI_COMMAND_IO;
if (r->flags & IORESOURCE_MEM)
newcmd |= PCI_COMMAND_MEMORY;
}
/* /*
* Bridges (eg, cardbus bridges) need to be fully enabled * Bridges (eg, cardbus bridges) need to be fully enabled
*/ */
if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
pci_read_config_word(dev, PCI_COMMAND, &cmd);
newcmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY; newcmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
if (newcmd != cmd) {
pr_info("PCI: enabling bridge %s (0x%04x -> 0x%04x)\n",
if (newcmd != cmd) { pci_name(dev), cmd, newcmd);
pr_info("PCI: enabling device %s (0x%04x -> 0x%04x)\n", pci_write_config_word(dev, PCI_COMMAND, newcmd);
pci_name(dev), cmd, newcmd); }
pci_write_config_word(dev, PCI_COMMAND, newcmd);
} }
return 0; return 0;
} }

View File

@ -249,45 +249,11 @@ static int __init pcibios_init(void)
subsys_initcall(pcibios_init); subsys_initcall(pcibios_init);
static int pcibios_enable_resources(struct pci_dev *dev, int mask)
{
u16 cmd, old_cmd;
int idx;
struct resource *r;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
pci_dev_for_each_resource(dev, r, idx) {
/* Only set up the requested stuff */
if (!(mask & (1<<idx)))
continue;
if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
continue;
if ((idx == PCI_ROM_RESOURCE) &&
(!(r->flags & IORESOURCE_ROM_ENABLE)))
continue;
if (!r->start && r->end) {
pci_err(dev,
"can't enable device: resource collisions\n");
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
cmd |= PCI_COMMAND_IO;
if (r->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
if (cmd != old_cmd) {
pci_info(dev, "enabling device (%04x -> %04x)\n", old_cmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0;
}
int pcibios_enable_device(struct pci_dev *dev, int mask) int pcibios_enable_device(struct pci_dev *dev, int mask)
{ {
int err = pcibios_enable_resources(dev, mask); int err;
err = pci_enable_resources(dev, mask);
if (err < 0) if (err < 0)
return err; return err;

View File

@ -60,30 +60,3 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
pci_assign_unassigned_resources(); pci_assign_unassigned_resources();
pci_bus_add_devices(root_bus); pci_bus_add_devices(root_bus);
} }
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
struct resource *res;
u16 cmd, oldcmd;
int i;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
oldcmd = cmd;
pci_dev_for_each_resource(dev, res, i) {
/* Only set up the requested stuff */
if (!(mask & (1<<i)))
continue;
if (res->flags & IORESOURCE_IO)
cmd |= PCI_COMMAND_IO;
if (res->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
if (cmd != oldcmd) {
pci_info(dev, "enabling device (%04x -> %04x)\n", oldcmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0;
}

View File

@ -722,33 +722,6 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
return bus; return bus;
} }
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
struct resource *res;
u16 cmd, oldcmd;
int i;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
oldcmd = cmd;
pci_dev_for_each_resource(dev, res, i) {
/* Only set up the requested stuff */
if (!(mask & (1<<i)))
continue;
if (res->flags & IORESOURCE_IO)
cmd |= PCI_COMMAND_IO;
if (res->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
if (cmd != oldcmd) {
pci_info(dev, "enabling device (%04x -> %04x)\n", oldcmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0;
}
/* Platform support for /proc/bus/pci/X/Y mmap()s. */ /* Platform support for /proc/bus/pci/X/Y mmap()s. */
int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma) int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma)
{ {

View File

@ -641,33 +641,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
} }
} }
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
struct resource *res;
u16 cmd, oldcmd;
int i;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
oldcmd = cmd;
pci_dev_for_each_resource(dev, res, i) {
/* Only set up the requested stuff */
if (!(mask & (1<<i)))
continue;
if (res->flags & IORESOURCE_IO)
cmd |= PCI_COMMAND_IO;
if (res->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
if (cmd != oldcmd) {
pci_info(dev, "enabling device (%04x -> %04x)\n", oldcmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0;
}
/* Makes compiler happy */ /* Makes compiler happy */
static volatile int pcic_timer_dummy; static volatile int pcic_timer_dummy;

View File

@ -204,6 +204,9 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
if (!r) if (!r)
continue; continue;
if (r->flags & (IORESOURCE_UNSET|IORESOURCE_DISABLED))
continue;
/* type_mask must match */ /* type_mask must match */
if ((res->flags ^ r->flags) & type_mask) if ((res->flags ^ r->flags) & type_mask)
continue; continue;

View File

@ -177,6 +177,13 @@ static ssize_t resource_show(struct device *dev, struct device_attribute *attr,
for (i = 0; i < max; i++) { for (i = 0; i < max; i++) {
struct resource *res = &pci_dev->resource[i]; struct resource *res = &pci_dev->resource[i];
struct resource zerores = {};
/* For backwards compatibility */
if (i >= PCI_BRIDGE_RESOURCES && i <= PCI_BRIDGE_RESOURCE_END &&
res->flags & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
res = &zerores;
pci_resource_to_user(pci_dev, i, res, &start, &end); pci_resource_to_user(pci_dev, i, res, &start, &end);
len += sysfs_emit_at(buf, len, "0x%016llx 0x%016llx 0x%016llx\n", len += sysfs_emit_at(buf, len, "0x%016llx 0x%016llx 0x%016llx\n",
(unsigned long long)start, (unsigned long long)start,
@ -1573,13 +1580,19 @@ static ssize_t __resource_resize_store(struct device *dev, int n,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
unsigned long size, flags; struct pci_bus *bus = pdev->bus;
struct resource *b_win, *res;
unsigned long size;
int ret, i; int ret, i;
u16 cmd; u16 cmd;
if (kstrtoul(buf, 0, &size) < 0) if (kstrtoul(buf, 0, &size) < 0)
return -EINVAL; return -EINVAL;
b_win = pbus_select_window(bus, pci_resource_n(pdev, n));
if (!b_win)
return -EINVAL;
device_lock(dev); device_lock(dev);
if (dev->driver || pci_num_vf(pdev)) { if (dev->driver || pci_num_vf(pdev)) {
ret = -EBUSY; ret = -EBUSY;
@ -1599,19 +1612,19 @@ static ssize_t __resource_resize_store(struct device *dev, int n,
pci_write_config_word(pdev, PCI_COMMAND, pci_write_config_word(pdev, PCI_COMMAND,
cmd & ~PCI_COMMAND_MEMORY); cmd & ~PCI_COMMAND_MEMORY);
flags = pci_resource_flags(pdev, n);
pci_remove_resource_files(pdev); pci_remove_resource_files(pdev);
for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) { pci_dev_for_each_resource(pdev, res, i) {
if (pci_resource_len(pdev, i) && if (i >= PCI_BRIDGE_RESOURCES)
pci_resource_flags(pdev, i) == flags) break;
if (b_win == pbus_select_window(bus, res))
pci_release_resource(pdev, i); pci_release_resource(pdev, i);
} }
ret = pci_resize_resource(pdev, n, size); ret = pci_resize_resource(pdev, n, size);
pci_assign_unassigned_bus_resources(pdev->bus); pci_assign_unassigned_bus_resources(bus);
if (pci_create_resource_files(pdev)) if (pci_create_resource_files(pdev))
pci_warn(pdev, "Failed to recreate resource files after BAR resizing\n"); pci_warn(pdev, "Failed to recreate resource files after BAR resizing\n");

View File

@ -82,6 +82,10 @@ struct pcie_tlp_log;
#define PCIE_MSG_CODE_DEASSERT_INTC 0x26 #define PCIE_MSG_CODE_DEASSERT_INTC 0x26
#define PCIE_MSG_CODE_DEASSERT_INTD 0x27 #define PCIE_MSG_CODE_DEASSERT_INTD 0x27
#define PCI_BUS_BRIDGE_IO_WINDOW 0
#define PCI_BUS_BRIDGE_MEM_WINDOW 1
#define PCI_BUS_BRIDGE_PREF_MEM_WINDOW 2
extern const unsigned char pcie_link_speed[]; extern const unsigned char pcie_link_speed[];
extern bool pci_early_dump; extern bool pci_early_dump;
@ -331,7 +335,7 @@ struct device *pci_get_host_bridge_device(struct pci_dev *dev);
void pci_put_host_bridge_device(struct device *dev); void pci_put_host_bridge_device(struct device *dev);
unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge); unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge);
int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type); int pbus_reassign_bridge_resources(struct pci_bus *bus, struct resource *res);
int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align); int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align);
int pci_configure_extended_tags(struct pci_dev *dev, void *ign); int pci_configure_extended_tags(struct pci_dev *dev, void *ign);
@ -382,6 +386,8 @@ static inline int pci_resource_num(const struct pci_dev *dev,
return resno; return resno;
} }
struct resource *pbus_select_window(struct pci_bus *bus,
const struct resource *res);
void pci_reassigndev_resource_alignment(struct pci_dev *dev); void pci_reassigndev_resource_alignment(struct pci_dev *dev);
void pci_disable_bridge_window(struct pci_dev *dev); void pci_disable_bridge_window(struct pci_dev *dev);
struct pci_bus *pci_bus_get(struct pci_bus *bus); struct pci_bus *pci_bus_get(struct pci_bus *bus);

View File

@ -420,13 +420,17 @@ static void pci_read_bridge_io(struct pci_dev *dev, struct resource *res,
limit |= ((unsigned long) io_limit_hi << 16); limit |= ((unsigned long) io_limit_hi << 16);
} }
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
if (base <= limit) { if (base <= limit) {
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
region.start = base; region.start = base;
region.end = limit + io_granularity - 1; region.end = limit + io_granularity - 1;
pcibios_bus_to_resource(dev->bus, res, &region); pcibios_bus_to_resource(dev->bus, res, &region);
if (log) if (log)
pci_info(dev, " bridge window %pR\n", res); pci_info(dev, " bridge window %pR\n", res);
} else {
resource_set_range(res, 0, 0);
res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
} }
} }
@ -441,13 +445,18 @@ static void pci_read_bridge_mmio(struct pci_dev *dev, struct resource *res,
pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
base = ((unsigned long) mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; base = ((unsigned long) mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
limit = ((unsigned long) mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16; limit = ((unsigned long) mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
if (base <= limit) { if (base <= limit) {
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
region.start = base; region.start = base;
region.end = limit + 0xfffff; region.end = limit + 0xfffff;
pcibios_bus_to_resource(dev->bus, res, &region); pcibios_bus_to_resource(dev->bus, res, &region);
if (log) if (log)
pci_info(dev, " bridge window %pR\n", res); pci_info(dev, " bridge window %pR\n", res);
} else {
resource_set_range(res, 0, 0);
res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
} }
} }
@ -490,16 +499,20 @@ static void pci_read_bridge_mmio_pref(struct pci_dev *dev, struct resource *res,
return; return;
} }
res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | IORESOURCE_MEM |
IORESOURCE_PREFETCH;
if (res->flags & PCI_PREF_RANGE_TYPE_64)
res->flags |= IORESOURCE_MEM_64;
if (base <= limit) { if (base <= limit) {
res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) |
IORESOURCE_MEM | IORESOURCE_PREFETCH;
if (res->flags & PCI_PREF_RANGE_TYPE_64)
res->flags |= IORESOURCE_MEM_64;
region.start = base; region.start = base;
region.end = limit + 0xfffff; region.end = limit + 0xfffff;
pcibios_bus_to_resource(dev->bus, res, &region); pcibios_bus_to_resource(dev->bus, res, &region);
if (log) if (log)
pci_info(dev, " bridge window %pR\n", res); pci_info(dev, " bridge window %pR\n", res);
} else {
resource_set_range(res, 0, 0);
res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
} }
} }
@ -525,10 +538,14 @@ static void pci_read_bridge_windows(struct pci_dev *bridge)
} }
if (io) { if (io) {
bridge->io_window = 1; bridge->io_window = 1;
pci_read_bridge_io(bridge, &res, true); pci_read_bridge_io(bridge,
pci_resource_n(bridge, PCI_BRIDGE_IO_WINDOW),
true);
} }
pci_read_bridge_mmio(bridge, &res, true); pci_read_bridge_mmio(bridge,
pci_resource_n(bridge, PCI_BRIDGE_MEM_WINDOW),
true);
/* /*
* DECchip 21050 pass 2 errata: the bridge may miss an address * DECchip 21050 pass 2 errata: the bridge may miss an address
@ -566,7 +583,10 @@ static void pci_read_bridge_windows(struct pci_dev *bridge)
bridge->pref_64_window = 1; bridge->pref_64_window = 1;
} }
pci_read_bridge_mmio_pref(bridge, &res, true); pci_read_bridge_mmio_pref(bridge,
pci_resource_n(bridge,
PCI_BRIDGE_PREF_MEM_WINDOW),
true);
} }
void pci_read_bridge_bases(struct pci_bus *child) void pci_read_bridge_bases(struct pci_bus *child)
@ -586,9 +606,13 @@ void pci_read_bridge_bases(struct pci_bus *child)
for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
pci_read_bridge_io(child->self, child->resource[0], false); pci_read_bridge_io(child->self,
pci_read_bridge_mmio(child->self, child->resource[1], false); child->resource[PCI_BUS_BRIDGE_IO_WINDOW], false);
pci_read_bridge_mmio_pref(child->self, child->resource[2], false); pci_read_bridge_mmio(child->self,
child->resource[PCI_BUS_BRIDGE_MEM_WINDOW], false);
pci_read_bridge_mmio_pref(child->self,
child->resource[PCI_BUS_BRIDGE_PREF_MEM_WINDOW],
false);
if (!dev->transparent) if (!dev->transparent)
return; return;

File diff suppressed because it is too large Load Diff

View File

@ -359,6 +359,9 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
res->flags &= ~IORESOURCE_UNSET; res->flags &= ~IORESOURCE_UNSET;
res->flags &= ~IORESOURCE_STARTALIGN; res->flags &= ~IORESOURCE_STARTALIGN;
if (resno >= PCI_BRIDGE_RESOURCES && resno <= PCI_BRIDGE_RESOURCE_END)
res->flags &= ~IORESOURCE_DISABLED;
pci_info(dev, "%s %pR: assigned\n", res_name, res); pci_info(dev, "%s %pR: assigned\n", res_name, res);
if (resno < PCI_BRIDGE_RESOURCES) if (resno < PCI_BRIDGE_RESOURCES)
pci_update_resource(dev, resno); pci_update_resource(dev, resno);
@ -406,20 +409,25 @@ int pci_reassign_resource(struct pci_dev *dev, int resno,
return 0; 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 = pci_resource_n(dev, resno); struct resource *res = pci_resource_n(dev, resno);
const char *res_name = pci_resource_name(dev, resno); const char *res_name = pci_resource_name(dev, resno);
int ret;
if (!res->parent) if (!res->parent)
return; return 0;
pci_info(dev, "%s %pR: releasing\n", res_name, res); pci_info(dev, "%s %pR: releasing\n", res_name, res);
release_resource(res); ret = release_resource(res);
if (ret)
return ret;
res->end = resource_size(res) - 1; res->end = resource_size(res) - 1;
res->start = 0; res->start = 0;
res->flags |= IORESOURCE_UNSET; res->flags |= IORESOURCE_UNSET;
return 0;
} }
EXPORT_SYMBOL(pci_release_resource); EXPORT_SYMBOL(pci_release_resource);
@ -488,7 +496,7 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size)
/* Check if the new config works by trying to assign everything. */ /* Check if the new config works by trying to assign everything. */
if (dev->bus->self) { if (dev->bus->self) {
ret = pci_reassign_bridge_resources(dev->bus->self, res->flags); ret = pbus_reassign_bridge_resources(dev->bus, res);
if (ret) if (ret)
goto error_resize; goto error_resize;
} }
@ -522,22 +530,26 @@ int pci_enable_resources(struct pci_dev *dev, int mask)
if (pci_resource_is_optional(dev, i)) if (pci_resource_is_optional(dev, i))
continue; continue;
if (r->flags & IORESOURCE_UNSET) { if (i < PCI_BRIDGE_RESOURCES) {
pci_err(dev, "%s %pR: not assigned; can't enable device\n", if (r->flags & IORESOURCE_UNSET) {
r_name, r); pci_err(dev, "%s %pR: not assigned; can't enable device\n",
return -EINVAL; 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) { if (r->parent) {
pci_err(dev, "%s %pR: not claimed; can't enable device\n", if (r->flags & IORESOURCE_IO)
r_name, r); cmd |= PCI_COMMAND_IO;
return -EINVAL; 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) { if (cmd != old_cmd) {

View File

@ -119,7 +119,8 @@ enum {
#define PCI_CB_BRIDGE_MEM_1_WINDOW (PCI_BRIDGE_RESOURCES + 3) #define PCI_CB_BRIDGE_MEM_1_WINDOW (PCI_BRIDGE_RESOURCES + 3)
/* Total number of bridge resources for P2P and CardBus */ /* Total number of bridge resources for P2P and CardBus */
#define PCI_BRIDGE_RESOURCE_NUM 4 #define PCI_P2P_BRIDGE_RESOURCE_NUM 3
#define PCI_BRIDGE_RESOURCE_NUM 4
/* Resources assigned to buses behind the bridge */ /* Resources assigned to buses behind the bridge */
PCI_BRIDGE_RESOURCES, PCI_BRIDGE_RESOURCES,
@ -1417,7 +1418,7 @@ void pci_reset_secondary_bus(struct pci_dev *dev);
void pcibios_reset_secondary_bus(struct pci_dev *dev); void pcibios_reset_secondary_bus(struct pci_dev *dev);
void pci_update_resource(struct pci_dev *dev, int resno); void pci_update_resource(struct pci_dev *dev, int resno);
int __must_check pci_assign_resource(struct pci_dev *dev, int i); int __must_check pci_assign_resource(struct pci_dev *dev, int i);
void pci_release_resource(struct pci_dev *dev, int resno); int pci_release_resource(struct pci_dev *dev, int resno);
static inline int pci_rebar_bytes_to_size(u64 bytes) static inline int pci_rebar_bytes_to_size(u64 bytes)
{ {
bytes = roundup_pow_of_two(bytes); bytes = roundup_pow_of_two(bytes);