From: NIIBE Y. <gn...@m1...> - 2002-01-08 05:13:25
|
Here's the changes against linux-2.5.2-pre10, I'm about to send to Linus. -------------------------- All are SuperH specific. Follow up: asm/scatterlist, Use of yield(), Matin Mares' e-mail address. Improvement: Implement pgprot_noncached (Takashi Yoshii) include/asm-sh/pgtable.h SH Watchdog timer update (Paul Mundt) drivers/char/shwdt.c FPU handling change (Kazumoto Kojima, NIIBE Yutaka) arch/sh/kernel/entry.S arch/sh/kernel/fpu.c arch/sh/kernel/head.S arch/sh/kernel/processor.h Bug fix: Unaligned access & null current->mm (Jeremy Siegel) arch/sh/kernel/traps.c arch/sh/mm/fault.c HW-bug workaround of RTC (SUGIOKA Toshinobu) arch/sh/kernel/rtc.c diff -ruNp linux/arch/sh/kernel/entry.S linux-2.5.2-pre10.superh/arch/sh/kernel/entry.S --- linux/arch/sh/kernel/entry.S Tue Oct 9 02:39:18 2001 +++ linux-2.5.2-pre10.superh/arch/sh/kernel/entry.S Sat Dec 29 15:50:38 2001 @@ -66,7 +66,6 @@ need_resched = 20 tsk_ptrace = 24 PT_TRACESYS = 0x00000002 -PF_USEDFPU = 0x00100000 ENOSYS = 38 EINVAL = 22 @@ -567,12 +566,6 @@ __irq_stat: .align 2 restore_all: -#if defined(__SH4__) - mov.l __fpu_prepare_fd, r0 - jsr @r0 - stc sr, r4 -#endif - ! mov.l @r15+, r0 mov.l @r15+, r1 mov.l @r15+, r2 @@ -585,7 +578,7 @@ restore_all: stc sr, r8 mov.l __blrb_flags, r9 ! BL =1, RB=1 or r9, r8 - ldc r8, sr ! here, change the register bank + ldc r8, sr ! here, change the register bank ! mov.l @r15+, r8 mov.l @r15+, r9 @@ -594,25 +587,25 @@ restore_all: mov.l @r15+, r12 mov.l @r15+, r13 mov.l @r15+, r14 - mov.l @r15+, k4 ! original stack pointer + mov.l @r15+, k4 ! original stack pointer ldc.l @r15+, spc lds.l @r15+, pr - mov.l @r15+, k3 ! original SR + mov.l @r15+, k3 ! original SR ldc.l @r15+, gbr lds.l @r15+, mach lds.l @r15+, macl - add #4, r15 ! Skip syscall number + add #4, r15 ! Skip syscall number ! ! Calculate new SR value - mov k3, k2 ! original SR value + mov k3, k2 ! original SR value mov.l 1f, k1 stc sr, k0 - and k1, k0 ! Get current FD-bit + and k1, k0 ! Get current FD-bit mov.l 2f, k1 - and k1, k2 ! Mask orignal SR value - or k0, k2 ! Inherit current FD-bit + and k1, k2 ! Mask orignal SR value + or k0, k2 ! Inherit current FD-bit ! - mov k3, k0 ! Calculate IMASK-bits + mov k3, k0 ! Calculate IMASK-bits shlr2 k0 and #0x3c, k0 cmp/eq #0x3c, k0 @@ -620,69 +613,15 @@ restore_all: shll2 k0 mov g_imask, k0 ! -7: or k0, k2 ! Set the IMASK-bits +7: or k0, k2 ! Set the IMASK-bits ldc k2, ssr ! -#if defined(__SH4__) - shll k2 - shll k2 - bf 9f ! user mode - /* Kernel to kernel transition */ - mov.l 1f, k1 - tst k1, k3 - bf 9f ! it hadn't FPU - ! Kernel to kernel and FPU was used - ! There's the case we don't get FPU now - stc sr, k2 - tst k1, k2 - bt 8f - ! We need to grab FPU here - xor k1, k2 - ldc k2, sr ! Grab FPU - mov.l __init_task_flags, k1 - mov.l @k1, k2 - mov.l __PF_USEDFPU, k0 - or k0, k2 - mov.l k2, @k1 ! Set init_task.flags |= PF_USEDFPU - ! - ! Restoring FPU... - ! -8: mov.l 3f, k1 - lds k1, fpscr - fmov.s @r15+, fr0 - fmov.s @r15+, fr1 - fmov.s @r15+, fr2 - fmov.s @r15+, fr3 - fmov.s @r15+, fr4 - fmov.s @r15+, fr5 - fmov.s @r15+, fr6 - fmov.s @r15+, fr7 - fmov.s @r15+, fr8 - fmov.s @r15+, fr9 - fmov.s @r15+, fr10 - fmov.s @r15+, fr11 - fmov.s @r15+, fr12 - fmov.s @r15+, fr13 - fmov.s @r15+, fr14 - fmov.s @r15+, fr15 - lds.l @r15+, fpscr - lds.l @r15+, fpul -9: -#endif mov k4, r15 rte nop .align 2 __blrb_flags: .long 0x30000000 -#if defined(__SH4__) -__fpu_prepare_fd: - .long SYMBOL_NAME(fpu_prepare_fd) -__init_task_flags: - .long SYMBOL_NAME(init_task_union)+4 -__PF_USEDFPU: - .long PF_USEDFPU -#endif 1: .long 0x00008000 ! FD 2: .long 0xffff7f0f ! ~(IMASK+FD) 3: .long 0x00080000 ! SZ=0, PR=1 @@ -732,61 +671,21 @@ handle_exception: ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), ! save all registers onto stack. ! - stc ssr, k0 ! from kernel space? - shll k0 ! Check MD bit (bit30) by shifting it into the T bit - shll k0 -#if defined(__SH4__) - bf/s 8f ! it's from user to kernel transition - mov r15, k0 ! save original stack to k0 - /* It's a kernel to kernel transition. */ - /* Is the FPU disabled? */ - mov.l 2f, k1 - stc ssr, k0 - tst k1, k0 - mov.l 4f, k1 - bf/s 9f ! FPU is not enabled, no need to save it - mov r15, k0 ! save original stack to k0 - ! FPU is enabled, save it - ! /* XXX: Need to save another bank of FPU if all FPU feature is used */ - ! /* Currently it's not the case for GCC (only udivsi3_i4, divsi3_i4) */ - sts.l fpul, @-r15 - sts.l fpscr, @-r15 - mov.l 6f, k1 - lds k1, fpscr - mov.l 3f, k1 - fmov.s fr15, @-r15 - fmov.s fr14, @-r15 - fmov.s fr13, @-r15 - fmov.s fr12, @-r15 - fmov.s fr11, @-r15 - fmov.s fr10, @-r15 - fmov.s fr9, @-r15 - fmov.s fr8, @-r15 - fmov.s fr7, @-r15 - fmov.s fr6, @-r15 - fmov.s fr5, @-r15 - fmov.s fr4, @-r15 - fmov.s fr3, @-r15 - fmov.s fr2, @-r15 - fmov.s fr1, @-r15 - bra 9f - fmov.s fr0, @-r15 -#else - mov.l 3f, k1 - bt/s 9f ! it's a kernel to kernel transition, and skip the FPU save. - mov r15, k0 ! save original stack to k0 anyway -#endif -8: /* User space to kernel */ + stc ssr, k0 ! Is it from kernel space? + shll k0 ! Check MD bit (bit30) by shifting it into... + shll k0 ! ...the T bit + bt/s 9f ! It's a kernel to kernel transition. + mov r15, k0 ! save original stack to k0 + /* User space to kernel */ mov #0x20, k1 - shll8 k1 ! k1 <= 8192 == THREAD_SIZE + shll8 k1 ! k1 <= 8192 == THREAD_SIZE add current, k1 mov k1, r15 ! change to kernel stack ! - mov.l 4f, k1 ! let kernel release FPU -9: ! Save the user registers on the stack. - ! At this point, k1 should have been set to the new SR value - mov #-1, k4 - mov.l k4, @-r15 ! syscall_nr (default: -1) +9: mov #-1, k4 + mov.l 3f, k1 + ! Save the user registers on the stack. + mov.l k4, @-r15 ! syscall_nr (default: -1) ! sts.l macl, @-r15 sts.l mach, @-r15 @@ -806,11 +705,11 @@ handle_exception: mov.l r9, @-r15 mov.l r8, @-r15 ! - stc sr, r8 ! Back to normal register bank, and - or k1, r8 ! Block all interrupts, may release FPU + stc sr, r8 ! Back to normal register bank, and + or k1, r8 ! Block all interrupts mov.l 5f, k1 - and k1, r8 ! ... - ldc r8, sr ! ...changed here. + and k1, r8 ! ... + ldc r8, sr ! ...changed here. ! mov.l r7, @-r15 mov.l r6, @-r15 @@ -831,9 +730,7 @@ handle_exception: nop .align 2 1: .long SYMBOL_NAME(exception_handling_table) -2: .long 0x00008000 ! FD=1 3: .long 0x000000f0 ! FD=0, IMASK=15 -4: .long 0x000080f0 ! FD=1, IMASK=15 5: .long 0xcfffffff ! RB=0, BL=0 6: .long 0x00080000 ! SZ=0, PR=1 diff -ruNp linux/arch/sh/kernel/fpu.c linux-2.5.2-pre10.superh/arch/sh/kernel/fpu.c --- linux/arch/sh/kernel/fpu.c Mon Jan 29 11:56:00 2001 +++ linux-2.5.2-pre10.superh/arch/sh/kernel/fpu.c Sat Dec 29 15:50:38 2001 @@ -18,6 +18,10 @@ #include <asm/processor.h> #include <asm/io.h> +/* + * Save FPU registers onto task structure. + * Assume called with FPU enabled (SR.FD=0). + */ void save_fpu(struct task_struct *tsk) { @@ -118,7 +122,8 @@ restore_fpu(struct task_struct *tsk) * double precission represents signaling NANS. */ -void fpu_init(void) +static void +fpu_init(void) { asm volatile("lds %0, fpul\n\t" "lds %1, fpscr\n\t" @@ -160,15 +165,125 @@ void fpu_init(void) : "r" (0), "r" (FPSCR_INIT)); } +/** + * denormal_to_double - Given denormalized float number, + * store double float + * + * @fpu: Pointer to sh_fpu_hard structure + * @n: Index to FP register + */ +static void +denormal_to_double (struct sh_fpu_hard_struct *fpu, int n) +{ + unsigned long du, dl; + unsigned long x = fpu->fpul; + int exp = 1023 - 126; + + if (x != 0 && (x & 0x7f800000) == 0) { + du = (x & 0x80000000); + while ((x & 0x00800000) == 0) { + x <<= 1; + exp--; + } + x &= 0x007fffff; + du |= (exp << 20) | (x >> 3); + dl = x << 29; + + fpu->fp_regs[n] = du; + fpu->fp_regs[n+1] = dl; + } +} + +/** + * ieee_fpe_handler - Handle denormalized number exception + * + * @regs: Pointer to register structure + * + * Returns 1 when it's handled (should not cause exception). + */ +static int +ieee_fpe_handler (struct pt_regs *regs) +{ + unsigned short insn = *(unsigned short *) regs->pc; + unsigned short finsn; + unsigned long nextpc; + int nib[4] = { + (insn >> 12) & 0xf, + (insn >> 8) & 0xf, + (insn >> 4) & 0xf, + insn & 0xf}; + + if (nib[0] == 0xb || + (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */ + regs->pr = regs->pc + 4; + + if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */ + nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3); + finsn = *(unsigned short *) (regs->pc + 2); + } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */ + if (regs->sr & 1) + nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); + else + nextpc = regs->pc + 4; + finsn = *(unsigned short *) (regs->pc + 2); + } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */ + if (regs->sr & 1) + nextpc = regs->pc + 4; + else + nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); + finsn = *(unsigned short *) (regs->pc + 2); + } else if (nib[0] == 0x4 && nib[3] == 0xb && + (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */ + nextpc = regs->regs[nib[1]]; + finsn = *(unsigned short *) (regs->pc + 2); + } else if (nib[0] == 0x0 && nib[3] == 0x3 && + (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */ + nextpc = regs->pc + 4 + regs->regs[nib[1]]; + finsn = *(unsigned short *) (regs->pc + 2); + } else if (insn == 0x000b) { /* rts */ + nextpc = regs->pr; + finsn = *(unsigned short *) (regs->pc + 2); + } else { + nextpc = regs->pc + 2; + finsn = insn; + } + + if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ + struct task_struct *tsk = current; + + save_fpu(tsk); + if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) { + /* FPU error */ + denormal_to_double (&tsk->thread.fpu.hard, + (finsn >> 8) & 0xf); + tsk->thread.fpu.hard.fpscr &= + ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); + grab_fpu(); + restore_fpu(tsk); + tsk->flags |= PF_USEDFPU; + } else { + tsk->thread.trap_no = 11; + tsk->thread.error_code = 0; + force_sig(SIGFPE, tsk); + } + + regs->pc = nextpc; + return 1; + } + + return 0; +} + asmlinkage void do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) { struct task_struct *tsk = current; - regs.pc += 2; + if (ieee_fpe_handler (®s)) + return; - grab_fpu(); + regs.pc += 2; save_fpu(tsk); tsk->thread.trap_no = 11; tsk->thread.error_code = 0; @@ -181,102 +296,12 @@ do_fpu_state_restore(unsigned long r4, u { struct task_struct *tsk = current; - if (!user_mode(®s)) { - if (tsk != &init_task) { - unlazy_fpu(tsk); - } - tsk = &init_task; - if (tsk->flags & PF_USEDFPU) { - /* - * This weird situation can be occurred. - * - * There's race condition in __cli: - * - * (1) SR --> register - * (2) Set IMASK of register - * (3) SR <-- register - * - * Between (1) and (2), or (2) and (3) getting - * interrupt, and interrupt handler (or - * softirq) may use FPU. - * - * Then, SR.FD is overwritten by (3). - * - * This results init_task.PF_USEDFPU is on, - * with SR.FD == 1. - * - */ - release_fpu(); - return; - } - } - grab_fpu(); - if (tsk->used_math) { - /* Using the FPU again. */ - restore_fpu(tsk); - } else { - /* First time FPU user. */ - fpu_init(); - tsk->used_math = 1; - } - tsk->flags |= PF_USEDFPU; - release_fpu(); -} - -/* - * Change current FD flag to set FD flag back to exception - */ -asmlinkage void -fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6, - unsigned long r7, struct pt_regs regs) -{ - __cli(); if (!user_mode(®s)) { - if (init_task.flags & PF_USEDFPU) - grab_fpu(); - else { - if (!(sr & SR_FD)) { - BUG(); - release_fpu(); - } - } + printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); return; } - if (sr & SR_FD) { /* Kernel doesn't grab FPU */ - if (current->flags & PF_USEDFPU) - grab_fpu(); - else { - if (init_task.flags & PF_USEDFPU) { - /* - * This weird situation can be occurred. - * See the comment in do_fpu_state_restore. - */ - grab_fpu(); - save_fpu(&init_task); - } - } - } else { - if (init_task.flags & PF_USEDFPU) - save_fpu(&init_task); - else { - BUG(); - release_fpu(); - } - } -} - -/* Short cut for the FPU exception */ -asmlinkage void -enable_fpu_in_danger(void) -{ - struct task_struct *tsk = current; - - if (tsk != &init_task) - unlazy_fpu(tsk); - - tsk = &init_task; if (tsk->used_math) { /* Using the FPU again. */ restore_fpu(tsk); diff -ruNp linux/arch/sh/kernel/head.S linux-2.5.2-pre10.superh/arch/sh/kernel/head.S --- linux/arch/sh/kernel/head.S Mon Jan 29 11:56:00 2001 +++ linux-2.5.2-pre10.superh/arch/sh/kernel/head.S Sat Dec 29 15:50:38 2001 @@ -50,12 +50,6 @@ ENTRY(_stext) sub r1, r0 ! ldc r0, r7_bank ! ... and init_task ! -#if defined(__SH4__) - ! Initialize fpu - mov.l 7f, r0 - jsr @r0 - nop -#endif ! Enable cache mov.l 6f, r0 jsr @r0 @@ -74,12 +68,9 @@ ENTRY(_stext) nop .balign 4 -1: .long 0x400000F0 ! MD=1, RB=0, BL=0, FD=0, IMASK=0xF +1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF 2: .long SYMBOL_NAME(stack) 3: .long SYMBOL_NAME(__bss_start) 4: .long SYMBOL_NAME(_end) 5: .long SYMBOL_NAME(start_kernel) 6: .long SYMBOL_NAME(cache_init) -#if defined(__SH4__) -7: .long SYMBOL_NAME(fpu_init) -#endif diff -ruNp linux/arch/sh/kernel/pci-sh7751.c linux-2.5.2-pre10.superh/arch/sh/kernel/pci-sh7751.c --- linux/arch/sh/kernel/pci-sh7751.c Mon Nov 5 02:31:58 2001 +++ linux-2.5.2-pre10.superh/arch/sh/kernel/pci-sh7751.c Tue Oct 16 05:44:49 2001 @@ -3,7 +3,7 @@ * * Dustin McIntire (du...@se...) * Derived from arch/i386/kernel/pci-*.c which bore the message: - * (c) 1999--2000 Martin Mares <mj...@uc...> + * (c) 1999--2000 Martin Mares <mj...@su...> * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. diff -ruNp linux/arch/sh/kernel/rtc.c linux-2.5.2-pre10.superh/arch/sh/kernel/rtc.c --- linux/arch/sh/kernel/rtc.c Thu Jun 28 05:55:29 2001 +++ linux-2.5.2-pre10.superh/arch/sh/kernel/rtc.c Wed Dec 12 19:14:20 2001 @@ -46,7 +46,7 @@ void sh_rtc_gettimeofday(struct timeval } while ((ctrl_inb(RCR1) & RCR1_CF) != 0); #if RTC_BIT_INVERTED != 0 - /* Work around to avoid reading correct value. */ + /* Work around to avoid reading incorrect value. */ if (sec128 == RTC_BIT_INVERTED) { schedule_timeout(1); goto again; @@ -81,12 +81,18 @@ void sh_rtc_gettimeofday(struct timeval goto again; } +#if RTC_BIT_INVERTED != 0 + if ((sec128 & RTC_BIT_INVERTED)) + sec--; +#endif + tv->tv_sec = mktime(yr100 * 100 + yr, mon, day, hr, min, sec); - tv->tv_usec = ((sec128 ^ RTC_BIT_INVERTED) * 1000000) / 128; + tv->tv_usec = (sec128 * 1000000) / 128; } -static int set_rtc_time(unsigned long nowtime) +int sh_rtc_settimeofday(const struct timeval *tv) { + unsigned long nowtime = tv->tv_sec; int retval = 0; int real_seconds, real_minutes, cmos_minutes; @@ -122,13 +128,4 @@ static int set_rtc_time(unsigned long no ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */ return retval; -} - -int sh_rtc_settimeofday(const struct timeval *tv) -{ -#if RTC_BIT_INVERTED != 0 - /* This is not accurate, but better than nothing. */ - schedule_timeout(HZ/2); -#endif - return set_rtc_time(tv->tv_sec); } diff -ruNp linux/arch/sh/kernel/traps.c linux-2.5.2-pre10.superh/arch/sh/kernel/traps.c --- linux/arch/sh/kernel/traps.c Tue Jan 8 11:22:54 2002 +++ linux-2.5.2-pre10.superh/arch/sh/kernel/traps.c Fri Dec 28 11:46:10 2001 @@ -300,10 +300,19 @@ static inline int handle_unaligned_delay /* * handle an instruction that does an unaligned memory access * - have to be careful of branch delay-slot instructions that fault + * SH3: * - if the branch would be taken PC points to the branch * - if the branch would not be taken, PC points to delay-slot + * SH4: + * - PC always points to delayed branch * - return 0 if handled, -EFAULT if failed (may not return if in kernel) */ + +/* Macros to determine offset from current PC for branch instructions */ +/* Explicit type coercion is used to force sign extension where needed */ +#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4) +#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) + static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) { u_int rm; @@ -392,15 +401,27 @@ static int handle_unaligned_access(u16 i break; case 0x0F00: /* bf/s lab */ ret = handle_unaligned_delayslot(regs); - if (ret==0) - regs->pc += (instruction&0x00FF)*2 + 4; + if (ret==0) { +#if defined(__SH4__) + if ((regs->sr & 0x00000001) != 0) + regs->pc += 4; /* next after slot */ + else +#endif + regs->pc += SH_PC_8BIT_OFFSET(instruction); + } break; case 0x0900: /* bt lab - no delayslot */ break; case 0x0D00: /* bt/s lab */ ret = handle_unaligned_delayslot(regs); - if (ret==0) - regs->pc += (instruction&0x00FF)*2 + 4; + if (ret==0) { +#if defined(__SH4__) + if ((regs->sr & 0x00000001) == 0) + regs->pc += 4; /* next after slot */ + else +#endif + regs->pc += SH_PC_8BIT_OFFSET(instruction); + } break; } break; @@ -408,14 +429,14 @@ static int handle_unaligned_access(u16 i case 0xA000: /* bra label */ ret = handle_unaligned_delayslot(regs); if (ret==0) - regs->pc += (instruction&0x0FFF)*2 + 4; + regs->pc += SH_PC_12BIT_OFFSET(instruction); break; case 0xB000: /* bsr label */ ret = handle_unaligned_delayslot(regs); if (ret==0) { regs->pr = regs->pc + 4; - regs->pc += (instruction&0x0FFF)*2 + 4; + regs->pc += SH_PC_12BIT_OFFSET(instruction); } break; } diff -ruNp linux/arch/sh/mm/fault.c linux-2.5.2-pre10.superh/arch/sh/mm/fault.c --- linux/arch/sh/mm/fault.c Tue Oct 16 05:36:48 2001 +++ linux-2.5.2-pre10.superh/arch/sh/mm/fault.c Fri Dec 28 11:46:10 2001 @@ -207,8 +207,7 @@ no_context: out_of_memory: up_read(&mm->mmap_sem); if (current->pid == 1) { - current->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } @@ -248,6 +247,8 @@ asmlinkage int __do_page_fault(struct pt if (address >= P3SEG && address < P4SEG) dir = pgd_offset_k(address); else if (address >= TASK_SIZE) + return 1; + else if (!current->mm) return 1; else dir = pgd_offset(current->mm, address); diff -ruNp linux/drivers/char/shwdt.c linux-2.5.2-pre10.superh/drivers/char/shwdt.c --- linux/drivers/char/shwdt.c Tue Jan 8 12:24:45 2002 +++ linux-2.5.2-pre10.superh/drivers/char/shwdt.c Tue Jan 8 13:13:00 2002 @@ -19,7 +19,6 @@ #include <linux/watchdog.h> #include <linux/reboot.h> #include <linux/notifier.h> -#include <linux/smp_lock.h> #include <linux/ioport.h> #include <asm/io.h> @@ -47,18 +46,47 @@ #define WTCSR_CKS1 0x02 #define WTCSR_CKS0 0x01 -#define WTCSR_CKS 0x07 -#define WTCSR_CKS_1 0x00 -#define WTCSR_CKS_4 0x01 -#define WTCSR_CKS_16 0x02 -#define WTCSR_CKS_32 0x03 -#define WTCSR_CKS_64 0x04 -#define WTCSR_CKS_256 0x05 -#define WTCSR_CKS_1024 0x06 +/* + * CKS0-2 supports a number of clock division ratios. At the time the watchdog + * is enabled, it defaults to a 41 usec overflow period .. we overload this to + * something a little more reasonable, and really can't deal with anything + * lower than WTCSR_CKS_1024, else we drop back into the usec range. + * + * Clock Division Ratio Overflow Period + * -------------------------------------------- + * 1/32 (initial value) 41 usecs + * 1/64 82 usecs + * 1/128 164 usecs + * 1/256 328 usecs + * 1/512 656 usecs + * 1/1024 1.31 msecs + * 1/2048 2.62 msecs + * 1/4096 5.25 msecs + */ +#define WTCSR_CKS_32 0x00 +#define WTCSR_CKS_64 0x01 +#define WTCSR_CKS_128 0x02 +#define WTCSR_CKS_256 0x03 +#define WTCSR_CKS_512 0x04 +#define WTCSR_CKS_1024 0x05 +#define WTCSR_CKS_2048 0x06 #define WTCSR_CKS_4096 0x07 -static int sh_is_open = 0; +/* + * Default clock division ratio is 5.25 msecs. Overload this at module load + * time. Any value not in the msec range will default to a timeout of one + * jiffy, which exceeds the usec overflow periods. + */ +static int clock_division_ratio = WTCSR_CKS_4096; + +#define msecs_to_jiffies(msecs) (jiffies + ((HZ * msecs + 999) / 1000)) +#define next_ping_period(cks) msecs_to_jiffies(cks - 4) +#define user_ping_period(cks) (next_ping_period(cks) * 10) + +static unsigned long sh_is_open = 0; static struct watchdog_info sh_wdt_info; +static struct timer_list timer; +static unsigned long next_heartbeat; /** * sh_wdt_write_cnt - Write to Counter @@ -93,6 +121,10 @@ static void sh_wdt_write_csr(__u8 val) */ static void sh_wdt_start(void) { + timer.expires = next_ping_period(clock_division_ratio); + next_heartbeat = user_ping_period(clock_division_ratio); + add_timer(&timer); + sh_wdt_write_csr(WTCSR_WT | WTCSR_CKS_4096); sh_wdt_write_cnt(0); sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME)); @@ -105,6 +137,8 @@ static void sh_wdt_start(void) */ static void sh_wdt_stop(void) { + del_timer(&timer); + sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME)); } @@ -117,8 +151,13 @@ static void sh_wdt_stop(void) */ static void sh_wdt_ping(unsigned long data) { - sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF)); - sh_wdt_write_cnt(0); + if (time_before(jiffies, next_heartbeat)) { + sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF)); + sh_wdt_write_cnt(0); + + timer.expires = next_ping_period(clock_division_ratio); + add_timer(&timer); + } } /** @@ -133,14 +172,12 @@ static int sh_wdt_open(struct inode *ino { switch (minor(inode->i_rdev)) { case WATCHDOG_MINOR: - if (sh_is_open) { + if (test_and_set_bit(0, &sh_is_open)) return -EBUSY; - } - sh_is_open = 1; sh_wdt_start(); - return 0; + break; default: return -ENODEV; } @@ -158,17 +195,13 @@ static int sh_wdt_open(struct inode *ino */ static int sh_wdt_close(struct inode *inode, struct file *file) { - lock_kernel(); - if (minor(inode->i_rdev) == WATCHDOG_MINOR) { #ifndef CONFIG_WATCHDOG_NOWAYOUT sh_wdt_stop(); #endif - sh_is_open = 0; + clear_bit(0, &sh_is_open); } - unlock_kernel(); - return 0; } @@ -206,7 +239,7 @@ static ssize_t sh_wdt_write(struct file return -ESPIPE; if (count) { - sh_wdt_ping(0); + next_heartbeat = user_ping_period(clock_division_ratio); return 1; } @@ -245,7 +278,7 @@ static int sh_wdt_ioctl(struct inode *in break; case WDIOC_KEEPALIVE: - sh_wdt_ping(0); + next_heartbeat = user_ping_period(clock_division_ratio); break; default: @@ -336,6 +369,10 @@ static int __init sh_wdt_init(void) return -EINVAL; } + init_timer(&timer); + timer.function = sh_wdt_ping; + timer.data = 0; + return 0; } @@ -358,6 +395,8 @@ EXPORT_NO_SYMBOLS; MODULE_AUTHOR("Paul Mundt <le...@ch...>"); MODULE_DESCRIPTION("SH 3/4 watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_PARM(clock_division_ratio, "i"); +MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7."); module_init(sh_wdt_init); module_exit(sh_wdt_exit); diff -ruNp linux/include/asm-sh/pgtable.h linux-2.5.2-pre10.superh/include/asm-sh/pgtable.h --- linux/include/asm-sh/pgtable.h Mon Nov 12 03:20:21 2001 +++ linux-2.5.2-pre10.superh/include/asm-sh/pgtable.h Thu Dec 20 10:38:10 2001 @@ -237,6 +237,19 @@ static inline pte_t pte_mkyoung(pte_t pt static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; } /* + * Macro and implementation to make a page protection as uncachable. + */ +#define pgprot_noncached pgprot_noncached + +static inline pgprot_t pgprot_noncached(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + + prot &= ~_PAGE_CACHABLE; + return __pgprot(prot); +} + +/* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. * diff -ruNp linux/include/asm-sh/processor.h linux-2.5.2-pre10.superh/include/asm-sh/processor.h --- linux/include/asm-sh/processor.h Sat Oct 6 04:11:05 2001 +++ linux-2.5.2-pre10.superh/include/asm-sh/processor.h Fri Dec 28 11:37:29 2001 @@ -184,18 +184,22 @@ extern void save_fpu(struct task_struct #define unlazy_fpu(tsk) do { \ if ((tsk)->flags & PF_USEDFPU) { \ - grab_fpu(); \ save_fpu(tsk); \ } \ } while (0) #define clear_fpu(tsk) do { \ - if ((tsk)->flags & PF_USEDFPU) \ + if ((tsk)->flags & PF_USEDFPU) { \ (tsk)->flags &= ~PF_USEDFPU; \ + release_fpu(); \ + } \ } while (0) /* Double presision, NANS as NANS, rounding to nearest, no exceptions */ #define FPSCR_INIT 0x00080000 + +#define FPSCR_CAUSE_MASK 0x0001f000 /* Cause bits */ +#define FPSCR_FLAG_MASK 0x0000007c /* Flag bits */ /* * Return saved PC of a blocked thread. diff -ruNp linux/include/asm-sh/scatterlist.h linux-2.5.2-pre10.superh/include/asm-sh/scatterlist.h --- linux/include/asm-sh/scatterlist.h Sat Oct 13 07:35:54 2001 +++ linux-2.5.2-pre10.superh/include/asm-sh/scatterlist.h Sat Jan 5 16:29:31 2002 @@ -2,7 +2,11 @@ #define __ASM_SH_SCATTERLIST_H struct scatterlist { - char * address; /* Location data is to be transferred to */ + char * address; /* Location data is to be transferred to, NULL for + * highmem page */ + struct page * page; /* Location for highmem page, if any */ + unsigned int offset;/* for highmem, page offset */ + dma_addr_t dma_address; unsigned int length; }; -- |
From: David W. <dw...@in...> - 2002-01-08 06:51:40
|
gn...@m1... said: > Here's the changes against linux-2.5.2-pre10, I'm about to send to > Linus. You ought to be able to remove asm-sh/segment.h now too. -- dwmw2 |
From: NIIBE Y. <gn...@m1...> - 2002-01-08 07:01:58
|
David Woodhouse wrote: > You ought to be able to remove asm-sh/segment.h now too. Thanks for your effort. Will do for our repository. Here's another turn. Changes from mainline. 2002-01-08 NIIBE Yutaka <gn...@m1...> Updated to 2.5.2-pre10. * Makefile, Documentation/Configure.help, arch/sh/kernel/process.c, arch/sh/kernel/setup.c, drivers/block/rd.c, drivers/char/sh-sci.c, drivers/char/shwdt.c, init/do_mounts.c, init/main.c, kernel/ptrace.c, mm/memory.c: Include changes from mainline (2.5.2-pre10). * drivers/cdrom/gdrom.c (DEVICE_NR): MINOR -> minor. (gdrom_init): MKDEV -> mk_kdev. * arch/sh/mm/fault.c (do_page_fault): Use yield. * include/asm-sh/mmu_context.h (sched_find_first_zero_bit): Implemented. (Just copied from x86 implementation.) * arch/sh/kernel/setup.c (sh_console_device): Returns /dev/null. * arch/sh/kernel/irq.c: Include <linux/mm.h>. * arch/sh/kernel/process.c: Include <linux/mm.h>. (cpu_idle): Don't call init_idle here. Remove setting of ->nice. Index: Makefile =================================================================== RCS file: /cvsroot/linuxsh/linux/Makefile,v retrieving revision 1.3 diff -u -3 -p -r1.3 Makefile --- Makefile 2002/01/07 03:57:47 1.3 +++ Makefile 2002/01/08 06:57:46 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 1 -EXTRAVERSION = +SUBLEVEL = 2 +EXTRAVERSION =-pre10 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) Index: Documentation/Configure.help =================================================================== RCS file: /cvsroot/linuxsh/linux/Documentation/Configure.help,v retrieving revision 1.3 diff -u -3 -p -r1.3 Configure.help --- Documentation/Configure.help 2002/01/07 03:57:47 1.3 +++ Documentation/Configure.help 2002/01/08 06:57:48 @@ -12541,6 +12541,30 @@ CONFIG_USB_LONG_TIMEOUT If you have an MGE Ellipse UPS, or you see timeouts in HID transactions, say Y; otherwise say N. +EHCI (USB 2.0) support +CONFIG_USB_EHCI_HCD + The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 + "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. + If your USB host controller supports USB 2.0, you will likely want to + configure this Host Controller Driver. At this writing, the primary + implementation of EHCI is a chip from NEC, widely available in add-on + PCI cards, but implementations are in the works from other vendors + including Intel and Philips. Motherboard support is appearing. + + EHCI controllers are packaged with "companion" host controllers (OHCI + or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports + will connect to EHCI if it the device is high speed, otherwise they + connect to a companion controller. If you configure EHCI, you should + probably configure the OHCI (for NEC and some other vendors) USB Host + Controller Driver too. + + You may want to read <file:Documentation/usb/ehci.txt>. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called ehci-hcd.o. If you want to compile it as a + module, say M here and read <file:Documentation/modules.txt>. + UHCI (Intel PIIX4, VIA, ...) support CONFIG_USB_UHCI The Universal Host Controller Interface is a standard by Intel for @@ -12841,6 +12865,17 @@ CONFIG_USB_SERIAL_VISOR The module will be called visor.o. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. +USB Compaq iPAQ Driver +CONFIG_USB_SERIAL_IPAQ + Say Y here if you want to connect to your Compaq iPAQ running + Windows CE 3.0 using a USB autosync cable. For information on using + the driver, read <file:Documentation/usb/usb-serial.txt>. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called ipaq.o. If you want to compile it as a + module, say M here and read <file:Documentation/modules.txt>. + USB IR Dongle Serial Driver CONFIG_USB_SERIAL_IR Say Y here if you want to enable simple serial support for USB IrDA @@ -13061,6 +13096,22 @@ CONFIG_USB_SERIAL_EDGEPORT The module will be called io_edgeport.o. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. +USB PalmConnect (and other KL5KUSB105-based) Single Port Serial Driver +CONFIG_USB_SERIAL_KLSI + Say Y here if you want to use a KL5KUSB105 - based single port + serial adapter. The most widely known -- and currently the only + tested -- device in this category is the PalmConnect USB Serial + adapter sold by Palm Inc. for use with their Palm III and Palm V + series PDAs. + + Please read <file:Documentation/usb/usb-serial.txt> for more + information. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called kl5kusb105.o. If you want to compile it as + a module, say M here and read <file:Documentation/modules.txt>. + USB Serial Converter verbose debug CONFIG_USB_SERIAL_DEBUG Say Y here if you want verbose debug messages from the USB Serial @@ -13167,6 +13218,54 @@ CONFIG_USB_PWC The module will be called pwc.o. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. +USB SE401 Camera support +CONFIG_USB_SE401 + Say Y here if you want to connect this type of camera to your + computer's USB port. See <file:Documentation/usb/se401.txt> for more + information and for a list of supported cameras. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Multimedia Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called se401.o. If you want to compile it as a + module, say M here and read <file:Documentation/modules.txt>. + +USB STV680 (Pencam) Camera support +CONFIG_USB_STV680 + Say Y here if you want to connect this type of camera to your + computer's USB port. This includes the Pencam line of cameras. + See <file:Documentation/usb/stv680.txt> for more information and for + a list of supported cameras. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Multimedia Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called stv680.o. If you want to compile it as a + module, say M here and read <file:Documentation/modules.txt>. + +Vicam +CONFIG_USB_VICAM + Say Y here if you have 3com homeconnect camera (vicam). + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Multimedia Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called vicam.o. If you want to compile it as a + module, say M here and read <file:Documentation/modules.txt>. + + Pegasus/Pegasus II based USB-Ethernet device support CONFIG_USB_PEGASUS Say Y here if you know you have Pegasus or Pegasus II based adapter. @@ -13415,6 +13514,16 @@ CONFIG_USB_RIO500 The module will be called rio500.o. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. +USB Auerswald ISDN device support +CONFIG_USB_AUERSWALD + Say Y here if you want to connect an Auerswald USB ISDN Device + to your computer's USB port. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called auerswald.o. If you want to compile it as + a module, say M here and read <file:Documentation/modules.txt>. + D-Link DSB-R100 FM radio support CONFIG_USB_DSBR Say Y here if you want to connect this type of radio to your @@ -16960,22 +17069,6 @@ CONFIG_PM Note that, even if you say N here, Linux on the x86 architecture will issue the hlt instruction if nothing is to be done, thereby sending the processor to sleep and saving power. - -USB SE401 Camera support -CONFIG_USB_SE401 - Say Y here if you want to connect this type of camera to your - computer's USB port. See <file:Documentation/usb/se401.txt> for more - information and for a list of supported cameras. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Multimedia Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>. - - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called se401.o. If you want to compile it as a - module, say M here and read <file:Documentation/modules.txt>. ACPI support CONFIG_ACPI Index: arch/sh/kernel/irq.c =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/kernel/irq.c,v retrieving revision 1.2 diff -u -3 -p -r1.2 irq.c --- arch/sh/kernel/irq.c 2002/01/07 03:57:48 1.2 +++ arch/sh/kernel/irq.c 2002/01/08 06:57:48 @@ -22,6 +22,7 @@ #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/timex.h> +#include <linux/mm.h> #include <linux/slab.h> #include <linux/random.h> #include <linux/smp.h> Index: arch/sh/kernel/process.c =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/kernel/process.c,v retrieving revision 1.1.1.1 diff -u -3 -p -r1.1.1.1 process.c --- arch/sh/kernel/process.c 2001/10/15 20:44:51 1.1.1.1 +++ arch/sh/kernel/process.c 2002/01/08 06:57:48 @@ -12,6 +12,7 @@ */ #include <linux/unistd.h> +#include <linux/mm.h> #include <linux/slab.h> #include <asm/io.h> @@ -39,10 +40,6 @@ void enable_hlt(void) void cpu_idle(void *unused) { /* endless idle loop with no priority at all */ - init_idle(); - current->nice = 20; - current->counter = -100; - while (1) { if (hlt_counter) { if (current->need_resched) Index: arch/sh/kernel/setup.c =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/kernel/setup.c,v retrieving revision 1.2 diff -u -3 -p -r1.2 setup.c --- arch/sh/kernel/setup.c 2001/12/03 22:15:34 1.2 +++ arch/sh/kernel/setup.c 2002/01/08 06:57:48 @@ -140,20 +140,10 @@ static void sh_console_write(struct cons sh_bios_console_write(s, count); } -/* - * Receive character from the serial port - */ -static int sh_console_wait_key(struct console *co) -{ - /* Not implemented yet */ - return 0; -} - static kdev_t sh_console_device(struct console *c) { - /* TODO: this is totally bogus */ - /* return MKDEV(SCI_MAJOR, SCI_MINOR_START + c->index); */ - return 0; + /* /dev/null */ + return mk_kdev(MEM_MAJOR, 3); } /* @@ -183,7 +173,6 @@ static struct console sh_console = { name: "bios", write: sh_console_write, device: sh_console_device, - wait_key: sh_console_wait_key, setup: sh_console_setup, flags: CON_PRINTBUFFER, index: -1, Index: arch/sh/mm/fault.c =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/mm/fault.c,v retrieving revision 1.2 diff -u -3 -p -r1.2 fault.c --- arch/sh/mm/fault.c 2001/12/26 19:30:07 1.2 +++ arch/sh/mm/fault.c 2002/01/08 06:57:48 @@ -207,8 +207,7 @@ no_context: out_of_memory: up_read(&mm->mmap_sem); if (current->pid == 1) { - current->policy |= SCHED_YIELD; - schedule(); + yield(); down_read(&mm->mmap_sem); goto survive; } Index: drivers/block/rd.c =================================================================== RCS file: /cvsroot/linuxsh/linux/drivers/block/rd.c,v retrieving revision 1.3 diff -u -3 -p -r1.3 rd.c --- drivers/block/rd.c 2001/12/17 07:25:45 1.3 +++ drivers/block/rd.c 2002/01/08 06:57:49 @@ -43,29 +43,12 @@ */ #include <linux/config.h> -#include <linux/sched.h> -#include <linux/minix_fs.h> -#include <linux/ext2_fs.h> -#include <linux/romfs_fs.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/hdreg.h> #include <linux/string.h> -#include <linux/mm.h> -#include <linux/mman.h> #include <linux/slab.h> -#include <linux/ioctl.h> -#include <linux/fd.h> #include <linux/module.h> #include <linux/init.h> #include <linux/devfs_fs_kernel.h> -#include <linux/smp_lock.h> - -#include <asm/system.h> #include <asm/uaccess.h> -#include <asm/byteorder.h> - -extern void wait_for_keypress(void); /* * 35 has been officially registered as the RAMDISK major number, but @@ -79,17 +62,11 @@ extern void wait_for_keypress(void); /* The RAM disk size is now a parameter */ #define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */ -#ifndef MODULE -/* We don't have to load RAM disks or gunzip them in a module. */ -#define RD_LOADER -#define BUILD_CRAMDISK - -void rd_load(void); -static int crd_load(struct file *fp, struct file *outfp); - #ifdef CONFIG_BLK_DEV_INITRD static int initrd_users; -#endif +static spinlock_t initrd_users_lock = SPIN_LOCK_UNLOCKED; +unsigned long initrd_start, initrd_end; +int initrd_below_start_ok; #endif /* Various static variables go here. Most are used only in the RAM disk code. @@ -98,7 +75,7 @@ static int initrd_users; static unsigned long rd_length[NUM_RAMDISKS]; /* Size of RAM disks in bytes */ static int rd_hardsec[NUM_RAMDISKS]; /* Size of real blocks in bytes */ static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :) */ -static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */ +static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */ static devfs_handle_t devfs_handle; static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */ @@ -122,70 +99,6 @@ int rd_size = CONFIG_BLK_DEV_RAM_SIZE; */ int rd_blocksize = BLOCK_SIZE; /* blocksize of the RAM disks */ -#ifndef MODULE - -int rd_doload; /* 1 = load RAM disk, 0 = don't load */ -int rd_prompt = 1; /* 1 = prompt for RAM disk, 0 = don't prompt */ -int rd_image_start; /* starting block # of image */ -#ifdef CONFIG_BLK_DEV_INITRD -unsigned long initrd_start, initrd_end; -int mount_initrd = 1; /* zero if initrd should not be mounted */ -int initrd_below_start_ok; - -static int __init no_initrd(char *str) -{ - mount_initrd = 0; - return 1; -} - -__setup("noinitrd", no_initrd); - -#endif - -static int __init ramdisk_start_setup(char *str) -{ - rd_image_start = simple_strtol(str,NULL,0); - return 1; -} - -static int __init load_ramdisk(char *str) -{ - rd_doload = simple_strtol(str,NULL,0) & 3; - return 1; -} - -static int __init prompt_ramdisk(char *str) -{ - rd_prompt = simple_strtol(str,NULL,0) & 1; - return 1; -} - -static int __init ramdisk_size(char *str) -{ - rd_size = simple_strtol(str,NULL,0); - return 1; -} - -static int __init ramdisk_size2(char *str) -{ - return ramdisk_size(str); -} - -static int __init ramdisk_blocksize(char *str) -{ - rd_blocksize = simple_strtol(str,NULL,0); - return 1; -} - -__setup("ramdisk_start=", ramdisk_start_setup); -__setup("load_ramdisk=", load_ramdisk); -__setup("prompt_ramdisk=", prompt_ramdisk); -__setup("ramdisk=", ramdisk_size); -__setup("ramdisk_size=", ramdisk_size2); -__setup("ramdisk_blocksize=", ramdisk_blocksize); - -#endif - /* * Copyright (C) 2000 Linus Torvalds. * 2000 Transmeta Corp. @@ -227,19 +140,19 @@ static struct address_space_operations r commit_write: ramdisk_commit_write, }; -static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor) +static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, + sector_t sector, int minor) { struct address_space * mapping; unsigned long index; int offset, size, err; - err = -EIO; err = 0; mapping = rd_bdev[minor]->bd_inode->i_mapping; - index = sbh->b_rsector >> (PAGE_CACHE_SHIFT - 9); - offset = (sbh->b_rsector << 9) & ~PAGE_CACHE_MASK; - size = sbh->b_size; + index = sector >> (PAGE_CACHE_SHIFT - 9); + offset = (sector << 9) & ~PAGE_CACHE_MASK; + size = vec->bv_len; do { int count; @@ -276,18 +189,18 @@ static int rd_blkdev_pagecache_IO(int rw if (rw == READ) { src = kmap(page); src += offset; - dst = bh_kmap(sbh); + dst = kmap(vec->bv_page) + vec->bv_offset; } else { dst = kmap(page); dst += offset; - src = bh_kmap(sbh); + src = kmap(vec->bv_page) + vec->bv_offset; } offset = 0; memcpy(dst, src, count); kunmap(page); - bh_kunmap(sbh); + kunmap(vec->bv_page); if (rw == READ) { flush_dcache_page(page); @@ -303,6 +216,22 @@ static int rd_blkdev_pagecache_IO(int rw return err; } +static int rd_blkdev_bio_IO(struct bio *bio, unsigned int minor) +{ + struct bio_vec *bvec; + sector_t sector; + int ret = 0, i, rw; + + sector = bio->bi_sector; + rw = bio_data_dir(bio); + bio_for_each_segment(bvec, bio, i) { + ret |= rd_blkdev_pagecache_IO(rw, bvec, sector, minor); + sector += bvec->bv_len >> 9; + } + + return ret; +} + /* * Basically, my strategy here is to set up a buffer-head which can't be * deleted, and make that my Ramdisk. If the request is outside of the @@ -311,19 +240,19 @@ static int rd_blkdev_pagecache_IO(int rw * 19-JAN-1998 Richard Gooch <rg...@at...> Added devfs support * */ -static int rd_make_request(request_queue_t * q, int rw, struct buffer_head *sbh) +static int rd_make_request(request_queue_t * q, struct bio *sbh) { unsigned int minor; unsigned long offset, len; + int rw = sbh->bi_rw; - minor = MINOR(sbh->b_rdev); + minor = minor(sbh->bi_dev); if (minor >= NUM_RAMDISKS) goto fail; - - offset = sbh->b_rsector << 9; - len = sbh->b_size; + offset = sbh->bi_sector << 9; + len = sbh->bi_size; if ((offset + len) > rd_length[minor]) goto fail; @@ -335,13 +264,14 @@ static int rd_make_request(request_queue goto fail; } - if (rd_blkdev_pagecache_IO(rw, sbh, minor)) + if (rd_blkdev_bio_IO(sbh, minor)) goto fail; - sbh->b_end_io(sbh,1); + set_bit(BIO_UPTODATE, &sbh->bi_flags); + sbh->bi_end_io(sbh, len >> 9); return 0; fail: - sbh->b_end_io(sbh,0); + bio_io_error(sbh); return 0; } @@ -350,10 +280,10 @@ static int rd_ioctl(struct inode *inode, int error = -EINVAL; unsigned int minor; - if (!inode || !inode->i_rdev) + if (!inode || kdev_none(inode->i_rdev)) goto out; - minor = MINOR(inode->i_rdev); + minor = minor(inode->i_rdev); switch (cmd) { case BLKFLSBUF: @@ -408,12 +338,15 @@ static int initrd_release(struct inode * { extern void free_initrd_mem(unsigned long, unsigned long); - lock_kernel(); + spin_lock(&initrd_users_lock); if (!--initrd_users) { + spin_unlock(&initrd_users_lock); free_initrd_mem(initrd_start, initrd_end); initrd_start = 0; + } else { + spin_unlock(&initrd_users_lock); } - unlock_kernel(); + blkdev_put(inode->i_bdev, BDEV_FILE); return 0; } @@ -433,8 +366,11 @@ static int rd_open(struct inode * inode, #ifdef CONFIG_BLK_DEV_INITRD if (unit == INITRD_MINOR) { - if (!initrd_start) return -ENODEV; + spin_lock(&initrd_users_lock); initrd_users++; + spin_unlock(&initrd_users_lock); + if (!initrd_start) + return -ENODEV; filp->f_op = &initrd_fops; return 0; } @@ -461,7 +397,6 @@ static struct block_device_operations rd ioctl: rd_ioctl, }; -#ifdef MODULE /* Before freeing the module, invalidate all of the protected buffers! */ static void __exit rd_cleanup (void) { @@ -472,19 +407,16 @@ static void __exit rd_cleanup (void) rd_bdev[i] = NULL; if (bdev) blkdev_put(bdev, BDEV_FILE); - destroy_buffers(MKDEV(MAJOR_NR, i)); + destroy_buffers(mk_kdev(MAJOR_NR, i)); } devfs_unregister (devfs_handle); unregister_blkdev( MAJOR_NR, "ramdisk" ); - hardsect_size[MAJOR_NR] = NULL; - blksize_size[MAJOR_NR] = NULL; - blk_size[MAJOR_NR] = NULL; + blk_clear(MAJOR_NR); } -#endif /* This is the registration and initialization section of the RAM disk driver */ -int __init rd_init (void) +static int __init rd_init (void) { int i; @@ -517,14 +449,15 @@ int __init rd_init (void) &rd_bd_op, NULL); for (i = 0; i < NUM_RAMDISKS; i++) - register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1); + register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1); #ifdef CONFIG_BLK_DEV_INITRD /* We ought to separate initrd operations here */ - register_disk(NULL, MKDEV(MAJOR_NR,INITRD_MINOR), 1, &rd_bd_op, rd_size<<1); + register_disk(NULL, mk_kdev(MAJOR_NR,INITRD_MINOR), 1, &rd_bd_op, rd_size<<1); + devfs_register(devfs_handle, "initrd", DEVFS_FL_DEFAULT, MAJOR_NR, + INITRD_MINOR, S_IFBLK | S_IRUSR, &rd_bd_op, NULL); #endif - hardsect_size[MAJOR_NR] = rd_hardsec; /* Size of the RAM disk blocks */ blksize_size[MAJOR_NR] = rd_blocksizes; /* Avoid set_blocksize() check */ blk_size[MAJOR_NR] = rd_kbsize; /* Size of the RAM disk in kB */ @@ -536,474 +469,34 @@ int __init rd_init (void) return 0; } -#ifdef MODULE module_init(rd_init); module_exit(rd_cleanup); -#endif - -/* loadable module support */ -MODULE_PARM (rd_size, "1i"); -MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes."); -MODULE_PARM (rd_blocksize, "i"); -MODULE_PARM_DESC(rd_blocksize, "Blocksize of each RAM disk in bytes."); - -MODULE_LICENSE("GPL"); - -/* End of non-loading portions of the RAM disk driver */ - -#ifdef RD_LOADER -/* - * This routine tries to find a RAM disk image to load, and returns the - * number of blocks to read for a non-compressed image, 0 if the image - * is a compressed image, and -1 if an image with the right magic - * numbers could not be found. - * - * We currently check for the following magic numbers: - * minix - * ext2 - * romfs - * gzip - */ -static int __init -identify_ramdisk_image(kdev_t device, struct file *fp, int start_block) -{ - const int size = 512; - struct minix_super_block *minixsb; - struct ext2_super_block *ext2sb; - struct romfs_super_block *romfsb; - int nblocks = -1; - unsigned char *buf; - - buf = kmalloc(size, GFP_KERNEL); - if (buf == 0) - return -1; - - minixsb = (struct minix_super_block *) buf; - ext2sb = (struct ext2_super_block *) buf; - romfsb = (struct romfs_super_block *) buf; - memset(buf, 0xe5, size); - - /* - * Read block 0 to test for gzipped kernel - */ - if (fp->f_op->llseek) - fp->f_op->llseek(fp, start_block * BLOCK_SIZE, 0); - fp->f_pos = start_block * BLOCK_SIZE; - - fp->f_op->read(fp, buf, size, &fp->f_pos); - - /* - * If it matches the gzip magic numbers, return -1 - */ - if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) { - printk(KERN_NOTICE - "RAMDISK: Compressed image found at block %d\n", - start_block); - nblocks = 0; - goto done; - } - - /* romfs is at block zero too */ - if (romfsb->word0 == ROMSB_WORD0 && - romfsb->word1 == ROMSB_WORD1) { - printk(KERN_NOTICE - "RAMDISK: romfs filesystem found at block %d\n", - start_block); - nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; - goto done; - } - - /* - * Read block 1 to test for minix and ext2 superblock - */ - if (fp->f_op->llseek) - fp->f_op->llseek(fp, (start_block+1) * BLOCK_SIZE, 0); - fp->f_pos = (start_block+1) * BLOCK_SIZE; - - fp->f_op->read(fp, buf, size, &fp->f_pos); - - /* Try minix */ - if (minixsb->s_magic == MINIX_SUPER_MAGIC || - minixsb->s_magic == MINIX_SUPER_MAGIC2) { - printk(KERN_NOTICE - "RAMDISK: Minix filesystem found at block %d\n", - start_block); - nblocks = minixsb->s_nzones << minixsb->s_log_zone_size; - goto done; - } - - /* Try ext2 */ - if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) { - printk(KERN_NOTICE - "RAMDISK: ext2 filesystem found at block %d\n", - start_block); - nblocks = le32_to_cpu(ext2sb->s_blocks_count); - goto done; - } - - printk(KERN_NOTICE - "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", - start_block); - -done: - if (fp->f_op->llseek) - fp->f_op->llseek(fp, start_block * BLOCK_SIZE, 0); - fp->f_pos = start_block * BLOCK_SIZE; - - kfree(buf); - return nblocks; -} -/* - * This routine loads in the RAM disk image. - */ -static void __init rd_load_image(kdev_t device, int offset, int unit) -{ - struct inode *inode, *out_inode; - struct file infile, outfile; - struct dentry in_dentry, out_dentry; - mm_segment_t fs; - kdev_t ram_device; - int nblocks, i; - char *buf; - unsigned short rotate = 0; - unsigned short devblocks = 0; -#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES) - char rotator[4] = { '|' , '/' , '-' , '\\' }; -#endif - ram_device = MKDEV(MAJOR_NR, unit); - - if ((inode = get_empty_inode()) == NULL) - return; - memset(&infile, 0, sizeof(infile)); - memset(&in_dentry, 0, sizeof(in_dentry)); - infile.f_mode = 1; /* read only */ - infile.f_dentry = &in_dentry; - in_dentry.d_inode = inode; - infile.f_op = &def_blk_fops; - init_special_inode(inode, S_IFBLK | S_IRUSR, kdev_t_to_nr(device)); - - if ((out_inode = get_empty_inode()) == NULL) - goto free_inode; - memset(&outfile, 0, sizeof(outfile)); - memset(&out_dentry, 0, sizeof(out_dentry)); - outfile.f_mode = 3; /* read/write */ - outfile.f_dentry = &out_dentry; - out_dentry.d_inode = out_inode; - outfile.f_op = &def_blk_fops; - init_special_inode(out_inode, S_IFBLK | S_IRUSR | S_IWUSR, kdev_t_to_nr(ram_device)); - - if (blkdev_open(inode, &infile) != 0) { - iput(out_inode); - goto free_inode; - } - if (blkdev_open(out_inode, &outfile) != 0) - goto free_inodes; - - fs = get_fs(); - set_fs(KERNEL_DS); - - nblocks = identify_ramdisk_image(device, &infile, offset); - if (nblocks < 0) - goto done; - - if (nblocks == 0) { -#ifdef BUILD_CRAMDISK - if (crd_load(&infile, &outfile) == 0) - goto successful_load; -#else - printk(KERN_NOTICE - "RAMDISK: Kernel does not support compressed " - "RAM disk images\n"); -#endif - goto done; - } - - /* - * NOTE NOTE: nblocks suppose that the blocksize is BLOCK_SIZE, so - * rd_load_image will work only with filesystem BLOCK_SIZE wide! - * So make sure to use 1k blocksize while generating ext2fs - * ramdisk-images. - */ - if (nblocks > (rd_length[unit] >> BLOCK_SIZE_BITS)) { - printk("RAMDISK: image too big! (%d/%ld blocks)\n", - nblocks, rd_length[unit] >> BLOCK_SIZE_BITS); - goto done; - } - - /* - * OK, time to copy in the data - */ - buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); - if (buf == 0) { - printk(KERN_ERR "RAMDISK: could not allocate buffer\n"); - goto done; - } - - if (blk_size[MAJOR(device)]) - devblocks = blk_size[MAJOR(device)][MINOR(device)]; - -#ifdef CONFIG_BLK_DEV_INITRD - if (MAJOR(device) == MAJOR_NR && MINOR(device) == INITRD_MINOR) - devblocks = nblocks; -#endif - - if (devblocks == 0) { - printk(KERN_ERR "RAMDISK: could not determine device size\n"); - goto done; - } - - printk(KERN_NOTICE "RAMDISK: Loading %d blocks [%d disk%s] into ram disk... ", - nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : ""); - for (i=0; i < nblocks; i++) { - if (i && (i % devblocks == 0)) { - printk("done disk #%d.\n", i/devblocks); - rotate = 0; - if (infile.f_op->release(inode, &infile) != 0) { - printk("Error closing the disk.\n"); - goto noclose_input; - } - printk("Please insert disk #%d and press ENTER\n", i/devblocks+1); - wait_for_keypress(); - if (blkdev_open(inode, &infile) != 0) { - printk("Error opening disk.\n"); - goto noclose_input; - } - infile.f_pos = 0; - printk("Loading disk #%d... ", i/devblocks+1); - } - infile.f_op->read(&infile, buf, BLOCK_SIZE, &infile.f_pos); - outfile.f_op->write(&outfile, buf, BLOCK_SIZE, &outfile.f_pos); -#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES) - if (!(i % 16)) { - printk("%c\b", rotator[rotate & 0x3]); - rotate++; - } -#endif - } - printk("done.\n"); - kfree(buf); - -successful_load: - ROOT_DEV = MKDEV(MAJOR_NR, unit); - if (ROOT_DEVICE_NAME != NULL) strcpy (ROOT_DEVICE_NAME, "rd/0"); - -done: - infile.f_op->release(inode, &infile); -noclose_input: - blkdev_close(out_inode, &outfile); - iput(inode); - iput(out_inode); - set_fs(fs); - return; -free_inodes: /* free inodes on error */ - iput(out_inode); - infile.f_op->release(inode, &infile); -free_inode: - iput(inode); -} - -#ifdef CONFIG_MAC_FLOPPY -int swim3_fd_eject(int devnum); -#endif - -static void __init rd_load_disk(int n) -{ - - if (rd_doload == 0) - return; - - if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR -#ifdef CONFIG_BLK_DEV_INITRD - && MAJOR(real_root_dev) != FLOPPY_MAJOR -#endif - ) - return; - - if (rd_prompt) { -#ifdef CONFIG_BLK_DEV_FD - floppy_eject(); -#endif -#ifdef CONFIG_MAC_FLOPPY - if(MAJOR(ROOT_DEV) == FLOPPY_MAJOR) - swim3_fd_eject(MINOR(ROOT_DEV)); - else if(MAJOR(real_root_dev) == FLOPPY_MAJOR) - swim3_fd_eject(MINOR(real_root_dev)); -#endif - printk(KERN_NOTICE - "VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER\n"); - wait_for_keypress(); - } - - rd_load_image(ROOT_DEV,rd_image_start, n); - -} - -void __init rd_load(void) +/* options - nonmodular */ +#ifndef MODULE +static int __init ramdisk_size(char *str) { - rd_load_disk(0); + rd_size = simple_strtol(str,NULL,0); + return 1; } - -void __init rd_load_secondary(void) +static int __init ramdisk_size2(char *str) /* kludge */ { - rd_load_disk(1); + return ramdisk_size(str); } - -#ifdef CONFIG_BLK_DEV_INITRD -void __init initrd_load(void) +static int __init ramdisk_blocksize(char *str) { - rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),rd_image_start,0); + rd_blocksize = simple_strtol(str,NULL,0); + return 1; } +__setup("ramdisk=", ramdisk_size); +__setup("ramdisk_size=", ramdisk_size2); +__setup("ramdisk_blocksize=", ramdisk_blocksize); #endif - -#endif /* RD_LOADER */ - -#ifdef BUILD_CRAMDISK - -/* - * gzip declarations - */ - -#define OF(args) args - -#ifndef memzero -#define memzero(s, n) memset ((s), 0, (n)) -#endif - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define INBUFSIZ 4096 -#define WSIZE 0x8000 /* window size--must be a power of two, and */ - /* at least 32K for zip's deflate method */ - -static uch *inbuf; -static uch *window; - -static unsigned insize; /* valid bytes in inbuf */ -static unsigned inptr; /* index of next byte to be processed in inbuf */ -static unsigned outcnt; /* bytes in output buffer */ -static int exit_code; -static long bytes_out; -static struct file *crd_infp, *crd_outfp; - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions (stubbed out) */ -#define Assert(cond,msg) -#define Trace(x) -#define Tracev(x) -#define Tracevv(x) -#define Tracec(c,x) -#define Tracecv(c,x) - -#define STATIC static - -static int fill_inbuf(void); -static void flush_window(void); -static void *malloc(int size); -static void free(void *where); -static void error(char *m); -static void gzip_mark(void **); -static void gzip_release(void **); - -#include "../../lib/inflate.c" - -static void __init *malloc(int size) -{ - return kmalloc(size, GFP_KERNEL); -} - -static void __init free(void *where) -{ - kfree(where); -} - -static void __init gzip_mark(void **ptr) -{ -} - -static void __init gzip_release(void **ptr) -{ -} - - -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - */ -static int __init fill_inbuf(void) -{ - if (exit_code) return -1; - - insize = crd_infp->f_op->read(crd_infp, inbuf, INBUFSIZ, - &crd_infp->f_pos); - if (insize == 0) return -1; - inptr = 1; - - return inbuf[0]; -} - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void __init flush_window(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, ch; - - crd_outfp->f_op->write(crd_outfp, window, outcnt, &crd_outfp->f_pos); - in = window; - for (n = 0; n < outcnt; n++) { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - outcnt = 0; -} - -static void __init error(char *x) -{ - printk(KERN_ERR "%s", x); - exit_code = 1; -} - -static int __init -crd_load(struct file * fp, struct file *outfp) -{ - int result; - - insize = 0; /* valid bytes in inbuf */ - inptr = 0; /* index of next byte to be processed in inbuf */ - outcnt = 0; /* bytes in output buffer */ - exit_code = 0; - bytes_out = 0; - crc = (ulg)0xffffffffL; /* shift register contents */ - - crd_infp = fp; - crd_outfp = outfp; - inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); - if (inbuf == 0) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); - return -1; - } - window = kmalloc(WSIZE, GFP_KERNEL); - if (window == 0) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n"); - kfree(inbuf); - return -1; - } - makecrc(); - result = gunzip(); - kfree(inbuf); - kfree(window); - return result; -} - -#endif /* BUILD_CRAMDISK */ +/* options - modular */ +MODULE_PARM (rd_size, "1i"); +MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes."); +MODULE_PARM (rd_blocksize, "i"); +MODULE_PARM_DESC(rd_blocksize, "Blocksize of each RAM disk in bytes."); +MODULE_LICENSE("GPL"); Index: drivers/cdrom/gdrom.c =================================================================== RCS file: /cvsroot/linuxsh/linux/drivers/cdrom/gdrom.c,v retrieving revision 1.2 diff -u -3 -p -r1.2 gdrom.c --- drivers/cdrom/gdrom.c 2001/12/04 18:58:02 1.2 +++ drivers/cdrom/gdrom.c 2002/01/08 06:57:49 @@ -30,7 +30,7 @@ #define DEVICE_NAME "GD-ROM" #define DEVICE_REQUEST do_gdrom_request -#define DEVICE_NR(device) (MINOR(device)) +#define DEVICE_NR(device) (minor(device)) #define DEVICE_STR "gdrom" #include <linux/blk.h> @@ -486,7 +486,7 @@ static int __init gdrom_init(void) hardsect_size[MAJOR_NR] = &gdrom_hardsecsize; read_ahead[MAJOR_NR] = 4; - gdrom_info.dev = MKDEV(MAJOR_NR,0); + gdrom_info.dev = mk_kdev(MAJOR_NR,0); if (register_cdrom(&gdrom_info) != 0) { printk(KERN_ERR "Cannot register SEGA GD-ROM!\n"); free_irq(GDROM_IRQ, NULL); Index: drivers/char/sh-sci.c =================================================================== RCS file: /cvsroot/linuxsh/linux/drivers/char/sh-sci.c,v retrieving revision 1.1.1.1 diff -u -3 -p -r1.1.1.1 sh-sci.c --- drivers/char/sh-sci.c 2001/10/15 20:44:59 1.1.1.1 +++ drivers/char/sh-sci.c 2002/01/08 06:57:49 @@ -813,7 +813,7 @@ static int sci_open(struct tty_struct * struct sci_port *port; int retval, line; - line = MINOR(tty->device) - SCI_MINOR_START; + line = minor(tty->device) - SCI_MINOR_START; if ((line < 0) || (line >= SCI_NPORTS)) return -ENODEV; @@ -1181,18 +1181,9 @@ static void serial_console_write(struct put_string(sercons_port, s, count); } -/* - * Receive character from the serial port - */ -static int serial_console_wait_key(struct console *co) -{ - /* Not implemented yet */ - return 0; -} - static kdev_t serial_console_device(struct console *c) { - return MKDEV(SCI_MAJOR, SCI_MINOR_START + c->index); + return mk_kdev(SCI_MAJOR, SCI_MINOR_START + c->index); } /* @@ -1273,7 +1264,6 @@ static struct console sercons = { name: "ttySC", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1, Index: drivers/char/shwdt.c =================================================================== RCS file: /cvsroot/linuxsh/linux/drivers/char/shwdt.c,v retrieving revision 1.3 diff -u -3 -p -r1.3 shwdt.c --- drivers/char/shwdt.c 2001/12/17 00:50:05 1.3 +++ drivers/char/shwdt.c 2002/01/08 06:57:49 @@ -170,7 +170,7 @@ static void sh_wdt_ping(unsigned long da */ static int sh_wdt_open(struct inode *inode, struct file *file) { - switch (MINOR(inode->i_rdev)) { + switch (minor(inode->i_rdev)) { case WATCHDOG_MINOR: if (test_and_set_bit(0, &sh_is_open)) return -EBUSY; @@ -195,7 +195,7 @@ static int sh_wdt_open(struct inode *ino */ static int sh_wdt_close(struct inode *inode, struct file *file) { - if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { + if (minor(inode->i_rdev) == WATCHDOG_MINOR) { #ifndef CONFIG_WATCHDOG_NOWAYOUT sh_wdt_stop(); #endif Index: include/asm-sh/mmu_context.h =================================================================== RCS file: /cvsroot/linuxsh/linux/include/asm-sh/mmu_context.h,v retrieving revision 1.1.1.1 diff -u -3 -p -r1.1.1.1 mmu_context.h --- include/asm-sh/mmu_context.h 2001/10/15 20:45:10 1.1.1.1 +++ include/asm-sh/mmu_context.h 2002/01/08 06:57:49 @@ -185,4 +185,29 @@ static __inline__ void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu) { } + +/* + * Every architecture must define this function. It's the fastest + * way of searching a 168-bit bitmap where the first 128 bits are + * unlikely to be set. It's guaranteed that at least one of the 168 + * bits is cleared. + */ +#if MAX_RT_PRIO != 128 || MAX_PRIO != 168 +# error update this function. +#endif + +static inline int sched_find_first_zero_bit(char *bitmap) +{ + unsigned int *b = (unsigned int *)bitmap; + unsigned int rt; + + rt = b[0] & b[1] & b[2] & b[3]; + if (unlikely(rt != 0xffffffff)) + return find_first_zero_bit(bitmap, MAX_RT_PRIO); + + if (b[4] != ~0) + return ffz(b[4]) + MAX_RT_PRIO; + return ffz(b[5]) + 32 + MAX_RT_PRIO; +} + #endif /* __ASM_SH_MMU_CONTEXT_H */ Index: init/do_mounts.c =================================================================== RCS file: /cvsroot/linuxsh/linux/init/do_mounts.c,v retrieving revision 1.1 diff -u -3 -p -r1.1 do_mounts.c --- init/do_mounts.c 2002/01/07 03:57:48 1.1 +++ init/do_mounts.c 2002/01/08 06:57:49 @@ -1,15 +1,15 @@ #define __KERNEL_SYSCALLS__ #include <linux/config.h> +#include <linux/kernel.h> +#include <linux/sched.h> #include <linux/slab.h> #include <linux/devfs_fs_kernel.h> #include <linux/unistd.h> -#include <linux/string.h> #include <linux/ctype.h> -#include <linux/init.h> -#include <linux/smp_lock.h> #include <linux/blk.h> -#include <linux/tty.h> #include <linux/fd.h> +#include <linux/tty.h> +#include <linux/init.h> #include <linux/nfs_fs.h> #include <linux/nfs_fs_sb.h> @@ -18,12 +18,9 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> -#include <asm/uaccess.h> - #define BUILD_CRAMDISK extern int get_filesystem_list(char * buf); -extern void wait_for_keypress(void); asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type, unsigned long flags, void *data); @@ -38,12 +35,21 @@ asmlinkage long sys_ioctl(int fd, int cm #ifdef CONFIG_BLK_DEV_INITRD unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ -#endif -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; +static int __initdata mount_initrd = 1; + +static int __init no_initrd(char *str) +{ + mount_initrd = 0; + return 1; +} + +__setup("noinitrd", no_initrd); #else -static int rd_doload = 0; +static int __initdata mount_initrd = 0; #endif + +int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */ + int root_mountflags = MS_RDONLY | MS_VERBOSE; static char root_device_name[64]; @@ -52,6 +58,13 @@ kdev_t ROOT_DEV; static int do_devfs = 0; +static int __init load_ramdisk(char *str) +{ + rd_doload = simple_strtol(str,NULL,0) & 3; + return 1; +} +__setup("load_ramdisk=", load_ramdisk); + static int __init readonly(char *str) { if (*str) @@ -342,8 +355,8 @@ static int __init create_dev(char *name, if (!do_devfs) return sys_mknod(name, S_IFBLK|0600, kdev_t_to_nr(dev)); - handle = devfs_find_handle(NULL, dev ? NULL : devfs_name, - MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1); + handle = devfs_find_handle(NULL, kdev_none(dev) ? devfs_name : NULL, + major(dev), minor(dev), DEVFS_SPECIAL_BLK, 1); if (!handle) return -1; n = devfs_generate_path(handle, path + 5, sizeof (path) - 5); @@ -354,8 +367,9 @@ static int __init create_dev(char *name, static void __init change_floppy(char *fmt, ...) { - extern void wait_for_keypress(void); + struct termios termios; char buf[80]; + char c; int fd; va_list args; va_start(args, fmt); @@ -367,11 +381,38 @@ static void __init change_floppy(char *f close(fd); } printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); - wait_for_keypress(); + fd = open("/dev/console", O_RDWR, 0); + if (fd >= 0) { + sys_ioctl(fd, TCGETS, (long)&termios); + termios.c_lflag &= ~ICANON; + sys_ioctl(fd, TCSETSF, (long)&termios); + read(fd, &c, 1); + termios.c_lflag |= ICANON; + sys_ioctl(fd, TCSETSF, (long)&termios); + close(fd); + } } #ifdef CONFIG_BLK_DEV_RAM +int __initdata rd_prompt = 1; /* 1 = prompt for RAM disk, 0 = don't prompt */ + +static int __init prompt_ramdisk(char *str) +{ + rd_prompt = simple_strtol(str,NULL,0) & 1; + return 1; +} +__setup("prompt_ramdisk=", prompt_ramdisk); + +int __initdata rd_image_start; /* starting block # of image */ + +static int __init ramdisk_start_setup(char *str) +{ + rd_image_start = simple_strtol(str,NULL,0); + return 1; +} +__setup("ramdisk_start=", ramdisk_start_setup); + static int __init crd_load(int in_fd, int out_fd); /* @@ -589,18 +630,74 @@ out: static int __init rd_load_disk(int n) { #ifdef CONFIG_BLK_DEV_RAM - extern int rd_prompt; if (rd_prompt) change_floppy("root floppy disk to be loaded into RAM disk"); - create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL); + create_dev("/dev/ram", mk_kdev(RAMDISK_MAJOR, n), NULL); #endif return rd_load_image("/dev/root"); } +#ifdef CONFIG_DEVFS_FS + +static void __init convert_name(char *prefix, char *name, char *p, int part) +{ + int host, bus, target, lun; + char dest[64]; + char src[64]; + char *base = p - 1; + + /* Decode "c#b#t#u#" */ + if (*p++ != 'c') + return; + host = simple_strtol(p, &p, 10); + if (*p++ != 'b') + return; + bus = simple_strtol(p, &p, 10); + if (*p++ != 't') + return; + target = simple_strtol(p, &p, 10); + if (*p++ != 'u') + return; + lun = simple_strtol(p, &p, 10); + if (!part) + sprintf(dest, "%s/host%d/bus%d/target%d/lun%d", + prefix, host, bus, target, lun); + else if (*p++ == 'p') + sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/part%s", + prefix, host, bus, target, lun, p); + else + sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/disc", + prefix, host, bus, target, lun); + *base = '\0'; + sprintf(src, "/dev/%s", name); + sys_mkdir(src, 0755); + *base = '/'; + sprintf(src, "/dev/%s", name); + sys_symlink(dest, src); +} + +static void __init devfs_make_root(char *name) +{ + + if (!strncmp(name, "sd/", 3)) + convert_name("../scsi", name, name+3, 1); + else if (!strncmp(name, "sr/", 3)) + convert_name("../scsi", name, name+3, 0); + else if (!strncmp(name, "ide/hd/", 7)) + convert_name("..", name, name + 7, 1); + else if (!strncmp(name, "ide/cd/", 7)) + convert_name("..", name, name + 7, 0); +} +#else +static void __init devfs_make_root(char *name) +{ +} +#endif + static void __init mount_root(void) { #ifdef CONFIG_ROOT_NFS - if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { + if (major(ROOT_DEV) == UNNAMED_MAJOR) { if (mount_nfs_root()) { sys_chdir("/root"); ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; @@ -608,17 +705,17 @@ static void __init mount_root(void) return; } printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); - ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0); + ROOT_DEV = mk_kdev(FLOPPY_MAJOR, 0); } #endif devfs_make_root(root_device_name); create_dev("/dev/root", ROOT_DEV, root_device_name); #ifdef CONFIG_BLK_DEV_FD - if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { + if (major(ROOT_DEV) == FLOPPY_MAJOR) { /* rd_doload is 2 for a dual initrd/ramload setup */ if (rd_doload==2) { if (rd_load_disk(1)) { - ROOT_DEV = MKDEV(RAMDISK_MAJOR, 1); + ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 1); create_dev("/dev/root", ROOT_DEV, NULL); } } else @@ -653,7 +750,7 @@ static int do_linuxrc(void * shell) static void __init handle_initrd(void) { #ifdef CONFIG_BLK_DEV_INITRD - int ram0 = kdev_t_to_nr(MKDEV(RAMDISK_MAJOR,0)); + kdev_t ram0 = mk_kdev(RAMDISK_MAJOR,0); int error; int i, pid; @@ -664,21 +761,19 @@ static void __init handle_initrd(void) pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid > 0) { - while (pid != wait(&i)) { - current->policy |= SCHED_YIELD; - schedule(); - } + while (pid != wait(&i)) + yield(); } sys_mount("..", ".", NULL, MS_MOVE, NULL); sys_umount("/old/dev", 0); - if (real_root_dev == ram0) { + if (real_root_dev == kdev_t_to_nr(ram0)) { sys_chdir("/old"); return; } - ROOT_DEV = real_root_dev; + ROOT_DEV = to_kdev_t(real_root_dev); mount_root(); printk(KERN_NOTICE "Trying to move old root to /initrd ... "); @@ -705,8 +800,8 @@ static void __init handle_initrd(void) static int __init initrd_load(void) { #ifdef CONFIG_BLK_DEV_INITRD - create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, 0), NULL); - create_dev("/dev/initrd", MKDEV(RAMDISK_MAJOR, INITRD_MINOR), NULL); + create_dev("/dev/ram", mk_kdev(RAMDISK_MAJOR, 0), NULL); + create_dev("/dev/initrd", mk_kdev(RAMDISK_MAJOR, INITRD_MINOR), NULL); #endif return rd_load_image("/dev/initrd"); } @@ -716,30 +811,28 @@ static int __init initrd_load(void) */ void prepare_namespace(void) { - int do_initrd = 0; - int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; + int is_floppy = major(ROOT_DEV) == FLOPPY_MAJOR; #ifdef CONFIG_BLK_DEV_INITRD if (!initrd_start) mount_initrd = 0; - if (mount_initrd) - do_initrd = 1; - real_root_dev = ROOT_DEV; + real_root_dev = kdev_t_to_nr(ROOT_DEV); #endif sys_mkdir("/dev", 0700); sys_mkdir("/root", 0700); + sys_mknod("/dev/console", S_IFCHR|0600, MKDEV(TTYAUX_MAJOR, 1)); #ifdef CONFIG_DEVFS_FS sys_mount("devfs", "/dev", "devfs", 0, NULL); do_devfs = 1; #endif create_dev("/dev/root", ROOT_DEV, NULL); - if (do_initrd) { - if (initrd_load() && ROOT_DEV != MKDEV(RAMDISK_MAJOR, 0)) { + if (mount_initrd) { + if (initrd_load() && kdev_same(ROOT_DEV, mk_kdev(RAMDISK_MAJOR, 0))) { handle_initrd(); goto out; } } else if (is_floppy && rd_doload && rd_load_disk(0)) - ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 0); mount_root(); out: sys_umount("/dev", 0); Index: init/main.c =================================================================== RCS file: /cvsroot/linuxsh/linux/init/main.c,v retrieving revision 1.3 diff -u -3 -p -r1.3 main.c --- init/main.c 2002/01/07 03:57:48 1.3 +++ init/main.c 2002/01/08 06:57:49 @@ -312,18 +312,9 @@ static void __init smp_init(void) /* Get other processors into their bootup holding patterns. */ smp_boot_cpus(); wait_init_idle = cpu_online_map; - clear_bit(current->processor, &wait_init_idle); /* Don't wait on me! */ smp_threads_ready=1; smp_commence(); - - /* Wait for the other cpus to set up their idle processes */ - printk("Waiting on wait_init_idle (map = 0x%lx)\n", wait_init_idle); - while (wait_init_idle) { - cpu_relax(); - barrier(); - } - printk("All processors have done init_idle\n"); } #endif @@ -339,7 +330,7 @@ static void rest_init(void) { kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); unlock_kernel(); - current->need_resched = 1; + init_idle(); /* This will also wait for all other CPUs */ cpu_idle(); } Index: kernel/ptrace.c =================================================================== RCS file: /cvsroot/linuxsh/linux/kernel/ptrace.c,v retrieving revision 1.2 diff -u -3 -p -r1.2 ptrace.c --- kernel/ptrace.c 2001/12/03 22:15:35 1.2 +++ kernel/ptrace.c 2002/01/08 06:57:49 @@ -31,20 +31,7 @@ int ptrace_check_attach(struct task_stru if (child->state != TASK_STOPPED) return -ESRCH; #ifdef CONFIG_SMP - /* Make sure the child gets off its CPU.. */ - for (;;) { - task_lock(child); - if (!task_has_cpu(child)) - break; - task_unlock(child); - do { - if (child->state != TASK_STOPPED) - return -ESRCH; - barrier(); - cpu_relax(); - } while (task_has_cpu(child)); - } - task_unlock(child); + wait_task_inactive(child); #endif } @@ -121,120 +108,17 @@ int ptrace_detach(struct task_struct *ch } /* - * Access another process' address space, one page at a time. + * Access another process' address space. + * Source/target buffer must be kernel space, + * Do not walk the page table directly, use get_user_pages */ -static int access_one_page(struct mm_struct * mm, struct vm_area_struct * vma, unsigned long addr, void *buf, int len, int write) -{ - pgd_t * pgdir; - pmd_t * pgmiddle; - pte_t * pgtable; - char *maddr; - struct page *page; - -repeat: - spin_lock(&mm->page_table_lock); - pgdir = pgd_offset(vma->vm_mm, addr); - if (pgd_none(*pgdir)) - goto fault_in_page; - if (pgd_bad(*pgdir)) - goto bad_pgd; - pgmiddle = pmd_offset(pgdir, addr); - if (pmd_none(*pgmiddle)) - goto fault_in_page; - if (pmd_bad(*pgmiddle)) - goto bad_pmd; - pgtable = pte_offset(pgmiddle, addr); - if (!pte_present(*pgtable)) - goto fault_in_page; - if (write && (!pte_write(*pgtable) || !pte_dirty(*pgtable))) - goto fault_in_page; - page = pte_page(*pgtable); - - /* ZERO_PAGE is special: reads from it are ok even though it's marked reserved */ - if (page != ZERO_PAGE(addr) || write) { - if ((!VALID_PAGE(page)) || PageReserved(page)) { - spin_unlock(&mm->page_table_lock); - return 0; - } - } - get_page(page); - spin_unlock(&mm->page_table_lock); - flush_cache_page(vma, addr); - - if (write) { - maddr = kmap(page); - memcpy(maddr + (addr & ~PAGE_MASK), buf, len); - flush_dcache_page(page); - flush_page_to_ram(page); - flush_icache_page(vma, page); - kunmap(page); - } else { - maddr = kmap(page); - memcpy(buf, maddr + (addr & ~PAGE_MASK), len); - flush_page_to_ram(page); - kunmap(page); - } - put_page(page); - return len; - -fault_in_page: - spin_unlock(&mm->page_table_lock); - /* -1: out of memory. 0 - unmapped page */ - if (handle_mm_fault(mm, vma, addr, write) > 0) - goto repeat; - return 0; - -bad_pgd: - spin_unlock(&mm->page_table_lock); - pgd_ERROR(*pgdir); - return 0; - -bad_pmd: - spin_unlock(&mm->page_table_lock); - pmd_ERROR(*pgmiddle); - return 0; -} - -static int access_mm(struct mm_struct *mm, struct vm_area_struct * vma, unsigned long addr, void *buf, int len, int write) -{ - int copied = 0; - for (;;) { - unsigned long offset = addr & ~PAGE_MASK; - int this_len = PAGE_SIZE - offset; - int retval; - - if (this_len > len) - this_len = len; - retval = access_one_page(mm, vma, addr, buf, this_len, write); - copied += retval; - if (retval != this_len) - break; - - len -= retval; - if (!len) - break; - - addr += retval; - buf += retval; - - if (addr < vma->vm_end) - continue; - if (!vma->vm_next) - break; - if (vma->vm_next->vm_start != vma->vm_end) - break; - - vma = vma->vm_next; - } - return copied; -} - int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) { - int copied; struct mm_struct *mm; - struct vm_area_struct * vma; + struct vm_area_struct *vma; + struct page *page; + void *old_buf = buf; /* Worry about races with exit() */ task_lock(tsk); @@ -246,14 +130,41 @@ int access_process_vm(struct task_struct return 0; down_read(&mm->mmap_sem); - vma = find_extend_vma(mm, addr); - copied = 0; - if (vma) - copied = access_mm(mm, vma, addr, buf, len, write); + /* ignore errors, just check how much was sucessfully transfered */ + while (len) { + int bytes, ret, offset; + void *maddr; + + ret = get_user_pages(current, mm, addr, 1, + write, 1, &page, &vma); + if (ret <= 0) + break; + + bytes = len; + offset = addr & (PAGE_SIZE-1); + if (bytes > PAGE_SIZE-offset) + bytes = PAGE_SIZE-offset; + + flush_cache_page(vma, addr); + maddr = kmap(page); + if (write) { + memcpy(maddr + offset, buf, bytes); + flush_page_to_ram(page); + flush_icache_page(vma, page); + } else { + memcpy(buf, maddr + offset, bytes); + flush_page_to_ram(page); + } + kunmap(page); + put_page(page); + len -= bytes; + buf += bytes; + } up_read(&mm->mmap_sem); mmput(mm); - return copied; + + return buf - old_buf; } int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len) Index: mm/memory.c =================================================================== RCS file: /cvsroot/linuxsh/linux/mm/memory.c,v retrieving revision 1.4 diff -u -3 -p -r1.4 memory.c --- mm/memory.c 2002/01/07 03:57:48 1.4 +++ mm/memory.c 2002/01/08 06:57:49 @@ -397,17 +397,16 @@ void zap_page_range(struct mm_struct *mm spin_unlock(&mm->page_table_lock); } - /* * Do a quick page-table lookup for a single page. */ -static struct page * follow_page(unsigned long address, int write) +static struct page * follow_page(struct mm_struct *mm, unsigned long address, int write) { pgd_t *pgd; pmd_t *pmd; pte_t *ptep, pte; - pgd = pgd_offset(current->mm, address); + pgd = pgd_offset(mm, address); if (pgd_none(*pgd) || pgd_bad(*pgd)) goto out; @@ -443,21 +442,74 @@ static inline struct page * get_page_map return page; } +int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, + int len, int write, int force, struct page **pages, struct vm_area_struct **vmas) +{ + int i = 0; + + do { + struct vm_area_struct * vma; + + vma = find_extend_vma(mm, start); + + if ( !vma || + (!force && + ((write && (!(vma->vm_flags & VM_WRITE))) || + (!write && (!(vma->vm_flags & VM_READ))) ) )) { + if (i) return i; + return -EFAULT; + } + + spin_lock(&mm->page_table_lock); + do { + struct page *map; + while (!(map = follow_page(mm, start, write))) { + spin_unlock(&mm->page_table_lock); + switch (handle_mm_fault(mm, vma, start, write)) { + case 1: + tsk->min_flt++; + break; + case 2: + tsk->maj_flt++; + break; + case 0: + if (i) return i; + return -EFAULT; + default: + if (i) return i; + return -ENOMEM; + } + spin_lock(&mm->page_table_lock); + } + if (pages) { + pages[i] = get_page_map(map); + /* FIXME: call the correct function, + * depending on the type of the found page + */ + if (pages[i]) + page_cache_get(pages[i]); + } + if (vmas) + vmas[i] = vma; + i++; + start += PAGE_SIZE; + len--; + } while(len && start < vma->vm_end); + spin_unlock(&mm->page_table_lock); + } while(len); + return i; +} + /* * Force in an entire range of pages from the current process's user VA, * and pin them in physical memory. */ - #define dprintk(x...) + int map_user_kiobuf(int rw, struct kiobuf *iobuf, unsigned long va, size_t len) { - unsigned long ptr, end; - int err; + int pgcount, err; struct mm_struct * mm; - struct vm_area_struct * vma = 0; - struct page * map; - int i; - int datain = (rw == READ); /* Make sure the iobuf is not already mapped somewhere. */ if (iobuf->nr_pages) @@ -466,79 +518,37 @@ int map_user_kiobuf(int rw, struct kiobu mm = current->mm; dprintk ("map_user_kiobuf: begin\n"); - ptr = va & PAGE_MASK; - end = (va + len + PAGE_SIZE - 1) & PAGE_MASK; - err = expand_kiobuf(iobuf, (end - ptr) >> PAGE_SHIFT); + pgcount = (va + len + PAGE_SIZE - 1)/PAGE_SIZE - va/PAGE_SIZE; + /* mapping 0 bytes is not permitted */ + if (!pgcount) BUG(); + err = expand_kiobuf(iobuf, pgcount); if (err) return err; - down_read(&mm->mmap_sem); - - err = -EFAULT; iobuf->locked = 0; - iobuf->offset = va & ~PAGE_MASK; + iobuf->offset = va & (PAGE_SIZE-1); iobuf->length = len; - i = 0; - - /* - * First of all, try to fault in all of the necessary pages - */ - while (ptr < end) { - if (!vma || ptr >= vma->vm_end) { - vma = find_vma(current->mm, ptr); - if (!vma) - goto out_unlock; - if (vma->vm_start > ptr) { - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto out_unlock; - if (expand_stack(vma, ptr)) - goto out_unlock; - } - if (((datain) && (!(vma->vm_flags & VM_WRITE))) || - (!(vma->vm_flags & VM_READ))) { - err = -EACCES; - goto out_unlock; - } - } - spin_lock(&mm->page_table_lock); - while (!(map = follow_page(ptr, datain))) { - int ret; - - spin_unlock(&mm->page_table_lock); - ret = handle_mm_fault(current->mm, vma, ptr, datain); - if (ret <= 0) { - if (!ret) - goto out_unlock; - else { - err = -ENOMEM; - goto out_unlock; - } - } - spin_lock(&mm->page_table_lock); - } - map = get_page_map(map); - if (map) { - flush_dcache_page(map); - page_cache_get(map); - } else - printk (KERN_INFO "Mapped page missing [%d]\n", i); - spin_unlock(&mm->page_table_lock); - iobuf->maplist[i] = map; - iobuf->nr_pages = ++i; - - ptr += PAGE_SIZE; - } - + /* Try to fault in all of the necessary pages */ + down_read(&mm->mmap_sem); + /* rw==READ means read from disk, write into memory area */ + err = get_user_pages(current, mm, va, pgcount, + (rw==READ), 0, iobuf->maplist, NULL); up_read(&mm->mmap_sem); + if (err < 0) { + unmap_kiobuf(iobuf); + dprintk ("map_user_kiobuf: end %d\n", err); + return err; + } + iobuf->nr_pages = err; + while (pgcount--) { + /* FIXME: flush superflous for rw==READ, + * probably wrong function for rw==WRITE + */ + flush_dcache_page(iobuf->maplist[pgcount]); + } dprintk ("map_user_kiobuf: end OK\n"); return 0; - - out_unlock: - up_read(&mm->mmap_sem); - unmap_kiobuf(iobuf); - dprintk ("map_user_kiobuf: end %d\n", err); - return err; } /* @@ -588,6 +598,9 @@ void unmap_kiobuf (struct kiobuf *iobuf) if (map) { if (iobuf->locked) UnlockPage(map); + /* FIXME: cache flush missing for rw==READ + * FIXME: call the correct reference counting function + */ page_cache_release(map); } } @@ -1418,23 +1431,19 @@ out: return pte_offset(pmd, address); } -/* - * Simplistic page force-in.. - */ int make_pages_present(unsigned long addr, unsigned long end) { - int write; - struct mm_struct *mm = current->mm; + int ret, len, write; struct vm_area_struct * vma; - vma = find_vma(mm, addr); + vma = find_vma(current->mm, addr); write = (vma->vm_flags & VM_WRITE) != 0; if (addr >= end) BUG(); - do { - if (handle_mm_fault(mm, vma, addr, write) < 0) - return -1; - addr += PAGE_SIZE; - } while (addr < end); - return 0; + if (end > vma->vm_end) + BUG(); + len = (end+PAGE_SIZE-1)/PAGE_SIZE-addr/PAGE_SIZE; + ret = get_user_pages(current, current->mm, addr, + len, write, 0, NULL, NULL); + return ret == len ? 0 : -1; } -- |
From: NIIBE Y. <gn...@m1...> - 2002-01-15 08:16:12
|
2.5.2 has been released. Sync to that. The update patch has not been included, I'll try next. 2002-01-15 NIIBE Yutaka <gn...@m1...> Updated to 2.5.2. * init/main.c (rest_init): Remove call of init_idle(). * drivers/net/8139too.c: Include <linux/crc32.h>, remove ether_crc and ethernet_polynomial. * arch/sh/config.in: souce lib/Config.in. * AGAINST-2.5.2: New file. * AGAINST-2.5.1: Removed. Index: arch/sh/config.in =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/config.in,v retrieving revision 1.2 diff -u -3 -p -r1.2 config.in --- arch/sh/config.in 2001/11/03 00:54:51 1.2 +++ arch/sh/config.in 2002/01/15 08:12:44 @@ -386,3 +386,5 @@ if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; bool 'Early printk support' CONFIG_SH_EARLY_PRINTK fi endmenu + +source lib/Config.in Index: drivers/net/8139too.c =================================================================== RCS file: /cvsroot/linuxsh/linux/drivers/net/8139too.c,v retrieving revision 1.4 diff -u -3 -p -r1.4 8139too.c --- drivers/net/8139too.c 2002/01/07 03:57:48 1.4 +++ drivers/net/8139too.c 2002/01/15 08:12:44 @@ -108,6 +108,7 @@ #include <linux/delay.h> #include <linux/ethtool.h> #include <linux/mii.h> +#include <linux/crc32.h> #include <linux/completion.h> #include <asm/io.h> @@ -602,7 +603,6 @@ static void rtl8139_interrupt (int irq, static int rtl8139_close (struct net_device *dev); static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); -static inline u32 ether_crc (int length, unsigned char *data); static void rtl8139_set_rx_mode (struct net_device *dev); static void __set_rx_mode (struct net_device *dev); static void rtl8139_hw_start (struct net_device *dev); @@ -2393,23 +2393,6 @@ static struct net_device_stats *rtl8139_ /* Set or clear the multicast filter for this adaptor. This routine is not state sensitive and need not be SMP locked. */ - -static unsigned const ethernet_polynomial = 0x04c11db7U; -static inline u32 ether_crc (int length, unsigned char *data) -{ - int crc = -1; - - while (--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) - crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? - ethernet_polynomial : 0); - } - - return crc; -} - static void __set_rx_mode (struct net_device *dev) { Index: init/main.c =================================================================== RCS file: /cvsroot/linuxsh/linux/init/main.c,v retrieving revision 1.4 diff -u -3 -p -r1.4 main.c --- init/main.c 2002/01/15 07:59:52 1.4 +++ init/main.c 2002/01/15 08:12:44 @@ -330,7 +330,6 @@ static void rest_init(void) { kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); unlock_kernel(); - init_idle(); /* This will also wait for all other CPUs */ cpu_idle(); } -- |
From: NIIBE Y. <gn...@m1...> - 2002-01-15 08:47:55
|
Is this correct? * include/asm-sh/pci.h (PCI_DMA_BUS_IS_PHYS): Added. Index: include/asm-sh/pci.h =================================================================== RCS file: /cvsroot/linuxsh/linux/include/asm-sh/pci.h,v retrieving revision 1.2 diff -u -3 -p -r1.2 pci.h --- include/asm-sh/pci.h 2001/10/30 23:22:36 1.2 +++ include/asm-sh/pci.h 2002/01/15 08:46:06 @@ -44,6 +44,12 @@ static inline void pcibios_penalize_isa_ * SuperH has everything mapped statically like x86. */ +/* The PCI address space does equal the physical memory + * address space. The networking and block device layers use + * this boolean for bounce buffer decisions. + */ +#define PCI_DMA_BUS_IS_PHYS (1) + #include <linux/types.h> #include <linux/slab.h> #include <asm/scatterlist.h> |
From: M. R. B. <mr...@0x...> - 2002-01-20 06:29:39
|
* NIIBE Yutaka <gn...@m1...> on Tue, Jan 15, 2002: > 2.5.2 has been released. Sync to that.=20 >=20 > The update patch has not been included, I'll try next. >=20 > 2002-01-15 NIIBE Yutaka <gn...@m1...> >=20 > Updated to 2.5.2. > * init/main.c (rest_init): Remove call of init_idle(). > * drivers/net/8139too.c: Include <linux/crc32.h>, remove > ether_crc and ethernet_polynomial. > * arch/sh/config.in: souce lib/Config.in. >=20 > * AGAINST-2.5.2: New file. For future reference, please update the AGAINST-* file agianst the *real* kernel version that you've synced against. The Makefile shows you've actually synced against 2.5.2-pre10 and not vanilla 2.5.2 as this AGAINST file tricked me into believing. I've updated the AGAINST-2.5.2-pre10 file. M. R. |
From: NIIBE Y. <gn...@m1...> - 2002-01-20 10:03:29
|
M. R. Brown wrote: > For future reference, please update the AGAINST-* file agianst the *real* > kernel version that you've synced against. The Makefile shows you've > actually synced against 2.5.2-pre10 and not vanilla 2.5.2 as this AGAINST > file tricked me into believing. > > I've updated the AGAINST-2.5.2-pre10 file. Sorry for my mistake. It is Makefile which is wrong. Current tree is against 2.5.2, I've forgot to sync the Makefile. I should have had the file AGAINST-2.5.2-pre10 and proceded to 2.5.2. -- |
From: M. R. B. <mr...@0x...> - 2002-01-20 14:58:35
|
* NIIBE Yutaka <gn...@m1...> on Sun, Jan 20, 2002: >=20 > Sorry for my mistake. It is Makefile which is wrong. Current tree is > against 2.5.2, I've forgot to sync the Makefile. >=20 > I should have had the file AGAINST-2.5.2-pre10 and proceded to 2.5.2. Ah, ok, no problem, it just took me a few minutes to figure what was going on :). I could only get the tree working against 2.5.2 anyway, so I guess I should've looked closer than that. BTW, are you tagging the last version before syncing to the next one? Plea= se, let's be diligent about this. Thanks, M. R. |
From: NIIBE Y. <gn...@m1...> - 2002-01-20 23:52:29
|
M. R. Brown wrote: > BTW, are you tagging the last version before syncing to the next one? Plea= > se, > let's be diligent about this. Done for 2.5.1. -- |