}
 
 static void *
-sn_default_pci_bus_fixup(struct pcibus_bussoft *soft)
+sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller)
 {
        return NULL;
 }
 
        provider_soft = NULL;
        if (provider->bus_fixup)
-               provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr);
+               provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller);
 
        if (provider_soft == NULL)
                return;         /* fixup failed or not applicable */
        SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info =
            &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]);
 
+       /*
+        * If the node information we obtained during the fixup phase is invalid
+        * then set controller->node to -1 (undetermined)
+        */
+       if (controller->node >= num_online_nodes()) {
+               struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
+
+               printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%lu"
+                                   "L_IO=%lx L_MEM=%lx BASE=%lx\n",
+                       b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
+                       b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
+               printk(KERN_WARNING "on node %d but only %d nodes online."
+                       "Association set to undetermined.\n",
+                       controller->node, num_online_nodes());
+               controller->node = -1;
+       }
        return;
 
 error_return:
 
 {
        void *cpuaddr;
        unsigned long phys_addr;
+       int node;
        struct pci_dev *pdev = to_pci_dev(dev);
        struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
 
        /*
         * Allocate the memory.
-        * FIXME: We should be doing alloc_pages_node for the node closest
-        *        to the PCI device.
         */
-       if (!(cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size))))
+       node = pcibus_to_node(pdev->bus);
+       if (likely(node >=0)) {
+               struct page *p = alloc_pages_node(node, GFP_ATOMIC, get_order(size));
+
+               if (likely(p))
+                       cpuaddr = page_address(p);
+               else
+                       return NULL;
+       } else
+               cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
+
+       if (unlikely(!cpuaddr))
                return NULL;
 
        memset(cpuaddr, 0x0, size);
 
 }
 
 void *
-pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft)
+pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
 {
        int nasid, cnode, j;
        struct hubdev_info *hubdev_info;
        memset(soft->pbi_int_ate_resource.ate, 0,
               (soft->pbi_int_ate_size * sizeof(uint64_t)));
 
+       if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP)
+               /*
+                * TIO PCI Bridge with no closest node information.
+                * FIXME: Find another way to determine the closest node
+                */
+               controller->node = -1;
+       else
+               controller->node = cnode;
        return soft;
 }
 
 
  * the caller.
  */
 static void *
-tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft)
+tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
 {
        struct tioca_common *tioca_common;
        struct tioca_kernel *tioca_kern;
                       __FUNCTION__, SGI_TIOCA_ERROR,
                       (int)tioca_common->ca_common.bs_persist_busnum);
 
+       /* Setup locality information */
+       controller->node = tioca_kern->ca_closest_node;
        return tioca_common;
 }
 
 
 #define pcibr_unlock(pcibus_info, flag)  spin_unlock_irqrestore(&pcibus_info->pbi_lock, flag)
 
 extern int  pcibr_init_provider(void);
-extern void *pcibr_bus_fixup(struct pcibus_bussoft *);
+extern void *pcibr_bus_fixup(struct pcibus_bussoft *, struct pci_controller *);
 extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t);
 extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t);
 extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int);
 
        struct xwidget_info     *bs_xwidget_info;
 };
 
+struct pci_controller;
 /*
  * SN pci bus indirection
  */
        dma_addr_t      (*dma_map)(struct pci_dev *, unsigned long, size_t);
        dma_addr_t      (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t);
        void            (*dma_unmap)(struct pci_dev *, dma_addr_t, int);
-       void *          (*bus_fixup)(struct pcibus_bussoft *);
+       void *          (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *);
 };
 
 extern struct sn_pcibus_provider *sn_pci_provider[];