Commit fe48f9c8 authored by Linus Torvalds's avatar Linus Torvalds

v2.5.2.4.1 -> v2.5.2.5

- Jeff Garzik: net driver updates
- NIIBE Yutaka: SuperH update
parent 397cbdc2
...@@ -185,6 +185,9 @@ if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then ...@@ -185,6 +185,9 @@ if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
fi fi
endmenu endmenu
mainmenu_option next_comment
comment 'General options'
# Visual Workstation support is utterly broken. # Visual Workstation support is utterly broken.
# If you want to see it working mail an VW540 to hch@infradead.org 8) # If you want to see it working mail an VW540 to hch@infradead.org 8)
#bool 'SGI Visual Workstation support' CONFIG_VISWS #bool 'SGI Visual Workstation support' CONFIG_VISWS
......
...@@ -1018,7 +1018,7 @@ void __init smp_boot_cpus(void) ...@@ -1018,7 +1018,7 @@ void __init smp_boot_cpus(void)
boot_cpu_logical_apicid = logical_smp_processor_id(); boot_cpu_logical_apicid = logical_smp_processor_id();
map_cpu_to_boot_apicid(0, boot_cpu_apicid); map_cpu_to_boot_apicid(0, boot_cpu_apicid);
global_irq_holder = 0; global_irq_holder = NO_PROC_ID;
current->cpu = 0; current->cpu = 0;
smp_tune_scheduling(); smp_tune_scheduling();
......
...@@ -66,7 +66,6 @@ need_resched = 20 ...@@ -66,7 +66,6 @@ need_resched = 20
tsk_ptrace = 24 tsk_ptrace = 24
PT_TRACESYS = 0x00000002 PT_TRACESYS = 0x00000002
PF_USEDFPU = 0x00100000
ENOSYS = 38 ENOSYS = 38
EINVAL = 22 EINVAL = 22
...@@ -567,12 +566,6 @@ __irq_stat: ...@@ -567,12 +566,6 @@ __irq_stat:
.align 2 .align 2
restore_all: restore_all:
#if defined(__SH4__)
mov.l __fpu_prepare_fd, r0
jsr @r0
stc sr, r4
#endif
!
mov.l @r15+, r0 mov.l @r15+, r0
mov.l @r15+, r1 mov.l @r15+, r1
mov.l @r15+, r2 mov.l @r15+, r2
...@@ -623,66 +616,12 @@ restore_all: ...@@ -623,66 +616,12 @@ restore_all:
7: or k0, k2 ! Set the IMASK-bits 7: or k0, k2 ! Set the IMASK-bits
ldc k2, ssr 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 mov k4, r15
rte rte
nop nop
.align 2 .align 2
__blrb_flags: .long 0x30000000 __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 1: .long 0x00008000 ! FD
2: .long 0xffff7f0f ! ~(IMASK+FD) 2: .long 0xffff7f0f ! ~(IMASK+FD)
3: .long 0x00080000 ! SZ=0, PR=1 3: .long 0x00080000 ! SZ=0, PR=1
...@@ -732,60 +671,20 @@ handle_exception: ...@@ -732,60 +671,20 @@ handle_exception:
! Using k0, k1 for scratch registers (r0_bank1, r1_bank), ! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
! save all registers onto stack. ! save all registers onto stack.
! !
stc ssr, k0 ! from kernel space? stc ssr, k0 ! Is it from kernel space?
shll k0 ! Check MD bit (bit30) by shifting it into the T bit shll k0 ! Check MD bit (bit30) by shifting it into...
shll k0 shll k0 ! ...the T bit
#if defined(__SH4__) bt/s 9f ! It's a kernel to kernel transition.
bf/s 8f ! it's from user to kernel transition
mov r15, k0 ! save original stack to k0 mov r15, k0 ! save original stack to k0
/* It's a kernel to kernel transition. */ /* User space to kernel */
/* 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 */
mov #0x20, k1 mov #0x20, k1
shll8 k1 ! k1 <= 8192 == THREAD_SIZE shll8 k1 ! k1 <= 8192 == THREAD_SIZE
add current, k1 add current, k1
mov k1, r15 ! change to kernel stack mov k1, r15 ! change to kernel stack
! !
mov.l 4f, k1 ! let kernel release FPU 9: mov #-1, k4
9: ! Save the user registers on the stack. mov.l 3f, k1
! At this point, k1 should have been set to the new SR value ! Save the user registers on the stack.
mov #-1, k4
mov.l k4, @-r15 ! syscall_nr (default: -1) mov.l k4, @-r15 ! syscall_nr (default: -1)
! !
sts.l macl, @-r15 sts.l macl, @-r15
...@@ -807,7 +706,7 @@ handle_exception: ...@@ -807,7 +706,7 @@ handle_exception:
mov.l r8, @-r15 mov.l r8, @-r15
! !
stc sr, r8 ! Back to normal register bank, and stc sr, r8 ! Back to normal register bank, and
or k1, r8 ! Block all interrupts, may release FPU or k1, r8 ! Block all interrupts
mov.l 5f, k1 mov.l 5f, k1
and k1, r8 ! ... and k1, r8 ! ...
ldc r8, sr ! ...changed here. ldc r8, sr ! ...changed here.
...@@ -831,9 +730,7 @@ handle_exception: ...@@ -831,9 +730,7 @@ handle_exception:
nop nop
.align 2 .align 2
1: .long SYMBOL_NAME(exception_handling_table) 1: .long SYMBOL_NAME(exception_handling_table)
2: .long 0x00008000 ! FD=1
3: .long 0x000000f0 ! FD=0, IMASK=15 3: .long 0x000000f0 ! FD=0, IMASK=15
4: .long 0x000080f0 ! FD=1, IMASK=15
5: .long 0xcfffffff ! RB=0, BL=0 5: .long 0xcfffffff ! RB=0, BL=0
6: .long 0x00080000 ! SZ=0, PR=1 6: .long 0x00080000 ! SZ=0, PR=1
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/io.h> #include <asm/io.h>
/*
* Save FPU registers onto task structure.
* Assume called with FPU enabled (SR.FD=0).
*/
void void
save_fpu(struct task_struct *tsk) save_fpu(struct task_struct *tsk)
{ {
...@@ -118,7 +122,8 @@ restore_fpu(struct task_struct *tsk) ...@@ -118,7 +122,8 @@ restore_fpu(struct task_struct *tsk)
* double precission represents signaling NANS. * double precission represents signaling NANS.
*/ */
void fpu_init(void) static void
fpu_init(void)
{ {
asm volatile("lds %0, fpul\n\t" asm volatile("lds %0, fpul\n\t"
"lds %1, fpscr\n\t" "lds %1, fpscr\n\t"
...@@ -160,123 +165,143 @@ void fpu_init(void) ...@@ -160,123 +165,143 @@ void fpu_init(void)
: "r" (0), "r" (FPSCR_INIT)); : "r" (0), "r" (FPSCR_INIT));
} }
asmlinkage void /**
do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, * denormal_to_double - Given denormalized float number,
struct pt_regs regs) * 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)
{ {
struct task_struct *tsk = current; unsigned long du, dl;
unsigned long x = fpu->fpul;
int exp = 1023 - 126;
regs.pc += 2; 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;
grab_fpu(); fpu->fp_regs[n] = du;
save_fpu(tsk); fpu->fp_regs[n+1] = dl;
tsk->thread.trap_no = 11; }
tsk->thread.error_code = 0;
force_sig(SIGFPE, tsk);
} }
asmlinkage void /**
do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, * ieee_fpe_handler - Handle denormalized number exception
unsigned long r7, struct pt_regs regs)
{
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 * @regs: Pointer to register structure
* 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.
* *
* Returns 1 when it's handled (should not cause exception).
*/ */
release_fpu(); static int
return; 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(); grab_fpu();
if (tsk->used_math) {
/* Using the FPU again. */
restore_fpu(tsk); restore_fpu(tsk);
tsk->flags |= PF_USEDFPU;
} else { } else {
/* First time FPU user. */ tsk->thread.trap_no = 11;
fpu_init(); tsk->thread.error_code = 0;
tsk->used_math = 1; force_sig(SIGFPE, tsk);
} }
tsk->flags |= PF_USEDFPU;
release_fpu(); regs->pc = nextpc;
return 1;
}
return 0;
} }
/*
* Change current FD flag to set FD flag back to exception
*/
asmlinkage void asmlinkage void
fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6, do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7,
unsigned long r7, struct pt_regs regs) struct pt_regs regs)
{ {
__cli(); struct task_struct *tsk = current;
if (!user_mode(&regs)) {
if (init_task.flags & PF_USEDFPU) if (ieee_fpe_handler (&regs))
grab_fpu();
else {
if (!(sr & SR_FD)) {
BUG();
release_fpu();
}
}
return; return;
}
if (sr & SR_FD) { /* Kernel doesn't grab FPU */ regs.pc += 2;
if (current->flags & PF_USEDFPU) save_fpu(tsk);
grab_fpu(); tsk->thread.trap_no = 11;
else { tsk->thread.error_code = 0;
if (init_task.flags & PF_USEDFPU) { force_sig(SIGFPE, tsk);
/*
* 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 asmlinkage void
enable_fpu_in_danger(void) do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
unsigned long r7, struct pt_regs regs)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
if (tsk != &init_task) grab_fpu();
unlazy_fpu(tsk); if (!user_mode(&regs)) {
printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
return;
}
tsk = &init_task;
if (tsk->used_math) { if (tsk->used_math) {
/* Using the FPU again. */ /* Using the FPU again. */
restore_fpu(tsk); restore_fpu(tsk);
......
...@@ -50,12 +50,6 @@ ENTRY(_stext) ...@@ -50,12 +50,6 @@ ENTRY(_stext)
sub r1, r0 ! sub r1, r0 !
ldc r0, r7_bank ! ... and init_task ldc r0, r7_bank ! ... and init_task
! !
#if defined(__SH4__)
! Initialize fpu
mov.l 7f, r0
jsr @r0
nop
#endif
! Enable cache ! Enable cache
mov.l 6f, r0 mov.l 6f, r0
jsr @r0 jsr @r0
...@@ -74,12 +68,9 @@ ENTRY(_stext) ...@@ -74,12 +68,9 @@ ENTRY(_stext)
nop nop
.balign 4 .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) 2: .long SYMBOL_NAME(stack)
3: .long SYMBOL_NAME(__bss_start) 3: .long SYMBOL_NAME(__bss_start)
4: .long SYMBOL_NAME(_end) 4: .long SYMBOL_NAME(_end)
5: .long SYMBOL_NAME(start_kernel) 5: .long SYMBOL_NAME(start_kernel)
6: .long SYMBOL_NAME(cache_init) 6: .long SYMBOL_NAME(cache_init)
#if defined(__SH4__)
7: .long SYMBOL_NAME(fpu_init)
#endif
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/smp.h> #include <linux/smp.h>
......
...@@ -12,7 +12,9 @@ ...@@ -12,7 +12,9 @@
*/ */
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/a.out.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -39,9 +41,6 @@ void enable_hlt(void) ...@@ -39,9 +41,6 @@ void enable_hlt(void)
void cpu_idle(void *unused) void cpu_idle(void *unused)
{ {
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
init_idle();
current->nice = 20;
while (1) { while (1) {
if (hlt_counter) { if (hlt_counter) {
if (need_resched()) if (need_resched())
......
...@@ -46,7 +46,7 @@ void sh_rtc_gettimeofday(struct timeval *tv) ...@@ -46,7 +46,7 @@ void sh_rtc_gettimeofday(struct timeval *tv)
} while ((ctrl_inb(RCR1) & RCR1_CF) != 0); } while ((ctrl_inb(RCR1) & RCR1_CF) != 0);
#if RTC_BIT_INVERTED != 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) { if (sec128 == RTC_BIT_INVERTED) {
schedule_timeout(1); schedule_timeout(1);
goto again; goto again;
...@@ -81,12 +81,18 @@ void sh_rtc_gettimeofday(struct timeval *tv) ...@@ -81,12 +81,18 @@ void sh_rtc_gettimeofday(struct timeval *tv)
goto again; 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_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 retval = 0;
int real_seconds, real_minutes, cmos_minutes; int real_seconds, real_minutes, cmos_minutes;
...@@ -123,12 +129,3 @@ static int set_rtc_time(unsigned long nowtime) ...@@ -123,12 +129,3 @@ static int set_rtc_time(unsigned long nowtime)
return retval; 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);
}
...@@ -142,9 +142,8 @@ static void sh_console_write(struct console *co, const char *s, ...@@ -142,9 +142,8 @@ static void sh_console_write(struct console *co, const char *s,
static kdev_t sh_console_device(struct console *c) static kdev_t sh_console_device(struct console *c)
{ {
/* TODO: this is totally bogus */ /* /dev/null */
/* return MKDEV(SCI_MAJOR, SCI_MINOR_START + c->index); */ return mk_kdev(MEM_MAJOR, 3);
return 0;
} }
/* /*
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/tty.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
......
...@@ -300,10 +300,19 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs) ...@@ -300,10 +300,19 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
/* /*
* handle an instruction that does an unaligned memory access * handle an instruction that does an unaligned memory access
* - have to be careful of branch delay-slot instructions that fault * - 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 be taken PC points to the branch
* - if the branch would not be taken, PC points to delay-slot * - 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) * - 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) static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
{ {
u_int rm; u_int rm;
...@@ -392,15 +401,27 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) ...@@ -392,15 +401,27 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
break; break;
case 0x0F00: /* bf/s lab */ case 0x0F00: /* bf/s lab */
ret = handle_unaligned_delayslot(regs); ret = handle_unaligned_delayslot(regs);
if (ret==0) if (ret==0) {
regs->pc += (instruction&0x00FF)*2 + 4; #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;
case 0x0900: /* bt lab - no delayslot */ case 0x0900: /* bt lab - no delayslot */
break; break;
case 0x0D00: /* bt/s lab */ case 0x0D00: /* bt/s lab */
ret = handle_unaligned_delayslot(regs); ret = handle_unaligned_delayslot(regs);
if (ret==0) if (ret==0) {
regs->pc += (instruction&0x00FF)*2 + 4; #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;
} }
break; break;
...@@ -408,14 +429,14 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) ...@@ -408,14 +429,14 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
case 0xA000: /* bra label */ case 0xA000: /* bra label */
ret = handle_unaligned_delayslot(regs); ret = handle_unaligned_delayslot(regs);
if (ret==0) if (ret==0)
regs->pc += (instruction&0x0FFF)*2 + 4; regs->pc += SH_PC_12BIT_OFFSET(instruction);
break; break;
case 0xB000: /* bsr label */ case 0xB000: /* bsr label */
ret = handle_unaligned_delayslot(regs); ret = handle_unaligned_delayslot(regs);
if (ret==0) { if (ret==0) {
regs->pr = regs->pc + 4; regs->pr = regs->pc + 4;
regs->pc += (instruction&0x0FFF)*2 + 4; regs->pc += SH_PC_12BIT_OFFSET(instruction);
} }
break; break;
} }
......
...@@ -207,8 +207,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, ...@@ -207,8 +207,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
out_of_memory: out_of_memory:
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
if (current->pid == 1) { if (current->pid == 1) {
current->policy |= SCHED_YIELD; yield();
schedule();
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
goto survive; goto survive;
} }
...@@ -249,6 +248,8 @@ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess, ...@@ -249,6 +248,8 @@ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
dir = pgd_offset_k(address); dir = pgd_offset_k(address);
else if (address >= TASK_SIZE) else if (address >= TASK_SIZE)
return 1; return 1;
else if (!current->mm)
return 1;
else else
dir = pgd_offset(current->mm, address); dir = pgd_offset(current->mm, address);
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/smp_lock.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -47,18 +46,47 @@ ...@@ -47,18 +46,47 @@
#define WTCSR_CKS1 0x02 #define WTCSR_CKS1 0x02
#define WTCSR_CKS0 0x01 #define WTCSR_CKS0 0x01
#define WTCSR_CKS 0x07 /*
#define WTCSR_CKS_1 0x00 * CKS0-2 supports a number of clock division ratios. At the time the watchdog
#define WTCSR_CKS_4 0x01 * is enabled, it defaults to a 41 usec overflow period .. we overload this to
#define WTCSR_CKS_16 0x02 * something a little more reasonable, and really can't deal with anything
#define WTCSR_CKS_32 0x03 * lower than WTCSR_CKS_1024, else we drop back into the usec range.
#define WTCSR_CKS_64 0x04 *
#define WTCSR_CKS_256 0x05 * Clock Division Ratio Overflow Period
#define WTCSR_CKS_1024 0x06 * --------------------------------------------
* 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 #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 watchdog_info sh_wdt_info;
static struct timer_list timer;
static unsigned long next_heartbeat;
/** /**
* sh_wdt_write_cnt - Write to Counter * sh_wdt_write_cnt - Write to Counter
...@@ -93,6 +121,10 @@ static void sh_wdt_write_csr(__u8 val) ...@@ -93,6 +121,10 @@ static void sh_wdt_write_csr(__u8 val)
*/ */
static void sh_wdt_start(void) 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_csr(WTCSR_WT | WTCSR_CKS_4096);
sh_wdt_write_cnt(0); sh_wdt_write_cnt(0);
sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME)); sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME));
...@@ -105,6 +137,8 @@ static void sh_wdt_start(void) ...@@ -105,6 +137,8 @@ static void sh_wdt_start(void)
*/ */
static void sh_wdt_stop(void) static void sh_wdt_stop(void)
{ {
del_timer(&timer);
sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME)); sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME));
} }
...@@ -117,8 +151,13 @@ static void sh_wdt_stop(void) ...@@ -117,8 +151,13 @@ static void sh_wdt_stop(void)
*/ */
static void sh_wdt_ping(unsigned long data) static void sh_wdt_ping(unsigned long data)
{ {
if (time_before(jiffies, next_heartbeat)) {
sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF)); sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF));
sh_wdt_write_cnt(0); 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) ...@@ -133,14 +172,12 @@ static int sh_wdt_open(struct inode *inode, struct file *file)
{ {
switch (minor(inode->i_rdev)) { switch (minor(inode->i_rdev)) {
case WATCHDOG_MINOR: case WATCHDOG_MINOR:
if (sh_is_open) { if (test_and_set_bit(0, &sh_is_open))
return -EBUSY; return -EBUSY;
}
sh_is_open = 1;
sh_wdt_start(); sh_wdt_start();
return 0; break;
default: default:
return -ENODEV; return -ENODEV;
} }
...@@ -158,17 +195,13 @@ static int sh_wdt_open(struct inode *inode, struct file *file) ...@@ -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) static int sh_wdt_close(struct inode *inode, struct file *file)
{ {
lock_kernel();
if (minor(inode->i_rdev) == WATCHDOG_MINOR) { if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
#ifndef CONFIG_WATCHDOG_NOWAYOUT #ifndef CONFIG_WATCHDOG_NOWAYOUT
sh_wdt_stop(); sh_wdt_stop();
#endif #endif
sh_is_open = 0; clear_bit(0, &sh_is_open);
} }
unlock_kernel();
return 0; return 0;
} }
...@@ -206,7 +239,7 @@ static ssize_t sh_wdt_write(struct file *file, const char *buf, ...@@ -206,7 +239,7 @@ static ssize_t sh_wdt_write(struct file *file, const char *buf,
return -ESPIPE; return -ESPIPE;
if (count) { if (count) {
sh_wdt_ping(0); next_heartbeat = user_ping_period(clock_division_ratio);
return 1; return 1;
} }
...@@ -245,7 +278,7 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file, ...@@ -245,7 +278,7 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file,
break; break;
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
sh_wdt_ping(0); next_heartbeat = user_ping_period(clock_division_ratio);
break; break;
default: default:
...@@ -336,6 +369,10 @@ static int __init sh_wdt_init(void) ...@@ -336,6 +369,10 @@ static int __init sh_wdt_init(void)
return -EINVAL; return -EINVAL;
} }
init_timer(&timer);
timer.function = sh_wdt_ping;
timer.data = 0;
return 0; return 0;
} }
...@@ -358,6 +395,8 @@ EXPORT_NO_SYMBOLS; ...@@ -358,6 +395,8 @@ EXPORT_NO_SYMBOLS;
MODULE_AUTHOR("Paul Mundt <lethal@chaoticdreams.org>"); MODULE_AUTHOR("Paul Mundt <lethal@chaoticdreams.org>");
MODULE_DESCRIPTION("SH 3/4 watchdog driver"); MODULE_DESCRIPTION("SH 3/4 watchdog driver");
MODULE_LICENSE("GPL"); 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_init(sh_wdt_init);
module_exit(sh_wdt_exit); module_exit(sh_wdt_exit);
......
...@@ -77,17 +77,6 @@ static int multicast_filter_limit = 32; ...@@ -77,17 +77,6 @@ static int multicast_filter_limit = 32;
MODULE_PARM (multicast_filter_limit, "i"); MODULE_PARM (multicast_filter_limit, "i");
MODULE_PARM_DESC (multicast_filter_limit, "8139cp maximum number of filtered multicast addresses"); 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 PFX DRV_NAME ": "
#define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ #define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \
...@@ -334,7 +323,7 @@ static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb) ...@@ -334,7 +323,7 @@ static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb)
netif_rx (skb); netif_rx (skb);
} }
static inline void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail, static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
u32 status, u32 len) u32 status, u32 len)
{ {
if (netif_msg_rx_err (cp)) if (netif_msg_rx_err (cp))
...@@ -429,8 +418,8 @@ static void cp_rx (struct cp_private *cp) ...@@ -429,8 +418,8 @@ static void cp_rx (struct cp_private *cp)
while (rx_work--) { while (rx_work--) {
u32 status, len; u32 status, len;
dma_addr_t mapping; dma_addr_t mapping;
struct sk_buff *skb, *copy_skb; struct sk_buff *skb, *new_skb;
unsigned copying_skb, buflen; unsigned buflen;
skb = cp->rx_skb[rx_tail].skb; skb = cp->rx_skb[rx_tail].skb;
if (!skb) if (!skb)
...@@ -453,43 +442,30 @@ static void cp_rx (struct cp_private *cp) ...@@ -453,43 +442,30 @@ static void cp_rx (struct cp_private *cp)
goto rx_next; goto rx_next;
} }
copying_skb = (len <= rx_copybreak);
if (netif_msg_rx_status(cp)) if (netif_msg_rx_status(cp))
printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d copying? %d\n", printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d\n",
cp->dev->name, rx_tail, status, len, cp->dev->name, rx_tail, status, len);
copying_skb);
buflen = copying_skb ? len : cp->rx_buf_sz; buflen = cp->rx_buf_sz + RX_OFFSET;
copy_skb = dev_alloc_skb (buflen + RX_OFFSET); new_skb = dev_alloc_skb (buflen);
if (!copy_skb) { if (!new_skb) {
cp->net_stats.rx_dropped++; cp->net_stats.rx_dropped++;
goto rx_next; goto rx_next;
} }
skb_reserve(copy_skb, RX_OFFSET); skb_reserve(new_skb, RX_OFFSET);
copy_skb->dev = cp->dev; new_skb->dev = cp->dev;
if (!copying_skb) {
pci_unmap_single(cp->pdev, mapping, pci_unmap_single(cp->pdev, mapping,
buflen, PCI_DMA_FROMDEVICE); buflen, PCI_DMA_FROMDEVICE);
skb->ip_summed = CHECKSUM_NONE; skb->ip_summed = CHECKSUM_NONE;
skb_trim(skb, len); skb_put(skb, len);
mapping = mapping =
cp->rx_skb[rx_tail].mapping = cp->rx_skb[rx_tail].mapping =
pci_map_single(cp->pdev, copy_skb->data, pci_map_single(cp->pdev, new_skb->tail,
buflen, PCI_DMA_FROMDEVICE); buflen, PCI_DMA_FROMDEVICE);
cp->rx_skb[rx_tail].skb = copy_skb; cp->rx_skb[rx_tail].skb = new_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;
}
cp_rx_skb(cp, skb); cp_rx_skb(cp, skb);
...@@ -884,10 +860,9 @@ static int cp_refill_rx (struct cp_private *cp) ...@@ -884,10 +860,9 @@ static int cp_refill_rx (struct cp_private *cp)
skb->dev = cp->dev; skb->dev = cp->dev;
skb_reserve(skb, RX_OFFSET); skb_reserve(skb, RX_OFFSET);
skb_put(skb, cp->rx_buf_sz);
cp->rx_skb[i].mapping = pci_map_single(cp->pdev, 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].skb = skb;
cp->rx_skb[i].frag = 0; cp->rx_skb[i].frag = 0;
...@@ -1046,6 +1021,9 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1046,6 +1021,9 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
struct cp_private *cp = dev->priv; struct cp_private *cp = dev->priv;
int rc = 0; int rc = 0;
if (!netif_running(dev))
return -EINVAL;
switch (cmd) { switch (cmd) {
case SIOCETHTOOL: case SIOCETHTOOL:
return cp_ethtool_ioctl(cp, (void *) rq->ifr_data); return cp_ethtool_ioctl(cp, (void *) rq->ifr_data);
......
...@@ -2301,6 +2301,9 @@ static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2301,6 +2301,9 @@ static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
int rc = 0; int rc = 0;
int phy = tp->phys[0] & 0x3f; int phy = tp->phys[0] & 0x3f;
if (!netif_running(dev))
return -EINVAL;
if (cmd != SIOCETHTOOL) { if (cmd != SIOCETHTOOL) {
/* With SIOCETHTOOL, this would corrupt the pointer. */ /* With SIOCETHTOOL, this would corrupt the pointer. */
data->phy_id &= 0x1f; data->phy_id &= 0x1f;
......
...@@ -17,7 +17,7 @@ O_TARGET := net.o ...@@ -17,7 +17,7 @@ O_TARGET := net.o
export-objs := 8390.o arlan.o aironet4500_core.o aironet4500_card.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 \ 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 list-multi := rcpci.o
rcpci-objs := rcpci45.o rclanmtl.o rcpci-objs := rcpci45.o rclanmtl.o
......
...@@ -537,7 +537,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); ...@@ -537,7 +537,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
dev->dev_addr[i*2+1] = eeprom_buff[i] >> 8; dev->dev_addr[i*2+1] = eeprom_buff[i] >> 8;
} }
if (net_debug > 1) 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); dev->name, lp->adapter_cnf);
} }
...@@ -582,8 +582,8 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); ...@@ -582,8 +582,8 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
i = lp->isa_config & INT_NO_MASK; i = lp->isa_config & INT_NO_MASK;
if (lp->chip_type == CS8900) { if (lp->chip_type == CS8900) {
/* Translate the IRQ using the IRQ mapping table. */ /* Translate the IRQ using the IRQ mapping table. */
if (i > sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0])) if (i >= sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
printk("\ncs89x0: bug: isa_config is %d\n", i); printk("\ncs89x0: invalid ISA interrupt number %d\n", i);
else else
i = cs8900_irq_map[i]; i = cs8900_irq_map[i];
......
...@@ -1769,7 +1769,7 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1769,7 +1769,7 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
case SIOCSMIIREG: /* Write MII PHY register. */ case SIOCSMIIREG: /* Write MII PHY register. */
case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */
if (!suser()) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
return 0; return 0;
......
/*
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);
...@@ -16,11 +16,16 @@ ...@@ -16,11 +16,16 @@
Support and updates available at Support and updates available at
http://www.scyld.com/network/sundance.html 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_NAME "sundance"
#define DRV_VERSION "1.01" #define DRV_VERSION "1.01a"
#define DRV_RELDATE "4/09/00" #define DRV_RELDATE "11-Nov-2001"
/* The user-configurable values. /* The user-configurable values.
...@@ -443,7 +448,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, ...@@ -443,7 +448,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
int irq; int irq;
int i; int i;
long ioaddr; long ioaddr;
u16 mii_reg0; u16 mii_ctl;
void *ring_space; void *ring_space;
dma_addr_t ring_dma; dma_addr_t ring_dma;
...@@ -582,15 +587,15 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, ...@@ -582,15 +587,15 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
} }
} }
/* Reset PHY */ /* Reset PHY */
mdio_write (dev, np->phys[0], 0, 0x8000); mdio_write (dev, np->phys[0], MII_BMCR, BMCR_RESET);
mdelay (300); 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 */ /* Force media type */
if (!np->an_enable) { if (!np->an_enable) {
mii_reg0 = 0; mii_ctl = 0;
mii_reg0 |= (np->speed == 100) ? 0x2000 : 0; mii_ctl |= (np->speed == 100) ? BMCR_SPEED100 : 0;
mii_reg0 |= (np->full_duplex) ? 0x0100 : 0; mii_ctl |= (np->full_duplex) ? BMCR_FULLDPLX : 0;
mdio_write (dev, np->phys[0], 0, mii_reg0); mdio_write (dev, np->phys[0], MII_BMCR, mii_ctl);
printk (KERN_INFO "Override speed=%d, %s duplex\n", printk (KERN_INFO "Override speed=%d, %s duplex\n",
np->speed, np->full_duplex ? "Full" : "Half"); np->speed, np->full_duplex ? "Full" : "Half");
...@@ -798,12 +803,12 @@ static void check_duplex(struct net_device *dev) ...@@ -798,12 +803,12 @@ static void check_duplex(struct net_device *dev)
{ {
struct netdev_private *np = dev->priv; struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr; long ioaddr = dev->base_addr;
int mii_reg5 = mdio_read(dev, np->phys[0], 5); int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
int negotiated = mii_reg5 & np->advertising; int negotiated = mii_lpa & np->advertising;
int duplex; int duplex;
/* Force media */ /* Force media */
if (!np->an_enable || mii_reg5 == 0xffff) { if (!np->an_enable || mii_lpa == 0xffff) {
if (np->full_duplex) if (np->full_duplex)
writew (readw (ioaddr + MACCtrl0) | EnbFullDuplex, writew (readw (ioaddr + MACCtrl0) | EnbFullDuplex,
ioaddr + MACCtrl0); ioaddr + MACCtrl0);
...@@ -1184,7 +1189,7 @@ static void netdev_error(struct net_device *dev, int intr_status) ...@@ -1184,7 +1189,7 @@ static void netdev_error(struct net_device *dev, int intr_status)
{ {
long ioaddr = dev->base_addr; long ioaddr = dev->base_addr;
struct netdev_private *np = dev->priv; struct netdev_private *np = dev->priv;
u16 mii_reg0, mii_reg4, mii_reg5; u16 mii_ctl, mii_advertise, mii_lpa;
int speed; int speed;
if (intr_status & IntrDrvRqst) { if (intr_status & IntrDrvRqst) {
...@@ -1200,27 +1205,27 @@ static void netdev_error(struct net_device *dev, int intr_status) ...@@ -1200,27 +1205,27 @@ static void netdev_error(struct net_device *dev, int intr_status)
} }
if (intr_status & LinkChange) { if (intr_status & LinkChange) {
if (np->an_enable) { if (np->an_enable) {
mii_reg4 = mdio_read (dev, np->phys[0], 4); mii_advertise = mdio_read (dev, np->phys[0], MII_ADVERTISE);
mii_reg5= mdio_read (dev, np->phys[0], 5); mii_lpa= mdio_read (dev, np->phys[0], MII_LPA);
mii_reg4 &= mii_reg5; mii_advertise &= mii_lpa;
printk (KERN_INFO "%s: Link changed: ", dev->name); printk (KERN_INFO "%s: Link changed: ", dev->name);
if (mii_reg4 & 0x0100) if (mii_advertise & ADVERTISE_100FULL)
printk ("100Mbps, full duplex\n"); printk ("100Mbps, full duplex\n");
else if (mii_reg4 & 0x0080) else if (mii_advertise & ADVERTISE_100HALF)
printk ("100Mbps, half duplex\n"); printk ("100Mbps, half duplex\n");
else if (mii_reg4 & 0x0040) else if (mii_advertise & ADVERTISE_10FULL)
printk ("10Mbps, full duplex\n"); printk ("10Mbps, full duplex\n");
else if (mii_reg4 & 0x0020) else if (mii_advertise & ADVERTISE_10HALF)
printk ("10Mbps, half duplex\n"); printk ("10Mbps, half duplex\n");
else else
printk ("\n"); printk ("\n");
} else { } else {
mii_reg0 = mdio_read (dev, np->phys[0], 0); mii_ctl = mdio_read (dev, np->phys[0], MII_BMCR);
speed = (mii_reg0 & 0x2000) ? 100 : 10; speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
printk (KERN_INFO "%s: Link changed: %dMbps ,", printk (KERN_INFO "%s: Link changed: %dMbps ,",
dev->name, speed); dev->name, speed);
printk ("%s duplex.\n", (mii_reg0 & 0x0100) ? printk ("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ?
"full" : "half"); "full" : "half");
} }
check_duplex (dev); check_duplex (dev);
......
...@@ -1358,7 +1358,7 @@ static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value) ...@@ -1358,7 +1358,7 @@ static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value)
static int via_mixer_open (struct inode *inode, struct file *file) 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 via_info *card;
struct pci_dev *pdev; struct pci_dev *pdev;
struct pci_driver *drvr; struct pci_driver *drvr;
...@@ -2974,7 +2974,7 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file, ...@@ -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) 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 via_info *card;
struct pci_dev *pdev; struct pci_dev *pdev;
struct via_channel *chan; struct via_channel *chan;
......
...@@ -413,6 +413,7 @@ static struct display disp; ...@@ -413,6 +413,7 @@ static struct display disp;
static struct clgenfb_info boards[MAX_NUM_BOARDS]; /* the boards */ static struct clgenfb_info boards[MAX_NUM_BOARDS]; /* the boards */
static unsigned clgen_def_mode = 1; static unsigned clgen_def_mode = 1;
static int noaccel = 0;
static int release_io_ports = 0; static int release_io_ports = 0;
...@@ -1405,7 +1406,9 @@ static void clgen_set_par (const void *par, struct fb_info_gen *info) ...@@ -1405,7 +1406,9 @@ static void clgen_set_par (const void *par, struct fb_info_gen *info)
break; break;
case BT_PICASSO4: case BT_PICASSO4:
#ifdef CONFIG_ZORRO
vga_wseq (fb_info->regs, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */ vga_wseq (fb_info->regs, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */
#endif
/* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */ /* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
break; break;
...@@ -2748,6 +2751,23 @@ int __init clgenfb_init(void) ...@@ -2748,6 +2751,23 @@ int __init clgenfb_init(void)
DPRINTK ("clgen: (RAM start set to: 0x%p)\n", fb_info->fbmem); 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); init_vgachip (fb_info);
/* set up a few more things, register framebuffer driver etc */ /* set up a few more things, register framebuffer driver etc */
...@@ -2851,6 +2871,8 @@ int __init clgenfb_setup(char *options) { ...@@ -2851,6 +2871,8 @@ int __init clgenfb_setup(char *options) {
if (strcmp (this_opt, s) == 0) if (strcmp (this_opt, s) == 0)
clgen_def_mode = i; clgen_def_mode = i;
} }
if (!strcmp(this_opt, "noaccel"))
noaccel = 1;
} }
return 0; return 0;
} }
......
...@@ -105,9 +105,11 @@ struct inode *driverfs_get_inode(struct super_block *sb, int mode, int dev) ...@@ -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) 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); 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); d_instantiate(dentry, inode);
dget(dentry); dget(dentry);
error = 0; error = 0;
...@@ -239,18 +241,14 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos) ...@@ -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__); DBG("%s: file entry is NULL\n",__FUNCTION__);
return -ENOENT; return -ENOENT;
} }
if (!entry->show)
return 0;
dev = list_entry(entry->parent,struct device, dir); dev = list_entry(entry->parent,struct device, dir);
get_device(dev);
if (!entry->show)
goto done;
page = (unsigned char*)__get_free_page(GFP_KERNEL); page = (unsigned char*)__get_free_page(GFP_KERNEL);
if (!page) { if (!page)
retval = -ENOMEM; return -ENOMEM;
goto done;
}
while (count > 0) { while (count > 0) {
ssize_t len; ssize_t len;
...@@ -274,9 +272,6 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos) ...@@ -274,9 +272,6 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
retval += len; retval += len;
} }
free_page((unsigned long)page); free_page((unsigned long)page);
done:
put_device(dev);
return retval; return retval;
} }
...@@ -305,12 +300,10 @@ driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *pp ...@@ -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__); DBG("%s: file entry is NULL\n",__FUNCTION__);
return -ENOENT; return -ENOENT;
} }
if (!entry->store)
return 0;
dev = list_entry(entry->parent,struct device, dir); dev = list_entry(entry->parent,struct device, dir);
get_device(dev);
if (!entry->store)
goto done;
while (count > 0) { while (count > 0) {
ssize_t len; ssize_t len;
...@@ -327,8 +320,6 @@ driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *pp ...@@ -327,8 +320,6 @@ driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *pp
*ppos += len; *ppos += len;
buf += len; buf += len;
} }
done:
put_device(dev);
return retval; return retval;
} }
...@@ -358,9 +349,28 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig) ...@@ -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) static int driverfs_open_file(struct inode * inode, struct file * filp)
{ {
if (filp && inode) struct driver_file_entry * entry;
filp->private_data = inode->u.generic_ip; 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; return 0;
} }
...@@ -392,6 +402,7 @@ static struct file_operations driverfs_file_operations = { ...@@ -392,6 +402,7 @@ static struct file_operations driverfs_file_operations = {
llseek: driverfs_file_lseek, llseek: driverfs_file_lseek,
mmap: generic_file_mmap, mmap: generic_file_mmap,
open: driverfs_open_file, open: driverfs_open_file,
flush: driverfs_flush,
fsync: driverfs_sync_file, fsync: driverfs_sync_file,
}; };
...@@ -623,13 +634,13 @@ driverfs_create_file(struct driver_file_entry * entry, ...@@ -623,13 +634,13 @@ driverfs_create_file(struct driver_file_entry * entry,
dentry = lookup_hash(&qstr,parent_dentry); dentry = lookup_hash(&qstr,parent_dentry);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
else else {
dentry->d_fsdata = (void *)entry;
error = vfs_create(parent_dentry->d_inode,dentry,entry->mode); error = vfs_create(parent_dentry->d_inode,dentry,entry->mode);
}
/* Still good? Ok, then fill in the blanks: */ /* Still good? Ok, then fill in the blanks: */
if (!error) { if (!error) {
dentry->d_fsdata = (void *)entry;
dentry->d_inode->u.generic_ip = (void *)entry; dentry->d_inode->u.generic_ip = (void *)entry;
entry->dentry = dentry; entry->dentry = dentry;
......
...@@ -185,4 +185,28 @@ static __inline__ void ...@@ -185,4 +185,28 @@ static __inline__ void
enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu) 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 */ #endif /* __ASM_SH_MMU_CONTEXT_H */
...@@ -236,6 +236,19 @@ static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | ...@@ -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_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; } 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, * Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to. * and a page entry and page directory to the page they refer to.
......
...@@ -184,19 +184,23 @@ extern void save_fpu(struct task_struct *__tsk); ...@@ -184,19 +184,23 @@ extern void save_fpu(struct task_struct *__tsk);
#define unlazy_fpu(tsk) do { \ #define unlazy_fpu(tsk) do { \
if ((tsk)->flags & PF_USEDFPU) { \ if ((tsk)->flags & PF_USEDFPU) { \
grab_fpu(); \
save_fpu(tsk); \ save_fpu(tsk); \
} \ } \
} while (0) } while (0)
#define clear_fpu(tsk) do { \ #define clear_fpu(tsk) do { \
if ((tsk)->flags & PF_USEDFPU) \ if ((tsk)->flags & PF_USEDFPU) { \
(tsk)->flags &= ~PF_USEDFPU; \ (tsk)->flags &= ~PF_USEDFPU; \
release_fpu(); \
} \
} while (0) } while (0)
/* Double presision, NANS as NANS, rounding to nearest, no exceptions */ /* Double presision, NANS as NANS, rounding to nearest, no exceptions */
#define FPSCR_INIT 0x00080000 #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. * Return saved PC of a blocked thread.
*/ */
......
...@@ -2,7 +2,11 @@ ...@@ -2,7 +2,11 @@
#define __ASM_SH_SCATTERLIST_H #define __ASM_SH_SCATTERLIST_H
struct scatterlist { 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; unsigned int length;
}; };
......
...@@ -70,6 +70,8 @@ ...@@ -70,6 +70,8 @@
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */ #define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ #define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
ADVERTISE_CSMA)
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ #define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
ADVERTISE_100HALF | ADVERTISE_100FULL) ADVERTISE_100HALF | ADVERTISE_100FULL)
...@@ -101,6 +103,27 @@ ...@@ -101,6 +103,27 @@
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */ #define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
#define NWAYTEST_RESV2 0xfe00 /* Unused... */ #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 */ /* This structure is used in all SIOCxMIIxxx ioctl calls */
struct mii_ioctl_data { struct mii_ioctl_data {
u16 phy_id; u16 phy_id;
......
...@@ -6,6 +6,8 @@ bool 'System V IPC' CONFIG_SYSVIPC ...@@ -6,6 +6,8 @@ bool 'System V IPC' CONFIG_SYSVIPC
bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
bool 'Sysctl support' CONFIG_SYSCTL bool 'Sysctl support' CONFIG_SYSCTL
endmenu
mainmenu_option next_comment mainmenu_option next_comment
comment 'Code maturity level options' comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
...@@ -19,5 +21,3 @@ if [ "$CONFIG_MODULES" = "y" ]; then ...@@ -19,5 +21,3 @@ if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Kernel module loader' CONFIG_KMOD bool ' Kernel module loader' CONFIG_KMOD
fi fi
endmenu endmenu
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment