X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fpci%2Fsetup-bus.c;h=8ddb918f5f57dfc0bdda3e4a287abe4c08bae365;hb=32aff5732a11739e81994b3bcd7a9d0e8b1ea06e;hp=6b0e6464eb391130d1751be13620ae38fd7d5635;hpb=81d4af1340badcd2100c84fbd1bfd13156de41aa;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 6b0e646..8ddb918 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -34,17 +34,7 @@ #define DBG(x...) #endif -#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) - -/* - * FIXME: IO should be max 256 bytes. However, since we may - * have a P2P bridge below a cardbus bridge, we need 4K. - */ -#define CARDBUS_IO_SIZE (4*1024) -#define CARDBUS_MEM_SIZE (32*1024*1024) - -static void __devinit -pbus_assign_resources_sorted(struct pci_bus *bus) +static void pbus_assign_resources_sorted(struct pci_bus *bus) { struct pci_dev *dev; struct resource *res; @@ -55,11 +45,19 @@ pbus_assign_resources_sorted(struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) { u16 class = dev->class >> 8; - /* Don't touch classless devices and host bridges. */ + /* Don't touch classless devices or host bridges or ioapics. */ if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST) continue; + /* Don't touch ioapic devices already enabled by firmware */ + if (class == PCI_CLASS_SYSTEM_PIC) { + u16 command; + pci_read_config_word(dev, PCI_COMMAND, &command); + if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) + continue; + } + pdev_sort_resources(dev, &head); } @@ -67,6 +65,7 @@ pbus_assign_resources_sorted(struct pci_bus *bus) res = list->res; idx = res - &list->dev->resource[0]; if (pci_assign_resource(list->dev, idx)) { + /* FIXME: get rid of this */ res->start = 0; res->end = 0; res->flags = 0; @@ -77,8 +76,7 @@ pbus_assign_resources_sorted(struct pci_bus *bus) } } -static void __devinit -pci_setup_cardbus(struct pci_bus *bus) +void pci_setup_cardbus(struct pci_bus *bus) { struct pci_dev *bridge = bus->self; struct pci_bus_region region; @@ -92,8 +90,9 @@ pci_setup_cardbus(struct pci_bus *bus) * The IO resource is allocated a range twice as large as it * would normally need. This allows us to set both IO regs. */ - printk(" IO window: %08lx-%08lx\n", - region.start, region.end); + printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n", + (unsigned long)region.start, + (unsigned long)region.end); pci_write_config_dword(bridge, PCI_CB_IO_BASE_0, region.start); pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0, @@ -102,8 +101,9 @@ pci_setup_cardbus(struct pci_bus *bus) pcibios_resource_to_bus(bridge, ®ion, bus->resource[1]); if (bus->resource[1]->flags & IORESOURCE_IO) { - printk(" IO window: %08lx-%08lx\n", - region.start, region.end); + printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n", + (unsigned long)region.start, + (unsigned long)region.end); pci_write_config_dword(bridge, PCI_CB_IO_BASE_1, region.start); pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1, @@ -112,8 +112,9 @@ pci_setup_cardbus(struct pci_bus *bus) pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); if (bus->resource[2]->flags & IORESOURCE_MEM) { - printk(" PREFETCH window: %08lx-%08lx\n", - region.start, region.end); + printk(KERN_INFO " PREFETCH window: 0x%08lx-0x%08lx\n", + (unsigned long)region.start, + (unsigned long)region.end); pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0, region.start); pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0, @@ -122,14 +123,16 @@ pci_setup_cardbus(struct pci_bus *bus) pcibios_resource_to_bus(bridge, ®ion, bus->resource[3]); if (bus->resource[3]->flags & IORESOURCE_MEM) { - printk(" MEM window: %08lx-%08lx\n", - region.start, region.end); + printk(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n", + (unsigned long)region.start, + (unsigned long)region.end); pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1, region.start); pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1, region.end); } } +EXPORT_SYMBOL(pci_setup_cardbus); /* Initialize bridges with base/limit values we have collected. PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998) @@ -142,12 +145,11 @@ pci_setup_cardbus(struct pci_bus *bus) config space writes, so it's quite possible that an I/O window of the bridge will have some undesirable address (e.g. 0) after the first write. Ditto 64-bit prefetchable MMIO. */ -static void __devinit -pci_setup_bridge(struct pci_bus *bus) +static void pci_setup_bridge(struct pci_bus *bus) { struct pci_dev *bridge = bus->self; struct pci_bus_region region; - u32 l, io_upper16; + u32 l, bu, lu, io_upper16; DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge)); @@ -161,7 +163,8 @@ pci_setup_bridge(struct pci_bus *bus) /* Set up upper 16 bits of I/O base/limit. */ io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); DBG(KERN_INFO " IO window: %04lx-%04lx\n", - region.start, region.end); + (unsigned long)region.start, + (unsigned long)region.end); } else { /* Clear upper 16 bits of I/O base/limit. */ @@ -182,8 +185,9 @@ pci_setup_bridge(struct pci_bus *bus) if (bus->resource[1]->flags & IORESOURCE_MEM) { l = (region.start >> 16) & 0xfff0; l |= region.end & 0xfff00000; - DBG(KERN_INFO " MEM window: %08lx-%08lx\n", - region.start, region.end); + DBG(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n", + (unsigned long)region.start, + (unsigned long)region.end); } else { l = 0x0000fff0; @@ -197,12 +201,16 @@ pci_setup_bridge(struct pci_bus *bus) pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); /* Set up PREF base/limit. */ + bu = lu = 0; pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { l = (region.start >> 16) & 0xfff0; l |= region.end & 0xfff00000; - DBG(KERN_INFO " PREFETCH window: %08lx-%08lx\n", - region.start, region.end); + bu = upper_32_bits(region.start); + lu = upper_32_bits(region.end); + DBG(KERN_INFO " PREFETCH window: 0x%016llx-0x%016llx\n", + (unsigned long long)region.start, + (unsigned long long)region.end); } else { l = 0x0000fff0; @@ -210,8 +218,9 @@ pci_setup_bridge(struct pci_bus *bus) } pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); - /* Clear out the upper 32 bits of PREF base. */ - pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0); + /* Set the upper 32 bits of PREF base & limit. */ + pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); + pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); } @@ -219,8 +228,7 @@ pci_setup_bridge(struct pci_bus *bus) /* Check whether the bridge supports optional I/O and prefetchable memory ranges. If not, the respective base/limit registers must be read-only and read as 0. */ -static void __devinit -pci_bridge_check_ranges(struct pci_bus *bus) +static void pci_bridge_check_ranges(struct pci_bus *bus) { u16 io; u32 pmem; @@ -258,8 +266,7 @@ pci_bridge_check_ranges(struct pci_bus *bus) bus resource of a given type. Note: we intentionally skip the bus resources which have already been assigned (that is, have non-NULL parent resource). */ -static struct resource * __devinit -find_free_bus_resource(struct pci_bus *bus, unsigned long type) +static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type) { int i; struct resource *r; @@ -280,8 +287,7 @@ find_free_bus_resource(struct pci_bus *bus, unsigned long type) since these windows have 4K granularity and the IO ranges of non-bridge PCI devices are limited to 256 bytes. We must be careful with the ISA aliasing though. */ -static void __devinit -pbus_size_io(struct pci_bus *bus) +static void pbus_size_io(struct pci_bus *bus) { struct pci_dev *dev; struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); @@ -313,7 +319,7 @@ pbus_size_io(struct pci_bus *bus) #if defined(CONFIG_ISA) || defined(CONFIG_EISA) size = (size & 0xff) + ((size & ~0xffUL) << 2); #endif - size = ROUND_UP(size + size1, 4096); + size = ALIGN(size + size1, 4096); if (!size) { b_res->flags = 0; return; @@ -321,16 +327,16 @@ pbus_size_io(struct pci_bus *bus) /* Alignment of the IO window is always 4K */ b_res->start = 4096; b_res->end = b_res->start + size - 1; + b_res->flags |= IORESOURCE_STARTALIGN; } /* Calculate the size of the bus and minimal alignment which guarantees that all child resources fit in this size. */ -static int __devinit -pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) +static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) { struct pci_dev *dev; - unsigned long min_align, align, size; - unsigned long aligns[12]; /* Alignments from 1Mb to 2Gb */ + resource_size_t min_align, align, size; + resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ int order, max_order; struct resource *b_res = find_free_bus_resource(bus, type); @@ -346,7 +352,7 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) for (i = 0; i < PCI_NUM_RESOURCES; i++) { struct resource *r = &dev->resource[i]; - unsigned long r_size; + resource_size_t r_size; if (r->parent || (r->flags & mask) != type) continue; @@ -356,8 +362,10 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) order = __ffs(align) - 20; if (order > 11) { printk(KERN_WARNING "PCI: region %s/%d " - "too large: %lx-%lx\n", - pci_name(dev), i, r->start, r->end); + "too large: 0x%016llx-0x%016llx\n", + pci_name(dev), i, + (unsigned long long)r->start, + (unsigned long long)r->end); r->flags = 0; continue; } @@ -376,26 +384,29 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) align = 0; min_align = 0; for (order = 0; order <= max_order; order++) { - unsigned long align1 = 1UL << (order + 20); - +#ifdef CONFIG_RESOURCES_64BIT + resource_size_t align1 = 1ULL << (order + 20); +#else + resource_size_t align1 = 1U << (order + 20); +#endif if (!align) min_align = align1; - else if (ROUND_UP(align + min_align, min_align) < align1) + else if (ALIGN(align + min_align, min_align) < align1) min_align = align1 >> 1; align += aligns[order]; } - size = ROUND_UP(size, min_align); + size = ALIGN(size, min_align); if (!size) { b_res->flags = 0; return 1; } b_res->start = min_align; b_res->end = size + min_align - 1; + b_res->flags |= IORESOURCE_STARTALIGN; return 1; } -static void __devinit -pci_bus_size_cardbus(struct pci_bus *bus) +static void pci_bus_size_cardbus(struct pci_bus *bus) { struct pci_dev *bridge = bus->self; struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES]; @@ -405,13 +416,13 @@ pci_bus_size_cardbus(struct pci_bus *bus) * Reserve some resources for CardBus. We reserve * a fixed amount of bus space for CardBus bridges. */ - b_res[0].start = CARDBUS_IO_SIZE; - b_res[0].end = b_res[0].start + CARDBUS_IO_SIZE - 1; - b_res[0].flags |= IORESOURCE_IO; + b_res[0].start = 0; + b_res[0].end = pci_cardbus_io_size - 1; + b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; - b_res[1].start = CARDBUS_IO_SIZE; - b_res[1].end = b_res[1].start + CARDBUS_IO_SIZE - 1; - b_res[1].flags |= IORESOURCE_IO; + b_res[1].start = 0; + b_res[1].end = pci_cardbus_io_size - 1; + b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN; /* * Check whether prefetchable memory is supported @@ -430,22 +441,21 @@ pci_bus_size_cardbus(struct pci_bus *bus) * twice the size. */ if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) { - b_res[2].start = CARDBUS_MEM_SIZE; - b_res[2].end = b_res[2].start + CARDBUS_MEM_SIZE - 1; - b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; + b_res[2].start = 0; + b_res[2].end = pci_cardbus_mem_size - 1; + b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN; - b_res[3].start = CARDBUS_MEM_SIZE; - b_res[3].end = b_res[3].start + CARDBUS_MEM_SIZE - 1; - b_res[3].flags |= IORESOURCE_MEM; + b_res[3].start = 0; + b_res[3].end = pci_cardbus_mem_size - 1; + b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; } else { - b_res[3].start = CARDBUS_MEM_SIZE * 2; - b_res[3].end = b_res[3].start + CARDBUS_MEM_SIZE * 2 - 1; - b_res[3].flags |= IORESOURCE_MEM; + b_res[3].start = 0; + b_res[3].end = pci_cardbus_mem_size * 2 - 1; + b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN; } } -void __devinit -pci_bus_size_bridges(struct pci_bus *bus) +void __ref pci_bus_size_bridges(struct pci_bus *bus) { struct pci_dev *dev; unsigned long mask, prefmask; @@ -495,8 +505,7 @@ pci_bus_size_bridges(struct pci_bus *bus) } EXPORT_SYMBOL(pci_bus_size_bridges); -void __devinit -pci_bus_assign_resources(struct pci_bus *bus) +void __ref pci_bus_assign_resources(struct pci_bus *bus) { struct pci_bus *b; struct pci_dev *dev;