Revert to Fedora kernel-2.6.17-1.2187_FC5 patched with vs2.0.2.1; there are too many...
[linux-2.6.git] / arch / sparc64 / kernel / pci_sun4v.c
index 03ad4c0..0c08952 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/pstate.h>
 #include <asm/oplib.h>
 #include <asm/hypervisor.h>
-#include <asm/prom.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -647,37 +646,35 @@ static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, u
 /* Recursively descend into the OBP device tree, rooted at toplevel_node,
  * looking for a PCI device matching bus and devfn.
  */
-static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn)
+static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn)
 {
-       toplevel_node = toplevel_node->child;
+       toplevel_node = prom_getchild(toplevel_node);
 
-       while (toplevel_node != NULL) {
-               struct linux_prom_pci_registers *regs;
-               struct property *prop;
-               int ret;
+       while (toplevel_node != 0) {
+               int ret = obp_find(pregs, toplevel_node, bus, devfn);
 
-               ret = obp_find(toplevel_node, bus, devfn);
                if (ret != 0)
                        return ret;
 
-               prop = of_find_property(toplevel_node, "reg", NULL);
-               if (!prop)
+               ret = prom_getproperty(toplevel_node, "reg", (char *) pregs,
+                                      sizeof(*pregs) * PROMREG_MAX);
+               if (ret == 0 || ret == -1)
                        goto next_sibling;
 
-               regs = prop->value;
-               if (((regs->phys_hi >> 16) & 0xff) == bus &&
-                   ((regs->phys_hi >> 8) & 0xff) == devfn)
+               if (((pregs[0].phys_hi >> 16) & 0xff) == bus &&
+                   ((pregs[0].phys_hi >> 8) & 0xff) == devfn)
                        break;
 
        next_sibling:
-               toplevel_node = toplevel_node->sibling;
+               toplevel_node = prom_getsibling(toplevel_node);
        }
 
-       return toplevel_node != NULL;
+       return toplevel_node;
 }
 
 static int pdev_htab_populate(struct pci_pbm_info *pbm)
 {
+       struct linux_prom_pci_registers pr[PROMREG_MAX];
        u32 devhandle = pbm->devhandle;
        unsigned int bus;
 
@@ -688,7 +685,7 @@ static int pdev_htab_populate(struct pci_pbm_info *pbm)
                        unsigned int device = PCI_SLOT(devfn);
                        unsigned int func = PCI_FUNC(devfn);
 
-                       if (obp_find(pbm->prom_node, bus, devfn)) {
+                       if (obp_find(pr, pbm->prom_node, bus, devfn)) {
                                int err = pdev_htab_add(devhandle, bus,
                                                        device, func);
                                if (err)
@@ -814,7 +811,8 @@ static void pbm_scan_bus(struct pci_controller_info *p,
        pci_fixup_host_bridge_self(pbm->pci_bus);
        pbm->pci_bus->self->sysdata = cookie;
 #endif
-       pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
+       pci_fill_in_pbm_cookies(pbm->pci_bus, pbm,
+                               pbm->prom_node);
        pci_record_assignments(pbm, pbm->pci_bus);
        pci_assign_unassigned(pbm, pbm->pci_bus);
        pci_fixup_irq(pbm, pbm->pci_bus);
@@ -824,18 +822,15 @@ static void pbm_scan_bus(struct pci_controller_info *p,
 
 static void pci_sun4v_scan_bus(struct pci_controller_info *p)
 {
-       struct property *prop;
-       struct device_node *dp;
-
-       if ((dp = p->pbm_A.prom_node) != NULL) {
-               prop = of_find_property(dp, "66mhz-capable", NULL);
-               p->pbm_A.is_66mhz_capable = (prop != NULL);
+       if (p->pbm_A.prom_node) {
+               p->pbm_A.is_66mhz_capable =
+                       prom_getbool(p->pbm_A.prom_node, "66mhz-capable");
 
                pbm_scan_bus(p, &p->pbm_A);
        }
-       if ((dp = p->pbm_B.prom_node) != NULL) {
-               prop = of_find_property(dp, "66mhz-capable", NULL);
-               p->pbm_B.is_66mhz_capable = (prop != NULL);
+       if (p->pbm_B.prom_node) {
+               p->pbm_B.is_66mhz_capable =
+                       prom_getbool(p->pbm_B.prom_node, "66mhz-capable");
 
                pbm_scan_bus(p, &p->pbm_B);
        }
@@ -843,6 +838,45 @@ static void pci_sun4v_scan_bus(struct pci_controller_info *p)
        /* XXX register error interrupt handlers XXX */
 }
 
+static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm,
+                                       struct pci_dev *pdev,
+                                       unsigned int devino)
+{
+       u32 devhandle = pbm->devhandle;
+       int pil;
+
+       pil = 5;
+       if (pdev) {
+               switch ((pdev->class >> 16) & 0xff) {
+               case PCI_BASE_CLASS_STORAGE:
+                       pil = 5;
+                       break;
+
+               case PCI_BASE_CLASS_NETWORK:
+                       pil = 6;
+                       break;
+
+               case PCI_BASE_CLASS_DISPLAY:
+                       pil = 9;
+                       break;
+
+               case PCI_BASE_CLASS_MULTIMEDIA:
+               case PCI_BASE_CLASS_MEMORY:
+               case PCI_BASE_CLASS_BRIDGE:
+               case PCI_BASE_CLASS_SERIAL:
+                       pil = 10;
+                       break;
+
+               default:
+                       pil = 5;
+                       break;
+               };
+       }
+       BUG_ON(PIL_RESERVED(pil));
+
+       return sun4v_build_irq(devhandle, devino, pil, IBF_PCI);
+}
+
 static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource)
 {
        struct pcidev_cookie *pcp = pdev->sysdata;
@@ -978,13 +1012,8 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
                                             HV_PCI_TSBID(0, i),
                                             &io_attrs, &ra);
                if (ret == HV_EOK) {
-                       if (page_in_phys_avail(ra)) {
-                               pci_sun4v_iommu_demap(devhandle,
-                                                     HV_PCI_TSBID(0, i), 1);
-                       } else {
-                               cnt++;
-                               __set_bit(i, arena->map);
-                       }
+                       cnt++;
+                       __set_bit(i, arena->map);
                }
        }
 
@@ -994,18 +1023,13 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
 static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
 {
        struct pci_iommu *iommu = pbm->iommu;
-       struct property *prop;
        unsigned long num_tsb_entries, sz;
        u32 vdma[2], dma_mask, dma_offset;
-       int tsbsize;
-
-       prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
-       if (prop) {
-               u32 *val = prop->value;
+       int err, tsbsize;
 
-               vdma[0] = val[0];
-               vdma[1] = val[1];
-       } else {
+       err = prom_getproperty(pbm->prom_node, "virtual-dma",
+                              (char *)&vdma[0], sizeof(vdma));
+       if (err == 0 || err == -1) {
                /* No property, use default values. */
                vdma[0] = 0x80000000;
                vdma[1] = 0x80000000;
@@ -1057,30 +1081,34 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
        iommu->arena.limit = num_tsb_entries;
 
        sz = probe_existing_entries(pbm, iommu);
-       if (sz)
-               printk("%s: Imported %lu TSB entries from OBP\n",
-                      pbm->name, sz);
+
+       printk("%s: TSB entries [%lu], existing mapings [%lu]\n",
+              pbm->name, num_tsb_entries, sz);
 }
 
 static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
 {
-       struct property *prop;
-       unsigned int *busrange;
-
-       prop = of_find_property(pbm->prom_node, "bus-range", NULL);
-
-       busrange = prop->value;
+       unsigned int busrange[2];
+       int prom_node = pbm->prom_node;
+       int err;
+
+       err = prom_getproperty(prom_node, "bus-range",
+                              (char *)&busrange[0],
+                              sizeof(busrange));
+       if (err == 0 || err == -1) {
+               prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
+               prom_halt();
+       }
 
        pbm->pci_first_busno = busrange[0];
        pbm->pci_last_busno = busrange[1];
 
 }
 
-static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
+static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 devhandle)
 {
        struct pci_pbm_info *pbm;
-       struct property *prop;
-       int len, i;
+       int err, i;
 
        if (devhandle & 0x40)
                pbm = &p->pbm_B;
@@ -1088,19 +1116,32 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
                pbm = &p->pbm_A;
 
        pbm->parent = p;
-       pbm->prom_node = dp;
+       pbm->prom_node = prom_node;
        pbm->pci_first_slot = 1;
 
        pbm->devhandle = devhandle;
 
-       pbm->name = dp->full_name;
+       sprintf(pbm->name, "SUN4V-PCI%d PBM%c",
+               p->index, (pbm == &p->pbm_A ? 'A' : 'B'));
 
-       printk("%s: SUN4V PCI Bus Module\n", pbm->name);
+       printk("%s: devhandle[%x] prom_node[%x:%x]\n",
+              pbm->name, pbm->devhandle,
+              pbm->prom_node, prom_getchild(pbm->prom_node));
+
+       prom_getstring(prom_node, "name",
+                      pbm->prom_name, sizeof(pbm->prom_name));
+
+       err = prom_getproperty(prom_node, "ranges",
+                              (char *) pbm->pbm_ranges,
+                              sizeof(pbm->pbm_ranges));
+       if (err == 0 || err == -1) {
+               prom_printf("%s: Fatal error, no ranges property.\n",
+                           pbm->name);
+               prom_halt();
+       }
 
-       prop = of_find_property(dp, "ranges", &len);
-       pbm->pbm_ranges = prop->value;
        pbm->num_pbm_ranges =
-               (len / sizeof(struct linux_prom_pci_ranges));
+               (err / sizeof(struct linux_prom_pci_ranges));
 
        /* Mask out the top 8 bits of the ranges, leaving the real
         * physical address.
@@ -1111,13 +1152,24 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
        pci_sun4v_determine_mem_io_space(pbm);
        pbm_register_toplevel_resources(p, pbm);
 
-       prop = of_find_property(dp, "interrupt-map", &len);
-       pbm->pbm_intmap = prop->value;
-       pbm->num_pbm_intmap =
-               (len / sizeof(struct linux_prom_pci_intmap));
+       err = prom_getproperty(prom_node, "interrupt-map",
+                              (char *)pbm->pbm_intmap,
+                              sizeof(pbm->pbm_intmap));
+       if (err == 0 || err == -1) {
+               prom_printf("%s: Fatal error, no interrupt-map property.\n",
+                           pbm->name);
+               prom_halt();
+       }
 
-       prop = of_find_property(dp, "interrupt-map-mask", NULL);
-       pbm->pbm_intmask = prop->value;
+       pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
+       err = prom_getproperty(prom_node, "interrupt-map-mask",
+                              (char *)&pbm->pbm_intmask,
+                              sizeof(pbm->pbm_intmask));
+       if (err == 0 || err == -1) {
+               prom_printf("%s: Fatal error, no interrupt-map-mask.\n",
+                           pbm->name);
+               prom_halt();
+       }
 
        pci_sun4v_get_bus_range(pbm);
        pci_sun4v_iommu_init(pbm);
@@ -1125,19 +1177,16 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
        pdev_htab_populate(pbm);
 }
 
-void sun4v_pci_init(struct device_node *dp, char *model_name)
+void sun4v_pci_init(int node, char *model_name)
 {
        struct pci_controller_info *p;
        struct pci_iommu *iommu;
-       struct property *prop;
-       struct linux_prom64_registers *regs;
+       struct linux_prom64_registers regs;
        u32 devhandle;
        int i;
 
-       prop = of_find_property(dp, "reg", NULL);
-       regs = prop->value;
-
-       devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;
+       prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
+       devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff;
 
        for (p = pci_controller_root; p; p = p->next) {
                struct pci_pbm_info *pbm;
@@ -1150,7 +1199,7 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
                       &p->pbm_B);
 
                if (pbm->devhandle == (devhandle ^ 0x40)) {
-                       pci_sun4v_pbm_init(p, dp, devhandle);
+                       pci_sun4v_pbm_init(p, node, devhandle);
                        return;
                }
        }
@@ -1191,6 +1240,7 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
        p->pbms_same_domain = 0;
 
        p->scan_bus = pci_sun4v_scan_bus;
+       p->irq_build = pci_sun4v_irq_build;
        p->base_address_update = pci_sun4v_base_address_update;
        p->resource_adjust = pci_sun4v_resource_adjust;
        p->pci_ops = &pci_sun4v_ops;
@@ -1200,7 +1250,7 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
         */
        pci_memspace_mask = 0x7fffffffUL;
 
-       pci_sun4v_pbm_init(p, dp, devhandle);
+       pci_sun4v_pbm_init(p, node, devhandle);
        return;
 
 fatal_memory_error: