tree 67d5a4d4c7af00ac4be4608092fec99a32683715
parent b28d2582ce8aafe531d909bb9c4dcf29189e786e
author Paul Mackerras <[EMAIL PROTECTED]> Tue, 06 Sep 2005 13:17:54 +1000
committer Paul Mackerras <[EMAIL PROTECTED]> Fri, 09 Sep 2005 22:11:38 +1000

[PATCH] Separate pci bits out of struct device_node

This patch pulls the PCI-related junk out of struct device_node and
puts it in a separate structure, struct pci_dn.  The device_node now
just has a void * pointer in it, which points to a struct pci_dn for
nodes that represent PCI devices.  It could potentially be used in
future for device-specific data for other sorts of devices, such as
virtual I/O devices.

Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]>

 arch/ppc64/kernel/eeh.c             |   55 ++++++++++++++++-----------
 arch/ppc64/kernel/iommu.c           |    3 +
 arch/ppc64/kernel/maple_pci.c       |    4 +-
 arch/ppc64/kernel/pSeries_iommu.c   |   72 ++++++++++++++++++++----------------
 arch/ppc64/kernel/pci.c             |    6 ++-
 arch/ppc64/kernel/pci.h             |    1 
 arch/ppc64/kernel/pci_dn.c          |   45 ++++++++++++++++------
 arch/ppc64/kernel/pci_iommu.c       |    2 -
 arch/ppc64/kernel/pmac_feature.c    |    8 ++--
 arch/ppc64/kernel/pmac_pci.c        |    6 +--
 arch/ppc64/kernel/prom.c            |    1 
 arch/ppc64/kernel/rtas_pci.c        |   39 +++++++++++--------
 arch/ppc64/kernel/sys_ppc32.c       |    4 +-
 arch/ppc64/kernel/u3_iommu.c        |    4 +-
 drivers/pci/hotplug/rpadlpar_core.c |   20 ++++++----
 drivers/pci/hotplug/rpaphp_pci.c    |    8 ++--
 drivers/video/offb.c                |    2 -
 include/asm-ppc64/pci-bridge.h      |   45 +++++++++++++++++++---
 include/asm-ppc64/prom.h            |   19 ---------
 19 files changed, 208 insertions(+), 136 deletions(-)

diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
--- a/arch/ppc64/kernel/eeh.c
+++ b/arch/ppc64/kernel/eeh.c
@@ -254,6 +254,7 @@ pci_addr_cache_insert(struct pci_dev *de
 static void __pci_addr_cache_insert_device(struct pci_dev *dev)
 {
        struct device_node *dn;
+       struct pci_dn *pdn;
        int i;
        int inserted = 0;
 
@@ -265,8 +266,9 @@ static void __pci_addr_cache_insert_devi
        }
 
        /* Skip any devices for which EEH is not enabled. */
-       if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
-           dn->eeh_mode & EEH_MODE_NOCHECK) {
+       pdn = dn->data;
+       if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
+           pdn->eeh_mode & EEH_MODE_NOCHECK) {
 #ifdef DEBUG
                printk(KERN_INFO "PCI: skip building address cache for=%s\n",
                       pci_name(dev));
@@ -415,6 +417,7 @@ int eeh_unregister_notifier(struct notif
 static int read_slot_reset_state(struct device_node *dn, int rets[])
 {
        int token, outputs;
+       struct pci_dn *pdn = dn->data;
 
        if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
                token = ibm_read_slot_reset_state2;
@@ -424,8 +427,8 @@ static int read_slot_reset_state(struct 
                outputs = 3;
        }
 
-       return rtas_call(token, 3, outputs, rets, dn->eeh_config_addr,
-                        BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid));
+       return rtas_call(token, 3, outputs, rets, pdn->eeh_config_addr,
+                        BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));
 }
 
 /**
@@ -534,6 +537,7 @@ int eeh_dn_check_failure(struct device_n
        unsigned long flags;
        int rc, reset_state;
        struct eeh_event  *event;
+       struct pci_dn *pdn;
 
        __get_cpu_var(total_mmio_ffs)++;
 
@@ -542,14 +546,15 @@ int eeh_dn_check_failure(struct device_n
 
        if (!dn)
                return 0;
+       pdn = dn->data;
 
        /* Access to IO BARs might get this far and still not want checking. */
-       if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
-           dn->eeh_mode & EEH_MODE_NOCHECK) {
+       if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
+           pdn->eeh_mode & EEH_MODE_NOCHECK) {
                return 0;
        }
 
-       if (!dn->eeh_config_addr) {
+       if (!pdn->eeh_config_addr) {
                return 0;
        }
 
@@ -557,7 +562,7 @@ int eeh_dn_check_failure(struct device_n
         * If we already have a pending isolation event for this
         * slot, we know it's bad already, we don't need to check...
         */
-       if (dn->eeh_mode & EEH_MODE_ISOLATED) {
+       if (pdn->eeh_mode & EEH_MODE_ISOLATED) {
                atomic_inc(&eeh_fail_count);
                if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) {
                        /* re-read the slot reset state */
@@ -582,7 +587,7 @@ int eeh_dn_check_failure(struct device_n
        }
 
        /* prevent repeated reports of this failure */
-       dn->eeh_mode |= EEH_MODE_ISOLATED;
+       pdn->eeh_mode |= EEH_MODE_ISOLATED;
 
        reset_state = rets[0];
 
@@ -590,9 +595,9 @@ int eeh_dn_check_failure(struct device_n
        memset(slot_errbuf, 0, eeh_error_buf_size);
 
        rc = rtas_call(ibm_slot_error_detail,
-                      8, 1, NULL, dn->eeh_config_addr,
-                      BUID_HI(dn->phb->buid),
-                      BUID_LO(dn->phb->buid), NULL, 0,
+                      8, 1, NULL, pdn->eeh_config_addr,
+                      BUID_HI(pdn->phb->buid),
+                      BUID_LO(pdn->phb->buid), NULL, 0,
                       virt_to_phys(slot_errbuf),
                       eeh_error_buf_size,
                       1 /* Temporary Error */);
@@ -679,8 +684,9 @@ static void *early_enable_eeh(struct dev
        u32 *device_id = (u32 *)get_property(dn, "device-id", NULL);
        u32 *regs;
        int enable;
+       struct pci_dn *pdn = dn->data;
 
-       dn->eeh_mode = 0;
+       pdn->eeh_mode = 0;
 
        if (status && strcmp(status, "ok") != 0)
                return NULL;    /* ignore devices with bad status */
@@ -691,7 +697,7 @@ static void *early_enable_eeh(struct dev
 
        /* There is nothing to check on PCI to ISA bridges */
        if (dn->type && !strcmp(dn->type, "isa")) {
-               dn->eeh_mode |= EEH_MODE_NOCHECK;
+               pdn->eeh_mode |= EEH_MODE_NOCHECK;
                return NULL;
        }
 
@@ -708,7 +714,7 @@ static void *early_enable_eeh(struct dev
                enable = 0;
 
        if (!enable)
-               dn->eeh_mode |= EEH_MODE_NOCHECK;
+               pdn->eeh_mode |= EEH_MODE_NOCHECK;
 
        /* Ok... see if this device supports EEH.  Some do, some don't,
         * and the only way to find out is to check each and every one. */
@@ -721,8 +727,8 @@ static void *early_enable_eeh(struct dev
                                EEH_ENABLE);
                if (ret == 0) {
                        eeh_subsystem_enabled = 1;
-                       dn->eeh_mode |= EEH_MODE_SUPPORTED;
-                       dn->eeh_config_addr = regs[0];
+                       pdn->eeh_mode |= EEH_MODE_SUPPORTED;
+                       pdn->eeh_config_addr = regs[0];
 #ifdef DEBUG
                        printk(KERN_DEBUG "EEH: %s: eeh enabled\n", 
dn->full_name);
 #endif
@@ -730,10 +736,11 @@ static void *early_enable_eeh(struct dev
 
                        /* This device doesn't support EEH, but it may have an
                         * EEH parent, in which case we mark it as supported. */
-                       if (dn->parent && (dn->parent->eeh_mode & 
EEH_MODE_SUPPORTED)) {
+                       if (dn->parent && dn->parent->data
+                           && (PCI_DN(dn->parent)->eeh_mode & 
EEH_MODE_SUPPORTED)) {
                                /* Parent supports EEH. */
-                               dn->eeh_mode |= EEH_MODE_SUPPORTED;
-                               dn->eeh_config_addr = 
dn->parent->eeh_config_addr;
+                               pdn->eeh_mode |= EEH_MODE_SUPPORTED;
+                               pdn->eeh_config_addr = 
PCI_DN(dn->parent)->eeh_config_addr;
                                return NULL;
                        }
                }
@@ -790,11 +797,13 @@ void __init eeh_init(void)
        for (phb = of_find_node_by_name(NULL, "pci"); phb;
             phb = of_find_node_by_name(phb, "pci")) {
                unsigned long buid;
+               struct pci_dn *pci;
 
                buid = get_phb_buid(phb);
-               if (buid == 0)
+               if (buid == 0 || phb->data == NULL)
                        continue;
 
+               pci = phb->data;
                info.buid_lo = BUID_LO(buid);
                info.buid_hi = BUID_HI(buid);
                traverse_pci_devices(phb, early_enable_eeh, &info);
@@ -823,9 +832,9 @@ void eeh_add_device_early(struct device_
        struct pci_controller *phb;
        struct eeh_early_enable_info info;
 
-       if (!dn)
+       if (!dn || !dn->data)
                return;
-       phb = dn->phb;
+       phb = PCI_DN(dn)->phb;
        if (NULL == phb || 0 == phb->buid) {
                printk(KERN_WARNING "EEH: Expected buid but found none\n");
                return;
diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
--- a/arch/ppc64/kernel/iommu.c
+++ b/arch/ppc64/kernel/iommu.c
@@ -438,7 +438,8 @@ struct iommu_table *iommu_init_table(str
 
 void iommu_free_table(struct device_node *dn)
 {
-       struct iommu_table *tbl = dn->iommu_table;
+       struct pci_dn *pdn = dn->data;
+       struct iommu_table *tbl = pdn->iommu_table;
        unsigned long bitmap_sz, i;
        unsigned int order;
 
diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c
--- a/arch/ppc64/kernel/maple_pci.c
+++ b/arch/ppc64/kernel/maple_pci.c
@@ -447,9 +447,9 @@ void __init maple_pci_init(void)
         */
        if (u3_agp) {
                struct device_node *np = u3_agp->arch_data;
-               np->busno = 0xf0;
+               PCI_DN(np)->busno = 0xf0;
                for (np = np->child; np; np = np->sibling)
-                       np->busno = 0xf0;
+                       PCI_DN(np)->busno = 0xf0;
        }
 
        /* Tell pci.c to use the common resource allocation mecanism */
diff --git a/arch/ppc64/kernel/pSeries_iommu.c 
b/arch/ppc64/kernel/pSeries_iommu.c
--- a/arch/ppc64/kernel/pSeries_iommu.c
+++ b/arch/ppc64/kernel/pSeries_iommu.c
@@ -295,7 +295,7 @@ static void iommu_table_setparms_lpar(st
                                      struct iommu_table *tbl,
                                      unsigned int *dma_window)
 {
-       tbl->it_busno  = dn->bussubno;
+       tbl->it_busno  = PCI_DN(dn)->bussubno;
 
        /* TODO: Parse field size properties properly. */
        tbl->it_size   = (((unsigned long)dma_window[4] << 32) |
@@ -311,6 +311,7 @@ static void iommu_table_setparms_lpar(st
 static void iommu_bus_setup_pSeries(struct pci_bus *bus)
 {
        struct device_node *dn, *pdn;
+       struct pci_dn *pci;
        struct iommu_table *tbl;
 
        DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self);
@@ -325,6 +326,7 @@ static void iommu_bus_setup_pSeries(stru
         */
 
        dn = pci_bus_to_OF_node(bus);
+       pci = dn->data;
 
        if (!bus->self) {
                /* Root bus */
@@ -341,18 +343,18 @@ static void iommu_bus_setup_pSeries(stru
                                 * alltogether. This leaves 768MB for the 
window.
                                 */
                                DBG("PHB has io-hole, reserving 256MB\n");
-                               dn->phb->dma_window_size = 3 << 28;
-                               dn->phb->dma_window_base_cur = 1 << 28;
+                               pci->phb->dma_window_size = 3 << 28;
+                               pci->phb->dma_window_base_cur = 1 << 28;
                        } else {
                                /* 1GB window by default */
-                               dn->phb->dma_window_size = 1 << 30;
-                               dn->phb->dma_window_base_cur = 0;
+                               pci->phb->dma_window_size = 1 << 30;
+                               pci->phb->dma_window_base_cur = 0;
                        }
 
                        tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
-                       iommu_table_setparms(dn->phb, dn, tbl);
-                       dn->iommu_table = iommu_init_table(tbl);
+                       iommu_table_setparms(pci->phb, dn, tbl);
+                       pci->iommu_table = iommu_init_table(tbl);
                } else {
                        /* Do a 128MB table at root. This is used for the IDE
                         * controller on some SMP-mode POWER4 machines. It
@@ -363,16 +365,16 @@ static void iommu_bus_setup_pSeries(stru
                         * Allocate at offset 128MB to avoid having to deal
                         * with ISA holes; 128MB table for IDE is plenty.
                         */
-                       dn->phb->dma_window_size = 1 << 27;
-                       dn->phb->dma_window_base_cur = 1 << 27;
+                       pci->phb->dma_window_size = 1 << 27;
+                       pci->phb->dma_window_base_cur = 1 << 27;
 
                        tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
-                       iommu_table_setparms(dn->phb, dn, tbl);
-                       dn->iommu_table = iommu_init_table(tbl);
+                       iommu_table_setparms(pci->phb, dn, tbl);
+                       pci->iommu_table = iommu_init_table(tbl);
 
                        /* All child buses have 256MB tables */
-                       dn->phb->dma_window_size = 1 << 28;
+                       pci->phb->dma_window_size = 1 << 28;
                }
        } else {
                pdn = pci_bus_to_OF_node(bus->parent);
@@ -386,12 +388,12 @@ static void iommu_bus_setup_pSeries(stru
 
                        tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
-                       iommu_table_setparms(dn->phb, dn, tbl);
+                       iommu_table_setparms(pci->phb, dn, tbl);
 
-                       dn->iommu_table = iommu_init_table(tbl);
+                       pci->iommu_table = iommu_init_table(tbl);
                } else {
                        /* Lower than first child or under python, use parent 
table */
-                       dn->iommu_table = pdn->iommu_table;
+                       pci->iommu_table = PCI_DN(pdn)->iommu_table;
                }
        }
 }
@@ -401,6 +403,7 @@ static void iommu_bus_setup_pSeriesLP(st
 {
        struct iommu_table *tbl;
        struct device_node *dn, *pdn;
+       struct pci_dn *ppci;
        unsigned int *dma_window = NULL;
 
        DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, 
bus->self);
@@ -419,22 +422,24 @@ static void iommu_bus_setup_pSeriesLP(st
                return;
        }
 
-       if (!pdn->iommu_table) {
+       ppci = pdn->data;
+       if (!ppci->iommu_table) {
                /* Bussubno hasn't been copied yet.
                 * Do it now because iommu_table_setparms_lpar needs it.
                 */
-               pdn->bussubno = bus->number;
+
+               ppci->bussubno = bus->number;
 
                tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
                                                    GFP_KERNEL);
        
-               iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window);
+               iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
 
-               pdn->iommu_table = iommu_init_table(tbl);
+               ppci->iommu_table = iommu_init_table(tbl);
        }
 
        if (pdn != dn)
-               dn->iommu_table = pdn->iommu_table;
+               PCI_DN(dn)->iommu_table = ppci->iommu_table;
 }
 
 
@@ -449,11 +454,11 @@ static void iommu_dev_setup_pSeries(stru
         */
        mydn = dn = pci_device_to_OF_node(dev);
 
-       while (dn && dn->iommu_table == NULL)
+       while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL)
                dn = dn->parent;
 
-       if (dn) {
-               mydn->iommu_table = dn->iommu_table;
+       if (dn && dn->data) {
+               PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table;
        } else {
                DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu 
table\n", dev, dev->pretty_name);
        }
@@ -463,10 +468,11 @@ static int iommu_reconfig_notifier(struc
 {
        int err = NOTIFY_OK;
        struct device_node *np = node;
+       struct pci_dn *pci = np->data;
 
        switch (action) {
        case PSERIES_RECONFIG_REMOVE:
-               if (np->iommu_table &&
+               if (pci->iommu_table &&
                    get_property(np, "ibm,dma-window", NULL))
                        iommu_free_table(np);
                break;
@@ -486,6 +492,7 @@ static void iommu_dev_setup_pSeriesLP(st
        struct device_node *pdn, *dn;
        struct iommu_table *tbl;
        int *dma_window = NULL;
+       struct pci_dn *pci;
 
        DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name);
 
@@ -497,8 +504,10 @@ static void iommu_dev_setup_pSeriesLP(st
         */
        dn = pci_device_to_OF_node(dev);
 
-       for (pdn = dn; pdn && !pdn->iommu_table; pdn = pdn->parent) {
-               dma_window = (unsigned int *)get_property(pdn, 
"ibm,dma-window", NULL);
+       for (pdn = dn; pdn && pdn->data && !PCI_DN(pdn)->iommu_table;
+            pdn = pdn->parent) {
+               dma_window = (unsigned int *)
+                       get_property(pdn, "ibm,dma-window", NULL);
                if (dma_window)
                        break;
        }
@@ -515,20 +524,21 @@ static void iommu_dev_setup_pSeriesLP(st
                DBG("Found DMA window, allocating table\n");
        }
 
-       if (!pdn->iommu_table) {
+       pci = pdn->data;
+       if (!pci->iommu_table) {
                /* iommu_table_setparms_lpar needs bussubno. */
-               pdn->bussubno = pdn->phb->bus->number;
+               pci->bussubno = pci->phb->bus->number;
 
                tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
                                                    GFP_KERNEL);
 
-               iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window);
+               iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
 
-               pdn->iommu_table = iommu_init_table(tbl);
+               pci->iommu_table = iommu_init_table(tbl);
        }
 
        if (pdn != dn)
-               dn->iommu_table = pdn->iommu_table;
+               PCI_DN(dn)->iommu_table = pci->iommu_table;
 }
 
 static void iommu_bus_setup_null(struct pci_bus *b) { }
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -837,9 +837,11 @@ int pcibios_scan_all_fns(struct pci_bus 
         * device tree.  If they are then we need to scan all the
         * functions of this slot.
         */
-       for (dn = busdn->child; dn; dn = dn->sibling)
-               if ((dn->devfn >> 3) == (devfn >> 3))
+       for (dn = busdn->child; dn; dn = dn->sibling) {
+              struct pci_dn *pdn = dn->data;
+              if (pdn && (pdn->devfn >> 3) == (devfn >> 3))
                        return 1;
+       }
 
        return 0;
 }
diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
--- a/arch/ppc64/kernel/pci.h
+++ b/arch/ppc64/kernel/pci.h
@@ -34,7 +34,6 @@ void *traverse_pci_devices(struct device
 
 void pci_devs_phb_init(void);
 void pci_devs_phb_init_dynamic(struct pci_controller *phb);
-struct device_node *fetch_dev_dn(struct pci_dev *dev);
 
 /* PCI address cache management routines */
 void pci_addr_cache_insert_device(struct pci_dev *dev);
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c
--- a/arch/ppc64/kernel/pci_dn.c
+++ b/arch/ppc64/kernel/pci_dn.c
@@ -23,6 +23,8 @@
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
 
 #include <asm/io.h>
 #include <asm/prom.h>
@@ -40,16 +42,26 @@ static void * __devinit update_dn_pci_in
        struct pci_controller *phb = data;
        int *type = (int *)get_property(dn, "ibm,pci-config-space-type", NULL);
        u32 *regs;
+       struct pci_dn *pdn;
 
-       dn->phb = phb;
+       if (phb->is_dynamic)
+               pdn = kmalloc(sizeof(*pdn), GFP_KERNEL);
+       else
+               pdn = alloc_bootmem(sizeof(*pdn));
+       if (pdn == NULL)
+               return NULL;
+       memset(pdn, 0, sizeof(*pdn));
+       dn->data = pdn;
+       pdn->node = dn;
+       pdn->phb = phb;
        regs = (u32 *)get_property(dn, "reg", NULL);
        if (regs) {
                /* First register entry is addr (00BBSS00)  */
-               dn->busno = (regs[0] >> 16) & 0xff;
-               dn->devfn = (regs[0] >> 8) & 0xff;
+               pdn->busno = (regs[0] >> 16) & 0xff;
+               pdn->devfn = (regs[0] >> 8) & 0xff;
        }
 
-       dn->pci_ext_config_space = (type && *type == 1);
+       pdn->pci_ext_config_space = (type && *type == 1);
        return NULL;
 }
 
@@ -112,10 +124,15 @@ void *traverse_pci_devices(struct device
 void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
 {
        struct device_node * dn = (struct device_node *) phb->arch_data;
+       struct pci_dn *pdn;
 
        /* PHB nodes themselves must not match */
-       dn->devfn = dn->busno = -1;
-       dn->phb = phb;
+       update_dn_pci_info(dn, phb);
+       pdn = dn->data;
+       if (pdn) {
+               pdn->devfn = pdn->busno = -1;
+               pdn->phb = phb;
+       }
 
        /* Update dn->phb ptrs for new phb and children devices */
        traverse_pci_devices(dn, update_dn_pci_info, phb);
@@ -123,14 +140,17 @@ void __devinit pci_devs_phb_init_dynamic
 
 /*
  * Traversal func that looks for a <busno,devfcn> value.
- * If found, the device_node is returned (thus terminating the traversal).
+ * If found, the pci_dn is returned (thus terminating the traversal).
  */
 static void *is_devfn_node(struct device_node *dn, void *data)
 {
        int busno = ((unsigned long)data >> 8) & 0xff;
        int devfn = ((unsigned long)data) & 0xff;
+       struct pci_dn *pci = dn->data;
 
-       return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL;
+       if (pci && (devfn == pci->devfn) && (busno == pci->busno))
+               return dn;
+       return NULL;
 }
 
 /*
@@ -149,13 +169,10 @@ static void *is_devfn_node(struct device
 struct device_node *fetch_dev_dn(struct pci_dev *dev)
 {
        struct device_node *orig_dn = dev->sysdata;
-       struct pci_controller *phb = orig_dn->phb; /* assume same phb as 
orig_dn */
-       struct device_node *phb_dn;
        struct device_node *dn;
        unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
 
-       phb_dn = phb->arch_data;
-       dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval);
+       dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval);
        if (dn)
                dev->sysdata = dn;
        return dn;
@@ -165,11 +182,13 @@ EXPORT_SYMBOL(fetch_dev_dn);
 static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long 
action, void *node)
 {
        struct device_node *np = node;
+       struct pci_dn *pci;
        int err = NOTIFY_OK;
 
        switch (action) {
        case PSERIES_RECONFIG_ADD:
-               update_dn_pci_info(np, np->parent->phb);
+               pci = np->parent->data;
+               update_dn_pci_info(np, pci->phb);
                break;
        default:
                err = NOTIFY_DONE;
diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c
--- a/arch/ppc64/kernel/pci_iommu.c
+++ b/arch/ppc64/kernel/pci_iommu.c
@@ -66,7 +66,7 @@ static inline struct iommu_table *devnod
 #endif /* CONFIG_PPC_ISERIES */
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
-       return PCI_GET_DN(pdev)->iommu_table;
+       return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
 #endif /* CONFIG_PPC_MULTIPLATFORM */
 }
 
diff --git a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c
--- a/arch/ppc64/kernel/pmac_feature.c
+++ b/arch/ppc64/kernel/pmac_feature.c
@@ -674,6 +674,7 @@ void __init pmac_check_ht_link(void)
 #if 0 /* Disabled for now */
        u32     ufreq, freq, ucfg, cfg;
        struct device_node *pcix_node;
+       struct pci_dn *pdn;
        u8      px_bus, px_devfn;
        struct pci_controller *px_hose;
 
@@ -687,9 +688,10 @@ void __init pmac_check_ht_link(void)
                printk("No PCI-X bridge found\n");
                return;
        }
-       px_hose = pcix_node->phb;
-       px_bus = pcix_node->busno;
-       px_devfn = pcix_node->devfn;
+       pdn = pcix_node->data;
+       px_hose = pdn->phb;
+       px_bus = pdn->busno;
+       px_devfn = pdn->devfn;
        
        early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
        early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c
--- a/arch/ppc64/kernel/pmac_pci.c
+++ b/arch/ppc64/kernel/pmac_pci.c
@@ -242,7 +242,7 @@ static int u3_ht_skip_device(struct pci_
        else
                busdn = hose->arch_data;
        for (dn = busdn->child; dn; dn = dn->sibling)
-               if (dn->devfn == devfn)
+               if (dn->data && PCI_DN(dn)->devfn == devfn)
                        break;
        if (dn == NULL)
                return -1;
@@ -746,9 +746,9 @@ void __init pmac_pci_init(void)
         */
        if (u3_agp) {
                struct device_node *np = u3_agp->arch_data;
-               np->busno = 0xf0;
+               PCI_DN(np)->busno = 0xf0;
                for (np = np->child; np; np = np->sibling)
-                       np->busno = 0xf0;
+                       PCI_DN(np)->busno = 0xf0;
        }
 
        pmac_check_ht_link();
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -1733,6 +1733,7 @@ static void of_node_release(struct kref 
        kfree(node->intrs);
        kfree(node->addrs);
        kfree(node->full_name);
+       kfree(node->data);
        kfree(node);
 }
 
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c
--- a/arch/ppc64/kernel/rtas_pci.c
+++ b/arch/ppc64/kernel/rtas_pci.c
@@ -48,7 +48,7 @@ static int write_pci_config;
 static int ibm_read_pci_config;
 static int ibm_write_pci_config;
 
-static int config_access_valid(struct device_node *dn, int where)
+static int config_access_valid(struct pci_dn *dn, int where)
 {
        if (where < 256)
                return 1;
@@ -78,15 +78,17 @@ static int rtas_read_config(struct devic
        int returnval = -1;
        unsigned long buid, addr;
        int ret;
+       struct pci_dn *pdn;
 
-       if (!dn)
+       if (!dn || !dn->data)
                return PCIBIOS_DEVICE_NOT_FOUND;
-       if (!config_access_valid(dn, where))
+       pdn = dn->data;
+       if (!config_access_valid(pdn, where))
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
-       addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
-               (dn->devfn << 8) | (where & 0xff);
-       buid = dn->phb->buid;
+       addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
+               (pdn->devfn << 8) | (where & 0xff);
+       buid = pdn->phb->buid;
        if (buid) {
                ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
                                addr, buid >> 32, buid & 0xffffffff, size);
@@ -98,8 +100,8 @@ static int rtas_read_config(struct devic
        if (ret)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
-       if (returnval == EEH_IO_ERROR_VALUE(size)
-           && eeh_dn_check_failure (dn, NULL))
+       if (returnval == EEH_IO_ERROR_VALUE(size) &&
+           eeh_dn_check_failure (dn, NULL))
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        return PCIBIOS_SUCCESSFUL;
@@ -118,24 +120,28 @@ static int rtas_pci_read_config(struct p
 
        /* Search only direct children of the bus */
        for (dn = busdn->child; dn; dn = dn->sibling)
-               if (dn->devfn == devfn && of_device_available(dn))
+               if (dn->data && PCI_DN(dn)->devfn == devfn
+                   && of_device_available(dn))
                        return rtas_read_config(dn, where, size, val);
+
        return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-static int rtas_write_config(struct device_node *dn, int where, int size, u32 
val)
+int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
 {
        unsigned long buid, addr;
        int ret;
+       struct pci_dn *pdn;
 
-       if (!dn)
+       if (!dn || !dn->data)
                return PCIBIOS_DEVICE_NOT_FOUND;
-       if (!config_access_valid(dn, where))
+       pdn = dn->data;
+       if (!config_access_valid(pdn, where))
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
-       addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
-               (dn->devfn << 8) | (where & 0xff);
-       buid = dn->phb->buid;
+       addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
+               (pdn->devfn << 8) | (where & 0xff);
+       buid = pdn->phb->buid;
        if (buid) {
                ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 
32, buid & 0xffffffff, size, (ulong) val);
        } else {
@@ -161,7 +167,8 @@ static int rtas_pci_write_config(struct 
 
        /* Search only direct children of the bus */
        for (dn = busdn->child; dn; dn = dn->sibling)
-               if (dn->devfn == devfn && of_device_available(dn))
+               if (dn->data && PCI_DN(dn)->devfn == devfn
+                   && of_device_available(dn))
                        return rtas_write_config(dn, where, size, val);
        return PCIBIOS_DEVICE_NOT_FOUND;
 }
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -747,8 +747,8 @@ asmlinkage int sys32_pciconfig_iobase(u3
        if (bus == NULL || bus->sysdata == NULL)
                return -ENODEV;
 
-       hose_node = (struct device_node *)bus->sysdata;
-       hose = hose_node->phb;
+       hose_node = bus->sysdata;
+       hose = PCI_DN(hose_node)->phb;
 
        switch (which) {
        case IOBASE_BRIDGE_NUMBER:
diff --git a/arch/ppc64/kernel/u3_iommu.c b/arch/ppc64/kernel/u3_iommu.c
--- a/arch/ppc64/kernel/u3_iommu.c
+++ b/arch/ppc64/kernel/u3_iommu.c
@@ -276,7 +276,7 @@ static void iommu_dev_setup_u3(struct pc
        dn = pci_device_to_OF_node(dev);
 
        if (dn)
-               dn->iommu_table = &iommu_table_u3;
+               PCI_DN(dn)->iommu_table = &iommu_table_u3;
 }
 
 static void iommu_bus_setup_u3(struct pci_bus *bus)
@@ -291,7 +291,7 @@ static void iommu_bus_setup_u3(struct pc
        dn = pci_bus_to_OF_node(bus);
 
        if (dn)
-               dn->iommu_table = &iommu_table_u3;
+               PCI_DN(dn)->iommu_table = &iommu_table_u3;
 }
 
 static void iommu_dev_setup_null(struct pci_dev *dev) { }
diff --git a/drivers/pci/hotplug/rpadlpar_core.c 
b/drivers/pci/hotplug/rpadlpar_core.c
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -134,7 +134,8 @@ static void rpadlpar_claim_one_bus(struc
 static int pci_add_secondary_bus(struct device_node *dn,
                struct pci_dev *bridge_dev)
 {
-       struct pci_controller *hose = dn->phb;
+       struct pci_dn *pdn = dn->data;
+       struct pci_controller *hose = pdn->phb;
        struct pci_bus *child;
        u8 sec_busno;
 
@@ -159,7 +160,7 @@ static int pci_add_secondary_bus(struct 
        if (hose->last_busno < child->number)
                hose->last_busno = child->number;
 
-       dn->bussubno = child->number;
+       pdn->bussubno = child->number;
 
        /* ioremap() for child bus, which may or may not succeed */
        remap_bus_range(child);
@@ -183,11 +184,12 @@ static struct pci_dev *dlpar_find_new_de
 
 static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
 {
-       struct pci_controller *hose = dn->phb;
+       struct pci_dn *pdn = dn->data;
+       struct pci_controller *hose = pdn->phb;
        struct pci_dev *dev = NULL;
 
        /* Scan phb bus for EADS device, adding new one to bus->devices */
-       if (!pci_scan_single_device(hose->bus, dn->devfn)) {
+       if (!pci_scan_single_device(hose->bus, pdn->devfn)) {
                printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__);
                return NULL;
        }
@@ -269,6 +271,7 @@ static int dlpar_remove_root_bus(struct 
 static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
 {
        struct slot *slot;
+       struct pci_dn *pdn;
        int rc = 0;
 
        if (!rpaphp_find_pci_bus(dn))
@@ -285,12 +288,13 @@ static int dlpar_remove_phb(char *drc_na
                }
        }
 
-       BUG_ON(!dn->phb);
-       rc = dlpar_remove_root_bus(dn->phb);
+       pdn = dn->data;
+       BUG_ON(!pdn || !pdn->phb);
+       rc = dlpar_remove_root_bus(pdn->phb);
        if (rc < 0)
                return rc;
 
-       dn->phb = NULL;
+       pdn->phb = NULL;
 
        return 0;
 }
@@ -299,7 +303,7 @@ static int dlpar_add_phb(char *drc_name,
 {
        struct pci_controller *phb;
 
-       if (dn->phb) {
+       if (PCI_DN(dn)->phb) {
                /* PHB already exists */
                return -EINVAL;
        }
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -51,10 +51,12 @@ static struct pci_bus *find_bus_among_ch
 
 struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
 {
-       if (!dn->phb || !dn->phb->bus)
+       struct pci_dn *pdn = dn->data;
+
+       if (!pdn  || !pdn->phb || !pdn->phb->bus)
                return NULL;
 
-       return find_bus_among_children(dn->phb->bus, dn);
+       return find_bus_among_children(pdn->phb->bus, dn);
 }
 EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
 
@@ -229,7 +231,7 @@ rpaphp_pci_config_slot(struct pci_bus *b
        if (!dn || !dn->child)
                return NULL;
 
-       slotno = PCI_SLOT(dn->child->devfn);
+       slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
 
        /* pci_scan_slot should find all children */
        num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -363,7 +363,7 @@ static void __init offb_init_nodriver(st
                address = (u_long) dp->addrs[i].address;
 
 #ifdef CONFIG_PPC64
-               address += dp->phb->pci_mem_offset;
+               address += ((struct pci_dn *)dp->data)->phb->pci_mem_offset;
 #endif
 
                /* kludge for valkyrie */
diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
--- a/include/asm-ppc64/pci-bridge.h
+++ b/include/asm-ppc64/pci-bridge.h
@@ -48,19 +48,52 @@ struct pci_controller {
        unsigned long dma_window_size;
 };
 
+/*
+ * PCI stuff, for nodes representing PCI devices, pointed to
+ * by device_node->data.
+ */
+struct pci_controller;
+struct iommu_table;
+
+struct pci_dn {
+       int     busno;                  /* for pci devices */
+       int     bussubno;               /* for pci devices */
+       int     devfn;                  /* for pci devices */
+       int     eeh_mode;               /* See eeh.h for possible EEH_MODEs */
+       int     eeh_config_addr;
+       int     eeh_capable;            /* from firmware */
+       int     eeh_check_count;        /* # times driver ignored error */
+       int     eeh_freeze_count;       /* # times this device froze up. */
+       int     eeh_is_bridge;          /* device is pci-to-pci bridge */
+
+       int     pci_ext_config_space;   /* for pci devices */
+       struct  pci_controller *phb;    /* for pci devices */
+       struct  iommu_table *iommu_table;       /* for phb's or bridges */
+       struct  pci_dev *pcidev;        /* back-pointer to the pci device */
+       struct  device_node *node;      /* back-pointer to the device_node */
+       u32     config_space[16];       /* saved PCI config space */
+};
+
+/* Get the pointer to a device_node's pci_dn */
+#define PCI_DN(dn)     ((struct pci_dn *) (dn)->data)
+
 struct device_node *fetch_dev_dn(struct pci_dev *dev);
 
-/* Get a device_node from a pci_dev.  This code must be fast except in the case
- * where the sysdata is incorrect and needs to be fixed up (hopefully just 
once)
+/* Get a device_node from a pci_dev.  This code must be fast except
+ * in the case where the sysdata is incorrect and needs to be fixed
+ * up (this will only happen once).
+ * In this case the sysdata will have been inherited from a PCI host
+ * bridge or a PCI-PCI bridge further up the tree, so it will point
+ * to a valid struct pci_dn, just not the one we want.
  */
 static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
 {
        struct device_node *dn = dev->sysdata;
+       struct pci_dn *pdn = dn->data;
 
-       if (dn->devfn == dev->devfn && dn->busno == dev->bus->number)
+       if (pdn && pdn->devfn == dev->devfn && pdn->busno == dev->bus->number)
                return dn;      /* fast path.  sysdata is good */
-       else
-               return fetch_dev_dn(dev);
+       return fetch_dev_dn(dev);
 }
 
 static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
@@ -83,7 +116,7 @@ static inline struct pci_controller *pci
        struct device_node *busdn = bus->sysdata;
 
        BUG_ON(busdn == NULL);
-       return busdn->phb;
+       return PCI_DN(busdn)->phb;
 }
 
 #endif
diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h
--- a/include/asm-ppc64/prom.h
+++ b/include/asm-ppc64/prom.h
@@ -116,14 +116,6 @@ struct property {
        struct property *next;
 };
 
-/* NOTE: the device_node contains PCI specific info for pci devices.
- * This perhaps could be hung off the device_node with another struct,
- * but for now it is directly in the node.  The phb ptr is a good
- * indication of a real PCI node.  Other nodes leave these fields zeroed.
- */
-struct pci_controller;
-struct iommu_table;
-
 struct device_node {
        char    *name;
        char    *type;
@@ -135,16 +127,6 @@ struct device_node {
        struct  interrupt_info *intrs;
        char    *full_name;
 
-       /* PCI stuff probably doesn't belong here */
-       int     busno;                  /* for pci devices */
-       int     bussubno;               /* for pci devices */
-       int     devfn;                  /* for pci devices */
-       int     eeh_mode;               /* See eeh.h for possible EEH_MODEs */
-       int     eeh_config_addr;
-       int     pci_ext_config_space;   /* for pci devices */
-       struct  pci_controller *phb;    /* for pci devices */
-       struct  iommu_table *iommu_table;       /* for phb's or bridges */
-
        struct  property *properties;
        struct  device_node *parent;
        struct  device_node *child;
@@ -154,6 +136,7 @@ struct device_node {
        struct  proc_dir_entry *pde;    /* this node's proc directory */
        struct  kref kref;
        unsigned long _flags;
+       void    *data;
 };
 
 extern struct device_node *of_chosen;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to