Commit 36eaa6e4 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[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
parent 8b318c7c
...@@ -184,7 +184,7 @@ source "drivers/scsi/Kconfig" ...@@ -184,7 +184,7 @@ source "drivers/scsi/Kconfig"
source "drivers/md/Kconfig" source "drivers/md/Kconfig"
#source drivers/message/fusion/Kconfig source drivers/message/fusion/Kconfig
#source drivers/ieee1394/Kconfig #source drivers/ieee1394/Kconfig
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
# Modified for PA-RISC Linux by Paul Lahaie, Alex deVries, # Modified for PA-RISC Linux by Paul Lahaie, Alex deVries,
# Mike Shaver, Helge Deller and Martin K. Petersen # Mike Shaver, Helge Deller and Martin K. Petersen
# #
NM = sh arch/parisc/nm
ifdef CONFIG_PARISC64 ifdef CONFIG_PARISC64
CROSS_COMPILE := hppa64-linux- CROSS_COMPILE := hppa64-linux-
UTS_MACHINE := parisc64 UTS_MACHINE := parisc64
......
...@@ -150,24 +150,25 @@ CONFIG_CHR_DEV_SG=y ...@@ -150,24 +150,25 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_LASI700=y CONFIG_SCSI_LASI700=y
CONFIG_53C700_MEM_MAPPED=y CONFIG_53C700_MEM_MAPPED=y
CONFIG_53C700_LE_ON_BE=y CONFIG_53C700_LE_ON_BE=y
# CONFIG_SCSI_NCR53C7xx is not set CONFIG_SCSI_SYM53C8XX_2=y
# CONFIG_SCSI_SYM53C8XX_2 is not set 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_ZALON=y
# CONFIG_SCSI_NCR53C8XX is not set
CONFIG_SCSI_SYM53C8XX=y
CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
CONFIG_SCSI_NCR53C8XX_SYNC=20 CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_NCR53C8XX_PROFILE is not set # 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_NCR53C8XX_SYMBIOS_COMPAT is not set
# CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 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_DC390T is not set
# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_DEBUG is not set
...@@ -374,7 +375,6 @@ CONFIG_SERIO=y ...@@ -374,7 +375,6 @@ CONFIG_SERIO=y
# CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PARKBD is not set # CONFIG_SERIO_PARKBD is not set
CONFIG_HP_SDC=y CONFIG_HP_SDC=y
CONFIG_HIL_MLC=y
# #
# Input Device Drivers # Input Device Drivers
......
...@@ -21,17 +21,20 @@ ...@@ -21,17 +21,20 @@
*/ */
#ifdef __LP64__ #ifdef __LP64__
#warning Must be changed for PA64 #warning PA64 support needs more work...did first cut
#endif #endif
#include <asm/offsets.h> #include <asm/offsets.h>
#include <asm/assembly.h>
#include <asm/signal.h>
#ifdef __LP64__
.level 2.0w
#else
.level 1.1 .level 1.1
#endif
.text .text
#include <asm/assembly.h>
#include <asm/signal.h>
/* These should probably go in a header file somewhere. /* These should probably go in a header file somewhere.
* They are duplicated in kernel/wrappers.S * They are duplicated in kernel/wrappers.S
* Possibly we should consider consolidating these * Possibly we should consider consolidating these
...@@ -41,41 +44,41 @@ ...@@ -41,41 +44,41 @@
#ifdef __LP64__ #ifdef __LP64__
#warning NEEDS WORK for 64-bit #warning NEEDS WORK for 64-bit
#endif #endif
stw %r3, PT_GR3(\regs) STREG %r3, PT_GR3(\regs)
stw %r4, PT_GR4(\regs) STREG %r4, PT_GR4(\regs)
stw %r5, PT_GR5(\regs) STREG %r5, PT_GR5(\regs)
stw %r6, PT_GR6(\regs) STREG %r6, PT_GR6(\regs)
stw %r7, PT_GR7(\regs) STREG %r7, PT_GR7(\regs)
stw %r8, PT_GR8(\regs) STREG %r8, PT_GR8(\regs)
stw %r9, PT_GR9(\regs) STREG %r9, PT_GR9(\regs)
stw %r10,PT_GR10(\regs) STREG %r10,PT_GR10(\regs)
stw %r11,PT_GR11(\regs) STREG %r11,PT_GR11(\regs)
stw %r12,PT_GR12(\regs) STREG %r12,PT_GR12(\regs)
stw %r13,PT_GR13(\regs) STREG %r13,PT_GR13(\regs)
stw %r14,PT_GR14(\regs) STREG %r14,PT_GR14(\regs)
stw %r15,PT_GR15(\regs) STREG %r15,PT_GR15(\regs)
stw %r16,PT_GR16(\regs) STREG %r16,PT_GR16(\regs)
stw %r17,PT_GR17(\regs) STREG %r17,PT_GR17(\regs)
stw %r18,PT_GR18(\regs) STREG %r18,PT_GR18(\regs)
.endm .endm
.macro reg_restore regs .macro reg_restore regs
ldw PT_GR3(\regs), %r3 LDREG PT_GR3(\regs), %r3
ldw PT_GR4(\regs), %r4 LDREG PT_GR4(\regs), %r4
ldw PT_GR5(\regs), %r5 LDREG PT_GR5(\regs), %r5
ldw PT_GR6(\regs), %r6 LDREG PT_GR6(\regs), %r6
ldw PT_GR7(\regs), %r7 LDREG PT_GR7(\regs), %r7
ldw PT_GR8(\regs), %r8 LDREG PT_GR8(\regs), %r8
ldw PT_GR9(\regs), %r9 LDREG PT_GR9(\regs), %r9
ldw PT_GR10(\regs),%r10 LDREG PT_GR10(\regs),%r10
ldw PT_GR11(\regs),%r11 LDREG PT_GR11(\regs),%r11
ldw PT_GR12(\regs),%r12 LDREG PT_GR12(\regs),%r12
ldw PT_GR13(\regs),%r13 LDREG PT_GR13(\regs),%r13
ldw PT_GR14(\regs),%r14 LDREG PT_GR14(\regs),%r14
ldw PT_GR15(\regs),%r15 LDREG PT_GR15(\regs),%r15
ldw PT_GR16(\regs),%r16 LDREG PT_GR16(\regs),%r16
ldw PT_GR17(\regs),%r17 LDREG PT_GR17(\regs),%r17
ldw PT_GR18(\regs),%r18 LDREG PT_GR18(\regs),%r18
.endm .endm
...@@ -88,18 +91,18 @@ hpux_fork_wrapper: ...@@ -88,18 +91,18 @@ hpux_fork_wrapper:
;! pointer in task ;! pointer in task
reg_save %r1 reg_save %r1
stw %r2,-20(%r30) STREG %r2,-20(%r30)
ldo 64(%r30),%r30 ldo 64(%r30),%r30
stw %r2,PT_GR19(%r1) ;! save for child STREG %r2,PT_GR19(%r1) ;! save for child
stw %r30,PT_GR21(%r1) ;! save for child STREG %r30,PT_GR21(%r1) ;! save for child
ldw PT_GR30(%r1),%r25 LDREG PT_GR30(%r1),%r25
mtctl %r25,%cr29 mtctl %r25,%cr29
copy %r1,%r24 copy %r1,%r24
bl sys_clone,%r2 bl sys_clone,%r2
ldi SIGCHLD,%r26 ldi SIGCHLD,%r26
ldw -84(%r30),%r2 LDREG -84(%r30),%r2
fork_return: fork_return:
ldo -64(%r30),%r30 ldo -64(%r30),%r30
ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
...@@ -116,14 +119,14 @@ fork_return: ...@@ -116,14 +119,14 @@ fork_return:
* know the difference. We can fix this later if necessary. * 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 */ comb,>>=,n %r28,%r1,fork_exit /* just let the syscall exit handle it */
or,= %r28,%r0,%r0 or,= %r28,%r0,%r0
or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */ 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 */ ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */
fork_exit: fork_exit:
bv %r0(%r2) bv %r0(%r2)
nop nop
/* Set the return value for the child */ /* Set the return value for the child */
...@@ -134,7 +137,7 @@ hpux_child_return: ...@@ -134,7 +137,7 @@ hpux_child_return:
nop nop
#endif #endif
ldw TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
b fork_return b fork_return
copy %r0,%r28 copy %r0,%r28
...@@ -157,17 +160,17 @@ hpux_execve_wrapper: ...@@ -157,17 +160,17 @@ hpux_execve_wrapper:
/* Store arg0, arg1 and arg2 so that hpux_execve will find them */ /* Store arg0, arg1 and arg2 so that hpux_execve will find them */
stw %r26,PT_GR26(%r1) STREG %r26,PT_GR26(%r1)
stw %r25,PT_GR25(%r1) STREG %r25,PT_GR25(%r1)
stw %r24,PT_GR24(%r1) STREG %r24,PT_GR24(%r1)
stw %r2,-20(%r30) STREG %r2,-20(%r30)
ldo 64(%r30),%r30 ldo 64(%r30),%r30
bl hpux_execve,%r2 bl hpux_execve,%r2
copy %r1,%arg0 copy %r1,%arg0
ldo -64(%r30),%r30 ldo -64(%r30),%r30
ldw -20(%r30),%r2 LDREG -20(%r30),%r2
/* If exec succeeded we need to load the args */ /* If exec succeeded we need to load the args */
...@@ -175,10 +178,10 @@ hpux_execve_wrapper: ...@@ -175,10 +178,10 @@ hpux_execve_wrapper:
comb,>>= %r28,%r1,exec_error comb,>>= %r28,%r1,exec_error
copy %r2,%r19 copy %r2,%r19
ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr
ldw TASK_PT_GR26(%r1),%r26 LDREG TASK_PT_GR26(%r1),%r26
ldw TASK_PT_GR25(%r1),%r25 LDREG TASK_PT_GR25(%r1),%r25
ldw TASK_PT_GR24(%r1),%r24 LDREG TASK_PT_GR24(%r1),%r24
ldw TASK_PT_GR23(%r1),%r23 LDREG TASK_PT_GR23(%r1),%r23
copy %r0,%r2 /* Flag to syscall_exit not to clear args */ copy %r0,%r2 /* Flag to syscall_exit not to clear args */
exec_error: exec_error:
...@@ -191,7 +194,7 @@ exec_error: ...@@ -191,7 +194,7 @@ exec_error:
/* HP-UX expects pipefd's returned in r28 & r29 */ /* HP-UX expects pipefd's returned in r28 & r29 */
hpux_pipe_wrapper: hpux_pipe_wrapper:
stw %r2,-20(%r30) STREG %r2,-20(%r30)
ldo 64(%r30),%r30 ldo 64(%r30),%r30
bl hpux_pipe,%r2 bl hpux_pipe,%r2
ldo -56(%r30),%r26 /* pass local array to hpux_pipe */ ldo -56(%r30),%r26 /* pass local array to hpux_pipe */
...@@ -199,12 +202,12 @@ hpux_pipe_wrapper: ...@@ -199,12 +202,12 @@ hpux_pipe_wrapper:
ldo -1024(%r0),%r1 ldo -1024(%r0),%r1
comb,>>= %r28,%r1,pipe_exit /* let syscall exit handle it */ 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 */ /* if success, load fd's from stack array */
ldw -56(%r30),%r28 LDREG -56(%r30),%r28
ldw -52(%r30),%r29 LDREG -52(%r30),%r29
pipe_exit: pipe_exit:
bv %r0(%r2) bv %r0(%r2)
...@@ -251,4 +254,4 @@ no_error: ...@@ -251,4 +254,4 @@ no_error:
hpux_unimplemented_wrapper: hpux_unimplemented_wrapper:
b hpux_unimplemented b hpux_unimplemented
stw %r22,-64(%r30) /* overwrite arg8 with syscall number */ STREG %r22,-64(%r30) /* overwrite arg8 with syscall number */
...@@ -232,7 +232,8 @@ void __flush_dcache_page(struct page *page) ...@@ -232,7 +232,8 @@ void __flush_dcache_page(struct page *page)
if (!page->mapping) if (!page->mapping)
return; return;
/* check shared list first if it's not empty...it's usually
* the shortest */
list_for_each(l, &page->mapping->i_mmap_shared) { list_for_each(l, &page->mapping->i_mmap_shared) {
struct vm_area_struct *mpnt; struct vm_area_struct *mpnt;
unsigned long off; unsigned long off;
...@@ -254,6 +255,33 @@ void __flush_dcache_page(struct page *page) ...@@ -254,6 +255,33 @@ void __flush_dcache_page(struct page *page)
flush_cache_page(mpnt, mpnt->vm_start + (off << PAGE_SHIFT)); 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, /* All user shared mappings should be equivalently mapped,
* so once we've flushed one we should be ok * so once we've flushed one we should be ok
*/ */
......
...@@ -447,7 +447,7 @@ int register_parisc_device(struct parisc_device *dev) ...@@ -447,7 +447,7 @@ int register_parisc_device(struct parisc_device *dev)
#define MAX_NATIVE_DEVICES 64 #define MAX_NATIVE_DEVICES 64
#define NATIVE_DEVICE_OFFSET 0x1000 #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_LOW offsetof(struct bc_module, io_io_low)
#define IO_IO_HIGH offsetof(struct bc_module, io_io_high) #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) #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, ...@@ -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); } 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 * walk_central_bus - Find devices attached to the central bus
......
...@@ -842,6 +842,10 @@ int probe_irq_off(unsigned long val) ...@@ -842,6 +842,10 @@ int probe_irq_off(unsigned long val)
return irq_found; return irq_found;
} }
unsigned int probe_irq_mask(unsigned long irqs)
{
return 0;
}
void __init init_IRQ(void) void __init init_IRQ(void)
{ {
......
...@@ -41,6 +41,13 @@ ...@@ -41,6 +41,13 @@
return -ENOEXEC; \ 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 /* three functions to determine where in the module core
* or init pieces the location is */ * or init pieces the location is */
static inline int is_init(struct module *me, void *loc) 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) ...@@ -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; got = me->module_core + me->arch.got_offset;
for (i = 0; got[i].addr; i++) for (i = 0; got[i].addr; i++)
if (got[i].addr == value) if (got[i].addr == value)
return i * sizeof(struct got_entry); goto out;
BUG_ON(++me->arch.got_count > me->arch.got_max); BUG_ON(++me->arch.got_count > me->arch.got_max);
got[i].addr = value; 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); return i * sizeof(struct got_entry);
} }
#endif /* __LP64__ */ #endif /* __LP64__ */
...@@ -387,7 +397,7 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, ...@@ -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[2] = 0xe820d000; /* bve (%r1) */
stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ 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 else
{ {
...@@ -516,6 +526,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, ...@@ -516,6 +526,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
case R_PARISC_PCREL22F: case R_PARISC_PCREL22F:
/* 22-bit PC relative address; only defined for pa20 */ /* 22-bit PC relative address; only defined for pa20 */
val = get_stub(me, val, addend, 0, is_init(me, loc)); 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; val = (val - dot - 8)/4;
CHECK_RELOC(val, 22); CHECK_RELOC(val, 22);
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
...@@ -618,6 +631,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, ...@@ -618,6 +631,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
val = get_stub(me, val, addend, 0, val = get_stub(me, val, addend, 0,
is_init(me, loc)); 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 /* FIXME: local symbols work as long as the
* core and init pieces aren't separated too * core and init pieces aren't separated too
* far. If this is ever broken, you will trip * far. If this is ever broken, you will trip
...@@ -646,6 +662,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, ...@@ -646,6 +662,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
/* 64-bit function address */ /* 64-bit function address */
if(is_local(me, (void *)(val + addend))) { if(is_local(me, (void *)(val + addend))) {
*loc64 = get_fdesc(me, 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 { } else {
/* if the symbol is not local to this /* if the symbol is not local to this
* module then val+addend is a pointer * module then val+addend is a pointer
...@@ -711,8 +730,13 @@ int module_finalize(const Elf_Ehdr *hdr, ...@@ -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); 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 */ /* no symbol table */
if(symhdr == NULL) if(symhdr == NULL)
......
...@@ -37,6 +37,7 @@ EXPORT_SYMBOL(get_pci_node_path); ...@@ -37,6 +37,7 @@ EXPORT_SYMBOL(get_pci_node_path);
#include <asm/irq.h> #include <asm/irq.h>
EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(probe_irq_mask);
#include <asm/processor.h> #include <asm/processor.h>
EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(kernel_thread);
...@@ -201,6 +202,9 @@ EXPORT_SYMBOL(__ashldi3); ...@@ -201,6 +202,9 @@ EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__lshrdi3); EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(__muldi3); EXPORT_SYMBOL(__muldi3);
asmlinkage void * __canonicalize_funcptr_for_compare(void *);
EXPORT_SYMBOL(__canonicalize_funcptr_for_compare);
#ifdef __LP64__ #ifdef __LP64__
extern void __divdi3(void); extern void __divdi3(void);
extern void __udivdi3(void); extern void __udivdi3(void);
......
This diff is collapsed.
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/version.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/offsets.h> #include <asm/offsets.h>
......
...@@ -123,7 +123,7 @@ save_control_regs: ...@@ -123,7 +123,7 @@ save_control_regs:
nop nop
restore_control_regs: 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(%cr15, %r26)
POP_CR(%cr31, %r26) POP_CR(%cr31, %r26)
POP_CR(%cr30, %r26) POP_CR(%cr30, %r26)
...@@ -275,6 +275,7 @@ r64_ret: ...@@ -275,6 +275,7 @@ r64_ret:
nop nop
#endif #endif
.export pc_in_user_space .export pc_in_user_space
.text .text
/* Doesn't belong here but I couldn't find a nicer spot. */ /* Doesn't belong here but I couldn't find a nicer spot. */
...@@ -283,3 +284,17 @@ pc_in_user_space: ...@@ -283,3 +284,17 @@ pc_in_user_space:
bv,n 0(%rp) bv,n 0(%rp)
nop 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
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
* arch/parisc/hpux/signal.c when we figure out how to do them. * arch/parisc/hpux/signal.c when we figure out how to do them.
*/ */
#include <linux/version.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h> #include <linux/smp.h>
...@@ -458,6 +457,8 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) ...@@ -458,6 +457,8 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
if (in_syscall) { if (in_syscall) {
/* Check the return code */ /* Check the return code */
switch (regs->gr[28]) { switch (regs->gr[28]) {
case -ERESTART_RESTARTBLOCK:
current_thread_info()->restart_block.fn = do_no_restart_syscall;
case -ERESTARTNOHAND: case -ERESTARTNOHAND:
DBG(("ERESTARTNOHAND: returning -EINTR\n")); DBG(("ERESTARTNOHAND: returning -EINTR\n"));
regs->gr[28] = -EINTR; regs->gr[28] = -EINTR;
...@@ -495,7 +496,8 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) ...@@ -495,7 +496,8 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
/* Did we come from a system call? */ /* Did we come from a system call? */
if (in_syscall) { if (in_syscall) {
/* Restart the system call - no handlers present */ /* 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] == -ERESTARTSYS ||
regs->gr[28] == -ERESTARTNOINTR) { regs->gr[28] == -ERESTARTNOINTR) {
/* Hooray for delayed branching. We don't /* Hooray for delayed branching. We don't
......
...@@ -30,8 +30,6 @@ static unsigned long get_unshared_area(unsigned long addr, unsigned long len) ...@@ -30,8 +30,6 @@ static unsigned long get_unshared_area(unsigned long addr, unsigned long len)
{ {
struct vm_area_struct *vma; struct vm_area_struct *vma;
if (!addr)
addr = TASK_UNMAPPED_BASE;
addr = PAGE_ALIGN(addr); addr = PAGE_ALIGN(addr);
for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { 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) ...@@ -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)) #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) mapping << (PAGE_SHIFT - 8);
int offset; return offset & 0x3FF000;
}
#endif
first_vma = list_entry(inode->i_mapping->i_mmap_shared.next, struct vm_area_struct, shared); static unsigned long get_shared_area(struct address_space *mapping,
offset = (first_vma->vm_start + ((pgoff - first_vma->vm_pgoff) << PAGE_SHIFT)) & (SHMLBA - 1); 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; addr = DCACHE_ALIGN(addr - offset) + offset;
for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { 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, ...@@ -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 arch_get_unmapped_area(struct file *filp, unsigned long addr,
unsigned long len, unsigned long pgoff, unsigned long flags) unsigned long len, unsigned long pgoff, unsigned long flags)
{ {
struct inode *inode = NULL; struct inode *inode;
if (len > TASK_SIZE) if (len > TASK_SIZE)
return -ENOMEM; return -ENOMEM;
if (!addr)
addr = TASK_UNMAPPED_BASE;
if (filp) { inode = filp ? filp->f_dentry->d_inode : NULL;
inode = filp->f_dentry->d_inode;
}
if (inode && (flags & MAP_SHARED) && (!list_empty(&inode->i_mapping->i_mmap_shared))) { if (inode && (flags & MAP_SHARED)) {
addr = get_shared_area(inode, addr, len, pgoff); addr = get_shared_area(inode->i_mapping, addr, len, pgoff);
} else { } else {
addr = get_unshared_area(addr, len); addr = get_unshared_area(addr, len);
} }
...@@ -185,6 +204,7 @@ extern asmlinkage ssize_t sys_pread64(unsigned int fd, char *buf, ...@@ -185,6 +204,7 @@ extern asmlinkage ssize_t sys_pread64(unsigned int fd, char *buf,
size_t count, loff_t pos); size_t count, loff_t pos);
extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char *buf, extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char *buf,
size_t count, loff_t pos); 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, asmlinkage ssize_t parisc_pread64(unsigned int fd, char *buf, size_t count,
unsigned int high, unsigned int low) unsigned int high, unsigned int low)
...@@ -198,6 +218,11 @@ asmlinkage ssize_t parisc_pwrite64(unsigned int fd, const char *buf, ...@@ -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); 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 * 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_ ...@@ -271,7 +296,7 @@ static int copyout_broken_shmid64(struct broken_shmid64_ds *buf, struct shmid64_
tbuf.shm_cpid = sbuf->shm_cpid; tbuf.shm_cpid = sbuf->shm_cpid;
tbuf.shm_lpid = sbuf->shm_lpid; tbuf.shm_lpid = sbuf->shm_lpid;
tbuf.shm_nattch = sbuf->shm_nattch; 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) int sys_msgctl_broken(int msqid, int cmd, struct msqid_ds *buf)
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/swap.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -373,18 +374,16 @@ put_compat_timeval(struct compat_timeval *u, struct timeval *t) ...@@ -373,18 +374,16 @@ put_compat_timeval(struct compat_timeval *u, struct timeval *t)
return copy_to_user(u, &t32, sizeof t32); return copy_to_user(u, &t32, sizeof t32);
} }
static int static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
get_compat_timeval(struct compat_timeval *u, struct timeval *t)
{ {
int err; long usec;
struct compat_timeval t32;
if ((err = copy_from_user(&t32, u, sizeof t32)) == 0) if (__get_user(o->tv_sec, &i->tv_sec))
{ return -EFAULT;
t->tv_sec = t32.tv_sec; if (__get_user(usec, &i->tv_usec))
t->tv_usec = t32.tv_usec; return -EFAULT;
} o->tv_nsec = usec * 1000;
return err; return 0;
} }
asmlinkage long sys32_time(compat_time_t *tloc) asmlinkage long sys32_time(compat_time_t *tloc)
...@@ -418,23 +417,22 @@ sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz) ...@@ -418,23 +417,22 @@ sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
return 0; return 0;
} }
asmlinkage int asmlinkage
sys32_settimeofday(struct compat_timespec *tv, struct timezone *tz) int sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
{ {
struct timeval ktv; struct timespec kts;
struct timezone ktz; struct timezone ktz;
extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
if (tv) { if (tv) {
if (get_compat_timeval(tv, &ktv)) if (get_ts32(&kts, tv))
return -EFAULT; return -EFAULT;
} }
if (tz) { if (tz) {
if (copy_from_user(&ktz, tz, sizeof(ktz))) if (copy_from_user(&ktz, tz, sizeof(ktz)))
return -EFAULT; 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) int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
...@@ -1089,6 +1087,27 @@ asmlinkage long sys32_msgrcv(int msqid, ...@@ -1089,6 +1087,27 @@ asmlinkage long sys32_msgrcv(int msqid,
return err; 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 */ /* EXPORT/UNEXPORT */
struct nfsctl_export32 { struct nfsctl_export32 {
char ex_client[NFSCLNT_IDMAX+1]; char ex_client[NFSCLNT_IDMAX+1];
......
...@@ -483,7 +483,7 @@ sys_call_table: ...@@ -483,7 +483,7 @@ sys_call_table:
ENTRY_SAME(madvise) ENTRY_SAME(madvise)
ENTRY_SAME(clone_wrapper) /* 120 */ ENTRY_SAME(clone_wrapper) /* 120 */
ENTRY_SAME(setdomainname) ENTRY_SAME(setdomainname)
ENTRY_SAME(sendfile) ENTRY_DIFF(sendfile)
/* struct sockaddr... */ /* struct sockaddr... */
ENTRY_SAME(recvfrom) ENTRY_SAME(recvfrom)
/* struct timex contains longs */ /* struct timex contains longs */
...@@ -592,7 +592,7 @@ sys_call_table: ...@@ -592,7 +592,7 @@ sys_call_table:
ENTRY_SAME(ni_syscall) ENTRY_SAME(ni_syscall)
ENTRY_SAME(ni_syscall) /* 205 */ ENTRY_SAME(ni_syscall) /* 205 */
ENTRY_SAME(gettid) ENTRY_SAME(gettid)
ENTRY_SAME(readahead) ENTRY_OURS(readahead)
ENTRY_SAME(ni_syscall) /* tkill */ ENTRY_SAME(ni_syscall) /* tkill */
ENTRY_SAME(sendfile64) ENTRY_SAME(sendfile64)
......
...@@ -221,6 +221,8 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) ...@@ -221,6 +221,8 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
return; return;
} }
oops_in_progress = 1;
/* Amuse the user in a SPARC fashion */ /* Amuse the user in a SPARC fashion */
printk( printk(
" _______________________________ \n" " _______________________________ \n"
...@@ -414,6 +416,8 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o ...@@ -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; static spinlock_t terminate_lock = SPIN_LOCK_UNLOCKED;
oops_in_progress = 1;
set_eiem(0); set_eiem(0);
local_irq_disable(); local_irq_disable();
spin_lock(&terminate_lock); spin_lock(&terminate_lock);
......
#!/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]*$'
...@@ -76,8 +76,6 @@ asp_init_chip(struct parisc_device *dev) ...@@ -76,8 +76,6 @@ asp_init_chip(struct parisc_device *dev)
printk(KERN_INFO "%s version %d at 0x%lx found.\n", printk(KERN_INFO "%s version %d at 0x%lx found.\n",
asp->name, asp->version, dev->hpa); 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 */ /* the IRQ ASP should use */
ret = -EBUSY; ret = -EBUSY;
......
...@@ -129,6 +129,92 @@ struct ioa_registers { ...@@ -129,6 +129,92 @@ struct ioa_registers {
volatile uint32_t io_io_high; /* Offset 15 */ 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 ioc {
struct ioa_registers *ioc_hpa; /* I/O MMU base address */ struct ioa_registers *ioc_hpa; /* I/O MMU base address */
u8 *res_map; /* resource map, bit == pdir entry */ u8 *res_map; /* resource map, bit == pdir entry */
...@@ -1448,13 +1534,74 @@ static void __init ccio_init_resources(struct ioc *ioc) ...@@ -1448,13 +1534,74 @@ static void __init ccio_init_resources(struct ioc *ioc)
(unsigned long)&ioc->ioc_hpa->io_io_low_hv); (unsigned long)&ioc->ioc_hpa->io_io_low_hv);
} }
static void expand_ioc_area(struct ioc *ioc, unsigned long size, static int expand_resource(struct resource *res, unsigned long size,
unsigned long min, unsigned long max, unsigned long align) unsigned long align)
{ {
#ifdef NASTY_HACK_FOR_K_CLASS struct resource *temp_res;
__raw_writel(0xfffff600, (unsigned long)&(ioc->ioc_hpa->io_io_high)); unsigned long start = res->start;
ioc->mmio_region[0].end = 0xf5ffffff; unsigned long end ;
#endif
/* 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, static struct resource *ccio_get_resource(struct ioc* ioc,
...@@ -1488,7 +1635,7 @@ int ccio_allocate_resource(const struct parisc_device *dev, ...@@ -1488,7 +1635,7 @@ int ccio_allocate_resource(const struct parisc_device *dev,
alignf_data)) alignf_data))
return 0; 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, return allocate_resource(parent, res, size, min, max, align, alignf,
alignf_data); alignf_data);
} }
...@@ -1522,7 +1669,6 @@ static int ccio_probe(struct parisc_device *dev) ...@@ -1522,7 +1669,6 @@ static int ccio_probe(struct parisc_device *dev)
memset(ioc, 0, sizeof(struct ioc)); memset(ioc, 0, sizeof(struct ioc));
ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn"; 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); printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa);
......
...@@ -401,23 +401,7 @@ dino_isr(int irq, void *intr_dev, struct pt_regs *regs) ...@@ -401,23 +401,7 @@ dino_isr(int irq, void *intr_dev, struct pt_regs *regs)
{ {
int irq; int irq;
/* irq = __ffs(mask);
* 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 */
}
}
mask &= ~(1<<irq); mask &= ~(1<<irq);
...@@ -440,7 +424,7 @@ dino_isr(int irq, void *intr_dev, struct pt_regs *regs) ...@@ -440,7 +424,7 @@ dino_isr(int irq, void *intr_dev, struct pt_regs *regs)
if (mask) { if (mask) {
if (--ilr_loop > 0) if (--ilr_loop > 0)
goto ilr_again; 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_NONE;
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -479,15 +463,35 @@ dino_card_setup(struct pci_bus *bus, unsigned long base_addr) ...@@ -479,15 +463,35 @@ dino_card_setup(struct pci_bus *bus, unsigned long base_addr)
int i; int i;
struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->dev)); struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->dev));
struct resource *res; struct resource *res;
char name[128];
int size;
res = &dino_dev->hba.lmmio_space; res = &dino_dev->hba.lmmio_space;
res->flags = IORESOURCE_MEM; 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, if (ccio_allocate_resource(dino_dev->hba.dev, res, _8MB,
(unsigned long) 0xfffffffff0000000UL | _8MB, F_EXTEND(0xf0000000UL) | _8MB,
0xffffffffffffffffUL &~ _8MB, _8MB, F_EXTEND(0xffffffffUL) &~ _8MB, _8MB,
NULL, NULL) < 0) { 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; return;
} }
bus->resource[1] = res; bus->resource[1] = res;
...@@ -495,9 +499,11 @@ dino_card_setup(struct pci_bus *bus, unsigned long base_addr) ...@@ -495,9 +499,11 @@ dino_card_setup(struct pci_bus *bus, unsigned long base_addr)
/* Now tell dino what range it has */ /* Now tell dino what range it has */
for (i = 1; i < 31; i++) { for (i = 1; i < 31; i++) {
if (res->start == (0xfffffffff0000000UL | i * _8MB)) if (res->start == F_EXTEND(0xf0000000UL | (i * _8MB)))
break; 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); gsc_writel(1 << i, base_addr + DINO_IO_ADDR_EN);
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
...@@ -521,7 +527,7 @@ dino_card_fixup(struct pci_dev *dev) ...@@ -521,7 +527,7 @@ dino_card_fixup(struct pci_dev *dev)
** Set Latency Timer to 0xff (not a shared bus) ** Set Latency Timer to 0xff (not a shared bus)
** Set CACHELINE_SIZE. ** 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. ** Program INT_LINE for card-mode devices.
...@@ -532,13 +538,13 @@ dino_card_fixup(struct pci_dev *dev) ...@@ -532,13 +538,13 @@ dino_card_fixup(struct pci_dev *dev)
** "-1" converts INTA-D (1-4) to PCIINTA-D (0-3) range. ** "-1" converts INTA-D (1-4) to PCIINTA-D (0-3) range.
** The additional "-1" adjusts for skewing the IRQ<->slot. ** 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 ; dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ;
/* Shouldn't really need to do this but it's in case someone tries /* Shouldn't really need to do this but it's in case someone tries
** to bypass PCI services and look at the card themselves. ** 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) ...@@ -585,8 +591,8 @@ dino_fixup_bus(struct pci_bus *bus)
#ifdef __LP64__ #ifdef __LP64__
/* Sign Extend MMIO addresses */ /* Sign Extend MMIO addresses */
else if (res->flags & IORESOURCE_MEM) { else if (res->flags & IORESOURCE_MEM) {
res->start |= 0xffffffff00000000UL; res->start |= F_EXTEND(0UL);
res->end |= 0xffffffff00000000UL; res->end |= F_EXTEND(0UL);
} }
#endif #endif
} }
...@@ -789,8 +795,8 @@ static int __init dino_common_init(struct parisc_device *dev, ...@@ -789,8 +795,8 @@ static int __init dino_common_init(struct parisc_device *dev,
return 0; return 0;
} }
#define CUJO_RAVEN_ADDR 0xfffffffff1000000UL #define CUJO_RAVEN_ADDR F_EXTEND(0xf1000000UL)
#define CUJO_FIREHAWK_ADDR 0xfffffffff1604000UL #define CUJO_FIREHAWK_ADDR F_EXTEND(0xf1604000UL)
#define CUJO_RAVEN_BADPAGE 0x01003000UL #define CUJO_RAVEN_BADPAGE 0x01003000UL
#define CUJO_FIREHAWK_BADPAGE 0x01607000UL #define CUJO_FIREHAWK_BADPAGE 0x01607000UL
...@@ -818,9 +824,16 @@ dino_driver_callback(struct parisc_device *dev) ...@@ -818,9 +824,16 @@ dino_driver_callback(struct parisc_device *dev)
{ {
struct dino_device *dino_dev; // Dino specific control struct struct dino_device *dino_dev; // Dino specific control struct
const char *version = "unknown"; const char *version = "unknown";
const char *name = "Dino"; const int name_len = 32;
char *name;
int is_cujo = 0; 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)) { if (is_card_dino(&dev->id)) {
version = "3.x (card mode)"; version = "3.x (card mode)";
} else { } else {
...@@ -838,8 +851,6 @@ dino_driver_callback(struct parisc_device *dev) ...@@ -838,8 +851,6 @@ dino_driver_callback(struct parisc_device *dev)
} }
printk("%s version %s found at 0x%lx\n", name, version, dev->hpa); 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)) { if (!request_mem_region(dev->hpa, PAGE_SIZE, name)) {
printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%ld)!\n", printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%ld)!\n",
......
...@@ -327,14 +327,13 @@ static int __devinit eisa_probe(struct parisc_device *dev) ...@@ -327,14 +327,13 @@ static int __devinit eisa_probe(struct parisc_device *dev)
printk(KERN_INFO "%s EISA Adapter found at 0x%08lx\n", printk(KERN_INFO "%s EISA Adapter found at 0x%08lx\n",
name, dev->hpa); name, dev->hpa);
snprintf(dev->dev.name, sizeof(dev->dev.name), "%s EISA", name);
eisa_dev.hba.dev = dev; eisa_dev.hba.dev = dev;
eisa_dev.hba.iommu = ccio_get_iommu(dev); eisa_dev.hba.iommu = ccio_get_iommu(dev);
eisa_dev.hba.lmmio_space.name = "EISA"; eisa_dev.hba.lmmio_space.name = "EISA";
eisa_dev.hba.lmmio_space.start = (unsigned long) 0xfffffffffc000000; eisa_dev.hba.lmmio_space.start = F_EXTEND(0xfc000000);
eisa_dev.hba.lmmio_space.end = (unsigned long) 0xffffffffffbfffff; eisa_dev.hba.lmmio_space.end = F_EXTEND(0xffbfffff);
eisa_dev.hba.lmmio_space.flags = IORESOURCE_MEM; eisa_dev.hba.lmmio_space.flags = IORESOURCE_MEM;
result = ccio_request_resource(dev, &eisa_dev.hba.lmmio_space); result = ccio_request_resource(dev, &eisa_dev.hba.lmmio_space);
if (result < 0) { if (result < 0) {
......
...@@ -70,7 +70,6 @@ static int hppb_probe(struct parisc_device *dev) ...@@ -70,7 +70,6 @@ static int hppb_probe(struct parisc_device *dev)
card = card->next; card = card->next;
} }
printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa); 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->hpa = dev->hpa;
card->mmio_region.name = "HP-PB Bus"; card->mmio_region.name = "HP-PB Bus";
......
...@@ -643,7 +643,7 @@ iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev) ...@@ -643,7 +643,7 @@ iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
if (NULL == isi) { if (NULL == isi) {
printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n", printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n",
pcidev->dev.name); pci_name(pcidev));
return(-1); return(-1);
} }
......
...@@ -185,8 +185,6 @@ lasi_init_chip(struct parisc_device *dev) ...@@ -185,8 +185,6 @@ lasi_init_chip(struct parisc_device *dev)
lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf; lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf;
printk(KERN_INFO "%s version %d at 0x%lx found.\n", printk(KERN_INFO "%s version %d at 0x%lx found.\n",
lasi->name, lasi->version, lasi->hpa); 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 */ /* initialize the chassis LEDs really early */
lasi_led_init(lasi->hpa); lasi_led_init(lasi->hpa);
......
...@@ -782,7 +782,7 @@ lba_fixup_bus(struct pci_bus *bus) ...@@ -782,7 +782,7 @@ lba_fixup_bus(struct pci_bus *bus)
int i; int i;
struct pci_dev *dev = pci_dev_b(ln); 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. */ /* Virtualize Device/Bridge Resources. */
for (i = 0; i < PCI_NUM_RESOURCES; i++) { for (i = 0; i < PCI_NUM_RESOURCES; i++) {
...@@ -1358,8 +1358,6 @@ lba_driver_callback(struct parisc_device *dev) ...@@ -1358,8 +1358,6 @@ lba_driver_callback(struct parisc_device *dev)
printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n", printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
MODULE_NAME, version, func_class & 0xf, dev->hpa); 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... */ /* Just in case we find some prototypes... */
if (func_class < 2) { if (func_class < 2) {
......
...@@ -91,7 +91,7 @@ struct pdc_chassis_lcd_info_ret_block { ...@@ -91,7 +91,7 @@ struct pdc_chassis_lcd_info_ret_block {
/* LCD_CMD and LCD_DATA for KittyHawk machines */ /* 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) #define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD+1)
/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's /* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's
......
...@@ -1978,8 +1978,6 @@ sba_driver_callback(struct parisc_device *dev) ...@@ -1978,8 +1978,6 @@ sba_driver_callback(struct parisc_device *dev)
printk(KERN_INFO "%s found %s at 0x%lx\n", printk(KERN_INFO "%s found %s at 0x%lx\n",
MODULE_NAME, version, dev->hpa); MODULE_NAME, version, dev->hpa);
snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %s",
MODULE_NAME, version);
#ifdef DEBUG_SBA_INIT #ifdef DEBUG_SBA_INIT
sba_dump_tlb(dev->hpa); sba_dump_tlb(dev->hpa);
......
...@@ -83,8 +83,6 @@ wax_init_chip(struct parisc_device *dev) ...@@ -83,8 +83,6 @@ wax_init_chip(struct parisc_device *dev)
wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */ wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */
printk(KERN_INFO "%s at 0x%lx found.\n", wax->name, wax->hpa); 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 */ /* Stop wax hissing for a bit */
wax_init_irq(wax); wax_init_irq(wax);
......
...@@ -49,27 +49,14 @@ extern spinlock_t __atomic_hash[ATOMIC_HASH_SIZE]; ...@@ -49,27 +49,14 @@ extern spinlock_t __atomic_hash[ATOMIC_HASH_SIZE];
* Cache-line alignment would conflict with, for example, linux/module.h * Cache-line alignment would conflict with, for example, linux/module.h
*/ */
typedef struct { typedef struct { volatile long counter; } atomic_t;
volatile int counter;
} atomic_t;
/*
** xchg/cmpxchg moved from asm/system.h - ggg
*/
#if 1
/* This should get optimized out since it's never called. /* This should get optimized out since it's never called.
** Or get a link error if xchg is used "wrong". ** Or get a link error if xchg is used "wrong".
*/ */
extern void __xchg_called_with_bad_pointer(void); 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 */ /* __xchg32/64 defined in arch/parisc/lib/bitops.c */
extern unsigned long __xchg8(char, char *); extern unsigned long __xchg8(char, char *);
......
...@@ -203,55 +203,102 @@ static __inline__ int test_bit(int nr, const void *address) ...@@ -203,55 +203,102 @@ static __inline__ int test_bit(int nr, const void *address)
return !!(*addr & mask); 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__ #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 * @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)) { static __inline__ unsigned long __ffs(unsigned long x)
result++; {
word >>= 1; unsigned long ret;
}
return result; __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 * ffs: find first bit set. returns 1 to BITS_PER_LONG or 0 (if none set)
* the libc and compiler builtin ffs routines, therefore * This is defined the same way as the libc and compiler builtin
* differs in spirit from the above ffz (man ffs). * ffs routines, therefore differs in spirit from the above ffz (man ffs).
*/ */
static __inline__ int ffs(int x) static __inline__ int ffs(int x)
{ {
if (!x) return x ? (__ffs((unsigned long)x) + 1) : 0;
return 0;
return __ffs((unsigned long)x);
} }
/* /*
* 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 * hweightN: returns the hamming weight (i.e. the number
......
...@@ -5,6 +5,25 @@ ...@@ -5,6 +5,25 @@
#ifdef __GNUC__ #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) static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
{ {
unsigned int temp; unsigned int temp;
...@@ -39,34 +58,21 @@ static __inline__ __const__ __u64 ___arch__swab64(__u64 x) { ...@@ -39,34 +58,21 @@ static __inline__ __const__ __u64 ___arch__swab64(__u64 x) {
return x; return x;
} }
#define __arch__swab64(x) ___arch__swab64(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) static __inline__ __const__ __u64 ___arch__swab64(__u64 x)
{ {
__u32 t1 = (__u32) x; __u32 t1 = ___arch__swab32((__u32) x);
__u32 t2 = (__u32) ((x) >> 32); __u32 t2 = ___arch__swab32((__u32) (x >> 32));
___arch__swab32(t1); return (((__u64) t1 << 32) | t2);
___arch__swab32(t2);
return (((__u64) t1 << 32) + ((__u64) t2));
} }
#define __arch__swab64(x) ___arch__swab64(x)
#define __BYTEORDER_HAS_U64__
#endif #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) #define __arch__swab16(x) ___arch__swab16(x)
#define __arch__swab24(x) ___arch__swab24(x)
#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) #define __arch__swab32(x) ___arch__swab32(x)
# define __BYTEORDER_HAS_U64__
# define __SWAB_64_THRU_32__
#endif
#endif /* __GNUC__ */ #endif /* __GNUC__ */
......
...@@ -78,8 +78,9 @@ static inline void flush_dcache_page(struct page *page) ...@@ -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_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) \ #define flush_icache_user_range(vma, page, addr, len) do { \
flush_icache_page((vma), (page)) 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, static inline void flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end) unsigned long start, unsigned long end)
......
...@@ -283,6 +283,7 @@ struct pt_regs; /* forward declaration... */ ...@@ -283,6 +283,7 @@ struct pt_regs; /* forward declaration... */
*/ */
#define ELF_DATA ELFDATA2MSB #define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_PARISC #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 /* %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 registered using atexit. This provides a mean for the dynamic
......
#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
...@@ -291,4 +291,11 @@ extern void outsl (unsigned long port, const void *src, unsigned long count); ...@@ -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(_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) #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 #endif
#ifndef _ARCH_PARISC_LOCAL_H
#define _ARCH_PARISC_LOCAL_H
#include <linux/percpu.h>
#include <asm/atomic.h>
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 */
#ifndef _PARISC_SECTIONS_H
#define _PARISC_SECTIONS_H
/* nothing to see, move along */
#include <asm-generic/sections.h>
#endif
...@@ -28,6 +28,11 @@ ...@@ -28,6 +28,11 @@
* that put_user is the same as __put_user, etc. * 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 access_ok(type,addr,size) (1)
#define verify_area(type,addr,size) (0) #define verify_area(type,addr,size) (0)
...@@ -35,8 +40,8 @@ ...@@ -35,8 +40,8 @@
#define get_user __get_user #define get_user __get_user
#if BITS_PER_LONG == 32 #if BITS_PER_LONG == 32
#define LDD_KERNEL(ptr) BUG() #define LDD_KERNEL(ptr) __get_kernel_bad();
#define LDD_USER(ptr) BUG() #define LDD_USER(ptr) __get_user_bad();
#define STD_KERNEL(x, ptr) __put_kernel_asm64((u32)x,ptr) #define STD_KERNEL(x, ptr) __put_kernel_asm64((u32)x,ptr)
#define STD_USER(x, ptr) __put_user_asm64((u32)x,ptr) #define STD_USER(x, ptr) __put_user_asm64((u32)x,ptr)
#else #else
...@@ -72,7 +77,7 @@ struct exception_table_entry { ...@@ -72,7 +77,7 @@ struct exception_table_entry {
case 2: __get_kernel_asm("ldh",ptr); break; \ case 2: __get_kernel_asm("ldh",ptr); break; \
case 4: __get_kernel_asm("ldw",ptr); break; \ case 4: __get_kernel_asm("ldw",ptr); break; \
case 8: LDD_KERNEL(ptr); break; \ case 8: LDD_KERNEL(ptr); break; \
default: BUG(); break; \ default: __get_kernel_bad(); break; \
} \ } \
} \ } \
else { \ else { \
...@@ -81,7 +86,7 @@ struct exception_table_entry { ...@@ -81,7 +86,7 @@ struct exception_table_entry {
case 2: __get_user_asm("ldh",ptr); break; \ case 2: __get_user_asm("ldh",ptr); break; \
case 4: __get_user_asm("ldw",ptr); break; \ case 4: __get_user_asm("ldw",ptr); break; \
case 8: LDD_USER(ptr); break; \ case 8: LDD_USER(ptr); break; \
default: BUG(); break; \ default: __get_user_bad(); break; \
} \ } \
} \ } \
\ \
...@@ -141,7 +146,7 @@ struct exception_table_entry { ...@@ -141,7 +146,7 @@ struct exception_table_entry {
case 2: __put_kernel_asm("sth",x,ptr); break; \ case 2: __put_kernel_asm("sth",x,ptr); break; \
case 4: __put_kernel_asm("stw",x,ptr); break; \ case 4: __put_kernel_asm("stw",x,ptr); break; \
case 8: STD_KERNEL(x,ptr); break; \ case 8: STD_KERNEL(x,ptr); break; \
default: BUG(); break; \ default: __put_kernel_bad(); break; \
} \ } \
} \ } \
else { \ else { \
...@@ -150,7 +155,7 @@ struct exception_table_entry { ...@@ -150,7 +155,7 @@ struct exception_table_entry {
case 2: __put_user_asm("sth",x,ptr); break; \ case 2: __put_user_asm("sth",x,ptr); break; \
case 4: __put_user_asm("stw",x,ptr); break; \ case 4: __put_user_asm("stw",x,ptr); break; \
case 8: STD_USER(x,ptr); break; \ case 8: STD_USER(x,ptr); break; \
default: BUG(); break; \ default: __put_user_bad(); break; \
} \ } \
} \ } \
\ \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment