Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 180997
b: refs/heads/master
c: 2fe2abf
h: refs/heads/master
i:
  180995: 3f1e6c4
v: v3
  • Loading branch information
Bjorn Helgaas authored and Jesse Barnes committed Feb 23, 2010
1 parent e0ede2e commit 13c1dda
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 52 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 89a74ecccd1f78e51faf6287e5c0e93a92ac096e
refs/heads/master: 2fe2abf896c1e7a0ee65faaf3ef0ce654848abbd
12 changes: 3 additions & 9 deletions trunk/arch/ia64/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,23 +320,17 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
static void __devinit
pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl)
{
int i, j;
int i;

j = 0;
pci_bus_remove_resources(bus);
for (i = 0; i < ctrl->windows; i++) {
struct resource *res = &ctrl->window[i].resource;
/* HP's firmware has a hack to work around a Windows bug.
* Ignore these tiny memory ranges */
if ((res->flags & IORESOURCE_MEM) &&
(res->end - res->start < 16))
continue;
if (j >= PCI_BUS_NUM_RESOURCES) {
dev_warn(&bus->dev,
"ignoring host bridge window %pR (no space)\n",
res);
continue;
}
bus->resource[j++] = res;
pci_bus_add_resource(bus, res, 0);
}
}

Expand Down
33 changes: 4 additions & 29 deletions trunk/arch/x86/pci/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,6 @@ count_resource(struct acpi_resource *acpi_res, void *data)
return AE_OK;
}

static int
bus_has_transparent_bridge(struct pci_bus *bus)
{
struct pci_dev *dev;

list_for_each_entry(dev, &bus->devices, bus_list) {
u16 class = dev->class >> 8;

if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent)
return true;
}
return false;
}

static void
align_resource(struct acpi_device *bridge, struct resource *res)
{
Expand Down Expand Up @@ -92,12 +78,8 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
acpi_status status;
unsigned long flags;
struct resource *root;
int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;
u64 start, end;

if (bus_has_transparent_bridge(info->bus))
max_root_bus_resources -= 3;

status = resource_to_addr(acpi_res, &addr);
if (!ACPI_SUCCESS(status))
return AE_OK;
Expand All @@ -115,15 +97,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)

start = addr.minimum + addr.translation_offset;
end = start + addr.address_length - 1;
if (info->res_num >= max_root_bus_resources) {
if (pci_probe & PCI_USE__CRS)
printk(KERN_WARNING "PCI: Failed to allocate "
"0x%lx-0x%lx from %s for %s due to _CRS "
"returning more than %d resource descriptors\n",
(unsigned long) start, (unsigned long) end,
root->name, info->name, max_root_bus_resources);
return AE_OK;
}

res = &info->res[info->res_num];
res->name = info->name;
Expand All @@ -143,7 +116,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
dev_err(&info->bridge->dev,
"can't allocate host bridge window %pR\n", res);
} else {
info->bus->resource[info->res_num] = res;
pci_bus_add_resource(info->bus, res, 0);
info->res_num++;
if (addr.translation_offset)
dev_info(&info->bridge->dev, "host bridge window %pR "
Expand All @@ -164,7 +137,9 @@ get_current_resources(struct acpi_device *device, int busnum,
struct pci_root_info info;
size_t size;

if (!(pci_probe & PCI_USE__CRS))
if (pci_probe & PCI_USE__CRS)
pci_bus_remove_resources(bus);
else
dev_info(&device->dev,
"ignoring host bridge windows from ACPI; "
"boot with \"pci=use_crs\" to use them\n");
Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/x86/pci/bus_numa.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b)
printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n",
b->number);

pci_bus_remove_resources(b);
info = &pci_root_info[i];
for (j = 0; j < info->res_num; j++) {
struct resource *res;
struct resource *root;

res = &info->res[j];
b->resource[j] = res;
pci_bus_add_resource(b, res, 0);
if (res->flags & IORESOURCE_IO)
root = &ioport_resource;
else
Expand Down
3 changes: 1 addition & 2 deletions trunk/arch/x86/pci/bus_numa.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

/*
* sub bus (transparent) will use entres from 3 to store extra from
* root, so need to make sure we have enough slot there, Should we
* increase PCI_BUS_NUM_RESOURCES?
* root, so need to make sure we have enough slot there.
*/
#define RES_NUM 16
struct pci_root_info {
Expand Down
46 changes: 46 additions & 0 deletions trunk/drivers/pci/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,52 @@

#include "pci.h"

void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
unsigned int flags)
{
struct pci_bus_resource *bus_res;

bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL);
if (!bus_res) {
dev_err(&bus->dev, "can't add %pR resource\n", res);
return;
}

bus_res->res = res;
bus_res->flags = flags;
list_add_tail(&bus_res->list, &bus->resources);
}

struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n)
{
struct pci_bus_resource *bus_res;

if (n < PCI_BRIDGE_RESOURCE_NUM)
return bus->resource[n];

n -= PCI_BRIDGE_RESOURCE_NUM;
list_for_each_entry(bus_res, &bus->resources, list) {
if (n-- == 0)
return bus_res->res;
}
return NULL;
}
EXPORT_SYMBOL_GPL(pci_bus_resource_n);

void pci_bus_remove_resources(struct pci_bus *bus)
{
struct pci_bus_resource *bus_res, *tmp;
int i;

for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
bus->resource[i] = 0;

list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
list_del(&bus_res->list);
kfree(bus_res);
}
}

/**
* pci_bus_alloc_resource - allocate a resource from a parent bus
* @bus: PCI bus
Expand Down
17 changes: 13 additions & 4 deletions trunk/drivers/pci/probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ static void release_pcibus_dev(struct device *dev)

if (pci_bus->bridge)
put_device(pci_bus->bridge);
pci_bus_remove_resources(pci_bus);
kfree(pci_bus);
}

Expand Down Expand Up @@ -394,6 +395,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
void __devinit pci_read_bridge_bases(struct pci_bus *child)
{
struct pci_dev *dev = child->self;
struct resource *res;
int i;

if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */
Expand All @@ -403,17 +405,23 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
child->secondary, child->subordinate,
dev->transparent ? " (subtractive decode)" : "");

pci_bus_remove_resources(child);
for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];

pci_read_bridge_io(child);
pci_read_bridge_mmio(child);
pci_read_bridge_mmio_pref(child);

if (dev->transparent) {
for (i = 3; i < PCI_BUS_NUM_RESOURCES; i++) {
child->resource[i] = child->parent->resource[i - 3];
if (child->resource[i])
pci_bus_for_each_resource(child->parent, res, i) {
if (res) {
pci_bus_add_resource(child, res,
PCI_SUBTRACTIVE_DECODE);
dev_printk(KERN_DEBUG, &dev->dev,
" bridge window %pR (subtractive decode)\n",
child->resource[i]);
res);
}
}
}
}
Expand All @@ -428,6 +436,7 @@ static struct pci_bus * pci_alloc_bus(void)
INIT_LIST_HEAD(&b->children);
INIT_LIST_HEAD(&b->devices);
INIT_LIST_HEAD(&b->slots);
INIT_LIST_HEAD(&b->resources);
b->max_bus_speed = PCI_SPEED_UNKNOWN;
b->cur_bus_speed = PCI_SPEED_UNKNOWN;
}
Expand Down
35 changes: 29 additions & 6 deletions trunk/include/linux/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,9 +364,26 @@ static inline void pci_add_saved_cap(struct pci_dev *pci_dev,
hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space);
}

#ifndef PCI_BUS_NUM_RESOURCES
#define PCI_BUS_NUM_RESOURCES 16
#endif
/*
* 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
* buses below host bridges or subtractive decode bridges) go in the list.
* Use pci_bus_for_each_resource() to iterate through all the resources.
*/

/*
* PCI_SUBTRACTIVE_DECODE means the bridge forwards the window implicitly
* and there's no way to program the bridge with the details of the window.
* This does not apply to ACPI _CRS windows, even with the _DEC subtractive-
* decode bit set, because they are explicit and can be programmed with _SRS.
*/
#define PCI_SUBTRACTIVE_DECODE 0x1

struct pci_bus_resource {
struct list_head list;
struct resource *res;
unsigned int flags;
};

#define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */

Expand All @@ -377,8 +394,8 @@ struct pci_bus {
struct list_head devices; /* list of devices on this bus */
struct pci_dev *self; /* bridge device as seen by parent */
struct list_head slots; /* list of slots on this bus */
struct resource *resource[PCI_BUS_NUM_RESOURCES];
/* address space routed to this bus */
struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
struct list_head resources; /* address space routed to this bus */

struct pci_ops *ops; /* configuration access functions */
void *sysdata; /* hook for sys-specific extension */
Expand Down Expand Up @@ -829,8 +846,14 @@ int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *);
void pci_release_selected_regions(struct pci_dev *, int);

/* drivers/pci/bus.c */
void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, unsigned int flags);
struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n);
void pci_bus_remove_resources(struct pci_bus *bus);

#define pci_bus_for_each_resource(bus, res, i) \
for (i = 0; res = bus->resource[i], i < PCI_BUS_NUM_RESOURCES; i++)
for (i = 0; \
(res = pci_bus_resource_n(bus, i)) || i < PCI_BRIDGE_RESOURCE_NUM; \
i++)

int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
struct resource *res, resource_size_t size,
Expand Down

0 comments on commit 13c1dda

Please sign in to comment.