diff options
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r-- | arch/sparc64/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/entry.S | 12 | ||||
-rw-r--r-- | arch/sparc64/kernel/iommu.c | 142 | ||||
-rw-r--r-- | arch/sparc64/kernel/iommu_common.c | 244 | ||||
-rw-r--r-- | arch/sparc64/kernel/iommu_common.h | 29 | ||||
-rw-r--r-- | arch/sparc64/kernel/ktlb.S | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci.c | 16 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_fire.c | 8 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 7 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 19 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 181 | ||||
-rw-r--r-- | arch/sparc64/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/smp.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/sparc64_ksyms.c | 1 | ||||
-rw-r--r-- | arch/sparc64/kernel/sun4v_tlb_miss.S | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/systbls.S | 9 | ||||
-rw-r--r-- | arch/sparc64/kernel/time.c | 5 | ||||
-rw-r--r-- | arch/sparc64/kernel/traps.c | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/unaligned.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/vio.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/vmlinux.lds.S | 8 |
22 files changed, 179 insertions, 530 deletions
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index ef50d217432f..4b78b24ef413 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -11,7 +11,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ traps.o auxio.o una_asm.o sysfs.o iommu.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o pci.o starfire.o semaphore.o \ - power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ + power.o sbus.o sparc64_ksyms.o chmc.o \ visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o obj-$(CONFIG_STACKTRACE) += stacktrace.o diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index c9b0d7af64ae..ea257e828364 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -2593,3 +2593,15 @@ sun4v_mmustat_info: retl nop .size sun4v_mmustat_info, .-sun4v_mmustat_info + + .globl sun4v_mmu_demap_all + .type sun4v_mmu_demap_all,#function +sun4v_mmu_demap_all: + clr %o0 + clr %o1 + mov HV_MMU_ALL, %o2 + mov HV_FAST_MMU_DEMAP_ALL, %o5 + ta HV_FAST_TRAP + retl + nop + .size sun4v_mmu_demap_all, .-sun4v_mmu_demap_all diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c index 070a4846c0cb..5623a4d59dff 100644 --- a/arch/sparc64/kernel/iommu.c +++ b/arch/sparc64/kernel/iommu.c @@ -472,94 +472,15 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr, spin_unlock_irqrestore(&iommu->lock, flags); } -#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG)))) - -static void fill_sg(iopte_t *iopte, struct scatterlist *sg, - int nused, int nelems, - unsigned long iopte_protection) -{ - struct scatterlist *dma_sg = sg; - int i; - - for (i = 0; i < nused; i++) { - unsigned long pteval = ~0UL; - u32 dma_npages; - - dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) + - dma_sg->dma_length + - ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT; - do { - unsigned long offset; - signed int len; - - /* If we are here, we know we have at least one - * more page to map. So walk forward until we - * hit a page crossing, and begin creating new - * mappings from that spot. - */ - for (;;) { - unsigned long tmp; - - tmp = SG_ENT_PHYS_ADDRESS(sg); - len = sg->length; - if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) { - pteval = tmp & IO_PAGE_MASK; - offset = tmp & (IO_PAGE_SIZE - 1UL); - break; - } - if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) { - pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK; - offset = 0UL; - len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL))); - break; - } - sg = sg_next(sg); - nelems--; - } - - pteval = iopte_protection | (pteval & IOPTE_PAGE); - while (len > 0) { - *iopte++ = __iopte(pteval); - pteval += IO_PAGE_SIZE; - len -= (IO_PAGE_SIZE - offset); - offset = 0; - dma_npages--; - } - - pteval = (pteval & IOPTE_PAGE) + len; - sg = sg_next(sg); - nelems--; - - /* Skip over any tail mappings we've fully mapped, - * adjusting pteval along the way. Stop when we - * detect a page crossing event. - */ - while (nelems && - (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && - (pteval == SG_ENT_PHYS_ADDRESS(sg)) && - ((pteval ^ - (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { - pteval += sg->length; - sg = sg_next(sg); - nelems--; - } - if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) - pteval = ~0UL; - } while (dma_npages != 0); - dma_sg = sg_next(dma_sg); - } -} - static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { - struct iommu *iommu; + unsigned long flags, ctx, i, npages, iopte_protection; + struct scatterlist *sg; struct strbuf *strbuf; - unsigned long flags, ctx, npages, iopte_protection; + struct iommu *iommu; iopte_t *base; u32 dma_base; - struct scatterlist *sgtmp; - int used; /* Fast path single entry scatterlists. */ if (nelems == 1) { @@ -578,11 +499,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, if (unlikely(direction == DMA_NONE)) goto bad_no_ctx; - /* Step 1: Prepare scatter list. */ - - npages = prepare_sg(sglist, nelems); - - /* Step 2: Allocate a cluster and context, if necessary. */ + npages = calc_npages(sglist, nelems); spin_lock_irqsave(&iommu->lock, flags); @@ -599,18 +516,6 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << IO_PAGE_SHIFT); - /* Step 3: Normalize DMA addresses. */ - used = nelems; - - sgtmp = sglist; - while (used && sgtmp->dma_length) { - sgtmp->dma_address += dma_base; - sgtmp = sg_next(sgtmp); - used--; - } - used = nelems - used; - - /* Step 4: Create the mappings. */ if (strbuf->strbuf_enabled) iopte_protection = IOPTE_STREAMING(ctx); else @@ -618,13 +523,27 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, if (direction != DMA_TO_DEVICE) iopte_protection |= IOPTE_WRITE; - fill_sg(base, sglist, used, nelems, iopte_protection); + for_each_sg(sglist, sg, nelems, i) { + unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg); + unsigned long slen = sg->length; + unsigned long this_npages; -#ifdef VERIFY_SG - verify_sglist(sglist, nelems, base, npages); -#endif + this_npages = iommu_num_pages(paddr, slen); - return used; + sg->dma_address = dma_base | (paddr & ~IO_PAGE_MASK); + sg->dma_length = slen; + + paddr &= IO_PAGE_MASK; + while (this_npages--) { + iopte_val(*base) = iopte_protection | paddr; + + base++; + paddr += IO_PAGE_SIZE; + dma_base += IO_PAGE_SIZE; + } + } + + return nelems; bad: iommu_free_ctx(iommu, ctx); @@ -637,11 +556,10 @@ bad_no_ctx: static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { - struct iommu *iommu; + unsigned long flags, ctx, i, npages; struct strbuf *strbuf; + struct iommu *iommu; iopte_t *base; - unsigned long flags, ctx, i, npages; - struct scatterlist *sg, *sgprv; u32 bus_addr; if (unlikely(direction == DMA_NONE)) { @@ -654,15 +572,7 @@ static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist, bus_addr = sglist->dma_address & IO_PAGE_MASK; - sgprv = NULL; - for_each_sg(sglist, sg, nelems, i) { - if (sg->dma_length == 0) - break; - sgprv = sg; - } - - npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) - - bus_addr) >> IO_PAGE_SHIFT; + npages = calc_npages(sglist, nelems); base = iommu->page_table + ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c deleted file mode 100644 index efd5dff85f60..000000000000 --- a/arch/sparc64/kernel/iommu_common.c +++ /dev/null @@ -1,244 +0,0 @@ -/* $Id: iommu_common.c,v 1.9 2001/12/17 07:05:09 davem Exp $ - * iommu_common.c: UltraSparc SBUS/PCI common iommu code. - * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - -#include "iommu_common.h" - -/* You are _strongly_ advised to enable the following debugging code - * any time you make changes to the sg code below, run it for a while - * with filesystems mounted read-only before buying the farm... -DaveM - */ - -#ifdef VERIFY_SG -static int verify_lengths(struct scatterlist *sglist, int nents, int npages) -{ - int sg_len, dma_len; - int i, pgcount; - struct scatterlist *sg; - - sg_len = 0; - for_each_sg(sglist, sg, nents, i) - sg_len += sg->length; - - dma_len = 0; - for_each_sg(sglist, sg, nents, i) { - if (!sg->dma_length) - break; - dma_len += sg->dma_length; - } - - if (sg_len != dma_len) { - printk("verify_lengths: Error, different, sg[%d] dma[%d]\n", - sg_len, dma_len); - return -1; - } - - pgcount = 0; - for_each_sg(sglist, sg, nents, i) { - unsigned long start, end; - - if (!sg->dma_length) - break; - - start = sg->dma_address; - start = start & IO_PAGE_MASK; - - end = sg->dma_address + sg->dma_length; - end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK; - - pgcount += ((end - start) >> IO_PAGE_SHIFT); - } - - if (pgcount != npages) { - printk("verify_lengths: Error, page count wrong, " - "npages[%d] pgcount[%d]\n", - npages, pgcount); - return -1; - } - - /* This test passes... */ - return 0; -} - -static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte) -{ - struct scatterlist *sg = *__sg; - iopte_t *iopte = *__iopte; - u32 dlen = dma_sg->dma_length; - u32 daddr; - unsigned int sglen; - unsigned long sgaddr; - - daddr = dma_sg->dma_address; - sglen = sg->length; - sgaddr = (unsigned long) sg_virt(sg); - while (dlen > 0) { - unsigned long paddr; - - /* SG and DMA_SG must begin at the same sub-page boundary. */ - if ((sgaddr & ~IO_PAGE_MASK) != (daddr & ~IO_PAGE_MASK)) { - printk("verify_one_map: Wrong start offset " - "sg[%08lx] dma[%08x]\n", - sgaddr, daddr); - nents = -1; - goto out; - } - - /* Verify the IOPTE points to the right page. */ - paddr = iopte_val(*iopte) & IOPTE_PAGE; - if ((paddr + PAGE_OFFSET) != (sgaddr & IO_PAGE_MASK)) { - printk("verify_one_map: IOPTE[%08lx] maps the " - "wrong page, should be [%08lx]\n", - iopte_val(*iopte), (sgaddr & IO_PAGE_MASK) - PAGE_OFFSET); - nents = -1; - goto out; - } - - /* If this SG crosses a page, adjust to that next page - * boundary and loop. - */ - if ((sgaddr & IO_PAGE_MASK) ^ ((sgaddr + sglen - 1) & IO_PAGE_MASK)) { - unsigned long next_page, diff; - - next_page = (sgaddr + IO_PAGE_SIZE) & IO_PAGE_MASK; - diff = next_page - sgaddr; - sgaddr += diff; - daddr += diff; - sglen -= diff; - dlen -= diff; - if (dlen > 0) - iopte++; - continue; - } - - /* SG wholly consumed within this page. */ - daddr += sglen; - dlen -= sglen; - - if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0)) - iopte++; - - sg = sg_next(sg); - if (--nents <= 0) - break; - sgaddr = (unsigned long) sg_virt(sg); - sglen = sg->length; - } - if (dlen < 0) { - /* Transfer overrun, big problems. */ - printk("verify_one_map: Transfer overrun by %d bytes.\n", - -dlen); - nents = -1; - } else { - /* Advance to next dma_sg implies that the next iopte will - * begin it. - */ - iopte++; - } - -out: - *__sg = sg; - *__iopte = iopte; - return nents; -} - -static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte) -{ - struct scatterlist *dma_sg = sg; - struct scatterlist *orig_dma_sg = dma_sg; - int orig_nents = nents; - - for (;;) { - nents = verify_one_map(dma_sg, &sg, nents, &iopte); - if (nents <= 0) - break; - dma_sg = sg_next(dma_sg); - if (dma_sg->dma_length == 0) - break; - } - - if (nents > 0) { - printk("verify_maps: dma maps consumed by some sgs remain (%d)\n", - nents); - return -1; - } - - if (nents < 0) { - printk("verify_maps: Error, messed up mappings, " - "at sg %d dma_sg %d\n", - (int) (orig_nents + nents), (int) (dma_sg - orig_dma_sg)); - return -1; - } - - /* This test passes... */ - return 0; -} - -void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int npages) -{ - struct scatterlist *sg; - - if (verify_lengths(sglist, nents, npages) < 0 || - verify_maps(sglist, nents, iopte) < 0) { - int i; - - printk("verify_sglist: Crap, messed up mappings, dumping, iodma at "); - printk("%016lx.\n", sglist->dma_address & IO_PAGE_MASK); - - for_each_sg(sglist, sg, nents, i) { - printk("sg(%d): page_addr(%p) off(%x) length(%x) " - "dma_address[%016x] dma_length[%016x]\n", - i, - page_address(sg_page(sg)), sg->offset, - sg->length, - sg->dma_address, sg->dma_length); - } - } - - /* Seems to be ok */ -} -#endif - -unsigned long prepare_sg(struct scatterlist *sg, int nents) -{ - struct scatterlist *dma_sg = sg; - unsigned long prev; - u32 dent_addr, dent_len; - - prev = (unsigned long) sg_virt(sg); - prev += (unsigned long) (dent_len = sg->length); - dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL)); - while (--nents) { - unsigned long addr; - - sg = sg_next(sg); - addr = (unsigned long) sg_virt(sg); - if (! VCONTIG(prev, addr)) { - dma_sg->dma_address = dent_addr; - dma_sg->dma_length = dent_len; - dma_sg = sg_next(dma_sg); - - dent_addr = ((dent_addr + - dent_len + - (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT); - dent_addr <<= IO_PAGE_SHIFT; - dent_addr += addr & (IO_PAGE_SIZE - 1UL); - dent_len = 0; - } - dent_len += sg->length; - prev = addr + sg->length; - } - dma_sg->dma_address = dent_addr; - dma_sg->dma_length = dent_len; - - if (dma_sg != sg) { - dma_sg = sg_next(dma_sg); - dma_sg->dma_length = 0; - } - - return ((unsigned long) dent_addr + - (unsigned long) dent_len + - (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT; -} diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h index 75b5a5814522..4b5cafa2877a 100644 --- a/arch/sparc64/kernel/iommu_common.h +++ b/arch/sparc64/kernel/iommu_common.h @@ -9,6 +9,7 @@ #include <linux/sched.h> #include <linux/mm.h> #include <linux/scatterlist.h> +#include <linux/device.h> #include <asm/iommu.h> #include <asm/scatterlist.h> @@ -29,6 +30,32 @@ */ #define IOMMU_PAGE_SHIFT 13 +#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG)))) + +static inline unsigned long iommu_num_pages(unsigned long vaddr, + unsigned long slen) +{ + unsigned long npages; + + npages = IO_PAGE_ALIGN(vaddr + slen) - (vaddr & IO_PAGE_MASK); + npages >>= IO_PAGE_SHIFT; + + return npages; +} + +static inline unsigned long calc_npages(struct scatterlist *sglist, int nelems) +{ + unsigned long i, npages = 0; + struct scatterlist *sg; + + for_each_sg(sglist, sg, nelems, i) { + unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg); + npages += iommu_num_pages(paddr, sg->length); + } + + return npages; +} + /* You are _strongly_ advised to enable the following debugging code * any time you make changes to the sg code below, run it for a while * with filesystems mounted read-only before buying the farm... -DaveM @@ -46,4 +73,4 @@ extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int #define VCONTIG(__X, __Y) (((__X) == (__Y)) || \ (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL) -extern unsigned long prepare_sg(struct scatterlist *sg, int nents); +extern unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents); diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S index 964527d2ffa0..cef8defcd7a9 100644 --- a/arch/sparc64/kernel/ktlb.S +++ b/arch/sparc64/kernel/ktlb.S @@ -1,6 +1,6 @@ /* arch/sparc64/kernel/ktlb.S: Kernel mapping TLB miss handling. * - * Copyright (C) 1995, 1997, 2005 David S. Miller <davem@davemloft.net> + * Copyright (C) 1995, 1997, 2005, 2008 David S. Miller <davem@davemloft.net> * Copyright (C) 1996 Eddie C. Dost (ecd@brainaid.de) * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1996,98,99 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -226,6 +226,7 @@ kvmap_dtlb_load: ba,pt %xcc, sun4v_dtlb_load mov %g5, %g3 +#ifdef CONFIG_SPARSEMEM_VMEMMAP kvmap_vmemmap: sub %g4, %g5, %g5 srlx %g5, 22, %g5 @@ -234,6 +235,7 @@ kvmap_vmemmap: or %g1, %lo(vmemmap_table), %g1 ba,pt %xcc, kvmap_dtlb_load ldx [%g1 + %g5], %g5 +#endif kvmap_dtlb_nonlinear: /* Catch kernel NULL pointer derefs. */ @@ -242,12 +244,14 @@ kvmap_dtlb_nonlinear: bleu,pn %xcc, kvmap_dtlb_longpath nop +#ifdef CONFIG_SPARSEMEM_VMEMMAP /* Do not use the TSB for vmemmap. */ mov (VMEMMAP_BASE >> 24), %g5 sllx %g5, 24, %g5 cmp %g4,%g5 bgeu,pn %xcc, kvmap_vmemmap nop +#endif KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 63b3ebc0c3c2..a61c38fe75ea 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -1275,4 +1275,20 @@ int pci_dma_supported(struct pci_dev *pdev, u64 device_mask) return (device_mask & dma_addr_mask) == dma_addr_mask; } +void pci_resource_to_user(const struct pci_dev *pdev, int bar, + const struct resource *rp, resource_size_t *start, + resource_size_t *end) +{ + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; + unsigned long offset; + + if (rp->flags & IORESOURCE_IO) + offset = pbm->io_space.start; + else + offset = pbm->mem_space.start; + + *start = rp->start - offset; + *end = rp->end - offset; +} + #endif /* !(CONFIG_PCI) */ diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index fef3b37487bf..7571ed563147 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -30,7 +30,7 @@ "i" (ASI_PHYS_BYPASS_EC_E) \ : "memory") -static void pci_fire_scan_bus(struct pci_pbm_info *pbm) +static void __init pci_fire_scan_bus(struct pci_pbm_info *pbm) { pbm->pci_bus = pci_scan_one_pbm(pbm); @@ -434,8 +434,8 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0); } -static int pci_fire_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid) +static int __init pci_fire_pbm_init(struct pci_controller_info *p, + struct device_node *dp, u32 portid) { const struct linux_prom64_registers *regs; struct pci_pbm_info *pbm; @@ -488,7 +488,7 @@ static inline int portid_compare(u32 x, u32 y) return 0; } -void fire_pci_init(struct device_node *dp, const char *model_name) +void __init fire_pci_init(struct device_node *dp, const char *model_name) { struct pci_controller_info *p; u32 portid = of_getintprop_default(dp, "portid", 0xff); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index d27ee5d528a2..0bad96e5d184 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -801,7 +801,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void psycho_scan_bus(struct pci_pbm_info *pbm) +static void __init psycho_scan_bus(struct pci_pbm_info *pbm) { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = 0; @@ -965,7 +965,7 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, #define PSYCHO_MEMSPACE_B 0x180000000UL #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL -static void psycho_pbm_init(struct pci_controller_info *p, +static void __init psycho_pbm_init(struct pci_controller_info *p, struct device_node *dp, int is_pbm_a) { struct property *prop; @@ -1012,7 +1012,7 @@ static void psycho_pbm_init(struct pci_controller_info *p, #define PSYCHO_CONFIGSPACE 0x001000000UL -void psycho_init(struct device_node *dp, char *model_name) +void __init psycho_init(struct device_node *dp, char *model_name) { struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index fba67c3d8809..1c5f5fa2339f 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -633,7 +633,7 @@ static void apb_init(struct pci_bus *sabre_bus) } } -static void sabre_scan_bus(struct pci_pbm_info *pbm) +static void __init sabre_scan_bus(struct pci_pbm_info *pbm) { static int once; @@ -731,7 +731,8 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, return 0; } -static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *pbm, struct device_node *dp) +static void __init sabre_pbm_init(struct pci_controller_info *p, + struct pci_pbm_info *pbm, struct device_node *dp) { pbm->name = dp->full_name; printk("%s: SABRE PCI Bus Module\n", pbm->name); @@ -750,7 +751,7 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *p pci_determine_mem_io_space(pbm); } -void sabre_init(struct device_node *dp, char *model_name) +void __init sabre_init(struct device_node *dp, char *model_name) { const struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 9546ba9f5dee..e30609362322 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -850,7 +850,7 @@ static int pbm_routes_this_ino(struct pci_pbm_info *pbm, u32 ino) /* How the Tomatillo IRQs are routed around is pure guesswork here. * * All the Tomatillo devices I see in prtconf dumps seem to have only - * a single PCI bus unit attached to it. It would seem they are seperate + * a single PCI bus unit attached to it. It would seem they are separate * devices because their PortID (ie. JBUS ID) values are all different * and thus the registers are mapped to totally different locations. * @@ -1084,7 +1084,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void schizo_scan_bus(struct pci_pbm_info *pbm) +static void __init schizo_scan_bus(struct pci_pbm_info *pbm) { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = @@ -1333,9 +1333,9 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) } } -static int schizo_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid, - int chip_type) +static int __init schizo_pbm_init(struct pci_controller_info *p, + struct device_node *dp, u32 portid, + int chip_type) { const struct linux_prom64_registers *regs; struct pci_pbm_info *pbm; @@ -1430,7 +1430,8 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) return (x == y); } -static void __schizo_init(struct device_node *dp, char *model_name, int chip_type) +static void __init __schizo_init(struct device_node *dp, char *model_name, + int chip_type) { struct pci_controller_info *p; struct pci_pbm_info *pbm; @@ -1474,17 +1475,17 @@ fatal_memory_error: prom_halt(); } -void schizo_init(struct device_node *dp, char *model_name) +void __init schizo_init(struct device_node *dp, char *model_name) { __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO); } -void schizo_plus_init(struct device_node *dp, char *model_name) +void __init schizo_plus_init(struct device_node *dp, char *model_name) { __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); } -void tomatillo_init(struct device_node *dp, char *model_name) +void __init tomatillo_init(struct device_node *dp, char *model_name) { __schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO); } diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index e587a372f3fe..61baf8dc095e 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -365,113 +365,14 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr, spin_unlock_irqrestore(&iommu->lock, flags); } -#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG)))) - -static long fill_sg(long entry, struct device *dev, - struct scatterlist *sg, - int nused, int nelems, unsigned long prot) -{ - struct scatterlist *dma_sg = sg; - unsigned long flags; - int i; - - local_irq_save(flags); - - iommu_batch_start(dev, prot, entry); - - for (i = 0; i < nused; i++) { - unsigned long pteval = ~0UL; - u32 dma_npages; - - dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) + - dma_sg->dma_length + - ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT; - do { - unsigned long offset; - signed int len; - - /* If we are here, we know we have at least one - * more page to map. So walk forward until we - * hit a page crossing, and begin creating new - * mappings from that spot. - */ - for (;;) { - unsigned long tmp; - - tmp = SG_ENT_PHYS_ADDRESS(sg); - len = sg->length; - if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) { - pteval = tmp & IO_PAGE_MASK; - offset = tmp & (IO_PAGE_SIZE - 1UL); - break; - } - if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) { - pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK; - offset = 0UL; - len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL))); - break; - } - sg = sg_next(sg); - nelems--; - } - - pteval = (pteval & IOPTE_PAGE); - while (len > 0) { - long err; - - err = iommu_batch_add(pteval); - if (unlikely(err < 0L)) - goto iommu_map_failed; - - pteval += IO_PAGE_SIZE; - len -= (IO_PAGE_SIZE - offset); - offset = 0; - dma_npages--; - } - - pteval = (pteval & IOPTE_PAGE) + len; - sg = sg_next(sg); - nelems--; - - /* Skip over any tail mappings we've fully mapped, - * adjusting pteval along the way. Stop when we - * detect a page crossing event. - */ - while (nelems && - (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && - (pteval == SG_ENT_PHYS_ADDRESS(sg)) && - ((pteval ^ - (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { - pteval += sg->length; - sg = sg_next(sg); - nelems--; - } - if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) - pteval = ~0UL; - } while (dma_npages != 0); - dma_sg = sg_next(dma_sg); - } - - if (unlikely(iommu_batch_end() < 0L)) - goto iommu_map_failed; - - local_irq_restore(flags); - return 0; - -iommu_map_failed: - local_irq_restore(flags); - return -1L; -} - static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { + unsigned long flags, npages, i, prot; + struct scatterlist *sg; struct iommu *iommu; - unsigned long flags, npages, prot; - u32 dma_base; - struct scatterlist *sgtmp; long entry, err; - int used; + u32 dma_base; /* Fast path single entry scatterlists. */ if (nelems == 1) { @@ -489,10 +390,8 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, if (unlikely(direction == DMA_NONE)) goto bad; - /* Step 1: Prepare scatter list. */ - npages = prepare_sg(sglist, nelems); + npages = calc_npages(sglist, nelems); - /* Step 2: Allocate a cluster and context, if necessary. */ spin_lock_irqsave(&iommu->lock, flags); entry = arena_alloc(&iommu->arena, npages); spin_unlock_irqrestore(&iommu->lock, flags); @@ -503,27 +402,45 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, dma_base = iommu->page_table_map_base + (entry << IO_PAGE_SHIFT); - /* Step 3: Normalize DMA addresses. */ - used = nelems; - - sgtmp = sglist; - while (used && sgtmp->dma_length) { - sgtmp->dma_address += dma_base; - sgtmp = sg_next(sgtmp); - used--; - } - used = nelems - used; - - /* Step 4: Create the mappings. */ prot = HV_PCI_MAP_ATTR_READ; if (direction != DMA_TO_DEVICE) prot |= HV_PCI_MAP_ATTR_WRITE; - err = fill_sg(entry, dev, sglist, used, nelems, prot); + local_irq_save(flags); + + iommu_batch_start(dev, prot, entry); + + for_each_sg(sglist, sg, nelems, i) { + unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg); + unsigned long slen = sg->length; + unsigned long this_npages; + + this_npages = iommu_num_pages(paddr, slen); + + sg->dma_address = dma_base | (paddr & ~IO_PAGE_MASK); + sg->dma_length = slen; + + paddr &= IO_PAGE_MASK; + while (this_npages--) { + err = iommu_batch_add(paddr); + if (unlikely(err < 0L)) { + local_irq_restore(flags); + goto iommu_map_failed; + } + + paddr += IO_PAGE_SIZE; + dma_base += IO_PAGE_SIZE; + } + } + + err = iommu_batch_end(); + + local_irq_restore(flags); + if (unlikely(err < 0L)) goto iommu_map_failed; - return used; + return nelems; bad: if (printk_ratelimit()) @@ -541,12 +458,11 @@ iommu_map_failed: static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { + unsigned long flags, npages; struct pci_pbm_info *pbm; + u32 devhandle, bus_addr; struct iommu *iommu; - unsigned long flags, i, npages; - struct scatterlist *sg, *sgprv; long entry; - u32 devhandle, bus_addr; if (unlikely(direction == DMA_NONE)) { if (printk_ratelimit()) @@ -558,16 +474,8 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist, devhandle = pbm->devhandle; bus_addr = sglist->dma_address & IO_PAGE_MASK; - sgprv = NULL; - for_each_sg(sglist, sg, nelems, i) { - if (sg->dma_length == 0) - break; - - sgprv = sg; - } - npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) - - bus_addr) >> IO_PAGE_SHIFT; + npages = calc_npages(sglist, nelems); entry = ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); @@ -612,7 +520,7 @@ const struct dma_ops sun4v_dma_ops = { .sync_sg_for_cpu = dma_4v_sync_sg_for_cpu, }; -static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm) +static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm) { struct property *prop; struct device_node *dp; @@ -625,8 +533,8 @@ static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm) /* XXX register error interrupt handlers XXX */ } -static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, - struct iommu *iommu) +static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm, + struct iommu *iommu) { struct iommu_arena *arena = &iommu->arena; unsigned long i, cnt = 0; @@ -653,7 +561,7 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, return cnt; } -static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) +static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) { struct iommu *iommu = pbm->iommu; struct property *prop; @@ -960,7 +868,8 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) } #endif /* !(CONFIG_PCI_MSI) */ -static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) +static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, + struct device_node *dp, u32 devhandle) { struct pci_pbm_info *pbm; diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 0f5be828ee92..a813441b358f 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -421,7 +421,7 @@ static void c_stop(struct seq_file *m, void *v) { } -struct seq_operations cpuinfo_op = { +const struct seq_operations cpuinfo_op = { .start =c_start, .next = c_next, .stop = c_stop, diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index c39944927f1a..a8052b76df41 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -46,8 +46,6 @@ #include <asm/ldc.h> #include <asm/hypervisor.h> -extern void calibrate_delay(void); - int sparc64_multi_core __read_mostly; cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 60765e314bd8..8649635d6d74 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -277,6 +277,7 @@ EXPORT_SYMBOL(sys_getpid); EXPORT_SYMBOL(sys_geteuid); EXPORT_SYMBOL(sys_getuid); EXPORT_SYMBOL(sys_getegid); +EXPORT_SYMBOL(sysctl_nr_open); EXPORT_SYMBOL(sys_getgid); EXPORT_SYMBOL(svr4_getcontext); EXPORT_SYMBOL(svr4_setcontext); diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc64/kernel/sun4v_tlb_miss.S index 9871dbb1ab42..fd9430562e0b 100644 --- a/arch/sparc64/kernel/sun4v_tlb_miss.S +++ b/arch/sparc64/kernel/sun4v_tlb_miss.S @@ -215,6 +215,7 @@ sun4v_itlb_error: 1: ba,pt %xcc, etrap 2: or %g7, %lo(2b), %g7 + mov %l4, %o1 call sun4v_itlb_error_report add %sp, PTREGS_OFF, %o0 @@ -241,6 +242,7 @@ sun4v_dtlb_error: 1: ba,pt %xcc, etrap 2: or %g7, %lo(2b), %g7 + mov %l4, %o1 call sun4v_dtlb_error_report add %sp, PTREGS_OFF, %o0 diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 06d10907d8ce..adc62f490f36 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -80,7 +80,8 @@ sys_call_table32: .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare /*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy .word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait -/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, compat_sys_timerfd, sys_eventfd, compat_sys_fallocate +/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate + .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime #endif /* CONFIG_COMPAT */ @@ -152,7 +153,8 @@ sys_call_table: .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare /*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait -/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate +/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate + .word sys_timerfd_settime, sys_timerfd_gettime #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) @@ -271,6 +273,7 @@ sunos_sys_table: .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys /*310*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys #endif diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 4352ee4d8dac..d204f1ab1d4c 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -1707,6 +1707,11 @@ static void __exit rtc_mini_exit(void) misc_deregister(&rtc_mini_dev); } +int __devinit read_current_timer(unsigned long *timer_val) +{ + *timer_val = tick_ops->get_tick(); + return 0; +} module_init(rtc_mini_init); module_exit(rtc_mini_exit); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 04998388259f..2b6abf633343 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -1950,6 +1950,8 @@ void sun4v_itlb_error_report(struct pt_regs *regs, int tl) printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl); print_symbol(KERN_EMERG "SUN4V-ITLB: TPC<%s>\n", regs->tpc); + printk(KERN_EMERG "SUN4V-ITLB: O7[%lx]\n", regs->u_regs[UREG_I7]); + print_symbol(KERN_EMERG "SUN4V-ITLB: O7<%s>\n", regs->u_regs[UREG_I7]); printk(KERN_EMERG "SUN4V-ITLB: vaddr[%lx] ctx[%lx] " "pte[%lx] error[%lx]\n", sun4v_err_itlb_vaddr, sun4v_err_itlb_ctx, @@ -1971,6 +1973,8 @@ void sun4v_dtlb_error_report(struct pt_regs *regs, int tl) printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl); print_symbol(KERN_EMERG "SUN4V-DTLB: TPC<%s>\n", regs->tpc); + printk(KERN_EMERG "SUN4V-DTLB: O7[%lx]\n", regs->u_regs[UREG_I7]); + print_symbol(KERN_EMERG "SUN4V-DTLB: O7<%s>\n", regs->u_regs[UREG_I7]); printk(KERN_EMERG "SUN4V-DTLB: vaddr[%lx] ctx[%lx] " "pte[%lx] error[%lx]\n", sun4v_err_dtlb_vaddr, sun4v_err_dtlb_ctx, diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index 953be816fa25..dc7bf1b6321c 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -175,7 +175,7 @@ unsigned long compute_effective_address(struct pt_regs *regs, } /* This is just to make gcc think die_if_kernel does return... */ -static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs) +static void __used unaligned_panic(char *str, struct pt_regs *regs) { die_if_kernel(str, regs); } diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index 0c1ee619d814..e78b3517940b 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c @@ -131,7 +131,7 @@ void vio_unregister_driver(struct vio_driver *viodrv) } EXPORT_SYMBOL(vio_unregister_driver); -static void __devinit vio_dev_release(struct device *dev) +static void vio_dev_release(struct device *dev) { kfree(to_vio_dev(dev)); } diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S index 9fcd503bc04a..01f809617e5e 100644 --- a/arch/sparc64/kernel/vmlinux.lds.S +++ b/arch/sparc64/kernel/vmlinux.lds.S @@ -56,11 +56,11 @@ SECTIONS .init.text : { __init_begin = .; _sinittext = .; - *(.init.text) + INIT_TEXT _einittext = .; } .init.data : { - *(.init.data) + INIT_DATA } . = ALIGN(16); .init.setup : { @@ -137,8 +137,8 @@ SECTIONS PROVIDE (end = .); /DISCARD/ : { - *(.exit.text) - *(.exit.data) + EXIT_TEXT + EXIT_DATA *(.exitcall.exit) } |