diff options
Diffstat (limited to 'arch/alpha')
-rw-r--r-- | arch/alpha/Kconfig | 5 | ||||
-rw-r--r-- | arch/alpha/include/asm/atomic.h | 4 | ||||
-rw-r--r-- | arch/alpha/include/asm/bitops.h | 38 | ||||
-rw-r--r-- | arch/alpha/include/asm/thread_info.h | 2 | ||||
-rw-r--r-- | arch/alpha/kernel/pci-sysfs.c | 8 | ||||
-rw-r--r-- | arch/alpha/kernel/time.c | 170 | ||||
-rw-r--r-- | arch/alpha/math-emu/sfp-util.h | 5 | ||||
-rw-r--r-- | arch/alpha/mm/fault.c | 11 |
8 files changed, 109 insertions, 134 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 75291fd..24efdfe 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -51,9 +51,8 @@ config GENERIC_TIME bool default y -config ARCH_USES_GETTIMEOFFSET - bool - default y +config GENERIC_CMOS_UPDATE + def_bool y config ZONE_DMA bool diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index 610dff4..e756d04 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -17,8 +17,8 @@ #define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) #define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } ) -#define atomic_read(v) ((v)->counter + 0) -#define atomic64_read(v) ((v)->counter + 0) +#define atomic_read(v) (*(volatile int *)&(v)->counter) +#define atomic64_read(v) (*(volatile long *)&(v)->counter) #define atomic_set(v,i) ((v)->counter = (i)) #define atomic64_set(v,i) ((v)->counter = (i)) diff --git a/arch/alpha/include/asm/bitops.h b/arch/alpha/include/asm/bitops.h index 15f3ae2..1dce24b 100644 --- a/arch/alpha/include/asm/bitops.h +++ b/arch/alpha/include/asm/bitops.h @@ -405,29 +405,31 @@ static inline int fls(int x) #if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67) /* Whee. EV67 can calculate it directly. */ -static inline unsigned long hweight64(unsigned long w) +static inline unsigned long __arch_hweight64(unsigned long w) { return __kernel_ctpop(w); } -static inline unsigned int hweight32(unsigned int w) +static inline unsigned int __arch_weight32(unsigned int w) { - return hweight64(w); + return __arch_hweight64(w); } -static inline unsigned int hweight16(unsigned int w) +static inline unsigned int __arch_hweight16(unsigned int w) { - return hweight64(w & 0xffff); + return __arch_hweight64(w & 0xffff); } -static inline unsigned int hweight8(unsigned int w) +static inline unsigned int __arch_hweight8(unsigned int w) { - return hweight64(w & 0xff); + return __arch_hweight64(w & 0xff); } #else -#include <asm-generic/bitops/hweight.h> +#include <asm-generic/bitops/arch_hweight.h> #endif +#include <asm-generic/bitops/const_hweight.h> + #endif /* __KERNEL__ */ #include <asm-generic/bitops/find.h> @@ -436,22 +438,20 @@ static inline unsigned int hweight8(unsigned int w) /* * Every architecture must define this function. It's the fastest - * way of searching a 140-bit bitmap where the first 100 bits are - * unlikely to be set. It's guaranteed that at least one of the 140 - * bits is set. + * way of searching a 100-bit bitmap. It's guaranteed that at least + * one of the 100 bits is cleared. */ static inline unsigned long -sched_find_first_bit(unsigned long b[3]) +sched_find_first_bit(const unsigned long b[2]) { - unsigned long b0 = b[0], b1 = b[1], b2 = b[2]; - unsigned long ofs; + unsigned long b0, b1, ofs, tmp; - ofs = (b1 ? 64 : 128); - b1 = (b1 ? b1 : b2); - ofs = (b0 ? 0 : ofs); - b0 = (b0 ? b0 : b1); + b0 = b[0]; + b1 = b[1]; + ofs = (b0 ? 0 : 64); + tmp = (b0 ? b0 : b1); - return __ffs(b0) + ofs; + return __ffs(tmp) + ofs; } #include <asm-generic/bitops/ext2-non-atomic.h> diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h index b3e8886..6f32f9c 100644 --- a/arch/alpha/include/asm/thread_info.h +++ b/arch/alpha/include/asm/thread_info.h @@ -77,7 +77,7 @@ register struct thread_info *__current_thread_info __asm__("$8"); #define TIF_UAC_NOPRINT 10 /* see sysinfo.h */ #define TIF_UAC_NOFIX 11 #define TIF_UAC_SIGBUS 12 -#define TIF_MEMDIE 13 +#define TIF_MEMDIE 13 /* is terminating due to OOM killer */ #define TIF_RESTORE_SIGMASK 14 /* restore signal mask in do_signal */ #define TIF_FREEZE 16 /* is freezing for suspend */ diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c index d979e7c..a5fffc8 100644 --- a/arch/alpha/kernel/pci-sysfs.c +++ b/arch/alpha/kernel/pci-sysfs.c @@ -53,6 +53,7 @@ static int __pci_mmap_fits(struct pci_dev *pdev, int num, /** * pci_mmap_resource - map a PCI resource into user memory space + * @filp: open sysfs file * @kobj: kobject for mapping * @attr: struct bin_attribute for the file being mapped * @vma: struct vm_area_struct passed into the mmap @@ -60,7 +61,8 @@ static int __pci_mmap_fits(struct pci_dev *pdev, int num, * * Use the bus mapping routines to map a PCI resource into userspace. */ -static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, +static int pci_mmap_resource(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, struct vm_area_struct *vma, int sparse) { struct pci_dev *pdev = to_pci_dev(container_of(kobj, @@ -89,14 +91,14 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, return hose_mmap_page_range(pdev->sysdata, vma, mmap_type, sparse); } -static int pci_mmap_resource_sparse(struct kobject *kobj, +static int pci_mmap_resource_sparse(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, struct vm_area_struct *vma) { return pci_mmap_resource(kobj, attr, vma, 1); } -static int pci_mmap_resource_dense(struct kobject *kobj, +static int pci_mmap_resource_dense(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, struct vm_area_struct *vma) { diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index 5d08266..1efbed8 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -51,6 +51,7 @@ #include <linux/mc146818rtc.h> #include <linux/time.h> #include <linux/timex.h> +#include <linux/clocksource.h> #include "proto.h" #include "irq_impl.h" @@ -75,8 +76,6 @@ static struct { __u32 last_time; /* ticks/cycle * 2^48 */ unsigned long scaled_ticks_per_cycle; - /* last time the CMOS clock got updated */ - time_t last_rtc_update; /* partial unused tick */ unsigned long partial_tick; } state; @@ -91,6 +90,52 @@ static inline __u32 rpcc(void) return result; } +int update_persistent_clock(struct timespec now) +{ + return set_rtc_mmss(now.tv_sec); +} + +void read_persistent_clock(struct timespec *ts) +{ + unsigned int year, mon, day, hour, min, sec, epoch; + + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + sec = bcd2bin(sec); + min = bcd2bin(min); + hour = bcd2bin(hour); + day = bcd2bin(day); + mon = bcd2bin(mon); + year = bcd2bin(year); + } + + /* PC-like is standard; used for year >= 70 */ + epoch = 1900; + if (year < 20) + epoch = 2000; + else if (year >= 20 && year < 48) + /* NT epoch */ + epoch = 1980; + else if (year >= 48 && year < 70) + /* Digital UNIX epoch */ + epoch = 1952; + + printk(KERN_INFO "Using epoch = %d\n", epoch); + + if ((year += epoch) < 1970) + year += 100; + + ts->tv_sec = mktime(year, mon, day, hour, min, sec); +} + + + /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -123,19 +168,6 @@ irqreturn_t timer_interrupt(int irq, void *dev) if (nticks) do_timer(nticks); - /* - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - if (ntp_synced() - && xtime.tv_sec > state.last_rtc_update + 660 - && xtime.tv_nsec >= 500000 - ((unsigned) TICK_SIZE) / 2 - && xtime.tv_nsec <= 500000 + ((unsigned) TICK_SIZE) / 2) { - int tmp = set_rtc_mmss(xtime.tv_sec); - state.last_rtc_update = xtime.tv_sec - (tmp ? 600 : 0); - } - write_sequnlock(&xtime_lock); #ifndef CONFIG_SMP @@ -301,10 +333,38 @@ rpcc_after_update_in_progress(void) return rpcc(); } +#ifndef CONFIG_SMP +/* Until and unless we figure out how to get cpu cycle counters + in sync and keep them there, we can't use the rpcc. */ +static cycle_t read_rpcc(struct clocksource *cs) +{ + cycle_t ret = (cycle_t)rpcc(); + return ret; +} + +static struct clocksource clocksource_rpcc = { + .name = "rpcc", + .rating = 300, + .read = read_rpcc, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS +}; + +static inline void register_rpcc_clocksource(long cycle_freq) +{ + clocksource_calc_mult_shift(&clocksource_rpcc, cycle_freq, 4); + clocksource_register(&clocksource_rpcc); +} +#else /* !CONFIG_SMP */ +static inline void register_rpcc_clocksource(long cycle_freq) +{ +} +#endif /* !CONFIG_SMP */ + void __init time_init(void) { - unsigned int year, mon, day, hour, min, sec, cc1, cc2, epoch; + unsigned int cc1, cc2; unsigned long cycle_freq, tolerance; long diff; @@ -348,53 +408,17 @@ time_init(void) bogomips yet, but this is close on a 500Mhz box. */ __delay(1000000); - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - sec = bcd2bin(sec); - min = bcd2bin(min); - hour = bcd2bin(hour); - day = bcd2bin(day); - mon = bcd2bin(mon); - year = bcd2bin(year); - } - - /* PC-like is standard; used for year >= 70 */ - epoch = 1900; - if (year < 20) - epoch = 2000; - else if (year >= 20 && year < 48) - /* NT epoch */ - epoch = 1980; - else if (year >= 48 && year < 70) - /* Digital UNIX epoch */ - epoch = 1952; - - printk(KERN_INFO "Using epoch = %d\n", epoch); - - if ((year += epoch) < 1970) - year += 100; - - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = 0; - - wall_to_monotonic.tv_sec -= xtime.tv_sec; - wall_to_monotonic.tv_nsec = 0; if (HZ > (1<<16)) { extern void __you_loose (void); __you_loose(); } + register_rpcc_clocksource(cycle_freq); + state.last_time = cc1; state.scaled_ticks_per_cycle = ((unsigned long) HZ << FIX_SHIFT) / cycle_freq; - state.last_rtc_update = 0; state.partial_tick = 0L; /* Startup the timer source. */ @@ -402,44 +426,6 @@ time_init(void) } /* - * Use the cycle counter to estimate an displacement from the last time - * tick. Unfortunately the Alpha designers made only the low 32-bits of - * the cycle counter active, so we overflow on 8.2 seconds on a 500MHz - * part. So we can't do the "find absolute time in terms of cycles" thing - * that the other ports do. - */ -u32 arch_gettimeoffset(void) -{ -#ifdef CONFIG_SMP - /* Until and unless we figure out how to get cpu cycle counters - in sync and keep them there, we can't use the rpcc tricks. */ - return 0; -#else - unsigned long delta_cycles, delta_usec, partial_tick; - - delta_cycles = rpcc() - state.last_time; - partial_tick = state.partial_tick; - /* - * usec = cycles * ticks_per_cycle * 2**48 * 1e6 / (2**48 * ticks) - * = cycles * (s_t_p_c) * 1e6 / (2**48 * ticks) - * = cycles * (s_t_p_c) * 15625 / (2**42 * ticks) - * - * which, given a 600MHz cycle and a 1024Hz tick, has a - * dynamic range of about 1.7e17, which is less than the - * 1.8e19 in an unsigned long, so we are safe from overflow. - * - * Round, but with .5 up always, since .5 to even is harder - * with no clear gain. - */ - - delta_usec = (delta_cycles * state.scaled_ticks_per_cycle - + partial_tick) * 15625; - delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2; - return delta_usec * 1000; -#endif -} - -/* * In order to set the CMOS clock precisely, set_rtc_mmss has to be * called 500 ms after the second nowtime has started, because when * nowtime is written into the registers of the CMOS clock, it will diff --git a/arch/alpha/math-emu/sfp-util.h b/arch/alpha/math-emu/sfp-util.h index f53707f..d4c6ae7 100644 --- a/arch/alpha/math-emu/sfp-util.h +++ b/arch/alpha/math-emu/sfp-util.h @@ -28,8 +28,3 @@ extern unsigned long __udiv_qrnnd (unsigned long *, unsigned long, #define UDIV_NEEDS_NORMALIZATION 1 #define abort() goto bad_insn - -#ifndef __LITTLE_ENDIAN -#define __LITTLE_ENDIAN -1 -#endif -#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 00a31de..fadd5f8 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -142,7 +142,6 @@ do_page_fault(unsigned long address, unsigned long mmcsr, goto bad_area; } - survive: /* If for any reason at all we couldn't handle the fault, make sure we exit gracefully rather than endlessly redo the fault. */ @@ -188,16 +187,10 @@ do_page_fault(unsigned long address, unsigned long mmcsr, /* We ran out of memory, or some other thing happened to us that made us unable to handle the page fault gracefully. */ out_of_memory: - if (is_global_init(current)) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk(KERN_ALERT "VM: killing process %s(%d)\n", - current->comm, task_pid_nr(current)); if (!user_mode(regs)) goto no_context; - do_group_exit(SIGKILL); + pagefault_out_of_memory(); + return; do_sigbus: /* Send a sigbus, regardless of whether we were in kernel |