diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_sun4v.c')
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 54 |
1 files changed, 28 insertions, 26 deletions
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 044e8ec..6b3fe2c 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -12,6 +12,7 @@ #include <linux/percpu.h> #include <linux/irq.h> #include <linux/msi.h> +#include <linux/log2.h> #include <asm/iommu.h> #include <asm/irq.h> @@ -26,6 +27,9 @@ #include "pci_sun4v.h" +static unsigned long vpci_major = 1; +static unsigned long vpci_minor = 1; + #define PGLIST_NENTS (PAGE_SIZE / sizeof(u64)) struct iommu_batch { @@ -638,9 +642,8 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) { struct iommu *iommu = pbm->iommu; struct property *prop; - unsigned long num_tsb_entries, sz; + unsigned long num_tsb_entries, sz, tsbsize; u32 vdma[2], dma_mask, dma_offset; - int tsbsize; prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); if (prop) { @@ -654,31 +657,15 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) vdma[1] = 0x80000000; } - dma_mask = vdma[0]; - switch (vdma[1]) { - case 0x20000000: - dma_mask |= 0x1fffffff; - tsbsize = 64; - break; - - case 0x40000000: - dma_mask |= 0x3fffffff; - tsbsize = 128; - break; - - case 0x80000000: - dma_mask |= 0x7fffffff; - tsbsize = 256; - break; - - default: - prom_printf("PCI-SUN4V: strange virtual-dma size.\n"); - prom_halt(); + if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) { + prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n", + vdma[0], vdma[1]); + prom_halt(); }; - tsbsize *= (8 * 1024); - - num_tsb_entries = tsbsize / sizeof(iopte_t); + dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); + num_tsb_entries = vdma[1] / IO_PAGE_SIZE; + tsbsize = num_tsb_entries * sizeof(iopte_t); dma_offset = vdma[0]; @@ -689,7 +676,7 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) iommu->dma_addr_mask = dma_mask; /* Allocate and initialize the free area map. */ - sz = num_tsb_entries / 8; + sz = (num_tsb_entries + 7) / 8; sz = (sz + 7UL) & ~7UL; iommu->arena.map = kzalloc(sz, GFP_KERNEL); if (!iommu->arena.map) { @@ -1178,6 +1165,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node void sun4v_pci_init(struct device_node *dp, char *model_name) { + static int hvapi_negotiated = 0; struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; @@ -1186,6 +1174,20 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) u32 devhandle; int i; + if (!hvapi_negotiated++) { + int err = sun4v_hvapi_register(HV_GRP_PCI, + vpci_major, + &vpci_minor); + + if (err) { + prom_printf("SUN4V_PCI: Could not register hvapi, " + "err=%d\n", err); + prom_halt(); + } + printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n", + vpci_major, vpci_minor); + } + prop = of_find_property(dp, "reg", NULL); regs = prop->value; |