Loading arch/ia64/ia32/sys_ia32.c +1 −1 Original line number Diff line number Diff line Loading @@ -2427,7 +2427,7 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents, { struct epoll_event *events64 = NULL; mm_segment_t old_fs = get_fs(); int error, numevents, size; int numevents, size; int evt_idx; int do_free_pages = 0; Loading arch/ia64/kernel/mca.c +2 −2 Original line number Diff line number Diff line Loading @@ -1103,8 +1103,6 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) return IRQ_HANDLED; } #endif /* CONFIG_ACPI */ /* * ia64_mca_cpe_poll * Loading @@ -1122,6 +1120,8 @@ ia64_mca_cpe_poll (unsigned long dummy) platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0); } #endif /* CONFIG_ACPI */ /* * C portion of the OS INIT handler * Loading arch/ppc64/kernel/prom_init.c +61 −41 Original line number Diff line number Diff line Loading @@ -211,13 +211,23 @@ struct { */ #define ADDR(x) (u32) ((unsigned long)(x) - offset) /* * Error results ... some OF calls will return "-1" on error, some * will return 0, some will return either. To simplify, here are * macros to use with any ihandle or phandle return value to check if * it is valid */ #define PROM_ERROR (-1u) #define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR) #define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR) /* This is the one and *ONLY* place where we actually call open * firmware from, since we need to make sure we're running in 32b * mode when we do. We switch back to 64b mode upon return. */ #define PROM_ERROR (-1) static int __init call_prom(const char *service, int nargs, int nret, ...) { int i; Loading Loading @@ -587,14 +597,13 @@ static void __init prom_send_capabilities(void) { unsigned long offset = reloc_offset(); ihandle elfloader; int ret; elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); if (elfloader == 0) { prom_printf("couldn't open /packages/elf-loader\n"); return; } ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"), call_prom("call-method", 3, 1, ADDR("process-elf-header"), elfloader, ADDR(&fake_elf)); call_prom("close", 1, 0, elfloader); } Loading Loading @@ -646,7 +655,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align) base = _ALIGN_UP(base + 0x100000, align)) { prom_debug(" trying: 0x%x\n\r", base); addr = (unsigned long)prom_claim(base, size, 0); if ((int)addr != PROM_ERROR) if (addr != PROM_ERROR) break; addr = 0; if (align == 0) Loading Loading @@ -708,7 +717,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align, for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { prom_debug(" trying: 0x%x\n\r", base); addr = (unsigned long)prom_claim(base, size, 0); if ((int)addr != PROM_ERROR) if (addr != PROM_ERROR) break; addr = 0; } Loading Loading @@ -902,18 +911,19 @@ static void __init prom_instantiate_rtas(void) { unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); phandle prom_rtas, rtas_node; phandle rtas_node; ihandle rtas_inst; u32 base, entry = 0; u32 size = 0; prom_debug("prom_instantiate_rtas: start...\n"); prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); prom_debug("prom_rtas: %x\n", prom_rtas); if (prom_rtas == (phandle) -1) rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas")); prom_debug("rtas_node: %x\n", rtas_node); if (!PHANDLE_VALID(rtas_node)) return; prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size)); prom_getprop(rtas_node, "rtas-size", &size, sizeof(size)); if (size == 0) return; Loading @@ -922,14 +932,18 @@ static void __init prom_instantiate_rtas(void) prom_printf("RTAS allocation failed !\n"); return; } prom_printf("instantiating rtas at 0x%x", base); rtas_node = call_prom("open", 1, 1, ADDR("/rtas")); prom_printf("..."); rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); if (!IHANDLE_VALID(rtas_inst)) { prom_printf("opening rtas package failed"); return; } prom_printf("instantiating rtas at 0x%x ...", base); if (call_prom("call-method", 3, 2, ADDR("instantiate-rtas"), rtas_node, base) != PROM_ERROR) { rtas_inst, base) != PROM_ERROR) { entry = (long)_prom->args.rets[1]; } if (entry == 0) { Loading @@ -940,8 +954,8 @@ static void __init prom_instantiate_rtas(void) reserve_mem(base, size); prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base)); prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry)); prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); prom_debug("rtas base = 0x%x\n", base); prom_debug("rtas entry = 0x%x\n", entry); Loading Loading @@ -1062,7 +1076,7 @@ static void __init prom_initialize_tce_table(void) prom_printf("opening PHB %s", path); phb_node = call_prom("open", 1, 1, path); if ( (long)phb_node <= 0) if (phb_node == 0) prom_printf("... failed\n"); else prom_printf("... done\n"); Loading Loading @@ -1279,12 +1293,12 @@ static void __init prom_init_client_services(unsigned long pp) /* get a handle for the stdout device */ _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); if ((long)_prom->chosen <= 0) if (!PHANDLE_VALID(_prom->chosen)) prom_panic("cannot find chosen"); /* msg won't be printed :( */ /* get device tree root */ _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); if ((long)_prom->root <= 0) if (!PHANDLE_VALID(_prom->root)) prom_panic("cannot find device tree root"); /* msg won't be printed :( */ } Loading Loading @@ -1356,9 +1370,8 @@ static int __init prom_find_machine_type(void) } /* Default to pSeries. We need to know if we are running LPAR */ rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); if (rtas != (phandle) -1) { unsigned long x; x = prom_getproplen(rtas, "ibm,hypertas-functions"); if (!PHANDLE_VALID(rtas)) { int x = prom_getproplen(rtas, "ibm,hypertas-functions"); if (x != PROM_ERROR) { prom_printf("Hypertas detected, assuming LPAR !\n"); return PLATFORM_PSERIES_LPAR; Loading Loading @@ -1426,12 +1439,13 @@ static void __init prom_check_displays(void) * leave some room at the end of the path for appending extra * arguments */ if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0) if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) == PROM_ERROR) continue; prom_printf("found display : %s, opening ... ", path); ih = call_prom("open", 1, 1, path); if (ih == (ihandle)0 || ih == (ihandle)-1) { if (ih == 0) { prom_printf("failed\n"); continue; } Loading Loading @@ -1514,6 +1528,12 @@ static unsigned long __init dt_find_string(char *str) return 0; } /* * The Open Firmware 1275 specification states properties must be 31 bytes or * less, however not all firmwares obey this. Make it 64 bytes to be safe. */ #define MAX_PROPERTY_NAME 64 static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, unsigned long *mem_end) { Loading @@ -1527,10 +1547,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, /* get and store all property names */ prev_name = RELOC(""); for (;;) { int rc; /* 32 is max len of name including nul. */ namep = make_room(mem_start, mem_end, 32, 1); if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) { /* 64 is max len of name including nul. */ namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); rc = call_prom("nextprop", 3, 1, node, prev_name, namep); if (rc != 1) { /* No more nodes: unwind alloc */ *mem_start = (unsigned long)namep; break; Loading @@ -1555,12 +1577,6 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, } } /* * The Open Firmware 1275 specification states properties must be 31 bytes or * less, however not all firmwares obey this. Make it 64 bytes to be safe. */ #define MAX_PROPERTY_NAME 64 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, unsigned long *mem_end) { Loading Loading @@ -1607,7 +1623,10 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, prev_name = RELOC(""); sstart = (char *)RELOC(dt_string_start); for (;;) { if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0) int rc; rc = call_prom("nextprop", 3, 1, node, prev_name, pname); if (rc != 1) break; /* find string offset */ Loading @@ -1623,7 +1642,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, l = call_prom("getproplen", 2, 1, node, pname); /* sanity checks */ if (l < 0) if (l == PROM_ERROR) continue; if (l > MAX_PROPERTY_LENGTH) { prom_printf("WARNING: ignoring large property "); Loading Loading @@ -1771,17 +1790,18 @@ static void __init fixup_device_tree(void) /* Some G5s have a missing interrupt definition, fix it up here */ u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); if ((long)u3 <= 0) if (!PHANDLE_VALID(u3)) return; i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); if ((long)i2c <= 0) if (!PHANDLE_VALID(i2c)) return; mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); if ((long)mpic <= 0) if (!PHANDLE_VALID(mpic)) return; /* check if proper rev of u3 */ if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0) if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) == PROM_ERROR) return; if (u3_rev != 0x35) return; Loading arch/sparc64/kernel/pci_iommu.c +68 −20 Original line number Diff line number Diff line Loading @@ -196,6 +196,34 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long return NULL; } static int iommu_alloc_ctx(struct pci_iommu *iommu) { int lowest = iommu->ctx_lowest_free; int sz = IOMMU_NUM_CTXS - lowest; int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest); if (unlikely(n == sz)) { n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1); if (unlikely(n == lowest)) { printk(KERN_WARNING "IOMMU: Ran out of contexts.\n"); n = 0; } } if (n) __set_bit(n, iommu->ctx_bitmap); return n; } static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) { if (likely(ctx)) { __clear_bit(ctx, iommu->ctx_bitmap); if (ctx < iommu->ctx_lowest_free) iommu->ctx_lowest_free = ctx; } } /* Allocate and map kernel buffer of size SIZE using consistent mode * DMA for PCI device PDEV. Return non-NULL cpu-side address if * successful and set *DMA_ADDRP to the PCI side dma address. Loading Loading @@ -236,7 +264,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad npages = size >> IO_PAGE_SHIFT; ctx = 0; if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; ctx = iommu_alloc_ctx(iommu); first_page = __pa(first_page); while (npages--) { iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) | Loading Loading @@ -317,6 +345,8 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ } } iommu_free_ctx(iommu, ctx); spin_unlock_irqrestore(&iommu->lock, flags); order = get_order(size); Loading Loading @@ -360,7 +390,7 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct base_paddr = __pa(oaddr & IO_PAGE_MASK); ctx = 0; if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; ctx = iommu_alloc_ctx(iommu); if (strbuf->strbuf_enabled) iopte_protection = IOPTE_STREAMING(ctx); else Loading @@ -380,39 +410,53 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct return PCI_DMA_ERROR_CODE; } static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages) static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction) { int limit; PCI_STC_FLUSHFLAG_INIT(strbuf); if (strbuf->strbuf_ctxflush && iommu->iommu_ctxflush) { unsigned long matchreg, flushreg; u64 val; flushreg = strbuf->strbuf_ctxflush; matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); limit = 100000; pci_iommu_write(flushreg, ctx); for(;;) { if (((long)pci_iommu_read(matchreg)) >= 0L) break; limit--; if (!limit) break; udelay(1); val = pci_iommu_read(matchreg); val &= 0xffff; if (!val) goto do_flush_sync; while (val) { if (val & 0x1) pci_iommu_write(flushreg, ctx); val >>= 1; } if (!limit) val = pci_iommu_read(matchreg); if (unlikely(val)) { printk(KERN_WARNING "pci_strbuf_flush: ctx flush " "timeout vaddr[%08x] ctx[%lx]\n", vaddr, ctx); "timeout matchreg[%lx] ctx[%lx]\n", val, ctx); goto do_page_flush; } } else { unsigned long i; do_page_flush: for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, vaddr); } do_flush_sync: /* If the device could not have possibly put dirty data into * the streaming cache, no flush-flag synchronization needs * to be performed. */ if (direction == PCI_DMA_TODEVICE) return; PCI_STC_FLUSHFLAG_INIT(strbuf); pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); (void) pci_iommu_read(iommu->write_complete_reg); Loading Loading @@ -466,7 +510,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); /* Step 2: Clear out first TSB entry. */ iopte_make_dummy(iommu, base); Loading @@ -474,6 +518,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages, ctx); iommu_free_ctx(iommu, ctx); spin_unlock_irqrestore(&iommu->lock, flags); } Loading Loading @@ -613,7 +659,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int /* Step 4: Choose a context if necessary. */ ctx = 0; if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; ctx = iommu_alloc_ctx(iommu); /* Step 5: Create the mappings. */ if (strbuf->strbuf_enabled) Loading Loading @@ -678,7 +724,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); /* Step 2: Clear out first TSB entry. */ iopte_make_dummy(iommu, base); Loading @@ -686,6 +732,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages, ctx); iommu_free_ctx(iommu, ctx); spin_unlock_irqrestore(&iommu->lock, flags); } Loading Loading @@ -724,7 +772,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size } /* Step 2: Kick data out of streaming buffers. */ pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); spin_unlock_irqrestore(&iommu->lock, flags); } Loading Loading @@ -768,7 +816,7 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i i--; npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT; pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); spin_unlock_irqrestore(&iommu->lock, flags); } Loading arch/sparc64/kernel/pci_psycho.c +1 −1 Original line number Diff line number Diff line Loading @@ -1212,7 +1212,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) /* Setup initial software IOMMU state. */ spin_lock_init(&iommu->lock); iommu->iommu_cur_ctx = 0; iommu->ctx_lowest_free = 1; /* Register addresses. */ iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; Loading Loading
arch/ia64/ia32/sys_ia32.c +1 −1 Original line number Diff line number Diff line Loading @@ -2427,7 +2427,7 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents, { struct epoll_event *events64 = NULL; mm_segment_t old_fs = get_fs(); int error, numevents, size; int numevents, size; int evt_idx; int do_free_pages = 0; Loading
arch/ia64/kernel/mca.c +2 −2 Original line number Diff line number Diff line Loading @@ -1103,8 +1103,6 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) return IRQ_HANDLED; } #endif /* CONFIG_ACPI */ /* * ia64_mca_cpe_poll * Loading @@ -1122,6 +1120,8 @@ ia64_mca_cpe_poll (unsigned long dummy) platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0); } #endif /* CONFIG_ACPI */ /* * C portion of the OS INIT handler * Loading
arch/ppc64/kernel/prom_init.c +61 −41 Original line number Diff line number Diff line Loading @@ -211,13 +211,23 @@ struct { */ #define ADDR(x) (u32) ((unsigned long)(x) - offset) /* * Error results ... some OF calls will return "-1" on error, some * will return 0, some will return either. To simplify, here are * macros to use with any ihandle or phandle return value to check if * it is valid */ #define PROM_ERROR (-1u) #define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR) #define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR) /* This is the one and *ONLY* place where we actually call open * firmware from, since we need to make sure we're running in 32b * mode when we do. We switch back to 64b mode upon return. */ #define PROM_ERROR (-1) static int __init call_prom(const char *service, int nargs, int nret, ...) { int i; Loading Loading @@ -587,14 +597,13 @@ static void __init prom_send_capabilities(void) { unsigned long offset = reloc_offset(); ihandle elfloader; int ret; elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); if (elfloader == 0) { prom_printf("couldn't open /packages/elf-loader\n"); return; } ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"), call_prom("call-method", 3, 1, ADDR("process-elf-header"), elfloader, ADDR(&fake_elf)); call_prom("close", 1, 0, elfloader); } Loading Loading @@ -646,7 +655,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align) base = _ALIGN_UP(base + 0x100000, align)) { prom_debug(" trying: 0x%x\n\r", base); addr = (unsigned long)prom_claim(base, size, 0); if ((int)addr != PROM_ERROR) if (addr != PROM_ERROR) break; addr = 0; if (align == 0) Loading Loading @@ -708,7 +717,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align, for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { prom_debug(" trying: 0x%x\n\r", base); addr = (unsigned long)prom_claim(base, size, 0); if ((int)addr != PROM_ERROR) if (addr != PROM_ERROR) break; addr = 0; } Loading Loading @@ -902,18 +911,19 @@ static void __init prom_instantiate_rtas(void) { unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); phandle prom_rtas, rtas_node; phandle rtas_node; ihandle rtas_inst; u32 base, entry = 0; u32 size = 0; prom_debug("prom_instantiate_rtas: start...\n"); prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); prom_debug("prom_rtas: %x\n", prom_rtas); if (prom_rtas == (phandle) -1) rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas")); prom_debug("rtas_node: %x\n", rtas_node); if (!PHANDLE_VALID(rtas_node)) return; prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size)); prom_getprop(rtas_node, "rtas-size", &size, sizeof(size)); if (size == 0) return; Loading @@ -922,14 +932,18 @@ static void __init prom_instantiate_rtas(void) prom_printf("RTAS allocation failed !\n"); return; } prom_printf("instantiating rtas at 0x%x", base); rtas_node = call_prom("open", 1, 1, ADDR("/rtas")); prom_printf("..."); rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); if (!IHANDLE_VALID(rtas_inst)) { prom_printf("opening rtas package failed"); return; } prom_printf("instantiating rtas at 0x%x ...", base); if (call_prom("call-method", 3, 2, ADDR("instantiate-rtas"), rtas_node, base) != PROM_ERROR) { rtas_inst, base) != PROM_ERROR) { entry = (long)_prom->args.rets[1]; } if (entry == 0) { Loading @@ -940,8 +954,8 @@ static void __init prom_instantiate_rtas(void) reserve_mem(base, size); prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base)); prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry)); prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); prom_debug("rtas base = 0x%x\n", base); prom_debug("rtas entry = 0x%x\n", entry); Loading Loading @@ -1062,7 +1076,7 @@ static void __init prom_initialize_tce_table(void) prom_printf("opening PHB %s", path); phb_node = call_prom("open", 1, 1, path); if ( (long)phb_node <= 0) if (phb_node == 0) prom_printf("... failed\n"); else prom_printf("... done\n"); Loading Loading @@ -1279,12 +1293,12 @@ static void __init prom_init_client_services(unsigned long pp) /* get a handle for the stdout device */ _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); if ((long)_prom->chosen <= 0) if (!PHANDLE_VALID(_prom->chosen)) prom_panic("cannot find chosen"); /* msg won't be printed :( */ /* get device tree root */ _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); if ((long)_prom->root <= 0) if (!PHANDLE_VALID(_prom->root)) prom_panic("cannot find device tree root"); /* msg won't be printed :( */ } Loading Loading @@ -1356,9 +1370,8 @@ static int __init prom_find_machine_type(void) } /* Default to pSeries. We need to know if we are running LPAR */ rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); if (rtas != (phandle) -1) { unsigned long x; x = prom_getproplen(rtas, "ibm,hypertas-functions"); if (!PHANDLE_VALID(rtas)) { int x = prom_getproplen(rtas, "ibm,hypertas-functions"); if (x != PROM_ERROR) { prom_printf("Hypertas detected, assuming LPAR !\n"); return PLATFORM_PSERIES_LPAR; Loading Loading @@ -1426,12 +1439,13 @@ static void __init prom_check_displays(void) * leave some room at the end of the path for appending extra * arguments */ if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0) if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) == PROM_ERROR) continue; prom_printf("found display : %s, opening ... ", path); ih = call_prom("open", 1, 1, path); if (ih == (ihandle)0 || ih == (ihandle)-1) { if (ih == 0) { prom_printf("failed\n"); continue; } Loading Loading @@ -1514,6 +1528,12 @@ static unsigned long __init dt_find_string(char *str) return 0; } /* * The Open Firmware 1275 specification states properties must be 31 bytes or * less, however not all firmwares obey this. Make it 64 bytes to be safe. */ #define MAX_PROPERTY_NAME 64 static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, unsigned long *mem_end) { Loading @@ -1527,10 +1547,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, /* get and store all property names */ prev_name = RELOC(""); for (;;) { int rc; /* 32 is max len of name including nul. */ namep = make_room(mem_start, mem_end, 32, 1); if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) { /* 64 is max len of name including nul. */ namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); rc = call_prom("nextprop", 3, 1, node, prev_name, namep); if (rc != 1) { /* No more nodes: unwind alloc */ *mem_start = (unsigned long)namep; break; Loading @@ -1555,12 +1577,6 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, } } /* * The Open Firmware 1275 specification states properties must be 31 bytes or * less, however not all firmwares obey this. Make it 64 bytes to be safe. */ #define MAX_PROPERTY_NAME 64 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, unsigned long *mem_end) { Loading Loading @@ -1607,7 +1623,10 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, prev_name = RELOC(""); sstart = (char *)RELOC(dt_string_start); for (;;) { if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0) int rc; rc = call_prom("nextprop", 3, 1, node, prev_name, pname); if (rc != 1) break; /* find string offset */ Loading @@ -1623,7 +1642,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, l = call_prom("getproplen", 2, 1, node, pname); /* sanity checks */ if (l < 0) if (l == PROM_ERROR) continue; if (l > MAX_PROPERTY_LENGTH) { prom_printf("WARNING: ignoring large property "); Loading Loading @@ -1771,17 +1790,18 @@ static void __init fixup_device_tree(void) /* Some G5s have a missing interrupt definition, fix it up here */ u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); if ((long)u3 <= 0) if (!PHANDLE_VALID(u3)) return; i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); if ((long)i2c <= 0) if (!PHANDLE_VALID(i2c)) return; mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); if ((long)mpic <= 0) if (!PHANDLE_VALID(mpic)) return; /* check if proper rev of u3 */ if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0) if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) == PROM_ERROR) return; if (u3_rev != 0x35) return; Loading
arch/sparc64/kernel/pci_iommu.c +68 −20 Original line number Diff line number Diff line Loading @@ -196,6 +196,34 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long return NULL; } static int iommu_alloc_ctx(struct pci_iommu *iommu) { int lowest = iommu->ctx_lowest_free; int sz = IOMMU_NUM_CTXS - lowest; int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest); if (unlikely(n == sz)) { n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1); if (unlikely(n == lowest)) { printk(KERN_WARNING "IOMMU: Ran out of contexts.\n"); n = 0; } } if (n) __set_bit(n, iommu->ctx_bitmap); return n; } static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) { if (likely(ctx)) { __clear_bit(ctx, iommu->ctx_bitmap); if (ctx < iommu->ctx_lowest_free) iommu->ctx_lowest_free = ctx; } } /* Allocate and map kernel buffer of size SIZE using consistent mode * DMA for PCI device PDEV. Return non-NULL cpu-side address if * successful and set *DMA_ADDRP to the PCI side dma address. Loading Loading @@ -236,7 +264,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad npages = size >> IO_PAGE_SHIFT; ctx = 0; if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; ctx = iommu_alloc_ctx(iommu); first_page = __pa(first_page); while (npages--) { iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) | Loading Loading @@ -317,6 +345,8 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ } } iommu_free_ctx(iommu, ctx); spin_unlock_irqrestore(&iommu->lock, flags); order = get_order(size); Loading Loading @@ -360,7 +390,7 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct base_paddr = __pa(oaddr & IO_PAGE_MASK); ctx = 0; if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; ctx = iommu_alloc_ctx(iommu); if (strbuf->strbuf_enabled) iopte_protection = IOPTE_STREAMING(ctx); else Loading @@ -380,39 +410,53 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct return PCI_DMA_ERROR_CODE; } static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages) static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction) { int limit; PCI_STC_FLUSHFLAG_INIT(strbuf); if (strbuf->strbuf_ctxflush && iommu->iommu_ctxflush) { unsigned long matchreg, flushreg; u64 val; flushreg = strbuf->strbuf_ctxflush; matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx); limit = 100000; pci_iommu_write(flushreg, ctx); for(;;) { if (((long)pci_iommu_read(matchreg)) >= 0L) break; limit--; if (!limit) break; udelay(1); val = pci_iommu_read(matchreg); val &= 0xffff; if (!val) goto do_flush_sync; while (val) { if (val & 0x1) pci_iommu_write(flushreg, ctx); val >>= 1; } if (!limit) val = pci_iommu_read(matchreg); if (unlikely(val)) { printk(KERN_WARNING "pci_strbuf_flush: ctx flush " "timeout vaddr[%08x] ctx[%lx]\n", vaddr, ctx); "timeout matchreg[%lx] ctx[%lx]\n", val, ctx); goto do_page_flush; } } else { unsigned long i; do_page_flush: for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, vaddr); } do_flush_sync: /* If the device could not have possibly put dirty data into * the streaming cache, no flush-flag synchronization needs * to be performed. */ if (direction == PCI_DMA_TODEVICE) return; PCI_STC_FLUSHFLAG_INIT(strbuf); pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); (void) pci_iommu_read(iommu->write_complete_reg); Loading Loading @@ -466,7 +510,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); /* Step 2: Clear out first TSB entry. */ iopte_make_dummy(iommu, base); Loading @@ -474,6 +518,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages, ctx); iommu_free_ctx(iommu, ctx); spin_unlock_irqrestore(&iommu->lock, flags); } Loading Loading @@ -613,7 +659,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int /* Step 4: Choose a context if necessary. */ ctx = 0; if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; ctx = iommu_alloc_ctx(iommu); /* Step 5: Create the mappings. */ if (strbuf->strbuf_enabled) Loading Loading @@ -678,7 +724,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); /* Step 2: Clear out first TSB entry. */ iopte_make_dummy(iommu, base); Loading @@ -686,6 +732,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages, ctx); iommu_free_ctx(iommu, ctx); spin_unlock_irqrestore(&iommu->lock, flags); } Loading Loading @@ -724,7 +772,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size } /* Step 2: Kick data out of streaming buffers. */ pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); spin_unlock_irqrestore(&iommu->lock, flags); } Loading Loading @@ -768,7 +816,7 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i i--; npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT; pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages); pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); spin_unlock_irqrestore(&iommu->lock, flags); } Loading
arch/sparc64/kernel/pci_psycho.c +1 −1 Original line number Diff line number Diff line Loading @@ -1212,7 +1212,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) /* Setup initial software IOMMU state. */ spin_lock_init(&iommu->lock); iommu->iommu_cur_ctx = 0; iommu->ctx_lowest_free = 1; /* Register addresses. */ iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; Loading