diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-08-08 18:54:49 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-08-08 18:54:49 +0000 |
commit | 5514f4babeeb3af00ee0c325e3cda7a562cc3d65 (patch) | |
tree | edd733879cab73e41324a99ca5da7bc154c4196d | |
parent | 6a9366db547e958e8c9bf8e1c13bcea6cb2bf393 (diff) |
Merge with Linux 2.4.0-test6-pre4.
178 files changed, 3571 insertions, 1862 deletions
@@ -1816,6 +1816,10 @@ S: Reinholdstrasse 14 S: D-37083 Goettingen S: Germany +N: Thomas Molina +E: tmolina@home.com +D: bug fixes, documentation, minor hackery + N: David Mosberger-Tang E: davidm@hpl.hp.com if IA-64 related, else David.Mosberger@acm.org D: Linux/Alpha and Linux/ia64 diff --git a/Documentation/Configure.help b/Documentation/Configure.help index b94126f2c..585a2b83b 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -16445,6 +16445,19 @@ CONFIG_BVME6000_SCC boards from BVM Ltd. Everyone using one of these boards should say Y here. +7-Segment Display support +CONFIG_DISPLAY7SEG + This is the driver for the 7-segment display and LED present on + Sun Microsystems CompactPCI models CP1400 and CP1500. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called display7seg.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. + + If you do not have a CompactPCI model CP1400 or CP1500, or + another UltraSPARC-IIi-cEngine boardset with a 7-segment display, + you should say N to this option. # # A couple of things I keep forgetting: diff --git a/Documentation/kbuild/config-language.txt b/Documentation/kbuild/config-language.txt index dc1756013..d139848da 100644 --- a/Documentation/kbuild/config-language.txt +++ b/Documentation/kbuild/config-language.txt @@ -291,6 +291,7 @@ Example: This verb displays /prompt/ to the user, accepts a value from the user, and assigns that value to /symbol/. /word/ is the default value. Legal input values are any ASCII string, except for the characters '"' and '\\'. +Configure will trap an input string of "?" to display help. The default value is mandatory. @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -test6-pre3 +EXTRAVERSION = -test6-pre4 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 078aa7d3d..4ac2e8b0d 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -199,9 +199,6 @@ EXPORT_SYMBOL(debug_spin_trylock); EXPORT_SYMBOL(write_lock); EXPORT_SYMBOL(read_lock); #endif -#else /* CONFIG_SMP */ -EXPORT_SYMBOL(__local_bh_count); -EXPORT_SYMBOL(__local_irq_count); #endif /* CONFIG_SMP */ EXPORT_SYMBOL(rtc_lock); diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 253b8d6c1..ac80051ed 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -577,10 +577,10 @@ entSys: ret_from_sys_call: cmovne $26,0,$19 /* $19 = 0 => non-restartable */ ldl $3,TASK_PROCESSOR($8) - lda $4,softirq_state + lda $4,irq_stat /* softirq_active */ sll $3,L1_CACHE_SHIFT,$3 addq $3,$4,$4 - ldq $4,0($4) + ldq $4,0($4) /* softirq_active[32] + softirq_mask[32] */ sll $4,32,$3 and $4,$3,$4 bne $4,handle_softirq diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c index 066af7e1e..59f102496 100644 --- a/arch/alpha/kernel/irq_alpha.c +++ b/arch/alpha/kernel/irq_alpha.c @@ -14,11 +14,7 @@ #include "proto.h" #include "irq_impl.h" -/* Only uniprocessor needs this IRQ/BH locking depth, on SMP it lives - in the per-cpu structure for cache reasons. */ #ifndef CONFIG_SMP -int __local_irq_count; -int __local_bh_count; unsigned long __irq_attempt[NR_IRQS]; #endif diff --git a/arch/alpha/kernel/irq_smp.c b/arch/alpha/kernel/irq_smp.c index 90a3c30b2..9022228a0 100644 --- a/arch/alpha/kernel/irq_smp.c +++ b/arch/alpha/kernel/irq_smp.c @@ -40,13 +40,13 @@ show(char * str, void *where) printk("\n%s, CPU %d: %p\n", str, cpu, where); printk("irq: %d [%d %d]\n", irqs_running(), - cpu_data[0].irq_count, - cpu_data[1].irq_count); + local_irq_count(0), + local_irq_count(1)); printk("bh: %d [%d %d]\n", spin_is_locked(&global_bh_lock) ? 1 : 0, - cpu_data[0].bh_count, - cpu_data[1].bh_count); + local_bh_count(0), + local_bh_count(1)); #if 0 stack = (unsigned long *) &str; for (i = 40; i ; i--) { diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index e51ff9d18..4f7a04b3f 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -108,8 +108,8 @@ smp_store_cpu_info(int cpuid) cpu_data[cpuid].loops_per_sec = loops_per_sec; cpu_data[cpuid].last_asn = (cpuid << WIDTH_HARDWARE_ASN) + ASN_FIRST_VERSION; - cpu_data[cpuid].irq_count = 0; - cpu_data[cpuid].bh_count = 0; + local_irq_count(cpuid) = 0; + local_bh_count(cpuid) = 0; } /* diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 6723291df..fc14d6c45 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -91,8 +91,6 @@ EXPORT_SYMBOL(kd_mksound); EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(udelay); -EXPORT_SYMBOL(local_bh_count); -EXPORT_SYMBOL(local_irq_count); #ifdef CONFIG_CPU_32 EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(__iounmap); diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index b4fbfe628..c260b8e19 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -9,7 +9,7 @@ #ifdef CONFIG_SMP #error SMP not supported #else - ldr \rd, __softirq_state + ldr \rd, __irq_stat #endif .endm @@ -22,7 +22,7 @@ slow_syscall_return: add sp, sp, #S_OFF ret_from_sys_call: @ external entry get_softirq r0 - ldmia r0, {r0, r1} + ldmia r0, {r0, r1} @ softirq_active, softirq_mask mov r4, #1 @ flag this as being syscall return tst r0, r1 blne SYMBOL_NAME(do_softirq) @@ -48,7 +48,7 @@ ret_reschedule: adrsvc al, lr, ret_with_reschedule @ internal .globl ret_from_exception ret_from_exception: @ external entry get_softirq r0 - ldmia r0, {r0, r1} + ldmia r0, {r0, r1} @ softirq_active, softirq_mask mov r4, #0 tst r0, r1 blne SYMBOL_NAME(do_softirq) @@ -129,9 +129,9 @@ vector_swi: save_user_regs b SYMBOL_NAME(deferred) .align 5 - .type __softirq_state, #object -__softirq_state: - .word SYMBOL_NAME(softirq_state) + .type __irq_stat, #object +__irq_stat: + .word SYMBOL_NAME(irq_stat) .type sys_call_table, #object ENTRY(sys_call_table) diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 40a47c45f..8af0c3b3f 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -46,8 +46,6 @@ */ #define MAX_IRQ_CNT 100000 -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; spinlock_t irq_controller_lock; int setup_arm_irq(int, struct irqaction *); @@ -236,7 +234,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) irq_exit(cpu, irq); - if (softirq_state[cpu].active & softirq_state[cpu].mask) + if (softirq_active(cpu) & softirq_mask(cpu)) do_softirq(); return; diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index da7fd047d..c36d01cce 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -206,11 +206,11 @@ ENTRY(ret_from_sys_call) #ifdef CONFIG_SMP movl processor(%ebx),%eax shll $5,%eax - movl SYMBOL_NAME(softirq_state)(,%eax),%ecx - testl SYMBOL_NAME(softirq_state)+4(,%eax),%ecx + movl SYMBOL_NAME(irq_stat)(,%eax),%ecx # softirq_active + testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx # softirq_mask #else - movl SYMBOL_NAME(softirq_state),%ecx - testl SYMBOL_NAME(softirq_state)+4,%ecx + movl SYMBOL_NAME(irq_stat),%ecx # softirq_active + testl SYMBOL_NAME(irq_stat)+4,%ecx # softirq_mask #endif jne handle_softirq @@ -262,11 +262,11 @@ ret_from_exception: GET_CURRENT(%ebx) movl processor(%ebx),%eax shll $5,%eax - movl SYMBOL_NAME(softirq_state)(,%eax),%ecx - testl SYMBOL_NAME(softirq_state)+4(,%eax),%ecx + movl SYMBOL_NAME(irq_stat)(,%eax),%ecx # softirq_active + testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx # softirq_mask #else - movl SYMBOL_NAME(softirq_state),%ecx - testl SYMBOL_NAME(softirq_state)+4,%ecx + movl SYMBOL_NAME(irq_stat),%ecx # softirq_active + testl SYMBOL_NAME(irq_stat)+4,%ecx # softirq_mask #endif jne handle_softirq diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 380ac4996..c11ab01f2 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -141,6 +141,4 @@ EXPORT_SYMBOL(screen_info); EXPORT_SYMBOL(get_wchan); -EXPORT_SYMBOL(irq_stat); - EXPORT_SYMBOL(rtc_lock); diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 406a30771..525f78624 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -1070,7 +1070,7 @@ static int __init nmi_irq_works(void) for (j = 0; j < smp_num_cpus; j++) { cpu = cpu_logical_map(j); - if (nmi_counter(cpu) - tmp[cpu].__nmi_counter <= 3) { + if (nmi_count(cpu) - tmp[cpu].__nmi_count <= 3) { printk(KERN_WARNING "CPU#%d NMI appears to be stuck.\n", cpu); return 0; } diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index fcc0a72f5..92ddd01f5 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -61,8 +61,6 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - /* * Controller mappings for all interrupt sources: */ @@ -160,7 +158,7 @@ int get_irq_list(char *buf) p += sprintf(p, "NMI: "); for (j = 0; j < smp_num_cpus; j++) p += sprintf(p, "%10u ", - nmi_counter(cpu_logical_map(j))); + nmi_count(cpu_logical_map(j))); p += sprintf(p, "\n"); #if CONFIG_SMP p += sprintf(p, "LOC: "); @@ -624,7 +622,7 @@ out: desc->handler->end(irq); spin_unlock(&desc->lock); - if (softirq_state[cpu].active & softirq_state[cpu].mask) + if (softirq_active(cpu) & softirq_mask(cpu)) do_softirq(); return 1; } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index eea525873..7bd8a04d0 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -459,7 +459,7 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code) unsigned char reason = inb(0x61); - ++nmi_counter(smp_processor_id()); + ++nmi_count(smp_processor_id()); if (!(reason & 0xc0)) { #if CONFIG_X86_IO_APIC /* diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 3aadb43a0..f9beac21d 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -506,7 +506,7 @@ GLOBAL_ENTRY(ia64_leave_kernel) PT_REGS_UNWIND_INFO(0) #ifdef CONFIG_SMP adds r2=IA64_TASK_PROCESSOR_OFFSET,r13 - movl r3=softirq_state + movl r3=irq_stat // softirq_active ;; ld4 r2=[r2] ;; @@ -514,10 +514,10 @@ GLOBAL_ENTRY(ia64_leave_kernel) ;; add r3=r2,r3 #else - movl r3=softirq_state + movl r3=irq_stat // softirq_active #endif ;; - ld8 r2=[r3] // r3 is guaranteed to be 8-byte aligned! + ld8 r2=[r3] // r3 (softirq_active+softirq_mask) is guaranteed to be 8-byte aligned! ;; shr r3=r2,32 ;; diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c index 7f01b667c..2e4ffe403 100644 --- a/arch/ia64/kernel/ia64_ksyms.c +++ b/arch/ia64/kernel/ia64_ksyms.c @@ -32,10 +32,6 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); -#include <asm/current.h> -#include <asm/hardirq.h> -EXPORT_SYMBOL(irq_stat); - #include <asm/processor.h> EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(kernel_thread); diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index ed7eb88fc..c913fdc3d 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -60,8 +60,6 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - /* * Controller mappings for all interrupt sources: */ @@ -162,7 +160,7 @@ int get_irq_list(char *buf) p += sprintf(p, "NMI: "); for (j = 0; j < smp_num_cpus; j++) p += sprintf(p, "%10u ", - nmi_counter(cpu_logical_map(j))); + nmi_count(cpu_logical_map(j))); p += sprintf(p, "\n"); #if defined(CONFIG_SMP) && defined(__i386__) p += sprintf(p, "LOC: "); diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index f47ff3a7a..f92c45f60 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -168,7 +168,7 @@ asmlinkage void IRQ_NAME(n); \ void atari_slow_irq_##n##_dummy (void) { \ __asm__ (__ALIGN_STR "\n" \ SYMBOL_NAME_STR(atari_slow_irq_) #n "_handler:\t" \ -" addql #1,"SYMBOL_NAME_STR(local_irq_count)"\n" \ +" addql #1,"SYMBOL_NAME_STR(irq_stat)"+8\n" /* local_irq_count */ \ SAVE_ALL_INT "\n" \ GET_CURRENT(%%d0) "\n" \ " andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \ @@ -274,7 +274,7 @@ __asm__ (__ALIGN_STR "\n" SYMBOL_NAME_STR(atari_fast_irq_handler) ": orw #0x700,%%sr /* disable all interrupts */ "SYMBOL_NAME_STR(atari_prio_irq_handler) ":\t - addql #1,"SYMBOL_NAME_STR(local_irq_count)"\n" + addql #1,"SYMBOL_NAME_STR(irq_stat)"+8\n" /* local_irq_count */ SAVE_ALL_INT "\n" GET_CURRENT(%%d0) " /* get vector number from stack frame and convert to source */ diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 5f08ef216..7cbb69d03 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -171,7 +171,7 @@ do_delayed_trace: #if 0 #if CONFIG_AMIGA SYMBOL_NAME_LABEL(ami_inthandler) - addql #1,SYMBOL_NAME(local_irq_count) + addql #1,SYMBOL_NAME(irq_stat)+8 | local_irq_count SAVE_ALL_INT GET_CURRENT(%d0) @@ -203,7 +203,7 @@ ENTRY(nmi_handler) SYMBOL_NAME_LABEL(inthandler) SAVE_ALL_INT GET_CURRENT(%d0) - addql #1,SYMBOL_NAME(local_irq_count) + addql #1,SYMBOL_NAME(irq_stat)+8 | local_irq_count | put exception # in d0 bfextu %sp@(PT_VECTOR){#4,#10},%d0 @@ -222,7 +222,7 @@ SYMBOL_NAME_LABEL(inthandler) 3: addql #8,%sp | pop parameters off stack SYMBOL_NAME_LABEL(ret_from_interrupt) - subql #1,SYMBOL_NAME(local_irq_count) + subql #1,SYMBOL_NAME(irq_stat)+8 | local_irq_count jeq 1f 2: RESTORE_ALL @@ -236,8 +236,8 @@ SYMBOL_NAME_LABEL(ret_from_interrupt) #endif /* check if we need to do software interrupts */ - movel SYMBOL_NAME(softirq_state),%d0 - andl SYMBOL_NAME(softirq_state)+4,%d0 + movel SYMBOL_NAME(irq_stat),%d0 | softirq_active + andl SYMBOL_NAME(irq_stat)+4,%d0 | softirq_mask jeq SYMBOL_NAME(ret_from_exception) pea SYMBOL_NAME(ret_from_exception) diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 9dc6427e6..74e1e4c1e 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -57,10 +57,6 @@ volatile unsigned int num_spurious; #define NUM_IRQ_NODES 100 static irq_node_t nodes[NUM_IRQ_NODES]; -unsigned int local_irq_count[NR_CPUS]; - -unsigned int local_bh_count[NR_CPUS]; - static void dummy_enable_irq(unsigned int irq); static void dummy_disable_irq(unsigned int irq); static int dummy_request_irq(unsigned int irq, diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 6f8300422..7bf46149f 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -52,8 +52,6 @@ EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(local_irq_count); -EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_thread); diff --git a/arch/mips/baget/irq.c b/arch/mips/baget/irq.c index 08b15a7a8..03d68ee17 100644 --- a/arch/mips/baget/irq.c +++ b/arch/mips/baget/irq.c @@ -29,7 +29,6 @@ #include <asm/baget/baget.h> -irq_cpustat_t irq_stat [NR_CPUS]; unsigned long spurious_count = 0; /* diff --git a/arch/mips/dec/irq.c b/arch/mips/dec/irq.c index 7551ae681..91e1ce463 100644 --- a/arch/mips/dec/irq.c +++ b/arch/mips/dec/irq.c @@ -31,10 +31,6 @@ extern volatile unsigned int *isr; /* address of the interrupt status register extern volatile unsigned int *imr; /* address of the interrupt mask register */ extern decint_t dec_interrupt[NR_INTS]; -irq_cpustat_t irq_stat [NR_CPUS]; - -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; static inline void mask_irq(unsigned int irq_nr) diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index bde21011f..bc56db51b 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -43,8 +43,8 @@ reschedule: jal schedule EXPORT(ret_from_sys_call) EXPORT(ret_from_irq) .type ret_from_irq,@function - lw t0, softirq_state - lw t1, softirq_state+4 # unused delay slot + lw t0, irq_stat # softirq_active + lw t1, irq_stat+4 # softirq_mask. unused delay slot and t0, t1 bnez t0, handle_softirq diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 54c2c3c81..fcb7a632f 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -47,8 +47,6 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - /* * This contains the irq mask for both 8259A irq controllers, it's an * int so we can deal with the third PIC in some systems like the RM300. @@ -63,8 +61,6 @@ static unsigned int cached_irq_mask = 0xffff; #define cached_21 (__byte(0,cached_irq_mask)) #define cached_A1 (__byte(1,cached_irq_mask)) -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; /* @@ -228,7 +224,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) } irq_exit(cpu); - if (softirq_state[cpu].active&softirq_state[cpu].mask) + if (softirq_active(cpu)&softirq_mask(cpu)) do_softirq(); /* unmasking and bottom half handling is done magically for us. */ diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index b58272f46..3b3c43111 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -140,4 +140,3 @@ EXPORT_SYMBOL(ide_ops); #endif EXPORT_SYMBOL(get_wchan); -EXPORT_SYMBOL(irq_stat); diff --git a/arch/mips/kernel/scall_o32.S b/arch/mips/kernel/scall_o32.S index ddf69a964..bdc72ca4e 100644 --- a/arch/mips/kernel/scall_o32.S +++ b/arch/mips/kernel/scall_o32.S @@ -65,8 +65,8 @@ stack_done: 1: sw v0, PT_R2(sp) # result EXPORT(o32_ret_from_sys_call) - lw t0, softirq_state - lw t1, softirq_state+4 # unused delay slot + lw t0, irq_stat # softirq_active + lw t1, irq_stat+4 # softirq_mask. unused delay slot and t0, t1 bnez t0, o32_handle_softirq diff --git a/arch/mips/orion/irq.c b/arch/mips/orion/irq.c index f61690b85..1721b47ae 100644 --- a/arch/mips/orion/irq.c +++ b/arch/mips/orion/irq.c @@ -25,9 +25,6 @@ void (*board_time_init)(struct irqaction *irq); extern asmlinkage void orionIRQ(void); -irq_cpustat_t irq_stat [NR_CPUS]; -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; irq_desc_t irq_desc[NR_IRQS]; @@ -186,7 +183,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) irq_exit(cpu); - if (softirq_state[cpu].active&softirq_state[cpu].mask) + if (softirq_active(cpu)&softirq_mask(cpu)) do_softirq(); /* unmasking and bottom half handling is done magically for us. */ diff --git a/arch/mips/orion/misc.c b/arch/mips/orion/misc.c index 1c6d9e2fa..0d8881058 100644 --- a/arch/mips/orion/misc.c +++ b/arch/mips/orion/misc.c @@ -35,10 +35,8 @@ #include <asm/stackframe.h> #include <asm/system.h> #include <asm/cpu.h> -#include <linux/sched.h> #include <linux/bootmem.h> #include <asm/addrspace.h> -#include <asm/bootinfo.h> #include <asm/mc146818rtc.h> char arcs_cmdline[CL_SIZE] = {0, }; diff --git a/arch/mips/orion/setup.c b/arch/mips/orion/setup.c index 8d4cc54f0..c247d6b52 100644 --- a/arch/mips/orion/setup.c +++ b/arch/mips/orion/setup.c @@ -35,10 +35,8 @@ #include <asm/stackframe.h> #include <asm/system.h> #include <asm/cpu.h> -#include <linux/sched.h> #include <linux/bootmem.h> #include <asm/addrspace.h> -#include <asm/bootinfo.h> #include <asm/mc146818rtc.h> #include <asm/orion.h> diff --git a/arch/mips/sgi/kernel/indy_int.c b/arch/mips/sgi/kernel/indy_int.c index 06d8573cb..2e104bf79 100644 --- a/arch/mips/sgi/kernel/indy_int.c +++ b/arch/mips/sgi/kernel/indy_int.c @@ -55,8 +55,6 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - /* #define DEBUG_SGINT */ struct sgi_int2_regs *sgi_i2regs; @@ -72,8 +70,6 @@ static char lc3msk_to_irqnr[256]; extern asmlinkage void indyIRQ(void); -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; /* Local IRQ's are layed out logically like this: diff --git a/arch/mips64/kernel/entry.S b/arch/mips64/kernel/entry.S index 8f61ca7ee..ee4881448 100644 --- a/arch/mips64/kernel/entry.S +++ b/arch/mips64/kernel/entry.S @@ -35,14 +35,14 @@ reschedule: jal schedule FEXPORT(ret_from_sys_call) FEXPORT(ret_from_irq) - la t1, softirq_state + la t1, irq_stat # softirq_active #ifdef CONFIG_SMP lwu t0, TASK_PROCESSOR($28) dsll t0, t0, 5 daddu t1, t0 #endif - lw t0, 0 (t1) - lw t1, 4 (t1) # unused delay slot + lw t0, 0 (t1) # softirq_active + lw t1, 4 (t1) # softirq_mask. unused delay slot and t0, t1 bnez t0, handle_softirq 9: ld t0, PT_STATUS(sp) # returning to kernel mode? diff --git a/arch/mips64/kernel/scall_64.S b/arch/mips64/kernel/scall_64.S index a6ac27f68..2e65e1732 100644 --- a/arch/mips64/kernel/scall_64.S +++ b/arch/mips64/kernel/scall_64.S @@ -63,8 +63,8 @@ NESTED(handle_sys64, PT_SIZE, sp) 1: sd v0, PT_R2(sp) # result FEXPORT(ret_from_sys_call_64) - lw t0, softirq_state - lw t1, softirq_state+4 # unused delay slot + lw t0, irq_stat # softirq_active + lw t1, irq_stat+4 # softirq_mask. unused delay slot and t0, t1 bnez t0, handle_softirq_64 diff --git a/arch/mips64/kernel/scall_o32.S b/arch/mips64/kernel/scall_o32.S index de5b98494..a43fef7bd 100644 --- a/arch/mips64/kernel/scall_o32.S +++ b/arch/mips64/kernel/scall_o32.S @@ -76,8 +76,8 @@ stack_done: 1: sd v0, PT_R2(sp) # result FEXPORT(o32_ret_from_sys_call) - lw t0, softirq_state - lw t1, softirq_state+4 # unused delay slot + lw t0, irq_stat # softirq_active + lw t1, irq_stat+4 # softirq_mask. unused delay slot and t0, t1 bnez t0, o32_handle_softirq diff --git a/arch/mips64/sgi-ip22/ip22-int.c b/arch/mips64/sgi-ip22/ip22-int.c index 891e121f6..19c61e6dc 100644 --- a/arch/mips64/sgi-ip22/ip22-int.c +++ b/arch/mips64/sgi-ip22/ip22-int.c @@ -53,8 +53,6 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - struct sgi_int2_regs *sgi_i2regs; struct sgi_int3_regs *sgi_i3regs; struct sgi_ioc_ints *ioc_icontrol; @@ -73,8 +71,6 @@ int (*irq_cannonicalize)(int irq); extern void rs_kgdb_hook(int); #endif -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; /* Local IRQ's are layed out logically like this: diff --git a/arch/mips64/sgi-ip27/ip27-irq.c b/arch/mips64/sgi-ip27/ip27-irq.c index f5160af15..ead444bb5 100644 --- a/arch/mips64/sgi-ip27/ip27-irq.c +++ b/arch/mips64/sgi-ip27/ip27-irq.c @@ -59,16 +59,12 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - extern asmlinkage void ip27_irq(void); extern int irq_to_bus[], irq_to_slot[], bus_to_cpu[]; int (*irq_cannonicalize)(int irq); int intr_connect_level(int cpu, int bit); int intr_disconnect_level(int cpu, int bit); -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; /* diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index 8ccb0f571..d40a54cf1 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -319,16 +319,16 @@ lost_irq_ret: addi r3,r1,STACK_FRAME_OVERHEAD bl do_IRQ b 3b -1: lis r4,softirq_state@ha - addi r4,r4,softirq_state@l +1: lis r4,irq_stat@ha /* &softirq_active for cpu 0 */ + addi r4,r4,irq_stat@l #ifdef CONFIG_SMP /* get processor # */ lwz r3,PROCESSOR(r2) slwi r3,r3,5 add r4,r4,r3 #endif /* CONFIG_SMP */ - lwz r5,0(r4) - lwz r4,4(r4) + lwz r5,0(r4) /* softirq_active */ + lwz r4,4(r4) /* softirq_mask */ and. r5,r5,r4 beq+ 2f bl do_softirq diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index ee63ca902..64ef4b4dc 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -74,7 +74,6 @@ volatile unsigned char *chrp_int_ack_special; irq_desc_t irq_desc[NR_IRQS]; int ppc_spurious_interrupts = 0; -irq_cpustat_t irq_stat [NR_CPUS]; struct irqaction *ppc_irq_action[NR_IRQS]; unsigned int ppc_cached_irq_mask[NR_MASK_WORDS]; unsigned int ppc_lost_interrupts[NR_MASK_WORDS]; diff --git a/arch/ppc/kernel/local_irq.h b/arch/ppc/kernel/local_irq.h index 840b14d6f..5c616bbbd 100644 --- a/arch/ppc/kernel/local_irq.h +++ b/arch/ppc/kernel/local_irq.h @@ -15,8 +15,6 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); extern int ppc_spurious_interrupts; extern int ppc_second_irq; extern struct irqaction *ppc_irq_action[NR_IRQS]; -extern unsigned int ppc_local_bh_count[NR_CPUS]; -extern unsigned int ppc_local_irq_count[NR_CPUS]; extern unsigned int ppc_cached_irq_mask[NR_MASK_WORDS]; extern unsigned int ppc_lost_interrupts[NR_MASK_WORDS]; extern atomic_t ppc_n_lost_interrupts; diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 3f0b52ead..1317359e7 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -78,7 +78,6 @@ EXPORT_SYMBOL(do_lost_interrupts); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq_nosync); -EXPORT_SYMBOL(irq_stat); #ifdef CONFIG_SMP EXPORT_SYMBOL(kernel_flag); #endif /* CONFIG_SMP */ diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 9acccfd97..9913d5967 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -193,7 +193,6 @@ RES_DN1: */ sysc_lit: - sysc_softirq_state: .long softirq_state sysc_do_signal: .long do_signal sysc_do_softirq: .long do_softirq sysc_schedule: .long schedule @@ -237,17 +236,8 @@ sysc_return: # # check, if bottom-half has to be done # -#ifdef CONFIG_SMP - l %r1,processor(%r9) # get processor index - sll %r1,5 - al %r1,sysc_softirq_state-sysc_lit(%r13) - l %r0,0(%r1) # get softirq_state[cpu].active - n %r0,4(%r1) # and it with softirq_state[cpu].mask -#else - l %r1,sysc_softirq_state-sysc_lit(%r13) - l %r0,0(%r1) # get softirq_state.active - n %r0,4(%r1) # and it with softirq_state.mask -#endif + l %r0,__LC_IRQ_STAT # get softirq_active + n %r0,__LC_IRQ_STAT+4 # and it with softirq_mask jnz sysc_handle_bottom_half # # check, if reschedule is needed @@ -714,7 +704,6 @@ io_lit: io_do_IRQ: .long do_IRQ io_schedule: .long schedule io_do_signal: .long do_signal - io_softirq_state: .long softirq_state io_do_softirq: .long do_softirq .globl io_int_handler @@ -737,17 +726,8 @@ io_return: # # check, if bottom-half has to be done # -#ifdef CONFIG_SMP - l %r1,processor(%r9) # get processor index - sll %r1,5 - al %r1,io_softirq_state-io_lit(%r13) - l %r0,0(%r1) # get softirq_state[cpu].active - n %r0,4(%r1) # and it with softirq_state[cpu].mask -#else - l %r1,io_softirq_state-io_lit(%r13) - l %r0,0(%r1) # get softirq_state.active - n %r0,4(%r1) # and it with softirq_state.mask -#endif + l %r0,__LC_IRQ_STAT # get softirq_active + n %r0,__LC_IRQ_STAT+4 # and it with softirq_mask jnz io_handle_bottom_half io_return_bh: # diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 298aa2482..ba513325a 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -143,9 +143,9 @@ static void show(char * str) printk("\n%s, CPU %d:\n", str, cpu); printk("irq: %d [%d]\n", - atomic_read(&global_irq_count),atomic_read(&S390_lowcore.local_irq_count)); + atomic_read(&global_irq_count),local_irq_count(smp_processor_id())); printk("bh: %d [%d]\n", - atomic_read(&global_bh_count),atomic_read(&S390_lowcore.local_bh_count)); + atomic_read(&global_bh_count),local_bh_count(smp_processor_id())); stack = (unsigned long *) &str; for (i = 40; i ; i--) { unsigned long x = *++stack; @@ -181,7 +181,7 @@ static inline void wait_on_irq(int cpu) * already executing in one.. */ if (!atomic_read(&global_irq_count)) { - if (atomic_read(&safe_get_cpu_lowcore(cpu).local_bh_count)|| + if (local_bh_count(cpu)|| !atomic_read(&global_bh_count)) break; } @@ -202,7 +202,7 @@ static inline void wait_on_irq(int cpu) continue; if (atomic_read(&global_irq_lock)) continue; - if (!(atomic_read(&safe_get_cpu_lowcore(cpu).local_bh_count)) + if (!local_bh_count(cpu) && atomic_read(&global_bh_count)) continue; if (!test_and_set_bit(0,&global_irq_lock)) @@ -288,7 +288,7 @@ void __global_cli(void) if (flags & (1 << EFLAGS_I_SHIFT)) { int cpu = smp_processor_id(); __cli(); - if (!atomic_read(&S390_lowcore.local_irq_count)) + if (!in_irq()) get_irqlock(cpu); } } @@ -296,7 +296,7 @@ void __global_cli(void) void __global_sti(void) { - if (!atomic_read(&S390_lowcore.local_irq_count)) + if (!in_irq()) release_irqlock(smp_processor_id()); __sti(); } @@ -320,7 +320,7 @@ unsigned long __global_save_flags(void) retval = 2 + local_enabled; /* check for global flags if we're not in an interrupt */ - if (!atomic_read(&S390_lowcore.local_irq_count)) + if (!in_irq()) { if (local_enabled) retval = 1; diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 93d4dff76..6f6a5287b 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -64,8 +64,8 @@ int cpu_idle(void *unused) wait_psw.mask = _WAIT_PSW_MASK; wait_psw.addr = (unsigned long) &&idle_wakeup | 0x80000000L; while(1) { - if (softirq_state[smp_processor_id()].active & - softirq_state[smp_processor_id()].mask) { + if (softirq_active(smp_processor_id()) & + softirq_mask(smp_processor_id())) { do_softirq(); continue; } diff --git a/arch/s390/kernel/s390io.c b/arch/s390/kernel/s390io.c index 7a4e531d5..b1db16707 100644 --- a/arch/s390/kernel/s390io.c +++ b/arch/s390/kernel/s390io.c @@ -621,8 +621,11 @@ void s390_init_IRQ( void ) // Hopefully bh_count's will get set when we copy the prefix lowcore // structure to other CPI's ( DJB ) - atomic_set(&S390_lowcore.local_bh_count,0); - atomic_set(&S390_lowcore.local_irq_count,0); + softirq_active(smp_processor_id()) = 0; + softirq_mask(smp_processor_id()) = 0; + local_bh_count(smp_processor_id()) = 0; + local_irq_count(smp_processor_id()) = 0; + syscall_count(smp_processor_id()) = 0; asm volatile ("STCK %0" : "=m" (irq_IPL_TOD)); diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index cfc744a63..f20a9d49e 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -65,7 +65,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) address = S390_lowcore.trans_exc_code&0x7ffff000; - if (atomic_read(&S390_lowcore.local_irq_count)) + if (in_irq()) die("page fault from irq handler",regs,error_code); tsk = current; diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S index cbca87e69..450d49824 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/entry.S @@ -462,9 +462,9 @@ syscall_ret: /* fall through */ ENTRY(ret_from_syscall) - mov.l __softirq_state, $r0 + mov.l __irq_stat, $r0 ! softirq_active mov.l @$r0, $r1 - mov.l @(4,$r0), $r2 + mov.l @(4,$r0), $r2 ! softirq_mask tst $r2, $r1 bt ret_with_reschedule handle_softirq: @@ -489,8 +489,8 @@ signal_return: .align 2 __do_signal: .long SYMBOL_NAME(do_signal) -__softirq_state: - .long SYMBOL_NAME(softirq_state) +__irq_stat: + .long SYMBOL_NAME(irq_stat) __do_softirq: .long SYMBOL_NAME(do_softirq) diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 399d435af..a353b0995 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -41,9 +41,6 @@ #include <asm/hd64461.h> #endif -unsigned int __local_bh_count[NR_CPUS]; -unsigned int __local_irq_count[NR_CPUS]; - /* * Micro-access to controllers is serialized over the whole * system. We never hold this lock when we call the actual @@ -183,7 +180,7 @@ void disable_irq(unsigned int irq) { disable_irq_nosync(irq); - if (!__local_irq_count[smp_processor_id()]) { + if (!local_irq_count(smp_processor_id())) { do { barrier(); } while (irq_desc[irq].status & IRQ_INPROGRESS); @@ -319,7 +316,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, #if 0 __sti(); #endif - if (softirq_state[cpu].active&softirq_state[cpu].mask) + if (softirq_active(cpu)&softirq_mask(cpu)) do_softirq(); return 1; } diff --git a/arch/sparc/config.in b/arch/sparc/config.in index e79dfd803..570f86325 100644 --- a/arch/sparc/config.in +++ b/arch/sparc/config.in @@ -1,10 +1,11 @@ -# $Id: config.in,v 1.98 2000/07/06 01:41:29 davem Exp $ +# $Id: config.in,v 1.99 2000/08/01 04:53:58 anton Exp $ # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. # mainmenu_name "Linux/SPARC Kernel Configuration" define_bool CONFIG_UID16 y +define_bool CONFIG_HIGHMEM y mainmenu_option next_comment comment 'Code maturity level options' diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index 65e95afdb..a6fd32fa4 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -195,16 +195,9 @@ void free_irq(unsigned int irq, void *dev_id) restore_flags(flags); } -#ifndef CONFIG_SMP -unsigned int __local_bh_count; -unsigned int __local_irq_count; - -#else +#ifdef CONFIG_SMP /* SMP interrupt locking on Sparc. */ -unsigned int __local_bh_count[NR_CPUS]; -unsigned int __local_irq_count[NR_CPUS]; - /* Who has global_irq_lock. */ unsigned char global_irq_holder = NO_PROC_ID; @@ -229,14 +222,14 @@ static void show(char * str) printk("irq: %d [ ", atomic_read(&global_irq_count)); for (i = 0; i < NR_CPUS; i++) { - printk("%d ", __local_irq_count[i]); + printk("%d ", local_irq_count(i)); } printk("]\n"); printk("bh: %d [ ", (spin_is_locked(&global_bh_lock) ? 1 : 0)); for (i = 0; i < NR_CPUS; i++) { - printk("%d ", __local_bh_count[cpu]); + printk("%d ", local_bh_count(cpu)); } printk("]\n"); @@ -263,7 +256,7 @@ static inline void wait_on_irq(int cpu) * already executing in one.. */ if (!atomic_read(&global_irq_count)) { - if (__local_bh_count[cpu] || !spin_is_locked(&global_bh_lock)) + if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) break; } @@ -282,7 +275,7 @@ static inline void wait_on_irq(int cpu) continue; if (spin_is_locked (&global_irq_lock)) continue; - if (!__local_bh_count[cpu] && spin_is_locked(&global_bh_lock)) + if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) continue; if (spin_trylock(&global_irq_lock)) break; @@ -358,7 +351,7 @@ void __global_cli(void) if ((flags & PSR_PIL) != PSR_PIL) { int cpu = smp_processor_id(); __cli(); - if (!__local_irq_count[cpu]) + if (!local_irq_count(cpu)) get_irqlock(cpu); } } @@ -367,7 +360,7 @@ void __global_sti(void) { int cpu = smp_processor_id(); - if (!__local_irq_count[cpu]) + if (!local_irq_count(cpu)) release_irqlock(cpu); __sti(); } @@ -394,7 +387,7 @@ unsigned long __global_save_flags(void) retval = 2 + local_enabled; /* check for global flags if we're not in an interrupt */ - if (!__local_irq_count[smp_processor_id()]) { + if (!local_irq_count(smp_processor_id())) { if (local_enabled) retval = 1; if (global_irq_holder == (unsigned char) smp_processor_id()) diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S index dcfc2dc78..c44040bde 100644 --- a/arch/sparc/kernel/rtrap.S +++ b/arch/sparc/kernel/rtrap.S @@ -50,10 +50,10 @@ rtrap_7win_patch5: and %g1, 0x7f, %g1 ret_trap_entry: ld [%curptr + AOFF_task_processor], %l3 sll %l3, 5, %l3 - sethi %hi(C_LABEL(softirq_state)), %l4 + sethi %hi(C_LABEL(irq_stat)), %l4 ! &softirq_active add %l4, %l3, %l4 - ld [%l4 + %lo(C_LABEL(softirq_state))], %g5 - ld [%l4 + %lo(C_LABEL(softirq_state) + 4)], %g4 + ld [%l4 + %lo(C_LABEL(irq_stat))], %g5 ! softirq_active + ld [%l4 + %lo(C_LABEL(irq_stat) + 4)], %g4 ! softirq_mask andcc %g4, %g5, %g0 be C_LABEL(ret_trap_lockless_ipi) nop diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index a51995713..37c276c7f 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -146,8 +146,6 @@ EXPORT_SYMBOL(global_bh_lock); EXPORT_SYMBOL(global_irq_count); EXPORT_SYMBOL(synchronize_irq); #endif -EXPORT_SYMBOL(__local_irq_count); -EXPORT_SYMBOL(__local_bh_count); EXPORT_SYMBOL(udelay); EXPORT_SYMBOL(mstk48t02_regs); diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index 5ac1845a3..ced31b91f 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.88 2000/07/10 20:56:53 anton Exp $ +/* $Id: init.c,v 1.89 2000/08/01 04:53:58 anton Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -51,7 +51,9 @@ extern char __init_begin, __init_end, _start, _end, etext , edata; extern unsigned int sparc_ramdisk_image; extern unsigned int sparc_ramdisk_size; -unsigned long totalram_pages = 0; +unsigned long highstart_pfn, highend_pfn; +unsigned long totalram_pages; +static unsigned long totalhigh_pages; /* * BAD_PAGE is the page that is used for page faults when linux @@ -79,6 +81,21 @@ pte_t __bad_page(void) PAGE_SHARED)); } +pte_t *kmap_pte; +pgprot_t kmap_prot; + +#define kmap_get_fixed_pte(vaddr) \ + pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) + +void __init kmap_init(void) +{ + unsigned long pteval; + + /* cache the first kmap pte */ + kmap_pte = kmap_get_fixed_pte(FIX_KMAP_BEGIN); + kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE); +} + void show_mem(void) { printk("Mem-info:\n"); @@ -119,22 +136,15 @@ void __init sparc_context_init(int numctx) #define DEBUG_BOOTMEM extern unsigned long cmdline_memory_size; +extern unsigned long last_valid_pfn; -unsigned long __init bootmem_init(void) +void __init bootmem_init(void) { - unsigned long bootmap_size, start_pfn, end_pfn; + unsigned long bootmap_size, start_pfn, max_pfn; unsigned long end_of_phys_memory = 0UL; unsigned long bootmap_pfn; int i; - /* - * XXX Limit maximum memory until we implement highmem for sparc. - * The nocache region has taken up some room but I'll rearrange - * the virtual address regions soon - Anton - */ - if (!cmdline_memory_size || cmdline_memory_size > 0x0c000000) - cmdline_memory_size = 0x0c000000; - /* XXX It is a bit ambiguous here, whether we should * XXX treat the user specified mem=xxx as total wanted * XXX physical memory, or as a limit to the upper @@ -181,7 +191,16 @@ unsigned long __init bootmem_init(void) bootmap_pfn = start_pfn; - end_pfn = end_of_phys_memory >> PAGE_SHIFT; + max_pfn = end_of_phys_memory >> PAGE_SHIFT; + + max_low_pfn = max_pfn; + highstart_pfn = highend_pfn = max_pfn; + + if (max_low_pfn > (SRMMU_MAXMEM >> PAGE_SHIFT)) { + highstart_pfn = max_low_pfn = (SRMMU_MAXMEM >> PAGE_SHIFT); + printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", + (highend_pfn - highstart_pfn) >> (20-PAGE_SHIFT)); + } #ifdef CONFIG_BLK_DEV_INITRD /* Now have to check initial ramdisk, so that bootmap does not overwrite it */ @@ -205,22 +224,41 @@ unsigned long __init bootmem_init(void) #endif /* Initialize the boot-time allocator. */ #ifdef DEBUG_BOOTMEM - prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],epfn[%lx])\n", - start_pfn, bootmap_pfn, end_pfn); + prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],mlpfn[%lx])\n", + start_pfn, bootmap_pfn, max_low_pfn); #endif - bootmap_size = init_bootmem(bootmap_pfn, end_pfn); + bootmap_size = init_bootmem(bootmap_pfn, max_low_pfn); /* Now register the available physical memory with the * allocator. */ for (i = 0; sp_banks[i].num_bytes != 0; i++) { + unsigned long curr_pfn, last_pfn, size; + + curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT; + if (curr_pfn >= max_low_pfn) + break; + + last_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT; + if (last_pfn > max_low_pfn) + last_pfn = max_low_pfn; + + /* + * .. finally, did all the rounding and playing + * around just make the area go away? + */ + if (last_pfn <= curr_pfn) + continue; + + size = (last_pfn - curr_pfn) << PAGE_SHIFT; + #ifdef DEBUG_BOOTMEM prom_printf("free_bootmem: base[%lx] size[%lx]\n", sp_banks[i].base_addr, - sp_banks[i].num_bytes); + size); #endif free_bootmem(sp_banks[i].base_addr, - sp_banks[i].num_bytes); + size); } /* Reserve the kernel text/data/bss, the bootmem bitmap and initrd. */ @@ -245,10 +283,7 @@ unsigned long __init bootmem_init(void) reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base); reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size); -#ifdef DEBUG_BOOTMEM - prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn); -#endif - return end_pfn; + last_valid_pfn = max_pfn; } /* @@ -391,6 +426,25 @@ void __init free_unused_mem_map(void) #endif } +void map_high_region(unsigned long start_pfn, unsigned long end_pfn) +{ + unsigned long tmp; + +#ifdef DEBUG_HIGHMEM + printk("mapping high region %08lx - %08lx\n", start_pfn, end_pfn); +#endif + + for (tmp = start_pfn; tmp < end_pfn; tmp++) { + struct page *page = mem_map + tmp; + + ClearPageReserved(page); + set_bit(PG_highmem, &page->flags); + atomic_set(&page->count, 1); + __free_page(page); + totalhigh_pages++; + } +} + void __init mem_init(void) { int codepages = 0; @@ -401,6 +455,10 @@ void __init mem_init(void) unsigned long addr, last; #endif + highmem_start_page = mem_map + highstart_pfn; + /* cache the highmem_mapnr */ + highmem_mapnr = highstart_pfn; + /* Saves us work later. */ memset((void *)&empty_zero_page, 0, PAGE_SIZE); @@ -419,7 +477,7 @@ void __init mem_init(void) taint_real_pages(); max_mapnr = last_valid_pfn; - high_memory = __va(last_valid_pfn << PAGE_SHIFT); + high_memory = __va(max_low_pfn << PAGE_SHIFT); #ifdef DEBUG_BOOTMEM prom_printf("mem_init: Calling free_all_bootmem().\n"); @@ -430,6 +488,21 @@ void __init mem_init(void) free_unused_mem_map(); #endif + for (i = 0; sp_banks[i].num_bytes != 0; i++) { + unsigned long start_pfn = sp_banks[i].base_addr >> PAGE_SHIFT; + unsigned long end_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT; + + if (end_pfn <= highstart_pfn) + continue; + + if (start_pfn < highstart_pfn) + start_pfn = highstart_pfn; + + map_high_region(start_pfn, end_pfn); + } + + totalram_pages += totalhigh_pages; + codepages = (((unsigned long) &etext) - ((unsigned long)&_start)); codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT; datapages = (((unsigned long) &edata) - ((unsigned long)&etext)); @@ -437,11 +510,12 @@ void __init mem_init(void) initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin)); initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT; - printk("Memory: %dk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n", + printk("Memory: %dk available (%dk kernel code, %dk data, %dk init, %ldk highmem) [%08lx,%08lx]\n", nr_free_pages() << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10), initpages << (PAGE_SHIFT-10), + totalhigh_pages << (PAGE_SHIFT-10), (unsigned long)PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT)); /* NOTE NOTE NOTE NOTE @@ -501,9 +575,16 @@ void si_meminfo(struct sysinfo *val) val->sharedram = 0; val->freeram = nr_free_pages(); val->bufferram = atomic_read(&buffermem_pages); - - val->totalhigh = 0; - val->freehigh = 0; + val->totalhigh = totalhigh_pages; + val->freehigh = nr_free_highpages(); val->mem_unit = PAGE_SIZE; } + +void flush_page_to_ram(struct page *page) +{ + unsigned long vaddr; + vaddr = kmap(page); + __flush_page_to_ram(page_address(page)); + kunmap(page); +} diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 612436b47..c7f839f28 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.218 2000/07/10 23:22:32 anton Exp $ +/* $Id: srmmu.c,v 1.219 2000/08/01 04:53:58 anton Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -87,7 +87,7 @@ char *srmmu_name; ctxd_t *srmmu_ctx_table_phys; ctxd_t *srmmu_context_table; -int viking_mxcc_present = 0; +int viking_mxcc_present; spinlock_t srmmu_context_spinlock = SPIN_LOCK_UNLOCKED; int is_hypersparc; @@ -117,10 +117,6 @@ static inline int srmmu_device_memory(unsigned long x) int srmmu_cache_pagetables; /* XXX Make this dynamic based on ram size - Anton */ -#define SRMMU_NOCACHE_NPAGES 256 -#define SRMMU_NOCACHE_VADDR 0xfc000000 -#define SRMMU_NOCACHE_SIZE (SRMMU_NOCACHE_NPAGES*PAGE_SIZE) -#define SRMMU_NOCACHE_END (SRMMU_NOCACHE_VADDR + SRMMU_NOCACHE_SIZE) #define SRMMU_NOCACHE_BITMAP_SIZE (SRMMU_NOCACHE_NPAGES * 16) #define SRMMU_NOCACHE_BITMAP_SHIFT (PAGE_SHIFT - 4) @@ -1190,9 +1186,11 @@ void __init srmmu_paging_init(void) { int i, cpunode; char node_str[128]; - unsigned long end_pfn; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; - sparc_iomap.start = 0xfd000000; /* 16MB of IOSPACE on all sun4m's. */ + sparc_iomap.start = SUN4M_IOBASE_VADDR; /* 16MB of IOSPACE on all sun4m's. */ if (sparc_cpu_model == sun4d) num_contexts = 65536; /* We know it is Viking */ @@ -1215,7 +1213,7 @@ void __init srmmu_paging_init(void) prom_halt(); } - last_valid_pfn = end_pfn = bootmem_init(); + bootmem_init(); srmmu_nocache_init(); srmmu_inherit_prom_mappings(0xfe400000,(LINUX_OPPROM_ENDVM-PAGE_SIZE)); @@ -1238,6 +1236,14 @@ void __init srmmu_paging_init(void) srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END); #endif + srmmu_allocate_ptable_skeleton(FIX_KMAP_BEGIN, FIX_KMAP_END); + srmmu_allocate_ptable_skeleton(PKMAP_BASE, PKMAP_BASE_END); + + pgd = pgd_offset_k(PKMAP_BASE); + pmd = pmd_offset(pgd, PKMAP_BASE); + pte = pte_offset(pmd, PKMAP_BASE); + pkmap_page_table = pte; + flush_cache_all(); flush_tlb_all(); @@ -1253,10 +1259,13 @@ void __init srmmu_paging_init(void) sparc_context_init(num_contexts); + kmap_init(); + { unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0}; - zones_size[ZONE_DMA] = end_pfn; + zones_size[ZONE_DMA] = max_low_pfn; + zones_size[ZONE_HIGHMEM] = highend_pfn - max_low_pfn; free_area_init(zones_size); } } diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in index 95c148eee..c57f14bb1 100644 --- a/arch/sparc64/config.in +++ b/arch/sparc64/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.117 2000/07/10 20:57:35 davem Exp $ +# $Id: config.in,v 1.119 2000/08/02 10:45:03 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -67,6 +67,7 @@ source drivers/parport/Config.in dep_tristate ' Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT if [ "$CONFIG_PCI" = "y" ]; then tristate 'SUNW, envctrl support' CONFIG_ENVCTRL + tristate '7-Segment Display support' CONFIG_DISPLAY7SEG fi endmenu @@ -200,6 +201,28 @@ endmenu source drivers/fc4/Config.in +if [ "$CONFIG_PCI" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then + mainmenu_option next_comment + comment 'IEEE 1394 (FireWire) support' + + dep_tristate 'IEEE 1394 (FireWire) support (EXPERIMENTAL)' CONFIG_IEEE1394 $CONFIG_PCI + + if [ "$CONFIG_IEEE1394" != "n" ]; then + dep_tristate 'Texas Instruments PCILynx support' CONFIG_IEEE1394_PCILYNX $CONFIG_IEEE1394 + if [ "$CONFIG_IEEE1394_PCILYNX" != "n" ]; then + bool ' Use PCILynx local RAM' CONFIG_IEEE1394_PCILYNX_LOCALRAM + bool ' Support for non-IEEE1394 local ports' CONFIG_IEEE1394_PCILYNX_PORTS + fi + + dep_tristate 'OHCI (Open Host Controller Interface) support' CONFIG_IEEE1394_OHCI1394 $CONFIG_IEEE1394 + + dep_tristate 'Raw IEEE1394 I/O support' CONFIG_IEEE1394_RAWIO $CONFIG_IEEE1394 + + bool 'Excessive debugging output' CONFIG_IEEE1394_VERBOSEDEBUG + fi + endmenu +fi + if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment comment 'Network device support' diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index e013e47fb..168109d49 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -65,6 +65,7 @@ CONFIG_PARPORT_PC_FIFO=y CONFIG_PARPORT_1284=y CONFIG_PRINTER=m CONFIG_ENVCTRL=m +CONFIG_DISPLAY7SEG=m # # Console drivers @@ -323,6 +324,17 @@ CONFIG_SCSI_PLUTO=m CONFIG_SCSI_FCAL=m # +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m +CONFIG_IEEE1394_PCILYNX=m +# CONFIG_IEEE1394_PCILYNX_LOCALRAM is not set +# CONFIG_IEEE1394_PCILYNX_PORTS is not set +CONFIG_IEEE1394_OHCI1394=m +CONFIG_IEEE1394_RAWIO=m +# CONFIG_IEEE1394_VERBOSEDEBUG is not set + +# # Network device support # CONFIG_NETDEVICES=y diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index f64422a0e..5872046b1 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.47 2000/03/25 05:18:10 davem Exp $ +/* $Id: ebus.c,v 1.48 2000/08/02 06:22:35 davem Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -34,6 +34,9 @@ extern int flash_init(void); #ifdef CONFIG_ENVCTRL extern int envctrl_init(void); #endif +#ifdef CONFIG_DISPLAY7SEG +extern int d7s_init(void); +#endif static inline void *ebus_alloc(size_t size) { @@ -384,6 +387,9 @@ void __init ebus_init(void) #ifdef CONFIG_OBP_FLASH flash_init(); #endif +#ifdef CONFIG_DISPLAY7SEG + d7s_init(); +#endif clock_probe(); power_init(); } diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 3195d3e75..e95e0392e 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.117 2000/07/11 02:21:12 davem Exp $ +/* $Id: entry.S,v 1.118 2000/08/01 00:11:31 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -980,7 +980,7 @@ linux_syscall_trace: .align 32 .globl linux_sparc_syscall32 linux_sparc_syscall32: - /* Direct access to user regs, must faster. */ + /* Direct access to user regs, much faster. */ cmp %g1, NR_SYSCALLS ! IEU1 Group bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI srl %i0, 0, %o0 ! IEU0 @@ -1009,7 +1009,7 @@ linux_sparc_syscall32: .align 32 .globl linux_sparc_syscall, ret_sys_call linux_sparc_syscall: - /* Direct access to user regs, must faster. */ + /* Direct access to user regs, much faster. */ cmp %g1, NR_SYSCALLS ! IEU1 Group bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI mov %i0, %o0 ! IEU0 diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 98e209de2..d4f499726 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.93 2000/07/24 22:43:15 anton Exp $ +/* $Id: ioctl32.c,v 1.96 2000/08/02 06:22:35 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -72,7 +72,7 @@ #include <asm/envctrl.h> #include <asm/audioio.h> #include <asm/ethtool.h> - +#include <asm/display7seg.h> #include <linux/soundcard.h> #include <linux/atm.h> @@ -3175,6 +3175,9 @@ COMPATIBLE_IOCTL(RTCGET) COMPATIBLE_IOCTL(RTCSET) COMPATIBLE_IOCTL(I2CIOCSADR) COMPATIBLE_IOCTL(I2CIOCGADR) +COMPATIBLE_IOCTL(D7SIOCRD) +COMPATIBLE_IOCTL(D7SIOCWR) +COMPATIBLE_IOCTL(D7SIOCTM) /* Little m */ COMPATIBLE_IOCTL(MTIOCTOP) /* OPENPROMIO, SunOS/Solaris only, the NetBSD one's have @@ -3725,7 +3728,9 @@ int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, u int i; if (!additional_ioctls) { additional_ioctls = module_map(PAGE_SIZE); - if (!additional_ioctls) return -ENOMEM; + if (!additional_ioctls) + return -ENOMEM; + memset(additional_ioctls, 0, PAGE_SIZE); } for (i = 0; i < PAGE_SIZE/sizeof(struct ioctl_trans); i++) if (!additional_ioctls[i].cmd) @@ -3773,7 +3778,6 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp); struct ioctl_trans *t; - lock_kernel(); filp = fget(fd); if(!filp) goto out2; @@ -3801,6 +3805,5 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) out: fput(filp); out2: - unlock_kernel(); return error; } diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 12925b1c2..c7f4905b8 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.89 2000/06/30 10:18:38 davem Exp $ +/* $Id: irq.c,v 1.90 2000/08/01 00:28:33 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -548,13 +548,7 @@ out: restore_flags(flags); } -/* Only uniprocessor needs this IRQ/BH locking depth, on SMP it - * lives in the brlock table for cache reasons. - */ -#ifndef CONFIG_SMP -unsigned int __local_irq_count; -unsigned int __local_bh_count; -#else +#ifdef CONFIG_SMP /* Who has global_irq_lock. */ unsigned char global_irq_holder = NO_PROC_ID; @@ -571,7 +565,7 @@ static void show(char * str) printk("]\nbh: %d [ ", (spin_is_locked(&global_bh_lock) ? 1 : 0)); for (i = 0; i < smp_num_cpus; i++) - printk("%u ", cpu_data[i].bh_count); + printk("%u ", local_bh_count(i)); printk("]\n"); } @@ -768,10 +762,12 @@ void handler_irq(int irq, struct pt_regs *regs) nbp = __bucket(bp->irq_chain); if ((flags & IBF_ACTIVE) != 0) { +#ifdef CONFIG_PCI if ((flags & IBF_DMA_SYNC) != 0) { upa_readl(dma_sync_reg_table[bp->synctab_ent]); upa_readq(pci_dma_wsync); } +#endif if ((flags & IBF_MULTI) == 0) { struct irqaction *ap = bp->irq_info; ap->handler(__irq(bp), ap->dev_id, regs); diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 2d5d81452..5784201e2 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.109 2000/07/11 01:38:57 davem Exp $ +/* $Id: process.c,v 1.110 2000/07/28 09:43:39 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -524,7 +524,7 @@ void synchronize_user_stack(void) } } -void fault_in_user_windows(struct pt_regs *regs) +void fault_in_user_windows(void) { struct thread_struct *t = ¤t->thread; unsigned long window; diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index 1c9b6ac3f..3295938e6 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.49 2000/03/29 09:55:31 davem Exp $ +/* $Id: rtrap.S,v 1.51 2000/07/28 09:43:39 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -40,8 +40,9 @@ __handle_preemption: __handle_user_windows: wrpr %g0, RTRAP_PSTATE, %pstate call fault_in_user_windows - add %sp, STACK_BIAS + REGWIN_SZ, %g0 - ba,a,pt %xcc, __handle_user_windows_continue + nop + ba,pt %xcc, __handle_user_windows_continue + nop __handle_perfctrs: /* Don't forget to preserve user window invariants. */ wrpr %g0, RTRAP_PSTATE, %pstate @@ -54,9 +55,9 @@ __handle_perfctrs: wrpr %g0, RTRAP_PSTATE, %pstate call fault_in_user_windows - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + nop ba,pt %xcc, __handle_perfctrs_continue - nop + nop __handle_userfpu: rd %fprs, %l5 andcc %l5, FPRS_FEF, %g0 @@ -69,18 +70,25 @@ __handle_signal: mov %l6, %o3 call do_signal add %sp, STACK_BIAS + REGWIN_SZ, %o1 + clr %l6 + + /* Signal delivery can modify pt_regs tstate, so we must + * reload it. + */ + ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 + sethi %hi(0xf << 20), %l4 + and %l1, %l4, %l4 ba,pt %xcc, __handle_signal_continue - clr %l6 - nop + andn %l1, %l4, %l1 .align 64 .globl rtrap_clr_l6, rtrap rtrap_clr_l6: clr %l6 rtrap: lduw [%g6 + AOFF_task_processor], %l0 - sethi %hi(softirq_state), %l2 - or %l2, %lo(softirq_state), %l2 + sethi %hi(irq_stat), %l2 ! &softirq_active + or %l2, %lo(irq_stat), %l2 ! &softirq_active sllx %l0, 6, %l0 - ldx [%l2 + %l0], %l1 + ldx [%l2 + %l0], %l1 ! softirq_active + softirq_mask srlx %l1, 32, %l2 andcc %l1, %l2, %g0 diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index c666dc408..d1e7e4215 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.52 2000/07/07 04:25:17 davem Exp $ +/* $Id: signal.c,v 1.53 2000/07/30 23:12:24 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -166,7 +166,6 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) return; do_sigsegv: - lock_kernel(); do_exit(SIGSEGV); } @@ -254,7 +253,6 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs) return; do_sigsegv: - lock_kernel(); do_exit(SIGSEGV); } @@ -566,10 +564,8 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, return; sigill: - lock_kernel(); do_exit(SIGILL); sigsegv: - lock_kernel(); do_exit(SIGSEGV); } diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index f99b9660c..96f8624ca 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -87,7 +87,6 @@ void __init smp_store_cpu_info(int id) { int i; - cpu_data[id].bh_count = 0; /* multiplier and counter set by smp_setup_percpu_timer() */ cpu_data[id].udelay_val = loops_per_sec; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index eccc7885a..4a79b76bf 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.86 2000/06/30 10:18:38 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.89 2000/07/28 12:15:02 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -65,7 +65,6 @@ extern int __strncmp(const char *, const char *, __kernel_size_t); extern __kernel_size_t __strlen(const char *); extern __kernel_size_t strlen(const char *); extern char saved_command_line[]; -extern char *getname32(u32 name); extern void linux_sparc_syscall(void); extern void rtrap(void); extern void show_regs(struct pt_regs *); @@ -84,6 +83,7 @@ extern long sparc32_open(const char * filename, int flags, int mode); extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); extern int unregister_ioctl32_conversion(unsigned int cmd); extern int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space); +extern void flush_dcache_page(void *addr); extern int __ashrdi3(int, int); @@ -156,9 +156,6 @@ EXPORT_SYMBOL(_do_write_lock); EXPORT_SYMBOL(_do_write_unlock); #endif -#else -EXPORT_SYMBOL(__local_bh_count); -EXPORT_SYMBOL(__local_irq_count); #endif /* rw semaphores */ @@ -183,6 +180,8 @@ EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL_PRIVATE(flushw_user); +EXPORT_SYMBOL(flush_dcache_page); + EXPORT_SYMBOL(mstk48t02_regs); EXPORT_SYMBOL(request_fast_irq); #if CONFIG_SBUS @@ -279,7 +278,6 @@ EXPORT_SYMBOL(strtok); EXPORT_SYMBOL(strstr); #ifdef CONFIG_SOLARIS_EMUL_MODULE -EXPORT_SYMBOL(getname32); EXPORT_SYMBOL(linux_sparc_syscall); EXPORT_SYMBOL(rtrap); EXPORT_SYMBOL(show_regs); diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c index d32ea68c2..bcfa77a39 100644 --- a/arch/sparc64/kernel/sunos_ioctl32.c +++ b/arch/sparc64/kernel/sunos_ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: sunos_ioctl32.c,v 1.10 1998/08/15 20:42:46 davem Exp $ +/* $Id: sunos_ioctl32.c,v 1.11 2000/07/30 23:12:24 davem Exp $ * sunos_ioctl32.c: SunOS ioctl compatability on sparc64. * * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -98,7 +98,6 @@ asmlinkage int sunos_ioctl (int fd, u32 cmd, u32 arg) { int ret = -EBADF; - lock_kernel(); if(fd >= SUNOS_NR_OPEN) goto out; if(!fcheck(fd)) @@ -281,6 +280,5 @@ asmlinkage int sunos_ioctl (int fd, u32 cmd, u32 arg) /* so stupid... */ ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); out: - unlock_kernel(); return ret; } diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 859d0c7ea..e869af4e6 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.44 2000/07/10 20:57:35 davem Exp $ +/* $Id: sys_sparc.c,v 1.45 2000/07/30 23:12:24 davem Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -299,13 +299,14 @@ c_sys_nis_syscall (struct pt_regs *regs) static int count=0; /* Don't make the system unusable, if someone goes stuck */ - if (count++ > 5) return -ENOSYS; - lock_kernel(); + if (count++ > 5) + return -ENOSYS; + printk ("Unimplemented SPARC system call %ld\n",regs->u_regs[1]); #ifdef DEBUG_UNIMP_SYSCALL show_regs (regs); #endif - unlock_kernel(); + return -ENOSYS; } @@ -316,7 +317,6 @@ sparc_breakpoint (struct pt_regs *regs) { siginfo_t info; - lock_kernel(); #ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Entering kernel PC=%lx, nPC=%lx\n", regs->tpc, regs->tnpc); #endif @@ -329,7 +329,6 @@ sparc_breakpoint (struct pt_regs *regs) #ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc); #endif - unlock_kernel(); } extern void check_pending(int signum); @@ -364,7 +363,7 @@ asmlinkage int sys_aplib(void) asmlinkage int solaris_syscall(struct pt_regs *regs) { static int count = 0; - lock_kernel(); + regs->tpc = regs->tnpc; regs->tnpc += 4; if(++count <= 5) { @@ -372,7 +371,7 @@ asmlinkage int solaris_syscall(struct pt_regs *regs) show_regs (regs); } send_sig(SIGSEGV, current, 1); - unlock_kernel(); + return -ENOSYS; } @@ -380,13 +379,13 @@ asmlinkage int solaris_syscall(struct pt_regs *regs) asmlinkage int sunos_syscall(struct pt_regs *regs) { static int count = 0; - lock_kernel(); + regs->tpc = regs->tnpc; regs->tnpc += 4; if(++count <= 20) printk ("SunOS binary emulation not compiled in\n"); force_sig(SIGSEGV, current); - unlock_kernel(); + return -ENOSYS; } #endif @@ -408,32 +407,37 @@ asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, put_user_ret(NULL, old_d, -EFAULT); return 0; } - lock_kernel(); if (!current->thread.utraps) { - current->thread.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); + current->thread.utraps = + kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); if (!current->thread.utraps) return -ENOMEM; current->thread.utraps[0] = 1; memset(current->thread.utraps+1, 0, UT_TRAP_INSTRUCTION_31*sizeof(long)); } else { - if ((utrap_handler_t)current->thread.utraps[type] != new_p && current->thread.utraps[0] > 1) { + if ((utrap_handler_t)current->thread.utraps[type] != new_p && + current->thread.utraps[0] > 1) { long *p = current->thread.utraps; - - current->thread.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); + + current->thread.utraps = + kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), + GFP_KERNEL); if (!current->thread.utraps) { current->thread.utraps = p; return -ENOMEM; } p[0]--; current->thread.utraps[0] = 1; - memcpy(current->thread.utraps+1, p+1, UT_TRAP_INSTRUCTION_31*sizeof(long)); + memcpy(current->thread.utraps+1, p+1, + UT_TRAP_INSTRUCTION_31*sizeof(long)); } } if (old_p) - put_user_ret((utrap_handler_t)(current->thread.utraps[type]), old_p, -EFAULT); + put_user_ret((utrap_handler_t)(current->thread.utraps[type]), + old_p, -EFAULT); if (old_d) put_user_ret(NULL, old_d, -EFAULT); current->thread.utraps[type] = (long)new_p; - unlock_kernel(); + return 0; } diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 89c1a90ea..7d8a71d6a 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.156 2000/07/13 10:59:13 davem Exp $ +/* $Id: sys_sparc32.c,v 1.158 2000/07/29 00:55:49 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -253,45 +253,6 @@ asmlinkage long sys32_getegid16(void) return high2lowgid(current->egid); } -/* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the - * kernel data space before using them.. - * - * POSIX.1 2.4: an empty pathname is invalid (ENOENT). - */ -static inline int do_getname32(const char *filename, char *page) -{ - int retval; - - /* 32bit pointer will be always far below TASK_SIZE :)) */ - retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE); - if (retval > 0) { - if (retval < PAGE_SIZE) - return 0; - return -ENAMETOOLONG; - } else if (!retval) - retval = -ENOENT; - return retval; -} - -char * getname32(const char *filename) -{ - char *tmp, *result; - - result = ERR_PTR(-ENOMEM); - tmp = __getname(); - if (tmp) { - int retval = do_getname32(filename, tmp); - - result = tmp; - if (retval < 0) { - putname(tmp); - result = ERR_PTR(retval); - } - } - return result; -} - /* 32-bit timeval and related flotsam. */ struct timeval32 @@ -799,7 +760,6 @@ asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u { int version, err; - lock_kernel(); version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; @@ -861,7 +821,6 @@ asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u err = -EINVAL; out: - unlock_kernel(); return err; } @@ -953,7 +912,7 @@ asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned lon return sys_quotactl(cmd, special, id, (caddr_t)addr); } - spec = getname32 (special); + spec = getname (special); err = PTR_ERR(spec); if (IS_ERR(spec)) return err; old_fs = get_fs (); @@ -998,7 +957,7 @@ asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf) mm_segment_t old_fs = get_fs(); char *pth; - pth = getname32 (path); + pth = getname (path); ret = PTR_ERR(pth); if (!IS_ERR(pth)) { set_fs (KERNEL_DS); @@ -1064,7 +1023,7 @@ asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times) if (get_user (t.actime, ×->actime) || __get_user (t.modtime, ×->modtime)) return -EFAULT; - filenam = getname32 (filename); + filenam = getname (filename); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { old_fs = get_fs(); @@ -1572,6 +1531,16 @@ static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf) return err; } +/* Perhaps this belongs in fs.h or similar. -DaveM */ +static __inline__ int +do_revalidate(struct dentry *dentry) +{ + struct inode * inode = dentry->d_inode; + if (inode->i_op && inode->i_op->revalidate) + return inode->i_op->revalidate(dentry); + return 0; +} + asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf) { struct nameidata nd; @@ -1579,16 +1548,9 @@ asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf) error = user_path_walk(filename, &nd); if (!error) { - struct inode *inode = nd.dentry->d_inode; - - if (inode->i_op && - inode->i_op->revalidate) - error = inode->i_op->revalidate(nd.dentry); - else - error = 0; + error = do_revalidate(nd.dentry); if (!error) - error = cp_new_stat32(inode, statbuf); - + error = cp_new_stat32(nd.dentry->d_inode, statbuf); path_release(&nd); } return error; @@ -1601,15 +1563,9 @@ asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf) error = user_path_walk_link(filename, &nd); if (!error) { - struct inode *inode = nd.dentry->d_inode; - - if (inode->i_op && - inode->i_op->revalidate) - error = inode->i_op->revalidate(nd.dentry); - else - error = 0; + error = do_revalidate(nd.dentry); if (!error) - error = cp_new_stat32(inode, statbuf); + error = cp_new_stat32(nd.dentry->d_inode, statbuf); path_release(&nd); } @@ -1623,16 +1579,11 @@ asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf) f = fget(fd); if (f) { - struct inode *inode = f->f_dentry->d_inode; + struct dentry * dentry = f->f_dentry; - if (inode->i_op && - inode->i_op->revalidate) - err = inode->i_op->revalidate(f->f_dentry); - else - err = 0; + err = do_revalidate(dentry); if (!err) - err = cp_new_stat32(inode, statbuf); - + err = cp_new_stat32(dentry->d_inode, statbuf); fput(f); } return err; @@ -1738,7 +1689,6 @@ asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned is_smb = is_ncp = 0; - lock_kernel(); err = copy_mount_stuff_to_kernel((const void *)type, &type_page); if (err) goto out; @@ -1764,16 +1714,20 @@ asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned goto dev_out; if (!is_smb && !is_ncp) { + lock_kernel(); err = do_mount((char*)dev_page, (char*)dir_page, (char*)type_page, new_flags, (char*)data_page); + unlock_kernel(); } else { if (is_ncp) do_ncp_super_data_conv((void *)data_page); else do_smb_super_data_conv((void *)data_page); + lock_kernel(); err = do_mount((char*)dev_page, (char*)dir_page, (char*)type_page, new_flags, (char*)data_page); + unlock_kernel(); } free_page(dir_page); @@ -1787,7 +1741,6 @@ type_out: free_page(type_page); out: - unlock_kernel(); return err; } @@ -2234,34 +2187,9 @@ asmlinkage int sys32_getrusage(int who, struct rusage32 *ru) 24 for IPv6, about 80 for AX.25 */ -/* XXX These as well... */ -extern __inline__ struct socket *socki_lookup(struct inode *inode) -{ - return &inode->u.socket_i; -} - -extern __inline__ struct socket *sockfd_lookup(int fd, int *err) -{ - struct file *file; - struct inode *inode; - - if (!(file = fget(fd))) - { - *err = -EBADF; - return NULL; - } - - inode = file->f_dentry->d_inode; - if (!inode || !inode->i_sock || !socki_lookup(inode)) - { - *err = -ENOTSOCK; - fput(file); - return NULL; - } - - return socki_lookup(inode); -} +extern struct socket *sockfd_lookup(int fd, int *err); +/* XXX This as well... */ extern __inline__ void sockfd_put(struct socket *sock) { fput(sock->file); @@ -2678,7 +2606,6 @@ asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_fl } kern_msg.msg_flags = user_flags; - lock_kernel(); sock = sockfd_lookup(fd, &err); if (sock != NULL) { if (sock->file->f_flags & O_NONBLOCK) @@ -2686,7 +2613,6 @@ asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_fl err = sock_sendmsg(sock, &kern_msg, total_len); sockfd_put(sock); } - unlock_kernel(); /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ if(ctl_buf != ctl) @@ -2725,7 +2651,6 @@ asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int use cmsg_ptr = (unsigned long) kern_msg.msg_control; kern_msg.msg_flags = 0; - lock_kernel(); sock = sockfd_lookup(fd, &err); if (sock != NULL) { struct scm_cookie scm; @@ -2762,7 +2687,6 @@ asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int use } sockfd_put(sock); } - unlock_kernel(); if(uaddr != NULL && err >= 0) err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); @@ -3084,7 +3008,7 @@ asmlinkage int sparc32_execve(struct pt_regs *regs) if((u32)regs->u_regs[UREG_G1] == 0) base = 1; - filename = getname32((char *)AA(regs->u_regs[base + UREG_I0])); + filename = getname((char *)AA(regs->u_regs[base + UREG_I0])); error = PTR_ERR(filename); if(IS_ERR(filename)) goto out; @@ -3926,7 +3850,7 @@ asmlinkage int sys32_utimes(char *filename, struct timeval32 *tvs) mm_segment_t old_fs; int ret; - kfilename = getname32(filename); + kfilename = getname(filename); ret = PTR_ERR(kfilename); if (!IS_ERR(kfilename)) { if (tvs) { diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index 3f43e99dc..9015a2fec 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.52 2000/07/10 20:57:35 davem Exp $ +/* $Id: sys_sunos32.c,v 1.53 2000/07/30 23:12:24 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -179,21 +179,18 @@ asmlinkage u32 sunos_sbrk(int increment) int error, oldbrk; /* This should do it hopefully... */ - lock_kernel(); oldbrk = (int)current->mm->brk; error = sunos_brk(((int) current->mm->brk) + increment); if(!error) error = oldbrk; - unlock_kernel(); return error; } asmlinkage u32 sunos_sstk(int increment) { - lock_kernel(); printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n", current->comm, increment); - unlock_kernel(); + return (u32)-1; } @@ -213,12 +210,13 @@ static char *vstrings[] = { asmlinkage void sunos_vadvise(u32 strategy) { + static int count = 0; + /* I wanna see who uses this... */ - lock_kernel(); - printk("%s: Advises us to use %s paging strategy\n", - current->comm, - strategy <= 3 ? vstrings[strategy] : "BOGUS"); - unlock_kernel(); + if (count++ < 5) + printk("%s: Advises us to use %s paging strategy\n", + current->comm, + strategy <= 3 ? vstrings[strategy] : "BOGUS"); } /* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE @@ -457,7 +455,6 @@ asmlinkage int sunos_nosys(void) siginfo_t info; static int cnt; - lock_kernel(); regs = current->thread.kregs; info.si_signo = SIGSYS; info.si_errno = 0; @@ -470,7 +467,6 @@ asmlinkage int sunos_nosys(void) (int) regs->u_regs[UREG_G1]); show_regs(regs); } - unlock_kernel(); return -ENOSYS; } @@ -726,7 +722,7 @@ sunos_mount(char *type, char *dir, int flags, void *data) if (!capable (CAP_SYS_ADMIN)) return -EPERM; - lock_kernel(); + /* We don't handle the integer fs type */ if ((flags & SMNT_NEWTYPE) == 0) goto out; @@ -772,7 +768,9 @@ sunos_mount(char *type, char *dir, int flags, void *data) ret = PTR_ERR(dev_fname); if (IS_ERR(dev_fname)) goto out2; + lock_kernel(); ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL); + unlock_kernel(); if (dev_fname) putname(dev_fname); out2: @@ -780,7 +778,6 @@ out2: out1: putname(dir_page); out: - unlock_kernel(); return ret; } @@ -818,12 +815,7 @@ asmlinkage int sunos_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 extern int kill_pg(int, int, int); asmlinkage int sunos_killpg(int pgrp, int sig) { - int ret; - - lock_kernel(); - ret = kill_pg(pgrp, sig, 0); - unlock_kernel(); - return ret; + return kill_pg(pgrp, sig, 0); } asmlinkage int sunos_audit(void) @@ -836,9 +828,8 @@ extern asmlinkage u32 sunos_gethostid(void) { u32 ret; - lock_kernel(); ret = (((u32)idprom->id_machtype << 24) | ((u32)idprom->id_sernum)); - unlock_kernel(); + return ret; } diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 7b5d32614..de4968ac4 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.66 2000/05/09 17:40:14 davem Exp $ +/* $Id: traps.c,v 1.67 2000/07/30 23:12:24 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -255,7 +255,6 @@ void bad_trap (struct pt_regs *regs, long lvl) { siginfo_t info; - lock_kernel (); if (lvl < 0x100) { char buffer[24]; @@ -270,17 +269,14 @@ void bad_trap (struct pt_regs *regs, long lvl) info.si_addr = (void *)regs->tpc; info.si_trapno = lvl - 0x100; force_sig_info(SIGILL, &info, current); - unlock_kernel (); } void bad_trap_tl1 (struct pt_regs *regs, long lvl) { char buffer[24]; - lock_kernel(); sprintf (buffer, "Bad trap %lx at tl>0", lvl); die_if_kernel (buffer, regs); - unlock_kernel(); } void instruction_access_exception (struct pt_regs *regs, @@ -288,7 +284,6 @@ void instruction_access_exception (struct pt_regs *regs, { siginfo_t info; - lock_kernel(); if (regs->tstate & TSTATE_PRIV) { #if 1 printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n", @@ -302,7 +297,6 @@ void instruction_access_exception (struct pt_regs *regs, info.si_addr = (void *)regs->tpc; info.si_trapno = 0; force_sig_info(SIGSEGV, &info, current); - unlock_kernel(); } void data_access_exception (struct pt_regs *regs, @@ -343,9 +337,7 @@ void data_access_exception (struct pt_regs *regs, info.si_code = SEGV_MAPERR; info.si_addr = (void *)sfar; info.si_trapno = 0; - lock_kernel(); force_sig_info(SIGSEGV, &info, current); - unlock_kernel(); } #ifdef CONFIG_PCI @@ -389,9 +381,7 @@ void do_iae(struct pt_regs *regs) info.si_code = BUS_OBJERR; info.si_addr = (void *)0; info.si_trapno = 0; - lock_kernel(); force_sig_info(SIGBUS, &info, current); - unlock_kernel(); } void do_dae(struct pt_regs *regs) @@ -692,7 +682,6 @@ void die_if_kernel(char *str, struct pt_regs *regs) smp_report_regs(); #endif - lock_kernel(); /* Or else! */ if(regs->tstate & TSTATE_PRIV) do_exit(SIGKILL); do_exit(SIGSEGV); diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index 090eb96a1..3cf5b6883 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -1,4 +1,4 @@ -/* $Id: fs.c,v 1.21 2000/07/10 20:57:35 davem Exp $ +/* $Id: fs.c,v 1.22 2000/07/28 12:15:02 davem Exp $ * fs.c: fs related syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -25,8 +25,6 @@ #include "conv.h" -extern char * getname32(u32 filename); - #define R4_DEV(DEV) ((DEV & 0xff) | ((DEV & 0xff00) << 10)) #define R4_MAJOR(DEV) (((DEV) >> 18) & 0x3fff) #define R4_MINOR(DEV) ((DEV) & 0x3ffff) @@ -136,7 +134,7 @@ asmlinkage int solaris_stat(u32 filename, u32 statbuf) int (*sys_newstat)(char *,struct stat *) = (int (*)(char *,struct stat *))SYS(stat); - filenam = getname32 (filename); + filenam = getname ((char *)A(filename)); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { set_fs (KERNEL_DS); @@ -164,7 +162,7 @@ asmlinkage int solaris_stat64(u32 filename, u32 statbuf) int (*sys_newstat)(char *,struct stat *) = (int (*)(char *,struct stat *))SYS(stat); - filenam = getname32 (filename); + filenam = getname ((char *)A(filename)); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { set_fs (KERNEL_DS); @@ -186,7 +184,7 @@ asmlinkage int solaris_lstat(u32 filename, u32 statbuf) int (*sys_newlstat)(char *,struct stat *) = (int (*)(char *,struct stat *))SYS(lstat); - filenam = getname32 (filename); + filenam = getname ((char *)A(filename)); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { set_fs (KERNEL_DS); @@ -213,7 +211,7 @@ asmlinkage int solaris_lstat64(u32 filename, u32 statbuf) int (*sys_newlstat)(char *,struct stat *) = (int (*)(char *,struct stat *))SYS(lstat); - filenam = getname32 (filename); + filenam = getname ((char *)A(filename)); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { set_fs (KERNEL_DS); diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c index 18d73e686..0e899da18 100644 --- a/arch/sparc64/solaris/ioctl.c +++ b/arch/sparc64/solaris/ioctl.c @@ -1,4 +1,4 @@ -/* $Id: ioctl.c,v 1.14 1999/09/22 09:28:50 davem Exp $ +/* $Id: ioctl.c,v 1.15 2000/07/28 12:15:02 davem Exp $ * ioctl.c: Solaris ioctl emulation. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -31,9 +31,6 @@ #include "conv.h" #include "socksys.h" -extern char *getname32(u32 filename); -#define putname32 putname - extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, @@ -486,7 +483,7 @@ static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd return -ENOSYS; case 2: /* I_PUSH */ { - p = getname32 (arg); + p = getname ((char *)A(arg)); if (IS_ERR (p)) return PTR_ERR(p); ret = -EINVAL; @@ -503,7 +500,7 @@ static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd break; } } - putname32 (p); + putname (p); return ret; } case 3: /* I_POP */ @@ -546,7 +543,7 @@ static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd case 11: /* I_FIND */ { int i; - p = getname32 (arg); + p = getname ((char *)A(arg)); if (IS_ERR (p)) return PTR_ERR(p); ret = 0; @@ -557,7 +554,7 @@ static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd break; } } - putname32 (p); + putname (p); return ret; } case 19: /* I_SWROPT */ diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c index 946b20fae..3ef9c943b 100644 --- a/arch/sparc64/solaris/timod.c +++ b/arch/sparc64/solaris/timod.c @@ -1,4 +1,4 @@ -/* $Id: timod.c,v 1.9 2000/07/12 23:21:02 davem Exp $ +/* $Id: timod.c,v 1.10 2000/07/28 12:15:02 davem Exp $ * timod.c: timod emulation. * * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) @@ -27,9 +27,6 @@ #include "conv.h" #include "socksys.h" -extern char *getname32(u32 filename); -#define putname32 putname - extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, diff --git a/drivers/char/Config.in b/drivers/char/Config.in index f41c3d48b..2ac91160d 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -259,7 +259,7 @@ endmenu tristate '/dev/agpgart (AGP Support)' CONFIG_AGP $CONFIG_DRM_AGP if [ "$CONFIG_AGP" != "n" ]; then - bool ' Intel 440LX/BX/GX support' CONFIG_AGP_INTEL + bool ' Intel 440LX/BX/GX 840 support' CONFIG_AGP_INTEL bool ' Intel I810/I810 DC100/I810e support' CONFIG_AGP_I810 bool ' VIA chipset support' CONFIG_AGP_VIA bool ' AMD Irongate support' CONFIG_AGP_AMD diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c index dcc8176f9..573419a28 100644 --- a/drivers/char/agp/agpgart_be.c +++ b/drivers/char/agp/agpgart_be.c @@ -2114,6 +2114,12 @@ static struct { #endif /* CONFIG_AGP_SIS */ #ifdef CONFIG_AGP_VIA + { PCI_DEVICE_ID_VIA_8371_0, + PCI_VENDOR_ID_VIA, + VIA_APOLLO_SUPER, + "Via", + "Apollo Super", + via_generic_setup }, { PCI_DEVICE_ID_VIA_8501_0, PCI_VENDOR_ID_VIA, VIA_MVP4, @@ -2183,16 +2189,15 @@ static int __init agp_lookup_host_bridge (struct pci_dev *pdev) * there is a 'generic' bridge entry for this vendor */ if (agp_try_unsupported && agp_bridge_info[i].device_id == 0) { printk(KERN_WARNING PFX "Trying generic %s routines" - " for device id: %x\n", + " for device id: %04x\n", agp_bridge_info[i].vendor_name, pdev->device); agp_bridge.type = agp_bridge_info[i].chipset; return agp_bridge_info[i].chipset_setup (pdev); } - printk(KERN_ERR PFX "Unsupported %s chipset," - " you might want to try " - "agp_try_unsupported=1.\n", - agp_bridge_info[i].vendor_name); + printk(KERN_ERR PFX "Unsupported %s chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + agp_bridge_info[i].vendor_name, pdev->device); return -ENODEV; } diff --git a/drivers/char/drm/agpsupport.c b/drivers/char/drm/agpsupport.c index 48a6aa5f9..e1e1ccedd 100644 --- a/drivers/char/drm/agpsupport.c +++ b/drivers/char/drm/agpsupport.c @@ -289,20 +289,21 @@ drm_agp_head_t *drm_agp_init(void) (*drm_agp.copy_info)(&head->agp_info); head->memory = NULL; switch (head->agp_info.chipset) { - case INTEL_GENERIC: head->chipset = "Intel"; break; - case INTEL_LX: head->chipset = "Intel 440LX"; break; - case INTEL_BX: head->chipset = "Intel 440BX"; break; - case INTEL_GX: head->chipset = "Intel 440GX"; break; - case INTEL_I810: head->chipset = "Intel i810"; break; - case VIA_GENERIC: head->chipset = "VIA"; break; - case VIA_VP3: head->chipset = "VIA VP3"; break; - case VIA_MVP3: head->chipset = "VIA MVP3"; break; - case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break; - case SIS_GENERIC: head->chipset = "SiS"; break; - case AMD_GENERIC: head->chipset = "AMD"; break; - case AMD_IRONGATE: head->chipset = "AMD Irongate"; break; - case ALI_GENERIC: head->chipset = "ALi"; break; - case ALI_M1541: head->chipset = "ALi M1541"; break; + case INTEL_GENERIC: head->chipset = "Intel"; break; + case INTEL_LX: head->chipset = "Intel 440LX"; break; + case INTEL_BX: head->chipset = "Intel 440BX"; break; + case INTEL_GX: head->chipset = "Intel 440GX"; break; + case INTEL_I810: head->chipset = "Intel i810"; break; + case VIA_GENERIC: head->chipset = "VIA"; break; + case VIA_VP3: head->chipset = "VIA VP3"; break; + case VIA_MVP3: head->chipset = "VIA MVP3"; break; + case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break; + case VIA_APOLLO_SUPER: head->chipset = "VIA Apollo Super"; break; + case SIS_GENERIC: head->chipset = "SiS"; break; + case AMD_GENERIC: head->chipset = "AMD"; break; + case AMD_IRONGATE: head->chipset = "AMD Irongate"; break; + case ALI_GENERIC: head->chipset = "ALi"; break; + case ALI_M1541: head->chipset = "ALi M1541"; break; default: } DRM_INFO("AGP %d.%d on %s @ 0x%08lx %dMB\n", diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 3e5149c91..e4783c8db 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -578,7 +578,9 @@ extern void drm_vm_close(struct vm_area_struct *vma); extern int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma); extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); - +extern struct vm_operations_struct drm_vm_ops; +extern struct vm_operations_struct drm_vm_shm_ops; +extern struct vm_operations_struct drm_vm_dma_ops; /* Proc support (proc.c) */ extern int drm_proc_init(drm_device_t *dev); diff --git a/drivers/char/drm/drm_syms.c b/drivers/char/drm/drm_syms.c index e7aaf569d..661ac4816 100644 --- a/drivers/char/drm/drm_syms.c +++ b/drivers/char/drm/drm_syms.c @@ -31,6 +31,9 @@ EXPORT_SYMBOL(drm_vm_open); EXPORT_SYMBOL(drm_vm_close); EXPORT_SYMBOL(drm_mmap_dma); EXPORT_SYMBOL(drm_mmap); +EXPORT_SYMBOL(drm_vm_ops); +EXPORT_SYMBOL(drm_vm_shm_ops); +EXPORT_SYMBOL(drm_vm_dma_ops); /* Proc support (proc.c) */ EXPORT_SYMBOL(drm_proc_init); diff --git a/drivers/char/radio-typhoon.c b/drivers/char/radio-typhoon.c index 434dff875..a0bbf343f 100644 --- a/drivers/char/radio-typhoon.c +++ b/drivers/char/radio-typhoon.c @@ -300,32 +300,26 @@ static struct video_device typhoon_radio = static int typhoon_get_info(char *buf, char **start, off_t offset, int len) { + char *out = buf; + #ifdef MODULE #define MODULEPROCSTRING "Driver loaded as a module" #else #define MODULEPROCSTRING "Driver compiled into kernel" #endif - #define LIMIT (PAGE_SIZE - 80) - - len = 0; - len += sprintf(buf + len, BANNER); - if (len > LIMIT) return len; - len += sprintf(buf + len, "Load type: " MODULEPROCSTRING "\n\n"); - if (len > LIMIT) return len; - len += sprintf(buf + len, "frequency = %lu kHz\n", + /* output must be kept under PAGE_SIZE */ + out += sprintf(out, BANNER); + out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n"); + out += sprintf(out, "frequency = %lu kHz\n", typhoon_unit.curfreq >> 4); - if (len > LIMIT) return len; - len += sprintf(buf + len, "volume = %d\n", typhoon_unit.curvol); - if (len > LIMIT) return len; - len += sprintf(buf + len, "mute = %s\n", typhoon_unit.muted ? + out += sprintf(out, "volume = %d\n", typhoon_unit.curvol); + out += sprintf(out, "mute = %s\n", typhoon_unit.muted ? "on" : "off"); - if (len > LIMIT) return len; - len += sprintf(buf + len, "iobase = 0x%x\n", typhoon_unit.iobase); - if (len > LIMIT) return len; - len += sprintf(buf + len, "mute frequency = %lu kHz\n", + out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase); + out += sprintf(out, "mute frequency = %lu kHz\n", typhoon_unit.mutefreq >> 4); - return len; + return out - buf; } #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */ diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index 681379708..d9b818824 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -1273,19 +1273,19 @@ static int __init ltpc_setup(char *str) __setup("ltpc=", ltpc_setup); #endif /* MODULE */ -MODULE_PARM(debug, "i"); -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(dma, "i"); - -#ifdef MODULE - static struct net_device dev_ltpc = { "", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, NULL, ltpc_probe }; +#ifdef MODULE +MODULE_PARM(debug, "i"); +MODULE_PARM(io, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(dma, "i"); + + int __init init_module(void) { int err, result; diff --git a/drivers/net/pcmcia/ray_cs.c b/drivers/net/pcmcia/ray_cs.c index 36b11f907..281940845 100644 --- a/drivers/net/pcmcia/ray_cs.c +++ b/drivers/net/pcmcia/ray_cs.c @@ -385,7 +385,6 @@ static dev_link_t *ray_attach(void) DEBUG(2,"ray_cs ray_attach calling ether_setup.)\n"); ether_setup(dev); - strcpy(dev->name, local->node.dev_name); dev->init = &ray_dev_init; dev->open = &ray_open; dev->stop = &ray_dev_close; @@ -581,6 +580,8 @@ static void ray_config(dev_link_t *link) return; } + strcpy(local->node.dev_name, dev->name); + link->state &= ~DEV_CONFIG_PENDING; printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ", dev->name, dev->irq); diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index a2da24437..84dc28025 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -5,9 +5,16 @@ * PPPoE --- PPP over Ethernet (RFC 2516) * * - * Version: 0.5.1 + * Version: 0.6.0 * - * 030700 : Fixed connect logic to allow for disconnect + * 030700 : Fixed connect logic to allow for disconnect. + * 270700 : Fixed potential SMP problems; we must protect against + * simultaneous invocation of ppp_input + * and ppp_unregister_channel. + * + * Module reference count is decremented in the right spot now, + * guards against sock_put not actually freeing the sk + * in pppoe_release. * * Author: Michal Ostrowski <mostrows@styx.uwaterloo.ca> * @@ -204,6 +211,8 @@ static inline struct pppox_opt *get_item(unsigned long sid, read_lock_bh(&pppoe_hash_lock); po = __get_item(sid, addr); + if(po) + sock_hold(po->sk); read_unlock_bh(&pppoe_hash_lock); return po; @@ -245,14 +254,16 @@ static struct pppox_opt *find_on_dev(struct net_device *dev, struct pppox_opt *po; read_lock_bh(&pppoe_hash_lock); po = __find_on_dev(dev,start); + if(po) + sock_hold(po->sk); read_unlock_bh(&pppoe_hash_lock); return po; } /*************************************************************************** * - * Handler for device events - * Certain device events require that sockets be unconnected + * Handler for device events. + * Certain device events require that sockets be unconnected. * **************************************************************************/ static int pppoe_device_event(struct notifier_block *this, @@ -274,20 +285,14 @@ static int pppoe_device_event(struct notifier_block *this, po = find_on_dev(dev, po); if(!po) break; - + + lock_sock(po->sk); if (po->sk->state & PPPOX_CONNECTED) pppox_unbind_sock(po->sk); - if (po->sk->state & PPPOX_CONNECTED) { - lock_sock(po->sk); - po->sk->shutdown = RCV_SHUTDOWN&SEND_SHUTDOWN; - - po->sk->state = PPPOX_DEAD; - po->pppoe_dev = NULL; + release_sock(po->sk); + sock_put(po->sk); - wake_up(po->sk->sleep); - release_sock(po->sk); - } } while (1); break; @@ -310,31 +315,15 @@ static struct notifier_block pppoe_notifier = { /************************************************************************ * - * Receive a PPPoE Session frame. + * Do the real work of receiving a PPPoE Session frame. * ***********************************************************************/ -static int pppoe_rcv(struct sk_buff *skb, - struct net_device *dev, - struct packet_type *pt) - -{ - struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; - struct pppox_opt *po; - struct sock *sk ; - - po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); - - if(!po) - goto abort; - - sk = po->sk; - - if (!sk || !(sk->state & PPPOX_CONNECTED)) - goto abort; +int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb){ + struct pppox_opt *po=sk->protinfo.pppox; if (sk->state & PPPOX_BOUND) { skb_pull(skb, sizeof(struct pppoe_hdr)); - + ppp_input(&po->chan, skb); } else if( sk->state & PPPOX_RELAY ){ struct pppox_opt *relay_po; @@ -342,28 +331,88 @@ static int pppoe_rcv(struct sk_buff *skb, relay_po = get_item_by_addr( &po->pppoe_relay ); if( relay_po == NULL || - !( relay_po->sk->state & PPPOX_CONNECTED ) ) + !( relay_po->sk->state & PPPOX_CONNECTED ) ){ + sock_put(relay_po->sk); goto abort; - + } + skb_pull(skb, sizeof(struct pppoe_hdr)); - if( !__pppoe_xmit( relay_po->sk , skb) ) + if( !__pppoe_xmit( relay_po->sk , skb) ){ + sock_put(relay_po->sk); goto abort; + } } else { sock_queue_rcv_skb(sk, skb); } - return 1; - abort: - kfree_skb(skb); + sock_put(sk); + return 0; + +} + + + + +/************************************************************************ + * + * Receive wrapper called in BH context. + * + ***********************************************************************/ +static int pppoe_rcv(struct sk_buff *skb, + struct net_device *dev, + struct packet_type *pt) + +{ + struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; + struct pppox_opt *po; + struct sock *sk ; + int ret; + + po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); + + if(!po){ + kfree(skb); + return 0; + } + + sk = po->sk; + bh_lock_sock(sk); + + /* Socket state is unknown, must put skb into backlog. */ + if( sk->lock.users != 0 ){ + sk_add_backlog( sk, skb); + ret = 1; + }else{ + ret = pppoe_rcv_core(sk, skb); + } + + bh_unlock_sock(sk); + sock_put(sk); + return ret; +} + + +/************************************************************************ + * + * Receive wrapper called in process context. + * + ***********************************************************************/ +int pppoe_backlog_rcv(struct sock *sk, struct sk_buff *skb) +{ + lock_sock(sk); + pppoe_rcv_core(sk, skb); + release_sock(sk); return 0; } + + /************************************************************************ * * Receive a PPPoE Discovery frame. - * -- This is solely for detection of PADT frames + * This is solely for detection of PADT frames * ***********************************************************************/ static int pppoe_disc_rcv(struct sk_buff *skb, @@ -373,7 +422,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb, { struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; struct pppox_opt *po; - struct sock *sk ; + struct sock *sk = NULL; if (ph->code != PADT_CODE) goto abort; @@ -381,13 +430,15 @@ static int pppoe_disc_rcv(struct sk_buff *skb, po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); if (!po) - goto abort; + goto abort_put; sk = po->sk; pppox_unbind_sock(sk); -abort: + abort_put: + sock_put(sk); + abort: kfree_skb(skb); return 0; } @@ -422,22 +473,7 @@ void sock_pppoe_destruct(struct sock *sk) if (sk->protinfo.destruct_hook) kfree(sk->protinfo.destruct_hook); - while (skb_queue_len(&sk->receive_queue) > 0) { - struct sk_buff *skb = skb_dequeue(&sk->receive_queue); - if (skb) - kfree_skb(skb); - } -} - -int pppoe_backlog_rcv(struct sock *sk, struct sk_buff *skb) -{ - /* Never seen this called, don't expect it to be called, - though I've curious whether or not it ever will be. */ - DEBUG(KERN_CRIT "Backlog rcv called: %p\n", sk); - - kfree_skb(skb); - - return 0; + MOD_DEC_USE_COUNT; } /*********************************************************************** @@ -487,7 +523,6 @@ static int pppoe_create(struct socket *sock) free_sk: sk_free(sk); - MOD_DEC_USE_COUNT; return error; } @@ -505,8 +540,6 @@ int pppoe_release(struct socket *sock) pppox_unbind_sock(sk); - sock_orphan(sk); - /* Signal the death of the socket. */ sk->state = PPPOX_DEAD; @@ -514,12 +547,9 @@ int pppoe_release(struct socket *sock) if (po->pppoe_pa.sid) delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote); - kfree(po); - - /* Should also do a queue purge here */ - sk->protinfo.pppox = NULL; + sock_orphan(sk); sock->sk = NULL; skb_queue_purge(&sk->receive_queue); diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c index 1ee37e20e..096d8164a 100644 --- a/drivers/net/wan/syncppp.c +++ b/drivers/net/wan/syncppp.c @@ -723,7 +723,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) struct in_device *in_dev; struct in_ifaddr *ifa; u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ - +#ifdef CONFIG_INET if ((in_dev=in_dev_get(dev)) != NULL) { read_lock(&in_dev->lock); @@ -739,6 +739,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) read_unlock(&in_dev->lock); in_dev_put(in_dev); } +#endif /* I hope both addr and mask are in the net order */ sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask); break; diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile index 4a88efda3..84ee1ad22 100644 --- a/drivers/sbus/char/Makefile +++ b/drivers/sbus/char/Makefile @@ -37,6 +37,14 @@ else endif endif +ifeq ($(CONFIG_DISPLAY7SEG),y) +O_OBJS += display7seg.o +else + ifeq ($(CONFIG_DISPLAY7SEG),m) + M_OBJS += display7seg.o + endif +endif + endif # eq($(CONFIG_PCI,y) ifeq ($(CONFIG_OBP_FLASH),y) diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c new file mode 100644 index 000000000..c9d4ea0f6 --- /dev/null +++ b/drivers/sbus/char/display7seg.c @@ -0,0 +1,238 @@ +/* $Id: display7seg.c,v 1.2 2000/08/02 06:22:35 davem Exp $ + * + * display7seg - Driver implementation for the 7-segment display + * present on Sun Microsystems CP1400 and CP1500 + * + * Copyright (c) 2000 Eric Brower (ebrower@usa.net) + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/fs.h> +#include <linux/errno.h> +#include <linux/major.h> +#include <linux/init.h> +#include <linux/miscdevice.h> +#include <linux/ioport.h> /* request_region, check_region */ +#include <asm/ebus.h> /* EBus device */ +#include <asm/oplib.h> /* OpenProm Library */ +#include <asm/uaccess.h> /* put_/get_user_ret */ + +#include <asm/display7seg.h> + +#define D7S_MINOR 193 +#define D7S_OBPNAME "display7seg" +#define D7S_DEVNAME "d7s" + +static int sol_compat = 0; /* Solaris compatibility mode */ + +#ifdef MODULE +EXPORT_NO_SYMBOLS; + +/* Solaris compatibility flag - + * The Solaris implementation omits support for several + * documented driver features (ref Sun doc 806-0180-03). + * By default, this module supports the documented driver + * abilities, rather than the Solaris implementation: + * + * 1) Device ALWAYS reverts to OBP-specified FLIPPED mode + * upon closure of device or module unload. + * 2) Device ioctls D7SIOCRD/D7SIOCWR honor toggling of + * FLIP bit + * + * If you wish the device to operate as under Solaris, + * omitting above features, set this parameter to non-zero. + */ +MODULE_PARM + (sol_compat, "1i"); +MODULE_PARM_DESC + (sol_compat, + "Disables documented functionality omitted from Solaris driver"); + +MODULE_AUTHOR + ("Eric Brower <ebrower@usa.net>"); +MODULE_DESCRIPTION + ("7-Segment Display driver for Sun Microsystems CP1400/1500"); +MODULE_SUPPORTED_DEVICE + ("d7s"); +#endif /* ifdef MODULE */ + +/* + * Register block address- see header for details + * ----------------------------------------- + * | DP | ALARM | FLIP | 4 | 3 | 2 | 1 | 0 | + * ----------------------------------------- + * + * DP - Toggles decimal point on/off + * ALARM - Toggles "Alarm" LED green/red + * FLIP - Inverts display for upside-down mounted board + * bits 0-4 - 7-segment display contents + */ +volatile u8* d7s_regs = 0; + +static inline void d7s_free(void) +{ + iounmap(d7s_regs); +} + +static inline int d7s_obpflipped(void) +{ + int opt_node; + + opt_node = prom_getchild(prom_root_node); + opt_node = prom_searchsiblings(opt_node, "options"); + return ((-1 != prom_getintdefault(opt_node, "d7s-flipped?", -1)) ? 0 : 1); +} + +static int d7s_open(struct inode *inode, struct file *f) +{ + if (D7S_MINOR != MINOR(inode->i_rdev)) + return -ENODEV; + + MOD_INC_USE_COUNT; + return 0; +} + +static int d7s_release(struct inode *inode, struct file *f) +{ + if (D7S_MINOR != MINOR(inode->i_rdev)) + return -ENODEV; + + MOD_DEC_USE_COUNT; + + /* Reset flipped state to OBP default only if + * no other users have the device open and we + * are not operating in solaris-compat mode + */ + if (0 == MOD_IN_USE && 0 == sol_compat) { + int regval = 0; + + regval = readb(d7s_regs); + (0 == d7s_obpflipped()) ? + writeb(regval |= D7S_FLIP, d7s_regs): + writeb(regval &= ~D7S_FLIP, d7s_regs); + } + + return 0; +} + +static int d7s_ioctl(struct inode *inode, struct file *f, + unsigned int cmd, unsigned long arg) +{ + __u8 regs = readb(d7s_regs); + __u8 ireg = 0; + + if (D7S_MINOR != MINOR(inode->i_rdev)) + return -ENODEV; + + switch (cmd) { + case D7SIOCWR: + /* assign device register values + * we mask-out D7S_FLIP if in sol_compat mode + */ + get_user_ret(ireg, (int *) arg, -EFAULT); + if (0 != sol_compat) { + (regs & D7S_FLIP) ? + (ireg |= D7S_FLIP) : (ireg &= ~D7S_FLIP); + } + writeb(ireg, d7s_regs); + break; + + case D7SIOCRD: + /* retrieve device register values + * NOTE: Solaris implementation returns D7S_FLIP bit + * as toggled by user, even though it does not honor it. + * This driver will not misinform you about the state + * of your hardware while in sol_compat mode + */ + put_user_ret(regs, (int *) arg, -EFAULT); + break; + + case D7SIOCTM: + /* toggle device mode-- flip display orientation */ + (regs & D7S_FLIP) ? + (regs &= ~D7S_FLIP) : (regs |= D7S_FLIP); + writeb(regs, d7s_regs); + break; + }; + + return 0; +} + +static struct file_operations d7s_fops = { + owner: THIS_MODULE, + ioctl: d7s_ioctl, + open: d7s_open, + release: d7s_release, +}; + +static struct miscdevice d7s_miscdev = { D7S_MINOR, D7S_DEVNAME, &d7s_fops }; + +#ifdef MODULE +int init_module(void) +#else +int __init d7s_init(void) +#endif +{ + struct linux_ebus *ebus = NULL; + struct linux_ebus_device *edev = NULL; + int iTmp = 0, regs = 0; + + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, D7S_OBPNAME)) + goto ebus_done; + } + } + +ebus_done: + if(!edev) { + printk("%s: unable to locate device\n", D7S_DEVNAME); + return -ENODEV; + } + + d7s_regs = ioremap(edev->resource[0].start, sizeof(__u8)); + + iTmp = misc_register(&d7s_miscdev); + if (0 != iTmp) { + printk("%s: unable to acquire miscdevice minor %i\n", + D7S_DEVNAME, D7S_MINOR); + return iTmp; + } + + /* OBP option "d7s-flipped?" is honored as default + * for the device, and reset default when detached + */ + regs = readb(d7s_regs); + iTmp = d7s_obpflipped(); + (0 == iTmp) ? + writeb(regs |= D7S_FLIP, d7s_regs): + writeb(regs &= ~D7S_FLIP, d7s_regs); + + printk("%s: 7-Segment Display%s at 0x%lx %s\n", + D7S_DEVNAME, + (0 == iTmp) ? (" (FLIPPED)") : (""), + edev->resource[0].start, + (0 != sol_compat) ? ("in sol_compat mode") : ("")); + + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + int regs = readb(d7s_regs); + + /* Honor OBP d7s-flipped? unless operating in solaris-compat mode */ + if (0 == sol_compat) { + (0 == d7s_obpflipped()) ? + writeb(regs |= D7S_FLIP, d7s_regs): + writeb(regs &= ~D7S_FLIP, d7s_regs); + } + + misc_deregister(&d7s_miscdev); + d7s_free(); +} +#endif diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index ebe4e33ba..ba6cc03cf 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -62,6 +62,8 @@ 1.02.00.001 - Added support for full command packet posts through ioctls for 3DM. Bug fix so hot spare drives don't show up. + 1.02.00.002 - Fix bug with tw_setfeature() call that caused oops on some + systems. */ #include <linux/module.h> @@ -107,7 +109,7 @@ static struct notifier_block tw_notifier = { }; /* Globals */ -char *tw_driver_version="1.02.00.001"; +char *tw_driver_version="1.02.00.002"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; @@ -747,7 +749,7 @@ int tw_findcards(Scsi_Host_Template *tw_host) kfree(tw_dev); /* Tell the firmware we support shutdown notification*/ - tw_setfeature(tw_dev, 2, 1, &c); + tw_setfeature(tw_dev2, 2, 1, &c); } if (numcards == 0) diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index e5c5ca10f..9ebe9e927 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -66,6 +66,18 @@ /* 3.60.01 - Remove bogus error check in passthru routine */ /* 3.60.02 - Make DCDB direction based on lookup table */ /* - Only allow one DCDB command to a SCSI ID at a time */ +/* 4.00.00 - Add support for ServeRAID 4 */ +/* 4.00.01 - Add support for First Failure Data Capture */ +/* 4.00.02 - Fix problem with PT DCDB with no buffer */ +/* 4.00.03 - Add alternative passthru interface */ +/* - Add ability to flash ServeRAID BIOS */ +/* 4.00.04 - Rename structures/constants to be prefixed with IPS_ */ +/* 4.00.05 - Remove wish_block from init routine */ +/* - Use linux/spinlock.h instead of asm/spinlock.h for kernels */ +/* 2.3.18 and later */ +/* - Sync with other changes from the 2.3 kernels */ +/* 4.00.06 - Fix timeout with initial FFDC command */ +/* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig <hch@caldera.de> */ /* */ /*****************************************************************************/ @@ -78,9 +90,7 @@ * */ -#if defined (MODULE) - #include <linux/module.h> -#endif /* MODULE */ +#include <linux/module.h> #include <asm/io.h> #include <asm/byteorder.h> @@ -110,14 +120,33 @@ #include <linux/stat.h> #include <linux/config.h> + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,18) #include <linux/spinlock.h> +#else +#include <asm/spinlock.h> +#endif + #include <linux/smp.h> /* * DRIVER_VER */ -#define IPS_VERSION_HIGH "3.60" /* MUST be 4 chars */ -#define IPS_VERSION_LOW ".02 " /* MUST be 4 chars */ +#define IPS_VERSION_HIGH "4.00" /* MUST be 4 chars */ +#define IPS_VERSION_LOW ".06 " /* MUST be 4 chars */ + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27) +struct proc_dir_entry proc_scsi_ips = { +#if !defined(PROC_SCSI_IPS) + 0, /* Use dynamic inode allocation */ +#else + PROC_SCSI_IPS, +#endif + 3, "ips", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +} +; +#endif #if !defined(__i386__) #error "This driver has only been tested on the x86 platform" @@ -132,7 +161,7 @@ #endif #if IPS_DEBUG >= 12 - #define DBG(s) printk(KERN_NOTICE s "\n"); MDELAY(2*ONE_SEC) + #define DBG(s) printk(KERN_NOTICE s "\n"); MDELAY(2*IPS_ONE_SEC) #elif IPS_DEBUG >= 11 #define DBG(s) printk(KERN_NOTICE s "\n") #else @@ -149,7 +178,7 @@ static unsigned int ips_num_controllers = 0; static int ips_cmd_timeout = 60; static int ips_reset_timeout = 60 * 5; -#define MAX_ADAPTER_NAME 6 +#define MAX_ADAPTER_NAME 7 static char ips_adapter_name[][30] = { "ServeRAID", @@ -157,64 +186,65 @@ static char ips_adapter_name[][30] = { "ServeRAID on motherboard", "ServeRAID on motherboard", "ServeRAID 3H", - "ServeRAID 3L" + "ServeRAID 3L", + "ServeRAID 4H" }; /* * Direction table */ static char ips_command_direction[] = { -IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, -IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, -IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, -IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_OUT, -IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_OUT, -IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_IN, -IPS_DATA_UNK, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_UNK, -IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, -IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_NONE, -IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, -IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, -IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_NONE, -IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, -IPS_DATA_NONE, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_NONE, -IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_OUT, -IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_NONE, -IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_OUT, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK +IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, +IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, +IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, +IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_OUT, +IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_OUT, +IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_IN, +IPS_DATA_UNK, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_UNK, +IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, +IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_NONE, +IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, +IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, +IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_NONE, +IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, +IPS_DATA_NONE, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_NONE, +IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_OUT, +IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_NONE, +IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_OUT, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK }; /* @@ -232,8 +262,8 @@ const char * ips_info(struct Scsi_Host *); void do_ipsintr(int, void *, struct pt_regs *); static int ips_hainit(ips_ha_t *); static int ips_map_status(ips_scb_t *, ips_stat_t *); -static int ips_send(ips_ha_t *, ips_scb_t *, scb_callback); -static int ips_send_wait(ips_ha_t *, ips_scb_t *, int); +static int ips_send(ips_ha_t *, ips_scb_t *, ips_scb_callback); +static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int); static int ips_send_cmd(ips_ha_t *, ips_scb_t *); static int ips_chkstatus(ips_ha_t *); static int ips_online(ips_ha_t *, ips_scb_t *); @@ -247,14 +277,14 @@ static int ips_statupd(ips_ha_t *); static int ips_issue(ips_ha_t *, ips_scb_t *); static int ips_isintr(ips_ha_t *); static int ips_wait(ips_ha_t *, int, int); -static int ips_write_driver_status(ips_ha_t *); -static int ips_read_adapter_status(ips_ha_t *); -static int ips_read_subsystem_parameters(ips_ha_t *); -static int ips_read_config(ips_ha_t *); -static int ips_clear_adapter(ips_ha_t *); -static int ips_readwrite_page5(ips_ha_t *, int); +static int ips_write_driver_status(ips_ha_t *, int); +static int ips_read_adapter_status(ips_ha_t *, int); +static int ips_read_subsystem_parameters(ips_ha_t *, int); +static int ips_read_config(ips_ha_t *, int); +static int ips_clear_adapter(ips_ha_t *, int); +static int ips_readwrite_page5(ips_ha_t *, int, int); static void ips_intr(ips_ha_t *); -static void ips_next(ips_ha_t *); +static void ips_next(ips_ha_t *, int); static void ipsintr_blocking(ips_ha_t *, struct ips_scb *); static void ipsintr_done(ips_ha_t *, struct ips_scb *); static void ips_done(ips_ha_t *, ips_scb_t *); @@ -262,6 +292,9 @@ static void ips_free(ips_ha_t *); static void ips_init_scb(ips_ha_t *, ips_scb_t *); static void ips_freescb(ips_ha_t *, ips_scb_t *); static void ips_statinit(ips_ha_t *); +static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t); +static void ips_ffdc_reset(ips_ha_t *, int); +static void ips_ffdc_time(ips_ha_t *, int); static ips_scb_t * ips_getscb(ips_ha_t *); static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *); static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *); @@ -271,17 +304,26 @@ static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *); static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *); static inline Scsi_Cmnd * ips_removeq_wait_head(ips_wait_queue_t *); static inline Scsi_Cmnd * ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *); +static inline void ips_putq_copp_head(ips_copp_queue_t *, ips_copp_wait_item_t *); +static inline void ips_putq_copp_tail(ips_copp_queue_t *, ips_copp_wait_item_t *); +static inline ips_copp_wait_item_t * ips_removeq_copp(ips_copp_queue_t *, ips_copp_wait_item_t *); +static inline ips_copp_wait_item_t * ips_removeq_copp_head(ips_copp_queue_t *); +static int ips_erase_bios(ips_ha_t *); +static int ips_program_bios(ips_ha_t *, char *, int); +static int ips_verify_bios(ips_ha_t *, char *, int); #ifndef NO_IPS_CMDLINE static int ips_is_passthru(Scsi_Cmnd *); static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *); static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *); +static int ips_newusrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *); +static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *); #endif int ips_proc_info(char *, char **, off_t, int, int, int); static int ips_host_info(ips_ha_t *, char *, off_t, int); -static void copy_mem_info(INFOSTR *, char *, int); -static int copy_info(INFOSTR *, char *, ...); +static void copy_mem_info(IPS_INFOSTR *, char *, int); +static int copy_info(IPS_INFOSTR *, char *, ...); /*--------------------------------------------------------------------------*/ /* Exported Functions */ @@ -295,6 +337,8 @@ static int copy_info(INFOSTR *, char *, ...); /* */ /* Detect and initialize the driver */ /* */ +/* NOTE: this routine is called under the io_request_lock spinlock */ +/* */ /****************************************************************************/ int ips_detect(Scsi_Host_Template *SHT) { @@ -302,6 +346,7 @@ ips_detect(Scsi_Host_Template *SHT) { ips_ha_t *ha; u32 io_addr; u16 planer; + u8 revision_id; u8 bus; u8 func; u8 irq; @@ -311,7 +356,11 @@ ips_detect(Scsi_Host_Template *SHT) { DBG("ips_detect"); SHT->proc_info = ips_proc_info; +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27) + SHT->proc_dir = &proc_scsi_ips; +#else SHT->proc_name = "ips"; +#endif #if defined(CONFIG_PCI) @@ -325,26 +374,27 @@ ips_detect(Scsi_Host_Template *SHT) { if (!(dev = pci_find_device(IPS_VENDORID, IPS_DEVICEID, dev))) break; + if (pci_enable_device(dev)) - break; + break; + /* stuff that we get in dev */ irq = dev->irq; bus = dev->bus->number; func = dev->devfn; io_addr = pci_resource_start(dev, 0); + + /* check I/O address */ + if (pci_resource_flags(dev, 0) & IORESOURCE_MEM) + continue; /* get planer status */ if (pci_read_config_word(dev, 0x04, &planer)) { printk(KERN_WARNING "(%s%d) can't get planer status.\n", ips_name, index); - continue; } - /* check I/O address */ - if (pci_resource_flags(dev, 0) & IORESOURCE_MEM) - continue; - /* check to see if an onboard planer controller is disabled */ if (!(planer & 0x000C)) { @@ -361,6 +411,14 @@ ips_detect(Scsi_Host_Template *SHT) { ips_name, index, bus, func, irq, io_addr); #endif + /* get the revision ID */ + if (pci_read_config_byte(dev, 0x08, &revision_id)) { + printk(KERN_WARNING "(%s%d) can't get revision id.\n", + ips_name, index); + + continue; + } + /* found a controller */ sh = scsi_register(SHT, sizeof(ips_ha_t)); @@ -371,19 +429,23 @@ ips_detect(Scsi_Host_Template *SHT) { continue; } - ha = HA(sh); + ha = IPS_HA(sh); memset(ha, 0, sizeof(ips_ha_t)); /* Initialize spin lock */ spin_lock_init(&ha->scb_lock); spin_lock_init(&ha->copp_lock); + spin_lock_init(&ha->ips_lock); + spin_lock_init(&ha->copp_waitlist.lock); + spin_lock_init(&ha->scb_waitlist.lock); + spin_lock_init(&ha->scb_activelist.lock); ips_sh[ips_num_controllers] = sh; ips_ha[ips_num_controllers] = ha; ips_num_controllers++; ha->active = 1; - ha->enq = kmalloc(sizeof(ENQCMD), GFP_KERNEL|GFP_DMA); + ha->enq = kmalloc(sizeof(IPS_ENQ), GFP_KERNEL|GFP_DMA); if (!ha->enq) { printk(KERN_WARNING "(%s%d) Unable to allocate host inquiry structure - skipping contoller\n", @@ -394,7 +456,7 @@ ips_detect(Scsi_Host_Template *SHT) { continue; } - ha->adapt = kmalloc(sizeof(ADAPTER_AREA), GFP_KERNEL|GFP_DMA); + ha->adapt = kmalloc(sizeof(IPS_ADAPTER), GFP_KERNEL|GFP_DMA); if (!ha->adapt) { printk(KERN_WARNING "(%s%d) Unable to allocate host adapt structure - skipping controller\n", @@ -405,7 +467,7 @@ ips_detect(Scsi_Host_Template *SHT) { continue; } - ha->conf = kmalloc(sizeof(CONFCMD), GFP_KERNEL|GFP_DMA); + ha->conf = kmalloc(sizeof(IPS_CONF), GFP_KERNEL|GFP_DMA); if (!ha->conf) { printk(KERN_WARNING "(%s%d) Unable to allocate host conf structure - skipping controller\n", @@ -416,7 +478,7 @@ ips_detect(Scsi_Host_Template *SHT) { continue; } - ha->nvram = kmalloc(sizeof(NVRAM_PAGE5), GFP_KERNEL|GFP_DMA); + ha->nvram = kmalloc(sizeof(IPS_NVRAM_P5), GFP_KERNEL|GFP_DMA); if (!ha->nvram) { printk(KERN_WARNING "(%s%d) Unable to allocate host nvram structure - skipping controller\n", @@ -427,7 +489,7 @@ ips_detect(Scsi_Host_Template *SHT) { continue; } - ha->subsys = kmalloc(sizeof(SUBSYS_PARAM), GFP_KERNEL|GFP_DMA); + ha->subsys = kmalloc(sizeof(IPS_SUBSYS), GFP_KERNEL|GFP_DMA); if (!ha->subsys) { printk(KERN_WARNING "(%s%d) Unable to allocate host subsystem structure - skipping controller\n", @@ -438,7 +500,7 @@ ips_detect(Scsi_Host_Template *SHT) { continue; } - ha->dummy = kmalloc(sizeof(BASIC_IO_CMD), GFP_KERNEL|GFP_DMA); + ha->dummy = kmalloc(sizeof(IPS_IO_CMD), GFP_KERNEL|GFP_DMA); if (!ha->dummy) { printk(KERN_WARNING "(%s%d) Unable to allocate host dummy structure - skipping controller\n", @@ -449,6 +511,17 @@ ips_detect(Scsi_Host_Template *SHT) { continue; } + ha->ioctl_data = kmalloc(IPS_IOCTL_SIZE, GFP_KERNEL|GFP_DMA); + ha->ioctl_datasize = IPS_IOCTL_SIZE; + if (!ha->ioctl_data) { + printk(KERN_WARNING "(%s%d) Unable to allocate ioctl data - skipping controller\n", + ips_name, index); + + ha->active = 0; + + continue; + } + /* Store away needed values for later use */ sh->io_port = io_addr; sh->n_io_port = 255; @@ -465,6 +538,7 @@ ips_detect(Scsi_Host_Template *SHT) { ha->io_addr = io_addr; ha->irq = irq; ha->host_num = index; + ha->revision_id = revision_id; /* install the interrupt handler */ if (request_irq(irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) { @@ -491,7 +565,7 @@ ips_detect(Scsi_Host_Template *SHT) { } memset(ha->scbs, 0, sizeof(ips_scb_t)); - ha->scbs->sg_list = (SG_LIST *) kmalloc(sizeof(SG_LIST) * MAX_SG_ELEMENTS, GFP_KERNEL|GFP_DMA); + ha->scbs->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_KERNEL|GFP_DMA); if (!ha->scbs->sg_list) { /* couldn't allocate a temp SCB S/G list */ printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n", @@ -569,7 +643,7 @@ ips_release(struct Scsi_Host *sh) { panic("(%s) release, invalid Scsi_Host pointer.\n", ips_name); - ha = HA(sh); + ha = IPS_HA(sh); if (!ha) return (FALSE); @@ -580,11 +654,11 @@ ips_release(struct Scsi_Host *sh) { ips_init_scb(ha, scb); scb->timeout = ips_cmd_timeout; - scb->cdb[0] = FLUSH_CACHE; + scb->cdb[0] = IPS_CMD_FLUSH; - scb->cmd.flush_cache.op_code = FLUSH_CACHE; + scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH; scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb); - scb->cmd.flush_cache.state = NORM_STATE; + scb->cmd.flush_cache.state = IPS_NORM_STATE; scb->cmd.flush_cache.reserved = 0; scb->cmd.flush_cache.reserved2 = 0; scb->cmd.flush_cache.reserved3 = 0; @@ -593,7 +667,7 @@ ips_release(struct Scsi_Host *sh) { printk("(%s%d) Flushing Cache.\n", ips_name, ha->host_num); /* send command */ - if (ips_send_wait(ha, scb, ips_cmd_timeout) == IPS_FAILURE) + if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) == IPS_FAILURE) printk("(%s%d) Incomplete Flush.\n", ips_name, ha->host_num); printk("(%s%d) Flushing Complete.\n", ips_name, ha->host_num); @@ -625,6 +699,7 @@ ips_release(struct Scsi_Host *sh) { int ips_eh_abort(Scsi_Cmnd *SC) { ips_ha_t *ha; + ips_copp_wait_item_t *item; DBG("ips_eh_abort"); @@ -651,9 +726,23 @@ ips_eh_abort(Scsi_Cmnd *SC) { if (test_and_set_bit(IPS_IN_ABORT, &ha->flags)) return (FAILED); + /* See if the command is on the copp queue */ + IPS_QUEUE_LOCK(&ha->copp_waitlist); + item = ha->copp_waitlist.head; + while ((item) && (item->scsi_cmd != SC)) + item = item->next; + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + + if (item) { + /* Found it */ + ips_removeq_copp(&ha->copp_waitlist, item); + clear_bit(IPS_IN_ABORT, &ha->flags); + + return (SUCCESS); + } + /* See if the command is on the wait queue */ - if (ips_removeq_wait(&ha->scb_waitlist, SC) || - ips_removeq_wait(&ha->copp_waitlist, SC)) { + if (ips_removeq_wait(&ha->scb_waitlist, SC)) { /* command not sent yet */ clear_bit(IPS_IN_ABORT, &ha->flags); @@ -678,6 +767,7 @@ ips_eh_abort(Scsi_Cmnd *SC) { int ips_abort(Scsi_Cmnd *SC) { ips_ha_t *ha; + ips_copp_wait_item_t *item; DBG("ips_abort"); @@ -704,9 +794,23 @@ ips_abort(Scsi_Cmnd *SC) { if (test_and_set_bit(IPS_IN_ABORT, &ha->flags)) return (SCSI_ABORT_SNOOZE); + /* See if the command is on the copp queue */ + IPS_QUEUE_LOCK(&ha->copp_waitlist); + item = ha->copp_waitlist.head; + while ((item) && (item->scsi_cmd != SC)) + item = item->next; + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + + if (item) { + /* Found it */ + ips_removeq_copp(&ha->copp_waitlist, item); + clear_bit(IPS_IN_ABORT, &ha->flags); + + return (SCSI_ABORT_PENDING); + } + /* See if the command is on the wait queue */ - if (ips_removeq_wait(&ha->scb_waitlist, SC) || - ips_removeq_wait(&ha->copp_waitlist, SC)) { + if (ips_removeq_wait(&ha->scb_waitlist, SC)) { /* command not sent yet */ clear_bit(IPS_IN_ABORT, &ha->flags); @@ -727,11 +831,15 @@ ips_abort(Scsi_Cmnd *SC) { /* */ /* Reset the controller (with new eh error code) */ /* */ +/* NOTE: this routine is called under the io_request_lock spinlock */ +/* */ /****************************************************************************/ int ips_eh_reset(Scsi_Cmnd *SC) { - ips_ha_t *ha; - ips_scb_t *scb; + u32 cpu_flags; + ips_ha_t *ha; + ips_scb_t *scb; + ips_copp_wait_item_t *item; DBG("ips_eh_reset"); @@ -765,11 +873,25 @@ ips_eh_reset(Scsi_Cmnd *SC) { if (test_and_set_bit(IPS_IN_RESET, &ha->flags)) return (FAILED); - /* See if the command is on the waiting queue */ - if (ips_removeq_wait(&ha->scb_waitlist, SC) || - ips_removeq_wait(&ha->copp_waitlist, SC)) { + /* See if the command is on the copp queue */ + IPS_QUEUE_LOCK(&ha->copp_waitlist); + item = ha->copp_waitlist.head; + while ((item) && (item->scsi_cmd != SC)) + item = item->next; + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + + if (item) { + /* Found it */ + ips_removeq_copp(&ha->copp_waitlist, item); + clear_bit(IPS_IN_RESET, &ha->flags); + + return (SUCCESS); + } + + /* See if the command is on the wait queue */ + if (ips_removeq_wait(&ha->scb_waitlist, SC)) { /* command not sent yet */ - clear_bit(IPS_IN_ABORT, &ha->flags); + clear_bit(IPS_IN_RESET, &ha->flags); return (SUCCESS); } @@ -784,25 +906,39 @@ ips_eh_reset(Scsi_Cmnd *SC) { return (FAILED); } - if (!ips_clear_adapter(ha)) { + if (!ips_clear_adapter(ha, IPS_INTR_IORL)) { clear_bit(IPS_IN_RESET, &ha->flags); return (FAILED); } + /* FFDC */ + if (ha->subsys->param[3] & 0x300000) { + struct timeval tv; + + do_gettimeofday(&tv); + IPS_HA_LOCK(cpu_flags); + ha->last_ffdc = tv.tv_sec; + ha->reset_count++; + IPS_HA_UNLOCK(cpu_flags); + ips_ffdc_reset(ha, IPS_INTR_IORL); + } + /* Now fail all of the active commands */ #if IPS_DEBUG >= 1 printk(KERN_WARNING "(%s%d) Failing active commands\n", ips_name, ha->host_num); #endif while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) { - scb->scsi_cmd->result = DID_RESET << 16; + scb->scsi_cmd->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24); scb->scsi_cmd->scsi_done(scb->scsi_cmd); ips_freescb(ha, scb); } /* Reset the number of active IOCTLs */ + IPS_HA_LOCK(cpu_flags); ha->num_ioctl = 0; + IPS_HA_UNLOCK(cpu_flags); clear_bit(IPS_IN_RESET, &ha->flags); @@ -814,7 +950,7 @@ ips_eh_reset(Scsi_Cmnd *SC) { * handler wants to do this and since * interrupts are turned off here.... */ - ips_next(ha); + ips_next(ha, IPS_INTR_IORL); } return (SUCCESS); @@ -831,11 +967,15 @@ ips_eh_reset(Scsi_Cmnd *SC) { /* */ /* Reset the controller */ /* */ +/* NOTE: this routine is called under the io_request_lock spinlock */ +/* */ /****************************************************************************/ int ips_reset(Scsi_Cmnd *SC, unsigned int flags) { - ips_ha_t *ha; - ips_scb_t *scb; + u32 cpu_flags; + ips_ha_t *ha; + ips_scb_t *scb; + ips_copp_wait_item_t *item; DBG("ips_reset"); @@ -869,11 +1009,25 @@ ips_reset(Scsi_Cmnd *SC, unsigned int flags) { if (test_and_set_bit(IPS_IN_RESET, &ha->flags)) return (SCSI_RESET_SNOOZE); - /* See if the command is on the waiting queue */ - if (ips_removeq_wait(&ha->scb_waitlist, SC) || - ips_removeq_wait(&ha->copp_waitlist, SC)) { + /* See if the command is on the copp queue */ + IPS_QUEUE_LOCK(&ha->copp_waitlist); + item = ha->copp_waitlist.head; + while ((item) && (item->scsi_cmd != SC)) + item = item->next; + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + + if (item) { + /* Found it */ + ips_removeq_copp(&ha->copp_waitlist, item); + clear_bit(IPS_IN_RESET, &ha->flags); + + return (SCSI_RESET_SNOOZE); + } + + /* See if the command is on the wait queue */ + if (ips_removeq_wait(&ha->scb_waitlist, SC)) { /* command not sent yet */ - clear_bit(IPS_IN_ABORT, &ha->flags); + clear_bit(IPS_IN_RESET, &ha->flags); return (SCSI_RESET_SNOOZE); } @@ -885,25 +1039,39 @@ ips_reset(Scsi_Cmnd *SC, unsigned int flags) { return (SCSI_RESET_ERROR); } - if (!ips_clear_adapter(ha)) { + if (!ips_clear_adapter(ha, IPS_INTR_IORL)) { clear_bit(IPS_IN_RESET, &ha->flags); return (SCSI_RESET_ERROR); } + /* FFDC */ + if (ha->subsys->param[3] & 0x300000) { + struct timeval tv; + + do_gettimeofday(&tv); + IPS_HA_LOCK(cpu_flags); + ha->last_ffdc = tv.tv_sec; + ha->reset_count++; + IPS_HA_UNLOCK(cpu_flags); + ips_ffdc_reset(ha, IPS_INTR_IORL); + } + /* Now fail all of the active commands */ #if IPS_DEBUG >= 1 printk(KERN_WARNING "(%s%d) Failing active commands\n", ips_name, ha->host_num); #endif while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) { - scb->scsi_cmd->result = DID_RESET << 16; + scb->scsi_cmd->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24); scb->scsi_cmd->scsi_done(scb->scsi_cmd); ips_freescb(ha, scb); } /* Reset the number of active IOCTLs */ + IPS_HA_LOCK(cpu_flags); ha->num_ioctl = 0; + IPS_HA_UNLOCK(cpu_flags); clear_bit(IPS_IN_RESET, &ha->flags); @@ -915,7 +1083,7 @@ ips_reset(Scsi_Cmnd *SC, unsigned int flags) { * handler wants to do this and since * interrupts are turned off here.... */ - ips_next(ha); + ips_next(ha, IPS_INTR_IORL); } return (SCSI_RESET_SUCCESS); @@ -932,10 +1100,15 @@ ips_reset(Scsi_Cmnd *SC, unsigned int flags) { /* */ /* Send a command to the controller */ /* */ +/* NOTE: */ +/* Linux obtains io_request_lock before calling this function */ +/* */ /****************************************************************************/ int ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) { ips_ha_t *ha; + u32 cpu_flags; + DECLARE_MUTEX_LOCKED(sem); DBG("ips_queue"); @@ -949,19 +1122,27 @@ ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) { #ifndef NO_IPS_CMDLINE if (ips_is_passthru(SC)) { + IPS_QUEUE_LOCK(&ha->copp_waitlist); if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) { + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); SC->result = DID_BUS_BUSY << 16; done(SC); return (0); + } else { + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); } } else { #endif + IPS_QUEUE_LOCK(&ha->scb_waitlist); if (ha->scb_waitlist.count == IPS_MAX_QUEUE) { + IPS_QUEUE_UNLOCK(&ha->scb_waitlist); SC->result = DID_BUS_BUSY << 16; done(SC); return (0); + } else { + IPS_QUEUE_UNLOCK(&ha->scb_waitlist); } #ifndef NO_IPS_CMDLINE @@ -978,21 +1159,82 @@ ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) { SC->target, SC->lun); #if IPS_DEBUG >= 11 - MDELAY(2*ONE_SEC); + MDELAY(2*IPS_ONE_SEC); #endif #endif #ifndef NO_IPS_CMDLINE - if (ips_is_passthru(SC)) - ips_putq_wait_tail(&ha->copp_waitlist, SC); + if (ips_is_passthru(SC)) { + ips_copp_wait_item_t *scratch; + + /* allocate space for the scribble */ + scratch = kmalloc(sizeof(ips_copp_wait_item_t), GFP_KERNEL); + + if (!scratch) { + SC->result = DID_ERROR << 16; + done(SC); + + return (0); + } + + scratch->scsi_cmd = SC; + scratch->sem = &sem; + scratch->next = NULL; + + ips_putq_copp_tail(&ha->copp_waitlist, scratch); + } else #endif ips_putq_wait_tail(&ha->scb_waitlist, SC); + IPS_HA_LOCK(cpu_flags); if ((!test_bit(IPS_IN_INTR, &ha->flags)) && (!test_bit(IPS_IN_ABORT, &ha->flags)) && - (!test_bit(IPS_IN_RESET, &ha->flags))) - ips_next(ha); + (!test_bit(IPS_IN_RESET, &ha->flags))) { + IPS_HA_UNLOCK(cpu_flags); + ips_next(ha, IPS_INTR_IORL); + } else { + IPS_HA_UNLOCK(cpu_flags); + } + + /* + * If this request was a new style IOCTL wait + * for it to finish. + * + * NOTE: we relinquished the lock above so this should + * not cause contention problems + */ + if (ips_is_passthru(SC) && SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) { + char *user_area; + char *kern_area; + u32 datasize; + + /* free io_request_lock */ + spin_unlock_irq(&io_request_lock); + + /* wait for the command to finish */ + down(&sem); + + /* reobtain the lock */ + spin_lock_irq(&io_request_lock); + + /* command finished -- copy back */ + user_area = *((char **) &SC->cmnd[4]); + kern_area = ha->ioctl_data; + datasize = *((u32 *) &SC->cmnd[8]); + + if (copy_to_user(user_area, kern_area, datasize) > 0) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) passthru failed - unable to copy out user data\n", + ips_name, ha->host_num); +#endif + + SC->result = DID_ERROR << 16; + SC->scsi_done(SC); + } else { + SC->scsi_done(SC); + } + } return (0); } @@ -1024,17 +1266,17 @@ ips_biosparam(Disk *disk, kdev_t dev, int geom[]) { if (!ha->active) return (0); - if (!ips_read_adapter_status(ha)) + if (!ips_read_adapter_status(ha, IPS_INTR_ON)) /* ?!?! Enquiry command failed */ return (0); if ((disk->capacity > 0x400000) && ((ha->enq->ucMiscFlag & 0x8) == 0)) { - heads = NORM_MODE_HEADS; - sectors = NORM_MODE_SECTORS; + heads = IPS_NORM_HEADS; + sectors = IPS_NORM_SECTORS; } else { - heads = COMP_MODE_HEADS; - sectors = COMP_MODE_SECTORS; + heads = IPS_COMP_HEADS; + sectors = IPS_COMP_SECTORS; } cylinders = disk->capacity / (heads * sectors); @@ -1063,7 +1305,7 @@ ips_biosparam(Disk *disk, kdev_t dev, int geom[]) { void do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) { ips_ha_t *ha; - unsigned int cpu_flags; + u32 cpu_flags; DBG("do_ipsintr"); @@ -1096,6 +1338,9 @@ do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) { clear_bit(IPS_IN_INTR, &ha->flags); spin_unlock_irqrestore(&io_request_lock, cpu_flags); + + /* start the next command */ + ips_next(ha, IPS_INTR_ON); } /****************************************************************************/ @@ -1114,6 +1359,7 @@ ips_intr(ips_ha_t *ha) { ips_stat_t *sp; ips_scb_t *scb; int status; + u32 cpu_flags; DBG("ips_intr"); @@ -1123,6 +1369,7 @@ ips_intr(ips_ha_t *ha) { if (!ha->active) return; + IPS_HA_LOCK(cpu_flags); while (ips_isintr(ha)) { sp = &ha->sp; @@ -1139,10 +1386,12 @@ ips_intr(ips_ha_t *ha) { * use the callback function to finish things up * NOTE: interrupts are OFF for this */ + IPS_HA_UNLOCK(cpu_flags); (*scb->callback) (ha, scb); + IPS_HA_LOCK(cpu_flags); } - clear_bit(IPS_IN_INTR, &ha->flags); + IPS_HA_UNLOCK(cpu_flags); } /****************************************************************************/ @@ -1162,7 +1411,7 @@ ips_info(struct Scsi_Host *SH) { DBG("ips_info"); - ha = HA(SH); + ha = IPS_HA(SH); if (!ha) return (NULL); @@ -1250,10 +1499,10 @@ ips_is_passthru(Scsi_Cmnd *SC) { if (!SC) return (0); - if ((SC->channel == 0) && + if (((SC->cmnd[0] == IPS_IOCTL_COMMAND) || (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND)) && + (SC->channel == 0) && (SC->target == IPS_ADAPTER_ID) && (SC->lun == 0) && - (SC->cmnd[0] == 0x0d) && (SC->request_bufflen) && (!SC->use_sg) && (((char *) SC->request_buffer)[0] == 'C') && @@ -1268,7 +1517,7 @@ ips_is_passthru(Scsi_Cmnd *SC) { /****************************************************************************/ /* */ -/* Routine Name: ips_is_passthru */ +/* Routine Name: ips_make_passthru */ /* */ /* Routine Description: */ /* */ @@ -1315,17 +1564,23 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) { } pt = (ips_passthru_t *) SC->request_buffer; - scb->scsi_cmd = SC; - - if (SC->request_bufflen < (sizeof(ips_passthru_t) + pt->CmdBSize)) { - /* wrong size */ -#if IPS_DEBUG_PT >= 1 - printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n", - ips_name, ha->host_num); -#endif - return (IPS_FAILURE); - } + /* + * Some notes about the passthru interface used + * + * IF the scsi op_code == 0x0d then we assume + * that the data came along with/goes with the + * packet we received from the sg driver. In this + * case the CmdBSize field of the pt structure is + * used for the size of the buffer. + * + * IF the scsi op_code == 0x81 then we assume that + * we will need our own buffer and we will copy the + * data to/from the user buffer passed in the scsi + * command. The data address resides at offset 4 + * in the scsi command. The length of the data resides + * at offset 8 in the scsi command. + */ switch (pt->CoppCmd) { case IPS_NUMCTRLS: @@ -1334,19 +1589,128 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) { SC->result = DID_OK << 16; return (IPS_SUCCESS_IMM); + case IPS_CTRLINFO: memcpy(SC->request_buffer + sizeof(ips_passthru_t), ha, sizeof(ips_ha_t)); SC->result = DID_OK << 16; return (IPS_SUCCESS_IMM); - case COPPUSRCMD: - if (ips_usrcmd(ha, pt, scb)) - return (IPS_SUCCESS); - else - return (IPS_FAILURE); + + case IPS_COPPUSRCMD: + case IPS_COPPIOCCMD: + if (SC->cmnd[0] == IPS_IOCTL_COMMAND) { + if (SC->request_bufflen < (sizeof(ips_passthru_t) + pt->CmdBSize)) { + /* wrong size */ + #if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n", + ips_name, ha->host_num); + #endif + + return (IPS_FAILURE); + } + + if (ips_usrcmd(ha, pt, scb)) + return (IPS_SUCCESS); + else + return (IPS_FAILURE); + } else if (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) { + if (SC->request_bufflen < (sizeof(ips_passthru_t))) { + /* wrong size */ + #if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n", + ips_name, ha->host_num); + #endif + + return (IPS_FAILURE); + } + + if (ips_newusrcmd(ha, pt, scb)) + return (IPS_SUCCESS); + else + return (IPS_FAILURE); + } + break; - } + + case IPS_FLASHBIOS: + /* we must use the new interface */ + if (SC->cmnd[0] != IPS_IOCTL_NEW_COMMAND) + return (IPS_FAILURE); + + /* don't flash the BIOS on future cards */ + if (ha->revision_id > IPS_REVID_TROMBONE64) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) flash bios failed - unsupported controller\n", + ips_name, ha->host_num); +#endif + return (IPS_FAILURE); + } + + /* copy in the size/buffer ptr from the scsi command */ + memcpy(&pt->CmdBuffer, &SC->cmnd[4], 4); + memcpy(&pt->CmdBSize, &SC->cmnd[8], 4); + + /* must have a buffer */ + if ((!pt->CmdBSize) || (!pt->CmdBuffer)) + return (IPS_FAILURE); + + /* make sure buffer is big enough */ + if (pt->CmdBSize > ha->ioctl_datasize) { + void *bigger_struct; + + /* try to allocate a bigger struct */ + bigger_struct = kmalloc(pt->CmdBSize, GFP_KERNEL|GFP_DMA); + if (bigger_struct) { + /* free the old memory */ + kfree(ha->ioctl_data); + + /* use the new memory */ + ha->ioctl_data = bigger_struct; + ha->ioctl_datasize = pt->CmdBSize; + } else + return (IPS_FAILURE); + } + + /* copy in the buffer */ + if (copy_from_user(ha->ioctl_data, pt->CmdBuffer, pt->CmdBSize) > 0) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) flash bios failed - unable to copy user buffer\n", + ips_name, ha->host_num); +#endif + + return (IPS_FAILURE); + } + + if (ips_erase_bios(ha)) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) flash bios failed - unable to erase flash\n", + ips_name, ha->host_num); +#endif + + return (IPS_FAILURE); + } + + if (ips_program_bios(ha, ha->ioctl_data, pt->CmdBSize)) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) flash bios failed - unable to program flash\n", + ips_name, ha->host_num); +#endif + + return (IPS_FAILURE); + } + + if (ips_verify_bios(ha, ha->ioctl_data, pt->CmdBSize)) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) flash bios failed - unable to verify flash\n", + ips_name, ha->host_num); +#endif + + return (IPS_FAILURE); + } + + return (IPS_SUCCESS_IMM); + } /* end switch */ return (IPS_FAILURE); } @@ -1362,7 +1726,7 @@ ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) { /****************************************************************************/ static int ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) { - SG_LIST *sg_list; + IPS_SG_LIST *sg_list; DBG("ips_usrcmd"); @@ -1373,15 +1737,15 @@ ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) { sg_list = scb->sg_list; /* copy in the CP */ - memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IOCTL_INFO)); - memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(DCDB_TABLE)); + memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IPS_IOCTL_CMD)); + memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(IPS_DCDB_TABLE)); /* FIX stuff that might be wrong */ scb->sg_list = sg_list; scb->scb_busaddr = VIRT_TO_BUS(scb); - scb->bus = 0; - scb->target_id = 0; - scb->lun = 0; + scb->bus = scb->scsi_cmd->channel; + scb->target_id = scb->scsi_cmd->target; + scb->lun = scb->scsi_cmd->lun; scb->sg_len = 0; scb->data_len = 0; scb->flags = 0; @@ -1391,9 +1755,9 @@ ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) { scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); /* we don't support DCDB/READ/WRITE Scatter Gather */ - if ((scb->cmd.basic_io.op_code == READ_SCATTER_GATHER) || - (scb->cmd.basic_io.op_code == WRITE_SCATTER_GATHER) || - (scb->cmd.basic_io.op_code == DIRECT_CDB_SCATTER_GATHER)) + if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) || + (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) || + (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG)) return (0); if (pt->CmdBSize) { @@ -1402,13 +1766,129 @@ ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) { scb->data_busaddr = 0L; } + if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) + scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb); + if (pt->CmdBSize) { - if (scb->cmd.dcdb.op_code == DIRECT_CDB) { - scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb); + if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) scb->dcdb.buffer_pointer = scb->data_busaddr; - } else { + else scb->cmd.basic_io.sg_addr = scb->data_busaddr; + } + + /* set timeouts */ + if (pt->TimeOut) { + scb->timeout = pt->TimeOut; + + if (pt->TimeOut <= 10) + scb->dcdb.cmd_attribute |= IPS_TIMEOUT10; + else if (pt->TimeOut <= 60) + scb->dcdb.cmd_attribute |= IPS_TIMEOUT60; + else + scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; + } + + /* assume success */ + scb->scsi_cmd->result = DID_OK << 16; + + /* success */ + return (1); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_newusrcmd */ +/* */ +/* Routine Description: */ +/* */ +/* Process a user command and make it ready to send */ +/* */ +/****************************************************************************/ +static int +ips_newusrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) { + IPS_SG_LIST *sg_list; + char *user_area; + char *kern_area; + u32 datasize; + + DBG("ips_usrcmd"); + + if ((!scb) || (!pt) || (!ha)) + return (0); + + /* Save the S/G list pointer so it doesn't get clobbered */ + sg_list = scb->sg_list; + + /* copy in the CP */ + memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IPS_IOCTL_CMD)); + memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(IPS_DCDB_TABLE)); + + /* FIX stuff that might be wrong */ + scb->sg_list = sg_list; + scb->scb_busaddr = VIRT_TO_BUS(scb); + scb->bus = scb->scsi_cmd->channel; + scb->target_id = scb->scsi_cmd->target; + scb->lun = scb->scsi_cmd->lun; + scb->sg_len = 0; + scb->data_len = 0; + scb->flags = 0; + scb->op_code = 0; + scb->callback = ipsintr_done; + scb->timeout = ips_cmd_timeout; + scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); + + /* we don't support DCDB/READ/WRITE Scatter Gather */ + if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) || + (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) || + (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG)) + return (0); + + if (pt->CmdBSize) { + if (pt->CmdBSize > ha->ioctl_datasize) { + void *bigger_struct; + + /* try to allocate a bigger struct */ + bigger_struct = kmalloc(pt->CmdBSize, GFP_KERNEL|GFP_DMA); + if (bigger_struct) { + /* free the old memory */ + kfree(ha->ioctl_data); + + /* use the new memory */ + ha->ioctl_data = bigger_struct; + ha->ioctl_datasize = pt->CmdBSize; + } else + return (0); + } + + scb->data_busaddr = VIRT_TO_BUS(ha->ioctl_data); + + /* Attempt to copy in the data */ + user_area = *((char **) &scb->scsi_cmd->cmnd[4]); + kern_area = ha->ioctl_data; + datasize = *((u32 *) &scb->scsi_cmd->cmnd[8]); + + if (copy_from_user(kern_area, user_area, datasize) > 0) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) passthru failed - unable to copy in user data\n", + ips_name, ha->host_num); +#endif + + return (0); + } + + } else { + scb->data_busaddr = 0L; + } + + if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) + scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb); + + if (pt->CmdBSize) { + if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) + scb->dcdb.buffer_pointer = scb->data_busaddr; + else + scb->cmd.basic_io.sg_addr = scb->data_busaddr; } /* set timeouts */ @@ -1416,15 +1896,15 @@ ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) { scb->timeout = pt->TimeOut; if (pt->TimeOut <= 10) - scb->dcdb.cmd_attribute |= TIMEOUT_10; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT10; else if (pt->TimeOut <= 60) - scb->dcdb.cmd_attribute |= TIMEOUT_60; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT60; else - scb->dcdb.cmd_attribute |= TIMEOUT_20M; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; } - /* assume error */ - scb->scsi_cmd->result = DID_ERROR << 16; + /* assume success */ + scb->scsi_cmd->result = DID_OK << 16; /* success */ return (1); @@ -1440,7 +1920,7 @@ ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) { /* */ /****************************************************************************/ static void -ips_cleanup_passthru(ips_scb_t *scb) { +ips_cleanup_passthru(ips_ha_t *ha, ips_scb_t *scb) { ips_passthru_t *pt; DBG("ips_cleanup_passthru"); @@ -1456,10 +1936,15 @@ ips_cleanup_passthru(ips_scb_t *scb) { pt = (ips_passthru_t *) scb->scsi_cmd->request_buffer; /* Copy data back to the user */ - pt->BasicStatus = scb->basic_status; - pt->ExtendedStatus = scb->extended_status; - - scb->scsi_cmd->result = DID_OK << 16; + if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_COMMAND) { + /* Copy data back to the user */ + pt->BasicStatus = scb->basic_status; + pt->ExtendedStatus = scb->extended_status; + } else { + pt->BasicStatus = scb->basic_status; + pt->ExtendedStatus = scb->extended_status; + up(scb->sem); + } } #endif @@ -1475,7 +1960,7 @@ ips_cleanup_passthru(ips_scb_t *scb) { /****************************************************************************/ static int ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) { - INFOSTR info; + IPS_INFOSTR info; DBG("ips_host_info"); @@ -1486,7 +1971,7 @@ ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) { copy_info(&info, "\nIBM ServeRAID General Information:\n\n"); - if ((ha->nvram->signature == NVRAM_PAGE5_SIGNATURE) && + if ((ha->nvram->signature == IPS_NVRAM_P5_SIG) && (ha->nvram->adapter_type != 0)) copy_info(&info, "\tController Type : %s\n", ips_adapter_name[ha->ad_type-1]); else @@ -1495,7 +1980,7 @@ ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) { copy_info(&info, "\tIO port address : 0x%lx\n", ha->io_addr); copy_info(&info, "\tIRQ number : %d\n", ha->irq); - if (ha->nvram->signature == NVRAM_PAGE5_SIGNATURE) + if (ha->nvram->signature == IPS_NVRAM_P5_SIG) copy_info(&info, "\tBIOS Version : %c%c%c%c%c%c%c%c\n", ha->nvram->bios_high[0], ha->nvram->bios_high[1], ha->nvram->bios_high[2], ha->nvram->bios_high[3], @@ -1541,11 +2026,11 @@ ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) { /* */ /* Routine Description: */ /* */ -/* Copy data into an INFOSTR structure */ +/* Copy data into an IPS_INFOSTR structure */ /* */ /****************************************************************************/ static void -copy_mem_info(INFOSTR *info, char *data, int len) { +copy_mem_info(IPS_INFOSTR *info, char *data, int len) { DBG("copy_mem_info"); if (info->pos + len > info->length) @@ -1577,7 +2062,7 @@ copy_mem_info(INFOSTR *info, char *data, int len) { /* */ /****************************************************************************/ static int -copy_info(INFOSTR *info, char *fmt, ...) { +copy_info(IPS_INFOSTR *info, char *fmt, ...) { va_list args; char buf[81]; int len; @@ -1616,11 +2101,15 @@ ips_hainit(ips_ha_t *ha) { /* initialize status queue */ ips_statinit(ha); + ha->reset_count = 1; + /* Setup HBA ID's */ - if (!ips_read_config(ha)) { + if (!ips_read_config(ha, IPS_INTR_IORL)) { #ifndef NO_IPS_RESET + ha->reset_count++; + /* Try to reset the controller and try again */ if (!ips_reset_adapter(ha)) { printk(KERN_WARNING "(%s%d) unable to reset controller.\n", @@ -1629,7 +2118,7 @@ ips_hainit(ips_ha_t *ha) { return (0); } - if (!ips_clear_adapter(ha)) { + if (!ips_clear_adapter(ha, IPS_INTR_IORL)) { printk(KERN_WARNING "(%s%d) unable to initialize controller.\n", ips_name, ha->host_num); @@ -1638,7 +2127,7 @@ ips_hainit(ips_ha_t *ha) { #endif - if (!ips_read_config(ha)) { + if (!ips_read_config(ha, IPS_INTR_IORL)) { printk(KERN_WARNING "(%s%d) unable to read config from controller.\n", ips_name, ha->host_num); @@ -1647,31 +2136,40 @@ ips_hainit(ips_ha_t *ha) { } /* end if */ /* write driver version */ - if (!ips_write_driver_status(ha)) { + if (!ips_write_driver_status(ha, IPS_INTR_IORL)) { printk(KERN_WARNING "(%s%d) unable to write driver info to controller.\n", ips_name, ha->host_num); return (0); } - if (!ips_read_adapter_status(ha)) { + if (!ips_read_adapter_status(ha, IPS_INTR_IORL)) { printk(KERN_WARNING "(%s%d) unable to read controller status.\n", ips_name, ha->host_num); return (0); } - if (!ips_read_subsystem_parameters(ha)) { + if (!ips_read_subsystem_parameters(ha, IPS_INTR_IORL)) { printk(KERN_WARNING "(%s%d) unable to read subsystem parameters.\n", ips_name, ha->host_num); return (0); } + /* FFDC */ + if (ha->subsys->param[3] & 0x300000) { + struct timeval tv; + + do_gettimeofday(&tv); + ha->last_ffdc = tv.tv_sec; + ips_ffdc_reset(ha, IPS_INTR_IORL); + } + /* set limits on SID, LUN, BUS */ - ha->ntargets = MAX_TARGETS + 1; + ha->ntargets = IPS_MAX_TARGETS + 1; ha->nlun = 1; - ha->nbus = (ha->enq->ucMaxPhysicalDevices / MAX_TARGETS); + ha->nbus = (ha->enq->ucMaxPhysicalDevices / IPS_MAX_TARGETS); switch (ha->conf->logical_drive[0].ucStripeSize) { case 4: @@ -1736,21 +2234,55 @@ ips_hainit(ips_ha_t *ha) { /* */ /* Take the next command off the queue and send it to the controller */ /* */ -/* ASSUMED to be called from within a lock */ -/* */ /****************************************************************************/ static void -ips_next(ips_ha_t *ha) { - ips_scb_t *scb; - Scsi_Cmnd *SC; - Scsi_Cmnd *p; - int ret; +ips_next(ips_ha_t *ha, int intr) { + ips_scb_t *scb; + Scsi_Cmnd *SC; + Scsi_Cmnd *p; + ips_copp_wait_item_t *item; + int ret; + int intr_status; + u32 cpu_flags; + u32 cpu_flags2; DBG("ips_next"); if (!ha) return ; + /* + * Block access to the queue function so + * this command won't time out + */ + if (intr == IPS_INTR_ON) { + spin_lock_irqsave(&io_request_lock, cpu_flags2); + intr_status = IPS_INTR_IORL; + } else { + intr_status = intr; + + /* Quiet the compiler */ + cpu_flags2 = 0; + } + + if (ha->subsys->param[3] & 0x300000) { + struct timeval tv; + + do_gettimeofday(&tv); + + IPS_HA_LOCK(cpu_flags); + if (tv.tv_sec - ha->last_ffdc > IPS_SECS_8HOURS) { + ha->last_ffdc = tv.tv_sec; + IPS_HA_UNLOCK(cpu_flags); + ips_ffdc_time(ha, intr_status); + } else { + IPS_HA_UNLOCK(cpu_flags); + } + } + + if (intr == IPS_INTR_ON) + spin_unlock_irqrestore(&io_request_lock, cpu_flags2); + #ifndef NO_IPS_CMDLINE /* * Send passthru commands @@ -1759,32 +2291,50 @@ ips_next(ips_ha_t *ha) { * since we limit the number that can be active * on the card at any one time */ + IPS_HA_LOCK(cpu_flags); + IPS_QUEUE_LOCK(&ha->copp_waitlist); while ((ha->num_ioctl < IPS_MAX_IOCTL) && (ha->copp_waitlist.head) && (scb = ips_getscb(ha))) { - SC = ips_removeq_wait_head(&ha->copp_waitlist); - ret = ips_make_passthru(ha, SC, scb); + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + IPS_HA_UNLOCK(cpu_flags); + item = ips_removeq_copp_head(&ha->copp_waitlist); + scb->scsi_cmd = item->scsi_cmd; + scb->sem = item->sem; + kfree(item); + + ret = ips_make_passthru(ha, scb->scsi_cmd, scb); switch (ret) { case IPS_FAILURE: if (scb->scsi_cmd) { + /* raise the semaphore */ + if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND) + up(scb->sem); + scb->scsi_cmd->result = DID_ERROR << 16; - scb->scsi_cmd->scsi_done(scb->scsi_cmd); } ips_freescb(ha, scb); break; case IPS_SUCCESS_IMM: - if (scb->scsi_cmd) - scb->scsi_cmd->scsi_done(scb->scsi_cmd); + if (scb->scsi_cmd) { + /* raise the semaphore */ + if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND) + up(scb->sem); + } + ips_freescb(ha, scb); break; default: break; } /* end case */ - if (ret != IPS_SUCCESS) + if (ret != IPS_SUCCESS) { + IPS_HA_LOCK(cpu_flags); + IPS_QUEUE_LOCK(&ha->copp_waitlist); continue; + } ret = ips_send_cmd(ha, scb); @@ -1796,27 +2346,43 @@ ips_next(ips_ha_t *ha) { switch(ret) { case IPS_FAILURE: if (scb->scsi_cmd) { + /* raise the semaphore */ + if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND) + up(scb->sem); + scb->scsi_cmd->result = DID_ERROR << 16; - scb->scsi_cmd->scsi_done(scb->scsi_cmd); } ips_freescb(ha, scb); break; case IPS_SUCCESS_IMM: - if (scb->scsi_cmd) - scb->scsi_cmd->scsi_done(scb->scsi_cmd); + if (scb->scsi_cmd) { + /* raise the semaphore */ + if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND) + up(scb->sem); + } + ips_freescb(ha, scb); break; default: break; } /* end case */ + + IPS_HA_LOCK(cpu_flags); + IPS_QUEUE_LOCK(&ha->copp_waitlist); } + + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + IPS_HA_UNLOCK(cpu_flags); #endif /* * Send "Normal" I/O commands */ + IPS_HA_LOCK(cpu_flags); + IPS_QUEUE_LOCK(&ha->scb_waitlist); p = ha->scb_waitlist.head; + IPS_QUEUE_UNLOCK(&ha->scb_waitlist); while ((p) && (scb = ips_getscb(ha))) { if ((p->channel > 0) && (ha->dcdb_active[p->channel-1] & (1 << p->target))) { ips_freescb(ha, scb); @@ -1824,6 +2390,8 @@ ips_next(ips_ha_t *ha) { continue; } + IPS_HA_UNLOCK(cpu_flags); + SC = ips_removeq_wait(&ha->scb_waitlist, p); SC->result = DID_OK; @@ -1904,7 +2472,7 @@ ips_next(ips_ha_t *ha) { scb->dcdb.transfer_length = 0; if (scb->data_len >= IPS_MAX_XFER) { - scb->dcdb.cmd_attribute |= TRANSFER_64K; + scb->dcdb.cmd_attribute |= IPS_TRANSFER64K; scb->dcdb.transfer_length = 0; } @@ -1939,7 +2507,11 @@ ips_next(ips_ha_t *ha) { } /* end case */ p = (Scsi_Cmnd *) p->host_scribble; + + IPS_HA_LOCK(cpu_flags); } /* end while */ + + IPS_HA_UNLOCK(cpu_flags); } /****************************************************************************/ @@ -1960,6 +2532,8 @@ ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) { if (!item) return ; + IPS_QUEUE_LOCK(queue); + item->q_next = queue->head; queue->head = item; @@ -1967,6 +2541,8 @@ ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) { queue->tail = item; queue->count++; + + IPS_QUEUE_UNLOCK(queue); } /****************************************************************************/ @@ -1987,6 +2563,8 @@ ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) { if (!item) return ; + IPS_QUEUE_LOCK(queue); + item->q_next = NULL; if (queue->tail) @@ -1998,6 +2576,8 @@ ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) { queue->head = item; queue->count++; + + IPS_QUEUE_UNLOCK(queue); } /****************************************************************************/ @@ -2017,10 +2597,15 @@ ips_removeq_scb_head(ips_scb_queue_t *queue) { DBG("ips_removeq_scb_head"); + IPS_QUEUE_LOCK(queue); + item = queue->head; - if (!item) + if (!item) { + IPS_QUEUE_UNLOCK(queue); + return (NULL); + } queue->head = item->q_next; item->q_next = NULL; @@ -2030,6 +2615,8 @@ ips_removeq_scb_head(ips_scb_queue_t *queue) { queue->count--; + IPS_QUEUE_UNLOCK(queue); + return (item); } @@ -2053,8 +2640,13 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) { if (!item) return (NULL); - if (item == queue->head) + IPS_QUEUE_LOCK(queue); + + if (item == queue->head) { + IPS_QUEUE_UNLOCK(queue); + return (ips_removeq_scb_head(queue)); + } p = queue->head; @@ -2071,9 +2663,13 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) { item->q_next = NULL; queue->count--; + IPS_QUEUE_UNLOCK(queue); + return (item); } + IPS_QUEUE_UNLOCK(queue); + return (NULL); } @@ -2095,6 +2691,8 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) { if (!item) return ; + IPS_QUEUE_LOCK(queue); + item->host_scribble = (char *) queue->head; queue->head = item; @@ -2102,6 +2700,8 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) { queue->tail = item; queue->count++; + + IPS_QUEUE_UNLOCK(queue); } /****************************************************************************/ @@ -2122,6 +2722,8 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { if (!item) return ; + IPS_QUEUE_LOCK(queue); + item->host_scribble = NULL; if (queue->tail) @@ -2133,6 +2735,8 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { queue->head = item; queue->count++; + + IPS_QUEUE_UNLOCK(queue); } /****************************************************************************/ @@ -2152,10 +2756,15 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) { DBG("ips_removeq_wait_head"); + IPS_QUEUE_LOCK(queue); + item = queue->head; - if (!item) + if (!item) { + IPS_QUEUE_UNLOCK(queue); + return (NULL); + } queue->head = (Scsi_Cmnd *) item->host_scribble; item->host_scribble = NULL; @@ -2165,6 +2774,8 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) { queue->count--; + IPS_QUEUE_UNLOCK(queue); + return (item); } @@ -2188,8 +2799,13 @@ ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) { if (!item) return (NULL); - if (item == queue->head) + IPS_QUEUE_LOCK(queue); + + if (item == queue->head) { + IPS_QUEUE_UNLOCK(queue); + return (ips_removeq_wait_head(queue)); + } p = queue->head; @@ -2206,9 +2822,172 @@ ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) { item->host_scribble = NULL; queue->count--; + IPS_QUEUE_UNLOCK(queue); + return (item); } + IPS_QUEUE_UNLOCK(queue); + + return (NULL); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_putq_copp_head */ +/* */ +/* Routine Description: */ +/* */ +/* Add an item to the head of the queue */ +/* */ +/* ASSUMED to be called from within a lock */ +/* */ +/****************************************************************************/ +static inline void +ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { + DBG("ips_putq_copp_head"); + + if (!item) + return ; + + IPS_QUEUE_LOCK(queue); + + item->next = queue->head; + queue->head = item; + + if (!queue->tail) + queue->tail = item; + + queue->count++; + + IPS_QUEUE_UNLOCK(queue); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_putq_copp_tail */ +/* */ +/* Routine Description: */ +/* */ +/* Add an item to the tail of the queue */ +/* */ +/* ASSUMED to be called from within a lock */ +/* */ +/****************************************************************************/ +static inline void +ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { + DBG("ips_putq_copp_tail"); + + if (!item) + return ; + + IPS_QUEUE_LOCK(queue); + + item->next = NULL; + + if (queue->tail) + queue->tail->next = item; + + queue->tail = item; + + if (!queue->head) + queue->head = item; + + queue->count++; + + IPS_QUEUE_UNLOCK(queue); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_removeq_copp_head */ +/* */ +/* Routine Description: */ +/* */ +/* Remove the head of the queue */ +/* */ +/* ASSUMED to be called from within a lock */ +/* */ +/****************************************************************************/ +static inline ips_copp_wait_item_t * +ips_removeq_copp_head(ips_copp_queue_t *queue) { + ips_copp_wait_item_t *item; + + DBG("ips_removeq_copp_head"); + + IPS_QUEUE_LOCK(queue); + + item = queue->head; + + if (!item) { + IPS_QUEUE_UNLOCK(queue); + + return (NULL); + } + + queue->head = item->next; + item->next = NULL; + + if (queue->tail == item) + queue->tail = NULL; + + queue->count--; + + IPS_QUEUE_UNLOCK(queue); + + return (item); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_removeq_copp */ +/* */ +/* Routine Description: */ +/* */ +/* Remove an item from a queue */ +/* */ +/* ASSUMED to be called from within a lock */ +/* */ +/****************************************************************************/ +static inline ips_copp_wait_item_t * +ips_removeq_copp(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { + ips_copp_wait_item_t *p; + + DBG("ips_removeq_copp"); + + if (!item) + return (NULL); + + IPS_QUEUE_LOCK(queue); + + if (item == queue->head) { + IPS_QUEUE_UNLOCK(queue); + + return (ips_removeq_copp_head(queue)); + } + + p = queue->head; + + while ((p) && (item != p->next)) + p = p->next; + + if (p) { + /* found a match */ + p->next = item->next; + + if (!item->next) + queue->tail = p; + + item->next = NULL; + queue->count--; + + IPS_QUEUE_UNLOCK(queue); + + return (item); + } + + IPS_QUEUE_UNLOCK(queue); + return (NULL); } @@ -2269,6 +3048,7 @@ ipsintr_done(ips_ha_t *ha, ips_scb_t *scb) { static void ips_done(ips_ha_t *ha, ips_scb_t *scb) { int ret; + u32 cpu_flags; DBG("ips_done"); @@ -2277,8 +3057,10 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) { #ifndef NO_IPS_CMDLINE if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd))) { - ips_cleanup_passthru(scb); + ips_cleanup_passthru(ha, scb); + IPS_HA_LOCK(cpu_flags); ha->num_ioctl--; + IPS_HA_UNLOCK(cpu_flags); } else { #endif /* @@ -2342,11 +3124,12 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) { scb->dcdb.cmd_attribute |= ips_command_direction[scb->scsi_cmd->cmnd[0]]; - + if (!scb->dcdb.cmd_attribute & 0x3) scb->dcdb.transfer_length = 0; + if (scb->data_len >= IPS_MAX_XFER) { - scb->dcdb.cmd_attribute |= TRANSFER_64K; + scb->dcdb.cmd_attribute |= IPS_TRANSFER64K; scb->dcdb.transfer_length = 0; } @@ -2379,15 +3162,17 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) { } /* end if passthru */ #endif - if (scb->bus) + if (scb->bus) { + IPS_HA_LOCK(cpu_flags); ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id); + IPS_HA_UNLOCK(cpu_flags); + } /* call back to SCSI layer */ - scb->scsi_cmd->scsi_done(scb->scsi_cmd); - ips_freescb(ha, scb); + if (scb->scsi_cmd && scb->scsi_cmd->cmnd[0] != IPS_IOCTL_NEW_COMMAND) + scb->scsi_cmd->scsi_done(scb->scsi_cmd); - /* do the next command */ - ips_next(ha); + ips_freescb(ha, scb); } /****************************************************************************/ @@ -2426,19 +3211,19 @@ ips_map_status(ips_scb_t *scb, ips_stat_t *sp) { /* default driver error */ errcode = DID_ERROR; - switch (scb->basic_status & GSC_STATUS_MASK) { - case CMD_TIMEOUT: + switch (scb->basic_status & IPS_GSC_STATUS_MASK) { + case IPS_CMD_TIMEOUT: errcode = DID_TIME_OUT; break; - case INVAL_OPCO: - case INVAL_CMD_BLK: - case INVAL_PARM_BLK: - case LOG_DRV_ERROR: - case CMD_CMPLT_WERROR: + case IPS_INVAL_OPCO: + case IPS_INVAL_CMD_BLK: + case IPS_INVAL_PARM_BLK: + case IPS_LD_ERROR: + case IPS_CMD_CMPLT_WERROR: break; - case PHYS_DRV_ERROR: + case IPS_PHYS_DRV_ERROR: /* * For physical drive errors that * are not on a logical drive should @@ -2449,14 +3234,14 @@ ips_map_status(ips_scb_t *scb, ips_stat_t *sp) { errcode = DID_OK; switch (scb->extended_status) { - case SELECTION_TIMEOUT: + case IPS_ERR_SEL_TO: if (scb->bus) { scb->scsi_cmd->result |= DID_TIME_OUT << 16; return (0); } break; - case DATA_OVER_UNDER_RUN: + case IPS_ERR_OU_RUN: if ((scb->bus) && (scb->dcdb.transfer_length < scb->data_len)) { if ((scb->scsi_cmd->cmnd[0] == INQUIRY) && ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == TYPE_DISK)) { @@ -2475,7 +3260,7 @@ ips_map_status(ips_scb_t *scb, ips_stat_t *sp) { } break; - case EXT_RECOVERY: + case IPS_ERR_RECOVERY: /* don't fail recovered errors */ if (scb->bus) { scb->scsi_cmd->result |= DID_OK << 16; @@ -2484,12 +3269,12 @@ ips_map_status(ips_scb_t *scb, ips_stat_t *sp) { } break; - case EXT_HOST_RESET: - case EXT_DEVICE_RESET: + case IPS_ERR_HOST_RESET: + case IPS_ERR_DEV_RESET: errcode = DID_RESET; break; - case EXT_CHECK_CONDITION: + case IPS_ERR_CKCOND: break; } /* end switch */ } /* end switch */ @@ -2509,7 +3294,7 @@ ips_map_status(ips_scb_t *scb, ips_stat_t *sp) { /* */ /****************************************************************************/ static int -ips_send(ips_ha_t *ha, ips_scb_t *scb, scb_callback callback) { +ips_send(ips_ha_t *ha, ips_scb_t *scb, ips_scb_callback callback) { int ret; DBG("ips_send"); @@ -2531,7 +3316,7 @@ ips_send(ips_ha_t *ha, ips_scb_t *scb, scb_callback callback) { /* */ /****************************************************************************/ static int -ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout) { +ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout, int intr) { int ret; DBG("ips_send_wait"); @@ -2544,7 +3329,7 @@ ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout) { if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)) return (ret); - ret = ips_wait(ha, timeout, IPS_INTR_OFF); + ret = ips_wait(ha, timeout, intr); return (ret); } @@ -2610,9 +3395,9 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { scb->scsi_cmd->result = DID_OK << 16; if (scb->scsi_cmd->cmnd[0] == INQUIRY) { - IPS_INQUIRYDATA inq; + IPS_INQ_DATA inq; - memset(&inq, 0, sizeof(IPS_INQUIRYDATA)); + memset(&inq, 0, sizeof(IPS_INQ_DATA)); inq.DeviceType = TYPE_PROCESSOR; inq.DeviceTypeQualifier = 0; @@ -2628,7 +3413,7 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { scb->scsi_cmd->result = DID_OK << 16; } } else { - scb->cmd.logical_info.op_code = GET_LOGICAL_DRIVE_INFO; + scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO; scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info); scb->cmd.logical_info.reserved = 0; @@ -2647,10 +3432,10 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { case WRITE_6: if (!scb->sg_len) { scb->cmd.basic_io.op_code = - (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_READ : IPS_WRITE; + (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_CMD_READ : IPS_CMD_WRITE; } else { scb->cmd.basic_io.op_code = - (scb->scsi_cmd->cmnd[0] == READ_6) ? READ_SCATTER_GATHER : WRITE_SCATTER_GATHER; + (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_CMD_READ_SG : IPS_CMD_WRITE_SG; } scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); @@ -2678,10 +3463,10 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { case WRITE_10: if (!scb->sg_len) { scb->cmd.basic_io.op_code = - (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_READ : IPS_WRITE; + (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_CMD_READ : IPS_CMD_WRITE; } else { scb->cmd.basic_io.op_code = - (scb->scsi_cmd->cmnd[0] == READ_10) ? READ_SCATTER_GATHER : WRITE_SCATTER_GATHER; + (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_CMD_READ_SG : IPS_CMD_WRITE_SG; } scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); @@ -2719,14 +3504,14 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { break; case MODE_SENSE: - scb->cmd.basic_io.op_code = ENQUIRY; + scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY; scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq); ret = IPS_SUCCESS; break; case READ_CAPACITY: - scb->cmd.logical_info.op_code = GET_LOGICAL_DRIVE_INFO; + scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO; scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info); scb->cmd.logical_info.reserved = 0; @@ -2758,9 +3543,9 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { /* setup DCDB */ if (scb->bus > 0) { if (!scb->sg_len) - scb->cmd.dcdb.op_code = DIRECT_CDB; + scb->cmd.dcdb.op_code = IPS_CMD_DCDB; else - scb->cmd.dcdb.op_code = DIRECT_CDB_SCATTER_GATHER; + scb->cmd.dcdb.op_code = IPS_CMD_DCDB_SG; ha->dcdb_active[scb->bus-1] |= (1 << scb->target_id); scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb); @@ -2770,19 +3555,19 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { scb->cmd.dcdb.reserved3 = 0; scb->dcdb.device_address = ((scb->bus - 1) << 4) | scb->target_id; - scb->dcdb.cmd_attribute |= DISCONNECT_ALLOWED; + scb->dcdb.cmd_attribute |= IPS_DISCONNECT_ALLOWED; if (scb->timeout) { if (scb->timeout <= 10) - scb->dcdb.cmd_attribute |= TIMEOUT_10; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT10; else if (scb->timeout <= 60) - scb->dcdb.cmd_attribute |= TIMEOUT_60; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT60; else - scb->dcdb.cmd_attribute |= TIMEOUT_20M; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; } - if (!(scb->dcdb.cmd_attribute & TIMEOUT_20M)) - scb->dcdb.cmd_attribute |= TIMEOUT_20M; + if (!(scb->dcdb.cmd_attribute & IPS_TIMEOUT20M)) + scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; scb->dcdb.sense_length = sizeof(scb->scsi_cmd->sense_buffer); scb->dcdb.buffer_pointer = scb->data_busaddr; @@ -2817,7 +3602,7 @@ ips_chkstatus(ips_ha_t *ha) { command_id = ips_statupd(ha); - if (command_id > (MAX_CMDS-1)) { + if (command_id > (IPS_MAX_CMDS-1)) { printk(KERN_NOTICE "(%s%d) invalid command id received: %d\n", ips_name, ha->host_num, command_id); @@ -2827,7 +3612,7 @@ ips_chkstatus(ips_ha_t *ha) { scb = &ha->scbs[command_id]; sp->scb_addr = (u32) scb; sp->residue_len = 0; - scb->basic_status = basic_status = ha->adapt->p_status_tail->basic_status & BASIC_STATUS_MASK; + scb->basic_status = basic_status = ha->adapt->p_status_tail->basic_status & IPS_BASIC_STATUS_MASK; scb->extended_status = ext_status = ha->adapt->p_status_tail->extended_status; /* Remove the item from the active queue */ @@ -2846,12 +3631,12 @@ ips_chkstatus(ips_ha_t *ha) { errcode = DID_OK; ret = 0; - if (((basic_status & GSC_STATUS_MASK) == SSUCCESS) || - ((basic_status & GSC_STATUS_MASK) == RECOVERED_ERROR)) { + if (((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_SUCCESS) || + ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR)) { if (scb->bus == 0) { #if IPS_DEBUG >= 1 - if ((basic_status & GSC_STATUS_MASK) == RECOVERED_ERROR) { + if ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR) { printk(KERN_NOTICE "(%s%d) Recovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x\n", ips_name, ha->host_num, scb->cmd.basic_io.op_code, basic_status, ext_status); @@ -2975,20 +3760,20 @@ static int ips_online(ips_ha_t *ha, ips_scb_t *scb) { DBG("ips_online"); - if (scb->target_id >= MAX_LOGICAL_DRIVES) + if (scb->target_id >= IPS_MAX_LD) return (0); - if ((scb->basic_status & GSC_STATUS_MASK) > 1) { + if ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1) { memset(&ha->adapt->logical_drive_info, 0, sizeof(ha->adapt->logical_drive_info)); return (0); } if (scb->target_id < ha->adapt->logical_drive_info.no_of_log_drive && - ha->adapt->logical_drive_info.drive_info[scb->target_id].state != OFF_LINE && - ha->adapt->logical_drive_info.drive_info[scb->target_id].state != FREE && - ha->adapt->logical_drive_info.drive_info[scb->target_id].state != CRS && - ha->adapt->logical_drive_info.drive_info[scb->target_id].state != SYS) + ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_OFFLINE && + ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_FREE && + ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_CRS && + ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_SYS) return (1); else return (0); @@ -3005,11 +3790,11 @@ ips_online(ips_ha_t *ha, ips_scb_t *scb) { /****************************************************************************/ static int ips_inquiry(ips_ha_t *ha, ips_scb_t *scb) { - IPS_INQUIRYDATA inq; + IPS_INQ_DATA inq; DBG("ips_inquiry"); - memset(&inq, 0, sizeof(IPS_INQUIRYDATA)); + memset(&inq, 0, sizeof(IPS_INQ_DATA)); inq.DeviceType = TYPE_DISK; inq.DeviceTypeQualifier = 0; @@ -3036,14 +3821,14 @@ ips_inquiry(ips_ha_t *ha, ips_scb_t *scb) { /****************************************************************************/ static int ips_rdcap(ips_ha_t *ha, ips_scb_t *scb) { - CAPACITY_T *cap; + IPS_CAPACITY *cap; DBG("ips_rdcap"); if (scb->scsi_cmd->bufflen < 8) return (0); - cap = (CAPACITY_T *) scb->scsi_cmd->request_buffer; + cap = (IPS_CAPACITY *) scb->scsi_cmd->request_buffer; cap->lba = htonl(ha->adapt->logical_drive_info.drive_info[scb->target_id].sector_count - 1); cap->len = htonl((u32) IPS_BLKSIZE); @@ -3071,11 +3856,11 @@ ips_msense(ips_ha_t *ha, ips_scb_t *scb) { if (ha->enq->ulDriveSize[scb->target_id] > 0x400000 && (ha->enq->ucMiscFlag & 0x8) == 0) { - heads = NORM_MODE_HEADS; - sectors = NORM_MODE_SECTORS; + heads = IPS_NORM_HEADS; + sectors = IPS_NORM_SECTORS; } else { - heads = COMP_MODE_HEADS; - sectors = COMP_MODE_SECTORS; + heads = IPS_COMP_HEADS; + sectors = IPS_COMP_SECTORS; } cylinders = ha->enq->ulDriveSize[scb->target_id] / (heads * sectors); @@ -3088,7 +3873,7 @@ ips_msense(ips_ha_t *ha, ips_scb_t *scb) { case 0x03: /* page 3 */ mdata.pdata.pg3.pg_pc = 0x3; mdata.pdata.pg3.pg_res1 = 0; - mdata.pdata.pg3.pg_len = sizeof(DADF_T); + mdata.pdata.pg3.pg_len = sizeof(IPS_DADF); mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg3.pg_len; mdata.pdata.pg3.pg_trk_z = 0; mdata.pdata.pg3.pg_asec_z = 0; @@ -3110,7 +3895,7 @@ ips_msense(ips_ha_t *ha, ips_scb_t *scb) { case 0x4: mdata.pdata.pg4.pg_pc = 0x4; mdata.pdata.pg4.pg_res1 = 0; - mdata.pdata.pg4.pg_len = sizeof(RDDG_T); + mdata.pdata.pg4.pg_len = sizeof(IPS_RDDG); mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg4.pg_len; mdata.pdata.pg4.pg_cylu = (cylinders >> 8) & 0xffff; mdata.pdata.pg4.pg_cyll = cylinders & 0xff; @@ -3204,6 +3989,12 @@ ips_free(ips_ha_t *ha) { ha->dummy = NULL; } + if (ha->ioctl_data) { + kfree(ha->ioctl_data); + ha->ioctl_data = NULL; + ha->ioctl_datasize = 0; + } + if (ha->scbs) { for (i = 0; i < ha->max_cmds; i++) { if (ha->scbs[i].sg_list) @@ -3241,7 +4032,7 @@ ips_allocatescbs(ips_ha_t *ha) { scb_p = &ha->scbs[i]; /* allocate S/G list */ - scb_p->sg_list = (SG_LIST *) kmalloc(sizeof(SG_LIST) * MAX_SG_ELEMENTS, GFP_KERNEL|GFP_DMA); + scb_p->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_KERNEL|GFP_DMA); if (! scb_p->sg_list) return (0); @@ -3268,7 +4059,7 @@ ips_allocatescbs(ips_ha_t *ha) { /****************************************************************************/ static void ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) { - SG_LIST *sg_list; + IPS_SG_LIST *sg_list; DBG("ips_init_scb"); @@ -3279,19 +4070,19 @@ ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) { /* zero fill */ memset(scb, 0, sizeof(ips_scb_t)); - memset(ha->dummy, 0, sizeof(BASIC_IO_CMD)); + memset(ha->dummy, 0, sizeof(IPS_IO_CMD)); /* Initialize dummy command bucket */ ha->dummy->op_code = 0xFF; ha->dummy->ccsar = VIRT_TO_BUS(ha->dummy); - ha->dummy->command_id = MAX_CMDS; + ha->dummy->command_id = IPS_MAX_CMDS; /* set bus address of scb */ scb->scb_busaddr = VIRT_TO_BUS(scb); scb->sg_list = sg_list; /* Neptune Fix */ - scb->cmd.basic_io.cccr = ILE; + scb->cmd.basic_io.cccr = IPS_BIT_ILE; scb->cmd.basic_io.ccsar = VIRT_TO_BUS(ha->dummy); } @@ -3309,13 +4100,13 @@ ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) { static ips_scb_t * ips_getscb(ips_ha_t *ha) { ips_scb_t *scb; - unsigned int cpu_flags; + u32 cpu_flags; DBG("ips_getscb"); - spin_lock_irqsave(&ha->scb_lock, cpu_flags); + IPS_SCB_LOCK(cpu_flags); if ((scb = ha->scb_freelist) == NULL) { - spin_unlock_irqrestore(&ha->scb_lock, cpu_flags); + IPS_SCB_UNLOCK(cpu_flags); return (NULL); } @@ -3323,7 +4114,7 @@ ips_getscb(ips_ha_t *ha) { ha->scb_freelist = scb->q_next; scb->q_next = NULL; - spin_unlock_irqrestore(&ha->scb_lock, cpu_flags); + IPS_SCB_UNLOCK(cpu_flags); ips_init_scb(ha, scb); @@ -3343,16 +4134,16 @@ ips_getscb(ips_ha_t *ha) { /****************************************************************************/ static void ips_freescb(ips_ha_t *ha, ips_scb_t *scb) { - unsigned int cpu_flags; + u32 cpu_flags; DBG("ips_freescb"); /* check to make sure this is not our "special" scb */ if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) { - spin_lock_irqsave(&ha->scb_lock, cpu_flags); + IPS_SCB_LOCK(cpu_flags); scb->q_next = ha->scb_freelist; ha->scb_freelist = scb; - spin_unlock_irqrestore(&ha->scb_lock, cpu_flags); + IPS_SCB_UNLOCK(cpu_flags); } } @@ -3369,10 +4160,11 @@ static int ips_reset_adapter(ips_ha_t *ha) { u8 Isr; u8 Cbsp; - u8 PostByte[MAX_POST_BYTES]; - u8 ConfigByte[MAX_CONFIG_BYTES]; + u8 PostByte[IPS_MAX_POST_BYTES]; + u8 ConfigByte[IPS_MAX_CONFIG_BYTES]; int i, j; int reset_counter; + u32 cpu_flags; DBG("ips_reset_adapter"); @@ -3381,108 +4173,125 @@ ips_reset_adapter(ips_ha_t *ha) { ha->io_addr, ha->irq); #endif + IPS_HA_LOCK(cpu_flags); + reset_counter = 0; while (reset_counter < 2) { reset_counter++; - outb(RST, ha->io_addr + SCPR); - MDELAY(ONE_SEC); - outb(0, ha->io_addr + SCPR); - MDELAY(ONE_SEC); + outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR); + MDELAY(IPS_ONE_SEC); + outb(0, ha->io_addr + IPS_REG_SCPR); + MDELAY(IPS_ONE_SEC); - for (i = 0; i < MAX_POST_BYTES; i++) { + for (i = 0; i < IPS_MAX_POST_BYTES; i++) { for (j = 0; j < 45; j++) { - Isr = inb(ha->io_addr + HISR); - if (Isr & GHI) + Isr = inb(ha->io_addr + IPS_REG_HISR); + if (Isr & IPS_BIT_GHI) break; - MDELAY(ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (j >= 45) { /* error occured */ if (reset_counter < 2) continue; - else + else { /* reset failed */ + IPS_HA_UNLOCK(cpu_flags); + return (0); + } } - PostByte[i] = inb(ha->io_addr + ISPR); - outb(Isr, ha->io_addr + HISR); + PostByte[i] = inb(ha->io_addr + IPS_REG_ISPR); + outb(Isr, ha->io_addr + IPS_REG_HISR); } - if (PostByte[0] < GOOD_POST_BASIC_STATUS) { + if (PostByte[0] < IPS_GOOD_POST_STATUS) { printk("(%s%d) reset controller fails (post status %x %x).\n", ips_name, ha->host_num, PostByte[0], PostByte[1]); + IPS_HA_UNLOCK(cpu_flags); + return (0); } - for (i = 0; i < MAX_CONFIG_BYTES; i++) { + for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) { for (j = 0; j < 240; j++) { - Isr = inb(ha->io_addr + HISR); - if (Isr & GHI) + Isr = inb(ha->io_addr + IPS_REG_HISR); + if (Isr & IPS_BIT_GHI) break; - MDELAY(ONE_SEC); /* 100 msec */ + MDELAY(IPS_ONE_SEC); /* 100 msec */ } if (j >= 240) { /* error occured */ if (reset_counter < 2) continue; - else + else { /* reset failed */ + IPS_HA_UNLOCK(cpu_flags); + return (0); + } } - ConfigByte[i] = inb(ha->io_addr + ISPR); - outb(Isr, ha->io_addr + HISR); + ConfigByte[i] = inb(ha->io_addr + IPS_REG_ISPR); + outb(Isr, ha->io_addr + IPS_REG_HISR); } if (ConfigByte[0] == 0 && ConfigByte[1] == 2) { printk("(%s%d) reset controller fails (status %x %x).\n", ips_name, ha->host_num, ConfigByte[0], ConfigByte[1]); + IPS_HA_UNLOCK(cpu_flags); + return (0); } for (i = 0; i < 240; i++) { - Cbsp = inb(ha->io_addr + CBSP); + Cbsp = inb(ha->io_addr + IPS_REG_CBSP); - if ((Cbsp & OP) == 0) + if ((Cbsp & IPS_BIT_OP) == 0) break; - MDELAY(ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 240) { /* error occured */ if (reset_counter < 2) continue; - else + else { /* reset failed */ + IPS_HA_UNLOCK(cpu_flags); + return (0); + } } /* setup CCCR */ - outw(0x1010, ha->io_addr + CCCR); + outw(0x1010, ha->io_addr + IPS_REG_CCCR); /* Enable busmastering */ - outb(EBM, ha->io_addr + SCPR); + outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR); /* setup status queues */ ips_statinit(ha); /* Enable interrupts */ - outb(EI, ha->io_addr + HISR); + outb(IPS_BIT_EI, ha->io_addr + IPS_REG_HISR); /* if we get here then everything went OK */ break; } + IPS_HA_UNLOCK(cpu_flags); + return (1); } @@ -3502,14 +4311,14 @@ ips_statinit(ips_ha_t *ha) { DBG("ips_statinit"); ha->adapt->p_status_start = ha->adapt->status; - ha->adapt->p_status_end = ha->adapt->status + MAX_CMDS; + ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS; ha->adapt->p_status_tail = ha->adapt->status; phys_status_start = VIRT_TO_BUS(ha->adapt->status); - outl(phys_status_start, ha->io_addr + SQSR); - outl(phys_status_start + STATUS_Q_SIZE, ha->io_addr + SQER); - outl(phys_status_start + STATUS_SIZE, ha->io_addr + SQHR); - outl(phys_status_start, ha->io_addr + SQTR); + outl(phys_status_start, ha->io_addr + IPS_REG_SQSR); + outl(phys_status_start + IPS_STATUS_Q_SIZE, ha->io_addr + IPS_REG_SQER); + outl(phys_status_start + IPS_STATUS_SIZE, ha->io_addr + IPS_REG_SQHR); + outl(phys_status_start, ha->io_addr + IPS_REG_SQTR); ha->adapt->hw_status_start = phys_status_start; ha->adapt->hw_status_tail = phys_status_start; @@ -3532,13 +4341,13 @@ ips_statupd(ips_ha_t *ha) { if (ha->adapt->p_status_tail != ha->adapt->p_status_end) { ha->adapt->p_status_tail++; - ha->adapt->hw_status_tail += sizeof(STATUS); + ha->adapt->hw_status_tail += sizeof(IPS_STATUS); } else { ha->adapt->p_status_tail = ha->adapt->p_status_start; ha->adapt->hw_status_tail = ha->adapt->hw_status_start; } - outl(ha->adapt->hw_status_tail, ha->io_addr + SQTR); + outl(ha->adapt->hw_status_tail, ha->io_addr + IPS_REG_SQTR); command_id = ha->adapt->p_status_tail->command_id; @@ -3560,6 +4369,7 @@ static int ips_issue(ips_ha_t *ha, ips_scb_t *scb) { u32 TimeOut; u16 val; + u32 cpu_flags; DBG("ips_issue"); @@ -3577,17 +4387,19 @@ ips_issue(ips_ha_t *ha, ips_scb_t *scb) { ips_name, scb->cmd.basic_io.command_id); #if IPS_DEBUG >= 11 - MDELAY(ONE_SEC); + MDELAY(IPS_ONE_SEC); #endif #endif + IPS_HA_LOCK(cpu_flags); + TimeOut = 0; - while ((val = inw(ha->io_addr + CCCR)) & SEMAPHORE) { + while ((val = inw(ha->io_addr + IPS_REG_CCCR)) & IPS_BIT_SEM) { UDELAY(1000); - if (++TimeOut >= SEMAPHORE_TIMEOUT) { - if (!(val & START_STOP_BIT)) + if (++TimeOut >= IPS_SEM_TIMEOUT) { + if (!(val & IPS_BIT_START_STOP)) break; printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n", @@ -3595,12 +4407,16 @@ ips_issue(ips_ha_t *ha, ips_scb_t *scb) { printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n", ips_name, ha->host_num); + IPS_HA_UNLOCK(cpu_flags); + return (IPS_FAILURE); } /* end if */ } /* end while */ - outl(scb->scb_busaddr, ha->io_addr + CCSAR); - outw(START_COMMAND, ha->io_addr + CCCR); + outl(scb->scb_busaddr, ha->io_addr + IPS_REG_CCSAR); + outw(IPS_BIT_START_CMD, ha->io_addr + IPS_REG_CCCR); + + IPS_HA_UNLOCK(cpu_flags); return (IPS_SUCCESS); } @@ -3620,18 +4436,18 @@ ips_isintr(ips_ha_t *ha) { DBG("ips_isintr"); - Isr = inb(ha->io_addr + HISR); + Isr = inb(ha->io_addr + IPS_REG_HISR); if (Isr == 0xFF) /* ?!?! Nothing really there */ return (0); - if (Isr & SCE) + if (Isr & IPS_BIT_SCE) return (1); - else if (Isr & (SQO | GHI)) { + else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) { /* status queue overflow or GHI */ /* just clear the interrupt */ - outb(Isr, ha->io_addr + HISR); + outb(Isr, ha->io_addr + IPS_REG_HISR); } return (0); @@ -3649,15 +4465,23 @@ ips_isintr(ips_ha_t *ha) { static int ips_wait(ips_ha_t *ha, int time, int intr) { int ret; + u8 done; DBG("ips_wait"); ret = IPS_FAILURE; + done = FALSE; - time *= ONE_SEC; /* convert seconds to milliseconds */ + time *= IPS_ONE_SEC; /* convert seconds to milliseconds */ - while (time > 0) { - if (intr == IPS_INTR_OFF) { + while ((time > 0) && (!done)) { + if (intr == IPS_INTR_ON) { + if (ha->waitflag == FALSE) { + ret = IPS_SUCCESS; + done = TRUE; + break; + } + } else if (intr == IPS_INTR_IORL) { if (ha->waitflag == FALSE) { /* * controller generated an interupt to @@ -3665,28 +4489,50 @@ ips_wait(ips_ha_t *ha, int time, int intr) { * and ips_intr() has serviced the interrupt. */ ret = IPS_SUCCESS; + done = TRUE; break; } /* - * NOTE: Interrupts are disabled here - * On an SMP system interrupts will only - * be disabled on one processor. - * So, ultimately we still need to set the - * "I'm in the interrupt handler flag" + * NOTE: we already have the io_request_lock so + * even if we get an interrupt it won't get serviced + * until after we finish. */ + while (test_and_set_bit(IPS_IN_INTR, &ha->flags)) UDELAY(1000); ips_intr(ha); clear_bit(IPS_IN_INTR, &ha->flags); - - } else { + } else if (intr == IPS_INTR_HAL) { if (ha->waitflag == FALSE) { + /* + * controller generated an interupt to + * acknowledge completion of the command + * and ips_intr() has serviced the interrupt. + */ ret = IPS_SUCCESS; + done = TRUE; break; } + + /* + * NOTE: since we were not called with the iorequest lock + * we must obtain it before we can call the interrupt handler. + * We were called under the HA lock so we can assume that interrupts + * are masked. + */ + spin_lock(&io_request_lock); + + while (test_and_set_bit(IPS_IN_INTR, &ha->flags)) + UDELAY(1000); + + ips_intr(ha); + + clear_bit(IPS_IN_INTR, &ha->flags); + + spin_unlock(&io_request_lock); } UDELAY(1000); /* 1 milisecond */ @@ -3706,10 +4552,10 @@ ips_wait(ips_ha_t *ha, int time, int intr) { /* */ /****************************************************************************/ static int -ips_write_driver_status(ips_ha_t *ha) { +ips_write_driver_status(ips_ha_t *ha, int intr) { DBG("ips_write_driver_status"); - if (!ips_readwrite_page5(ha, FALSE)) { + if (!ips_readwrite_page5(ha, FALSE, intr)) { printk(KERN_WARNING "(%s%d) unable to read NVRAM page 5.\n", ips_name, ha->host_num); @@ -3718,7 +4564,7 @@ ips_write_driver_status(ips_ha_t *ha) { /* check to make sure the page has a valid */ /* signature */ - if (ha->nvram->signature != NVRAM_PAGE5_SIGNATURE) { + if (ha->nvram->signature != IPS_NVRAM_P5_SIG) { #if IPS_DEBUG >= 1 printk("(%s%d) NVRAM page 5 has an invalid signature: %X.\n", ips_name, ha->host_num, ha->nvram->signature); @@ -3739,12 +4585,12 @@ ips_write_driver_status(ips_ha_t *ha) { ha->ad_type = ha->nvram->adapter_type; /* change values (as needed) */ - ha->nvram->operating_system = OS_LINUX; + ha->nvram->operating_system = IPS_OS_LINUX; strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4); strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4); /* now update the page */ - if (!ips_readwrite_page5(ha, TRUE)) { + if (!ips_readwrite_page5(ha, TRUE, intr)) { printk(KERN_WARNING "(%s%d) unable to write NVRAM page 5.\n", ips_name, ha->host_num); @@ -3764,7 +4610,7 @@ ips_write_driver_status(ips_ha_t *ha) { /* */ /****************************************************************************/ static int -ips_read_adapter_status(ips_ha_t *ha) { +ips_read_adapter_status(ips_ha_t *ha, int intr) { ips_scb_t *scb; int ret; @@ -3775,9 +4621,9 @@ ips_read_adapter_status(ips_ha_t *ha) { ips_init_scb(ha, scb); scb->timeout = ips_cmd_timeout; - scb->cdb[0] = ENQUIRY; + scb->cdb[0] = IPS_CMD_ENQUIRY; - scb->cmd.basic_io.op_code = ENQUIRY; + scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY; scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.basic_io.sg_count = 0; scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq); @@ -3787,7 +4633,7 @@ ips_read_adapter_status(ips_ha_t *ha) { scb->cmd.basic_io.reserved = 0; /* send command */ - ret = ips_send_wait(ha, scb, ips_cmd_timeout); + ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr); if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)) return (0); @@ -3804,7 +4650,7 @@ ips_read_adapter_status(ips_ha_t *ha) { /* */ /****************************************************************************/ static int -ips_read_subsystem_parameters(ips_ha_t *ha) { +ips_read_subsystem_parameters(ips_ha_t *ha, int intr) { ips_scb_t *scb; int ret; @@ -3815,9 +4661,9 @@ ips_read_subsystem_parameters(ips_ha_t *ha) { ips_init_scb(ha, scb); scb->timeout = ips_cmd_timeout; - scb->cdb[0] = GET_SUBSYS_PARAM; + scb->cdb[0] = IPS_CMD_GET_SUBSYS; - scb->cmd.basic_io.op_code = GET_SUBSYS_PARAM; + scb->cmd.basic_io.op_code = IPS_CMD_GET_SUBSYS; scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.basic_io.sg_count = 0; scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->subsys); @@ -3827,7 +4673,7 @@ ips_read_subsystem_parameters(ips_ha_t *ha) { scb->cmd.basic_io.reserved = 0; /* send command */ - ret = ips_send_wait(ha, scb, ips_cmd_timeout); + ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr); if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)) return (0); @@ -3844,7 +4690,7 @@ ips_read_subsystem_parameters(ips_ha_t *ha) { /* */ /****************************************************************************/ static int -ips_read_config(ips_ha_t *ha) { +ips_read_config(ips_ha_t *ha, int intr) { ips_scb_t *scb; int i; int ret; @@ -3861,18 +4707,18 @@ ips_read_config(ips_ha_t *ha) { ips_init_scb(ha, scb); scb->timeout = ips_cmd_timeout; - scb->cdb[0] = READ_NVRAM_CONFIGURATION; + scb->cdb[0] = IPS_CMD_READ_CONF; - scb->cmd.basic_io.op_code = READ_NVRAM_CONFIGURATION; + scb->cmd.basic_io.op_code = IPS_CMD_READ_CONF; scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->conf); /* send command */ - if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout)) == IPS_FAILURE) || + if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM) || - ((scb->basic_status & GSC_STATUS_MASK) > 1)) { + ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) { - memset(ha->conf, 0, sizeof(CONFCMD)); + memset(ha->conf, 0, sizeof(IPS_CONF)); /* reset initiator IDs */ ha->conf->init_id[0] = IPS_ADAPTER_ID; @@ -3891,11 +4737,11 @@ ips_read_config(ips_ha_t *ha) { /* */ /* Routine Description: */ /* */ -/* Read the configuration on the adapter */ +/* Read nvram page 5 from the adapter */ /* */ /****************************************************************************/ static int -ips_readwrite_page5(ips_ha_t *ha, int write) { +ips_readwrite_page5(ips_ha_t *ha, int write, int intr) { ips_scb_t *scb; int ret; @@ -3906,9 +4752,9 @@ ips_readwrite_page5(ips_ha_t *ha, int write) { ips_init_scb(ha, scb); scb->timeout = ips_cmd_timeout; - scb->cdb[0] = RW_NVRAM_PAGE; + scb->cdb[0] = IPS_CMD_RW_NVRAM_PAGE; - scb->cmd.nvram.op_code = RW_NVRAM_PAGE; + scb->cmd.nvram.op_code = IPS_CMD_RW_NVRAM_PAGE; scb->cmd.nvram.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.nvram.page = 5; scb->cmd.nvram.write = write; @@ -3917,11 +4763,11 @@ ips_readwrite_page5(ips_ha_t *ha, int write) { scb->cmd.nvram.reserved2 = 0; /* issue the command */ - if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout)) == IPS_FAILURE) || + if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM) || - ((scb->basic_status & GSC_STATUS_MASK) > 1)) { + ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) { - memset(ha->nvram, 0, sizeof(NVRAM_PAGE5)); + memset(ha->nvram, 0, sizeof(IPS_NVRAM_P5)); return (0); } @@ -3939,7 +4785,7 @@ ips_readwrite_page5(ips_ha_t *ha, int write) { /* */ /****************************************************************************/ static int -ips_clear_adapter(ips_ha_t *ha) { +ips_clear_adapter(ips_ha_t *ha, int intr) { ips_scb_t *scb; int ret; @@ -3950,43 +4796,415 @@ ips_clear_adapter(ips_ha_t *ha) { ips_init_scb(ha, scb); scb->timeout = ips_reset_timeout; - scb->cdb[0] = CONFIG_SYNC; + scb->cdb[0] = IPS_CMD_CONFIG_SYNC; - scb->cmd.config_sync.op_code = CONFIG_SYNC; + scb->cmd.config_sync.op_code = IPS_CMD_CONFIG_SYNC; scb->cmd.config_sync.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.config_sync.channel = 0; - scb->cmd.config_sync.source_target = POCL; + scb->cmd.config_sync.source_target = IPS_POCL; scb->cmd.config_sync.reserved = 0; scb->cmd.config_sync.reserved2 = 0; scb->cmd.config_sync.reserved3 = 0; /* issue command */ - ret = ips_send_wait(ha, scb, ips_reset_timeout); + ret = ips_send_wait(ha, scb, ips_reset_timeout, intr); if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)) return (0); /* send unlock stripe command */ ips_init_scb(ha, scb); - scb->cdb[0] = GET_ERASE_ERROR_TABLE; + scb->cdb[0] = IPS_CMD_ERROR_TABLE; scb->timeout = ips_reset_timeout; - scb->cmd.unlock_stripe.op_code = GET_ERASE_ERROR_TABLE; + scb->cmd.unlock_stripe.op_code = IPS_CMD_ERROR_TABLE; scb->cmd.unlock_stripe.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.unlock_stripe.log_drv = 0; - scb->cmd.unlock_stripe.control = CSL; + scb->cmd.unlock_stripe.control = IPS_CSL; scb->cmd.unlock_stripe.reserved = 0; scb->cmd.unlock_stripe.reserved2 = 0; scb->cmd.unlock_stripe.reserved3 = 0; /* issue command */ - ret = ips_send_wait(ha, scb, ips_reset_timeout); + ret = ips_send_wait(ha, scb, ips_reset_timeout, intr); if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)) return (0); return (1); } +/****************************************************************************/ +/* */ +/* Routine Name: ips_ffdc_reset */ +/* */ +/* Routine Description: */ +/* */ +/* FFDC: write reset info */ +/* */ +/****************************************************************************/ +static void +ips_ffdc_reset(ips_ha_t *ha, int intr) { + ips_scb_t *scb; + + DBG("ips_ffdc_reset"); + + scb = &ha->scbs[ha->max_cmds-1]; + + ips_init_scb(ha, scb); + + scb->timeout = ips_cmd_timeout; + scb->cdb[0] = IPS_CMD_FFDC; + scb->cmd.ffdc.op_code = IPS_CMD_FFDC; + scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb); + scb->cmd.ffdc.reset_count = ha->reset_count; + scb->cmd.ffdc.reset_type = 0x80; + + /* convert time to what the card wants */ + ips_fix_ffdc_time(ha, scb, ha->last_ffdc); + + /* issue command */ + ips_send_wait(ha, scb, ips_cmd_timeout, intr); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_ffdc_time */ +/* */ +/* Routine Description: */ +/* */ +/* FFDC: write time info */ +/* */ +/****************************************************************************/ +static void +ips_ffdc_time(ips_ha_t *ha, int intr) { + ips_scb_t *scb; + + DBG("ips_ffdc_time"); + +#if IPS_DEBUG >= 1 + printk(KERN_NOTICE "(%s%d) Sending time update.\n", + ips_name, ha->host_num); +#endif + + scb = &ha->scbs[ha->max_cmds-1]; + + ips_init_scb(ha, scb); + + scb->timeout = ips_cmd_timeout; + scb->cdb[0] = IPS_CMD_FFDC; + scb->cmd.ffdc.op_code = IPS_CMD_FFDC; + scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb); + scb->cmd.ffdc.reset_count = 0; + scb->cmd.ffdc.reset_type = 0x80; + + /* convert time to what the card wants */ + ips_fix_ffdc_time(ha, scb, ha->last_ffdc); + + /* issue command */ + ips_send_wait(ha, scb, ips_cmd_timeout, intr); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_fix_ffdc_time */ +/* */ +/* Routine Description: */ +/* Adjust time_t to what the card wants */ +/* */ +/****************************************************************************/ +static void +ips_fix_ffdc_time(ips_ha_t *ha, ips_scb_t *scb, time_t current_time) { + long days; + long rem; + int i; + int year; + int yleap; + int year_lengths[2] = { IPS_DAYS_NORMAL_YEAR, IPS_DAYS_LEAP_YEAR }; + int month_lengths[12][2] = { {31, 31}, + {28, 29}, + {31, 31}, + {30, 30}, + {31, 31}, + {30, 30}, + {31, 31}, + {31, 31}, + {30, 30}, + {31, 31}, + {30, 30}, + {31, 31} }; + + days = current_time / IPS_SECS_DAY; + rem = current_time % IPS_SECS_DAY; + + scb->cmd.ffdc.hour = (rem / IPS_SECS_HOUR); + rem = rem % IPS_SECS_HOUR; + scb->cmd.ffdc.minute = (rem / IPS_SECS_MIN); + scb->cmd.ffdc.second = (rem % IPS_SECS_MIN); + + year = IPS_EPOCH_YEAR; + while (days < 0 || days >= year_lengths[yleap = IPS_IS_LEAP_YEAR(year)]) { + int newy; + + newy = year + (days / IPS_DAYS_NORMAL_YEAR); + if (days < 0) + --newy; + days -= (newy - year) * IPS_DAYS_NORMAL_YEAR + + IPS_NUM_LEAP_YEARS_THROUGH(newy - 1) - + IPS_NUM_LEAP_YEARS_THROUGH(year - 1); + year = newy; + } + + scb->cmd.ffdc.yearH = year / 100; + scb->cmd.ffdc.yearL = year % 100; + + for (i = 0; days >= month_lengths[i][yleap]; ++i) + days -= month_lengths[i][yleap]; + + scb->cmd.ffdc.month = i + 1; + scb->cmd.ffdc.day = days + 1; +} + +/**************************************************************************** + * BIOS Flash Routines * + ****************************************************************************/ + +/****************************************************************************/ +/* */ +/* Routine Name: ips_erase_bios */ +/* */ +/* Routine Description: */ +/* Erase the BIOS on the adapter */ +/* */ +/****************************************************************************/ +static int +ips_erase_bios(ips_ha_t *ha) { + int timeout; + u8 status; + + /* Clear the status register */ + outl(0, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(0x50, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* Erase Setup */ + outb(0x20, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* Erase Confirm */ + outb(0xD0, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* Erase Status */ + outb(0x70, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + timeout = 80000; /* 80 seconds */ + + while (timeout > 0) { + if (ha->revision_id == IPS_REVID_TROMBONE64) { + outl(0, ha->io_addr + IPS_REG_FLAP); + UDELAY(5); /* 5 us */ + } + + status = inb(ha->io_addr + IPS_REG_FLDP); + + if (status & 0x80) + break; + + MDELAY(1); + timeout--; + } + + /* check for timeout */ + if (timeout <= 0) { + /* timeout */ + + /* try to suspend the erase */ + outb(0xB0, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* wait for 10 seconds */ + timeout = 10000; + while (timeout > 0) { + if (ha->revision_id == IPS_REVID_TROMBONE64) { + outl(0, ha->io_addr + IPS_REG_FLAP); + UDELAY(5); /* 5 us */ + } + + status = inb(ha->io_addr + IPS_REG_FLDP); + + if (status & 0xC0) + break; + + MDELAY(1); + timeout--; + } + + return (1); + } + + /* check for valid VPP */ + if (status & 0x08) + /* VPP failure */ + return (1); + + /* check for succesful flash */ + if (status & 0x30) + /* sequence error */ + return (1); + + /* Otherwise, we were successful */ + /* clear status */ + outb(0x50, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* enable reads */ + outb(0xFF, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + return (0); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_program_bios */ +/* */ +/* Routine Description: */ +/* Program the BIOS on the adapter */ +/* */ +/****************************************************************************/ +static int +ips_program_bios(ips_ha_t *ha, char *buffer, int buffersize) { + int i; + int timeout; + u8 status; + + for (i = 0; i < buffersize; i++) { + /* write a byte */ + outl(i, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(0x40, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(buffer[i], ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* wait up to one second */ + timeout = 1000; + while (timeout > 0) { + if (ha->revision_id == IPS_REVID_TROMBONE64) { + outl(0, ha->io_addr + IPS_REG_FLAP); + UDELAY(5); /* 5 us */ + } + + status = inb(ha->io_addr + IPS_REG_FLDP); + + if (status & 0x80) + break; + + MDELAY(1); + timeout--; + } + + if (timeout == 0) { + /* timeout error */ + outl(0, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(0xFF, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + return (1); + } + + /* check the status */ + if (status & 0x18) { + /* programming error */ + outl(0, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(0xFF, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + return (1); + } + } /* end for */ + + /* Enable reading */ + outl(0, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(0xFF, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + return (0); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_verify_bios */ +/* */ +/* Routine Description: */ +/* Verify the BIOS on the adapter */ +/* */ +/****************************************************************************/ +static int +ips_verify_bios(ips_ha_t *ha, char *buffer, int buffersize) { + u8 checksum; + int i; + + /* test 1st byte */ + outl(0, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55) + return (1); + + outl(1, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA) + return (1); + + checksum = 0xff; + for (i = 2; i < buffersize; i++) { + + outl(i, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + checksum = (u8) checksum + inb(ha->io_addr + IPS_REG_FLDP); + } + + if (checksum != 0) + /* failure */ + return (1); + else + /* success */ + return (0); +} + #if defined (MODULE) Scsi_Host_Template driver_template = IPS; diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index d760ae3a6..e93fe8153 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -47,7 +47,6 @@ #ifndef _IPS_H_ #define _IPS_H_ - #include <linux/config.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -67,209 +66,276 @@ * Some handy macros */ #ifndef LinuxVersionCode - #define LinuxVersionCode(x,y,z) (((x)<<16)+((y)<<8)+(z)) + #define LinuxVersionCode(x,y,z) (((x)<<16)+((y)<<8)+(z)) #endif - #define HA(x) ((ips_ha_t *) x->hostdata) + #define IPS_HA(x) ((ips_ha_t *) x->hostdata) #define IPS_COMMAND_ID(ha, scb) (int) (scb - ha->scbs) - #define VIRT_TO_BUS(x) (unsigned int)virt_to_bus((void *) x) + + #ifndef VIRT_TO_BUS + #define VIRT_TO_BUS(x) (unsigned int)virt_to_bus((void *) x) + #endif - #define UDELAY udelay - #define MDELAY mdelay + #ifndef UDELAY + #define UDELAY udelay + #endif + + #ifndef MDELAY + #define MDELAY mdelay + #endif - #define verify_area_20(t,a,sz) (0) /* success */ - #define PUT_USER put_user - #define __PUT_USER __put_user - #define PUT_USER_RET put_user_ret - #define GET_USER get_user - #define __GET_USER __get_user - #define GET_USER_RET get_user_ret + #ifndef verify_area_20 + #define verify_area_20(t,a,sz) (0) /* success */ + #endif + + #ifndef PUT_USER + #define PUT_USER put_user + #endif + + #ifndef __PUT_USER + #define __PUT_USER __put_user + #endif + + #ifndef PUT_USER_RET + #define PUT_USER_RET put_user_ret + #endif + + #ifndef GET_USER + #define GET_USER get_user + #endif + + #ifndef __GET_USER + #define __GET_USER __get_user + #endif + + #ifndef GET_USER_RET + #define GET_USER_RET get_user_ret + #endif -/* - * Adapter address map equates - */ - #define HISR 0x08 /* Host Interrupt Status Reg */ - #define CCSAR 0x10 /* Cmd Channel System Addr Reg */ - #define CCCR 0x14 /* Cmd Channel Control Reg */ - #define SQHR 0x20 /* Status Q Head Reg */ - #define SQTR 0x24 /* Status Q Tail Reg */ - #define SQER 0x28 /* Status Q End Reg */ - #define SQSR 0x2C /* Status Q Start Reg */ - #define SCPR 0x05 /* Subsystem control port reg */ - #define ISPR 0x06 /* interrupt status port reg */ - #define CBSP 0x07 /* CBSP register */ + /* + * Lock macros + */ + #define IPS_SCB_LOCK(cpu_flags) spin_lock_irqsave(&ha->scb_lock, cpu_flags) + #define IPS_SCB_UNLOCK(cpu_flags) spin_unlock_irqrestore(&ha->scb_lock, cpu_flags) + #define IPS_QUEUE_LOCK(queue) spin_lock_irqsave(&(queue)->lock, (queue)->cpu_flags) + #define IPS_QUEUE_UNLOCK(queue) spin_unlock_irqrestore(&(queue)->lock, (queue)->cpu_flags) + #define IPS_HA_LOCK(cpu_flags) spin_lock_irqsave(&ha->ips_lock, cpu_flags) + #define IPS_HA_UNLOCK(cpu_flags) spin_unlock_irqrestore(&ha->ips_lock, cpu_flags) -/* - * Adapter register bit equates - */ - #define GHI 0x04 /* HISR General Host Interrupt */ - #define SQO 0x02 /* HISR Status Q Overflow */ - #define SCE 0x01 /* HISR Status Channel Enqueue */ - #define SEMAPHORE 0x08 /* CCCR Semaphore Bit */ - #define ILE 0x10 /* CCCR ILE Bit */ - #define START_COMMAND 0x101A /* CCCR Start Command Channel */ - #define START_STOP_BIT 0x0002 /* CCCR Start/Stop Bit */ - #define RST 0x80 /* SCPR Reset Bit */ - #define EBM 0x02 /* SCPR Enable Bus Master */ - #define EI 0x80 /* HISR Enable Interrupts */ - #define OP 0x01 /* OP bit in CBSP */ + /* + * Adapter address map equates + */ + #define IPS_REG_HISR 0x08 /* Host Interrupt Status Reg */ + #define IPS_REG_CCSAR 0x10 /* Cmd Channel System Addr Reg */ + #define IPS_REG_CCCR 0x14 /* Cmd Channel Control Reg */ + #define IPS_REG_SQHR 0x20 /* Status Q Head Reg */ + #define IPS_REG_SQTR 0x24 /* Status Q Tail Reg */ + #define IPS_REG_SQER 0x28 /* Status Q End Reg */ + #define IPS_REG_SQSR 0x2C /* Status Q Start Reg */ + #define IPS_REG_SCPR 0x05 /* Subsystem control port reg */ + #define IPS_REG_ISPR 0x06 /* interrupt status port reg */ + #define IPS_REG_CBSP 0x07 /* CBSP register */ + #define IPS_REG_FLAP 0x18 /* Flash address port */ + #define IPS_REG_FLDP 0x1C /* Flash data port */ -/* - * Adapter Command ID Equates - */ - #define GET_LOGICAL_DRIVE_INFO 0x19 - #define GET_SUBSYS_PARAM 0x40 - #define READ_NVRAM_CONFIGURATION 0x38 - #define RW_NVRAM_PAGE 0xBC - #define IPS_READ 0x02 - #define IPS_WRITE 0x03 - #define ENQUIRY 0x05 - #define FLUSH_CACHE 0x0A - #define NORM_STATE 0x00 - #define READ_SCATTER_GATHER 0x82 - #define WRITE_SCATTER_GATHER 0x83 - #define DIRECT_CDB 0x04 - #define DIRECT_CDB_SCATTER_GATHER 0x84 - #define CONFIG_SYNC 0x58 - #define POCL 0x30 - #define GET_ERASE_ERROR_TABLE 0x17 - #define RESET_CHANNEL 0x1A - #define CSL 0xFF - #define ADAPT_RESET 0xFF + /* + * Adapter register bit equates + */ + #define IPS_BIT_GHI 0x04 /* HISR General Host Interrupt */ + #define IPS_BIT_SQO 0x02 /* HISR Status Q Overflow */ + #define IPS_BIT_SCE 0x01 /* HISR Status Channel Enqueue */ + #define IPS_BIT_SEM 0x08 /* CCCR Semaphore Bit */ + #define IPS_BIT_ILE 0x10 /* CCCR ILE Bit */ + #define IPS_BIT_START_CMD 0x101A /* CCCR Start Command Channel */ + #define IPS_BIT_START_STOP 0x0002 /* CCCR Start/Stop Bit */ + #define IPS_BIT_RST 0x80 /* SCPR Reset Bit */ + #define IPS_BIT_EBM 0x02 /* SCPR Enable Bus Master */ + #define IPS_BIT_EI 0x80 /* HISR Enable Interrupts */ + #define IPS_BIT_OP 0x01 /* OP bit in CBSP */ -/* - * Adapter Equates - */ + /* + * Adapter Command ID Equates + */ + #define IPS_CMD_GET_LD_INFO 0x19 + #define IPS_CMD_GET_SUBSYS 0x40 + #define IPS_CMD_READ_CONF 0x38 + #define IPS_CMD_RW_NVRAM_PAGE 0xBC + #define IPS_CMD_READ 0x02 + #define IPS_CMD_WRITE 0x03 + #define IPS_CMD_FFDC 0xD7 + #define IPS_CMD_ENQUIRY 0x05 + #define IPS_CMD_FLUSH 0x0A + #define IPS_CMD_READ_SG 0x82 + #define IPS_CMD_WRITE_SG 0x83 + #define IPS_CMD_DCDB 0x04 + #define IPS_CMD_DCDB_SG 0x84 + #define IPS_CMD_CONFIG_SYNC 0x58 + #define IPS_CMD_ERROR_TABLE 0x17 + + /* + * Adapter Equates + */ + #define IPS_CSL 0xFF + #define IPS_POCL 0x30 + #define IPS_NORM_STATE 0x00 #define IPS_MAX_ADAPTERS 16 #define IPS_MAX_IOCTL 1 #define IPS_MAX_IOCTL_QUEUE 8 #define IPS_MAX_QUEUE 128 #define IPS_BLKSIZE 512 - #define MAX_SG_ELEMENTS 17 - #define MAX_LOGICAL_DRIVES 8 - #define MAX_CHANNELS 3 - #define MAX_TARGETS 15 - #define MAX_CHUNKS 16 - #define MAX_CMDS 128 + #define IPS_MAX_SG 17 + #define IPS_MAX_LD 8 + #define IPS_MAX_CHANNELS 4 + #define IPS_MAX_TARGETS 15 + #define IPS_MAX_CHUNKS 16 + #define IPS_MAX_CMDS 128 #define IPS_MAX_XFER 0x10000 - #define COMP_MODE_HEADS 128 - #define COMP_MODE_SECTORS 32 - #define NORM_MODE_HEADS 254 - #define NORM_MODE_SECTORS 63 - #define NVRAM_PAGE5_SIGNATURE 0xFFDDBB99 - #define MAX_POST_BYTES 0x02 - #define MAX_CONFIG_BYTES 0x02 - #define GOOD_POST_BASIC_STATUS 0x80 - #define SEMAPHORE_TIMEOUT 2000 - #define IPS_INTR_OFF 0 - #define IPS_INTR_ON 1 + #define IPS_NVRAM_P5_SIG 0xFFDDBB99 + #define IPS_MAX_POST_BYTES 0x02 + #define IPS_MAX_CONFIG_BYTES 0x02 + #define IPS_GOOD_POST_STATUS 0x80 + #define IPS_SEM_TIMEOUT 2000 + #define IPS_IOCTL_COMMAND 0x0D + #define IPS_IOCTL_NEW_COMMAND 0x81 + #define IPS_INTR_ON 0 + #define IPS_INTR_IORL 1 + #define IPS_INTR_HAL 2 #define IPS_ADAPTER_ID 0xF #define IPS_VENDORID 0x1014 #define IPS_DEVICEID 0x002E - #define TIMEOUT_10 0x10 - #define TIMEOUT_60 0x20 - #define TIMEOUT_20M 0x30 - #define STATUS_SIZE 4 - #define STATUS_Q_SIZE (MAX_CMDS+1) * STATUS_SIZE - #define ONE_MSEC 1 - #define ONE_SEC 1000 + #define IPS_IOCTL_SIZE 8192 + #define IPS_STATUS_SIZE 4 + #define IPS_STATUS_Q_SIZE (IPS_MAX_CMDS+1) * IPS_STATUS_SIZE + #define IPS_ONE_MSEC 1 + #define IPS_ONE_SEC 1000 + + /* + * Geometry Settings + */ + #define IPS_COMP_HEADS 128 + #define IPS_COMP_SECTORS 32 + #define IPS_NORM_HEADS 254 + #define IPS_NORM_SECTORS 63 -/* - * Adapter Basic Status Codes - */ - #define BASIC_STATUS_MASK 0xFF - #define GSC_STATUS_MASK 0x0F - #define SSUCCESS 0x00 - #define RECOVERED_ERROR 0x01 - #define IPS_CHECK_CONDITION 0x02 - #define INVAL_OPCO 0x03 - #define INVAL_CMD_BLK 0x04 - #define INVAL_PARM_BLK 0x05 + /* + * Adapter Basic Status Codes + */ + #define IPS_BASIC_STATUS_MASK 0xFF + #define IPS_GSC_STATUS_MASK 0x0F + #define IPS_CMD_SUCCESS 0x00 + #define IPS_CMD_RECOVERED_ERROR 0x01 + #define IPS_INVAL_OPCO 0x03 + #define IPS_INVAL_CMD_BLK 0x04 + #define IPS_INVAL_PARM_BLK 0x05 #define IPS_BUSY 0x08 - #define ADAPT_HARDWARE_ERROR 0x09 - #define ADAPT_FIRMWARE_ERROR 0x0A - #define CMD_CMPLT_WERROR 0x0C - #define LOG_DRV_ERROR 0x0D - #define CMD_TIMEOUT 0x0E - #define PHYS_DRV_ERROR 0x0F + #define IPS_CMD_CMPLT_WERROR 0x0C + #define IPS_LD_ERROR 0x0D + #define IPS_CMD_TIMEOUT 0x0E + #define IPS_PHYS_DRV_ERROR 0x0F -/* - * Adapter Extended Status Equates - */ - #define SELECTION_TIMEOUT 0xF0 - #define DATA_OVER_UNDER_RUN 0xF2 - #define EXT_HOST_RESET 0xF7 - #define EXT_DEVICE_RESET 0xF8 - #define EXT_RECOVERY 0xFC - #define EXT_CHECK_CONDITION 0xFF + /* + * Adapter Extended Status Equates + */ + #define IPS_ERR_SEL_TO 0xF0 + #define IPS_ERR_OU_RUN 0xF2 + #define IPS_ERR_HOST_RESET 0xF7 + #define IPS_ERR_DEV_RESET 0xF8 + #define IPS_ERR_RECOVERY 0xFC + #define IPS_ERR_CKCOND 0xFF -/* - * Operating System Defines - */ - #define OS_WINDOWS_NT 0x01 - #define OS_NETWARE 0x02 - #define OS_OPENSERVER 0x03 - #define OS_UNIXWARE 0x04 - #define OS_SOLARIS 0x05 - #define OS_OS2 0x06 - #define OS_LINUX 0x07 - #define OS_FREEBSD 0x08 + /* + * Operating System Defines + */ + #define IPS_OS_WINDOWS_NT 0x01 + #define IPS_OS_NETWARE 0x02 + #define IPS_OS_OPENSERVER 0x03 + #define IPS_OS_UNIXWARE 0x04 + #define IPS_OS_SOLARIS 0x05 + #define IPS_OS_OS2 0x06 + #define IPS_OS_LINUX 0x07 + #define IPS_OS_FREEBSD 0x08 -/* - * Adapter Command/Status Packet Definitions - */ + /* + * Adapter Revision ID's + */ + #define IPS_REVID_SERVERAID 0x02 + #define IPS_REVID_NAVAJO 0x03 + #define IPS_REVID_SERVERAID2 0x04 + #define IPS_REVID_CLARINETP1 0x05 + #define IPS_REVID_CLARINETP2 0x07 + #define IPS_REVID_CLARINETP3 0x0D + #define IPS_REVID_TROMBONE32 0x0F + #define IPS_REVID_TROMBONE64 0x10 + + /* + * Adapter Command/Status Packet Definitions + */ #define IPS_SUCCESS 0x01 /* Successfully completed */ #define IPS_SUCCESS_IMM 0x02 /* Success - Immediately */ #define IPS_FAILURE 0x04 /* Completed with Error */ -/* - * Logical Drive Equates - */ - #define OFF_LINE 0x02 - #define OKAY 0x03 - #define FREE 0x00 - #define SYS 0x06 - #define CRS 0x24 + /* + * Logical Drive Equates + */ + #define IPS_LD_OFFLINE 0x02 + #define IPS_LD_OKAY 0x03 + #define IPS_LD_FREE 0x00 + #define IPS_LD_SYS 0x06 + #define IPS_LD_CRS 0x24 -/* - * DCDB Table Equates - */ - #define NO_DISCONNECT 0x00 - #define DISCONNECT_ALLOWED 0x80 - #define NO_AUTO_REQUEST_SENSE 0x40 - #define IPS_DATA_NONE 0x00 - #define IPS_DATA_UNK 0x00 + /* + * DCDB Table Equates + */ + #define IPS_NO_DISCONNECT 0x00 + #define IPS_DISCONNECT_ALLOWED 0x80 + #define IPS_NO_AUTO_REQSEN 0x40 + #define IPS_DATA_NONE 0x00 + #define IPS_DATA_UNK 0x00 #define IPS_DATA_IN 0x01 #define IPS_DATA_OUT 0x02 - #define TRANSFER_64K 0x08 - #define NOTIMEOUT 0x00 - #define TIMEOUT10 0x10 - #define TIMEOUT60 0x20 - #define TIMEOUT20M 0x30 + #define IPS_TRANSFER64K 0x08 + #define IPS_NOTIMEOUT 0x00 + #define IPS_TIMEOUT10 0x10 + #define IPS_TIMEOUT60 0x20 + #define IPS_TIMEOUT20M 0x30 -/* - * Host adapter Flags (bit numbers) - */ + /* + * Host adapter Flags (bit numbers) + */ #define IPS_IN_INTR 0 #define IPS_IN_ABORT 1 #define IPS_IN_RESET 2 -/* - * SCB Flags - */ - #define SCB_ACTIVE 0x00001 - #define SCB_WAITING 0x00002 + /* + * SCB Flags + */ + #define IPS_SCB_ACTIVE 0x00001 + #define IPS_SCB_WAITING 0x00002 -/* - * Passthru stuff - */ - #define COPPUSRCMD (('C'<<8) | 65) + /* + * Passthru stuff + */ + #define IPS_COPPUSRCMD (('C'<<8) | 65) + #define IPS_COPPIOCCMD (('C'<<8) | 66) #define IPS_NUMCTRLS (('C'<<8) | 68) #define IPS_CTRLINFO (('C'<<8) | 69) + #define IPS_FLASHBIOS (('C'<<8) | 70) -/* - * Scsi_Host Template - */ + /* time oriented stuff */ + #define IPS_IS_LEAP_YEAR(y) (((y % 4 == 0) && ((y % 100 != 0) || (y % 400 == 0))) ? 1 : 0) + #define IPS_NUM_LEAP_YEARS_THROUGH(y) ((y) / 4 - (y) / 100 + (y) / 400) + + #define IPS_SECS_MIN 60 + #define IPS_SECS_HOUR 3600 + #define IPS_SECS_8HOURS 28800 + #define IPS_SECS_DAY 86400 + #define IPS_DAYS_NORMAL_YEAR 365 + #define IPS_DAYS_LEAP_YEAR 366 + #define IPS_EPOCH_YEAR 1970 + + /* + * Scsi_Host Template + */ #define IPS { \ next : NULL, \ module : NULL, \ @@ -291,7 +357,7 @@ bios_param : ips_biosparam, \ can_queue : 0, \ this_id: -1, \ - sg_tablesize : MAX_SG_ELEMENTS, \ + sg_tablesize : IPS_MAX_SG, \ cmd_per_lun: 16, \ present : 0, \ unchecked_isa_dma : 0, \ @@ -313,7 +379,7 @@ typedef struct { u16 reserved; u32 ccsar; u32 cccr; -} BASIC_IO_CMD, *PBASIC_IO_CMD; +} IPS_IO_CMD, *PIPS_IO_CMD; typedef struct { u8 op_code; @@ -324,7 +390,7 @@ typedef struct { u32 reserved3; u32 ccsar; u32 cccr; -} LOGICAL_INFO, *PLOGICAL_INFO; +} IPS_LD_CMD, *PIPS_LD_CMD; typedef struct { u8 op_code; @@ -334,7 +400,7 @@ typedef struct { u32 reserved3; u32 buffer_addr; u32 reserved4; -} IOCTL_INFO, *PIOCTL_INFO; +} IPS_IOCTL_CMD, *PIPS_IOCTL_CMD; typedef struct { u8 op_code; @@ -345,7 +411,7 @@ typedef struct { u32 reserved3; u32 ccsar; u32 cccr; -} DCDB_CMD, *PDCDB_CMD; +} IPS_DCDB_CMD, *PIPS_DCDB_CMD; typedef struct { u8 op_code; @@ -357,7 +423,7 @@ typedef struct { u32 reserved3; u32 ccsar; u32 cccr; -} CONFIG_SYNC_CMD, *PCONFIG_SYNC_CMD; +} IPS_CS_CMD, *PIPS_CS_CMD; typedef struct { u8 op_code; @@ -369,7 +435,7 @@ typedef struct { u32 reserved3; u32 ccsar; u32 cccr; -} UNLOCK_STRIPE_CMD, *PUNLOCK_STRIPE_CMD; +} IPS_US_CMD, *PIPS_US_CMD; typedef struct { u8 op_code; @@ -381,7 +447,7 @@ typedef struct { u32 reserved4; u32 ccsar; u32 cccr; -} FLUSH_CACHE_CMD, *PFLUSH_CACHE_CMD; +} IPS_FC_CMD, *PIPS_FC_CMD; typedef struct { u8 op_code; @@ -393,7 +459,7 @@ typedef struct { u32 reserved3; u32 ccsar; u32 cccr; -} STATUS_CMD, *PSTATUS_CMD; +} IPS_STATUS_CMD, *PIPS_STATUS_CMD; typedef struct { u8 op_code; @@ -405,19 +471,36 @@ typedef struct { u32 reserved2; u32 ccsar; u32 cccr; -} NVRAM_CMD, *PNVRAM_CMD; +} IPS_NVRAM_CMD, *PIPS_NVRAM_CMD; + +typedef struct { + u8 op_code; + u8 command_id; + u8 reset_count; + u8 reset_type; + u8 second; + u8 minute; + u8 hour; + u8 day; + u8 reserved1[4]; + u8 month; + u8 yearH; + u8 yearL; + u8 reserved2; +} IPS_FFDC_CMD, *PIPS_FFDC_CMD; typedef union { - BASIC_IO_CMD basic_io; - LOGICAL_INFO logical_info; - IOCTL_INFO ioctl_info; - DCDB_CMD dcdb; - CONFIG_SYNC_CMD config_sync; - UNLOCK_STRIPE_CMD unlock_stripe; - FLUSH_CACHE_CMD flush_cache; - STATUS_CMD status; - NVRAM_CMD nvram; -} HOST_COMMAND, *PHOST_COMMAND; + IPS_IO_CMD basic_io; + IPS_LD_CMD logical_info; + IPS_IOCTL_CMD ioctl_info; + IPS_DCDB_CMD dcdb; + IPS_CS_CMD config_sync; + IPS_US_CMD unlock_stripe; + IPS_FC_CMD flush_cache; + IPS_STATUS_CMD status; + IPS_NVRAM_CMD nvram; + IPS_FFDC_CMD ffdc; +} IPS_HOST_COMMAND, *PIPS_HOST_COMMAND; typedef struct { u8 logical_id; @@ -425,25 +508,13 @@ typedef struct { u8 raid_level; u8 state; u32 sector_count; -} DRIVE_INFO, *PDRIVE_INFO; - -typedef struct { - u8 no_of_log_drive; - u8 reserved[3]; - DRIVE_INFO drive_info[MAX_LOGICAL_DRIVES]; -} LOGICAL_DRIVE_INFO, *PLOGICAL_DRIVE_INFO; +} IPS_DRIVE_INFO, *PIPS_DRIVE_INFO; typedef struct { - u8 ha_num; - u8 bus_num; - u8 id; - u8 device_type; - u32 data_len; - u32 data_ptr; - u8 scsi_cdb[12]; - u32 data_counter; - u32 block_size; -} NON_DISK_DEVICE_INFO, *PNON_DISK_DEVICE_INFO; + u8 no_of_log_drive; + u8 reserved[3]; + IPS_DRIVE_INFO drive_info[IPS_MAX_LD]; +} IPS_LD_INFO, *PIPS_LD_INFO; typedef struct { u8 device_address; @@ -458,24 +529,24 @@ typedef struct { u8 sense_info[64]; u8 scsi_status; u8 reserved2[3]; -} DCDB_TABLE, *PDCDB_TABLE; +} IPS_DCDB_TABLE, *PIPS_DCDB_TABLE; typedef struct { volatile u8 reserved; volatile u8 command_id; volatile u8 basic_status; volatile u8 extended_status; -} STATUS, *PSTATUS; +} IPS_STATUS, *PIPS_STATUS; typedef struct { - STATUS status[MAX_CMDS + 1]; - volatile PSTATUS p_status_start; - volatile PSTATUS p_status_end; - volatile PSTATUS p_status_tail; + IPS_STATUS status[IPS_MAX_CMDS + 1]; + volatile PIPS_STATUS p_status_start; + volatile PIPS_STATUS p_status_end; + volatile PIPS_STATUS p_status_tail; volatile u32 hw_status_start; volatile u32 hw_status_tail; - LOGICAL_DRIVE_INFO logical_drive_info; -} ADAPTER_AREA, *PADAPTER_AREA; + IPS_LD_INFO logical_drive_info; +} IPS_ADAPTER, *PIPS_ADAPTER; typedef struct { u8 ucLogDriveCount; @@ -488,7 +559,7 @@ typedef struct { u8 ucNVramDevChgCnt; u8 CodeBlkVersion[8]; u8 BootBlkVersion[8]; - u32 ulDriveSize[MAX_LOGICAL_DRIVES]; + u32 ulDriveSize[IPS_MAX_LD]; u8 ucConcurrentCmdCount; u8 ucMaxPhysicalDevices; u16 usFlashRepgmCount; @@ -499,8 +570,8 @@ typedef struct { u16 usConfigUpdateCount; u8 ucBlkFlag; u8 reserved; - u16 usAddrDeadDisk[MAX_CHANNELS * MAX_TARGETS]; -} ENQCMD, *PENQCMD; + u16 usAddrDeadDisk[IPS_MAX_CHANNELS * IPS_MAX_TARGETS]; +} IPS_ENQ, *PIPS_ENQ; typedef struct { u8 ucInitiator; @@ -509,7 +580,7 @@ typedef struct { u8 ucState; u32 ulBlockCount; u8 ucDeviceId[28]; -} DEVSTATE, *PDEVSTATE; +} IPS_DEVSTATE, *PIPS_DEVSTATE; typedef struct { u8 ucChn; @@ -517,7 +588,7 @@ typedef struct { u16 ucReserved; u32 ulStartSect; u32 ulNoOfSects; -} CHUNK, *PCHUNK; +} IPS_CHUNK, *PIPS_CHUNK; typedef struct { u16 ucUserField; @@ -528,8 +599,8 @@ typedef struct { u8 ucParams; u8 ucReserved; u32 ulLogDrvSize; - CHUNK chunk[MAX_CHUNKS]; -} LOGICAL_DRIVE, *PLOGICAL_DRIVE; + IPS_CHUNK chunk[IPS_MAX_CHUNKS]; +} IPS_LD, *PIPS_LD; typedef struct { u8 board_disc[8]; @@ -539,7 +610,7 @@ typedef struct { u8 ucCompression; u8 ucNvramType; u32 ulNvramSize; -} HARDWARE_DISC, *PHARDWARE_DISC; +} IPS_HARDWARE, *PIPS_HARDWARE; typedef struct { u8 ucLogDriveCount; @@ -563,12 +634,12 @@ typedef struct { u16 user_field; u8 ucRebuildRate; u8 ucReserve; - HARDWARE_DISC hardware_disc; - LOGICAL_DRIVE logical_drive[MAX_LOGICAL_DRIVES]; - DEVSTATE dev[MAX_CHANNELS][MAX_TARGETS+1]; + IPS_HARDWARE hardware_disc; + IPS_LD logical_drive[IPS_MAX_LD]; + IPS_DEVSTATE dev[IPS_MAX_CHANNELS][IPS_MAX_TARGETS+1]; u8 reserved[512]; -} CONFCMD, *PCONFCMD; +} IPS_CONF, *PIPS_CONF; typedef struct { u32 signature; @@ -583,11 +654,11 @@ typedef struct { u8 driver_high[4]; u8 driver_low[4]; u8 reserved4[100]; -} NVRAM_PAGE5, *PNVRAM_PAGE5; +} IPS_NVRAM_P5, *PIPS_NVRAM_P5; -typedef struct _SUBSYS_PARAM { +typedef struct _IPS_SUBSYS { u32 param[128]; -} SUBSYS_PARAM, *PSUBSYS_PARAM; +} IPS_SUBSYS, *PIPS_SUBSYS; /* * Inquiry Data Format @@ -614,7 +685,7 @@ typedef struct { u8 ProductRevisionLevel[4]; u8 VendorSpecific[20]; u8 Reserved3[40]; -} IPS_INQUIRYDATA, *IPS_PINQUIRYDATA; +} IPS_INQ_DATA, *PIPS_INQ_DATA; /* * Read Capacity Data Format @@ -622,7 +693,7 @@ typedef struct { typedef struct { u32 lba; u32 len; -} CAPACITY_T; +} IPS_CAPACITY; /* * Sense Data Format @@ -646,7 +717,7 @@ typedef struct { u32 pg_rmb:1; /* Removeable */ u32 pg_hsec:1; /* Hard sector formatting */ u32 pg_ssec:1; /* Soft sector formatting */ -} DADF_T; +} IPS_DADF; typedef struct { u8 pg_pc:6; /* Page Code */ @@ -662,9 +733,9 @@ typedef struct { u32 pg_landu:16; /* Landing zone cylinder (upper) */ u32 pg_landl:8; /* Landing zone cylinder (lower) */ u32 pg_res2:24; /* Reserved */ -} RDDG_T; +} IPS_RDDG; -struct blk_desc { +struct ips_blk_desc { u8 bd_dencode; u8 bd_nblks1; u8 bd_nblks2; @@ -681,15 +752,15 @@ typedef struct { u8 plh_res:7; /* Reserved */ u8 plh_wp:1; /* Write protect */ u8 plh_bdl; /* Block descriptor length */ -} SENSE_PLH_T; +} ips_sense_plh_t; typedef struct { - SENSE_PLH_T plh; - struct blk_desc blk_desc; + ips_sense_plh_t plh; + struct ips_blk_desc blk_desc; union { - DADF_T pg3; - RDDG_T pg4; + IPS_DADF pg3; + IPS_RDDG pg4; } pdata; } ips_mdata_t; @@ -699,14 +770,14 @@ typedef struct { typedef struct ips_sglist { u32 address; u32 length; -} SG_LIST, *PSG_LIST; +} IPS_SG_LIST, *PIPS_SG_LIST; -typedef struct _INFOSTR { +typedef struct _IPS_INFOSTR { char *buffer; int length; int offset; int pos; -} INFOSTR; +} IPS_INFOSTR; /* * Status Info @@ -722,7 +793,9 @@ typedef struct ips_stat { typedef struct ips_scb_queue { struct ips_scb *head; struct ips_scb *tail; - unsigned int count; + u32 count; + u32 cpu_flags; + spinlock_t lock; } ips_scb_queue_t; /* @@ -731,12 +804,28 @@ typedef struct ips_scb_queue { typedef struct ips_wait_queue { Scsi_Cmnd *head; Scsi_Cmnd *tail; - unsigned int count; + u32 count; + u32 cpu_flags; + spinlock_t lock; } ips_wait_queue_t; +typedef struct ips_copp_wait_item { + Scsi_Cmnd *scsi_cmd; + struct semaphore *sem; + struct ips_copp_wait_item *next; +} ips_copp_wait_item_t; + +typedef struct ips_copp_queue { + struct ips_copp_wait_item *head; + struct ips_copp_wait_item *tail; + u32 count; + u32 cpu_flags; + spinlock_t lock; +} ips_copp_queue_t; + typedef struct ips_ha { - u8 ha_id[MAX_CHANNELS+1]; - u32 dcdb_active[MAX_CHANNELS]; + u8 ha_id[IPS_MAX_CHANNELS+1]; + u32 dcdb_active[IPS_MAX_CHANNELS]; u32 io_addr; /* Base I/O address */ u8 irq; /* IRQ for adapter */ u8 ntargets; /* Number of targets */ @@ -751,35 +840,39 @@ typedef struct ips_ha { struct ips_scb *scbs; /* Array of all CCBS */ struct ips_scb *scb_freelist; /* SCB free list */ ips_wait_queue_t scb_waitlist; /* Pending SCB list */ - ips_wait_queue_t copp_waitlist; /* Pending PT list */ + ips_copp_queue_t copp_waitlist; /* Pending PT list */ ips_scb_queue_t scb_activelist; /* Active SCB list */ - BASIC_IO_CMD *dummy; /* dummy command */ - ADAPTER_AREA *adapt; /* Adapter status area */ - ENQCMD *enq; /* Adapter Enquiry data */ - CONFCMD *conf; /* Adapter config data */ - NVRAM_PAGE5 *nvram; /* NVRAM page 5 data */ - SUBSYS_PARAM *subsys; /* Subsystem parameters */ + IPS_IO_CMD *dummy; /* dummy command */ + IPS_ADAPTER *adapt; /* Adapter status area */ + IPS_ENQ *enq; /* Adapter Enquiry data */ + IPS_CONF *conf; /* Adapter config data */ + IPS_NVRAM_P5 *nvram; /* NVRAM page 5 data */ + IPS_SUBSYS *subsys; /* Subsystem parameters */ + char *ioctl_data; /* IOCTL data area */ + u32 ioctl_datasize; /* IOCTL data size */ u32 cmd_in_progress; /* Current command in progress*/ u32 flags; /* HA flags */ u8 waitflag; /* are we waiting for cmd */ u8 active; - u32 reserved:16; /* reserved space */ - wait_queue_head_t copp_queue; /* passthru sync queue */ + u16 reset_count; /* number of resets */ + u32 last_ffdc; /* last time we sent ffdc info*/ + u8 revision_id; /* Revision level */ #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0) spinlock_t scb_lock; spinlock_t copp_lock; + spinlock_t ips_lock; #endif } ips_ha_t; -typedef void (*scb_callback) (ips_ha_t *, struct ips_scb *); +typedef void (*ips_scb_callback) (ips_ha_t *, struct ips_scb *); /* * SCB Format */ typedef struct ips_scb { - HOST_COMMAND cmd; - DCDB_TABLE dcdb; + IPS_HOST_COMMAND cmd; + IPS_DCDB_TABLE dcdb; u8 target_id; u8 bus; u8 lun; @@ -794,32 +887,54 @@ typedef struct ips_scb { u32 sg_len; u32 flags; u32 op_code; - SG_LIST *sg_list; + IPS_SG_LIST *sg_list; Scsi_Cmnd *scsi_cmd; struct ips_scb *q_next; - scb_callback callback; + ips_scb_callback callback; + struct semaphore *sem; } ips_scb_t; +typedef struct ips_scb_pt { + IPS_HOST_COMMAND cmd; + IPS_DCDB_TABLE dcdb; + u8 target_id; + u8 bus; + u8 lun; + u8 cdb[12]; + u32 scb_busaddr; + u32 data_busaddr; + u32 timeout; + u8 basic_status; + u8 extended_status; + u16 breakup; + u32 data_len; + u32 sg_len; + u32 flags; + u32 op_code; + IPS_SG_LIST *sg_list; + Scsi_Cmnd *scsi_cmd; + struct ips_scb *q_next; + ips_scb_callback callback; +} ips_scb_pt_t; + /* * Passthru Command Format */ typedef struct { - u8 CoppID[4]; - u32 CoppCmd; - u32 PtBuffer; - u8 *CmdBuffer; - u32 CmdBSize; - ips_scb_t CoppCP; - u32 TimeOut; - u8 BasicStatus; - u8 ExtendedStatus; - u16 reserved; + u8 CoppID[4]; + u32 CoppCmd; + u32 PtBuffer; + u8 *CmdBuffer; + u32 CmdBSize; + ips_scb_pt_t CoppCP; + u32 TimeOut; + u8 BasicStatus; + u8 ExtendedStatus; + u16 reserved; } ips_passthru_t; #endif - - /* * Overrides for Emacs so that we almost follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 2c7dbb018..399148c74 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -62,7 +62,7 @@ obj-$(CONFIG_SOUND_VMIDI) += v_midi.o obj-$(CONFIG_SOUND_VIDC) += vidc_mod.o obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o obj-$(CONFIG_SOUND_SGALAXY) += sgalaxy.o ad1848.o -obj-$(CONFIG_SOUND_AD1816) += ad1816.o sound.o +obj-$(CONFIG_SOUND_AD1816) += ad1816.o obj-$(CONFIG_SOUND_ACI_MIXER) += aci.o obj-$(CONFIG_SOUND_AWE32_SYNTH) += awe_wave.o diff --git a/drivers/video/Config.in b/drivers/video/Config.in index 0b30ebb38..fe26b4c01 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -64,14 +64,12 @@ if [ "$CONFIG_FB" = "y" ]; then fi if [ "$CONFIG_PPC" = "y" ]; then bool ' Open Firmware frame buffer device support' CONFIG_FB_OF - if [ "$CONFIG_FB_OF" = "y" ]; then - bool ' Apple "control" display support' CONFIG_FB_CONTROL - bool ' Apple "platinum" display support' CONFIG_FB_PLATINUM - bool ' Apple "valkyrie" display support' CONFIG_FB_VALKYRIE - bool ' IMS Twin Turbo display support' CONFIG_FB_IMSTT - bool ' Chips 65550 display support' CONFIG_FB_CT65550 - bool ' S3 Trio display support' CONFIG_FB_S3TRIO - fi + bool ' Apple "control" display support' CONFIG_FB_CONTROL + bool ' Apple "platinum" display support' CONFIG_FB_PLATINUM + bool ' Apple "valkyrie" display support' CONFIG_FB_VALKYRIE + bool ' Chips 65550 display support' CONFIG_FB_CT65550 + bool ' IMS Twin Turbo display support' CONFIG_FB_IMSTT + bool ' S3 Trio display support' CONFIG_FB_S3TRIO tristate ' VGA 16-color graphics console' CONFIG_FB_VGA16 fi if [ "$CONFIG_MAC" = "y" ]; then diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c index 333fd6576..bcc2b9b7b 100644 --- a/drivers/video/S3triofb.c +++ b/drivers/video/S3triofb.c @@ -77,6 +77,7 @@ static struct fb_var_screeninfo fb_var = { 0, }; * Interface used by the world */ +static void __init s3triofb_of_init(struct device_node *dp); static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info); static int s3trio_get_var(struct fb_var_screeninfo *var, int con, @@ -263,12 +264,11 @@ static int s3trio_set_cmap(struct fb_cmap *cmap, int kspc, int con, int __init s3triofb_init(void) { -#ifdef __powerpc__ - /* We don't want to be called like this. */ - /* We rely on Open Firmware (offb) instead. */ -#else /* !__powerpc__ */ - /* To be merged with cybervision */ -#endif /* !__powerpc__ */ + struct device_node *dp; + + dp = find_devices("S3Trio"); + if (dp != 0) + s3triofb_of_init(dp); return 0; } @@ -376,10 +376,10 @@ int __init s3trio_init(struct device_node *dp){ * We heavily rely on OF for the moment. This needs fixing. */ -void __init s3triofb_init_of(struct device_node *dp) +static void __init s3triofb_of_init(struct device_node *dp) { int i, *pp, len; - unsigned long address; + unsigned long address, size; u_long *CursorBase; strncat(s3trio_name, dp->name, sizeof(s3trio_name)); @@ -416,9 +416,13 @@ void __init s3triofb_init_of(struct device_node *dp) fb_fix.line_length = fb_var.xres_virtual; fb_fix.smem_len = fb_fix.line_length*fb_var.yres; - s3trio_init(dp); address = 0xc6000000; - s3trio_base = ioremap(address,64*1024*1024); + size = 64*1024*1024; + if (!request_mem_region(address, size, "S3triofb")) + return; + + s3trio_init(dp); + s3trio_base = ioremap(address, size); fb_fix.smem_start = address; fb_fix.type = FB_TYPE_PACKED_PIXELS; fb_fix.type_aux = 0; @@ -695,12 +699,6 @@ static void do_install_cmap(int con, struct fb_info *info) s3trio_setcolreg, &fb_info); } -int s3triofb_setup(char *options) { - - return 0; - -} - static void Trio_WaitQueue(u_short fifo) { u_short status; diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 96a3b9a79..22f6031b2 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -113,8 +113,8 @@ static struct pmu_sleep_notifier chips_sleep_notifier = { * Exported functions */ int chips_init(void); -void chips_of_init(struct device_node *dp); +static void chips_of_init(struct device_node *dp); static int chips_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info); static int chips_get_var(struct fb_var_screeninfo *var, int con, @@ -625,17 +625,15 @@ static void __init init_chips(struct fb_info_chips *p) int __init chips_init(void) { -#ifndef CONFIG_FB_OF struct device_node *dp; dp = find_devices("chips65550"); if (dp != 0) chips_of_init(dp); -#endif /* CONFIG_FB_OF */ return 0; } -void __init chips_of_init(struct device_node *dp) +static void __init chips_of_init(struct device_node *dp) { struct fb_info_chips *p; unsigned long addr; @@ -649,6 +647,10 @@ void __init chips_of_init(struct device_node *dp) return; memset(p, 0, sizeof(*p)); addr = dp->addrs[0].address; + if (!request_mem_region(addr, dp->addrs[0].size, "chipsfb")) { + kfree(p); + return; + } #ifdef __BIG_ENDIAN addr += 0x800000; // Use big-endian aperture #endif diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c index a88919d65..e38198485 100644 --- a/drivers/video/clgenfb.c +++ b/drivers/video/clgenfb.c @@ -56,9 +56,6 @@ #ifdef CONFIG_AMIGA #include <asm/amigahw.h> #endif -#ifdef CONFIG_FB_OF -#include <asm/prom.h> -#endif #include <video/fbcon.h> #include <video/fbcon-mfb.h> @@ -472,9 +469,6 @@ int clgenfb_setup (char *options); static int clgenfb_open (struct fb_info *info, int user); static int clgenfb_release (struct fb_info *info, int user); -#if defined(CONFIG_FB_OF) -int clgen_of_init (struct device_node *dp); -#endif /* function table of the above functions */ static struct fb_ops clgenfb_ops = { @@ -2400,34 +2394,6 @@ static void __init get_prep_addrs (unsigned long *display, unsigned long *regist -#ifdef CONFIG_FB_OF -static void __init get_of_addrs (const struct device_node *dp, - unsigned long *display, unsigned long *registers) -{ - int i; - - DPRINTK ("ENTER\n"); - - /* Map in frame buffer and registers */ - for (i = 0; i < dp->n_addrs; ++i) { - unsigned long addr = dp->addrs[i].address; - unsigned long size = dp->addrs[i].size; - printk ("dp->addrs[%d].address = %lx, dp->addrs[%d].size = %lx\n", - i, addr, i, size); - if (size >= 0x800000) { - *display = addr; - } else { - *registers = addr; - } - } - - DPRINTK ("EXIT\n"); -} -#endif /* CONFIG_FB_OF */ - - - - #ifdef CONFIG_PCI /* Pulled the logic from XFree86 Cirrus driver to get the memory size, * based on the DRAM bandwidth bit and DRAM bank switching bit. This @@ -2529,9 +2495,6 @@ static void __exit clgen_pci_unmap (struct clgenfb_info *info) static int __init clgen_pci_setup (struct clgenfb_info *info, clgen_board_t *btype) { -#ifdef CONFIG_FB_OF - struct device_node *dp; -#endif /* CONFIG_FB_OF */ struct pci_dev *pdev; unsigned long board_addr, board_size; @@ -2554,29 +2517,12 @@ static int __init clgen_pci_setup (struct clgenfb_info *info, pcibios_write_config_dword (0, pdev->devfn, PCI_BASE_ADDRESS_0, 0x00000000); #endif -#ifdef CONFIG_FB_OF - /* Ok, so its an ugly hack, since we could have passed it down from - * clgen_of_init() if we'd done it right. */ - DPRINTK ("Attempt to get OF info for MacPicasso\n"); - dp = find_devices ("MacPicasso"); - if (dp != 0) { - if (dp->n_addrs != 2) { - printk (KERN_ERR "expecting 2 address for clgen (got %d)\n", dp->n_addrs); - DPRINTK ("EXIT, returning 1\n"); - return 1; - } - get_of_addrs (dp, &board_addr, &info->fbregs_phys); - } else -#endif - { - #ifdef CONFIG_PREP - get_prep_addrs (&board_addr, &info->fbregs_phys); + get_prep_addrs (&board_addr, &info->fbregs_phys); #else /* CONFIG_PREP */ - DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n"); - get_pci_addrs (pdev, &board_addr, &info->fbregs_phys); + DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n"); + get_pci_addrs (pdev, &board_addr, &info->fbregs_phys); #endif /* CONFIG_PREP */ - } DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, info->fbregs_phys); @@ -2838,14 +2784,6 @@ int __init clgenfb_init(void) -#if defined(CONFIG_FB_OF) -int __init clgen_of_init (struct device_node *dp) -{ - return clgenfb_init (); -} -#endif /* CONFIG_FB_OF */ - - /* * Cleanup (only needed for module) */ diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 10453891d..b609f43f2 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -146,11 +146,9 @@ static int default_cmode = CMODE_NVRAM; * Exported functions */ int control_init(void); -#ifdef CONFIG_FB_OF -void control_of_init(struct device_node *dp); -#endif void control_setup(char *); +static void control_of_init(struct device_node *dp); static int read_control_sense(struct fb_info_control *p); static inline int control_vram_reqd(int video_mode, int color_mode); static void set_control_clock(unsigned char *params); @@ -195,6 +193,7 @@ int init_module(void) void cleanup_module(void) { + /* FIXME: clean up and release regions */ } #endif @@ -638,17 +637,15 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro int __init control_init(void) { -#ifndef CONFIG_FB_OF struct device_node *dp; dp = find_devices("control"); if (dp != 0) control_of_init(dp); -#endif /* CONFIG_FB_OF */ return 0; } -void __init control_of_init(struct device_node *dp) +static void __init control_of_init(struct device_node *dp) { struct fb_info_control *p; unsigned long addr, size; @@ -667,6 +664,11 @@ void __init control_of_init(struct device_node *dp) for (i = 0; i < dp->n_addrs; ++i) { addr = dp->addrs[i].address; size = dp->addrs[i].size; + /* Let's assume we can request either all or nothing */ + if (!request_mem_region(addr, size, "controlfb")) { + kfree(p); + return; + } if (size >= 0x800000) { /* use the big-endian aperture (??) */ addr += 0x800000; @@ -679,6 +681,7 @@ void __init control_of_init(struct device_node *dp) } } p->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */ + request_mem_region(p->cmap_regs_phys, 0x1000, "controlfb cmap"); p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000); /* Work out which banks of VRAM we have installed. */ diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 9cb20fc0d..6ca8c3dcf 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -67,7 +67,6 @@ extern int hitfb_setup(char*); extern int vfb_init(void); extern int vfb_setup(char*); extern int offb_init(void); -extern int offb_setup(char*); extern int atyfb_init(void); extern int atyfb_setup(char*); extern int aty128fb_init(void); @@ -83,7 +82,6 @@ extern int virgefb_init(void); extern int virgefb_setup(char*); extern int resolver_video_setup(char*); extern int s3triofb_init(void); -extern int s3triofb_setup(char*); extern int vesafb_init(void); extern int vesafb_setup(char*); extern int vga16fb_init(void); @@ -96,10 +94,13 @@ extern int hpfb_init(void); extern int hpfb_setup(char*); extern int sbusfb_init(void); extern int sbusfb_setup(char*); -extern int valkyriefb_init(void); -extern int valkyriefb_setup(char*); extern int control_init(void); extern int control_setup(char*); +extern int platinum_init(void); +extern int platinum_setup(char*); +extern int valkyriefb_init(void); +extern int valkyriefb_setup(char*); +extern int chips_init(void); extern int g364fb_init(void); extern int sa1100fb_init(void); extern int sa1100fb_setup(char*); @@ -122,6 +123,7 @@ static struct { int (*init)(void); int (*setup)(char*); } fb_drivers[] __initdata = { + #ifdef CONFIG_FB_SBUS /* * Sbusfb must be initialized _before_ other frame buffer devices that @@ -129,27 +131,17 @@ static struct { */ { "sbus", sbusfb_init, sbusfb_setup }, #endif -#ifdef CONFIG_FB_3DFX - { "tdfx", tdfxfb_init, tdfxfb_setup }, -#endif -#ifdef CONFIG_FB_SGIVW - { "sgivw", sgivwfb_init, sgivwfb_setup }, -#endif + + /* + * Chipset specific drivers that use resource management + */ + #ifdef CONFIG_FB_RETINAZ3 { "retz3", retz3fb_init, retz3fb_setup }, #endif -#ifdef CONFIG_FB_ACORN - { "acorn", acornfb_init, acornfb_setup }, -#endif #ifdef CONFIG_FB_AMIGA { "amifb", amifb_init, amifb_setup }, #endif -#ifdef CONFIG_FB_ATARI - { "atafb", atafb_init, atafb_setup }, -#endif -#ifdef CONFIG_FB_MAC - { "macfb", macfb_init, macfb_setup }, -#endif #ifdef CONFIG_FB_CYBER { "cyber", cyberfb_init, cyberfb_setup }, #endif @@ -171,79 +163,120 @@ static struct { #ifdef CONFIG_FB_ATY128 { "aty128fb", aty128fb_init, aty128fb_setup }, #endif +#ifdef CONFIG_FB_VIRGE + { "virge", virgefb_init, virgefb_setup }, +#endif +#ifdef CONFIG_FB_RIVA + { "riva", rivafb_init, rivafb_setup }, +#endif +#ifdef CONFIG_FB_CONTROL + { "controlfb", control_init, control_setup }, +#endif +#ifdef CONFIG_FB_PLATINUM + { "platinumfb", platinum_init, platinum_setup }, +#endif +#ifdef CONFIG_FB_VALKYRIE + { "valkyriefb", valkyriefb_init, valkyriefb_setup }, +#endif +#ifdef CONFIG_FB_CT65550 + { "chipsfb", chips_init, NULL }, +#endif +#ifdef CONFIG_FB_IMSTT + { "imsttfb", imsttfb_init, imsttfb_setup }, +#endif +#ifdef CONFIG_FB_S3TRIO + { "s3trio", s3triofb_init, NULL }, +#endif +#ifdef CONFIG_FB_FM2 + { "fm2fb", fm2fb_init, fm2fb_setup }, +#endif +#ifdef CONFIG_FB_SIS + { "sisfb", sisfb_init, sisfb_setup }, +#endif + + /* + * Generic drivers that are used as fallbacks + * + * These depend on resource management and must be initialized + * _after_ all other frame buffer devices that use resource + * management! + */ + #ifdef CONFIG_FB_OF + { "offb", offb_init, NULL }, +#endif +#ifdef CONFIG_FB_VESA + { "vesa", vesafb_init, vesafb_setup }, +#endif + /* - * Offb must be initialized _after_ all other frame buffer devices - * that use PCI probing and PCI resources! [ Geert ] + * Chipset specific drivers that don't use resource management (yet) */ - { "offb", offb_init, offb_setup }, + +#ifdef CONFIG_FB_3DFX + { "tdfx", tdfxfb_init, tdfxfb_setup }, +#endif +#ifdef CONFIG_FB_SGIVW + { "sgivw", sgivwfb_init, sgivwfb_setup }, #endif +#ifdef CONFIG_FB_ACORN + { "acorn", acornfb_init, acornfb_setup }, +#endif +#ifdef CONFIG_FB_ATARI + { "atafb", atafb_init, atafb_setup }, +#endif +#ifdef CONFIG_FB_MAC + { "macfb", macfb_init, macfb_setup }, +#endif +#ifdef CONFIG_FB_HGA + { "hga", hgafb_init, hgafb_setup }, +#endif #ifdef CONFIG_FB_IGA { "igafb", igafb_init, igafb_setup }, #endif -#ifdef CONFIG_FB_IMSTT - { "imsttfb", imsttfb_init, imsttfb_setup }, -#endif #ifdef CONFIG_APOLLO { "apollo", dnfb_init, NULL }, #endif #ifdef CONFIG_FB_Q40 { "q40fb", q40fb_init, NULL }, #endif -#ifdef CONFIG_FB_S3TRIO - { "s3trio", s3triofb_init, s3triofb_setup }, -#endif #ifdef CONFIG_FB_TGA { "tga", tgafb_init, tgafb_setup }, #endif -#ifdef CONFIG_FB_VIRGE - { "virge", virgefb_init, virgefb_setup }, -#endif -#ifdef CONFIG_FB_RIVA - { "riva", rivafb_init, rivafb_setup }, -#endif -#ifdef CONFIG_FB_VESA - { "vesa", vesafb_init, vesafb_setup }, -#endif -#ifdef CONFIG_FB_VGA16 - { "vga16", vga16fb_init, vga16fb_setup }, -#endif -#ifdef CONFIG_FB_HGA - { "hga", hgafb_init, hgafb_setup }, -#endif #ifdef CONFIG_FB_HP300 { "hpfb", hpfb_init, hpfb_setup }, #endif -#ifdef CONFIG_FB_CONTROL - { "controlfb", control_init, control_setup }, -#endif -#ifdef CONFIG_FB_VALKYRIE - { "valkyriefb", valkyriefb_init, valkyriefb_setup }, -#endif #ifdef CONFIG_FB_G364 { "g364", g364fb_init, NULL }, #endif #ifdef CONFIG_FB_SA1100 { "sa1100", sa1100fb_init, sa1100fb_setup }, #endif -#ifdef CONFIG_FB_FM2 - { "fm2fb", fm2fb_init, fm2fb_setup }, -#endif #ifdef CONFIG_FB_SUN3 { "sun3", sun3fb_init, sun3fb_setup }, #endif #ifdef CONFIG_FB_HIT { "hitfb", hitfb_init, hitfb_setup }, #endif + + /* + * Generic drivers that don't use resource management (yet) + */ + +#ifdef CONFIG_FB_VGA16 + { "vga16", vga16fb_init, vga16fb_setup }, +#endif + #ifdef CONFIG_GSP_RESOLVER /* Not a real frame buffer device... */ { "resolver", NULL, resolver_video_setup }, #endif -#ifdef CONFIG_FB_SIS - { "sisfb", sisfb_init, sisfb_setup }, -#endif + #ifdef CONFIG_FB_VIRTUAL - /* Must be last to avoid that vfb becomes your primary display */ + /* + * Vfb must be last to avoid that it becomes your primary display if + * other display devices are present + */ { "vfb", vfb_init, vfb_setup }, #endif }; @@ -264,6 +297,10 @@ static int first_fb_vc = 0; static int last_fb_vc = MAX_NR_CONSOLES-1; static int fbcon_is_default = 1; +#ifdef CONFIG_FB_OF +static int ofonly __initdata = 0; +#endif + static int fbmem_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *private) { @@ -728,6 +765,13 @@ fbmem_init(void) if (devfs_register_chrdev(FB_MAJOR,"fb",&fb_fops)) printk("unable to get major %d for fb devs\n", FB_MAJOR); +#ifdef CONFIG_FB_OF + if (ofonly) { + offb_init(); + return; + } +#endif + /* * Probe for all builtin frame buffer devices */ @@ -787,6 +831,13 @@ int __init video_setup(char *options) fbcon_is_default = 0; } +#ifdef CONFIG_FB_OF + if (!strcmp(options, "ofonly")) { + ofonly = 1; + return 0; + } +#endif + if (num_pref_init_funcs == FB_MAX) return 0; diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index d3b3e5a38..1749f3246 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -355,6 +355,7 @@ struct fb_info_imstt { struct imstt_regvals init; struct imstt_cursor cursor; unsigned long frame_buffer_phys; + unsigned long board_size; __u8 *frame_buffer; unsigned long dc_regs_phys; __u32 *dc_regs; @@ -1879,62 +1880,13 @@ init_imstt(struct fb_info_imstt *p) #endif /* CONFIG_FB_COMPAT_XPMAC */ } -#if defined(CONFIG_FB_OF) && !defined(MODULE) -void __init -imsttfb_of_init(struct device_node *dp) -{ - struct fb_info_imstt *p; - int i; - __u32 addr = 0; - __u8 bus, devfn; - __u16 cmd; - - for (i = 0; i < dp->n_addrs; i++) { - if (dp->addrs[i].size >= 0x02000000) - addr = dp->addrs[i].address; - } - if (!addr) - return; - - if (!pci_device_loc(dp, &bus, &devfn)) { - if (!pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd) && !(cmd & PCI_COMMAND_MEMORY)) { - cmd |= PCI_COMMAND_MEMORY; - pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); - } - } - - p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC); - if (!p) - return; - memset(p, 0, sizeof(struct fb_info_imstt)); - - if (dp->name[11] == '8' || (dp->name[6] == '3' && dp->name[7] == 'd')) - p->ramdac = TVP; - else - p->ramdac = IBM; - - p->frame_buffer_phys = addr; - p->frame_buffer = (__u8 *)ioremap(addr, p->ramdac == IBM ? 0x400000 : 0x800000); - p->dc_regs_phys = addr + 0x800000; - p->dc_regs = (__u32 *)ioremap(addr + 0x800000, 0x1000); - p->cmap_regs_phys = addr + 0x840000; - p->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000); - - init_imstt(p); -} -#endif - int __init imsttfb_init(void) { int i; -#if defined(CONFIG_FB_OF) && !defined(MODULE) - /* We don't want to be called like this. */ - /* We rely on Open Firmware (offb) instead. */ -#elif defined(CONFIG_PCI) struct pci_dev *pdev = NULL; struct fb_info_imstt *p; - __u32 addr; + unsigned long addr, size; __u16 cmd; while ((pdev = pci_find_device(PCI_VENDOR_ID_IMS, PCI_ANY_ID, pdev))) { @@ -1944,6 +1896,7 @@ imsttfb_init(void) continue; addr = pci_resource_start (pdev, 0); + size = pci_resource_len (pdev, 0); if (!addr) continue; @@ -1952,6 +1905,10 @@ imsttfb_init(void) continue; memset(p, 0, sizeof(struct fb_info_imstt)); + if (!request_mem_region(addr, size, "imsttfb")) { + kfree(p); + continue; + } printk("imsttfb: device=%04x\n", pdev->device); switch (pdev->device) { @@ -1965,6 +1922,7 @@ imsttfb_init(void) } p->frame_buffer_phys = addr; + p->board_size = size; p->frame_buffer = (__u8 *)ioremap(addr, p->ramdac == IBM ? 0x400000 : 0x800000); p->dc_regs_phys = addr + 0x800000; p->dc_regs = (__u32 *)ioremap(addr + 0x800000, 0x1000); @@ -1973,7 +1931,6 @@ imsttfb_init(void) init_imstt(p); } -#endif /* CONFIG_PCI */ for (i = 0; i < FB_MAX; i++) { if (fb_info_imstt_p[i]) return 0; @@ -2059,6 +2016,7 @@ cleanup_module (void) iounmap(p->dc_regs); iounmap(p->frame_buffer); kfree(p); + release_mem_region(p->frame_buffer_phys, p->board_size); } } diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index cbdc9848b..9ddb30140 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -95,7 +95,7 @@ #include <linux/matroxfb.h> #include <asm/uaccess.h> -#if defined(CONFIG_FB_OF) +#ifdef CONFIG_PPC unsigned char nvram_read_byte(int); static int default_vmode = VMODE_NVRAM; static int default_cmode = CMODE_NVRAM; @@ -2343,7 +2343,7 @@ int __init matroxfb_setup(char *options) { mem = simple_strtoul(this_opt+4, NULL, 0); else if (!strncmp(this_opt, "mode:", 5)) strncpy(videomode, this_opt+5, sizeof(videomode)-1); -#ifdef CONFIG_FB_OF +#ifdef CONFIG_PPC else if (!strncmp(this_opt, "vmode:", 6)) { unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0); if (vmode > 0 && vmode <= VMODE_MAX) @@ -2519,7 +2519,7 @@ MODULE_PARM(cross4MB, "i"); MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)"); MODULE_PARM(dfp, "i"); MODULE_PARM_DESC(dfp, "Specifies whether to use digital flat panel interface of G200/G400 (0 or 1) (default=0)"); -#ifdef CONFIG_FB_OF +#ifdef CONFIG_PPC MODULE_PARM(vmode, "i"); MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)"); MODULE_PARM(cmode, "i"); diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 69bb8cc72..1399d6882 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -68,14 +68,12 @@ struct fb_info_offb { #define mach_eieio() do {} while (0) #endif -static int ofonly = 0; /* * Interface used by the world */ int offb_init(void); -int offb_setup(char*); static int offb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info); @@ -90,7 +88,6 @@ static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con, extern boot_infos_t *boot_infos; -static int offb_init_driver(struct device_node *); static void offb_init_nodriver(struct device_node *); static void offb_init_fb(const char *name, const char *full_name, int width, int height, int depth, int pitch, unsigned long address, @@ -238,29 +235,6 @@ static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con, } -#ifdef CONFIG_FB_S3TRIO -extern void s3triofb_init_of(struct device_node *dp); -#endif /* CONFIG_FB_S3TRIO */ -#ifdef CONFIG_FB_IMSTT -extern void imsttfb_of_init(struct device_node *dp); -#endif -#ifdef CONFIG_FB_CT65550 -extern void chips_of_init(struct device_node *dp); -#endif /* CONFIG_FB_CT65550 */ -#ifdef CONFIG_FB_CONTROL -extern void control_of_init(struct device_node *dp); -#endif /* CONFIG_FB_CONTROL */ -#ifdef CONFIG_FB_VALKYRIE -extern void valkyrie_of_init(struct device_node *dp); -#endif /* CONFIG_FB_VALKYRIE */ -#ifdef CONFIG_FB_PLATINUM -extern void platinum_of_init(struct device_node *dp); -#endif /* CONFIG_FB_PLATINUM */ -#ifdef CONFIG_FB_CLGEN -extern void clgen_of_init(struct device_node *dp); -#endif /* CONFIG_FB_CLGEN */ - - /* * Initialisation */ @@ -324,89 +298,22 @@ int __init offb_init(void) } /* initialize it */ - if (ofonly || macos_display == NULL - || !offb_init_driver(macos_display)) { - offb_init_fb(macos_display? macos_display->name: "MacOS display", - macos_display? macos_display->full_name: "MacOS display", - boot_infos->dispDeviceRect[2], - boot_infos->dispDeviceRect[3], - boot_infos->dispDeviceDepth, - boot_infos->dispDeviceRowBytes, addr, NULL); - } + offb_init_fb(macos_display? macos_display->name: "MacOS display", + macos_display? macos_display->full_name: "MacOS display", + boot_infos->dispDeviceRect[2], + boot_infos->dispDeviceRect[3], + boot_infos->dispDeviceDepth, + boot_infos->dispDeviceRowBytes, addr, NULL); } for (dpy = 0; dpy < prom_num_displays; dpy++) { if ((dp = find_path_device(prom_display_paths[dpy]))) - if (ofonly || !offb_init_driver(dp)) - offb_init_nodriver(dp); - } - - if (!ofonly) { - for (dp = find_type_devices("display"); dp != NULL; dp = dp->next) { - for (dpy = 0; dpy < prom_num_displays; dpy++) - if (strcmp(dp->full_name, prom_display_paths[dpy]) == 0) - break; - if (dpy >= prom_num_displays && dp != macos_display) - offb_init_driver(dp); - } + offb_init_nodriver(dp); } return 0; } - /* - * This function is intended to go away as soon as all OF-aware frame - * buffer device drivers have been converted to use PCI probing and PCI - * resources. [ Geert ] - */ - -static int __init offb_init_driver(struct device_node *dp) -{ -#ifdef CONFIG_FB_S3TRIO - if (!strncmp(dp->name, "S3Trio", 6)) { - s3triofb_init_of(dp); - return 1; - } -#endif /* CONFIG_FB_S3TRIO */ -#ifdef CONFIG_FB_IMSTT - if (!strncmp(dp->name, "IMS,tt", 6)) { - imsttfb_of_init(dp); - return 1; - } -#endif -#ifdef CONFIG_FB_CT65550 - if (!strcmp(dp->name, "chips65550")) { - chips_of_init(dp); - return 1; - } -#endif /* CONFIG_FB_CT65550 */ -#ifdef CONFIG_FB_CONTROL - if(!strcmp(dp->name, "control")) { - control_of_init(dp); - return 1; - } -#endif /* CONFIG_FB_CONTROL */ -#ifdef CONFIG_FB_VALKYRIE - if(!strcmp(dp->name, "valkyrie")) { - valkyrie_of_init(dp); - return 1; - } -#endif /* CONFIG_FB_VALKYRIE */ -#ifdef CONFIG_FB_PLATINUM - if (!strncmp(dp->name, "platinum",8)) { - platinum_of_init(dp); - return 1; - } -#endif /* CONFIG_FB_PLATINUM */ -#ifdef CONFIG_FB_CLGEN - if (!strncmp(dp->name, "MacPicasso",10) || !strncmp(dp->name, "54m30",5)) { - clgen_of_init(dp); - return 1; - } -#endif /* CONFIG_FB_CLGEN */ - return 0; -} - static void __init offb_init_nodriver(struct device_node *dp) { int *pp, i; @@ -685,21 +592,6 @@ static void offb_init_fb(const char *name, const char *full_name, } - /* - * Setup: parse used options - */ - -int offb_setup(char *options) -{ - if (!options || !*options) - return 0; - - if (!strcmp(options, "ofonly")) - ofonly = 1; - return 0; -} - - static int offbcon_switch(int con, struct fb_info *info) { /* Do we have to save the colormap? */ diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 3bbd7fe48..558b6f44e 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -126,6 +126,7 @@ static void platinum_blank(int blank, struct fb_info *fb); * internal functions */ +static void platinum_of_init(struct device_node *dp); static inline int platinum_vram_reqd(int video_mode, int color_mode); static int read_platinum_sense(struct fb_info_platinum *info); static void set_platinum_clock(struct fb_info_platinum *info); @@ -153,12 +154,8 @@ static void do_install_cmap(int con, struct fb_info *info); */ int platinum_init(void); -#ifdef CONFIG_FB_OF -void platinum_of_init(struct device_node *dp); -#endif int platinum_setup(char*); - static struct fb_ops platinumfb_ops = { owner: THIS_MODULE, fb_get_fix: platinum_get_fix, @@ -625,13 +622,11 @@ static int __init init_platinum(struct fb_info_platinum *info) int __init platinum_init(void) { -#ifndef CONFIG_FB_OF struct device_node *dp; dp = find_devices("platinum"); if (dp != 0) platinum_of_init(dp); -#endif /* CONFIG_FB_OF */ return 0; } @@ -643,7 +638,7 @@ int __init platinum_init(void) #define invalidate_cache(addr) #endif -void __init platinum_of_init(struct device_node *dp) +static void __init platinum_of_init(struct device_node *dp) { struct fb_info_platinum *info; unsigned long addr, size; @@ -664,6 +659,11 @@ void __init platinum_of_init(struct device_node *dp) for (i = 0; i < dp->n_addrs; ++i) { addr = dp->addrs[i].address; size = dp->addrs[i].size; + /* Let's assume we can request either all or nothing */ + if (!request_mem_region(addr, size, "platinumfb")) { + kfree(info); + return; + } if (size >= 0x400000) { /* frame buffer - map only 4MB */ info->frame_buffer_phys = addr; @@ -677,6 +677,7 @@ void __init platinum_of_init(struct device_node *dp) } info->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */ + request_mem_region(info->cmap_regs_phys, 0x1000, "platinumfb cmap"); info->cmap_regs = ioremap(info->cmap_regs_phys, 0x1000); /* Grok total video ram */ diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 6739cecf9..9e7132f86 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -1,7 +1,8 @@ /* * valkyriefb.c -- frame buffer device for the PowerMac 'valkyrie' display * - * Created 8 August 1998 by Martin Costabel and Kevin Schoedel + * Created 8 August 1998 by + * Martin Costabel <costabel@wanadoo.fr> and Kevin Schoedel * * Vmode-switching changes and vmode 15/17 modifications created 29 August * 1998 by Barry K. Nathan <barryn@pobox.com>. @@ -114,9 +115,9 @@ struct fb_info_valkyrie { * Exported functions */ int valkyriefb_init(void); -void valkyrie_of_init(struct device_node *dp); int valkyriefb_setup(char*); +static void valkyrie_of_init(struct device_node *dp); static int valkyrie_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info); static int valkyrie_get_var(struct fb_var_screeninfo *var, int con, @@ -547,20 +548,18 @@ static void valkyrie_set_par(const struct fb_par_valkyrie *par, int __init valkyriefb_init(void) { -#ifndef CONFIG_FB_OF struct device_node *dp; dp = find_devices("valkyrie"); if (dp != 0) valkyrie_of_init(dp); -#endif /* CONFIG_FB_OF */ return 0; } -void __init valkyrie_of_init(struct device_node *dp) +static void __init valkyrie_of_init(struct device_node *dp) { struct fb_info_valkyrie *p; - unsigned long addr, size; + unsigned long addr; if(dp->n_addrs != 1) { printk(KERN_ERR "expecting 1 address for valkyrie (got %d)", dp->n_addrs); @@ -574,13 +573,16 @@ void __init valkyrie_of_init(struct device_node *dp) /* Map in frame buffer and registers */ addr = dp->addrs[0].address; - size = 4096; + if (!request_mem_region(addr, dp->addrs[0].size, "valkyriefb")) { + kfree(p); + return; + } p->frame_buffer_phys = addr; p->frame_buffer = __ioremap(addr, 0x100000, _PAGE_WRITETHRU); p->cmap_regs_phys = addr + 0x304000; - p->cmap_regs = ioremap(p->cmap_regs_phys, size); + p->cmap_regs = ioremap(p->cmap_regs_phys,4096); p->valkyrie_regs_phys = addr + 0x30a000; - p->valkyrie_regs = ioremap(p->valkyrie_regs_phys, size); + p->valkyrie_regs = ioremap(p->valkyrie_regs_phys, 4096); /* * kps: As far as I know, all Valkyries have fixed usable VRAM. @@ -650,31 +652,9 @@ static int valkyrie_var_to_par(struct fb_var_screeninfo *var, struct valkyrie_regvals *init; struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) fb_info; - /* these are old variables that are no longer needed with my new code - [bkn] - - int xres = var->xres; - int yres = var->yres; - */ - - /* - * Get the video params out of 'var'. If a value doesn't fit, round it up, - * if it's too big, return -EINVAL. - * - * Suggestion: Round up in the following order: bits_per_pixel, xres, - * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, - * bitfields, horizontal timing, vertical timing. - */ if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0) { - printk(KERN_ERR "valkyrie_var_to_par: mac_var_to_vmode unsuccessful.\n"); - printk(KERN_ERR "valkyrie_var_to_par: var->xres = %d\n", var->xres); - printk(KERN_ERR "valkyrie_var_to_par: var->yres = %d\n", var->yres); - printk(KERN_ERR "valkyrie_var_to_par: var->xres_virtual = %d\n", var->xres_virtual); - printk(KERN_ERR "valkyrie_var_to_par: var->yres_virtual = %d\n", var->yres_virtual); - printk(KERN_ERR "valkyrie_var_to_par: var->bits_per_pixel = %d\n", var->bits_per_pixel); - printk(KERN_ERR "valkyrie_var_to_par: var->pixclock = %d\n", var->pixclock); - printk(KERN_ERR "valkyrie_var_to_par: var->vmode = %d\n", var->vmode); + printk(KERN_ERR "valkyrie_var_to_par: %dx%dx%d unsuccessful.\n",var->xres,var->yres,var->bits_per_pixel); return -EINVAL; } diff --git a/drivers/video/valkyriefb.h b/drivers/video/valkyriefb.h index c8984b38b..8ff0eaabf 100644 --- a/drivers/video/valkyriefb.h +++ b/drivers/video/valkyriefb.h @@ -1,10 +1,13 @@ /* * valkyriefb.h: Constants of all sorts for valkyriefb * - * Created 8 August 1998 by Martin Costabel and Kevin Schoedel + * Created 8 August 1998 by + * Martin Costabel <costabel@wanadoo.fr> and Kevin Schoedel * * Vmode-switching changes and vmode 15/17 modifications created 29 August * 1998 by Barry K. Nathan <barryn@pobox.com>. + * + * vmode 10 changed by Steven Borley <sjb@salix.demon.co.uk>, 14 mai 2000 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -141,7 +144,8 @@ static struct valkyrie_regvals valkyrie_reg_init_11 = { /* Register values for 800x600, 60Hz mode (10) */ static struct valkyrie_regvals valkyrie_reg_init_10 = { 12, - { 20, 53, 2 }, /* pixel clock = 41.41MHz for V=59.78Hz */ + { 25, 32, 3 }, /* pixel clock = 40.0015MHz, + used to be 20,53,2, pixel clock 41.41MHz for V=59.78Hz */ { 800, 1600 }, 800, 600 }; diff --git a/fs/inode.c b/fs/inode.c index 62acffd58..455c4af6e 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -489,10 +489,10 @@ static struct inode * find_inode(struct super_block * sb, unsigned long ino, str if (tmp == head) break; inode = list_entry(tmp, struct inode, i_hash); - if (inode->i_sb != sb) - continue; if (inode->i_ino != ino) continue; + if (inode->i_sb != sb) + continue; if (find_actor && !find_actor(inode, ino, opaque)) continue; break; diff --git a/include/asm-alpha/hardirq.h b/include/asm-alpha/hardirq.h index 3961ac4a4..66ab89ce4 100644 --- a/include/asm-alpha/hardirq.h +++ b/include/asm-alpha/hardirq.h @@ -1,20 +1,19 @@ #ifndef _ALPHA_HARDIRQ_H #define _ALPHA_HARDIRQ_H -/* Initially just a straight copy of the i386 code. */ - #include <linux/config.h> #include <linux/threads.h> -#ifndef CONFIG_SMP -extern int __local_irq_count; -#define local_irq_count(cpu) ((void)(cpu), __local_irq_count) -extern unsigned long __irq_attempt[]; -#define irq_attempt(cpu, irq) ((void)(cpu), __irq_attempt[irq]) -#else -#define local_irq_count(cpu) (cpu_data[cpu].irq_count) -#define irq_attempt(cpu, irq) (cpu_data[cpu].irq_attempt[irq]) -#endif +/* entry.S is sensitive to the offsets of these fields */ +typedef struct { + unsigned int __softirq_active; + unsigned int __softirq_mask; + unsigned int __local_irq_count; + unsigned int __local_bh_count; + unsigned int __syscall_count; +} ____cacheline_aligned irq_cpustat_t; + +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ /* * Are we in an interrupt context? Either doing bottom half @@ -31,6 +30,9 @@ extern unsigned long __irq_attempt[]; #ifndef CONFIG_SMP +extern unsigned long __irq_attempt[]; +#define irq_attempt(cpu, irq) ((void)(cpu), __irq_attempt[irq]) + #define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) #define hardirq_endlock(cpu) ((void) 0) @@ -41,6 +43,8 @@ extern unsigned long __irq_attempt[]; #else +#define irq_attempt(cpu, irq) (cpu_data[cpu].irq_attempt[irq]) + #include <asm/atomic.h> #include <linux/spinlock.h> #include <asm/smp.h> diff --git a/include/asm-alpha/smp.h b/include/asm-alpha/smp.h index 3143b0872..44ec5e8ea 100644 --- a/include/asm-alpha/smp.h +++ b/include/asm-alpha/smp.h @@ -33,7 +33,6 @@ struct cpuinfo_alpha { unsigned long irq_attempt[NR_IRQS]; unsigned long prof_multiplier; unsigned long prof_counter; - int irq_count, bh_count; unsigned char mcheck_expected; unsigned char mcheck_taken; unsigned char mcheck_extra; diff --git a/include/asm-alpha/softirq.h b/include/asm-alpha/softirq.h index ef77f861e..dd18dc490 100644 --- a/include/asm-alpha/softirq.h +++ b/include/asm-alpha/softirq.h @@ -6,13 +6,6 @@ #include <asm/atomic.h> #include <asm/hardirq.h> -#ifndef CONFIG_SMP -extern int __local_bh_count; -#define local_bh_count(cpu) ((void)(cpu), __local_bh_count) -#else -#define local_bh_count(cpu) (cpu_data[cpu].bh_count) -#endif - extern inline void cpu_bh_disable(int cpu) { local_bh_count(cpu)++; diff --git a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h index c12ed91e3..550310ffe 100644 --- a/include/asm-arm/hardirq.h +++ b/include/asm-arm/hardirq.h @@ -4,11 +4,16 @@ #include <linux/config.h> #include <linux/threads.h> -extern unsigned int local_irq_count[NR_CPUS]; -extern unsigned int local_bh_count[NR_CPUS]; - -#define local_irq_count(cpu) (local_irq_count[(cpu)]) -#define local_bh_count(cpu) (local_bh_count[(cpu)]) +/* entry.S is sensitive to the offsets of these fields */ +typedef struct { + unsigned int __softirq_active; + unsigned int __softirq_mask; + unsigned int __local_irq_count; + unsigned int __local_bh_count; + unsigned int __syscall_count; +} ____cacheline_aligned irq_cpustat_t; + +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ /* * Are we in an interrupt context? Either doing bottom half diff --git a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h index aef182212..3860288ad 100644 --- a/include/asm-i386/hardirq.h +++ b/include/asm-i386/hardirq.h @@ -5,21 +5,17 @@ #include <linux/threads.h> #include <linux/irq.h> +/* entry.S is sensitive to the offsets of these fields */ typedef struct { + unsigned int __softirq_active; + unsigned int __softirq_mask; unsigned int __local_irq_count; unsigned int __local_bh_count; - unsigned int __nmi_counter; - unsigned int __pad[5]; + unsigned int __syscall_count; + unsigned int __nmi_count; /* arch dependent */ } ____cacheline_aligned irq_cpustat_t; -extern irq_cpustat_t irq_stat [NR_CPUS]; - -/* - * Simple wrappers reducing source bloat - */ -#define local_irq_count(cpu) (irq_stat[(cpu)].__local_irq_count) -#define local_bh_count(cpu) (irq_stat[(cpu)].__local_bh_count) -#define nmi_counter(cpu) (irq_stat[(cpu)].__nmi_counter) +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ /* * Are we in an interrupt context? Either doing bottom half diff --git a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h index 7b24f385c..38a12be6e 100644 --- a/include/asm-ia64/hardirq.h +++ b/include/asm-ia64/hardirq.h @@ -11,23 +11,17 @@ #include <linux/threads.h> #include <linux/irq.h> +/* entry.S is sensitive to the offsets of these fields */ typedef struct { + unsigned int __softirq_active; + unsigned int __softirq_mask; unsigned int __local_irq_count; unsigned int __local_bh_count; - unsigned int __nmi_counter; -# if NR_CPUS > 1 - unsigned int __pad[13]; /* this assumes 64-byte cache-lines... */ -# endif + unsigned int __syscall_count; + unsigned int __nmi_count; /* arch dependent */ } ____cacheline_aligned irq_cpustat_t; -extern irq_cpustat_t irq_stat[NR_CPUS]; - -/* - * Simple wrappers reducing source bloat - */ -#define local_irq_count(cpu) (irq_stat[(cpu)].__local_irq_count) -#define local_bh_count(cpu) (irq_stat[(cpu)].__local_bh_count) -#define nmi_counter(cpu) (irq_stat[(cpu)].__nmi_counter) +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ /* * Are we in an interrupt context? Either doing bottom half diff --git a/include/asm-m68k/hardirq.h b/include/asm-m68k/hardirq.h index aac7e8597..8a1e6a445 100644 --- a/include/asm-m68k/hardirq.h +++ b/include/asm-m68k/hardirq.h @@ -3,17 +3,26 @@ #include <linux/threads.h> -extern unsigned int local_irq_count[NR_CPUS]; +/* entry.S is sensitive to the offsets of these fields */ +typedef struct { + unsigned int __softirq_active; + unsigned int __softirq_mask; + unsigned int __local_irq_count; + unsigned int __local_bh_count; + unsigned int __syscall_count; +} ____cacheline_aligned irq_cpustat_t; -#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0) +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ -#define in_irq() (local_irq_count[smp_processor_id()] != 0) +#define in_interrupt() (local_irq_count(smp_processor_id()) + local_bh_count(smp_processor_id()) != 0) -#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) +#define in_irq() (local_irq_count(smp_processor_id()) != 0) + +#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) #define hardirq_endlock(cpu) do { } while (0) -#define irq_enter(cpu) (local_irq_count[cpu]++) -#define irq_exit(cpu) (local_irq_count[cpu]--) +#define irq_enter(cpu) (local_irq_count(cpu)++) +#define irq_exit(cpu) (local_irq_count(cpu)--) #define synchronize_irq() barrier() diff --git a/include/asm-m68k/softirq.h b/include/asm-m68k/softirq.h index a51563cd7..89a3e3971 100644 --- a/include/asm-m68k/softirq.h +++ b/include/asm-m68k/softirq.h @@ -7,16 +7,14 @@ #include <asm/atomic.h> -extern unsigned int local_bh_count[NR_CPUS]; - -#define local_bh_disable() (local_bh_count[smp_processor_id()]++) -#define local_bh_enable() (local_bh_count[smp_processor_id()]--) +#define local_bh_disable() (local_bh_count(smp_processor_id())++) +#define local_bh_enable() (local_bh_count(smp_processor_id())--) #define in_softirq() (local_bh_count != 0) /* These are for the irq's testing the lock */ -#define softirq_trylock(cpu) (local_bh_count[cpu] ? 0 : (local_bh_count[cpu]=1)) -#define softirq_endlock(cpu) (local_bh_count[cpu] = 0) +#define softirq_trylock(cpu) (local_bh_count(cpu) ? 0 : (local_bh_count(cpu)=1)) +#define softirq_endlock(cpu) (local_bh_count(cpu) = 0) #define synchronize_bh() barrier() #endif diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h index 64dab98d8..a33bb7c14 100644 --- a/include/asm-m68k/system.h +++ b/include/asm-m68k/system.h @@ -52,7 +52,7 @@ asmlinkage void resume(void); #else #include <asm/hardirq.h> #define __sti() ({ \ - if (!local_irq_count[smp_processor_id()]) \ + if (!local_irq_count(smp_processor_id())) \ asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory"); \ }) #endif diff --git a/include/asm-mips/hardirq.h b/include/asm-mips/hardirq.h index 4331f1367..eead2fb87 100644 --- a/include/asm-mips/hardirq.h +++ b/include/asm-mips/hardirq.h @@ -14,18 +14,16 @@ #include <linux/threads.h> #include <linux/irq.h> +/* entry.S is sensitive to the offsets of these fields */ typedef struct { + unsigned int __softirq_active; + unsigned int __softirq_mask; unsigned int __local_irq_count; unsigned int __local_bh_count; + unsigned int __syscall_count; } ____cacheline_aligned irq_cpustat_t; -extern irq_cpustat_t irq_stat [NR_CPUS]; - -/* - * Simple wrappers reducing source bloat - */ -#define local_irq_count(cpu) (irq_stat[(cpu)].__local_irq_count) -#define local_bh_count(cpu) (irq_stat[(cpu)].__local_bh_count) +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ /* * Are we in an interrupt context? Either doing bottom half diff --git a/include/asm-mips/mc146818rtc.h b/include/asm-mips/mc146818rtc.h index bae7fcd1a..f521b7239 100644 --- a/include/asm-mips/mc146818rtc.h +++ b/include/asm-mips/mc146818rtc.h @@ -10,6 +10,7 @@ #ifndef _ASM_MC146818RTC_H #define _ASM_MC146818RTC_H +#include <linux/config.h> #include <asm/io.h> #ifndef RTC_PORT diff --git a/include/asm-mips64/hardirq.h b/include/asm-mips64/hardirq.h index 192b61f7b..088fb8853 100644 --- a/include/asm-mips64/hardirq.h +++ b/include/asm-mips64/hardirq.h @@ -14,19 +14,16 @@ #include <linux/threads.h> #include <linux/irq.h> +/* entry.S is sensitive to the offsets of these fields */ typedef struct { - unsigned long __local_irq_count; - unsigned long __local_bh_count; - unsigned long __pad[14]; + unsigned int __softirq_active; + unsigned int __softirq_mask; + unsigned int __local_irq_count; + unsigned int __local_bh_count; + unsigned int __syscall_count; } ____cacheline_aligned irq_cpustat_t; -extern irq_cpustat_t irq_stat [NR_CPUS]; - -/* - * Simple wrappers reducing source bloat - */ -#define local_irq_count(cpu) (irq_stat[(cpu)].__local_irq_count) -#define local_bh_count(cpu) (irq_stat[(cpu)].__local_bh_count) +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ /* * Are we in an interrupt context? Either doing bottom half diff --git a/include/asm-mips64/processor.h b/include/asm-mips64/processor.h index 565d6cb88..3e8cab4b5 100644 --- a/include/asm-mips64/processor.h +++ b/include/asm-mips64/processor.h @@ -63,7 +63,6 @@ struct cpuinfo_mips { unsigned long *pte_quick; unsigned long pgtable_cache_sz; unsigned long last_asn; - unsigned int irq_count, bh_count; unsigned long asid_cache; #if defined(CONFIG_SGI_IP27) cpuid_t p_cpuid; /* PROM assigned cpuid */ diff --git a/include/asm-mips64/smp.h b/include/asm-mips64/smp.h index ed0420dd4..b8a8f8d75 100644 --- a/include/asm-mips64/smp.h +++ b/include/asm-mips64/smp.h @@ -20,7 +20,6 @@ struct cpuinfo_mips { /* XXX */ unsigned long smp_local_irq_count; unsigned long prof_multiplier; unsigned long prof_counter; - int irq_count, bh_count; } __attribute__((aligned(64))); extern struct cpuinfo_mips cpu_data[NR_CPUS]; diff --git a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h index cc7425e24..07398997a 100644 --- a/include/asm-ppc/hardirq.h +++ b/include/asm-ppc/hardirq.h @@ -4,19 +4,16 @@ #include <linux/config.h> #include <asm/smp.h> +/* entry.S is sensitive to the offsets of these fields */ typedef struct { + unsigned int __softirq_active; + unsigned int __softirq_mask; unsigned int __local_irq_count; unsigned int __local_bh_count; - unsigned int __pad[6]; + unsigned int __syscall_count; } ____cacheline_aligned irq_cpustat_t; -extern irq_cpustat_t irq_stat [NR_CPUS]; - -/* - * Simple wrappers reducing source bloat - */ -#define local_irq_count(cpu) (irq_stat[(cpu)].__local_irq_count) -#define local_bh_count(cpu) (irq_stat[(cpu)].__local_bh_count) +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ /* * Are we in an interrupt context? Either doing bottom half diff --git a/include/asm-ppc/softirq.h b/include/asm-ppc/softirq.h index f23ed416b..4eaed0be6 100644 --- a/include/asm-ppc/softirq.h +++ b/include/asm-ppc/softirq.h @@ -4,8 +4,6 @@ #include <asm/atomic.h> #include <asm/hardirq.h> -extern unsigned int local_bh_count[NR_CPUS]; - #define local_bh_disable() do { local_bh_count(smp_processor_id())++; barrier(); } while (0) #define local_bh_enable() do { barrier(); local_bh_count(smp_processor_id())--; } while (0) diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h index c21db1cd7..b32a0684a 100644 --- a/include/asm-s390/hardirq.h +++ b/include/asm-s390/hardirq.h @@ -16,21 +16,50 @@ #include <linux/threads.h> #include <asm/lowcore.h> #include <linux/sched.h> + +/* No irq_cpustat_t for s390, the data is held directly in S390_lowcore */ + +/* + * Simple wrappers reducing source bloat. S390 specific because each + * cpu stores its data in S390_lowcore (PSA) instead of using a cache + * aligned array element like most architectures. + */ + +#ifdef CONFIG_SMP + +#define softirq_active(cpu) (safe_get_cpu_lowcore(cpu).__softirq_active) +#define softirq_mask(cpu) (safe_get_cpu_lowcore(cpu).__softirq_mask) +#define local_irq_count(cpu) (safe_get_cpu_lowcore(cpu).__local_irq_count) +#define local_bh_count(cpu) (safe_get_cpu_lowcore(cpu).__local_bh_count) +#define syscall_count(cpu) (safe_get_cpu_lowcore(cpu).__syscall_count) + +#else /* CONFIG_SMP */ + +/* Optimize away the cpu calculation, it is always current PSA */ +#define softirq_active(cpu) ((void)(cpu), S390_lowcore.__softirq_active) +#define softirq_mask(cpu) ((void)(cpu), S390_lowcore.__softirq_mask) +#define local_irq_count(cpu) ((void)(cpu), S390_lowcore.__local_irq_count) +#define local_bh_count(cpu) ((void)(cpu), S390_lowcore.__local_bh_count) +#define syscall_count(cpu) ((void)(cpu), S390_lowcore.__syscall_count) + +#endif /* CONFIG_SMP */ + /* * Are we in an interrupt context? Either doing bottom half * or hardware interrupt processing? + * Special definitions for s390, always access current PSA. */ -#define in_interrupt() ((atomic_read(&S390_lowcore.local_irq_count) + atomic_read(&S390_lowcore.local_bh_count)) != 0) +#define in_interrupt() ((S390_lowcore.__local_irq_count + S390_lowcore.__local_bh_count) != 0) -#define in_irq() (atomic_read(&S390_lowcore.local_irq_count) != 0) +#define in_irq() (S390_lowcore.__local_irq_count != 0) #ifndef CONFIG_SMP -#define hardirq_trylock(cpu) (atomic_read(&S390_lowcore.local_irq_count) == 0) +#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) #define hardirq_endlock(cpu) do { } while (0) -#define hardirq_enter(cpu) (atomic_inc(&S390_lowcore.local_irq_count)) -#define hardirq_exit(cpu) (atomic_dec(&S390_lowcore.local_irq_count)) +#define hardirq_enter(cpu) (local_irq_count(cpu)++) +#define hardirq_exit(cpu) (local_irq_count(cpu)--) #define synchronize_irq() do { } while (0) @@ -54,14 +83,14 @@ static inline void release_irqlock(int cpu) static inline void hardirq_enter(int cpu) { - atomic_inc(&safe_get_cpu_lowcore(cpu).local_irq_count); + ++local_irq_count(cpu); atomic_inc(&global_irq_count); } static inline void hardirq_exit(int cpu) { atomic_dec(&global_irq_count); - atomic_dec(&safe_get_cpu_lowcore(cpu).local_irq_count); + --local_irq_count(cpu); } static inline int hardirq_trylock(int cpu) diff --git a/include/asm-s390/irq.h b/include/asm-s390/irq.h index 895c24649..5efcdd40b 100644 --- a/include/asm-s390/irq.h +++ b/include/asm-s390/irq.h @@ -734,8 +734,8 @@ static inline void irq_exit(int cpu, unsigned int irq) #else -#define irq_enter(cpu, irq) (++local_irq_count[cpu]) -#define irq_exit(cpu, irq) (--local_irq_count[cpu]) +#define irq_enter(cpu, irq) (++local_irq_count(cpu)) +#define irq_exit(cpu, irq) (--local_irq_count(cpu)) #endif diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h index 22ab31bd8..3430056da 100644 --- a/include/asm-s390/lowcore.h +++ b/include/asm-s390/lowcore.h @@ -41,9 +41,10 @@ #define __LC_SAVE_AREA 0xC00 #define __LC_KERNEL_STACK 0xC40 #define __LC_KERNEL_LEVEL 0xC44 -#define __LC_CPUID 0xC50 -#define __LC_CPUADDR 0xC58 -#define __LC_IPLDEV 0xC6C +#define __LC_IRQ_STAT 0xC48 +#define __LC_CPUID 0xC60 +#define __LC_CPUADDR 0xC68 +#define __LC_IPLDEV 0xC7C /* interrupt handler start with all io, external and mcck interrupt disabled */ @@ -145,19 +146,26 @@ struct _lowcore __u32 save_area[16]; /* 0xc00 */ __u32 kernel_stack; /* 0xc40 */ __u32 kernel_level; /* 0xc44 */ - atomic_t local_bh_count; /* 0xc48 */ - atomic_t local_irq_count; /* 0xc4c */ - struct cpuinfo_S390 cpu_data; /* 0xc50 */ - __u32 ipl_device; /* 0xc6c */ + /* entry.S sensitive area start */ + /* Next 6 words are the s390 equivalent of irq_stat */ + __u32 __softirq_active; /* 0xc48 */ + __u32 __softirq_mask; /* 0xc4c */ + __u32 __local_irq_count; /* 0xc50 */ + __u32 __local_bh_count; /* 0xc54 */ + __u32 __syscall_count; /* 0xc58 */ + __u8 pad10[0xc60-0xc5c]; /* 0xc5c */ + struct cpuinfo_S390 cpu_data; /* 0xc60 */ + __u32 ipl_device; /* 0xc7c */ + /* entry.S sensitive area end */ /* SMP info area: defined by DJB */ - __u64 jiffy_timer_cc; /* 0xc70 */ - atomic_t ext_call_fast; /* 0xc78 */ - atomic_t ext_call_queue; /* 0xc7c */ - atomic_t ext_call_count; /* 0xc80 */ + __u64 jiffy_timer_cc; /* 0xc80 */ + atomic_t ext_call_fast; /* 0xc88 */ + atomic_t ext_call_queue; /* 0xc8c */ + atomic_t ext_call_count; /* 0xc90 */ /* Align SMP info to the top 1k of prefix area */ - __u8 pad10[0x1000-0xc84]; /* 0xc84 */ + __u8 pad11[0x1000-0xc94]; /* 0xc94 */ } __attribute__((packed)); /* End structure*/ extern __inline__ void set_prefix(__u32 address) diff --git a/include/asm-s390/softirq.h b/include/asm-s390/softirq.h index b0ad1dc56..ce1254eba 100644 --- a/include/asm-s390/softirq.h +++ b/include/asm-s390/softirq.h @@ -17,13 +17,13 @@ #include <asm/hardirq.h> #include <asm/lowcore.h> -#define cpu_bh_disable(cpu) do { atomic_inc(&S390_lowcore.local_bh_count); barrier(); } while (0) -#define cpu_bh_enable(cpu) do { barrier(); atomic_dec(&S390_lowcore.local_bh_count); } while (0) +#define cpu_bh_disable(cpu) do { local_bh_count(cpu)++; barrier(); } while (0) +#define cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--; } while (0) #define local_bh_disable() cpu_bh_disable(smp_processor_id()) #define local_bh_enable() cpu_bh_enable(smp_processor_id()) -#define in_softirq() (atomic_read(&S390_lowcore.local_bh_count) != 0) +#define in_softirq() (local_bh_count(smp_processor_id()) != 0) #endif /* __ASM_SOFTIRQ_H */ diff --git a/include/asm-sh/hardirq.h b/include/asm-sh/hardirq.h index 592b31d95..cfb53de78 100644 --- a/include/asm-sh/hardirq.h +++ b/include/asm-sh/hardirq.h @@ -4,28 +4,33 @@ #include <linux/config.h> #include <linux/threads.h> -extern unsigned int __local_irq_count[NR_CPUS]; -extern unsigned int __local_bh_count[NR_CPUS]; +/* entry.S is sensitive to the offsets of these fields */ +typedef struct { + unsigned int __softirq_active; + unsigned int __softirq_mask; + unsigned int __local_irq_count; + unsigned int __local_bh_count; + unsigned int __syscall_count; +} ____cacheline_aligned irq_cpustat_t; -#define local_irq_count(cpu) (__local_irq_count[(cpu)]) -#define local_bh_count(cpu) (__local_bh_count[(cpu)]) +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ /* * Are we in an interrupt context? Either doing bottom half * or hardware interrupt processing? */ #define in_interrupt() ({ int __cpu = smp_processor_id(); \ - (__local_irq_count[__cpu] + __local_bh_count[__cpu] != 0); }) + (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); }) -#define in_irq() (__local_irq_count[smp_processor_id()] != 0) +#define in_irq() (local_irq_count(smp_processor_id()) != 0) #ifndef CONFIG_SMP -#define hardirq_trylock(cpu) (__local_irq_count[cpu] == 0) +#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) #define hardirq_endlock(cpu) do { } while (0) -#define irq_enter(cpu, irq) (__local_irq_count[cpu]++) -#define irq_exit(cpu, irq) (__local_irq_count[cpu]--) +#define irq_enter(cpu, irq) (local_irq_count(cpu)++) +#define irq_exit(cpu, irq) (local_irq_count(cpu)--) #define synchronize_irq() barrier() diff --git a/include/asm-sh/softirq.h b/include/asm-sh/softirq.h index 44f4e0423..5e539b0ae 100644 --- a/include/asm-sh/softirq.h +++ b/include/asm-sh/softirq.h @@ -4,12 +4,12 @@ #include <asm/atomic.h> #include <asm/hardirq.h> -#define cpu_bh_disable(cpu) do { __local_bh_count[(cpu)]++; barrier(); } while (0) -#define cpu_bh_enable(cpu) do { barrier(); __local_bh_count[(cpu)]--; } while (0) +#define cpu_bh_disable(cpu) do { local_bh_count(cpu)++; barrier(); } while (0) +#define cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--; } while (0) #define local_bh_disable() cpu_bh_disable(smp_processor_id()) #define local_bh_enable() cpu_bh_enable(smp_processor_id()) -#define in_softirq() (__local_bh_count[smp_processor_id()] != 0) +#define in_softirq() (local_bh_count(smp_processor_id()) != 0) #endif /* __ASM_SH_SOFTIRQ_H */ diff --git a/include/asm-sparc/hardirq.h b/include/asm-sparc/hardirq.h index 8b7b095ad..cfee071dc 100644 --- a/include/asm-sparc/hardirq.h +++ b/include/asm-sparc/hardirq.h @@ -10,26 +10,37 @@ #include <linux/config.h> #include <linux/threads.h> -#ifndef CONFIG_SMP -extern unsigned int __local_irq_count; -#define local_irq_count(cpu) __local_irq_count +/* entry.S is sensitive to the offsets of these fields */ +typedef struct { + unsigned int __softirq_active; + unsigned int __softirq_mask; + unsigned int __local_irq_count; + unsigned int __local_bh_count; + unsigned int __syscall_count; +} ____cacheline_aligned irq_cpustat_t; + +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ /* * Are we in an interrupt context? Either doing bottom half * or hardware interrupt processing? */ -#define in_interrupt() ((__local_irq_count + __local_bh_count) != 0) +#define in_interrupt() ({ int __cpu = smp_processor_id(); \ + (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); }) + +#define in_irq() ({ int __cpu = smp_processor_id(); \ + (local_irq_count(__cpu) != 0); }) -#define hardirq_trylock(cpu) ((void)(cpu), __local_irq_count == 0) +#ifndef CONFIG_SMP + +#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) #define hardirq_endlock(cpu) do { (void)(cpu); } while (0) -#define hardirq_enter(cpu) (__local_irq_count++) -#define hardirq_exit(cpu) (__local_irq_count--) +#define hardirq_enter(cpu) (++local_irq_count(cpu)) +#define hardirq_exit(cpu) (--local_irq_count(cpu)) #define synchronize_irq() barrier() -#define in_irq() (__local_irq_count != 0) - #else #include <asm/atomic.h> @@ -37,22 +48,10 @@ extern unsigned int __local_irq_count; #include <asm/system.h> #include <asm/smp.h> -extern unsigned int __local_irq_count[NR_CPUS]; -#define local_irq_count(cpu) __local_irq_count[cpu] extern unsigned char global_irq_holder; extern spinlock_t global_irq_lock; extern atomic_t global_irq_count; -/* - * Are we in an interrupt context? Either doing bottom half - * or hardware interrupt processing? - */ -#define in_interrupt() ({ int __cpu = smp_processor_id(); \ - (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); }) - -#define in_irq() ({ int __cpu = smp_processor_id(); \ - (local_irq_count(__cpu) != 0); }) - static inline void release_irqlock(int cpu) { /* if we didn't own the irq lock, just ignore.. */ diff --git a/include/asm-sparc/highmem.h b/include/asm-sparc/highmem.h new file mode 100644 index 000000000..ede2167e1 --- /dev/null +++ b/include/asm-sparc/highmem.h @@ -0,0 +1,149 @@ +/* + * highmem.h: virtual kernel memory mappings for high memory + * + * Used in CONFIG_HIGHMEM systems for memory pages which + * are not addressable by direct kernel virtual adresses. + * + * Copyright (C) 1999 Gerhard Wichert, Siemens AG + * Gerhard.Wichert@pdb.siemens.de + * + * + * Redesigned the x86 32-bit VM architecture to deal with + * up to 16 Terrabyte physical memory. With current x86 CPUs + * we now support up to 64 Gigabytes physical RAM. + * + * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> + */ + +#ifndef _ASM_HIGHMEM_H +#define _ASM_HIGHMEM_H + +#ifdef __KERNEL__ + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <asm/vaddrs.h> +#include <asm/kmap_types.h> +#include <asm/pgtable.h> + +/* undef for production */ +#define HIGHMEM_DEBUG 1 + +/* declarations for highmem.c */ +extern unsigned long highstart_pfn, highend_pfn; + +extern pte_t *kmap_pte; +extern pgprot_t kmap_prot; +extern pte_t *pkmap_page_table; + +extern void kmap_init(void) __init; + +/* + * Right now we initialize only a single pte table. It can be extended + * easily, subsequent pte tables have to be allocated in one physical + * chunk of RAM. + */ +#define LAST_PKMAP 1024 + +#define LAST_PKMAP_MASK (LAST_PKMAP-1) +#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) + +extern unsigned long kmap_high(struct page *page); +extern void kunmap_high(struct page *page); + +extern inline unsigned long kmap(struct page *page) +{ + if (in_interrupt()) + BUG(); + if (page < highmem_start_page) + return (unsigned long) page_address(page); + return kmap_high(page); +} + +extern inline void kunmap(struct page *page) +{ + if (in_interrupt()) + BUG(); + if (page < highmem_start_page) + return; + kunmap_high(page); +} + +/* + * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap + * gives a more generic (and caching) interface. But kmap_atomic can + * be used in IRQ contexts, so in some (very limited) cases we need + * it. + */ +extern inline unsigned long kmap_atomic(struct page *page, enum km_type type) +{ + unsigned long idx; + unsigned long vaddr; + + if (page < highmem_start_page) + return (unsigned long) page_address(page); + + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = FIX_KMAP_BEGIN + idx * PAGE_SIZE; + +/* XXX Fix - Anton */ +#if 0 + __flush_cache_one(vaddr); +#else + flush_cache_all(); +#endif + +#if HIGHMEM_DEBUG + if (!pte_none(*(kmap_pte+idx))) + BUG(); +#endif + set_pte(kmap_pte+idx, mk_pte(page, kmap_prot)); +/* XXX Fix - Anton */ +#if 0 + __flush_tlb_one(vaddr); +#else + flush_tlb_all(); +#endif + + return vaddr; +} + +extern inline void kunmap_atomic(unsigned long vaddr, enum km_type type) +{ +#if HIGHMEM_DEBUG + unsigned long idx = type + KM_TYPE_NR*smp_processor_id(); + +#if 0 + if (vaddr < FIXADDR_START) // FIXME + return; +#endif + + if (vaddr != FIX_KMAP_BEGIN + idx * PAGE_SIZE) + BUG(); + +/* XXX Fix - Anton */ +#if 0 + __flush_cache_one(vaddr); +#else + flush_cache_all(); +#endif + + /* + * force other mappings to Oops if they'll try to access + * this pte without first remap it + */ + pte_clear(kmap_pte+idx); +/* XXX Fix - Anton */ +#if 0 + __flush_tlb_one(vaddr); +#else + flush_tlb_all(); +#endif +#endif +} + +#endif /* __KERNEL__ */ + +#endif /* _ASM_HIGHMEM_H */ diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h index 5859d82e9..4b6dd0dae 100644 --- a/include/asm-sparc/irq.h +++ b/include/asm-sparc/irq.h @@ -23,16 +23,14 @@ BTFIXUPDEF_CALL(char *, __irq_itoa, unsigned int) /* IRQ handler dispatch entry and exit. */ #ifdef CONFIG_SMP -extern unsigned int __local_irq_count[NR_CPUS]; #define irq_enter(cpu, irq) \ do { hardirq_enter(cpu); \ spin_unlock_wait(&global_irq_lock); \ } while(0) #define irq_exit(cpu, irq) hardirq_exit(cpu) #else -extern unsigned int __local_irq_count; -#define irq_enter(cpu, irq) (__local_irq_count++) -#define irq_exit(cpu, irq) (__local_irq_count--) +#define irq_enter(cpu, irq) (++local_irq_count(cpu)) +#define irq_exit(cpu, irq) (--local_irq_count(cpu)) #endif /* Dave Redman (djhr@tadpole.co.uk) diff --git a/include/asm-sparc/kmap_types.h b/include/asm-sparc/kmap_types.h new file mode 100644 index 000000000..d92d81b20 --- /dev/null +++ b/include/asm-sparc/kmap_types.h @@ -0,0 +1,10 @@ +#ifndef _ASM_KMAP_TYPES_H +#define _ASM_KMAP_TYPES_H + +enum km_type { + KM_BOUNCE_READ, + KM_BOUNCE_WRITE, + KM_TYPE_NR +}; + +#endif diff --git a/include/asm-sparc/pgalloc.h b/include/asm-sparc/pgalloc.h index 20e9d805e..180709c85 100644 --- a/include/asm-sparc/pgalloc.h +++ b/include/asm-sparc/pgalloc.h @@ -1,4 +1,4 @@ -/* $Id: pgalloc.h,v 1.6 2000/07/10 20:56:53 anton Exp $ */ +/* $Id: pgalloc.h,v 1.9 2000/08/01 04:53:58 anton Exp $ */ #ifndef _SPARC_PGALLOC_H #define _SPARC_PGALLOC_H @@ -85,7 +85,9 @@ BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long) #define __flush_page_to_ram(addr) BTFIXUP_CALL(__flush_page_to_ram)(addr) #define flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(flush_sig_insns)(mm,insn_addr) -#define flush_page_to_ram(page) __flush_page_to_ram(page_address(page)) +extern void flush_page_to_ram(struct page *page); + +#define flush_dcache_page(page) do { } while (0) extern struct pgtable_cache_struct { unsigned long *pgd_cache; diff --git a/include/asm-sparc/softirq.h b/include/asm-sparc/softirq.h index f35407dc8..100f25a22 100644 --- a/include/asm-sparc/softirq.h +++ b/include/asm-sparc/softirq.h @@ -14,26 +14,9 @@ #include <asm/smp.h> #include <asm/hardirq.h> - -#ifdef CONFIG_SMP -extern unsigned int __local_bh_count[NR_CPUS]; -#define local_bh_count(cpu) __local_bh_count[cpu] - #define local_bh_disable() (local_bh_count(smp_processor_id())++) #define local_bh_enable() (local_bh_count(smp_processor_id())--) #define in_softirq() (local_bh_count(smp_processor_id()) != 0) -#else - -extern unsigned int __local_bh_count; -#define local_bh_count(cpu) __local_bh_count - -#define local_bh_disable() (__local_bh_count++) -#define local_bh_enable() (__local_bh_count--) - -#define in_softirq() (__local_bh_count != 0) - -#endif /* SMP */ - #endif /* __SPARC_SOFTIRQ_H */ diff --git a/include/asm-sparc/stat.h b/include/asm-sparc/stat.h index a70d4df3c..7be8e7092 100644 --- a/include/asm-sparc/stat.h +++ b/include/asm-sparc/stat.h @@ -1,4 +1,4 @@ -/* $Id: stat.h,v 1.11 2000/01/16 15:22:53 jj Exp $ */ +/* $Id: stat.h,v 1.12 2000/08/04 05:35:55 davem Exp $ */ #ifndef _SPARC_STAT_H #define _SPARC_STAT_H diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h index 4174294ca..0a101cacd 100644 --- a/include/asm-sparc/system.h +++ b/include/asm-sparc/system.h @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.82 2000/05/09 17:40:15 davem Exp $ */ +/* $Id: system.h,v 1.83 2000/08/04 05:35:55 davem Exp $ */ #include <linux/config.h> #ifndef __SPARC_SYSTEM_H diff --git a/include/asm-sparc/vaddrs.h b/include/asm-sparc/vaddrs.h index 5cbec8210..704f79003 100644 --- a/include/asm-sparc/vaddrs.h +++ b/include/asm-sparc/vaddrs.h @@ -1,4 +1,4 @@ -/* $Id: vaddrs.h,v 1.25 2000/06/05 06:08:46 anton Exp $ */ +/* $Id: vaddrs.h,v 1.26 2000/08/01 04:53:58 anton Exp $ */ #ifndef _SPARC_VADDRS_H #define _SPARC_VADDRS_H @@ -12,6 +12,20 @@ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com) */ +#define SRMMU_MAXMEM 0x0c000000 + +#define SRMMU_NOCACHE_VADDR 0xfc000000 /* KERNBASE + SRMMU_MAXMEM */ +/* XXX Make this dynamic based on ram size - Anton */ +#define SRMMU_NOCACHE_NPAGES 256 +#define SRMMU_NOCACHE_SIZE (SRMMU_NOCACHE_NPAGES * PAGE_SIZE) +#define SRMMU_NOCACHE_END (SRMMU_NOCACHE_VADDR + SRMMU_NOCACHE_SIZE) + +#define FIX_KMAP_BEGIN 0xfc100000 +#define FIX_KMAP_END (FIX_KMAP_BEGIN + ((KM_TYPE_NR*NR_CPUS)-1)*PAGE_SIZE) + +#define PKMAP_BASE 0xfc140000 +#define PKMAP_BASE_END (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE) + #define SUN4M_IOBASE_VADDR 0xfd000000 /* Base for mapping pages */ #define IOBASE_VADDR 0xfe000000 #define IOBASE_END 0xfe300000 diff --git a/include/asm-sparc64/display7seg.h b/include/asm-sparc64/display7seg.h new file mode 100644 index 000000000..955a35022 --- /dev/null +++ b/include/asm-sparc64/display7seg.h @@ -0,0 +1,79 @@ +/* $Id: display7seg.h,v 1.2 2000/08/02 06:22:35 davem Exp $ + * + * display7seg - Driver interface for the 7-segment display + * present on Sun Microsystems CP1400 and CP1500 + * + * Copyright (c) 2000 Eric Brower <ebrower@usa.net> + * + */ + +#ifndef __display7seg_h__ +#define __display7seg_h__ + +#define D7S_IOC 'p' + +#define D7SIOCRD _IOR(D7S_IOC, 0x45, int) /* Read device state */ +#define D7SIOCWR _IOW(D7S_IOC, 0x46, int) /* Write device state */ +#define D7SIOCTM _IO (D7S_IOC, 0x47) /* Translate mode (FLIP)*/ + +/* + * ioctl flag definitions + * + * POINT - Toggle decimal point (0=absent 1=present) + * ALARM - Toggle alarm LED (0=green 1=red) + * FLIP - Toggle inverted mode (0=normal 1=flipped) + * bits 0-4 - Character displayed (see definitions below) + * + * Display segments are defined as follows, + * subject to D7S_FLIP register state: + * + * a + * --- + * f| |b + * -g- + * e| |c + * --- + * d + */ + +#define D7S_POINT (1 << 7) /* Decimal point*/ +#define D7S_ALARM (1 << 6) /* Alarm LED */ +#define D7S_FLIP (1 << 5) /* Flip display */ + +#define D7S_0 0x00 /* Numerals 0-9 */ +#define D7S_1 0x01 +#define D7S_2 0x02 +#define D7S_3 0x03 +#define D7S_4 0x04 +#define D7S_5 0x05 +#define D7S_6 0x06 +#define D7S_7 0x07 +#define D7S_8 0x08 +#define D7S_9 0x09 +#define D7S_A 0x0A /* Letters A-F, H, L, P */ +#define D7S_B 0x0B +#define D7S_C 0x0C +#define D7S_D 0x0D +#define D7S_E 0x0E +#define D7S_F 0x0F +#define D7S_H 0x10 +#define D7S_E2 0x11 +#define D7S_L 0x12 +#define D7S_P 0x13 +#define D7S_SEGA 0x14 /* Individual segments */ +#define D7S_SEGB 0x15 +#define D7S_SEGC 0x16 +#define D7S_SEGD 0x17 +#define D7S_SEGE 0x18 +#define D7S_SEGF 0x19 +#define D7S_SEGG 0x1A +#define D7S_SEGABFG 0x1B /* Segment groupings */ +#define D7S_SEGCDEG 0x1C +#define D7S_SEGBCEF 0x1D +#define D7S_SEGADG 0x1E +#define D7S_BLANK 0x1F /* Clear all segments */ + +#define D7S_MIN_VAL 0x0 +#define D7S_MAX_VAL 0x1F + +#endif /* ifndef __display7seg_h__ */ diff --git a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h index 090239035..e4007b644 100644 --- a/include/asm-sparc64/hardirq.h +++ b/include/asm-sparc64/hardirq.h @@ -11,12 +11,27 @@ #include <linux/brlock.h> #include <linux/spinlock.h> +/* entry.S is sensitive to the offsets of these fields */ +typedef struct { + unsigned int __softirq_active; + unsigned int __softirq_mask; #ifndef CONFIG_SMP -extern unsigned int __local_irq_count; -#define local_irq_count(cpu) __local_irq_count -#define irq_enter(cpu, irq) (__local_irq_count++) -#define irq_exit(cpu, irq) (__local_irq_count--) + unsigned int __local_irq_count; #else + unsigned int __unused_on_SMP; /* DaveM says use brlock for SMP irq. KAO */ +#endif + unsigned int __local_bh_count; + unsigned int __syscall_count; +} ____cacheline_aligned irq_cpustat_t; + +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ +/* Note that local_irq_count() is replaced by sparc64 specific version for SMP */ + +#ifndef CONFIG_SMP +#define irq_enter(cpu, irq) ((void)(irq), local_irq_count(cpu)++) +#define irq_exit(cpu, irq) ((void)(irq), local_irq_count(cpu)--) +#else +#undef local_irq_count #define local_irq_count(cpu) (__brlock_array[cpu][BR_GLOBALIRQ_LOCK]) #define irq_enter(cpu, irq) br_read_lock(BR_GLOBALIRQ_LOCK) #define irq_exit(cpu, irq) br_read_unlock(BR_GLOBALIRQ_LOCK) diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h index c70b95dad..0927fe5cc 100644 --- a/include/asm-sparc64/smp.h +++ b/include/asm-sparc64/smp.h @@ -34,7 +34,7 @@ extern struct prom_cpuinfo linux_cpus[64]; /* Keep this a multiple of 64-bytes for cache reasons. */ struct cpuinfo_sparc { /* Dcache line 1 */ - unsigned int bh_count; + unsigned int __pad0; /* bh_count moved to irq_stat for consistency. KAO */ unsigned int multiplier; unsigned int counter; unsigned int idle_volume; diff --git a/include/asm-sparc64/softirq.h b/include/asm-sparc64/softirq.h index b224a279a..730da1b30 100644 --- a/include/asm-sparc64/softirq.h +++ b/include/asm-sparc64/softirq.h @@ -11,13 +11,6 @@ #include <asm/hardirq.h> #include <asm/system.h> /* for membar() */ -#ifndef CONFIG_SMP -extern unsigned int __local_bh_count; -#define local_bh_count(cpu) __local_bh_count -#else -#define local_bh_count(cpu) (cpu_data[cpu].bh_count) -#endif - #define local_bh_disable() (local_bh_count(smp_processor_id())++) #define local_bh_enable() (local_bh_count(smp_processor_id())--) diff --git a/include/asm-sparc64/stat.h b/include/asm-sparc64/stat.h index 4a4fabac0..48ae70dc9 100644 --- a/include/asm-sparc64/stat.h +++ b/include/asm-sparc64/stat.h @@ -1,4 +1,4 @@ -/* $Id: stat.h,v 1.6 1999/12/21 14:09:48 jj Exp $ */ +/* $Id: stat.h,v 1.7 2000/08/04 05:35:55 davem Exp $ */ #ifndef _SPARC64_STAT_H #define _SPARC64_STAT_H diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h index cf5cd0b02..803a15a51 100644 --- a/include/asm-sparc64/system.h +++ b/include/asm-sparc64/system.h @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.60 2000/05/29 05:34:02 davem Exp $ */ +/* $Id: system.h,v 1.61 2000/08/04 05:35:55 davem Exp $ */ #ifndef __SPARC64_SYSTEM_H #define __SPARC64_SYSTEM_H diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h index 698a6f262..a35094450 100644 --- a/include/linux/agp_backend.h +++ b/include/linux/agp_backend.h @@ -50,6 +50,7 @@ enum chipset_type { VIA_VP3, VIA_MVP3, VIA_MVP4, + VIA_APOLLO_SUPER, VIA_APOLLO_PRO, SIS_GENERIC, AMD_GENERIC, diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 8eb171810..9d214fadc 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -61,20 +61,9 @@ enum TASKLET_SOFTIRQ }; -#if SMP_CACHE_BYTES <= 32 -/* It is trick to make assembly easier. */ -#define SOFTIRQ_STATE_PAD 32 -#else -#define SOFTIRQ_STATE_PAD SMP_CACHE_BYTES -#endif - -struct softirq_state -{ - __u32 active; - __u32 mask; -} __attribute__ ((__aligned__(SOFTIRQ_STATE_PAD))); - -extern struct softirq_state softirq_state[NR_CPUS]; +/* softirq mask and active fields moved to irq_cpustat_t in + * asm/hardirq.h to get better cache usage. KAO + */ struct softirq_action { @@ -87,7 +76,7 @@ extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *d static inline void __cpu_raise_softirq(int cpu, int nr) { - softirq_state[cpu].active |= (1<<nr); + softirq_active(cpu) |= (1<<nr); } diff --git a/include/linux/irq_cpustat.h b/include/linux/irq_cpustat.h new file mode 100644 index 000000000..98cf96ff4 --- /dev/null +++ b/include/linux/irq_cpustat.h @@ -0,0 +1,35 @@ +#ifndef __irq_cpustat_h +#define __irq_cpustat_h + +/* + * Contains default mappings for irq_cpustat_t, used by almost every + * architecture. Some arch (like s390) have per cpu hardware pages and + * they define their own mappings for irq_stat. + * + * Keith Owens <kaos@ocs.com.au> July 2000. + */ + +/* + * Simple wrappers reducing source bloat. Define all irq_stat fields + * here, even ones that are arch dependent. That way we get common + * definitions instead of differing sets for each arch. + */ + +extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */ + +#ifdef CONFIG_SMP +#define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) +#else +#define __IRQ_STAT(cpu, member) ((void)(cpu), irq_stat[0].member) +#endif + + /* arch independent irq_stat fields */ +#define softirq_active(cpu) __IRQ_STAT((cpu), __softirq_active) +#define softirq_mask(cpu) __IRQ_STAT((cpu), __softirq_mask) +#define local_irq_count(cpu) __IRQ_STAT((cpu), __local_irq_count) +#define local_bh_count(cpu) __IRQ_STAT((cpu), __local_bh_count) +#define syscall_count(cpu) __IRQ_STAT((cpu), __syscall_count) + /* arch dependent irq_stat fields */ +#define nmi_count(cpu) __IRQ_STAT((cpu), __nmi_count) /* i386, ia64 */ + +#endif /* __irq_cpustat_h */ diff --git a/include/net/ipip.h b/include/net/ipip.h index b522397f8..398660ca8 100644 --- a/include/net/ipip.h +++ b/include/net/ipip.h @@ -9,7 +9,7 @@ struct ip_tunnel { struct ip_tunnel *next; - struct net_device *dev; + struct net_device *dev; struct net_device_stats stat; int recursion; /* Depth of hard_start_xmit recursion */ @@ -25,6 +25,25 @@ struct ip_tunnel struct ip_tunnel_parm parms; }; +#define IPTUNNEL_XMIT() do { \ + int err; \ + int pkt_len = skb->len; \ + \ + iph->tot_len = htons(skb->len); \ + ip_select_ident(iph, &rt->u.dst); \ + ip_send_check(iph); \ + \ + err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, do_ip_send); \ + if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { \ + stats->tx_bytes += pkt_len; \ + stats->tx_packets++; \ + } else { \ + stats->tx_errors++; \ + stats->tx_aborted_errors++; \ + } \ +} while (0) + + extern int ipip_init(void); extern int ipgre_init(void); extern int sit_init(void); diff --git a/kernel/exit.c b/kernel/exit.c index 993ba31f3..3e95fe878 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -26,17 +26,20 @@ void release(struct task_struct * p) { if (p != current) { #ifdef CONFIG_SMP - int has_cpu; - /* * Wait to make sure the process isn't on the * runqueue (active on some other CPU still) */ - do { + for (;;) { spin_lock_irq(&runqueue_lock); - has_cpu = p->has_cpu; + if (!p->has_cpu) + break; spin_unlock_irq(&runqueue_lock); - } while (has_cpu); + do { + barrier(); + } while (p->has_cpu); + } + spin_unlock_irq(&runqueue_lock); #endif atomic_dec(&p->user->processes); free_uid(p->user); diff --git a/kernel/kmod.c b/kernel/kmod.c index 8fc459453..348210c3b 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -112,6 +112,7 @@ int exec_usermodehelper(char *program_path, char *argv[], char *envp[]) struct user_struct *user = current->user; current->user = INIT_USER; atomic_inc(¤t->user->__count); + atomic_dec(&user->processes); free_uid(user); } diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 241855d8e..bcc6d2e31 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -353,6 +353,9 @@ EXPORT_SYMBOL(add_timer); EXPORT_SYMBOL(del_timer); EXPORT_SYMBOL(request_irq); EXPORT_SYMBOL(free_irq); +#if !defined(CONFIG_ARCH_S390) +EXPORT_SYMBOL(irq_stat); /* No separate irq_stat for s390, it is part of PSA */ +#endif /* waitqueue handling */ EXPORT_SYMBOL(add_wait_queue); diff --git a/kernel/sched.c b/kernel/sched.c index 6d99e08ab..688b30c7b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -506,7 +506,7 @@ tq_scheduler_back: release_kernel_lock(prev, this_cpu); /* Do "administrative" work here while we don't hold any locks */ - if (softirq_state[this_cpu].active & softirq_state[this_cpu].mask) + if (softirq_active(this_cpu) & softirq_mask(this_cpu)) goto handle_softirq; handle_softirq_back: diff --git a/kernel/softirq.c b/kernel/softirq.c index 19e068c65..8c5410315 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -38,8 +38,11 @@ - Bottom halves: globally serialized, grr... */ +/* No separate irq_stat for s390, it is part of PSA */ +#if !defined(CONFIG_ARCH_S390) +irq_cpustat_t irq_stat[NR_CPUS]; +#endif /* CONFIG_ARCH_S390 */ -struct softirq_state softirq_state[NR_CPUS]; static struct softirq_action softirq_vec[32]; asmlinkage void do_softirq() @@ -53,15 +56,15 @@ asmlinkage void do_softirq() local_bh_disable(); local_irq_disable(); - mask = softirq_state[cpu].mask; - active = softirq_state[cpu].active & mask; + mask = softirq_mask(cpu); + active = softirq_active(cpu) & mask; if (active) { struct softirq_action *h; restart: /* Reset active bitmask before enabling irqs */ - softirq_state[cpu].active &= ~active; + softirq_active(cpu) &= ~active; local_irq_enable(); @@ -77,7 +80,7 @@ restart: local_irq_disable(); - active = softirq_state[cpu].active; + active = softirq_active(cpu); if ((active &= mask) != 0) goto retry; } @@ -107,7 +110,7 @@ void open_softirq(int nr, void (*action)(struct softirq_action*), void *data) softirq_vec[nr].action = action; for (i=0; i<NR_CPUS; i++) - softirq_state[i].mask |= (1<<nr); + softirq_mask(i) |= (1<<nr); spin_unlock_irqrestore(&softirq_mask_lock, flags); } diff --git a/kernel/user.c b/kernel/user.c index d9f96da0a..daae4dff4 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -8,6 +8,7 @@ * able to have per-user limits for system resources. */ +#include <linux/config.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/slab.h> diff --git a/mm/highmem.c b/mm/highmem.c index 834968569..e11b5d0b1 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -118,6 +118,8 @@ static void flush_all_zero_pkmaps(void) { int i; + flush_cache_all(); + for (i = 0; i < LAST_PKMAP; i++) { struct page *page; pte_t pte; @@ -181,7 +183,7 @@ start: } } vaddr = PKMAP_ADDR(last_pkmap_nr); - pkmap_page_table[last_pkmap_nr] = mk_pte(page, kmap_prot); + set_pte(pkmap_page_table + last_pkmap_nr, mk_pte(page, kmap_prot)); pkmap_count[last_pkmap_nr] = 1; page->virtual = vaddr; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 1e19a9109..941cb5909 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -29,7 +29,7 @@ int nr_lru_pages; pg_data_t *pgdat_list; static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; -static int zone_balance_ratio[MAX_NR_ZONES] = { 128, 128, 128, }; +static int zone_balance_ratio[MAX_NR_ZONES] = { 32, 128, 128, }; static int zone_balance_min[MAX_NR_ZONES] = { 10 , 10, 10, }; static int zone_balance_max[MAX_NR_ZONES] = { 255 , 255, 255, }; @@ -430,7 +430,16 @@ void show_free_areas_core(int nid) zone_t *zone = NODE_DATA(nid)->node_zones + type; unsigned long nr, total, flags; - printk(" %s: ", zone->name); + printk(" %c%d%d %s: ", + (zone->free_pages > zone->pages_low + ? (zone->free_pages > zone->pages_high + ? ' ' + : 'H') + : (zone->free_pages > zone->pages_min + ? 'M' + : 'L')), + zone->zone_wake_kswapd, zone->low_on_memory, + zone->name); total = 0; if (zone->size) { diff --git a/mm/vmscan.c b/mm/vmscan.c index cbdd0cb7f..4dda15dd1 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -444,20 +444,24 @@ static inline int memory_pressure(void) */ static inline int keep_kswapd_awake(void) { + int all_recent = 1; pg_data_t *pgdat = pgdat_list; do { int i; for(i = 0; i < MAX_NR_ZONES; i++) { zone_t *zone = pgdat->node_zones+ i; - if (zone->size && - !zone->zone_wake_kswapd) - return 0; + if (zone->size) { + if (zone->free_pages < zone->pages_min) + return 1; + if (!zone->zone_wake_kswapd) + all_recent = 0; + } } pgdat = pgdat->node_next; } while (pgdat); - return 1; + return all_recent; } /* @@ -470,6 +474,9 @@ static inline int keep_kswapd_awake(void) * * Don't try _too_ hard, though. We don't want to have bad * latency. + * + * Note: only called by kswapd and try_to_free_pages + * both can WAIT at top level. */ #define FREE_COUNT 8 #define SWAP_COUNT 16 @@ -548,7 +555,7 @@ static int do_try_to_free_pages(unsigned int gfp_mask) } /* Return 1 if any page is freed, or * there are no more memory pressure */ - return (count < FREE_COUNT || !memory_pressure()); + return (count < FREE_COUNT || !keep_kswapd_awake()); done: return 1; diff --git a/net/bridge/br.c b/net/bridge/br.c index a569c0c97..3c6c9b72d 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br.c,v 1.43 2000/05/25 02:21:36 davem Exp $ + * $Id: br.c,v 1.44 2000/08/04 06:08:32 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -43,7 +43,9 @@ int __init br_init(void) printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); br_handle_frame_hook = br_handle_frame; +#ifdef CONFIG_INET br_ioctl_hook = br_ioctl_deviceless_stub; +#endif #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) br_fdb_get_hook = br_fdb_get; br_fdb_put_hook = br_fdb_put; @@ -60,7 +62,9 @@ static void __br_clear_frame_hook(void) static void __br_clear_ioctl_hook(void) { +#ifdef CONFIG_INET br_ioctl_hook = NULL; +#endif } static void __exit br_deinit(void) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b0d989516..f6df3a526 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -407,7 +407,7 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev) for (h=0; h<=PNEIGH_HASHMASK; h++) { np = &tbl->phash_buckets[h]; - for (np = &tbl->phash_buckets[h]; (n=*np) != NULL; np = &n->next) { + while ((n=*np) != NULL) { if (n->dev == dev || dev == NULL) { *np = n->next; if (tbl->pdestructor) diff --git a/net/core/sock.c b/net/core/sock.c index ab8cb89e8..3aaa2fd9a 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -7,7 +7,7 @@ * handler for protocols to use and generic option handler. * * - * Version: $Id: sock.c,v 1.95 2000/07/08 00:20:43 davem Exp $ + * Version: $Id: sock.c,v 1.96 2000/07/26 01:04:14 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 81d8ebe80..2dfd1763c 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1,6 +1,6 @@ /* linux/net/inet/arp.c * - * Version: $Id: arp.c,v 1.87 2000/07/07 22:40:35 davem Exp $ + * Version: $Id: arp.c,v 1.88 2000/08/02 06:05:02 davem Exp $ * * Copyright (C) 1994 by Florian La Roche * @@ -122,9 +122,6 @@ #include <asm/system.h> #include <asm/uaccess.h> -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) -static char *ax2asc2(ax25_address *a, char *buf); -#endif /* @@ -1015,6 +1012,9 @@ out: #ifndef CONFIG_PROC_FS static int arp_get_info(char *buffer, char **start, off_t offset, int length) { return 0; } #else +#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) +static char *ax2asc2(ax25_address *a, char *buf); +#endif #define HBUFFERLEN 30 static int arp_get_info(char *buffer, char **start, off_t offset, int length) @@ -1168,6 +1168,7 @@ void __init arp_init (void) } +#ifdef CONFIG_PROC_FS #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) /* @@ -1202,3 +1203,4 @@ char *ax2asc2(ax25_address *a, char *buf) } #endif +#endif diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index a7f5d3e49..050f5283d 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1,7 +1,7 @@ /* * NET3 IP device support routines. * - * Version: $Id: devinet.c,v 1.36 2000/01/09 02:19:46 davem Exp $ + * Version: $Id: devinet.c,v 1.37 2000/07/26 01:04:15 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 6cac59c91..ee7e44cd2 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -3,7 +3,7 @@ * * Alan Cox, <alan@redhat.com> * - * Version: $Id: icmp.c,v 1.70 2000/06/21 17:16:21 davem Exp $ + * Version: $Id: icmp.c,v 1.71 2000/08/02 06:01:48 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -669,7 +669,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info) room -= sizeof(struct iphdr) + icmp_param.replyopts.optlen; room -= sizeof(struct icmphdr); - icmp_param.data_len=(iph->ihl<<2)+(skb_in->tail-(u8*)iph); + icmp_param.data_len=(skb_in->tail-(u8*)iph); if (icmp_param.data_len > room) icmp_param.data_len = room; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 94d64999f..0af9ec321 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -8,7 +8,7 @@ * the older version didn't come out right using gcc 2.5.8, the newer one * seems to fall out with gcc 2.6.2. * - * Version: $Id: igmp.c,v 1.39 2000/06/21 17:17:32 davem Exp $ + * Version: $Id: igmp.c,v 1.40 2000/07/26 01:04:16 davem Exp $ * * Authors: * Alan Cox <Alan.Cox@linux.org> diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index a316401b0..c2a3ea271 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -668,7 +668,6 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) int gre_hlen; u32 dst; int mtu; - int err; if (tunnel->recursion++) { tunnel->stat.collisions++; @@ -856,26 +855,12 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) } } - iph->tot_len = htons(skb->len); - ip_select_ident(iph, &rt->u.dst); - ip_send_check(iph); - #ifdef CONFIG_NETFILTER nf_conntrack_put(skb->nfct); skb->nfct = NULL; #endif - err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, - do_ip_send); - if(err < 0) { - if(net_ratelimit()) - printk(KERN_ERR "ipgre_tunnel_xmit: ip_send() failed, err=%d\n", -err); - skb = NULL; - goto tx_error; - } - - stats->tx_bytes += skb->len; - stats->tx_packets++; + IPTUNNEL_XMIT(); tunnel->recursion--; return 0; @@ -884,8 +869,7 @@ tx_error_icmp: tx_error: stats->tx_errors++; - if(skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); tunnel->recursion--; return 0; } diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 89b3206f0..53e664444 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -5,7 +5,7 @@ * * The options processing module for ip.c * - * Version: $Id: ip_options.c,v 1.18 1999/06/09 08:29:06 davem Exp $ + * Version: $Id: ip_options.c,v 1.19 2000/07/26 01:04:17 davem Exp $ * * Authors: A.N.Kuznetsov * diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index c1c0bb047..22429bb5e 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -5,7 +5,7 @@ * * The IP to API glue. * - * Version: $Id: ip_sockglue.c,v 1.49 2000/07/08 00:20:43 davem Exp $ + * Version: $Id: ip_sockglue.c,v 1.50 2000/07/26 01:04:17 davem Exp $ * * Authors: see ip.c * diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 765da5148..f0e9bb5bb 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1,5 +1,5 @@ /* - * $Id: ipconfig.c,v 1.33 2000/06/21 17:21:43 davem Exp $ + * $Id: ipconfig.c,v 1.34 2000/07/26 01:04:18 davem Exp $ * * Automatic Configuration of IP -- use BOOTP or RARP or user-supplied * information to configure own IP address and routes. diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 1177033ca..02af22ff9 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -1,7 +1,7 @@ /* * Linux NET3: IP/IP protocol decoder. * - * Version: $Id: ipip.c,v 1.37 2000/07/07 23:47:45 davem Exp $ + * Version: $Id: ipip.c,v 1.38 2000/08/02 06:03:59 davem Exp $ * * Authors: * Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95 @@ -534,7 +534,6 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) int max_headroom; /* The extra header space needed */ u32 dst = tiph->daddr; int mtu; - int err; if (tunnel->recursion++) { tunnel->stat.collisions++; @@ -637,26 +636,12 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if ((iph->ttl = tiph->ttl) == 0) iph->ttl = old_iph->ttl; - iph->tot_len = htons(skb->len); - ip_select_ident(iph, &rt->u.dst); - ip_send_check(iph); - #ifdef CONFIG_NETFILTER nf_conntrack_put(skb->nfct); skb->nfct = NULL; #endif - err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, - do_ip_send); - if(err < 0) { - if(net_ratelimit()) - printk(KERN_ERR "ipip_tunnel_xmit: ip_send() failed, err=%d\n", -err); - skb = NULL; - goto tx_error; - } - - stats->tx_bytes += skb->len; - stats->tx_packets++; + IPTUNNEL_XMIT(); tunnel->recursion--; return 0; @@ -664,8 +649,7 @@ tx_error_icmp: dst_link_failure(skb); tx_error: stats->tx_errors++; - if(skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); tunnel->recursion--; return 0; } diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index e9d087d49..dc946b97b 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -9,7 +9,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version: $Id: ipmr.c,v 1.53 2000/05/05 02:17:17 davem Exp $ + * Version: $Id: ipmr.c,v 1.54 2000/08/02 06:05:16 davem Exp $ * * Fixes: * Michael Chastain : Incorrect size of copying. @@ -1581,6 +1581,7 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait) } #endif +#ifdef CONFIG_PROC_FS /* * The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif */ @@ -1711,7 +1712,6 @@ done: return len; } -#ifdef CONFIG_PROC_FS #endif #ifdef CONFIG_IP_PIMSM_V2 diff --git a/net/ipv4/netfilter/ipfwadm_core.c b/net/ipv4/netfilter/ipfwadm_core.c index 36614409d..aaaa134ba 100644 --- a/net/ipv4/netfilter/ipfwadm_core.c +++ b/net/ipv4/netfilter/ipfwadm_core.c @@ -20,7 +20,7 @@ * license in recognition of the original copyright. * -- Alan Cox. * - * $Id: ipfwadm_core.c,v 1.3 2000/06/09 07:35:49 davem Exp $ + * $Id: ipfwadm_core.c,v 1.4 2000/07/26 01:04:21 davem Exp $ * * Ported from BSD to Linux, * Alan Cox 22/Nov/1994. diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 39cd96ede..d267223ed 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -9,7 +9,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * $Id: syncookies.c,v 1.11 2000/01/16 05:11:27 davem Exp $ + * $Id: syncookies.c,v 1.12 2000/07/26 01:04:19 davem Exp $ * * Missing: IPv6 support. */ diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1fcf0e255..d9f7dd80d 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.209 2000/07/12 03:49:30 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.210 2000/07/26 01:04:19 davem Exp $ * * IPv4 specific functions * diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 582531a97..62b89af5c 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque <roque@di.fc.ul.pt> * - * $Id: mcast.c,v 1.31 2000/06/21 17:23:54 davem Exp $ + * $Id: mcast.c,v 1.32 2000/07/26 01:04:21 davem Exp $ * * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c * diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index b3ba4383d..57430f29f 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -314,7 +314,7 @@ ip6t_do_table(struct sk_buff **pskb, /* Initialization */ ipv6 = (*pskb)->nh.ipv6h; - protohdr = (u_int32_t *)ipv6 + IPV6_HDR_LEN; + protohdr = (u_int32_t *)((char *)ipv6 + IPV6_HDR_LEN); datalen = (*pskb)->len - IPV6_HDR_LEN; indev = in ? in->name : nulldevname; outdev = out ? out->name : nulldevname; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index c8a631f9f..b77f8789d 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -6,7 +6,7 @@ * Pedro Roque <roque@di.fc.ul.pt> * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> * - * $Id: sit.c,v 1.41 2000/07/07 23:47:45 davem Exp $ + * $Id: sit.c,v 1.42 2000/08/02 06:03:59 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -440,7 +440,6 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) int mtu; struct in6_addr *addr6; int addr_type; - int err; if (tunnel->recursion++) { tunnel->stat.collisions++; @@ -565,27 +564,12 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if ((iph->ttl = tiph->ttl) == 0) iph->ttl = iph6->hop_limit; - iph->tot_len = htons(skb->len); - ip_select_ident(iph, &rt->u.dst); - ip_send_check(iph); - #ifdef CONFIG_NETFILTER nf_conntrack_put(skb->nfct); skb->nfct = NULL; #endif - err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, - do_ip_send); - if(err < 0) { - if(net_ratelimit()) - printk(KERN_ERR "ipip6_tunnel_xmit: ip_send() failed, err=%d\n", -err); - skb = NULL; - goto tx_error; - } - - stats->tx_bytes += skb->len; - stats->tx_packets++; - + IPTUNNEL_XMIT(); tunnel->recursion--; return 0; @@ -593,8 +577,7 @@ tx_error_icmp: dst_link_failure(skb); tx_error: stats->tx_errors++; - if(skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); tunnel->recursion--; return 0; } diff --git a/net/netsyms.c b/net/netsyms.c index b8226883b..da99c0783 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -617,7 +617,6 @@ EXPORT_SYMBOL(ipt_unregister_match); EXPORT_SYMBOL(register_gifconf); EXPORT_SYMBOL(net_call_rx_atomic); -EXPORT_SYMBOL(softirq_state); EXPORT_SYMBOL(softnet_data); #endif /* CONFIG_NET */ diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index b342c4f14..b0ea8b730 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -5,7 +5,7 @@ * * PACKET - implements raw packet sockets. * - * Version: $Id: af_packet.c,v 1.36 2000/07/08 00:20:43 davem Exp $ + * Version: $Id: af_packet.c,v 1.37 2000/07/26 01:04:21 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 93a4fbb18..d1728e6a6 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -336,7 +336,7 @@ __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, } else { task->tk_running = 0; if (task->tk_callback) { - printk(KERN_ERR "RPC: %4d overwrites an active callback\n", task->tk_pid); + dprintk(KERN_ERR "RPC: %4d overwrites an active callback\n", task->tk_pid); BUG(); } task->tk_callback = action; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 628269f57..1d327267e 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -8,7 +8,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version: $Id: af_unix.c,v 1.101 2000/07/06 01:41:46 davem Exp $ + * Version: $Id: af_unix.c,v 1.102 2000/07/26 01:04:21 davem Exp $ * * Fixes: * Linus Torvalds : Assorted bug cures. diff --git a/scripts/Configure b/scripts/Configure index 0eec0f93d..4cc31e42b 100644 --- a/scripts/Configure +++ b/scripts/Configure @@ -419,7 +419,14 @@ function define_string () { function string () { old=$(eval echo "\${$2}") def=${old:-$3} - readln "$1 ($2) [$def] " "$def" "$old" + while :; do + readln "$1 ($2) [$def] " "$def" "$old" + if [ "$ans" = "?" ]; then + help "$2" + else + break + fi + done define_string "$2" "$ans" } # |