]> git.hungrycats.org Git - linux/commitdiff
v2.5.2.4.1 -> v2.5.2.5
authorLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 08:17:16 +0000 (00:17 -0800)
committerLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 08:17:16 +0000 (00:17 -0800)
- Jeff Garzik: net driver updates
- NIIBE Yutaka: SuperH update

29 files changed:
arch/i386/config.in
arch/i386/kernel/smpboot.c
arch/sh/kernel/entry.S
arch/sh/kernel/fpu.c
arch/sh/kernel/head.S
arch/sh/kernel/irq.c
arch/sh/kernel/process.c
arch/sh/kernel/rtc.c
arch/sh/kernel/setup.c
arch/sh/kernel/signal.c
arch/sh/kernel/traps.c
arch/sh/mm/fault.c
drivers/char/shwdt.c
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/Makefile
drivers/net/cs89x0.c
drivers/net/fealnx.c
drivers/net/mii.c [new file with mode: 0644]
drivers/net/sundance.c
drivers/sound/via82cxxx_audio.c
drivers/video/clgenfb.c
fs/driverfs/inode.c
include/asm-sh/mmu_context.h
include/asm-sh/pgtable.h
include/asm-sh/processor.h
include/asm-sh/scatterlist.h
include/linux/mii.h
init/Config.in

index 2b814675bc8d2c95c9f9e9e4f0bc308fcdd43626..ae7cd0b7d463b8081ef769802ee083abd45283a9 100644 (file)
@@ -185,6 +185,9 @@ if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
 fi
 endmenu
 
+mainmenu_option next_comment
+comment 'General options'
+
 # Visual Workstation support is utterly broken.
 # If you want to see it working mail an VW540 to hch@infradead.org 8)
 #bool 'SGI Visual Workstation support' CONFIG_VISWS
index 34ca9174abeffe371e302c6bfa2794bfa4c84ba6..0f5521b3fe37b99a3b09cfec07ff665433b4d8db 100644 (file)
@@ -1018,7 +1018,7 @@ void __init smp_boot_cpus(void)
        boot_cpu_logical_apicid = logical_smp_processor_id();
        map_cpu_to_boot_apicid(0, boot_cpu_apicid);
 
-       global_irq_holder = 0;
+       global_irq_holder = NO_PROC_ID;
        current->cpu = 0;
        smp_tune_scheduling();
 
index eb833f0fcb2b0c2efb6e6dfe81de3630dc006f2c..cb382df169833ec5b6eb570d8ea5c3cbef41a81d 100644 (file)
@@ -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
 
index 9036b20c015ccd137982464723a1d55f9acb885b..70cac48db933f01beea3f8386a0c43a0f2ddc146 100644 (file)
 #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 (&regs))
+               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, unsigned long r5, unsigned long r6,
 {
        struct task_struct *tsk = current;
 
-       if (!user_mode(&regs)) {
-               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(&regs)) {
-               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);
index 73c13dc7d917552b32430bcf6c66d8fabd822648..8e41182a2d14d4435b5b5c0219adc7c83bd22e4d 100644 (file)
@@ -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
index 0986f51d3397e5a054e1d77e9f69464e67a2bbc9..8a96a8c34ed1ac1fe7aa54abdeb14638041215f5 100644 (file)
@@ -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 f991af5c788ac9ebba4afb2eb696db78f12631a9..6d11338acad02ef169f58f9c31c18a380a29aeaf 100644 (file)
@@ -12,7 +12,9 @@
  */
 
 #include <linux/unistd.h>
+#include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/a.out.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -39,9 +41,6 @@ void enable_hlt(void)
 void cpu_idle(void *unused)
 {
        /* endless idle loop with no priority at all */
-       init_idle();
-       current->nice = 20;
-
        while (1) {
                if (hlt_counter) {
                        if (need_resched())
index d37d3960c5a98dbf4a1d7f13dc2b9c8e665d2629..6eb2f2cb4a8aaca6c8a88ab898ad4f8f441e656d 100644 (file)
@@ -46,7 +46,7 @@ void sh_rtc_gettimeofday(struct timeval *tv)
        } 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 *tv)
                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;
 
@@ -123,12 +129,3 @@ static int set_rtc_time(unsigned long nowtime)
 
        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);
-}
index bc0ed96a4fda9cf03d8f8f81277a1563252baecf..c7162e39953c8fea9631aee4a9149a1bf77a0731 100644 (file)
@@ -142,9 +142,8 @@ static void sh_console_write(struct console *co, const char *s,
 
 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);
 }
 
 /*
index 6eb893a5e197276610a7d17ed10ef22add92cebe..4f4cade82d6cd035e51eecc582b5fb58050f805f 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/personality.h>
+#include <linux/tty.h>
+
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
index ebe4d3d3b1942811923b3da7c39dc5fb115c565e..2608b613834ddbdebdae4038be76be8f00d6688b 100644 (file)
@@ -300,10 +300,19 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
 /*
  * 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 instruction, struct pt_regs *regs)
                        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 instruction, struct pt_regs *regs)
        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;
        }
index f26eb07a043122e684439684fbea24e33573663c..a169b0bedca8f0bdbecf4ea8dcdefa7569c6b4db 100644 (file)
@@ -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;
        }
@@ -249,6 +248,8 @@ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
                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);
 
index abd566b8374ad4c0713dbbe1f24ad63ee9d63412..c636eccc2c1a3f5d2bfac161df9a4df63b395729 100644 (file)
@@ -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>
 #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 *inode, struct file *file)
 {
        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 *inode, struct file *file)
  */
 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 *file, const char *buf,
                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 *inode, struct file *file,
 
                        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 <lethal@chaoticdreams.org>");
 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);
index e9f2252cf72c115b8d6c05b8a3afa8eabc7023da..e5745847f2b14ddcbf5ca244e8e9d9e50f11dac9 100644 (file)
@@ -77,17 +77,6 @@ static int multicast_filter_limit = 32;
 MODULE_PARM (multicast_filter_limit, "i");
 MODULE_PARM_DESC (multicast_filter_limit, "8139cp maximum number of filtered multicast addresses");
 
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
-#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
-        || defined(__sparc_) || defined(__ia64__) \
-        || defined(__sh__) || defined(__mips__)
-static int rx_copybreak = 1518;
-#else
-static int rx_copybreak = 100;
-#endif
-MODULE_PARM (rx_copybreak, "i");
-MODULE_PARM_DESC (rx_copybreak, "8139cp Breakpoint at which Rx packets are copied");
-
 #define PFX                    DRV_NAME ": "
 
 #define CP_DEF_MSG_ENABLE      (NETIF_MSG_DRV          | \
@@ -334,8 +323,8 @@ static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb)
        netif_rx (skb);
 }
 
-static inline void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
-                                  u32 status, u32 len)
+static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
+                           u32 status, u32 len)
 {
        if (netif_msg_rx_err (cp))
                printk (KERN_DEBUG
@@ -429,8 +418,8 @@ static void cp_rx (struct cp_private *cp)
        while (rx_work--) {
                u32 status, len;
                dma_addr_t mapping;
-               struct sk_buff *skb, *copy_skb;
-               unsigned copying_skb, buflen;
+               struct sk_buff *skb, *new_skb;
+               unsigned buflen;
 
                skb = cp->rx_skb[rx_tail].skb;
                if (!skb)
@@ -453,43 +442,30 @@ static void cp_rx (struct cp_private *cp)
                        goto rx_next;
                }
 
-               copying_skb = (len <= rx_copybreak);
-
                if (netif_msg_rx_status(cp))
-                       printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d copying? %d\n",
-                              cp->dev->name, rx_tail, status, len,
-                              copying_skb);
+                       printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d\n",
+                              cp->dev->name, rx_tail, status, len);
 
-               buflen = copying_skb ? len : cp->rx_buf_sz;
-               copy_skb = dev_alloc_skb (buflen + RX_OFFSET);
-               if (!copy_skb) {
+               buflen = cp->rx_buf_sz + RX_OFFSET;
+               new_skb = dev_alloc_skb (buflen);
+               if (!new_skb) {
                        cp->net_stats.rx_dropped++;
                        goto rx_next;
                }
 
-               skb_reserve(copy_skb, RX_OFFSET);
-               copy_skb->dev = cp->dev;
-
-               if (!copying_skb) {
-                       pci_unmap_single(cp->pdev, mapping,
-                                        buflen, PCI_DMA_FROMDEVICE);
-                       skb->ip_summed = CHECKSUM_NONE;
-                       skb_trim(skb, len);
-
-                       mapping =
-                       cp->rx_skb[rx_tail].mapping =
-                               pci_map_single(cp->pdev, copy_skb->data,
-                                              buflen, PCI_DMA_FROMDEVICE);
-                       cp->rx_skb[rx_tail].skb = copy_skb;
-                       skb_put(copy_skb, buflen);
-               } else {
-                       skb_put(copy_skb, len);
-                       pci_dma_sync_single(cp->pdev, mapping, len, PCI_DMA_FROMDEVICE);
-                       memcpy(copy_skb->data, skb->data, len);
-
-                       /* We'll reuse the original ring buffer. */
-                       skb = copy_skb;
-               }
+               skb_reserve(new_skb, RX_OFFSET);
+               new_skb->dev = cp->dev;
+
+               pci_unmap_single(cp->pdev, mapping,
+                                buflen, PCI_DMA_FROMDEVICE);
+               skb->ip_summed = CHECKSUM_NONE;
+               skb_put(skb, len);
+
+               mapping =
+               cp->rx_skb[rx_tail].mapping =
+                       pci_map_single(cp->pdev, new_skb->tail,
+                                      buflen, PCI_DMA_FROMDEVICE);
+               cp->rx_skb[rx_tail].skb = new_skb;
 
                cp_rx_skb(cp, skb);
 
@@ -884,10 +860,9 @@ static int cp_refill_rx (struct cp_private *cp)
 
                skb->dev = cp->dev;
                skb_reserve(skb, RX_OFFSET);
-               skb_put(skb, cp->rx_buf_sz);
 
                cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
-                       skb->data, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+                       skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
                cp->rx_skb[i].skb = skb;
                cp->rx_skb[i].frag = 0;
 
@@ -1046,6 +1021,9 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
        struct cp_private *cp = dev->priv;
        int rc = 0;
 
+       if (!netif_running(dev))
+               return -EINVAL;
+
        switch (cmd) {
        case SIOCETHTOOL:
                return cp_ethtool_ioctl(cp, (void *) rq->ifr_data);
index c96bce2accdcd0355c736e2a88ad6128e6070673..5d2e80dd6844a7da2464f4845c356506e71a2516 100644 (file)
@@ -2301,6 +2301,9 @@ static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
        int rc = 0;
        int phy = tp->phys[0] & 0x3f;
 
+       if (!netif_running(dev))
+               return -EINVAL;
+
        if (cmd != SIOCETHTOOL) {
                /* With SIOCETHTOOL, this would corrupt the pointer.  */
                data->phy_id &= 0x1f;
index f38266557dce1152a165af3ccac4d288220b0ecf..eaeaacd3373d55561577ff0d220b35bde6e2f3d1 100644 (file)
@@ -17,7 +17,7 @@ O_TARGET := net.o
 
 export-objs     :=     8390.o arlan.o aironet4500_core.o aironet4500_card.o \
                        ppp_async.o ppp_generic.o slhc.o pppox.o auto_irq.o \
-                       net_init.o
+                       net_init.o mii.o
 list-multi     :=      rcpci.o
 rcpci-objs     :=      rcpci45.o rclanmtl.o
 
index b21549c65ca0ca7c0a528ed3304cbf419349d072..cbe421d5f4984091334d1d4214d56e939068618d 100644 (file)
@@ -537,7 +537,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
                         dev->dev_addr[i*2+1] = eeprom_buff[i] >> 8;
                 }
                if (net_debug > 1)
-                       printk(KERN_DEBUG "%s: new adapter_cnf: 0%x\n",
+                       printk(KERN_DEBUG "%s: new adapter_cnf: 0x%x\n",
                                dev->name, lp->adapter_cnf);
         }
 
@@ -582,8 +582,8 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
                i = lp->isa_config & INT_NO_MASK;
                if (lp->chip_type == CS8900) {
                        /* Translate the IRQ using the IRQ mapping table. */
-                       if (i > sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
-                               printk("\ncs89x0: bug: isa_config is %d\n", i);
+                       if (i >= sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
+                               printk("\ncs89x0: invalid ISA interrupt number %d\n", i);
                        else
                                i = cs8900_irq_map[i];
                        
index e35d85f477be5f1a2fa9c2b40638ba0c0e13939f..66bde2a1c1ca01bc3201386dc45ac0bc4344cf09 100644 (file)
@@ -1769,7 +1769,7 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        case SIOCSMIIREG:               /* Write MII PHY register. */
        case SIOCDEVPRIVATE+2:          /* for binary compat, remove in 2.5 */
-               if (!suser())
+               if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
                mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
                return 0;
diff --git a/drivers/net/mii.c b/drivers/net/mii.c
new file mode 100644 (file)
index 0000000..78afc6a
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+
+       mii.c: MII interface library
+
+       Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
+       Copyright 2001 Jeff Garzik
+
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
+{
+       struct net_device *dev = mii->dev;
+       u32 advert, bmcr, lpa, nego;
+
+       ecmd->supported =
+           (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+            SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+            SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
+
+       /* only supports twisted-pair */
+       ecmd->port = PORT_MII;
+
+       /* only supports internal transceiver */
+       ecmd->transceiver = XCVR_INTERNAL;
+
+       /* this isn't fully supported at higher layers */
+       ecmd->phy_address = mii->phy_id;
+
+       ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
+       advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
+       if (advert & ADVERTISE_10HALF)
+               ecmd->advertising |= ADVERTISED_10baseT_Half;
+       if (advert & ADVERTISE_10FULL)
+               ecmd->advertising |= ADVERTISED_10baseT_Full;
+       if (advert & ADVERTISE_100HALF)
+               ecmd->advertising |= ADVERTISED_100baseT_Half;
+       if (advert & ADVERTISE_100FULL)
+               ecmd->advertising |= ADVERTISED_100baseT_Full;
+
+       bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+       lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
+       if (bmcr & BMCR_ANENABLE) {
+               ecmd->advertising |= ADVERTISED_Autoneg;
+               ecmd->autoneg = AUTONEG_ENABLE;
+               
+               nego = mii_nway_result(advert & lpa);
+               if (nego == LPA_100FULL || nego == LPA_100HALF)
+                       ecmd->speed = SPEED_100;
+               else
+                       ecmd->speed = SPEED_10;
+               if (nego == LPA_100FULL || nego == LPA_10FULL) {
+                       ecmd->duplex = DUPLEX_FULL;
+                       mii->full_duplex = 1;
+               } else {
+                       ecmd->duplex = DUPLEX_HALF;
+                       mii->full_duplex = 0;
+               }
+       } else {
+               ecmd->autoneg = AUTONEG_DISABLE;
+
+               ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
+               ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
+       }
+
+       /* ignore maxtxpkt, maxrxpkt for now */
+
+       return 0;
+}
+
+int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
+{
+       struct net_device *dev = mii->dev;
+
+       if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
+               return -EINVAL;
+       if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
+               return -EINVAL;
+       if (ecmd->port != PORT_MII)
+               return -EINVAL;
+       if (ecmd->transceiver != XCVR_INTERNAL)
+               return -EINVAL;
+       if (ecmd->phy_address != mii->phy_id)
+               return -EINVAL;
+       if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
+               return -EINVAL;
+                                 
+       /* ignore supported, maxtxpkt, maxrxpkt */
+       
+       if (ecmd->autoneg == AUTONEG_ENABLE) {
+               u32 bmcr, advert, tmp;
+
+               if ((ecmd->advertising & (ADVERTISED_10baseT_Half |
+                                         ADVERTISED_10baseT_Full |
+                                         ADVERTISED_100baseT_Half |
+                                         ADVERTISED_100baseT_Full)) == 0)
+                       return -EINVAL;
+
+               /* advertise only what has been requested */
+               advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
+               tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+               if (ADVERTISED_10baseT_Half)
+                       tmp |= ADVERTISE_10HALF;
+               if (ADVERTISED_10baseT_Full)
+                       tmp |= ADVERTISE_10FULL;
+               if (ADVERTISED_100baseT_Half)
+                       tmp |= ADVERTISE_100HALF;
+               if (ADVERTISED_100baseT_Full)
+                       tmp |= ADVERTISE_100FULL;
+               if (advert != tmp) {
+                       mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
+                       mii->advertising = tmp;
+               }
+               
+               /* turn on autonegotiation, and force a renegotiate */
+               bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+               bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+               mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
+
+               mii->duplex_lock = 0;
+       } else {
+               u32 bmcr, tmp;
+
+               /* turn off auto negotiation, set speed and duplexity */
+               bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+               tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
+               if (ecmd->speed == SPEED_100)
+                       bmcr |= BMCR_SPEED100;
+               if (ecmd->duplex == DUPLEX_FULL) {
+                       bmcr |= BMCR_FULLDPLX;
+                       mii->full_duplex = 1;
+               } else
+                       mii->full_duplex = 0;
+               if (bmcr != tmp)
+                       mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
+
+               mii->duplex_lock = 1;
+       }
+       return 0;
+}
+
+int mii_link_ok (struct mii_if_info *mii)
+{
+       if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
+               return 1;
+       return 0;
+}
+
+int mii_nway_restart (struct mii_if_info *mii)
+{
+       int bmcr;
+       int r = -EINVAL;
+
+       /* if autoneg is off, it's an error */
+       bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);
+
+       if (bmcr & BMCR_ANENABLE) {
+               bmcr |= BMCR_ANRESTART;
+               mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr);
+               r = 0;
+       }
+
+       return r;
+}
+
+EXPORT_SYMBOL(mii_link_ok);
+EXPORT_SYMBOL(mii_nway_restart);
+EXPORT_SYMBOL(mii_ethtool_gset);
+EXPORT_SYMBOL(mii_ethtool_sset);
index c55a85e826117fa212e336459475ce55a7baaa19..7321b34247fd5662e7a21104ca6f9c93d07dbba3 100644 (file)
 
        Support and updates available at
        http://www.scyld.com/network/sundance.html
+
+
+       Version 1.01a (jgarzik):
+       - Replace some MII-related magic numbers with constants
+
 */
 
 #define DRV_NAME       "sundance"
-#define DRV_VERSION    "1.01"
-#define DRV_RELDATE    "4/09/00"
+#define DRV_VERSION    "1.01a"
+#define DRV_RELDATE    "11-Nov-2001"
 
 
 /* The user-configurable values.
@@ -443,7 +448,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        int irq;
        int i;
        long ioaddr;
-       u16 mii_reg0;
+       u16 mii_ctl;
        void *ring_space;
        dma_addr_t ring_dma;
 
@@ -582,15 +587,15 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
                }
        }
        /* Reset PHY */
-       mdio_write (dev, np->phys[0], 0, 0x8000);
+       mdio_write (dev, np->phys[0], MII_BMCR, BMCR_RESET);
        mdelay (300);
-       mdio_write (dev, np->phys[0], 0, 0x1200);
+       mdio_write (dev, np->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART);
        /* Force media type */
        if (!np->an_enable) {
-               mii_reg0 = 0;
-               mii_reg0 |= (np->speed == 100) ? 0x2000 : 0;
-               mii_reg0 |= (np->full_duplex) ? 0x0100 : 0;
-               mdio_write (dev, np->phys[0], 0, mii_reg0);
+               mii_ctl = 0;
+               mii_ctl |= (np->speed == 100) ? BMCR_SPEED100 : 0;
+               mii_ctl |= (np->full_duplex) ? BMCR_FULLDPLX : 0;
+               mdio_write (dev, np->phys[0], MII_BMCR, mii_ctl);
                printk (KERN_INFO "Override speed=%d, %s duplex\n",
                        np->speed, np->full_duplex ? "Full" : "Half");
 
@@ -798,12 +803,12 @@ static void check_duplex(struct net_device *dev)
 {
        struct netdev_private *np = dev->priv;
        long ioaddr = dev->base_addr;
-       int mii_reg5 = mdio_read(dev, np->phys[0], 5);
-       int negotiated = mii_reg5 & np->advertising;
+       int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
+       int negotiated = mii_lpa & np->advertising;
        int duplex;
        
        /* Force media */
-       if (!np->an_enable || mii_reg5 == 0xffff) {
+       if (!np->an_enable || mii_lpa == 0xffff) {
                if (np->full_duplex)
                        writew (readw (ioaddr + MACCtrl0) | EnbFullDuplex,
                                ioaddr + MACCtrl0);
@@ -1184,7 +1189,7 @@ static void netdev_error(struct net_device *dev, int intr_status)
 {
        long ioaddr = dev->base_addr;
        struct netdev_private *np = dev->priv;
-       u16 mii_reg0, mii_reg4, mii_reg5;
+       u16 mii_ctl, mii_advertise, mii_lpa;
        int speed;
 
        if (intr_status & IntrDrvRqst) {
@@ -1200,27 +1205,27 @@ static void netdev_error(struct net_device *dev, int intr_status)
        }
        if (intr_status & LinkChange) {
                if (np->an_enable) {
-                       mii_reg4 = mdio_read (dev, np->phys[0], 4);
-                       mii_reg5= mdio_read (dev, np->phys[0], 5);
-                       mii_reg4 &= mii_reg5;
+                       mii_advertise = mdio_read (dev, np->phys[0], MII_ADVERTISE);
+                       mii_lpa= mdio_read (dev, np->phys[0], MII_LPA);
+                       mii_advertise &= mii_lpa;
                        printk (KERN_INFO "%s: Link changed: ", dev->name);
-                       if (mii_reg4 & 0x0100)
+                       if (mii_advertise & ADVERTISE_100FULL)
                                printk ("100Mbps, full duplex\n");
-                       else if (mii_reg4 & 0x0080)
+                       else if (mii_advertise & ADVERTISE_100HALF)
                                printk ("100Mbps, half duplex\n");
-                       else if (mii_reg4 & 0x0040)
+                       else if (mii_advertise & ADVERTISE_10FULL)
                                printk ("10Mbps, full duplex\n");
-                       else if (mii_reg4 & 0x0020)
+                       else if (mii_advertise & ADVERTISE_10HALF)
                                printk ("10Mbps, half duplex\n");
                        else
                                printk ("\n");
 
                } else {
-                       mii_reg0 = mdio_read (dev, np->phys[0], 0);
-                       speed = (mii_reg0 & 0x2000) ? 100 : 10;
+                       mii_ctl = mdio_read (dev, np->phys[0], MII_BMCR);
+                       speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
                        printk (KERN_INFO "%s: Link changed: %dMbps ,",
                                dev->name, speed);
-                       printk ("%s duplex.\n", (mii_reg0 & 0x0100) ?
+                       printk ("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ?
                                "full" : "half");
                }
                check_duplex (dev);
index cdb44556274e92340bd452732432f14a615f0168..510ff867a182b330d5728680abe685c9fc354a2a 100644 (file)
@@ -1358,7 +1358,7 @@ out:
 
 static int via_mixer_open (struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       int minor = minor(inode->i_rdev);
        struct via_info *card;
        struct pci_dev *pdev;
        struct pci_driver *drvr;
@@ -2974,7 +2974,7 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file,
 
 static int via_dsp_open (struct inode *inode, struct file *file)
 {
-       int minor = MINOR(inode->i_rdev);
+       int minor = minor(inode->i_rdev);
        struct via_info *card;
        struct pci_dev *pdev;
        struct via_channel *chan;
index 5a48f270a5682dfe3bc61d72a1a8c7a53dec6278..e5b58b326fe36a7da0b0e274fa4a664082a757e7 100644 (file)
@@ -413,6 +413,7 @@ static struct display disp;
 static struct clgenfb_info boards[MAX_NUM_BOARDS];     /* the boards */
 
 static unsigned clgen_def_mode = 1;
+static int noaccel = 0;
 
 static int release_io_ports = 0;
 
@@ -1405,7 +1406,9 @@ static void clgen_set_par (const void *par, struct fb_info_gen *info)
                        break;
 
                case BT_PICASSO4:
+#ifdef CONFIG_ZORRO
                        vga_wseq (fb_info->regs, CL_SEQRF, 0xb8);       /* ### INCOMPLETE!! */
+#endif
 /*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
                        break;
 
@@ -2748,6 +2751,23 @@ int __init clgenfb_init(void)
 
        DPRINTK ("clgen: (RAM start set to: 0x%p)\n", fb_info->fbmem);
 
+       if (noaccel)
+       {
+               printk("clgen: disabling text acceleration support\n");
+#ifdef FBCON_HAS_CFB8
+               fbcon_clgen_8.bmove = fbcon_cfb8_bmove;
+               fbcon_clgen_8.clear = fbcon_cfb8_clear;
+#endif
+#ifdef FBCON_HAS_CFB16
+               fbcon_clgen_16.bmove = fbcon_cfb16_bmove;
+               fbcon_clgen_16.clear = fbcon_cfb16_clear;
+#endif
+#ifdef FBCON_HAS_CFB32
+               fbcon_clgen_32.bmove = fbcon_cfb32_bmove;
+               fbcon_clgen_32.clear = fbcon_cfb32_clear;
+#endif
+       }
+
        init_vgachip (fb_info);
 
        /* set up a few more things, register framebuffer driver etc */
@@ -2851,6 +2871,8 @@ int __init clgenfb_setup(char *options) {
                        if (strcmp (this_opt, s) == 0)
                                clgen_def_mode = i;
                }
+               if (!strcmp(this_opt, "noaccel"))
+                       noaccel = 1;
        }
        return 0;
 }
index ff2163fe6cf92ac44336d695a87719b62ef5b497..3f3031de17a54312d301192ce4fd36a351054865 100644 (file)
@@ -105,9 +105,11 @@ struct inode *driverfs_get_inode(struct super_block *sb, int mode, int dev)
 static int driverfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
 {
        struct inode *inode = driverfs_get_inode(dir->i_sb, mode, dev);
-       int error = -ENOSPC;
+       int error = -EPERM;
 
-       if (inode) {
+       /* only allow create if ->d_fsdata is not NULL (so we can assume it 
+        * comes from the driverfs API below. */
+       if (dentry->d_fsdata && inode) {
                d_instantiate(dentry, inode);
                dget(dentry);
                error = 0;
@@ -239,18 +241,14 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
                DBG("%s: file entry is NULL\n",__FUNCTION__);
                return -ENOENT;
        }
+       if (!entry->show)
+               return 0;
 
        dev = list_entry(entry->parent,struct device, dir);
-       get_device(dev);
-
-       if (!entry->show)
-               goto done;
 
        page = (unsigned char*)__get_free_page(GFP_KERNEL);
-       if (!page) {
-               retval = -ENOMEM;
-               goto done;
-       }
+       if (!page)
+               return -ENOMEM;
 
        while (count > 0) {
                ssize_t len;
@@ -274,9 +272,6 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
                retval += len;
        }
        free_page((unsigned long)page);
-
- done:
-       put_device(dev);
        return retval;
 }
 
@@ -305,12 +300,10 @@ driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *pp
                DBG("%s: file entry is NULL\n",__FUNCTION__);
                return -ENOENT;
        }
+       if (!entry->store)
+               return 0;
 
        dev = list_entry(entry->parent,struct device, dir);
-       get_device(dev);
-
-       if (!entry->store)
-               goto done;
 
        while (count > 0) {
                ssize_t len;
@@ -327,8 +320,6 @@ driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *pp
                *ppos += len;
                buf += len;
        }
- done:
-       put_device(dev);
        return retval;
 }
 
@@ -358,9 +349,28 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig)
 
 static int driverfs_open_file(struct inode * inode, struct file * filp)
 {
-       if (filp && inode)
-               filp->private_data = inode->u.generic_ip;
+       struct driver_file_entry * entry;
+       struct device * dev;
+
+       entry = (struct driver_file_entry *)inode->u.generic_ip;
+       if (!entry)
+               return -EFAULT;
+       dev = (struct device *)list_entry(entry->parent,struct device,dir);
+       get_device(dev);
+       filp->private_data = entry;
+       return 0;
+}
+
+static int driverfs_flush(struct file * filp)
+{
+       struct driver_file_entry * entry;
+       struct device * dev;
 
+       entry = (struct driver_file_entry *)filp->private_data;
+       if (!entry)
+               return -EFAULT;
+       dev = (struct device *)list_entry(entry->parent,struct device,dir);
+       put_device(dev);
        return 0;
 }
 
@@ -392,6 +402,7 @@ static struct file_operations driverfs_file_operations = {
        llseek:         driverfs_file_lseek,
        mmap:           generic_file_mmap,
        open:           driverfs_open_file,
+       flush:          driverfs_flush,
        fsync:          driverfs_sync_file,
 };
 
@@ -623,13 +634,13 @@ driverfs_create_file(struct driver_file_entry * entry,
        dentry = lookup_hash(&qstr,parent_dentry);
        if (IS_ERR(dentry))
                error = PTR_ERR(dentry);
-       else
+       else {
+               dentry->d_fsdata = (void *)entry;
                error = vfs_create(parent_dentry->d_inode,dentry,entry->mode);
-
+       }
 
        /* Still good? Ok, then fill in the blanks: */
        if (!error) {
-               dentry->d_fsdata = (void *)entry;
                dentry->d_inode->u.generic_ip = (void *)entry;
 
                entry->dentry = dentry;
index 6eedcf32519dcef63f131f632527d9781456b937..47b497a7c77b60748f91ef0be5a2a85ed33d928d 100644 (file)
@@ -185,4 +185,28 @@ 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(unsigned long *b)
+{
+       unsigned int rt;
+
+       rt = b[0] & b[1] & b[2] & b[3];
+       if (unlikely(rt != 0xffffffff))
+               return find_first_zero_bit(b, 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 6c47e1bbb79805025951ff6b8e4463a594b8551d..38dee49f4c9716cd59fb76997d907c06f5c8b476 100644 (file)
@@ -236,6 +236,19 @@ static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) |
 static inline pte_t pte_mkyoung(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
 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.
index 92683003d9a29084a8c7d6189bb566bdc13c1a02..d0059ce6a93400ec52654d111f3010c3dbd9cb2f 100644 (file)
@@ -184,19 +184,23 @@ extern void save_fpu(struct task_struct *__tsk);
 
 #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.
  */
index fcd23eeb8b5a1f5ab9a8d4914db824cd5105ed98..d67ab413e33d16c3cffec69f452767d970abd444 100644 (file)
@@ -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;
 };
 
index 943913583deaaffb93c7dac9e45985a8f1fba3f9..4a3881211195e1a0b84b3c5c09f69973a1dbb697 100644 (file)
@@ -70,6 +70,8 @@
 #define ADVERTISE_LPACK         0x4000  /* Ack link partners response  */
 #define ADVERTISE_NPAGE         0x8000  /* Next page bit               */
 
+#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+                       ADVERTISE_CSMA)
 #define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
                        ADVERTISE_100HALF | ADVERTISE_100FULL)
 
 #define NWAYTEST_LOOPBACK       0x0100  /* Enable loopback for N-way   */
 #define NWAYTEST_RESV2          0xfe00  /* Unused...                   */
 
+
+struct mii_if_info {
+       int phy_id;
+       int advertising;
+
+       unsigned int full_duplex : 1;
+       unsigned int duplex_lock : 1;
+
+       struct net_device *dev;
+       int (*mdio_read) (struct net_device *dev, int phy_id, int location);
+       void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
+};
+
+struct ethtool_cmd;
+
+int mii_link_ok (struct mii_if_info *mii);
+int mii_nway_restart (struct mii_if_info *mii);
+int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+
+
 /* This structure is used in all SIOCxMIIxxx ioctl calls */
 struct mii_ioctl_data {
        u16             phy_id;
index cab88433d5b8da246a93c65caab1a6adba2b57c2..64c26435f1ffd99c907c9124ff35d4794e5df1a1 100644 (file)
@@ -6,6 +6,8 @@ bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 
+endmenu
+
 mainmenu_option next_comment
 comment 'Code maturity level options'
 bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
@@ -19,5 +21,3 @@ if [ "$CONFIG_MODULES" = "y" ]; then
    bool '  Kernel module loader' CONFIG_KMOD
 fi
 endmenu
-
-