Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c1b1a5f1 authored by David S. Miller's avatar David S. Miller
Browse files

[SPARC64]: NUMA device infrastructure.



Record and propagate NUMA information for devices.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0c49a573
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -396,6 +396,7 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de
	sd->op = &dev->ofdev;
	sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu;
	sd->stc = dev->bus->ofdev.dev.parent->archdata.stc;
	sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node;

	dev->ofdev.node = dp;
	dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
+21 −12
Original line number Diff line number Diff line
@@ -173,9 +173,11 @@ void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long np
}

int iommu_table_init(struct iommu *iommu, int tsbsize,
		     u32 dma_offset, u32 dma_addr_mask)
		     u32 dma_offset, u32 dma_addr_mask,
		     int numa_node)
{
	unsigned long i, tsbbase, order, sz, num_tsb_entries;
	unsigned long i, order, sz, num_tsb_entries;
	struct page *page;

	num_tsb_entries = tsbsize / sizeof(iopte_t);

@@ -188,11 +190,12 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
	/* Allocate and initialize the free area map.  */
	sz = num_tsb_entries / 8;
	sz = (sz + 7UL) & ~7UL;
	iommu->arena.map = kzalloc(sz, GFP_KERNEL);
	iommu->arena.map = kmalloc_node(sz, GFP_KERNEL, numa_node);
	if (!iommu->arena.map) {
		printk(KERN_ERR "IOMMU: Error, kmalloc(arena.map) failed.\n");
		return -ENOMEM;
	}
	memset(iommu->arena.map, 0, sz);
	iommu->arena.limit = num_tsb_entries;

	if (tlb_type != hypervisor)
@@ -201,21 +204,23 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
	/* Allocate and initialize the dummy page which we
	 * set inactive IO PTEs to point to.
	 */
	iommu->dummy_page = get_zeroed_page(GFP_KERNEL);
	if (!iommu->dummy_page) {
	page = alloc_pages_node(numa_node, GFP_KERNEL, 0);
	if (!page) {
		printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n");
		goto out_free_map;
	}
	iommu->dummy_page = (unsigned long) page_address(page);
	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);

	/* Now allocate and setup the IOMMU page table itself.  */
	order = get_order(tsbsize);
	tsbbase = __get_free_pages(GFP_KERNEL, order);
	if (!tsbbase) {
	page = alloc_pages_node(numa_node, GFP_KERNEL, order);
	if (!page) {
		printk(KERN_ERR "IOMMU: Error, gfp(tsb) failed.\n");
		goto out_free_dummy_page;
	}
	iommu->page_table = (iopte_t *)tsbbase;
	iommu->page_table = (iopte_t *)page_address(page);

	for (i = 0; i < num_tsb_entries; i++)
		iopte_make_dummy(iommu, &iommu->page_table[i]);
@@ -276,20 +281,24 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
				   dma_addr_t *dma_addrp, gfp_t gfp)
{
	unsigned long flags, order, first_page;
	struct iommu *iommu;
	struct page *page;
	int npages, nid;
	iopte_t *iopte;
	unsigned long flags, order, first_page;
	void *ret;
	int npages;

	size = IO_PAGE_ALIGN(size);
	order = get_order(size);
	if (order >= 10)
		return NULL;

	first_page = __get_free_pages(gfp, order);
	if (first_page == 0UL)
	nid = dev->archdata.numa_node;
	page = alloc_pages_node(nid, gfp, order);
	if (unlikely(!page))
		return NULL;

	first_page = (unsigned long) page_address(page);
	memset((char *)first_page, 0, PAGE_SIZE << order);

	iommu = dev->archdata.iommu;
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
		sd->op = &isa_dev->ofdev;
		sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu;
		sd->stc = isa_br->ofdev.dev.parent->archdata.stc;
		sd->numa_node = isa_br->ofdev.dev.parent->archdata.numa_node;

		isa_dev->ofdev.node = dp;
		isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
+11 −1
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/irq.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>

@@ -660,6 +661,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
	struct device_node *dp = op->node;
	struct device_node *pp, *ip;
	unsigned int orig_irq = irq;
	int nid;

	if (irq == 0xffffffff)
		return irq;
@@ -672,7 +674,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
			printk("%s: direct translate %x --> %x\n",
			       dp->full_name, orig_irq, irq);

		return irq;
		goto out;
	}

	/* Something more complicated.  Walk up to the root, applying
@@ -744,6 +746,14 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
		printk("%s: Apply IRQ trans [%s] %x --> %x\n",
		       op->node->full_name, ip->full_name, orig_irq, irq);

out:
	nid = of_node_to_nid(dp);
	if (nid != -1) {
		cpumask_t numa_mask = node_to_cpumask(nid);

		irq_set_affinity(irq, numa_mask);
	}

	return irq;
}

+12 −0
Original line number Diff line number Diff line
@@ -369,10 +369,12 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
	sd->host_controller = pbm;
	sd->prom_node = node;
	sd->op = of_find_device_by_node(node);
	sd->numa_node = pbm->numa_node;

	sd = &sd->op->dev.archdata;
	sd->iommu = pbm->iommu;
	sd->stc = &pbm->stc;
	sd->numa_node = pbm->numa_node;

	type = of_get_property(node, "device_type", NULL);
	if (type == NULL)
@@ -1159,6 +1161,16 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
	return 0;
}

#ifdef CONFIG_NUMA
int pcibus_to_node(struct pci_bus *pbus)
{
	struct pci_pbm_info *pbm = pbus->sysdata;

	return pbm->numa_node;
}
EXPORT_SYMBOL(pcibus_to_node);
#endif

/* Return the domain nuber for this pci bus */

int pci_domain_nr(struct pci_bus *pbus)
Loading