From 36eaa6e4c0e0b6950136b956b72fd08155b92ca3 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 8 Sep 2003 23:38:49 -0700 Subject: [PATCH] [PATCH] PA-RISC update for 2.6.0-test5 PA-RISC updates for 2.6.0-test5. Contributions from Paul Bame, James Bottomley, Randolph Chung, Helge Deller, Grant Grundler, LaMont Jones, Matthew Wilcox --- arch/parisc/Kconfig | 2 +- arch/parisc/Makefile | 2 +- arch/parisc/defconfig | 14 +- arch/parisc/hpux/wrappers.S | 127 +++++++------- arch/parisc/kernel/cache.c | 30 +++- arch/parisc/kernel/drivers.c | 4 +- arch/parisc/kernel/irq.c | 4 + arch/parisc/kernel/module.c | 30 +++- arch/parisc/kernel/parisc_ksyms.c | 4 + arch/parisc/kernel/pci.c | 222 ++++++++----------------- arch/parisc/kernel/process.c | 1 - arch/parisc/kernel/real2.S | 17 +- arch/parisc/kernel/signal.c | 6 +- arch/parisc/kernel/sys_parisc.c | 59 +++++-- arch/parisc/kernel/sys_parisc32.c | 67 +++++--- arch/parisc/kernel/syscall.S | 4 +- arch/parisc/kernel/traps.c | 4 + arch/parisc/{ => kernel}/vmlinux.lds.S | 0 arch/parisc/nm | 6 + drivers/parisc/asp.c | 2 - drivers/parisc/ccio-dma.c | 162 +++++++++++++++++- drivers/parisc/dino.c | 75 +++++---- drivers/parisc/eisa.c | 5 +- drivers/parisc/hppb.c | 1 - drivers/parisc/iosapic.c | 2 +- drivers/parisc/lasi.c | 2 - drivers/parisc/lba_pci.c | 4 +- drivers/parisc/led.c | 2 +- drivers/parisc/sba_iommu.c | 2 - drivers/parisc/wax.c | 2 - include/asm-parisc/atomic.h | 17 +- include/asm-parisc/bitops.h | 109 ++++++++---- include/asm-parisc/byteorder.h | 50 +++--- include/asm-parisc/cacheflush.h | 5 +- include/asm-parisc/elf.h | 1 + include/asm-parisc/hil.h | 26 --- include/asm-parisc/io.h | 7 + include/asm-parisc/local.h | 40 +++++ include/asm-parisc/sections.h | 7 + include/asm-parisc/uaccess.h | 17 +- 40 files changed, 704 insertions(+), 437 deletions(-) rename arch/parisc/{ => kernel}/vmlinux.lds.S (100%) create mode 100644 arch/parisc/nm delete mode 100644 include/asm-parisc/hil.h create mode 100644 include/asm-parisc/local.h create mode 100644 include/asm-parisc/sections.h diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 461a9d9f9f58c..d3fdab8f9e908 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -184,7 +184,7 @@ source "drivers/scsi/Kconfig" source "drivers/md/Kconfig" -#source drivers/message/fusion/Kconfig +source drivers/message/fusion/Kconfig #source drivers/ieee1394/Kconfig diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index f615675a7442f..201156cae9226 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -16,7 +16,7 @@ # Modified for PA-RISC Linux by Paul Lahaie, Alex deVries, # Mike Shaver, Helge Deller and Martin K. Petersen # - +NM = sh arch/parisc/nm ifdef CONFIG_PARISC64 CROSS_COMPILE := hppa64-linux- UTS_MACHINE := parisc64 diff --git a/arch/parisc/defconfig b/arch/parisc/defconfig index bcc94fed0de01..9a2d0b9b82eae 100644 --- a/arch/parisc/defconfig +++ b/arch/parisc/defconfig @@ -150,24 +150,25 @@ CONFIG_CHR_DEV_SG=y CONFIG_SCSI_LASI700=y CONFIG_53C700_MEM_MAPPED=y CONFIG_53C700_LE_ON_BE=y -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set CONFIG_SCSI_ZALON=y -# CONFIG_SCSI_NCR53C8XX is not set -CONFIG_SCSI_SYM53C8XX=y CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set # CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set @@ -374,7 +375,6 @@ CONFIG_SERIO=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PARKBD is not set CONFIG_HP_SDC=y -CONFIG_HIL_MLC=y # # Input Device Drivers diff --git a/arch/parisc/hpux/wrappers.S b/arch/parisc/hpux/wrappers.S index 6f26159bed618..1aa936dfe1476 100644 --- a/arch/parisc/hpux/wrappers.S +++ b/arch/parisc/hpux/wrappers.S @@ -21,17 +21,20 @@ */ #ifdef __LP64__ -#warning Must be changed for PA64 +#warning PA64 support needs more work...did first cut #endif #include +#include +#include +#ifdef __LP64__ + .level 2.0w +#else .level 1.1 +#endif .text -#include -#include - /* These should probably go in a header file somewhere. * They are duplicated in kernel/wrappers.S * Possibly we should consider consolidating these @@ -41,41 +44,41 @@ #ifdef __LP64__ #warning NEEDS WORK for 64-bit #endif - stw %r3, PT_GR3(\regs) - stw %r4, PT_GR4(\regs) - stw %r5, PT_GR5(\regs) - stw %r6, PT_GR6(\regs) - stw %r7, PT_GR7(\regs) - stw %r8, PT_GR8(\regs) - stw %r9, PT_GR9(\regs) - stw %r10,PT_GR10(\regs) - stw %r11,PT_GR11(\regs) - stw %r12,PT_GR12(\regs) - stw %r13,PT_GR13(\regs) - stw %r14,PT_GR14(\regs) - stw %r15,PT_GR15(\regs) - stw %r16,PT_GR16(\regs) - stw %r17,PT_GR17(\regs) - stw %r18,PT_GR18(\regs) + STREG %r3, PT_GR3(\regs) + STREG %r4, PT_GR4(\regs) + STREG %r5, PT_GR5(\regs) + STREG %r6, PT_GR6(\regs) + STREG %r7, PT_GR7(\regs) + STREG %r8, PT_GR8(\regs) + STREG %r9, PT_GR9(\regs) + STREG %r10,PT_GR10(\regs) + STREG %r11,PT_GR11(\regs) + STREG %r12,PT_GR12(\regs) + STREG %r13,PT_GR13(\regs) + STREG %r14,PT_GR14(\regs) + STREG %r15,PT_GR15(\regs) + STREG %r16,PT_GR16(\regs) + STREG %r17,PT_GR17(\regs) + STREG %r18,PT_GR18(\regs) .endm .macro reg_restore regs - ldw PT_GR3(\regs), %r3 - ldw PT_GR4(\regs), %r4 - ldw PT_GR5(\regs), %r5 - ldw PT_GR6(\regs), %r6 - ldw PT_GR7(\regs), %r7 - ldw PT_GR8(\regs), %r8 - ldw PT_GR9(\regs), %r9 - ldw PT_GR10(\regs),%r10 - ldw PT_GR11(\regs),%r11 - ldw PT_GR12(\regs),%r12 - ldw PT_GR13(\regs),%r13 - ldw PT_GR14(\regs),%r14 - ldw PT_GR15(\regs),%r15 - ldw PT_GR16(\regs),%r16 - ldw PT_GR17(\regs),%r17 - ldw PT_GR18(\regs),%r18 + LDREG PT_GR3(\regs), %r3 + LDREG PT_GR4(\regs), %r4 + LDREG PT_GR5(\regs), %r5 + LDREG PT_GR6(\regs), %r6 + LDREG PT_GR7(\regs), %r7 + LDREG PT_GR8(\regs), %r8 + LDREG PT_GR9(\regs), %r9 + LDREG PT_GR10(\regs),%r10 + LDREG PT_GR11(\regs),%r11 + LDREG PT_GR12(\regs),%r12 + LDREG PT_GR13(\regs),%r13 + LDREG PT_GR14(\regs),%r14 + LDREG PT_GR15(\regs),%r15 + LDREG PT_GR16(\regs),%r16 + LDREG PT_GR17(\regs),%r17 + LDREG PT_GR18(\regs),%r18 .endm @@ -88,18 +91,18 @@ hpux_fork_wrapper: ;! pointer in task reg_save %r1 - stw %r2,-20(%r30) + STREG %r2,-20(%r30) ldo 64(%r30),%r30 - stw %r2,PT_GR19(%r1) ;! save for child - stw %r30,PT_GR21(%r1) ;! save for child + STREG %r2,PT_GR19(%r1) ;! save for child + STREG %r30,PT_GR21(%r1) ;! save for child - ldw PT_GR30(%r1),%r25 - mtctl %r25,%cr29 + LDREG PT_GR30(%r1),%r25 + mtctl %r25,%cr29 copy %r1,%r24 bl sys_clone,%r2 ldi SIGCHLD,%r26 - ldw -84(%r30),%r2 + LDREG -84(%r30),%r2 fork_return: ldo -64(%r30),%r30 ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs @@ -116,14 +119,14 @@ fork_return: * know the difference. We can fix this later if necessary. */ - ldo -1024(%r0),%r1 + ldo -1024(%r0),%r1 comb,>>=,n %r28,%r1,fork_exit /* just let the syscall exit handle it */ - or,= %r28,%r0,%r0 - or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */ - ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */ + or,= %r28,%r0,%r0 + or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */ + ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */ fork_exit: - bv %r0(%r2) + bv %r0(%r2) nop /* Set the return value for the child */ @@ -134,7 +137,7 @@ hpux_child_return: nop #endif - ldw TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 + LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 b fork_return copy %r0,%r28 @@ -157,17 +160,17 @@ hpux_execve_wrapper: /* Store arg0, arg1 and arg2 so that hpux_execve will find them */ - stw %r26,PT_GR26(%r1) - stw %r25,PT_GR25(%r1) - stw %r24,PT_GR24(%r1) + STREG %r26,PT_GR26(%r1) + STREG %r25,PT_GR25(%r1) + STREG %r24,PT_GR24(%r1) - stw %r2,-20(%r30) + STREG %r2,-20(%r30) ldo 64(%r30),%r30 bl hpux_execve,%r2 copy %r1,%arg0 ldo -64(%r30),%r30 - ldw -20(%r30),%r2 + LDREG -20(%r30),%r2 /* If exec succeeded we need to load the args */ @@ -175,10 +178,10 @@ hpux_execve_wrapper: comb,>>= %r28,%r1,exec_error copy %r2,%r19 ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr - ldw TASK_PT_GR26(%r1),%r26 - ldw TASK_PT_GR25(%r1),%r25 - ldw TASK_PT_GR24(%r1),%r24 - ldw TASK_PT_GR23(%r1),%r23 + LDREG TASK_PT_GR26(%r1),%r26 + LDREG TASK_PT_GR25(%r1),%r25 + LDREG TASK_PT_GR24(%r1),%r24 + LDREG TASK_PT_GR23(%r1),%r23 copy %r0,%r2 /* Flag to syscall_exit not to clear args */ exec_error: @@ -191,7 +194,7 @@ exec_error: /* HP-UX expects pipefd's returned in r28 & r29 */ hpux_pipe_wrapper: - stw %r2,-20(%r30) + STREG %r2,-20(%r30) ldo 64(%r30),%r30 bl hpux_pipe,%r2 ldo -56(%r30),%r26 /* pass local array to hpux_pipe */ @@ -199,12 +202,12 @@ hpux_pipe_wrapper: ldo -1024(%r0),%r1 comb,>>= %r28,%r1,pipe_exit /* let syscall exit handle it */ - ldw -84(%r30),%r2 + LDREG -84(%r30),%r2 /* if success, load fd's from stack array */ - ldw -56(%r30),%r28 - ldw -52(%r30),%r29 + LDREG -56(%r30),%r28 + LDREG -52(%r30),%r29 pipe_exit: bv %r0(%r2) @@ -251,4 +254,4 @@ no_error: hpux_unimplemented_wrapper: b hpux_unimplemented - stw %r22,-64(%r30) /* overwrite arg8 with syscall number */ + STREG %r22,-64(%r30) /* overwrite arg8 with syscall number */ diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index a54ff14f1d29a..63110ae4d200d 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -232,7 +232,8 @@ void __flush_dcache_page(struct page *page) if (!page->mapping) return; - + /* check shared list first if it's not empty...it's usually + * the shortest */ list_for_each(l, &page->mapping->i_mmap_shared) { struct vm_area_struct *mpnt; unsigned long off; @@ -254,6 +255,33 @@ void __flush_dcache_page(struct page *page) flush_cache_page(mpnt, mpnt->vm_start + (off << PAGE_SHIFT)); + /* All user shared mappings should be equivalently mapped, + * so once we've flushed one we should be ok + */ + return; + } + + /* then check private mapping list for read only shared mappings + * which are flagged by VM_MAYSHARE */ + list_for_each(l, &page->mapping->i_mmap) { + struct vm_area_struct *mpnt; + unsigned long off; + + mpnt = list_entry(l, struct vm_area_struct, shared); + + + if (mpnt->vm_mm != mm || !(mpnt->vm_flags & VM_MAYSHARE)) + continue; + + if (page->index < mpnt->vm_pgoff) + continue; + + off = page->index - mpnt->vm_pgoff; + if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT) + continue; + + flush_cache_page(mpnt, mpnt->vm_start + (off << PAGE_SHIFT)); + /* All user shared mappings should be equivalently mapped, * so once we've flushed one we should be ok */ diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 047e32aa781a7..c5d8401dded7b 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -447,7 +447,7 @@ int register_parisc_device(struct parisc_device *dev) #define MAX_NATIVE_DEVICES 64 #define NATIVE_DEVICE_OFFSET 0x1000 -#define FLEX_MASK (unsigned long)0xfffffffffffc0000 +#define FLEX_MASK F_EXTEND(0xfffc0000) #define IO_IO_LOW offsetof(struct bc_module, io_io_low) #define IO_IO_HIGH offsetof(struct bc_module, io_io_high) #define READ_IO_IO_LOW(dev) (unsigned long)(signed int)__raw_readl(dev->hpa + IO_IO_LOW) @@ -514,7 +514,7 @@ static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, } while(!devices_found && hpa < io_io_high); } -#define CENTRAL_BUS_ADDR (unsigned long) 0xfffffffffff80000 +#define CENTRAL_BUS_ADDR F_EXTEND(0xfff80000) /** * walk_central_bus - Find devices attached to the central bus diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 81e369f23f5ea..9d3a97a5b0bb1 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -842,6 +842,10 @@ int probe_irq_off(unsigned long val) return irq_found; } +unsigned int probe_irq_mask(unsigned long irqs) +{ + return 0; +} void __init init_IRQ(void) { diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 067f9e3a7991e..f7d5964b4e974 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -41,6 +41,13 @@ return -ENOEXEC; \ } +/* Maximum number of GOT entries. We use a long displacement ldd from + * the bottom of the table, which has a maximum signed displacement of + * 0x3fff; however, since we're only going forward, this becomes + * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have + * at most 1023 entries */ +#define MAX_GOTS 1023 + /* three functions to determine where in the module core * or init pieces the location is */ static inline int is_init(struct module *me, void *loc) @@ -300,11 +307,14 @@ static Elf64_Word get_got(struct module *me, unsigned long value, long addend) got = me->module_core + me->arch.got_offset; for (i = 0; got[i].addr; i++) if (got[i].addr == value) - return i * sizeof(struct got_entry); + goto out; BUG_ON(++me->arch.got_count > me->arch.got_max); got[i].addr = value; + out: + DEBUGP("GOT ENTRY %d[%x] val %lx\n", i, i*sizeof(struct got_entry), + value); return i * sizeof(struct got_entry); } #endif /* __LP64__ */ @@ -387,7 +397,7 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, stub->insns[2] = 0xe820d000; /* bve (%r1) */ stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ - stub->insns[0] |= reassemble_14(rrsel(get_got(me, value, addend),0)); + stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff); } else { @@ -516,6 +526,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, case R_PARISC_PCREL22F: /* 22-bit PC relative address; only defined for pa20 */ val = get_stub(me, val, addend, 0, is_init(me, loc)); + DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", + strtab + sym->st_name, (unsigned long)loc, addend, + val) val = (val - dot - 8)/4; CHECK_RELOC(val, 22); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); @@ -618,6 +631,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, val = get_stub(me, val, addend, 0, is_init(me, loc)); } + DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", + strtab + sym->st_name, loc, sym->st_value, + addend, val); /* FIXME: local symbols work as long as the * core and init pieces aren't separated too * far. If this is ever broken, you will trip @@ -646,6 +662,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, /* 64-bit function address */ if(is_local(me, (void *)(val + addend))) { *loc64 = get_fdesc(me, val+addend); + DEBUGP("FDESC for %s at %p points to %lx\n", + strtab + sym->st_name, *loc64, + ((struct fdesc_entry *)*loc64)->addr); } else { /* if the symbol is not local to this * module then val+addend is a pointer @@ -711,8 +730,13 @@ int module_finalize(const Elf_Ehdr *hdr, } } - printk("module %s: strtab %p, symhdr %p\n", + DEBUGP("module %s: strtab %p, symhdr %p\n", me->name, strtab, symhdr); + + if(me->arch.got_count > MAX_GOTS) { + printk(KERN_ERR "%s: Global Offset Table overflow (used %ld, allowed %d\n", me->name, me->arch.got_count, MAX_GOTS); + return -EINVAL; + } /* no symbol table */ if(symhdr == NULL) diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 5158dd2e2a047..4a16af09be6d3 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -37,6 +37,7 @@ EXPORT_SYMBOL(get_pci_node_path); #include EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(probe_irq_mask); #include EXPORT_SYMBOL(kernel_thread); @@ -201,6 +202,9 @@ EXPORT_SYMBOL(__ashldi3); EXPORT_SYMBOL(__lshrdi3); EXPORT_SYMBOL(__muldi3); +asmlinkage void * __canonicalize_funcptr_for_compare(void *); +EXPORT_SYMBOL(__canonicalize_funcptr_for_compare); + #ifdef __LP64__ extern void __divdi3(void); extern void __udivdi3(void); diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index f79fbdc1b7fcf..1e299167edfca 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -25,7 +25,7 @@ #define DEBUG_CONFIG 0 #if DEBUG_CONFIG -# define DBGC(x...) printk(KERN_DEBUG x) +# define DBGC(x...) printk(KERN_DEBUG x) #else # define DBGC(x...) #endif @@ -38,13 +38,15 @@ #endif /* To be used as: mdelay(pci_post_reset_delay); -** -** post_reset is the time the kernel should stall to prevent anyone from -** accessing the PCI bus once #RESET is de-asserted. -** PCI spec somewhere says 1 second but with multi-PCI bus systems, -** this makes the boot time much longer than necessary. -** 20ms seems to work for all the HP PCI implementations to date. -*/ + * + * post_reset is the time the kernel should stall to prevent anyone from + * accessing the PCI bus once #RESET is de-asserted. + * PCI spec somewhere says 1 second but with multi-PCI bus systems, + * this makes the boot time much longer than necessary. + * 20ms seems to work for all the HP PCI implementations to date. + * + * XXX: turn into a #defined constant in ? + */ int pci_post_reset_delay = 50; struct pci_port_ops *pci_port; @@ -52,9 +54,7 @@ struct pci_bios_ops *pci_bios; int pci_hba_count = 0; -/* -** parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. -*/ +/* parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. */ #define PCI_HBA_MAX 32 struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX]; @@ -129,8 +129,6 @@ static int __init pcibios_init(void) /* Called from pci_do_scan_bus() *after* walking a bus but before walking PPBs. */ void pcibios_fixup_bus(struct pci_bus *bus) { - ASSERT(pci_bios != NULL); - if (pci_bios->fixup_bus) { pci_bios->fixup_bus(bus); } else { @@ -145,64 +143,26 @@ char *pcibios_setup(char *str) } -/* -** Used in drivers/pci/quirks.c -*/ +/* Used in drivers/pci/quirks.c */ struct pci_fixup pcibios_fixups[] = { {0} }; /* -** called by drivers/pci/setup.c:pdev_fixup_irq() -*/ -void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) -{ -/* -** updates IRQ_LINE cfg register to reflect PCI-PCI bridge skewing. -** -** Calling path for Alpha is: -** alpha/kernel/pci.c:common_init_pci(swizzle_func, pci_map_irq_func ) -** drivers/pci/setup.c:pci_fixup_irqs() -** drivers/pci/setup.c:pci_fixup_irq() (for each PCI device) -** invoke swizzle and map functions -** alpha/kernel/pci.c:pcibios_update_irq() -** -** Don't need this for PA legacy PDC systems. -** -** On PAT PDC systems, We only support one "swizzle" for any number -** of PCI-PCI bridges deep. That's how bit3 PCI expansion chassis -** are implemented. The IRQ lines are "skewed" for all devices but -** *NOT* routed through the PCI-PCI bridge. Ie any device "0" will -** share an IRQ line. Legacy PDC is expecting this IRQ line routing -** as well. -** -** Unfortunately, PCI spec allows the IRQ lines to be routed -** around the PCI bridge as long as the IRQ lines are skewed -** based on the device number...... -** -** Lastly, dino.c might be able to use pci_fixup_irq() to -** support RS-232 and PS/2 children. Not sure how but it's -** something to think about. -*/ -} - - -/* -** Called by pci_set_master() - a driver interface. -** -** Legacy PDC guarantees to set: -** Map Memory BAR's into PA IO space. -** Map Expansion ROM BAR into one common PA IO space per bus. -** Map IO BAR's into PCI IO space. -** Command (see below) -** Cache Line Size -** Latency Timer -** Interrupt Line -** PPB: secondary latency timer, io/mmio base/limit, -** bus numbers, bridge control -** -*/ -void -pcibios_set_master(struct pci_dev *dev) + * Called by pci_set_master() - a driver interface. + * + * Legacy PDC guarantees to set: + * Map Memory BAR's into PA IO space. + * Map Expansion ROM BAR into one common PA IO space per bus. + * Map IO BAR's into PCI IO space. + * Command (see below) + * Cache Line Size + * Latency Timer + * Interrupt Line + * PPB: secondary latency timer, io/mmio base/limit, + * bus numbers, bridge control + * + */ +void pcibios_set_master(struct pci_dev *dev) { u8 lat; @@ -214,43 +174,36 @@ pcibios_set_master(struct pci_dev *dev) ** HP generally has fewer devices on the bus than other architectures. ** upper byte is PCI_LATENCY_TIMER. */ - pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, + pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, (0x80 << 8) | (L1_CACHE_BYTES / sizeof(u32))); } -void __init -pcibios_init_bus(struct pci_bus *bus) +void __init pcibios_init_bus(struct pci_bus *bus) { struct pci_dev *dev = bus->self; + unsigned short bridge_ctl; /* We deal only with pci controllers and pci-pci bridges. */ - if (dev && (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) + if (!dev || (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) return; - - if (dev) { - unsigned short bridge_ctl; - /* PCI-PCI bridge - set the cache line and default latency - (32) for primary and secondary buses. */ - pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32); + /* PCI-PCI bridge - set the cache line and default latency + (32) for primary and secondary buses. */ + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32); - /* Read bridge control */ - pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl); - pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl - | PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR); - - } + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl); + bridge_ctl |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl); } -/* -** KLUGE: Link the child and parent resources - generic PCI didn't -*/ +/* KLUGE: Link the child and parent resources - generic PCI didn't */ static void pcibios_link_hba_resources( struct resource *hba_res, struct resource *r) { if (!r->parent) { + printk(KERN_EMERG "PCI: Tell willy he's wrong\n"); r->parent = hba_res; /* reverse link is harder *sigh* */ @@ -268,14 +221,9 @@ pcibios_link_hba_resources( struct resource *hba_res, struct resource *r) } } -/* -** called by drivers/pci/setup-res.c:pci_setup_bridge(). -*/ -void __devinit pcibios_resource_to_bus( - struct pci_dev *dev, - struct pci_bus_region *region, - struct resource *res - ) +/* called by drivers/pci/setup-bus.c:pci_setup_bridge(). */ +void __devinit pcibios_resource_to_bus(struct pci_dev *dev, + struct pci_bus_region *region, struct resource *res) { struct pci_bus *bus = dev->bus; struct pci_hba_data *hba = HBA_DATA(bus->dev->platform_data); @@ -313,17 +261,16 @@ EXPORT_SYMBOL(pcibios_resource_to_bus); #endif /* -** pcibios align resources() is called everytime generic PCI code -** wants to generate a new address. The process of looking for -** an available address, each candidate is first "aligned" and -** then checked if the resource is available until a match is found. -** -** Since we are just checking candidates, don't use any fields other -** than res->start. -*/ -void __devinit -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long alignment) + * pcibios align resources() is called every time generic PCI code + * wants to generate a new address. The process of looking for + * an available address, each candidate is first "aligned" and + * then checked if the resource is available until a match is found. + * + * Since we are just checking candidates, don't use any fields other + * than res->start. + */ +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long alignment) { unsigned long mask, align; @@ -332,10 +279,6 @@ pcibios_align_resource(void *data, struct resource *res, res->parent, res->start, res->end, (int) res->flags, size, alignment); - /* has resource already been aligned/assigned? */ - if (res->parent) - return; - /* If it's not IO, then it's gotta be MEM */ align = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; @@ -344,32 +287,26 @@ pcibios_align_resource(void *data, struct resource *res, res->start += mask; res->start &= ~mask; - /* - ** WARNING : caller is expected to update "end" field. - ** We can't since it might really represent the *size*. - ** The difference is "end = start + size" vs "end += start". - */ + /* The caller updates the end field, we don't. */ } -int __devinit -pcibios_enable_device(struct pci_dev *dev, int mask) +/* + * A driver is enabling the device. We make sure that all the appropriate + * bits are set to allow the device to operate as the driver is expecting. + * We enable the port IO and memory IO bits if the device has any BARs of + * that type, and we enable the PERR and SERR bits unconditionally. + * Drivers that do not need parity (eg graphics and possibly networking) + * can clear these bits if they want. + */ +int pcibios_enable_device(struct pci_dev *dev, int mask) { u16 cmd; int idx; - /* - ** The various platform PDC's (aka "BIOS" for PCs) don't - ** enable all the same bits. We just make sure they are here. - */ pci_read_config_word(dev, PCI_COMMAND, &cmd); - /* - ** See if any resources have been allocated - ** While "regular" PCI devices only use 0-5, Bridges use a few - ** beyond that for window registers. - */ - for (idx=0; idxresource[idx]; /* only setup requested resources */ @@ -382,14 +319,6 @@ pcibios_enable_device(struct pci_dev *dev, int mask) cmd |= PCI_COMMAND_MEMORY; } - /* - ** Enable System error and Parity Error reporting by default. - ** Devices that do NOT want those behaviors should clear them - ** (eg PCI graphics, possibly networking). - ** Interfaces like SCSI certainly should not. We want the - ** system to crash if a system or parity error is detected. - ** At least until the device driver can recover from such an error. - */ cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY); #if 0 @@ -402,30 +331,15 @@ pcibios_enable_device(struct pci_dev *dev, int mask) return 0; } -void __init -pcibios_setup_host_bridge(struct pci_bus *bus) -{ - ASSERT(pci_bios != NULL); -#if 0 - if (pci_bios) - { - if (pci_bios->setup_host_bridge) { - (*pci_bios->setup_host_bridge)(bus); - } - } -#endif -} - - -/* -** PARISC specific (unfortunately) -*/ +/* PA-RISC specific */ void pcibios_register_hba(struct pci_hba_data *hba) { - ASSERT(pci_hba_count < PCI_HBA_MAX); + if (pci_hba_count >= PCI_HBA_MAX) { + printk(KERN_ERR "PCI: Too many Host Bus Adapters\n"); + return; + } - /* pci_port->in/out() uses parisc_pci_hba to lookup parameter. */ parisc_pci_hba[pci_hba_count] = hba; hba->hba_num = pci_hba_count++; } diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 9bc568e4e755c..99c62d846a481 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S index 3cf3bd1d084e6..9dec500724a3d 100644 --- a/arch/parisc/kernel/real2.S +++ b/arch/parisc/kernel/real2.S @@ -123,7 +123,7 @@ save_control_regs: nop restore_control_regs: - load32 PA(save_cr_space + (N_SAVED_REGS * REG_SZ)), %r26 + load32 PA(save_cr_space+(N_SAVED_REGS*REG_SZ)), %r26 POP_CR(%cr15, %r26) POP_CR(%cr31, %r26) POP_CR(%cr30, %r26) @@ -275,6 +275,7 @@ r64_ret: nop #endif + .export pc_in_user_space .text /* Doesn't belong here but I couldn't find a nicer spot. */ @@ -283,3 +284,17 @@ pc_in_user_space: bv,n 0(%rp) nop + + .export __canonicalize_funcptr_for_compare + .text + /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html + ** GCC 3.3 and later has a new function in libgcc.a for + ** comparing function pointers. + */ +__canonicalize_funcptr_for_compare: +#ifdef __LP64__ + bve (%r2) +#else + bv %r0(%r2) +#endif + copy %r26,%r28 diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index a0aabd65bfe82..45eb0dd888d6d 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -13,7 +13,6 @@ * arch/parisc/hpux/signal.c when we figure out how to do them. */ -#include #include #include #include @@ -458,6 +457,8 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) if (in_syscall) { /* Check the return code */ switch (regs->gr[28]) { + case -ERESTART_RESTARTBLOCK: + current_thread_info()->restart_block.fn = do_no_restart_syscall; case -ERESTARTNOHAND: DBG(("ERESTARTNOHAND: returning -EINTR\n")); regs->gr[28] = -EINTR; @@ -495,7 +496,8 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) /* Did we come from a system call? */ if (in_syscall) { /* Restart the system call - no handlers present */ - if (regs->gr[28] == -ERESTARTNOHAND || + if (regs->gr[28] == -ERESTART_RESTARTBLOCK || + regs->gr[28] == -ERESTARTNOHAND || regs->gr[28] == -ERESTARTSYS || regs->gr[28] == -ERESTARTNOINTR) { /* Hooray for delayed branching. We don't diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 39b77b5db5fb9..b1743e58386d9 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -30,8 +30,6 @@ static unsigned long get_unshared_area(unsigned long addr, unsigned long len) { struct vm_area_struct *vma; - if (!addr) - addr = TASK_UNMAPPED_BASE; addr = PAGE_ALIGN(addr); for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { @@ -46,17 +44,38 @@ static unsigned long get_unshared_area(unsigned long addr, unsigned long len) #define DCACHE_ALIGN(addr) (((addr) + (SHMLBA - 1)) &~ (SHMLBA - 1)) -static unsigned long get_shared_area(struct inode *inode, unsigned long addr, - unsigned long len, unsigned long pgoff) +/* + * We need to know the offset to use. Old scheme was to look for + * existing mapping and use the same offset. New scheme is to use the + * address of the kernel data structure as the seed for the offset. + * We'll see how that works... + */ +#if 0 +static int get_offset(struct address_space *mapping) +{ + struct vm_area_struct *vma = list_entry(mapping->i_mmap_shared.next, + struct vm_area_struct, shared); + return (vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT)) & + (SHMLBA - 1); +} +#else +/* The mapping is cacheline aligned, so there's no information in the bottom + * few bits of the address. We're looking for 10 bits (4MB / 4k), so let's + * drop the bottom 8 bits and use bits 8-17. + */ +static int get_offset(struct address_space *mapping) { - struct vm_area_struct *vma, *first_vma; - int offset; + int offset = (int) mapping << (PAGE_SHIFT - 8); + return offset & 0x3FF000; +} +#endif - first_vma = list_entry(inode->i_mapping->i_mmap_shared.next, struct vm_area_struct, shared); - offset = (first_vma->vm_start + ((pgoff - first_vma->vm_pgoff) << PAGE_SHIFT)) & (SHMLBA - 1); +static unsigned long get_shared_area(struct address_space *mapping, + unsigned long addr, unsigned long len, unsigned long pgoff) +{ + struct vm_area_struct *vma; + int offset = get_offset(mapping); - if (!addr) - addr = TASK_UNMAPPED_BASE; addr = DCACHE_ALIGN(addr - offset) + offset; for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { @@ -74,17 +93,17 @@ static unsigned long get_shared_area(struct inode *inode, unsigned long addr, unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { - struct inode *inode = NULL; + struct inode *inode; if (len > TASK_SIZE) return -ENOMEM; + if (!addr) + addr = TASK_UNMAPPED_BASE; - if (filp) { - inode = filp->f_dentry->d_inode; - } + inode = filp ? filp->f_dentry->d_inode : NULL; - if (inode && (flags & MAP_SHARED) && (!list_empty(&inode->i_mapping->i_mmap_shared))) { - addr = get_shared_area(inode, addr, len, pgoff); + if (inode && (flags & MAP_SHARED)) { + addr = get_shared_area(inode->i_mapping, addr, len, pgoff); } else { addr = get_unshared_area(addr, len); } @@ -185,6 +204,7 @@ extern asmlinkage ssize_t sys_pread64(unsigned int fd, char *buf, size_t count, loff_t pos); extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos); +extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); asmlinkage ssize_t parisc_pread64(unsigned int fd, char *buf, size_t count, unsigned int high, unsigned int low) @@ -198,6 +218,11 @@ asmlinkage ssize_t parisc_pwrite64(unsigned int fd, const char *buf, return sys_pwrite64(fd, buf, count, (loff_t)high << 32 | low); } +asmlinkage ssize_t parisc_readahead(int fd, unsigned int high, unsigned int low, + size_t count) +{ + return sys_readahead(fd, (loff_t)high << 32 | low, count); +} /* * FIXME, please remove this crap as soon as possible @@ -271,7 +296,7 @@ static int copyout_broken_shmid64(struct broken_shmid64_ds *buf, struct shmid64_ tbuf.shm_cpid = sbuf->shm_cpid; tbuf.shm_lpid = sbuf->shm_lpid; tbuf.shm_nattch = sbuf->shm_nattch; - return copy_to_user(buf, &tbuf, sizeof tbuf); + return copy_to_user(buf, &tbuf, sizeof tbuf) ? -EFAULT : 0; } int sys_msgctl_broken(int msqid, int cmd, struct msqid_ds *buf) diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 33313daa9d09f..f251f86c86ecf 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -373,18 +374,16 @@ put_compat_timeval(struct compat_timeval *u, struct timeval *t) return copy_to_user(u, &t32, sizeof t32); } -static int -get_compat_timeval(struct compat_timeval *u, struct timeval *t) +static inline long get_ts32(struct timespec *o, struct compat_timeval *i) { - int err; - struct compat_timeval t32; + long usec; - if ((err = copy_from_user(&t32, u, sizeof t32)) == 0) - { - t->tv_sec = t32.tv_sec; - t->tv_usec = t32.tv_usec; - } - return err; + if (__get_user(o->tv_sec, &i->tv_sec)) + return -EFAULT; + if (__get_user(usec, &i->tv_usec)) + return -EFAULT; + o->tv_nsec = usec * 1000; + return 0; } asmlinkage long sys32_time(compat_time_t *tloc) @@ -418,23 +417,22 @@ sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz) return 0; } -asmlinkage int -sys32_settimeofday(struct compat_timespec *tv, struct timezone *tz) +asmlinkage +int sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz) { - struct timeval ktv; - struct timezone ktz; - extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz); + struct timespec kts; + struct timezone ktz; - if (tv) { - if (get_compat_timeval(tv, &ktv)) - return -EFAULT; - } - if (tz) { - if (copy_from_user(&ktz, tz, sizeof(ktz))) - return -EFAULT; - } + if (tv) { + if (get_ts32(&kts, tv)) + return -EFAULT; + } + if (tz) { + if (copy_from_user(&ktz, tz, sizeof(ktz))) + return -EFAULT; + } - return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); + return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) @@ -1089,6 +1087,27 @@ asmlinkage long sys32_msgrcv(int msqid, return err; } + +extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); +asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count) +{ + mm_segment_t old_fs = get_fs(); + int ret; + off_t of; + + if (offset && get_user(of, offset)) + return -EFAULT; + + set_fs(KERNEL_DS); + ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); + set_fs(old_fs); + + if (offset && put_user(of, offset)) + return -EFAULT; + + return ret; +} + /* EXPORT/UNEXPORT */ struct nfsctl_export32 { char ex_client[NFSCLNT_IDMAX+1]; diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 29e2ee7e7c122..08ffcb50fde05 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -483,7 +483,7 @@ sys_call_table: ENTRY_SAME(madvise) ENTRY_SAME(clone_wrapper) /* 120 */ ENTRY_SAME(setdomainname) - ENTRY_SAME(sendfile) + ENTRY_DIFF(sendfile) /* struct sockaddr... */ ENTRY_SAME(recvfrom) /* struct timex contains longs */ @@ -592,7 +592,7 @@ sys_call_table: ENTRY_SAME(ni_syscall) ENTRY_SAME(ni_syscall) /* 205 */ ENTRY_SAME(gettid) - ENTRY_SAME(readahead) + ENTRY_OURS(readahead) ENTRY_SAME(ni_syscall) /* tkill */ ENTRY_SAME(sendfile64) diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 616d19def18e8..602cc50279b63 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -221,6 +221,8 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) return; } + oops_in_progress = 1; + /* Amuse the user in a SPARC fashion */ printk( " _______________________________ \n" @@ -414,6 +416,8 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o { static spinlock_t terminate_lock = SPIN_LOCK_UNLOCKED; + oops_in_progress = 1; + set_eiem(0); local_irq_disable(); spin_lock(&terminate_lock); diff --git a/arch/parisc/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S similarity index 100% rename from arch/parisc/vmlinux.lds.S rename to arch/parisc/kernel/vmlinux.lds.S diff --git a/arch/parisc/nm b/arch/parisc/nm new file mode 100644 index 0000000000000..c788308de33f7 --- /dev/null +++ b/arch/parisc/nm @@ -0,0 +1,6 @@ +#!/bin/sh +## +# Hack to have an nm which removes the local symbols. We also rely +# on this nm being hidden out of the ordinarily executable path +## +${CROSS_COMPILE}nm $* | grep -v '.LC*[0-9]*$' diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c index e29f8ca8e6f32..2d45a5b099af9 100644 --- a/drivers/parisc/asp.c +++ b/drivers/parisc/asp.c @@ -76,8 +76,6 @@ asp_init_chip(struct parisc_device *dev) printk(KERN_INFO "%s version %d at 0x%lx found.\n", asp->name, asp->version, dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %d", - asp->name, asp->version); /* the IRQ ASP should use */ ret = -EBUSY; diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 5aeaa39086106..070069d833432 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -129,6 +129,92 @@ struct ioa_registers { volatile uint32_t io_io_high; /* Offset 15 */ }; +/* +** IOA Registers +** ------------- +** +** Runway IO_CONTROL Register (+0x38) +** +** The Runway IO_CONTROL register controls the forwarding of transactions. +** +** | 0 ... 13 | 14 15 | 16 ... 21 | 22 | 23 24 | 25 ... 31 | +** | HV | TLB | reserved | HV | mode | reserved | +** +** o mode field indicates the address translation of transactions +** forwarded from Runway to GSC+: +** Mode Name Value Definition +** Off (default) 0 Opaque to matching addresses. +** Include 1 Transparent for matching addresses. +** Peek 3 Map matching addresses. +** +** + "Off" mode: Runway transactions which match the I/O range +** specified by the IO_IO_LOW/IO_IO_HIGH registers will be ignored. +** + "Include" mode: all addresses within the I/O range specified +** by the IO_IO_LOW and IO_IO_HIGH registers are transparently +** forwarded. This is the I/O Adapter's normal operating mode. +** + "Peek" mode: used during system configuration to initialize the +** GSC+ bus. Runway Write_Shorts in the address range specified by +** IO_IO_LOW and IO_IO_HIGH are forwarded through the I/O Adapter +** *AND* the GSC+ address is remapped to the Broadcast Physical +** Address space by setting the 14 high order address bits of the +** 32 bit GSC+ address to ones. +** +** o TLB field affects transactions which are forwarded from GSC+ to Runway. +** "Real" mode is the poweron default. +** +** TLB Mode Value Description +** Real 0 No TLB translation. Address is directly mapped and the +** virtual address is composed of selected physical bits. +** Error 1 Software fills the TLB manually. +** Normal 2 IOA fetches IO TLB misses from IO PDIR (in host memory). +** +** +** IO_IO_LOW_HV +0x60 (HV dependent) +** IO_IO_HIGH_HV +0x64 (HV dependent) +** IO_IO_LOW +0x78 (Architected register) +** IO_IO_HIGH +0x7c (Architected register) +** +** IO_IO_LOW and IO_IO_HIGH set the lower and upper bounds of the +** I/O Adapter address space, respectively. +** +** 0 ... 7 | 8 ... 15 | 16 ... 31 | +** 11111111 | 11111111 | address | +** +** Each LOW/HIGH pair describes a disjoint address space region. +** (2 per GSC+ port). Each incoming Runway transaction address is compared +** with both sets of LOW/HIGH registers. If the address is in the range +** greater than or equal to IO_IO_LOW and less than IO_IO_HIGH the transaction +** for forwarded to the respective GSC+ bus. +** Specify IO_IO_LOW equal to or greater than IO_IO_HIGH to avoid specifying +** an address space region. +** +** In order for a Runway address to reside within GSC+ extended address space: +** Runway Address [0:7] must identically compare to 8'b11111111 +** Runway Address [8:11] must be equal to IO_IO_LOW(_HV)[16:19] +** Runway Address [12:23] must be greater than or equal to +** IO_IO_LOW(_HV)[20:31] and less than IO_IO_HIGH(_HV)[20:31]. +** Runway Address [24:39] is not used in the comparison. +** +** When the Runway transaction is forwarded to GSC+, the GSC+ address is +** as follows: +** GSC+ Address[0:3] 4'b1111 +** GSC+ Address[4:29] Runway Address[12:37] +** GSC+ Address[30:31] 2'b00 +** +** All 4 Low/High registers must be initialized (by PDC) once the lower bus +** is interrogated and address space is defined. The operating system will +** modify the architectural IO_IO_LOW and IO_IO_HIGH registers following +** the PDC initialization. However, the hardware version dependent IO_IO_LOW +** and IO_IO_HIGH registers should not be subsequently altered by the OS. +** +** Writes to both sets of registers will take effect immediately, bypassing +** the queues, which ensures that subsequent Runway transactions are checked +** against the updated bounds values. However reads are queued, introducing +** the possibility of a read being bypassed by a subsequent write to the same +** register. This sequence can be avoided by having software wait for read +** returns before issuing subsequent writes. +*/ + struct ioc { struct ioa_registers *ioc_hpa; /* I/O MMU base address */ u8 *res_map; /* resource map, bit == pdir entry */ @@ -1448,13 +1534,74 @@ static void __init ccio_init_resources(struct ioc *ioc) (unsigned long)&ioc->ioc_hpa->io_io_low_hv); } -static void expand_ioc_area(struct ioc *ioc, unsigned long size, - unsigned long min, unsigned long max, unsigned long align) +static int expand_resource(struct resource *res, unsigned long size, + unsigned long align) { -#ifdef NASTY_HACK_FOR_K_CLASS - __raw_writel(0xfffff600, (unsigned long)&(ioc->ioc_hpa->io_io_high)); - ioc->mmio_region[0].end = 0xf5ffffff; -#endif + struct resource *temp_res; + unsigned long start = res->start; + unsigned long end ; + + /* see if we can expand above */ + end = (res->end + size + align - 1) & ~(align - 1);; + + temp_res = __request_region(res->parent, res->end, end - res->end, + "expansion"); + if(!temp_res) { + /* now try below */ + start = ((res->start - size + align) & ~(align - 1)) - align; + end = res->end; + temp_res = __request_region(res->parent, start, size, + "expansion"); + if(!temp_res) { + return -ENOMEM; + } + } + release_resource(temp_res); + temp_res = res->parent; + release_resource(res); + res->start = start; + res->end = end; + + /* This could be caused by some sort of race. Basically, if + * this tripped something stole the region we just reserved + * and then released to check for expansion */ + BUG_ON(request_resource(temp_res, res) != 0); + + return 0; +} + +static void expand_ioc_area(struct resource *parent, struct ioc *ioc, + unsigned long size, unsigned long min, + unsigned long max, unsigned long align) +{ + if(ioc == NULL) + /* no IOC, so nothing to expand */ + return; + + if (expand_resource(parent, size, align) != 0) { + printk(KERN_ERR "Unable to expand %s window by 0x%lx\n", + parent->name, size); + return; + } + + /* OK, we have the memory, now expand the window */ + if (parent == &ioc->mmio_region[0]) { + __raw_writel(((parent->start)>>16) | 0xffff0000, + (unsigned long)&(ioc->ioc_hpa->io_io_low)); + __raw_writel(((parent->end)>>16) | 0xffff0000, + (unsigned long)&(ioc->ioc_hpa->io_io_high)); + } else if (parent == &ioc->mmio_region[1]) { + __raw_writel(((parent->start)>>16) | 0xffff0000, + (unsigned long)&(ioc->ioc_hpa->io_io_low_hv)); + __raw_writel(((parent->end)>>16) | 0xffff0000, + (unsigned long)&(ioc->ioc_hpa->io_io_high_hv)); + } else { + /* This should be impossible. It means + * expand_ioc_area got called with a resource that + * didn't belong to the ioc + */ + BUG(); + } } static struct resource *ccio_get_resource(struct ioc* ioc, @@ -1488,7 +1635,7 @@ int ccio_allocate_resource(const struct parisc_device *dev, alignf_data)) return 0; - expand_ioc_area(ioc, size, min, max, align); + expand_ioc_area(parent, ioc, size, min, max, align); return allocate_resource(parent, res, size, min, max, align, alignf, alignf_data); } @@ -1522,7 +1669,6 @@ static int ccio_probe(struct parisc_device *dev) memset(ioc, 0, sizeof(struct ioc)); ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn"; - strlcpy(dev->dev.name, ioc->name, sizeof(dev->dev.name)); printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa); diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 49bac9db320f6..cea71fe116b93 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -401,23 +401,7 @@ ilr_again: { int irq; - /* - * Perform a binary search on set bits. - * `Less than Fatal' and PS2 interrupts aren't supported. - */ - if (mask & 0xf) { - if (mask & 0x3) { - irq = (mask & 0x1) ? 0 : 1; /* PCI INT A, B */ - } else { - irq = (mask & 0x4) ? 2 : 3; /* PCI INT C, D */ - } - } else { - if (mask & 0x30) { - irq = (mask & 0x10) ? 4 : 5; /* PCI INT E, F */ - } else { - irq = (mask & 0x40) ? 6 : 10; /* GSC, RS232 */ - } - } + irq = __ffs(mask); mask &= ~(1< 0) goto ilr_again; - printk("Dino %lx: stuck interrupt %d\n", dino_dev->hba.base_addr, mask); + printk(KERN_ERR "Dino %lx: stuck interrupt %d\n", dino_dev->hba.base_addr, mask); return IRQ_NONE; } return IRQ_HANDLED; @@ -479,15 +463,35 @@ dino_card_setup(struct pci_bus *bus, unsigned long base_addr) int i; struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->dev)); struct resource *res; + char name[128]; + int size; res = &dino_dev->hba.lmmio_space; res->flags = IORESOURCE_MEM; + size = snprintf(name, sizeof(name), "Dino LMMIO (%s)", bus->dev->bus_id); + res->name = kmalloc(size+1, GFP_KERNEL); + if(res->name) + strcpy((char *)res->name, name); + else + res->name = dino_dev->hba.lmmio_space.name; + if (ccio_allocate_resource(dino_dev->hba.dev, res, _8MB, - (unsigned long) 0xfffffffff0000000UL | _8MB, - 0xffffffffffffffffUL &~ _8MB, _8MB, + F_EXTEND(0xf0000000UL) | _8MB, + F_EXTEND(0xffffffffUL) &~ _8MB, _8MB, NULL, NULL) < 0) { - printk(KERN_WARNING "Dino: Failed to allocate memory region\n"); + struct list_head *ln, *tmp_ln; + + printk(KERN_ERR "Dino: cannot attach bus %s\n", + bus->dev->bus_id); + /* kill the bus, we can't do anything with it */ + list_for_each_safe(ln, tmp_ln, &bus->devices) { + struct pci_dev *dev = pci_dev_b(ln); + + list_del(&dev->global_list); + list_del(&dev->bus_list); + } + return; } bus->resource[1] = res; @@ -495,9 +499,11 @@ dino_card_setup(struct pci_bus *bus, unsigned long base_addr) /* Now tell dino what range it has */ for (i = 1; i < 31; i++) { - if (res->start == (0xfffffffff0000000UL | i * _8MB)) + if (res->start == F_EXTEND(0xf0000000UL | (i * _8MB))) break; } + DBG("DINO GSC WRITE i=%d, start=%lx, dino addr = %lx\n", + i, res->start, base_addr + DINO_IO_ADDR_EN); gsc_writel(1 << i, base_addr + DINO_IO_ADDR_EN); pci_bus_assign_resources(bus); @@ -521,7 +527,7 @@ dino_card_fixup(struct pci_dev *dev) ** Set Latency Timer to 0xff (not a shared bus) ** Set CACHELINE_SIZE. */ - dino_cfg_write(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 16, 0xff00 | L1_CACHE_BYTES/4); + dino_cfg_write(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 2, 0xff00 | L1_CACHE_BYTES/4); /* ** Program INT_LINE for card-mode devices. @@ -532,13 +538,13 @@ dino_card_fixup(struct pci_dev *dev) ** "-1" converts INTA-D (1-4) to PCIINTA-D (0-3) range. ** The additional "-1" adjusts for skewing the IRQ<->slot. */ - dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 8, &irq_pin); + dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin); dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ; /* Shouldn't really need to do this but it's in case someone tries ** to bypass PCI services and look at the card themselves. */ - dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 8, dev->irq); + dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 1, dev->irq); } @@ -585,8 +591,8 @@ dino_fixup_bus(struct pci_bus *bus) #ifdef __LP64__ /* Sign Extend MMIO addresses */ else if (res->flags & IORESOURCE_MEM) { - res->start |= 0xffffffff00000000UL; - res->end |= 0xffffffff00000000UL; + res->start |= F_EXTEND(0UL); + res->end |= F_EXTEND(0UL); } #endif } @@ -789,8 +795,8 @@ static int __init dino_common_init(struct parisc_device *dev, return 0; } -#define CUJO_RAVEN_ADDR 0xfffffffff1000000UL -#define CUJO_FIREHAWK_ADDR 0xfffffffff1604000UL +#define CUJO_RAVEN_ADDR F_EXTEND(0xf1000000UL) +#define CUJO_FIREHAWK_ADDR F_EXTEND(0xf1604000UL) #define CUJO_RAVEN_BADPAGE 0x01003000UL #define CUJO_FIREHAWK_BADPAGE 0x01607000UL @@ -818,9 +824,16 @@ dino_driver_callback(struct parisc_device *dev) { struct dino_device *dino_dev; // Dino specific control struct const char *version = "unknown"; - const char *name = "Dino"; + const int name_len = 32; + char *name; int is_cujo = 0; + name = kmalloc(name_len, GFP_KERNEL); + if(name) + snprintf(name, name_len, "Dino %s", dev->dev.bus_id); + else + name = "Dino"; + if (is_card_dino(&dev->id)) { version = "3.x (card mode)"; } else { @@ -838,8 +851,6 @@ dino_driver_callback(struct parisc_device *dev) } printk("%s version %s found at 0x%lx\n", name, version, dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), - "%s version %s", name, version); if (!request_mem_region(dev->hpa, PAGE_SIZE, name)) { printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%ld)!\n", diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 6c076d4200bd2..dba62b8e543e6 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -327,14 +327,13 @@ static int __devinit eisa_probe(struct parisc_device *dev) printk(KERN_INFO "%s EISA Adapter found at 0x%08lx\n", name, dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s EISA", name); eisa_dev.hba.dev = dev; eisa_dev.hba.iommu = ccio_get_iommu(dev); eisa_dev.hba.lmmio_space.name = "EISA"; - eisa_dev.hba.lmmio_space.start = (unsigned long) 0xfffffffffc000000; - eisa_dev.hba.lmmio_space.end = (unsigned long) 0xffffffffffbfffff; + eisa_dev.hba.lmmio_space.start = F_EXTEND(0xfc000000); + eisa_dev.hba.lmmio_space.end = F_EXTEND(0xffbfffff); eisa_dev.hba.lmmio_space.flags = IORESOURCE_MEM; result = ccio_request_resource(dev, &eisa_dev.hba.lmmio_space); if (result < 0) { diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c index 9400303dd9960..8bda8bb50815d 100644 --- a/drivers/parisc/hppb.c +++ b/drivers/parisc/hppb.c @@ -70,7 +70,6 @@ static int hppb_probe(struct parisc_device *dev) card = card->next; } printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "GeckoBoa"); card->hpa = dev->hpa; card->mmio_region.name = "HP-PB Bus"; diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 89d1484e9a736..9eb6ada6d192c 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -643,7 +643,7 @@ iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev) if (NULL == isi) { printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n", - pcidev->dev.name); + pci_name(pcidev)); return(-1); } diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c index c78e2696c53fa..6e67ea060f738 100644 --- a/drivers/parisc/lasi.c +++ b/drivers/parisc/lasi.c @@ -185,8 +185,6 @@ lasi_init_chip(struct parisc_device *dev) lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf; printk(KERN_INFO "%s version %d at 0x%lx found.\n", lasi->name, lasi->version, lasi->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %d", - lasi->name, lasi->version); /* initialize the chassis LEDs really early */ lasi_led_init(lasi->hpa); diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 719a9b2384432..b1a1180db597c 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -782,7 +782,7 @@ lba_fixup_bus(struct pci_bus *bus) int i; struct pci_dev *dev = pci_dev_b(ln); - DBG("lba_fixup_bus() %s\n", dev->name); + DBG("lba_fixup_bus() %s\n", pci_name(dev)); /* Virtualize Device/Bridge Resources. */ for (i = 0; i < PCI_NUM_RESOURCES; i++) { @@ -1358,8 +1358,6 @@ lba_driver_callback(struct parisc_device *dev) printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n", MODULE_NAME, version, func_class & 0xf, dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %s", - MODULE_NAME, version); /* Just in case we find some prototypes... */ if (func_class < 2) { diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index d164351b49254..6396063d529e2 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -91,7 +91,7 @@ struct pdc_chassis_lcd_info_ret_block { /* LCD_CMD and LCD_DATA for KittyHawk machines */ -#define KITTYHAWK_LCD_CMD (0xfffffffff0190000UL) /* 64bit-ready */ +#define KITTYHAWK_LCD_CMD F_EXTEND(0xf0190000UL) /* 64bit-ready */ #define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD+1) /* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 501e351f03815..ce2412acf7d0d 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1978,8 +1978,6 @@ sba_driver_callback(struct parisc_device *dev) printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME, version, dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %s", - MODULE_NAME, version); #ifdef DEBUG_SBA_INIT sba_dump_tlb(dev->hpa); diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c index 1a9f67d73b705..e9044d225b7bc 100644 --- a/drivers/parisc/wax.c +++ b/drivers/parisc/wax.c @@ -83,8 +83,6 @@ wax_init_chip(struct parisc_device *dev) wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */ printk(KERN_INFO "%s at 0x%lx found.\n", wax->name, wax->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %d", - wax->name, wax->version); /* Stop wax hissing for a bit */ wax_init_irq(wax); diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h index d50c506dd8a48..808373512d6cf 100644 --- a/include/asm-parisc/atomic.h +++ b/include/asm-parisc/atomic.h @@ -49,27 +49,14 @@ extern spinlock_t __atomic_hash[ATOMIC_HASH_SIZE]; * Cache-line alignment would conflict with, for example, linux/module.h */ -typedef struct { - volatile int counter; -} atomic_t; +typedef struct { volatile long counter; } atomic_t; -/* -** xchg/cmpxchg moved from asm/system.h - ggg -*/ - -#if 1 /* This should get optimized out since it's never called. ** Or get a link error if xchg is used "wrong". */ extern void __xchg_called_with_bad_pointer(void); -#else -static inline void __xchg_called_with_bad_pointer(void) -{ - extern void panic(const char * fmt, ...); - panic("xchg called with bad pointer"); -} -#endif + /* __xchg32/64 defined in arch/parisc/lib/bitops.c */ extern unsigned long __xchg8(char, char *); diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h index 711e7d154afa2..51f4871ac6ceb 100644 --- a/include/asm-parisc/bitops.h +++ b/include/asm-parisc/bitops.h @@ -203,55 +203,102 @@ static __inline__ int test_bit(int nr, const void *address) return !!(*addr & mask); } -extern __inline__ unsigned long ffz(unsigned long word) -{ - unsigned long result; - - result = 0; - while (word & 1) { - result++; - word >>= 1; - } - - return result; -} - #ifdef __KERNEL__ /** - * __ffs - find first bit in word. + * __ffs - find first bit in word. returns 0 to "BITS_PER_LONG-1". * @word: The word to search * - * Undefined if no bit exists, so code should check against 0 first. + * __ffs() return is undefined if no bit is set. + * + * 32-bit fast __ffs by LaMont Jones "lamont At hp com". + * 64-bit enhancement by Grant Grundler "grundler At parisc-linux org". + * (with help from willy/jejb to get the semantics right) + * + * This algorithm avoids branches by making use of nullification. + * One side effect of "extr" instructions is it sets PSW[N] bit. + * How PSW[N] (nullify next insn) gets set is determined by the + * "condition" field (eg "<>" or "TR" below) in the extr* insn. + * Only the 1st and one of either the 2cd or 3rd insn will get executed. + * Each set of 3 insn will get executed in 2 cycles on PA8x00 vs 16 or so + * cycles for each mispredicted branch. */ -static __inline__ unsigned long __ffs(unsigned long word) -{ - unsigned long result = 0; - while (!(word & 1UL)) { - result++; - word >>= 1; - } - return result; +static __inline__ unsigned long __ffs(unsigned long x) +{ + unsigned long ret; + + __asm__( +#if BITS_PER_LONG > 32 + " ldi 63,%1\n" + " extrd,u,*<> %0,63,32,%%r0\n" + " extrd,u,*TR %0,31,32,%0\n" + " addi -32,%1,%1\n" +#else + " ldi 31,%1\n" +#endif + " extru,<> %0,31,16,%%r0\n" + " extru,TR %0,15,16,%0\n" + " addi -16,%1,%1\n" + " extru,<> %0,31,8,%%r0\n" + " extru,TR %0,23,8,%0\n" + " addi -8,%1,%1\n" + " extru,<> %0,31,4,%%r0\n" + " extru,TR %0,27,4,%0\n" + " addi -4,%1,%1\n" + " extru,<> %0,31,2,%%r0\n" + " extru,TR %0,29,2,%0\n" + " addi -2,%1,%1\n" + " extru,= %0,31,1,%%r0\n" + " addi -1,%1,%1\n" + : "+r" (x), "=r" (ret) ); + return ret; } +/* Undefined if no bit is zero. */ +#define ffz(x) __ffs(~x) + /* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). + * ffs: find first bit set. returns 1 to BITS_PER_LONG or 0 (if none set) + * This is defined the same way as the libc and compiler builtin + * ffs routines, therefore differs in spirit from the above ffz (man ffs). */ static __inline__ int ffs(int x) { - if (!x) - return 0; - return __ffs((unsigned long)x); + return x ? (__ffs((unsigned long)x) + 1) : 0; } /* - * fls: find last bit set. + * fls: find last (most significant) bit set. + * fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. */ -#define fls(x) generic_fls(x) +static __inline__ int fls(int x) +{ + int ret; + if (!x) + return 0; + + __asm__( + " ldi 1,%1\n" + " extru,<> %0,15,16,%%r0\n" + " zdep,TR %0,15,16,%0\n" /* xxxx0000 */ + " addi 16,%1,%1\n" + " extru,<> %0,7,8,%%r0\n" + " zdep,TR %0,23,24,%0\n" /* xx000000 */ + " addi 8,%1,%1\n" + " extru,<> %0,3,4,%%r0\n" + " zdep,TR %0,27,28,%0\n" /* x0000000 */ + " addi 4,%1,%1\n" + " extru,<> %0,1,2,%%r0\n" + " zdep,TR %0,29,30,%0\n" /* y0000000 (y&3 = 0 */ + " addi 2,%1,%1\n" + " extru,= %0,0,1,%%r0\n" + " addi 1,%1,%1\n" /* if y & 8, add 1 */ + : "+r" (x), "=r" (ret) ); + + return ret; +} /* * hweightN: returns the hamming weight (i.e. the number diff --git a/include/asm-parisc/byteorder.h b/include/asm-parisc/byteorder.h index 9ddeab1777a59..352b3146f7b01 100644 --- a/include/asm-parisc/byteorder.h +++ b/include/asm-parisc/byteorder.h @@ -5,6 +5,25 @@ #ifdef __GNUC__ +static __inline__ __const__ __u16 ___arch__swab16(__u16 x) +{ + __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */ + "shd %%r0, %0, 8, %0" /* shift 000000ab -> 00ba */ + : "=r" (x) + : "0" (x)); + return x; +} + +static __inline__ __const__ __u32 ___arch__swab24(__u32 x) +{ + __asm__("shd %0, %0, 8, %0\n\t" /* shift xabcxabc -> cxab */ + "dep %0, 15, 8, %0\n\t" /* deposit cxab -> cbab */ + "shd %%r0, %0, 8, %0" /* shift 0000cbab -> 0cba */ + : "=r" (x) + : "0" (x)); + return x; +} + static __inline__ __const__ __u32 ___arch__swab32(__u32 x) { unsigned int temp; @@ -39,34 +58,21 @@ static __inline__ __const__ __u64 ___arch__swab64(__u64 x) { return x; } #define __arch__swab64(x) ___arch__swab64(x) -#else +#define __BYTEORDER_HAS_U64__ +#elif !defined(__STRICT_ANSI__) static __inline__ __const__ __u64 ___arch__swab64(__u64 x) { - __u32 t1 = (__u32) x; - __u32 t2 = (__u32) ((x) >> 32); - ___arch__swab32(t1); - ___arch__swab32(t2); - return (((__u64) t1 << 32) + ((__u64) t2)); + __u32 t1 = ___arch__swab32((__u32) x); + __u32 t2 = ___arch__swab32((__u32) (x >> 32)); + return (((__u64) t1 << 32) | t2); } +#define __arch__swab64(x) ___arch__swab64(x) +#define __BYTEORDER_HAS_U64__ #endif - -static __inline__ __const__ __u16 ___arch__swab16(__u16 x) -{ - __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */ - "shd %r0, %0, 8, %0" /* shift 000000ab -> 00ba */ - : "=r" (x) - : "0" (x)); - return x; -} - -#define __arch__swab32(x) ___arch__swab32(x) #define __arch__swab16(x) ___arch__swab16(x) - -#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) -# define __BYTEORDER_HAS_U64__ -# define __SWAB_64_THRU_32__ -#endif +#define __arch__swab24(x) ___arch__swab24(x) +#define __arch__swab32(x) ___arch__swab32(x) #endif /* __GNUC__ */ diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h index 5392339e549bd..b88200337cca0 100644 --- a/include/asm-parisc/cacheflush.h +++ b/include/asm-parisc/cacheflush.h @@ -78,8 +78,9 @@ static inline void flush_dcache_page(struct page *page) #define flush_icache_range(s,e) do { flush_kernel_dcache_range_asm(s,e); flush_kernel_icache_range_asm(s,e); } while (0) -#define flush_icache_user_range(vma, page, addr, len) \ - flush_icache_page((vma), (page)) +#define flush_icache_user_range(vma, page, addr, len) do { \ + flush_user_dcache_range(addr, addr + len); \ + flush_user_icache_range(addr, addr + len); } while (0) static inline void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) diff --git a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h index b9f6090b78f25..a01e946dfc578 100644 --- a/include/asm-parisc/elf.h +++ b/include/asm-parisc/elf.h @@ -283,6 +283,7 @@ struct pt_regs; /* forward declaration... */ */ #define ELF_DATA ELFDATA2MSB #define ELF_ARCH EM_PARISC +#define ELF_OSABI ELFOSABI_LINUX /* %r23 is set by ld.so to a pointer to a function which might be registered using atexit. This provides a mean for the dynamic diff --git a/include/asm-parisc/hil.h b/include/asm-parisc/hil.h deleted file mode 100644 index 97cd5553f22fc..0000000000000 --- a/include/asm-parisc/hil.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _ASM_HIL_H -#define _ASM_HIL_H - -/* - * linux/asm-parisc/hil.h - * - * (c) 1999 Matthew Wilcox - */ - -extern unsigned long hil_base; /* declared in drivers/parisc/hil.c */ -extern unsigned int hil_irq; - -#define HILBASE hil_base /* 0xf0821000 (old) or 0xf0201000 (new) */ -#define HIL_DATA 0x800 -#define HIL_CMD 0x801 - -#define HIL_IRQ hil_irq - -#define hil_busy() (gsc_readb(HILBASE + HIL_CMD) & HIL_BUSY) -#define hil_data_available() (gsc_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) -#define hil_status() (gsc_readb(HILBASE + HIL_CMD)) -#define hil_command(x) do { gsc_writeb((x), HILBASE + HIL_CMD); } while (0) -#define hil_read_data() (gsc_readb(HILBASE + HIL_DATA)) -#define hil_write_data(x) do { gsc_writeb((x), HILBASE + HIL_DATA); } while (0) - -#endif diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h index 69933ab231590..0350f0198995d 100644 --- a/include/asm-parisc/io.h +++ b/include/asm-parisc/io.h @@ -291,4 +291,11 @@ extern void outsl (unsigned long port, const void *src, unsigned long count); #define dma_cache_wback(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0) #define dma_cache_wback_inv(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0) +/* PA machines have an MM I/O space from 0xf0000000-0xffffffff in 32 + * bit mode and from 0xfffffffff0000000-0xfffffffffffffff in 64 bit + * mode (essentially just sign extending. This macro takes in a 32 + * bit I/O address (still with the leading f) and outputs the correct + * value for either 32 or 64 bit mode */ +#define F_EXTEND(x) ((unsigned long)((x) | (0xffffffff00000000ULL))) + #endif diff --git a/include/asm-parisc/local.h b/include/asm-parisc/local.h new file mode 100644 index 0000000000000..892b3b2c4962c --- /dev/null +++ b/include/asm-parisc/local.h @@ -0,0 +1,40 @@ +#ifndef _ARCH_PARISC_LOCAL_H +#define _ARCH_PARISC_LOCAL_H + +#include +#include + +typedef atomic_t local_t; + +#define LOCAL_INIT(i) ATOMIC_INIT(i) +#define local_read(v) atomic_read(v) +#define local_set(v,i) atomic_set(v,i) + +#define local_inc(v) atomic_inc(v) +#define local_dec(v) atomic_dec(v) +#define local_add(i, v) atomic_add(i, v) +#define local_sub(i, v) atomic_sub(i, v) + +#define __local_inc(v) ((v)->counter++) +#define __local_dec(v) ((v)->counter--) +#define __local_add(i,v) ((v)->counter+=(i)) +#define __local_sub(i,v) ((v)->counter-=(i)) + +/* Use these for per-cpu local_t variables: on some archs they are + * much more efficient than these naive implementations. Note they take + * a variable, not an address. + */ +#define cpu_local_read(v) local_read(&__get_cpu_var(v)) +#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i)) + +#define cpu_local_inc(v) local_inc(&__get_cpu_var(v)) +#define cpu_local_dec(v) local_dec(&__get_cpu_var(v)) +#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v)) +#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v)) + +#define __cpu_local_inc(v) __local_inc(&__get_cpu_var(v)) +#define __cpu_local_dec(v) __local_dec(&__get_cpu_var(v)) +#define __cpu_local_add(i, v) __local_add((i), &__get_cpu_var(v)) +#define __cpu_local_sub(i, v) __local_sub((i), &__get_cpu_var(v)) + +#endif /* _ARCH_PARISC_LOCAL_H */ diff --git a/include/asm-parisc/sections.h b/include/asm-parisc/sections.h new file mode 100644 index 0000000000000..fdd43ec42ec56 --- /dev/null +++ b/include/asm-parisc/sections.h @@ -0,0 +1,7 @@ +#ifndef _PARISC_SECTIONS_H +#define _PARISC_SECTIONS_H + +/* nothing to see, move along */ +#include + +#endif diff --git a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h index 8bd1067c4a50c..cc9e311cabd19 100644 --- a/include/asm-parisc/uaccess.h +++ b/include/asm-parisc/uaccess.h @@ -28,6 +28,11 @@ * that put_user is the same as __put_user, etc. */ +extern int __get_kernel_bad(void); +extern int __get_user_bad(void); +extern int __put_kernel_bad(void); +extern int __put_user_bad(void); + #define access_ok(type,addr,size) (1) #define verify_area(type,addr,size) (0) @@ -35,8 +40,8 @@ #define get_user __get_user #if BITS_PER_LONG == 32 -#define LDD_KERNEL(ptr) BUG() -#define LDD_USER(ptr) BUG() +#define LDD_KERNEL(ptr) __get_kernel_bad(); +#define LDD_USER(ptr) __get_user_bad(); #define STD_KERNEL(x, ptr) __put_kernel_asm64((u32)x,ptr) #define STD_USER(x, ptr) __put_user_asm64((u32)x,ptr) #else @@ -72,7 +77,7 @@ struct exception_table_entry { case 2: __get_kernel_asm("ldh",ptr); break; \ case 4: __get_kernel_asm("ldw",ptr); break; \ case 8: LDD_KERNEL(ptr); break; \ - default: BUG(); break; \ + default: __get_kernel_bad(); break; \ } \ } \ else { \ @@ -81,7 +86,7 @@ struct exception_table_entry { case 2: __get_user_asm("ldh",ptr); break; \ case 4: __get_user_asm("ldw",ptr); break; \ case 8: LDD_USER(ptr); break; \ - default: BUG(); break; \ + default: __get_user_bad(); break; \ } \ } \ \ @@ -141,7 +146,7 @@ struct exception_table_entry { case 2: __put_kernel_asm("sth",x,ptr); break; \ case 4: __put_kernel_asm("stw",x,ptr); break; \ case 8: STD_KERNEL(x,ptr); break; \ - default: BUG(); break; \ + default: __put_kernel_bad(); break; \ } \ } \ else { \ @@ -150,7 +155,7 @@ struct exception_table_entry { case 2: __put_user_asm("sth",x,ptr); break; \ case 4: __put_user_asm("stw",x,ptr); break; \ case 8: STD_USER(x,ptr); break; \ - default: BUG(); break; \ + default: __put_user_bad(); break; \ } \ } \ \ -- 2.53.0