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 044e8ec4c0f5..6b3fe2c1d65e 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/percpu.h> | 12 | #include <linux/percpu.h> |
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <linux/msi.h> | 14 | #include <linux/msi.h> |
15 | #include <linux/log2.h> | ||
15 | 16 | ||
16 | #include <asm/iommu.h> | 17 | #include <asm/iommu.h> |
17 | #include <asm/irq.h> | 18 | #include <asm/irq.h> |
@@ -26,6 +27,9 @@ | |||
26 | 27 | ||
27 | #include "pci_sun4v.h" | 28 | #include "pci_sun4v.h" |
28 | 29 | ||
30 | static unsigned long vpci_major = 1; | ||
31 | static unsigned long vpci_minor = 1; | ||
32 | |||
29 | #define PGLIST_NENTS (PAGE_SIZE / sizeof(u64)) | 33 | #define PGLIST_NENTS (PAGE_SIZE / sizeof(u64)) |
30 | 34 | ||
31 | struct iommu_batch { | 35 | struct iommu_batch { |
@@ -638,9 +642,8 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
638 | { | 642 | { |
639 | struct iommu *iommu = pbm->iommu; | 643 | struct iommu *iommu = pbm->iommu; |
640 | struct property *prop; | 644 | struct property *prop; |
641 | unsigned long num_tsb_entries, sz; | 645 | unsigned long num_tsb_entries, sz, tsbsize; |
642 | u32 vdma[2], dma_mask, dma_offset; | 646 | u32 vdma[2], dma_mask, dma_offset; |
643 | int tsbsize; | ||
644 | 647 | ||
645 | prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); | 648 | prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); |
646 | if (prop) { | 649 | if (prop) { |
@@ -654,31 +657,15 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
654 | vdma[1] = 0x80000000; | 657 | vdma[1] = 0x80000000; |
655 | } | 658 | } |
656 | 659 | ||
657 | dma_mask = vdma[0]; | 660 | if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) { |
658 | switch (vdma[1]) { | 661 | prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n", |
659 | case 0x20000000: | 662 | vdma[0], vdma[1]); |
660 | dma_mask |= 0x1fffffff; | 663 | prom_halt(); |
661 | tsbsize = 64; | ||
662 | break; | ||
663 | |||
664 | case 0x40000000: | ||
665 | dma_mask |= 0x3fffffff; | ||
666 | tsbsize = 128; | ||
667 | break; | ||
668 | |||
669 | case 0x80000000: | ||
670 | dma_mask |= 0x7fffffff; | ||
671 | tsbsize = 256; | ||
672 | break; | ||
673 | |||
674 | default: | ||
675 | prom_printf("PCI-SUN4V: strange virtual-dma size.\n"); | ||
676 | prom_halt(); | ||
677 | }; | 664 | }; |
678 | 665 | ||
679 | tsbsize *= (8 * 1024); | 666 | dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); |
680 | 667 | num_tsb_entries = vdma[1] / IO_PAGE_SIZE; | |
681 | num_tsb_entries = tsbsize / sizeof(iopte_t); | 668 | tsbsize = num_tsb_entries * sizeof(iopte_t); |
682 | 669 | ||
683 | dma_offset = vdma[0]; | 670 | dma_offset = vdma[0]; |
684 | 671 | ||
@@ -689,7 +676,7 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
689 | iommu->dma_addr_mask = dma_mask; | 676 | iommu->dma_addr_mask = dma_mask; |
690 | 677 | ||
691 | /* Allocate and initialize the free area map. */ | 678 | /* Allocate and initialize the free area map. */ |
692 | sz = num_tsb_entries / 8; | 679 | sz = (num_tsb_entries + 7) / 8; |
693 | sz = (sz + 7UL) & ~7UL; | 680 | sz = (sz + 7UL) & ~7UL; |
694 | iommu->arena.map = kzalloc(sz, GFP_KERNEL); | 681 | iommu->arena.map = kzalloc(sz, GFP_KERNEL); |
695 | if (!iommu->arena.map) { | 682 | if (!iommu->arena.map) { |
@@ -1178,6 +1165,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node | |||
1178 | 1165 | ||
1179 | void sun4v_pci_init(struct device_node *dp, char *model_name) | 1166 | void sun4v_pci_init(struct device_node *dp, char *model_name) |
1180 | { | 1167 | { |
1168 | static int hvapi_negotiated = 0; | ||
1181 | struct pci_controller_info *p; | 1169 | struct pci_controller_info *p; |
1182 | struct pci_pbm_info *pbm; | 1170 | struct pci_pbm_info *pbm; |
1183 | struct iommu *iommu; | 1171 | struct iommu *iommu; |
@@ -1186,6 +1174,20 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) | |||
1186 | u32 devhandle; | 1174 | u32 devhandle; |
1187 | int i; | 1175 | int i; |
1188 | 1176 | ||
1177 | if (!hvapi_negotiated++) { | ||
1178 | int err = sun4v_hvapi_register(HV_GRP_PCI, | ||
1179 | vpci_major, | ||
1180 | &vpci_minor); | ||
1181 | |||
1182 | if (err) { | ||
1183 | prom_printf("SUN4V_PCI: Could not register hvapi, " | ||
1184 | "err=%d\n", err); | ||
1185 | prom_halt(); | ||
1186 | } | ||
1187 | printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n", | ||
1188 | vpci_major, vpci_minor); | ||
1189 | } | ||
1190 | |||
1189 | prop = of_find_property(dp, "reg", NULL); | 1191 | prop = of_find_property(dp, "reg", NULL); |
1190 | regs = prop->value; | 1192 | regs = prop->value; |
1191 | 1193 | ||