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
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
......
......@@ -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();
......
......@@ -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
......@@ -623,66 +616,12 @@ restore_all:
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,60 +671,20 @@ 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
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
/* 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 */
/* User space to kernel */
mov #0x20, k1
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
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
......@@ -807,7 +706,7 @@ handle_exception:
mov.l r8, @-r15
!
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
and k1, r8 ! ...
ldc r8, sr ! ...changed here.
......@@ -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
......
......@@ -18,6 +18,10 @@
#include <asm/processor.h>
#include <asm/io.h>
/*
* Save FPU registers onto task structure.
* Assume called with FPU enabled (SR.FD=0).
*/
void
save_fpu(struct task_struct *tsk)
{
......@@ -118,7 +122,8 @@ restore_fpu(struct task_struct *tsk)
* double precission represents signaling NANS.
*/
void fpu_init(void)
static void
fpu_init(void)
{
asm volatile("lds %0, fpul\n\t"
"lds %1, fpscr\n\t"
......@@ -160,123 +165,143 @@ void fpu_init(void)
: "r" (0), "r" (FPSCR_INIT));
}
asmlinkage void
do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7,
struct pt_regs regs)
/**
* 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)
{
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();
save_fpu(tsk);
tsk->thread.trap_no = 11;
tsk->thread.error_code = 0;
force_sig(SIGFPE, tsk);
fpu->fp_regs[n] = du;
fpu->fp_regs[n+1] = dl;
}
}
asmlinkage 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;
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
/**
* ieee_fpe_handler - Handle denormalized number exception
*
* 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.
* @regs: Pointer to register structure
*
* Returns 1 when it's handled (should not cause exception).
*/
release_fpu();
return;
}
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();
if (tsk->used_math) {
/* Using the FPU again. */
restore_fpu(tsk);
tsk->flags |= PF_USEDFPU;
} else {
/* First time FPU user. */
fpu_init();
tsk->used_math = 1;
tsk->thread.trap_no = 11;
tsk->thread.error_code = 0;
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
fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6,
unsigned long r7, struct pt_regs regs)
do_fpu_error(unsigned long r4, 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();
}
}
struct task_struct *tsk = current;
if (ieee_fpe_handler (&regs))
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();
}
}
regs.pc += 2;
save_fpu(tsk);
tsk->thread.trap_no = 11;
tsk->thread.error_code = 0;
force_sig(SIGFPE, tsk);
}
/* Short cut for the FPU exception */
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;
if (tsk != &init_task)
unlazy_fpu(tsk);
grab_fpu();
if (!user_mode(&regs)) {
printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
return;
}
tsk = &init_task;
if (tsk->used_math) {
/* Using the FPU again. */
restore_fpu(tsk);
......
......@@ -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
......@@ -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>
......
......@@ -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())
......
......@@ -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);
}
......@@ -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);
}
/*
......
......@@ -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>
......
......@@ -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;
}
......
......@@ -207,8 +207,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
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);
......
......@@ -19,7 +19,6 @@
#include <linux/watchdog.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
#include <linux/smp_lock.h>
#include <linux/ioport.h>
#include <asm/io.h>
......@@ -47,18 +46,47 @@
#define WTCSR_CKS1 0x02
#define WTCSR_CKS0 0x01
#define WTCSR_CKS 0x07
#define WTCSR_CKS_1 0x00
#define WTCSR_CKS_4 0x01
#define WTCSR_CKS_16 0x02
#define WTCSR_CKS_32 0x03
#define WTCSR_CKS_64 0x04
#define WTCSR_CKS_256 0x05
#define WTCSR_CKS_1024 0x06
/*
* CKS0-2 supports a number of clock division ratios. At the time the watchdog
* is enabled, it defaults to a 41 usec overflow period .. we overload this to
* something a little more reasonable, and really can't deal with anything
* lower than WTCSR_CKS_1024, else we drop back into the usec range.
*
* Clock Division Ratio Overflow Period
* --------------------------------------------
* 1/32 (initial value) 41 usecs
* 1/64 82 usecs
* 1/128 164 usecs
* 1/256 328 usecs
* 1/512 656 usecs
* 1/1024 1.31 msecs
* 1/2048 2.62 msecs
* 1/4096 5.25 msecs
*/
#define WTCSR_CKS_32 0x00
#define WTCSR_CKS_64 0x01
#define WTCSR_CKS_128 0x02
#define WTCSR_CKS_256 0x03
#define WTCSR_CKS_512 0x04
#define WTCSR_CKS_1024 0x05
#define WTCSR_CKS_2048 0x06
#define WTCSR_CKS_4096 0x07
static int sh_is_open = 0;
/*
* Default clock division ratio is 5.25 msecs. Overload this at module load
* time. Any value not in the msec range will default to a timeout of one
* jiffy, which exceeds the usec overflow periods.
*/
static int clock_division_ratio = WTCSR_CKS_4096;
#define msecs_to_jiffies(msecs) (jiffies + ((HZ * msecs + 999) / 1000))
#define next_ping_period(cks) msecs_to_jiffies(cks - 4)
#define user_ping_period(cks) (next_ping_period(cks) * 10)
static unsigned long sh_is_open = 0;
static struct watchdog_info sh_wdt_info;
static struct timer_list timer;
static unsigned long next_heartbeat;
/**
* sh_wdt_write_cnt - Write to Counter
......@@ -93,6 +121,10 @@ static void sh_wdt_write_csr(__u8 val)
*/
static void sh_wdt_start(void)
{
timer.expires = next_ping_period(clock_division_ratio);
next_heartbeat = user_ping_period(clock_division_ratio);
add_timer(&timer);
sh_wdt_write_csr(WTCSR_WT | WTCSR_CKS_4096);
sh_wdt_write_cnt(0);
sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME));
......@@ -105,6 +137,8 @@ static void sh_wdt_start(void)
*/
static void sh_wdt_stop(void)
{
del_timer(&timer);
sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME));
}
......@@ -117,8 +151,13 @@ static void sh_wdt_stop(void)
*/
static void sh_wdt_ping(unsigned long data)
{
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);
......
......@@ -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,7 +323,7 @@ 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,
static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
u32 status, u32 len)
{
if (netif_msg_rx_err (cp))
......@@ -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;
skb_reserve(new_skb, RX_OFFSET);
new_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);
skb_put(skb, len);
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);
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;
}
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);
......
......@@ -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;
......
......@@ -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
......
......@@ -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];
......
......@@ -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;
......
/*
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 @@
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);
......
......@@ -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)
{
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;
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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 */
......@@ -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.
......
......@@ -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.
*/
......
......@@ -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;
};
......
......@@ -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)
......@@ -101,6 +103,27 @@
#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;
......
......@@ -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
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