diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 2d58c26bff9a..e6f2a38d2e61 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -45,9 +45,13 @@ config SPARC select LOCKDEP_SMALL if LOCKDEP select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH + select HAVE_MEMBLOCK + select NO_BOOTMEM config SPARC32 def_bool !64BIT + select ARCH_HAS_SYNC_DMA_FOR_CPU + select DMA_NONCOHERENT_OPS select GENERIC_ATOMIC64 select CLZ_TAB select HAVE_UID16 @@ -60,7 +64,6 @@ config SPARC64 select HAVE_KRETPROBES select HAVE_KPROBES select HAVE_RCU_TABLE_FREE if SMP - select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP select HAVE_ARCH_TRANSPARENT_HUGEPAGE select HAVE_DYNAMIC_FTRACE @@ -79,7 +82,6 @@ config SPARC64 select IRQ_PREFLOW_FASTEOI select ARCH_HAVE_NMI_SAFE_CMPXCHG select HAVE_C_RECORDMCOUNT - select NO_BOOTMEM select HAVE_ARCH_AUDITSYSCALL select ARCH_SUPPORTS_ATOMIC_RMW select HAVE_NMI diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index 966a13d2b127..e32ef20de567 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile @@ -9,10 +9,10 @@ # Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) # We are not yet configured - so test on arch -ifeq ($(ARCH),sparc) - KBUILD_DEFCONFIG := sparc32_defconfig -else +ifeq ($(ARCH),sparc64) KBUILD_DEFCONFIG := sparc64_defconfig +else + KBUILD_DEFCONFIG := sparc32_defconfig endif ifeq ($(CONFIG_SPARC32),y) diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h index 12ae33daf52f..e17566376934 100644 --- a/arch/sparc/include/asm/dma-mapping.h +++ b/arch/sparc/include/asm/dma-mapping.h @@ -7,7 +7,6 @@ #include extern const struct dma_map_ops *dma_ops; -extern const struct dma_map_ops pci32_dma_ops; extern struct bus_type pci_bus_type; @@ -15,11 +14,11 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) { #ifdef CONFIG_SPARC_LEON if (sparc_cpu_model == sparc_leon) - return &pci32_dma_ops; + return &dma_noncoherent_ops; #endif #if defined(CONFIG_SPARC32) && defined(CONFIG_PCI) if (bus == &pci_bus_type) - return &pci32_dma_ops; + return &dma_noncoherent_ops; #endif return dma_ops; } diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index cca9134cfa7d..6799c93c9f27 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -434,42 +435,41 @@ arch_initcall(sparc_register_ioport); /* Allocate and map kernel buffer using consistent mode DMA for a device. * hwdev should be valid struct pci_dev pointer for PCI devices. */ -static void *pci32_alloc_coherent(struct device *dev, size_t len, - dma_addr_t *pba, gfp_t gfp, - unsigned long attrs) +void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t gfp, unsigned long attrs) { - unsigned long len_total = PAGE_ALIGN(len); + unsigned long len_total = PAGE_ALIGN(size); void *va; struct resource *res; int order; - if (len == 0) { + if (size == 0) { return NULL; } - if (len > 256*1024) { /* __get_free_pages() limit */ + if (size > 256*1024) { /* __get_free_pages() limit */ return NULL; } order = get_order(len_total); va = (void *) __get_free_pages(gfp, order); if (va == NULL) { - printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT); + printk("%s: no %ld pages\n", __func__, len_total>>PAGE_SHIFT); goto err_nopages; } if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { - printk("pci_alloc_consistent: no core\n"); + printk("%s: no core\n", __func__); goto err_nomem; } if (allocate_resource(&_sparc_dvma, res, len_total, _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) { - printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total); + printk("%s: cannot occupy 0x%lx", __func__, len_total); goto err_nova; } srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total); - *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */ + *dma_handle = virt_to_phys(va); return (void *) res->start; err_nova: @@ -481,184 +481,53 @@ err_nopages: } /* Free and unmap a consistent DMA buffer. - * cpu_addr is what was returned from pci_alloc_consistent, - * size must be the same as what as passed into pci_alloc_consistent, - * and likewise dma_addr must be the same as what *dma_addrp was set to. + * cpu_addr is what was returned arch_dma_alloc, size must be the same as what + * was passed into arch_dma_alloc, and likewise dma_addr must be the same as + * what *dma_ndler was set to. * * References to the memory and mappings associated with cpu_addr/dma_addr * past this call are illegal. */ -static void pci32_free_coherent(struct device *dev, size_t n, void *p, - dma_addr_t ba, unsigned long attrs) +void arch_dma_free(struct device *dev, size_t size, void *cpu_addr, + dma_addr_t dma_addr, unsigned long attrs) { struct resource *res; if ((res = lookup_resource(&_sparc_dvma, - (unsigned long)p)) == NULL) { - printk("pci_free_consistent: cannot free %p\n", p); + (unsigned long)cpu_addr)) == NULL) { + printk("%s: cannot free %p\n", __func__, cpu_addr); return; } - if (((unsigned long)p & (PAGE_SIZE-1)) != 0) { - printk("pci_free_consistent: unaligned va %p\n", p); + if (((unsigned long)cpu_addr & (PAGE_SIZE-1)) != 0) { + printk("%s: unaligned va %p\n", __func__, cpu_addr); return; } - n = PAGE_ALIGN(n); - if (resource_size(res) != n) { - printk("pci_free_consistent: region 0x%lx asked 0x%lx\n", - (long)resource_size(res), (long)n); + size = PAGE_ALIGN(size); + if (resource_size(res) != size) { + printk("%s: region 0x%lx asked 0x%zx\n", __func__, + (long)resource_size(res), size); return; } - dma_make_coherent(ba, n); - srmmu_unmapiorange((unsigned long)p, n); + dma_make_coherent(dma_addr, size); + srmmu_unmapiorange((unsigned long)cpu_addr, size); release_resource(res); kfree(res); - free_pages((unsigned long)phys_to_virt(ba), get_order(n)); + free_pages((unsigned long)phys_to_virt(dma_addr), get_order(size)); } -/* - * Same as pci_map_single, but with pages. - */ -static dma_addr_t pci32_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir, - unsigned long attrs) +/* IIep is write-through, not flushing on cpu to device transfer. */ + +void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr, + size_t size, enum dma_data_direction dir) { - /* IIep is write-through, not flushing. */ - return page_to_phys(page) + offset; + if (dir != PCI_DMA_TODEVICE) + dma_make_coherent(paddr, PAGE_ALIGN(size)); } -static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size, - enum dma_data_direction dir, unsigned long attrs) -{ - if (dir != PCI_DMA_TODEVICE && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) - dma_make_coherent(ba, PAGE_ALIGN(size)); -} - -/* Map a set of buffers described by scatterlist in streaming - * mode for DMA. This is the scatter-gather version of the - * above pci_map_single interface. Here the scatter gather list - * elements are each tagged with the appropriate dma address - * and length. They are obtained via sg_dma_{address,length}(SG). - * - * NOTE: An implementation may be able to use a smaller number of - * DMA address/length pairs than there are SG table elements. - * (for example via virtual mapping capabilities) - * The routine returns the number of addr/length pairs actually - * used, at most nents. - * - * Device ownership issues as mentioned above for pci_map_single are - * the same here. - */ -static int pci32_map_sg(struct device *device, struct scatterlist *sgl, - int nents, enum dma_data_direction dir, - unsigned long attrs) -{ - struct scatterlist *sg; - int n; - - /* IIep is write-through, not flushing. */ - for_each_sg(sgl, sg, nents, n) { - sg->dma_address = sg_phys(sg); - sg->dma_length = sg->length; - } - return nents; -} - -/* Unmap a set of streaming mode DMA translations. - * Again, cpu read rules concerning calls here are the same as for - * pci_unmap_single() above. - */ -static void pci32_unmap_sg(struct device *dev, struct scatterlist *sgl, - int nents, enum dma_data_direction dir, - unsigned long attrs) -{ - struct scatterlist *sg; - int n; - - if (dir != PCI_DMA_TODEVICE && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) { - for_each_sg(sgl, sg, nents, n) { - dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length)); - } - } -} - -/* Make physical memory consistent for a single - * streaming mode DMA translation before or after a transfer. - * - * If you perform a pci_map_single() but wish to interrogate the - * buffer using the cpu, yet do not wish to teardown the PCI dma - * mapping, you must call this function before doing so. At the - * next point you give the PCI dma address back to the card, you - * must first perform a pci_dma_sync_for_device, and then the - * device again owns the buffer. - */ -static void pci32_sync_single_for_cpu(struct device *dev, dma_addr_t ba, - size_t size, enum dma_data_direction dir) -{ - if (dir != PCI_DMA_TODEVICE) { - dma_make_coherent(ba, PAGE_ALIGN(size)); - } -} - -static void pci32_sync_single_for_device(struct device *dev, dma_addr_t ba, - size_t size, enum dma_data_direction dir) -{ - if (dir != PCI_DMA_TODEVICE) { - dma_make_coherent(ba, PAGE_ALIGN(size)); - } -} - -/* Make physical memory consistent for a set of streaming - * mode DMA translations after a transfer. - * - * The same as pci_dma_sync_single_* but for a scatter-gather list, - * same rules and usage. - */ -static void pci32_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, - int nents, enum dma_data_direction dir) -{ - struct scatterlist *sg; - int n; - - if (dir != PCI_DMA_TODEVICE) { - for_each_sg(sgl, sg, nents, n) { - dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length)); - } - } -} - -static void pci32_sync_sg_for_device(struct device *device, struct scatterlist *sgl, - int nents, enum dma_data_direction dir) -{ - struct scatterlist *sg; - int n; - - if (dir != PCI_DMA_TODEVICE) { - for_each_sg(sgl, sg, nents, n) { - dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length)); - } - } -} - -/* note: leon re-uses pci32_dma_ops */ -const struct dma_map_ops pci32_dma_ops = { - .alloc = pci32_alloc_coherent, - .free = pci32_free_coherent, - .map_page = pci32_map_page, - .unmap_page = pci32_unmap_page, - .map_sg = pci32_map_sg, - .unmap_sg = pci32_unmap_sg, - .sync_single_for_cpu = pci32_sync_single_for_cpu, - .sync_single_for_device = pci32_sync_single_for_device, - .sync_sg_for_cpu = pci32_sync_sg_for_cpu, - .sync_sg_for_device = pci32_sync_sg_for_device, -}; -EXPORT_SYMBOL(pci32_dma_ops); - const struct dma_map_ops *dma_ops = &sbus_dma_ops; EXPORT_SYMBOL(dma_ops); diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c index 95fe4f081ba3..92634d4e440c 100644 --- a/arch/sparc/mm/init_32.c +++ b/arch/sparc/mm/init_32.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -101,13 +102,46 @@ static unsigned long calc_max_low_pfn(void) return tmp; } +static void __init find_ramdisk(unsigned long end_of_phys_memory) +{ +#ifdef CONFIG_BLK_DEV_INITRD + unsigned long size; + + /* Now have to check initial ramdisk, so that it won't pass + * the end of memory + */ + if (sparc_ramdisk_image) { + if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE) + sparc_ramdisk_image -= KERNBASE; + initrd_start = sparc_ramdisk_image + phys_base; + initrd_end = initrd_start + sparc_ramdisk_size; + if (initrd_end > end_of_phys_memory) { + printk(KERN_CRIT "initrd extends beyond end of memory " + "(0x%016lx > 0x%016lx)\ndisabling initrd\n", + initrd_end, end_of_phys_memory); + initrd_start = 0; + } else { + /* Reserve the initrd image area. */ + size = initrd_end - initrd_start; + memblock_reserve(initrd_start, size); + + initrd_start = (initrd_start - phys_base) + PAGE_OFFSET; + initrd_end = (initrd_end - phys_base) + PAGE_OFFSET; + } + } +#endif +} + unsigned long __init bootmem_init(unsigned long *pages_avail) { - unsigned long bootmap_size, start_pfn; - unsigned long end_of_phys_memory = 0UL; - unsigned long bootmap_pfn, bytes_avail, size; + unsigned long start_pfn, bytes_avail, size; + unsigned long end_of_phys_memory = 0; + unsigned long high_pages = 0; int i; + memblock_set_bottom_up(true); + memblock_allow_resize(); + bytes_avail = 0UL; for (i = 0; sp_banks[i].num_bytes != 0; i++) { end_of_phys_memory = sp_banks[i].base_addr + @@ -124,24 +158,25 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) if (sp_banks[i].num_bytes == 0) { sp_banks[i].base_addr = 0xdeadbeef; } else { + memblock_add(sp_banks[i].base_addr, + sp_banks[i].num_bytes); sp_banks[i+1].num_bytes = 0; sp_banks[i+1].base_addr = 0xdeadbeef; } break; } } + memblock_add(sp_banks[i].base_addr, sp_banks[i].num_bytes); } /* Start with page aligned address of last symbol in kernel - * image. + * image. */ start_pfn = (unsigned long)__pa(PAGE_ALIGN((unsigned long) &_end)); /* Now shift down to get the real physical page frame number. */ start_pfn >>= PAGE_SHIFT; - bootmap_pfn = start_pfn; - max_pfn = end_of_phys_memory >> PAGE_SHIFT; max_low_pfn = max_pfn; @@ -150,85 +185,19 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) if (max_low_pfn > pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT)) { highstart_pfn = pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT); max_low_pfn = calc_max_low_pfn(); + high_pages = calc_highpages(); printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", - calc_highpages() >> (20 - PAGE_SHIFT)); + high_pages >> (20 - PAGE_SHIFT)); } -#ifdef CONFIG_BLK_DEV_INITRD - /* Now have to check initial ramdisk, so that bootmap does not overwrite it */ - if (sparc_ramdisk_image) { - if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE) - sparc_ramdisk_image -= KERNBASE; - initrd_start = sparc_ramdisk_image + phys_base; - initrd_end = initrd_start + sparc_ramdisk_size; - if (initrd_end > end_of_phys_memory) { - printk(KERN_CRIT "initrd extends beyond end of memory " - "(0x%016lx > 0x%016lx)\ndisabling initrd\n", - initrd_end, end_of_phys_memory); - initrd_start = 0; - } - if (initrd_start) { - if (initrd_start >= (start_pfn << PAGE_SHIFT) && - initrd_start < (start_pfn << PAGE_SHIFT) + 2 * PAGE_SIZE) - bootmap_pfn = PAGE_ALIGN (initrd_end) >> PAGE_SHIFT; - } - } -#endif - /* Initialize the boot-time allocator. */ - bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, - max_low_pfn); + find_ramdisk(end_of_phys_memory); - /* Now register the available physical memory with the - * allocator. - */ - *pages_avail = 0; - for (i = 0; sp_banks[i].num_bytes != 0; i++) { - unsigned long curr_pfn, last_pfn; - - curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT; - if (curr_pfn >= max_low_pfn) - break; - - last_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT; - if (last_pfn > max_low_pfn) - last_pfn = max_low_pfn; - - /* - * .. finally, did all the rounding and playing - * around just make the area go away? - */ - if (last_pfn <= curr_pfn) - continue; - - size = (last_pfn - curr_pfn) << PAGE_SHIFT; - *pages_avail += last_pfn - curr_pfn; - - free_bootmem(sp_banks[i].base_addr, size); - } - -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) { - /* Reserve the initrd image area. */ - size = initrd_end - initrd_start; - reserve_bootmem(initrd_start, size, BOOTMEM_DEFAULT); - *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; - - initrd_start = (initrd_start - phys_base) + PAGE_OFFSET; - initrd_end = (initrd_end - phys_base) + PAGE_OFFSET; - } -#endif /* Reserve the kernel text/data/bss. */ size = (start_pfn << PAGE_SHIFT) - phys_base; - reserve_bootmem(phys_base, size, BOOTMEM_DEFAULT); - *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; + memblock_reserve(phys_base, size); - /* Reserve the bootmem map. We do not account for it - * in pages_avail because we will release that memory - * in free_all_bootmem. - */ - size = bootmap_size; - reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size, BOOTMEM_DEFAULT); - *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; + size = memblock_phys_mem_size() - memblock_reserved_size(); + *pages_avail = (size >> PAGE_SHIFT) - high_pages; return max_pfn; } @@ -322,7 +291,7 @@ void __init mem_init(void) map_high_region(start_pfn, end_pfn); } - + mem_init_print_info(NULL); }