X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc64%2Fkernel%2Fpmac_pci.c;h=a0df4e8c0236b2f3c92f0d23c580875f740b7022;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=9e1a069554e7f063b03761f99e964c46b0aee1a6;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c index 9e1a06955..a0df4e8c0 100644 --- a/arch/ppc64/kernel/pmac_pci.c +++ b/arch/ppc64/kernel/pmac_pci.c @@ -39,15 +39,11 @@ #define DBG(x...) #endif -extern int pci_probe_only; -extern int pci_read_irq_line(struct pci_dev *pci_dev); - /* XXX Could be per-controller, but I don't think we risk anything by * assuming we won't have both UniNorth and Bandit */ static int has_uninorth; static struct pci_controller *u3_agp; -u8 pci_cache_line_size; -struct pci_dev *k2_skiplist[2]; +struct device_node *k2_skiplist[2]; static int __init fixup_one_level_bus_range(struct device_node *node, int higher) { @@ -150,16 +146,9 @@ static int __pmac macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { struct pci_controller *hose; - struct device_node *busdn; unsigned long addr; - if (bus->self) - busdn = pci_device_to_OF_node(bus->self); - else - busdn = bus->sysdata; /* must be a phb */ - if (busdn == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - hose = busdn->phb; + hose = pci_bus_to_host(bus); if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; @@ -188,16 +177,9 @@ static int __pmac macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose; - struct device_node *busdn; unsigned long addr; - if (bus->self) - busdn = pci_device_to_OF_node(bus->self); - else - busdn = bus->sysdata; /* must be a phb */ - if (busdn == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - hose = busdn->phb; + hose = pci_bus_to_host(bus); if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; @@ -236,14 +218,43 @@ static struct pci_ops macrisc_pci_ops = * implement self-view of the HT host yet */ -static int skip_k2_device(struct pci_bus *bus, unsigned int devfn) +/* + * This function deals with some "special cases" devices. + * + * 0 -> No special case + * 1 -> Skip the device but act as if the access was successfull + * (return 0xff's on reads, eventually, cache config space + * accesses in a later version) + * -1 -> Hide the device (unsuccessful acess) + */ +static int u3_ht_skip_device(struct pci_controller *hose, + struct pci_bus *bus, unsigned int devfn) { + struct device_node *busdn, *dn; int i; + /* We only allow config cycles to devices that are in OF device-tree + * as we are apparently having some weird things going on with some + * revs of K2 on recent G5s + */ + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = hose->arch_data; + for (dn = busdn->child; dn; dn = dn->sibling) + if (dn->devfn == devfn) + break; + if (dn == NULL) + return -1; + + /* + * When a device in K2 is powered down, we die on config + * cycle accesses. Fix that here. + */ for (i=0; i<2; i++) - if (k2_skiplist[i] && k2_skiplist[i]->bus == bus && - k2_skiplist[i]->devfn == devfn) + if (k2_skiplist[i] == dn) return 1; + return 0; } @@ -259,8 +270,7 @@ static unsigned long __pmac u3_ht_cfg_access(struct pci_controller* hose, { if (bus == hose->first_busno) { /* For now, we don't self probe U3 HT bridge */ - if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 || - PCI_SLOT(devfn) < 1) + if (PCI_SLOT(devfn) == 0) return 0; return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset); } else @@ -271,39 +281,21 @@ static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { struct pci_controller *hose; - struct device_node *busdn, *dn; unsigned long addr; - if (bus->self) - busdn = pci_device_to_OF_node(bus->self); - else - busdn = bus->sysdata; /* must be a phb */ - if (busdn == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - hose = busdn->phb; - if (hose == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - /* We only allow config cycles to devices that are in OF device-tree - * as we are apparently having some weird things going on with some - * revs of K2 on recent G5s - */ - for (dn = busdn->child; dn; dn = dn->sibling) - if (dn->devfn == devfn) - break; - if (dn == NULL) + hose = pci_bus_to_host(bus); + if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; - /* - * When a device in K2 is powered down, we die on config - * cycle accesses. Fix that here. We may ultimately want - * to cache the config space for those instead of returning - * 0xffffffff's to make life easier to HW detection tools - */ - if (skip_k2_device(bus, devfn)) { + + switch (u3_ht_skip_device(hose, bus, devfn)) { + case 0: + break; + case 1: switch (len) { case 1: *val = 0xff; break; @@ -313,6 +305,8 @@ static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, *val = 0xfffffffful; break; } return PCIBIOS_SUCCESSFUL; + default: + return PCIBIOS_DEVICE_NOT_FOUND; } /* @@ -337,28 +331,24 @@ static int __pmac u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose; - struct device_node *busdn; unsigned long addr; - if (bus->self) - busdn = pci_device_to_OF_node(bus->self); - else - busdn = bus->sysdata; /* must be a phb */ - if (busdn == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - hose = busdn->phb; + hose = pci_bus_to_host(bus); if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; - /* - * When a device in K2 is powered down, we die on config - * cycle accesses. Fix that here. - */ - if (skip_k2_device(bus, devfn)) + + switch (u3_ht_skip_device(hose, bus, devfn)) { + case 0: + break; + case 1: return PCIBIOS_SUCCESSFUL; + default: + return PCIBIOS_DEVICE_NOT_FOUND; + } /* * Note: the caller has already checked that offset is @@ -513,7 +503,7 @@ static void __init pmac_process_bridge_OF_ranges(struct pci_controller *hose, dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen); if (!dt_ranges) return; - /* lc_ranges = (unsigned int *) alloc_bootmem(rlen);*/ + /* lc_ranges = alloc_bootmem(rlen);*/ lc_ranges = static_lc_ranges; if (!lc_ranges) return; /* what can we do here ? */ @@ -623,15 +613,17 @@ static int __init add_bridge(struct device_node *dev) dev->full_name); } - hose = pci_alloc_pci_controller(phb_type_apple); - if (!hose) - return -ENOMEM; + hose = alloc_bootmem(sizeof(struct pci_controller)); + if (hose == NULL) + return -ENOMEM; + pci_setup_pci_controller(hose); + hose->arch_data = dev; hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; - of_prop = (struct property *)alloc_bootmem(sizeof(struct property) + - sizeof(hose->global_number)); + of_prop = alloc_bootmem(sizeof(struct property) + + sizeof(hose->global_number)); if (of_prop) { memset(of_prop, 0, sizeof(struct property)); of_prop->name = "linux,pci-domain"; @@ -669,13 +661,8 @@ void __init pmac_pcibios_fixup(void) { struct pci_dev *dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + for_each_pci_dev(dev) pci_read_irq_line(dev); - - pci_fix_bus_sysdata(); - - iommu_setup_u3(); - } static void __init pmac_fixup_phb_resources(void) @@ -747,14 +734,9 @@ void __init pmac_pci_init(void) pmac_check_ht_link(); - /* Tell pci.c to use the common resource allocation mecanism */ - pci_probe_only = 0; + /* Tell pci.c to not use the common resource allocation mecanism */ + pci_probe_only = 1; - /* HT don't do more than 64 bytes transfers. FIXME: Deal with - * the exception of U3/AGP (hook into pci_set_mwi) - */ - pci_cache_line_size = 16; /* 64 bytes */ - /* Allow all IO */ io_page_mask = -1; } @@ -763,7 +745,7 @@ void __init pmac_pci_init(void) * Disable second function on K2-SATA, it's broken * and disable IO BARs on first one */ -void fixup_k2_sata(struct pci_dev* dev) +static void fixup_k2_sata(struct pci_dev* dev) { int i; u16 cmd;