Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
[safe/jmp/linux-2.6] / arch / powerpc / kernel / prom_parse.c
index 3786dcc..8362620 100644 (file)
@@ -24,7 +24,7 @@
 /* Max address size we deal with */
 #define OF_MAX_ADDR_CELLS      4
 #define OF_CHECK_COUNTS(na, ns)        ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
-                       (ns) >= 0)
+                       (ns) > 0)
 
 static struct of_bus *of_match_bus(struct device_node *np);
 static int __of_address_to_resource(struct device_node *dev,
@@ -128,12 +128,35 @@ static void of_bus_pci_count_cells(struct device_node *np,
                *sizec = 2;
 }
 
+static unsigned int of_bus_pci_get_flags(const u32 *addr)
+{
+       unsigned int flags = 0;
+       u32 w = addr[0];
+
+       switch((w >> 24) & 0x03) {
+       case 0x01:
+               flags |= IORESOURCE_IO;
+               break;
+       case 0x02: /* 32 bits */
+       case 0x03: /* 64 bits */
+               flags |= IORESOURCE_MEM;
+               break;
+       }
+       if (w & 0x40000000)
+               flags |= IORESOURCE_PREFETCH;
+       return flags;
+}
+
 static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
 {
        u64 cp, s, da;
+       unsigned int af, rf;
+
+       af = of_bus_pci_get_flags(addr);
+       rf = of_bus_pci_get_flags(range);
 
        /* Check address type match */
-       if ((addr[0] ^ range[0]) & 0x03000000)
+       if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
                return OF_BAD_ADDR;
 
        /* Read address values, skipping high cell */
@@ -153,25 +176,6 @@ static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
        return of_bus_default_translate(addr + 1, offset, na - 1);
 }
 
-static unsigned int of_bus_pci_get_flags(const u32 *addr)
-{
-       unsigned int flags = 0;
-       u32 w = addr[0];
-
-       switch((w >> 24) & 0x03) {
-       case 0x01:
-               flags |= IORESOURCE_IO;
-               break;
-       case 0x02: /* 32 bits */
-       case 0x03: /* 64 bits */
-               flags |= IORESOURCE_MEM;
-               break;
-       }
-       if (w & 0x40000000)
-               flags |= IORESOURCE_PREFETCH;
-       return flags;
-}
-
 const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
                        unsigned int *flags)
 {
@@ -228,11 +232,6 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
 }
 EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
 
-static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
-{
-       return (((pin - 1) + slot) % 4) + 1;
-}
-
 int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
 {
        struct device_node *dn, *ppnode;
@@ -246,8 +245,11 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
         * parsing
         */
        dn = pci_device_to_OF_node(pdev);
-       if (dn)
-               return of_irq_map_one(dn, 0, out_irq);
+       if (dn) {
+               rc = of_irq_map_one(dn, 0, out_irq);
+               if (!rc)
+                       return rc;
+       }
 
        /* Ok, we don't, time to have fun. Let's start by building up an
         * interrupt spec.  we assume #interrupt-cells is 1, which is standard
@@ -273,7 +275,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
 #else
                        struct pci_controller *host;
                        host = pci_bus_to_host(pdev->bus);
-                       ppnode = host ? host->arch_data : NULL;
+                       ppnode = host ? host->dn : NULL;
 #endif
                        /* No node for host bridge ? give up */
                        if (ppnode == NULL)
@@ -299,7 +301,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
                /* We can only get here if we hit a P2P bridge with no node,
                 * let's do standard swizzling and try again
                 */
-               lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
+               lspec = pci_swizzle_interrupt_pin(pdev, lspec);
                pdev = ppdev;
        }
 
@@ -419,7 +421,7 @@ static struct of_bus *of_match_bus(struct device_node *np)
 
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
                            struct of_bus *pbus, u32 *addr,
-                           int na, int ns, int pna)
+                           int na, int ns, int pna, const char *rprop)
 {
        const u32 *ranges;
        unsigned int rlen;
@@ -438,7 +440,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
         * to translate addresses that aren't supposed to be translated in
         * the first place. --BenH.
         */
-       ranges = of_get_property(parent, "ranges", &rlen);
+       ranges = of_get_property(parent, rprop, &rlen);
        if (ranges == NULL || rlen == 0) {
                offset = of_read_number(addr, na);
                memset(addr, 0, pna * 4);
@@ -481,7 +483,8 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
  */
-u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
+u64 __of_translate_address(struct device_node *dev, const u32 *in_addr,
+                          const char *rprop)
 {
        struct device_node *parent = NULL;
        struct of_bus *bus, *pbus;
@@ -540,7 +543,7 @@ u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
                    pbus->name, pna, pns, parent->full_name);
 
                /* Apply bus translation */
-               if (of_translate_one(dev, bus, pbus, addr, na, ns, pna))
+               if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
                        break;
 
                /* Complete the move up one level */
@@ -556,8 +559,19 @@ u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
 
        return result;
 }
+
+u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
+{
+       return __of_translate_address(dev, in_addr, "ranges");
+}
 EXPORT_SYMBOL(of_translate_address);
 
+u64 of_translate_dma_address(struct device_node *dev, const u32 *in_addr)
+{
+       return __of_translate_address(dev, in_addr, "dma-ranges");
+}
+EXPORT_SYMBOL(of_translate_dma_address);
+
 const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
                    unsigned int *flags)
 {
@@ -715,10 +729,7 @@ void of_irq_map_init(unsigned int flags)
        if (flags & OF_IMAP_NO_PHANDLE) {
                struct device_node *np;
 
-               for(np = NULL; (np = of_find_all_nodes(np)) != NULL;) {
-                       if (of_get_property(np, "interrupt-controller", NULL)
-                           == NULL)
-                               continue;
+               for_each_node_with_property(np, "interrupt-controller") {
                        /* Skip /chosen/interrupt-controller */
                        if (strcmp(np->name, "chosen") == 0)
                                continue;
@@ -960,7 +971,7 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
        struct device_node *p;
        const u32 *intspec, *tmp, *addr;
        u32 intsize, intlen;
-       int res;
+       int res = -EINVAL;
 
        DBG("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index);
 
@@ -984,21 +995,20 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
 
        /* Get size of interrupt specifier */
        tmp = of_get_property(p, "#interrupt-cells", NULL);
-       if (tmp == NULL) {
-               of_node_put(p);
-               return -EINVAL;
-       }
+       if (tmp == NULL)
+               goto out;
        intsize = *tmp;
 
        DBG(" intsize=%d intlen=%d\n", intsize, intlen);
 
        /* Check index */
        if ((index + 1) * intsize > intlen)
-               return -EINVAL;
+               goto out;
 
        /* Get new specifier and map it */
        res = of_irq_map_raw(p, intspec + index * intsize, intsize,
                             addr, out_irq);
+out:
        of_node_put(p);
        return res;
 }