diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index b63b2834133f8078ae707798ef669659b9cadf10..b275c7df01867d0f67622a2febce28105de1c256 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -988,8 +988,13 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, HV_PCI_TSBID(0, i), &io_attrs, &ra); if (ret == HV_EOK) { - cnt++; - __set_bit(i, arena->map); + if (page_in_phys_avail(ra)) { + pci_sun4v_iommu_demap(devhandle, + HV_PCI_TSBID(0, i), 1); + } else { + cnt++; + __set_bit(i, arena->map); + } } } @@ -1062,9 +1067,9 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) iommu->arena.limit = num_tsb_entries; sz = probe_existing_entries(pbm, iommu); - - printk("%s: TSB entries [%lu], existing mapings [%lu]\n", - pbm->name, num_tsb_entries, sz); + if (sz) + printk("%s: Imported %lu TSB entries from OBP\n", + pbm->name, sz); } static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 9d2b0da590af1b98f50a66028c2001f4ecabba0f..513993414747d1c74bc7eafb5f2822ac0c480cb5 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1396,7 +1396,7 @@ static void __init taint_real_pages(void) while (old_start < old_end) { int n; - for (n = 0; pavail_rescan_ents; n++) { + for (n = 0; n < pavail_rescan_ents; n++) { unsigned long new_start, new_end; new_start = pavail_rescan[n].phys_addr; @@ -1418,6 +1418,32 @@ static void __init taint_real_pages(void) } } +int __init page_in_phys_avail(unsigned long paddr) +{ + int i; + + paddr &= PAGE_MASK; + + for (i = 0; i < pavail_rescan_ents; i++) { + unsigned long start, end; + + start = pavail_rescan[i].phys_addr; + end = start + pavail_rescan[i].reg_size; + + if (paddr >= start && paddr < end) + return 1; + } + if (paddr >= kern_base && paddr < (kern_base + kern_size)) + return 1; +#ifdef CONFIG_BLK_DEV_INITRD + if (paddr >= __pa(initrd_start) && + paddr < __pa(PAGE_ALIGN(initrd_end))) + return 1; +#endif + + return 0; +} + void __init mem_init(void) { unsigned long codepages, datapages, initpages; diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 4e218814bb3c2b62932b3f0b1ed3227dd523a0dd..03f5bc9b6becdcbfbe8fabd2be36d0cc2163c97f 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -756,6 +756,8 @@ extern unsigned long *sparc64_valid_addr_bitmap; #define kern_addr_valid(addr) \ (test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap)) +extern int page_in_phys_avail(unsigned long paddr); + extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot);