From 17cca07237617a2d712eb44cffd8720055e61291 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 4 Oct 2006 13:16:10 -0600 Subject: [PA-RISC] Fix sys32_sysctl When CONFIG_SYSCTL_SYSCALL isn't defined, do_sysctl doesn't exist and we fail to link. Fix with an ifdef, the same way sparc64 did. Also add some minor changes to be more like sparc64. Signed-off-by: Matthew Wilcox --- arch/parisc/kernel/sys_parisc32.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index e3b30bc..e0e4e0b 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -111,13 +111,14 @@ struct __sysctl_args32 { asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) { +#ifndef CONFIG_SYSCTL_SYSCALL + return -ENOSYS; +#else struct __sysctl_args32 tmp; int error; unsigned int oldlen32; - size_t oldlen, *oldlenp = NULL; + size_t oldlen, __user *oldlenp = NULL; unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7; - extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp, - void *newval, size_t newlen); DBG(("sysctl32(%p)\n", args)); @@ -144,8 +145,9 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) } lock_kernel(); - error = do_sysctl((int *)(u64)tmp.name, tmp.nlen, (void *)(u64)tmp.oldval, - oldlenp, (void *)(u64)tmp.newval, tmp.newlen); + error = do_sysctl((int __user *)(u64)tmp.name, tmp.nlen, + (void __user *)(u64)tmp.oldval, oldlenp, + (void __user *)(u64)tmp.newval, tmp.newlen); unlock_kernel(); if (oldlenp) { if (!error) { @@ -157,10 +159,11 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) error = -EFAULT; } } - if (copy_to_user(&args->__unused[0], tmp.__unused, sizeof(tmp.__unused))) + if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused))) error = -EFAULT; } return error; +#endif } #endif /* CONFIG_SYSCTL */ -- cgit v1.1 From 15c130c1cde38da528f82efce882e8d7632f4d91 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 4 Oct 2006 13:18:25 -0600 Subject: [PA-RISC] Fix filldir warnings filldir_t now takes a u64, not an ino_t. Signed-off-by: Matthew Wilcox --- arch/parisc/hpux/fs.c | 2 +- arch/parisc/kernel/sys_parisc32.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c index 2d58b92..4204cd1 100644 --- a/arch/parisc/hpux/fs.c +++ b/arch/parisc/hpux/fs.c @@ -73,7 +73,7 @@ struct getdents_callback { #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) static int filldir(void * __buf, const char * name, int namlen, loff_t offset, - ino_t ino, unsigned d_type) + u64 ino, unsigned d_type) { struct hpux_dirent * dirent; struct getdents_callback * buf = (struct getdents_callback *) __buf; diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index e0e4e0b..29be437 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -313,9 +313,8 @@ struct readdir32_callback { #define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1))) #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) -static int -filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino, - unsigned int d_type) +static int filldir32 (void *__buf, const char *name, int namlen, + loff_t offset, u64 ino, unsigned int d_type) { struct linux32_dirent __user * dirent; struct getdents32_callback * buf = (struct getdents32_callback *) __buf; @@ -377,9 +376,8 @@ out: return error; } -static int -fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, - unsigned int d_type) +static int fillonedir32(void * __buf, const char * name, int namlen, + loff_t offset, u64 ino, unsigned int d_type) { struct readdir32_callback * buf = (struct readdir32_callback *) __buf; struct old_linux32_dirent __user * dirent; -- cgit v1.1 From ccd6c355e89a21d9047ae19471629758d3a01959 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 4 Oct 2006 13:27:45 -0600 Subject: [PA-RISC] Remove warning from pci.c max() doesn't like comparing an unsigned long and a resource_size_t, so make the local variables resource_size_t too. Signed-off-by: Matthew Wilcox --- arch/parisc/kernel/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index d3b8fc5..199887a 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -290,7 +290,7 @@ EXPORT_SYMBOL(pcibios_bus_to_resource); void pcibios_align_resource(void *data, struct resource *res, resource_size_t size, resource_size_t alignment) { - unsigned long mask, align; + resource_size_t mask, align; DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx, 0x%lx)\n", pci_name(((struct pci_dev *) data)), -- cgit v1.1 From f64ef295032d07345ca26bf4876a1577c4dccb37 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 4 Oct 2006 13:33:53 -0600 Subject: [PA-RISC] Fix parisc_newuname() The utsname virtualisation broke parisc_newuname compilation. Rewrite the implementation to call sys_newuname() like sparc64 does. Signed-off-by: Matthew Wilcox --- arch/parisc/kernel/sys_parisc.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 1db5588..512642d 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -266,30 +266,17 @@ long parisc_personality(unsigned long personality) return err; } -static inline int override_machine(char __user *mach) { -#ifdef CONFIG_COMPAT - if (personality(current->personality) == PER_LINUX32) { - if (__put_user(0, mach + 6) || - __put_user(0, mach + 7)) - return -EFAULT; - } - - return 0; -#else /*!CONFIG_COMPAT*/ - return 0; -#endif /*CONFIG_COMPAT*/ -} - -long parisc_newuname(struct new_utsname __user *utsname) +long parisc_newuname(struct new_utsname __user *name) { - int err = 0; + int err = sys_newuname(name); - down_read(&uts_sem); - if (copy_to_user(utsname, &system_utsname, sizeof(*utsname))) - err = -EFAULT; - up_read(&uts_sem); - - err = override_machine(utsname->machine); +#ifdef CONFIG_COMPAT + if (!err && personality(current->personality) == PER_LINUX32) { + if (__put_user(0, name->machine + 6) || + __put_user(0, name->machine + 7)) + err = -EFAULT; + } +#endif - return (long)err; + return err; } -- cgit v1.1 From 1070c9655b90016ec4c9b59c402292e57ee15885 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 4 Oct 2006 13:37:41 -0600 Subject: [PA-RISC] Fix must_check warnings in drivers.c Panic if we can't register the parisc bus or the root parisc device. There's no way we can boot without them, so let the user know ASAP. If we can't register a parisc device, handle the failure gracefully. Signed-off-by: Matthew Wilcox --- arch/parisc/kernel/drivers.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 3d569a4..2b257e4 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -424,7 +424,10 @@ struct parisc_device * create_tree_node(char id, struct device *parent) /* make the generic dma mask a pointer to the parisc one */ dev->dev.dma_mask = &dev->dma_mask; dev->dev.coherent_dma_mask = dev->dma_mask; - device_register(&dev->dev); + if (!device_register(&dev->dev)) { + kfree(dev); + return NULL; + } return dev; } @@ -850,8 +853,10 @@ static void print_parisc_device(struct parisc_device *dev) */ void init_parisc_bus(void) { - bus_register(&parisc_bus_type); - device_register(&root); + if (!bus_register(&parisc_bus_type)) + panic("Could not register PA-RISC bus type\n"); + if (!device_register(&root)) + panic("Could not register PA-RISC root device\n"); get_device(&root); } -- cgit v1.1 From 1604f31895dcdb42edf6511ce7ef0546ff92c8e5 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 4 Oct 2006 15:12:52 -0600 Subject: [PA-RISC] Fix time.c for new do_timer() calling convention do_timer now wants to know how many ticks have elapsed. Now that we have to calculate that, we can eliminate some of the clever code that avoided having to calculate that. Also add some more documentation. I'd like to thank Grant Grundler for helping me with this. Signed-off-by: Matthew Wilcox --- arch/parisc/kernel/time.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index b3496b5..1d58ce0e 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -38,11 +38,28 @@ static unsigned long clocktick __read_mostly; /* timer cycles per tick */ extern void smp_do_timer(struct pt_regs *regs); #endif +/* + * We keep time on PA-RISC Linux by using the Interval Timer which is + * a pair of registers; one is read-only and one is write-only; both + * accessed through CR16. The read-only register is 32 or 64 bits wide, + * and increments by 1 every CPU clock tick. The architecture only + * guarantees us a rate between 0.5 and 2, but all implementations use a + * rate of 1. The write-only register is 32-bits wide. When the lowest + * 32 bits of the read-only register compare equal to the write-only + * register, it raises a maskable external interrupt. Each processor has + * an Interval Timer of its own and they are not synchronised. + * + * We want to generate an interrupt every 1/HZ seconds. So we program + * CR16 to interrupt every @clocktick cycles. The it_value in cpu_data + * is programmed with the intended time of the next tick. We can be + * held off for an arbitrarily long period of time by interrupts being + * disabled, so we may miss one or more ticks. + */ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned long now; unsigned long next_tick; - unsigned long cycles_elapsed; + unsigned long cycles_elapsed, ticks_elapsed; unsigned long cycles_remainder; unsigned int cpu = smp_processor_id(); @@ -67,11 +84,14 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) * of the more expensive div/mul method */ cycles_remainder = cycles_elapsed; + ticks_elapsed = 1; while (cycles_remainder > cpt) { cycles_remainder -= cpt; + ticks_elapsed++; } } else { cycles_remainder = cycles_elapsed % cpt; + ticks_elapsed = 1 + cycles_elapsed / cpt; } /* Can we differentiate between "early CR16" (aka Scenario 1) and @@ -81,18 +101,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) * cycles after the IT fires. But it's arbitrary how much time passes * before we call it "late". I've picked one second. */ -/* aproximate HZ with shifts. Intended math is "(elapsed/clocktick) > HZ" */ -#if HZ == 1000 - if (cycles_elapsed > (cpt << 10) ) -#elif HZ == 250 - if (cycles_elapsed > (cpt << 8) ) -#elif HZ == 100 - if (cycles_elapsed > (cpt << 7) ) -#else -#warn WTF is HZ set to anyway? - if (cycles_elapsed > (HZ * cpt) ) -#endif - { + if (ticks_elapsed > HZ) { /* Scenario 3: very long delay? bad in any case */ printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!" " cycles %lX rem %lX " @@ -136,7 +145,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) #endif if (cpu == 0) { write_seqlock(&xtime_lock); - do_timer(regs); + do_timer(ticks_elapsed); write_sequnlock(&xtime_lock); } -- cgit v1.1