Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 81110
b: refs/heads/master
c: 0ec6b5c
h: refs/heads/master
v: v3
  • Loading branch information
Benjamin Herrenschmidt authored and Paul Mackerras committed Dec 20, 2007
1 parent abd6814 commit 1d9cc94
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 175 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: b1258fd1029a47e99a624970b16ac11ad97ddb6a
refs/heads/master: 0ec6b5c1028f29aed07bc7c32945990c5cd48c14
191 changes: 17 additions & 174 deletions trunk/arch/powerpc/kernel/pci_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ int pcibios_assign_bus_offset = 1;

void pcibios_make_OF_bus_map(void);

static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);
static int probe_resource(struct pci_bus *parent, struct resource *pr,
struct resource *res, struct resource **conflict);
static void update_bridge_base(struct pci_bus *bus, int i);
static void pcibios_fixup_resources(struct pci_dev* dev);
static void fixup_broken_pcnet32(struct pci_dev* dev);
static int reparent_resources(struct resource *parent, struct resource *res);
Expand Down Expand Up @@ -134,7 +130,7 @@ pcibios_fixup_resources(struct pci_dev *dev)
if (offset != 0) {
res->start = (res->start + offset) & mask;
res->end = (res->end + offset) & mask;
DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
DBG("PCI: Fixup res %d (0x%lx) of dev %s: %llx -> %llx\n",
i, res->flags, pci_name(dev),
(u64)res->start - offset, (u64)res->start);
}
Expand Down Expand Up @@ -267,9 +263,12 @@ pcibios_allocate_bus_resources(struct list_head *bus_list)
}
}

DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n",
DBG("PCI: dev %s (bus 0x%02x) bridge rsrc %d: %016llx..%016llx "
"(f:0x%08lx), parent %p\n",
bus->self ? pci_name(bus->self) : "PHB", bus->number, i,
(u64)res->start, (u64)res->end, res->flags, pr);
if (pr) {

if (pr && !(pr->flags & IORESOURCE_UNSET)) {
if (request_resource(pr, res) == 0)
continue;
/*
Expand All @@ -280,10 +279,11 @@ pcibios_allocate_bus_resources(struct list_head *bus_list)
if (reparent_resources(pr, res) == 0)
continue;
}
printk(KERN_ERR "PCI: Cannot allocate resource region "
"%d of PCI bridge %d\n", i, bus->number);
if (pci_relocate_bridge_resource(bus, i))
bus->resource[i] = NULL;
printk(KERN_WARNING
"PCI: Cannot allocate resource region "
"%d of PCI bridge %d, will remap\n",
i, bus->number);
res->flags |= IORESOURCE_UNSET;
}
pcibios_allocate_bus_resources(&bus->children);
}
Expand Down Expand Up @@ -324,112 +324,6 @@ reparent_resources(struct resource *parent, struct resource *res)
return 0;
}

/*
* A bridge has been allocated a range which is outside the range
* of its parent bridge, so it needs to be moved.
*/
static int __init
pci_relocate_bridge_resource(struct pci_bus *bus, int i)
{
struct resource *res, *pr, *conflict;
resource_size_t try, size;
struct pci_bus *parent = bus->parent;
int j;

if (parent == NULL) {
/* shouldn't ever happen */
printk(KERN_ERR "PCI: can't move host bridge resource\n");
return -1;
}
res = bus->resource[i];
if (res == NULL)
return -1;
pr = NULL;
for (j = 0; j < 4; j++) {
struct resource *r = parent->resource[j];
if (!r)
continue;
if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
continue;
if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {
pr = r;
break;
}
if (res->flags & IORESOURCE_PREFETCH)
pr = r;
}
if (pr == NULL)
return -1;
size = res->end - res->start;
if (pr->start > pr->end || size > pr->end - pr->start)
return -1;
try = pr->end;
for (;;) {
res->start = try - size;
res->end = try;
if (probe_resource(bus->parent, pr, res, &conflict) == 0)
break;
if (conflict->start <= pr->start + size)
return -1;
try = conflict->start - 1;
}
if (request_resource(pr, res)) {
DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n",
(u64)res->start, (u64)res->end);
return -1; /* "can't happen" */
}
update_bridge_base(bus, i);
printk(KERN_INFO "PCI: bridge %d resource %d moved to %llx..%llx\n",
bus->number, i, (unsigned long long)res->start,
(unsigned long long)res->end);
return 0;
}

static int __init
probe_resource(struct pci_bus *parent, struct resource *pr,
struct resource *res, struct resource **conflict)
{
struct pci_bus *bus;
struct pci_dev *dev;
struct resource *r;
int i;

for (r = pr->child; r != NULL; r = r->sibling) {
if (r->end >= res->start && res->end >= r->start) {
*conflict = r;
return 1;
}
}
list_for_each_entry(bus, &parent->children, node) {
for (i = 0; i < 4; ++i) {
if ((r = bus->resource[i]) == NULL)
continue;
if (!r->flags || r->start > r->end || r == res)
continue;
if (pci_find_parent_resource(bus->self, r) != pr)
continue;
if (r->end >= res->start && res->end >= r->start) {
*conflict = r;
return 1;
}
}
}
list_for_each_entry(dev, &parent->devices, bus_list) {
for (i = 0; i < 6; ++i) {
r = &dev->resource[i];
if (!r->flags || (r->flags & IORESOURCE_UNSET))
continue;
if (pci_find_parent_resource(dev, r) != pr)
continue;
if (r->end >= res->start && res->end >= r->start) {
*conflict = r;
return 1;
}
}
}
return 0;
}

void __init
update_bridge_resource(struct pci_dev *dev, struct resource *res)
{
Expand Down Expand Up @@ -486,24 +380,16 @@ update_bridge_resource(struct pci_dev *dev, struct resource *res)
pci_write_config_word(dev, PCI_COMMAND, cmd);
}

static void __init
update_bridge_base(struct pci_bus *bus, int i)
{
struct resource *res = bus->resource[i];
struct pci_dev *dev = bus->self;
update_bridge_resource(dev, res);
}

static inline void alloc_resource(struct pci_dev *dev, int idx)
{
struct resource *pr, *r = &dev->resource[idx];

DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n",
DBG("PCI: Allocating %s: Resource %d: %016llx..%016llx (f=%lx)\n",
pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags);
pr = pci_find_parent_resource(dev, r);
if (!pr || request_resource(pr, r) < 0) {
printk(KERN_WARNING "PCI: Remapping resource region %d"
" of device %s\n", idx, pci_name(dev));
if (!pr || (pr->flags & IORESOURCE_UNSET) || request_resource(pr, r) < 0) {
printk(KERN_WARNING "PCI: Cannot allocate resource region %d"
" of device %s, will remap\n", idx, pci_name(dev));
if (pr)
DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n",
pr, (u64)pr->start, (u64)pr->end, pr->flags);
Expand Down Expand Up @@ -552,50 +438,6 @@ pcibios_allocate_resources(int pass)
}
}

static void __init
pcibios_assign_resources(void)
{
struct pci_dev *dev = NULL;
int idx;
struct resource *r;

for_each_pci_dev(dev) {
int class = dev->class >> 8;

/* Don't touch classless devices and host bridges */
if (!class || class == PCI_CLASS_BRIDGE_HOST)
continue;

for (idx = 0; idx < 6; idx++) {
r = &dev->resource[idx];

/*
* We shall assign a new address to this resource,
* either because the BIOS (sic) forgot to do so
* or because we have decided the old address was
* unusable for some reason.
*/
if ((r->flags & IORESOURCE_UNSET) && r->end &&
(!ppc_md.pcibios_enable_device_hook ||
!ppc_md.pcibios_enable_device_hook(dev, 1))) {
int rc;

r->flags &= ~IORESOURCE_UNSET;
rc = pci_assign_resource(dev, idx);
BUG_ON(rc);
}
}

#if 0 /* don't assign ROMs */
r = &dev->resource[PCI_ROM_RESOURCE];
r->end -= r->start;
r->start = 0;
if (r->end)
pci_assign_resource(dev, PCI_ROM_RESOURCE);
#endif
}
}

#ifdef CONFIG_PPC_OF
/*
* Functions below are used on OpenFirmware machines.
Expand Down Expand Up @@ -1122,7 +964,8 @@ pcibios_init(void)
#ifdef CONFIG_PPC_PMAC
pcibios_fixup_p2p_bridges();
#endif /* CONFIG_PPC_PMAC */
pcibios_assign_resources();
DBG("PCI: Assigning unassigned resouces...\n");
pci_assign_unassigned_resources();

/* Call machine dependent post-init code */
if (ppc_md.pcibios_after_init)
Expand Down

0 comments on commit 1d9cc94

Please sign in to comment.