From: Linus Torvalds Date: Fri, 23 Nov 2007 20:37:26 +0000 (-0500) Subject: Import 2.4.0-test6pre4 X-Git-Tag: 2.4.0-test6pre4 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=d5c129565a8d8661066b80c2178c8c8c392e6411;p=history.git Import 2.4.0-test6pre4 --- diff --git a/CREDITS b/CREDITS index 6398542e8694..49ba8e308656 100644 --- a/CREDITS +++ b/CREDITS @@ -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 ebee4956bb2d..baf746b70b25 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 dc175601332a..d139848da98a 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. diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 078aa7d3d890..4ac2e8b0d5a0 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 253b8d6c191a..ac80051ed33e 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 066af7e1e552..59f1024961ac 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 90a3c30b2895..9022228a0ac6 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 e51ff9d18c19..4f7a04b3f71c 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 6723291dfc6c..fc14d6c45661 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 b4fbfe62824c..c260b8e1919e 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 40a47c45fbdf..8af0c3b3f72c 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 da7fd047d80e..c36d01cce6b5 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 380ac49968aa..c11ab01f2cfa 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 406a307718aa..525f78624cb7 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 fcc0a72f5df7..92ddd01f5dea 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 eea525873039..7bd8a04d0523 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 3aadb43a07e5..f9beac21d769 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 7f01b667c867..2e4ffe403e3b 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 -#include -EXPORT_SYMBOL(irq_stat); - #include EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(kernel_thread); diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index ed7eb88fc5ba..c913fdc3d60e 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 f47ff3a7a920..f92c45f60d2d 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 5f08ef216d89..7cbb69d03395 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 9dc6427e6320..74e1e4c1e260 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 6f8300422e49..7bf46149fe59 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 08b15a7a8e12..03d68ee177fc 100644 --- a/arch/mips/baget/irq.c +++ b/arch/mips/baget/irq.c @@ -29,7 +29,6 @@ #include -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 7551ae6814d4..91e1ce463e50 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 bde21011fcff..bc56db51bc07 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 54c2c3c81b8a..fcb7a632f940 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 b58272f46f43..3b3c4311144c 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 ddf69a964c50..bdc72ca4ee21 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 f61690b851f0..1721b47aeb1a 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 1c6d9e2fa5d4..0d88810581bf 100644 --- a/arch/mips/orion/misc.c +++ b/arch/mips/orion/misc.c @@ -35,10 +35,8 @@ #include #include #include -#include #include #include -#include #include char arcs_cmdline[CL_SIZE] = {0, }; diff --git a/arch/mips/orion/setup.c b/arch/mips/orion/setup.c index 8d4cc54f0ff6..c247d6b528ae 100644 --- a/arch/mips/orion/setup.c +++ b/arch/mips/orion/setup.c @@ -35,10 +35,8 @@ #include #include #include -#include #include #include -#include #include #include diff --git a/arch/mips/sgi/kernel/indy_int.c b/arch/mips/sgi/kernel/indy_int.c index 06d8573cbb27..2e104bf79b5b 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 8f61ca7eec9e..ee4881448873 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 a6ac27f68667..2e65e1732443 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 2047c7303de4..2d7782d11a63 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 891e121f637b..19c61e6dcf06 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 f5160af15b5e..ead444bb5741 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 8ccb0f571cee..d40a54cf141e 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 ee63ca90213c..64ef4b4dc623 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 840b14d6fbd0..5c616bbbdbbc 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 3f0b52ead578..1317359e78cc 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 9acccfd970fe..9913d5967fc5 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 298aa2482b5d..ba513325a429 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 93d4dff7639f..6f6a5287b21e 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 7a4e531d5d84..b1db16707106 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 cfc744a63d61..f20a9d49e7ca 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 cbca87e694ab..450d4982446f 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 399d435af13a..a353b0995100 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -41,9 +41,6 @@ #include #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 e79dfd803093..570f86325859 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 65e95afdb294..a6fd32fa49e5 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 dcfc2dc785cd..c44040bde099 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 a51995713a91..37c276c7fec8 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 5ac1845a3a1b..ced31b91f3d7 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 612436b478d3..c7f839f28f13 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 95c148eee956..c57f14bb1913 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 e013e47fbe7c..168109d49b0c 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 @@ -322,6 +323,17 @@ CONFIG_FC4_SOCAL=m 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 # diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index f64422a0e3b6..5872046b15ad 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) { @@ -383,6 +386,9 @@ void __init ebus_init(void) #endif #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 3195d3e75d9f..e95e0392ef0e 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 98e209de22a9..d4f49972663b 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 #include #include - +#include #include #include @@ -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 12925b1c2a05..c7f4905b8c8e 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 2d5d8145282c..5784201e2c27 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 1c9b6ac3f7fd..3295938e6935 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 c666dc4089c8..d1e7e4215186 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 f99b9660cc11..96f8624caa91 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 eccc7885a80a..4a79b76bf3e6 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 d32ea68c2d33..bcfa77a396bf 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 859d0c7ea04c..e869af4e62e3 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 89c1a90eaec8..7d8a71d6af46 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 3f43e99dc1f0..9015a2fec8c7 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 7b5d3261457f..de4968ac4ca7 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 090eb96a1cee..3cf5b6883c0b 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 18d73e686891..0e899da18d95 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 946b20fae7c9..3ef9c943b5d2 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 f41c3d48b863..2ac91160de87 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 dcc8176f9e4e..573419a28b1e 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 48a6aa5f97f0..e1e1ccedddf0 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 3e5149c910e6..e4783c8db90d 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 e7aaf569d307..661ac48161aa 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 434dff875179..a0bbf343ffe2 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 6813797085e0..d9b81882412c 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 36b11f907e04..281940845193 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 a2da24437f4b..84dc28025bfd 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 * @@ -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 1ee37e20ed7a..096d8164a4d2 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 4a88efda31b3..84ee1ad22a8d 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 000000000000..c9d4ea0f63ec --- /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 +#include +#include +#include +#include +#include +#include +#include +#include /* request_region, check_region */ +#include /* EBus device */ +#include /* OpenProm Library */ +#include /* put_/get_user_ret */ + +#include + +#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 "); +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 ebe4e33bae52..ba6cc03cf58c 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 @@ -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 e5c5ca10fc66..9ebe9e927099 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 */ /* */ /*****************************************************************************/ @@ -78,9 +90,7 @@ * */ -#if defined (MODULE) - #include -#endif /* MODULE */ +#include #include #include @@ -110,14 +120,33 @@ #include #include + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,18) #include +#else +#include +#endif + #include /* * 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); } @@ -2048,38 +2635,206 @@ static inline ips_scb_t * ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) { ips_scb_t *p; - DBG("ips_removeq_scb"); + DBG("ips_removeq_scb"); + + if (!item) + return (NULL); + + IPS_QUEUE_LOCK(queue); + + if (item == queue->head) { + IPS_QUEUE_UNLOCK(queue); + + return (ips_removeq_scb_head(queue)); + } + + p = queue->head; + + while ((p) && (item != p->q_next)) + p = p->q_next; + + if (p) { + /* found a match */ + p->q_next = item->q_next; + + if (!item->q_next) + queue->tail = p; + + item->q_next = NULL; + queue->count--; + + IPS_QUEUE_UNLOCK(queue); + + return (item); + } + + IPS_QUEUE_UNLOCK(queue); + + return (NULL); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_putq_wait_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_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) { + DBG("ips_putq_wait_head"); + + if (!item) + return ; + + IPS_QUEUE_LOCK(queue); + + item->host_scribble = (char *) queue->head; + queue->head = item; + + if (!queue->tail) + queue->tail = item; + + queue->count++; + + IPS_QUEUE_UNLOCK(queue); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_putq_wait_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_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { + DBG("ips_putq_wait_tail"); + + if (!item) + return ; + + IPS_QUEUE_LOCK(queue); + + item->host_scribble = NULL; + + if (queue->tail) + queue->tail->host_scribble = (char *)item; + + queue->tail = item; + + if (!queue->head) + queue->head = item; + + queue->count++; + + IPS_QUEUE_UNLOCK(queue); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_removeq_wait_head */ +/* */ +/* Routine Description: */ +/* */ +/* Remove the head of the queue */ +/* */ +/* ASSUMED to be called from within a lock */ +/* */ +/****************************************************************************/ +static inline Scsi_Cmnd * +ips_removeq_wait_head(ips_wait_queue_t *queue) { + Scsi_Cmnd *item; + + DBG("ips_removeq_wait_head"); + + IPS_QUEUE_LOCK(queue); + + item = queue->head; + + if (!item) { + IPS_QUEUE_UNLOCK(queue); + + return (NULL); + } + + queue->head = (Scsi_Cmnd *) item->host_scribble; + item->host_scribble = NULL; + + if (queue->tail == item) + queue->tail = NULL; + + queue->count--; + + IPS_QUEUE_UNLOCK(queue); + + return (item); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_removeq_wait */ +/* */ +/* Routine Description: */ +/* */ +/* Remove an item from a queue */ +/* */ +/* ASSUMED to be called from within a lock */ +/* */ +/****************************************************************************/ +static inline Scsi_Cmnd * +ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) { + Scsi_Cmnd *p; + + DBG("ips_removeq_wait"); if (!item) return (NULL); - if (item == queue->head) - return (ips_removeq_scb_head(queue)); + IPS_QUEUE_LOCK(queue); + + if (item == queue->head) { + IPS_QUEUE_UNLOCK(queue); + + return (ips_removeq_wait_head(queue)); + } p = queue->head; - while ((p) && (item != p->q_next)) - p = p->q_next; + while ((p) && (item != (Scsi_Cmnd *) p->host_scribble)) + p = (Scsi_Cmnd *) p->host_scribble; if (p) { /* found a match */ - p->q_next = item->q_next; + p->host_scribble = item->host_scribble; - if (!item->q_next) + if (!item->host_scribble) queue->tail = p; - item->q_next = NULL; + item->host_scribble = NULL; queue->count--; + IPS_QUEUE_UNLOCK(queue); + return (item); } + IPS_QUEUE_UNLOCK(queue); + return (NULL); } /****************************************************************************/ /* */ -/* Routine Name: ips_putq_wait_head */ +/* Routine Name: ips_putq_copp_head */ /* */ /* Routine Description: */ /* */ @@ -2089,24 +2844,28 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) { /* */ /****************************************************************************/ static inline void -ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) { - DBG("ips_putq_wait_head"); +ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { + DBG("ips_putq_copp_head"); if (!item) return ; - item->host_scribble = (char *) queue->head; + 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_wait_tail */ +/* Routine Name: ips_putq_copp_tail */ /* */ /* Routine Description: */ /* */ @@ -2116,16 +2875,18 @@ ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) { /* */ /****************************************************************************/ static inline void -ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { - DBG("ips_putq_wait_tail"); +ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { + DBG("ips_putq_copp_tail"); if (!item) return ; - item->host_scribble = NULL; + IPS_QUEUE_LOCK(queue); + + item->next = NULL; if (queue->tail) - queue->tail->host_scribble = (char *)item; + queue->tail->next = item; queue->tail = item; @@ -2133,11 +2894,13 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { queue->head = item; queue->count++; + + IPS_QUEUE_UNLOCK(queue); } /****************************************************************************/ /* */ -/* Routine Name: ips_removeq_wait_head */ +/* Routine Name: ips_removeq_copp_head */ /* */ /* Routine Description: */ /* */ @@ -2146,31 +2909,38 @@ ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { /* ASSUMED to be called from within a lock */ /* */ /****************************************************************************/ -static inline Scsi_Cmnd * -ips_removeq_wait_head(ips_wait_queue_t *queue) { - Scsi_Cmnd *item; +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_wait_head"); + DBG("ips_removeq_copp_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; + 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_wait */ +/* Routine Name: ips_removeq_copp */ /* */ /* Routine Description: */ /* */ @@ -2179,36 +2949,45 @@ ips_removeq_wait_head(ips_wait_queue_t *queue) { /* ASSUMED to be called from within a lock */ /* */ /****************************************************************************/ -static inline Scsi_Cmnd * -ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) { - Scsi_Cmnd *p; +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_wait"); + DBG("ips_removeq_copp"); if (!item) return (NULL); - if (item == queue->head) - return (ips_removeq_wait_head(queue)); + IPS_QUEUE_LOCK(queue); + + if (item == queue->head) { + IPS_QUEUE_UNLOCK(queue); + + return (ips_removeq_copp_head(queue)); + } p = queue->head; - while ((p) && (item != (Scsi_Cmnd *) p->host_scribble)) - p = (Scsi_Cmnd *) p->host_scribble; + while ((p) && (item != p->next)) + p = p->next; if (p) { /* found a match */ - p->host_scribble = item->host_scribble; + p->next = item->next; - if (!item->host_scribble) + if (!item->next) queue->tail = p; - item->host_scribble = NULL; + 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 d760ae3a6ac2..e93fe8153bb6 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -47,7 +47,6 @@ #ifndef _IPS_H_ #define _IPS_H_ - #include #include #include @@ -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 2c7dbb018de4..399148c74129 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 0b30ebb38e2d..fe26b4c01327 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 333fd6576ef7..bcc2b9b7bca0 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 96a3b9a7904e..22f6031b2495 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 a88919d651c7..e38198485bb7 100644 --- a/drivers/video/clgenfb.c +++ b/drivers/video/clgenfb.c @@ -56,9 +56,6 @@ #ifdef CONFIG_AMIGA #include #endif -#ifdef CONFIG_FB_OF -#include -#endif #include