aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-05-23 21:00:46 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-05-29 05:49:15 -0400
commit59db8102bd0ab7a67d525d086ca08e07d69fadd4 (patch)
tree8c27da20237d2af91a04d9eab13c243904d3f01b
parenta1aadd55fb43e31407aecc4ebaf0258130a98238 (diff)
[SPARC64]: Don't be picky about virtual-dma values on sun4v.
Handle arbitrary base and length values as long as they are multiples of IO_PAGE_SIZE. Bug found by Arun Kumar Rao. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c36
1 files changed, 10 insertions, 26 deletions
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 044e8ec4c0f5..62e4d047dbc0 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>
@@ -638,9 +639,8 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
638{ 639{
639 struct iommu *iommu = pbm->iommu; 640 struct iommu *iommu = pbm->iommu;
640 struct property *prop; 641 struct property *prop;
641 unsigned long num_tsb_entries, sz; 642 unsigned long num_tsb_entries, sz, tsbsize;
642 u32 vdma[2], dma_mask, dma_offset; 643 u32 vdma[2], dma_mask, dma_offset;
643 int tsbsize;
644 644
645 prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); 645 prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
646 if (prop) { 646 if (prop) {
@@ -654,31 +654,15 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
654 vdma[1] = 0x80000000; 654 vdma[1] = 0x80000000;
655 } 655 }
656 656
657 dma_mask = vdma[0]; 657 if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) {
658 switch (vdma[1]) { 658 prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n",
659 case 0x20000000: 659 vdma[0], vdma[1]);
660 dma_mask |= 0x1fffffff; 660 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 }; 661 };
678 662
679 tsbsize *= (8 * 1024); 663 dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL);
680 664 num_tsb_entries = vdma[1] / IO_PAGE_SIZE;
681 num_tsb_entries = tsbsize / sizeof(iopte_t); 665 tsbsize = num_tsb_entries * sizeof(iopte_t);
682 666
683 dma_offset = vdma[0]; 667 dma_offset = vdma[0];
684 668
@@ -689,7 +673,7 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
689 iommu->dma_addr_mask = dma_mask; 673 iommu->dma_addr_mask = dma_mask;
690 674
691 /* Allocate and initialize the free area map. */ 675 /* Allocate and initialize the free area map. */
692 sz = num_tsb_entries / 8; 676 sz = (num_tsb_entries + 7) / 8;
693 sz = (sz + 7UL) & ~7UL; 677 sz = (sz + 7UL) & ~7UL;
694 iommu->arena.map = kzalloc(sz, GFP_KERNEL); 678 iommu->arena.map = kzalloc(sz, GFP_KERNEL);
695 if (!iommu->arena.map) { 679 if (!iommu->arena.map) {