From fde9fa96a28a10efe546471d6afad9a8c1362001 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:09:55 -0500 Subject: [PATCH] Import 1.1.93 --- Makefile | 2 +- arch/i386/boot/compressed/misc.c | 2 +- arch/i386/kernel/bios32.c | 8 +- arch/sparc/kernel/entry.S | 266 ++++++++++++++++++++++++++++- arch/sparc/kernel/head.S | 9 +- arch/sparc/kernel/ioport.c | 2 +- arch/sparc/kernel/irq.c | 51 +++++- arch/sparc/kernel/probe.c | 12 +- arch/sparc/kernel/setup.c | 2 - arch/sparc/mm/init.c | 2 +- drivers/block/README.ide | 9 +- drivers/block/ide.c | 29 +--- drivers/net/plip.c | 3 + drivers/scsi/53c7,8xx.c | 2 +- drivers/scsi/hosts.c | 17 ++ drivers/scsi/hosts.h | 18 +- drivers/scsi/qlogic.c | 170 ++++++++++--------- drivers/scsi/scsi.c | 281 +++++++++++++++++-------------- drivers/scsi/scsi.h | 17 ++ drivers/scsi/scsi_ioctl.c | 17 ++ drivers/scsi/sd.c | 25 +++ drivers/scsi/sd_ioctl.c | 16 ++ drivers/scsi/seagate.c | 3 +- drivers/scsi/sg.c | 17 ++ drivers/scsi/sr.c | 91 +++++++--- drivers/scsi/sr.h | 2 +- drivers/scsi/sr_ioctl.c | 19 ++- drivers/scsi/st.c | 40 +++-- include/asm-sparc/clock.h | 2 + include/asm-sparc/delay.h | 2 +- include/asm-sparc/head.h | 38 +++-- include/asm-sparc/io.h | 4 +- include/asm-sparc/pgtable.h | 25 ++- include/asm-sparc/system.h | 2 +- include/linux/ip.h | 6 + include/linux/tcp.h | 10 ++ mm/kmalloc.c | 7 +- mm/memory.c | 8 +- mm/swap.c | 72 +++++--- net/inet/af_inet.c | 21 ++- 40 files changed, 973 insertions(+), 356 deletions(-) diff --git a/Makefile b/Makefile index f91831ae3b3c..fe1c95a2803c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 92 +SUBLEVEL = 93 ARCH = i386 diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index de2917dfe955..2623925c7312 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -107,7 +107,7 @@ void *malloc(int size) } if (free_mem_ptr < 0x90000) return p; - puts("memory is tight..."); + puts("large kernel, low 1M tight..."); free_mem_ptr = (long)input_data; } } diff --git a/arch/i386/kernel/bios32.c b/arch/i386/kernel/bios32.c index eb6cdad99296..a7c58b714528 100644 --- a/arch/i386/kernel/bios32.c +++ b/arch/i386/kernel/bios32.c @@ -765,8 +765,12 @@ unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) } printk ("bios32_init : BIOS32 Service Directory structure at 0x%p\n", check); if (!bios32_entry) { - bios32_indirect.address = bios32_entry = check->fields.entry; - printk ("bios32_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); + if (check->fields.entry >= 0x100000) { + printk("bios32_init: entry in high memory, unable to access\n"); + } else { + bios32_indirect.address = bios32_entry = check->fields.entry; + printk ("bios32_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); + } } else { printk ("bios32_init : multiple entries, mail drew@colorado.edu\n"); /* diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 2704937bf25b..21548015ef22 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -10,7 +10,9 @@ #include #include +#include #include +#include /* Here are macros for routines we do often, this allows me to inline this * without making the code look real ugly. Well, the macro looks ugly too but @@ -179,12 +181,15 @@ andcc %l0, 0x40, %g0; \ bz 1f; \ andcc %l4, %l5, %g0; \ - bz,a 0f; \ sethi %hi( C_LABEL(eintstack) ), %l7; \ + or %l7, %lo( C_LABEL(eintstack) ), %l7; \ + bz 0f; \ + nop; \ TRAP_WIN_CLEAN \ sethi %hi( C_LABEL(eintstack) ), %l7; \ -0: cmp %fp, %l7; \ - bge,a 3f; \ + or %l7, %lo( C_LABEL(eintstack) ), %l7; \ +0: subcc %fp, %l7, %g0; \ + bg,a 3f; \ sub %l7, 0xb0, %sp; \ b 3f; \ sub %fp, 0xb0, %sp; \ @@ -204,12 +209,13 @@ 5: st %l5, [%l6 + THREAD_UWINDOWS]; \ bz,a 2f; \ sethi %hi( C_LABEL(eintstack) ), %l7; \ - TRAP_WIN_CLEAN; \ + TRAP_WIN_CLEAN \ sethi %hi( C_LABEL(eintstack) ), %l7; \ 2: \ sub %l7, 0xb0, %sp; \ 3: + .text .align 4 @@ -240,15 +246,257 @@ my_trap_handler: rett %l2 #endif /* bogon */ + .align 4 .globl sparc_timer sparc_timer: - ENTER_IRQ - or %g0, 0x10, %o0 - call C_LABEL(do_IRQ) + sethi %hi(TIMER_VADDR), %l4 + or %l4, %lo(TIMER_VADDR), %l4 ! read the limit register + ld [%l4 + 0xc], %l4 ! to clear the interrupt + rd %wim, %l4 + or %g0, 0x1, %l5 + sll %l5, %l0, %l5 + andcc %l0, 0x40, %g0 + bz st1 + sethi %hi( C_LABEL(eintstack) ), %l7 + andcc %l4, %l5, %g0 + bz st0 + or %l7, %lo( C_LABEL(eintstack) ), %l7 + TRAP_WIN_CLEAN + sethi %hi( C_LABEL(eintstack) ), %l7 + or %l7, %lo( C_LABEL(eintstack) ), %l7 +st0: subcc %fp, %l7, %g0 + bg,a st3 + sub %l7, 0xb0, %sp + b st3 + sub %fp, 0xb0, %sp +st1: sethi %hi( C_LABEL(current) ), %l6 + ld [%l6 + %lo( C_LABEL(current) )], %l6 + ld [%l6 + THREAD_WIM], %l5 + and %l0, 0x1f, %l7 + cmp %l5, %l7 + ble,a st4 + sethi %hi( C_LABEL(nwindowsm1) ), %l4 + sub %l5, %l7, %l7 + b st5 + sub %l7, 0x1, %l5 +st4: ld [%l4 + %lo( C_LABEL(nwindowsm1) )], %l4 + sub %l4, %l7, %l4 + add %l5, %l4, %l5 +st5: st %l5, [%l6 + THREAD_UWINDOWS] + sethi %hi( C_LABEL(eintstack) ), %l7 + bz,a st2 + or %l7, %lo( C_LABEL(eintstack) ), %l7 + TRAP_WIN_CLEAN + sethi %hi( C_LABEL(eintstack) ), %l7 + or %l7, %lo( C_LABEL(eintstack) ), %l7 +st2: sub %l7, 0xb0, %sp + +st3: std %g2, [%sp + 96 + 24] + or %g0, %g1, %l7 + rd %y, %l6 + std %g4, [%sp + 96 + 32] + andn %l0, PSR_PIL, %l4 + sll %l3, 0x8, %l5 + std %g6, [%sp + 96 + 40] + or %l5, %l4, %l4 + + wr %l4, 0x0, %psr + wr %l4, PSR_ET, %psr + + std %l0, [%sp + 96 + 0] + std %l2, [%sp + 96 + 8] + st %fp, [%sp + 96 + 16] + + or %g0, 14, %o0 + or %g0, %g0, %o1 + call C_LABEL(do_sparc_timer) + nop + + or %g0, %l7, %g1 + wr %l6, 0x0, %y + ldd [%sp + 96 + 24], %g2 + ldd [%sp + 96 + 32], %g4 + ldd [%sp + 96 + 40], %g6 + wr %l0, 0x0, %psr + nop + nop + nop + + and %l0, 31, %l5 + sethi %hi(lnx_winmask), %l6 + or %l6, %lo(lnx_winmask), %l6 + ldub [%l6 + %l5], %l5 + andcc %l0, PSR_PS, %g0 + bnz 1f + rd %wim, %l4 + +1: andcc %l5, %l4, %g0 + bnz 2f + wr %l0, 0x0, %psr + nop + nop + nop + + jmp %l1 + rett %l2 + +2: wr %g0, 0x0, %wim + nop + nop + nop + + restore + restore %g0, 0x1, %l1 + rd %psr, %l0 + and %l0, 31, %l0 + sll %l1, %l0, %l1 + wr %l1, 0x0, %wim + sethi %hi( C_LABEL(current) ), %l1 + ld [%l1 + %lo( C_LABEL(current) ) ], %l1 + st %l0, [%l1 + THREAD_WIM] + save %g0, %g0, %g0 + + ldd [%sp], %l0 + ldd [%sp + 0x8], %l2 + ldd [%sp + 0x10], %l4 + ldd [%sp + 0x18], %l6 + ldd [%sp + 0x20], %i0 + ldd [%sp + 0x28], %i2 + ldd [%sp + 0x30], %i4 + ldd [%sp + 0x38], %i6 + + save %g0, %g0, %g0 + + jmp %l1 + rett %l2 + + +/* For now all IRQ's not registered get sent here so I can see + * what is poking the chip. + */ + + .align 4 + .globl stray_irq_entry +stray_irq_entry: + rd %wim, %l4 + or %g0, 0x1, %l5 + sll %l5, %l0, %l5 + andcc %l0, 0x40, %g0 + bz tt1 + sethi %hi( C_LABEL(eintstack) ), %l7 + andcc %l4, %l5, %g0 + bz tt0 + or %l7, %lo( C_LABEL(eintstack) ), %l7 + TRAP_WIN_CLEAN + sethi %hi( C_LABEL(eintstack) ), %l7 + or %l7, %lo( C_LABEL(eintstack) ), %l7 +tt0: subcc %fp, %l7, %g0 + bg,a tt3 + sub %l7, 0xb0, %sp + b tt3 + sub %fp, 0xb0, %sp +tt1: sethi %hi( C_LABEL(current) ), %l6 + ld [%l6 + %lo( C_LABEL(current) )], %l6 + ld [%l6 + THREAD_WIM], %l5 + and %l0, 0x1f, %l7 + cmp %l5, %l7 + ble,a tt4 + sethi %hi( C_LABEL(nwindowsm1) ), %l4 + sub %l5, %l7, %l7 + b tt5 + sub %l7, 0x1, %l5 +tt4: ld [%l4 + %lo( C_LABEL(nwindowsm1) )], %l4 + sub %l4, %l7, %l4 + add %l5, %l4, %l5 +tt5: st %l5, [%l6 + THREAD_UWINDOWS] + sethi %hi( C_LABEL(eintstack) ), %l7 + bz,a tt2 + or %l7, %lo( C_LABEL(eintstack) ), %l7 + TRAP_WIN_CLEAN + sethi %hi( C_LABEL(eintstack) ), %l7 + or %l7, %lo( C_LABEL(eintstack) ), %l7 +tt2: sub %l7, 0xb0, %sp + +tt3: std %g2, [%sp + 96 + 24] + or %g0, %g1, %l7 + rd %y, %l6 + std %g4, [%sp + 96 + 32] + andn %l0, PSR_PIL, %l4 + sll %l3, 0x8, %l5 + std %g6, [%sp + 96 + 40] + or %l5, %l4, %l4 + + wr %l4, 0x0, %psr + wr %l4, PSR_ET, %psr + + std %l0, [%sp + 96 + 0] + std %l2, [%sp + 96 + 8] + st %fp, [%sp + 96 + 16] + + or %g0, %l3, %o0 or %g0, %g0, %o1 + call C_LABEL(unexpected_irq) + nop + + or %g0, %l7, %g1 + wr %l6, 0x0, %y + ldd [%sp + 96 + 24], %g2 + ldd [%sp + 96 + 32], %g4 + ldd [%sp + 96 + 40], %g6 + wr %l0, 0x0, %psr + nop + nop + nop + + and %l0, 31, %l5 + sethi %hi(lnx_winmask), %l6 + or %l6, %lo(lnx_winmask), %l6 + ldub [%l6 + %l5], %l5 + andcc %l0, PSR_PS, %g0 + bnz 1f + rd %wim, %l4 + +1: andcc %l5, %l4, %g0 + bnz 2f + wr %l0, 0x0, %psr + nop + nop + nop + jmp %l1 rett %l2 - nop + +2: wr %g0, 0x0, %wim + nop + nop + nop + + restore + restore %g0, 0x1, %l1 + rd %psr, %l0 + and %l0, 31, %l0 + sll %l1, %l0, %l1 + wr %l1, 0x0, %wim + sethi %hi( C_LABEL(current) ), %l1 + ld [%l1 + %lo( C_LABEL(current) ) ], %l1 + st %l0, [%l1 + THREAD_WIM] + save %g0, %g0, %g0 + + ldd [%sp], %l0 + ldd [%sp + 0x8], %l2 + ldd [%sp + 0x10], %l4 + ldd [%sp + 0x18], %l6 + ldd [%sp + 0x20], %i0 + ldd [%sp + 0x28], %i2 + ldd [%sp + 0x30], %i4 + ldd [%sp + 0x38], %i6 + + save %g0, %g0, %g0 + + jmp %l1 + rett %l2 + + /* This routine is optimized for kernel window fills. User fills take about two * or three extra jumps on the average. We'll see how this works out. @@ -529,7 +777,7 @@ leave_trap: .data .align 4 -lnx_winmask: .byte 2, 4, 8, 16, 32, 64, 128,1 ! lnx_winmask[0..7] +lnx_winmask: .byte 2, 4, 8, 16, 32, 64, 128, 1 ! lnx_winmask[0..7] .align 4 diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S index 73f6482522ca..c99c28832f25 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head.S @@ -263,7 +263,7 @@ C_LABEL(trapbase): TRAP_ENTRY_INTERRUPT(11) /* Interrupt Level 11 */ TRAP_ENTRY_INTERRUPT(12) /* Interrupt Level 12 */ TRAP_ENTRY_INTERRUPT(13) /* Interrupt Level 13 */ - TRAP_ENTRY(0x27, sparc_timer) /* Interrupt Level 14 */ + TRAP_ENTRY_TIMER /* Interrupt Level 14 */ TRAP_ENTRY_INTERRUPT_NMI(15, linux_trap_nmi) /* Level 15 (nmi) */ TRAP_ENTRY(0x20, my_trap_handler) /* General Register Access Error */ @@ -370,7 +370,7 @@ C_LABEL(trapbase): TRAP_ENTRY(0x85, my_trap_handler) /* Software Trap */ TRAP_ENTRY(0x86, my_trap_handler) /* Fix Unaligned Access Trap XXX */ TRAP_ENTRY(0x87, my_trap_handler) /* Integer Overflow Trap XXX */ - TRAP_ENTRY(0x88, my_trap_handler) /* Software Trap */ + TRAP_ENTRY(0x88, my_trap_handler) /* Slowaris System Call */ TRAP_ENTRY(0x89, my_trap_handler) /* NetBSD System Call */ TRAP_ENTRY(0x8a, my_trap_handler) /* Software Trap */ TRAP_ENTRY(0x8b, my_trap_handler) /* Software Trap */ @@ -725,10 +725,7 @@ rest_of_boot: sta %l1, [%l0] ASI_PTE - or %g0, INTS_ENAB, %l1 - nop - nop - + or %g0, 0x1, %l1 stb %l1, [%l0] diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 1a927deeeeb0..effa6c25e094 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -1,6 +1,6 @@ /* ioport.c: I/O access on the Sparc. Work in progress.. Most of the things * in this file are for the sole purpose of getting the kernel - * through the compiler. :-) + * through the compiler. :-) * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index a564ab6c08ff..5dcaf197162e 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -30,6 +30,11 @@ #include #include #include +#include +#include +#include + +#define DEBUG_IRQ void disable_irq(unsigned int irq_nr) { @@ -43,7 +48,7 @@ void disable_irq(unsigned int irq_nr) * have to do here is frob the bits. */ - int_reg = (char *) IRQ_ENA_ADR; + int_reg = (unsigned char *) IRQ_ENA_ADR; switch(irq_nr) { @@ -78,7 +83,7 @@ void disable_irq(unsigned int irq_nr) void enable_irq(unsigned int irq_nr) { unsigned long flags; - unsigned int *int_reg; + unsigned char *int_reg; save_flags(flags); cli(); @@ -87,8 +92,12 @@ void enable_irq(unsigned int irq_nr) * have to do here is frob the bits. */ - int_reg = (unsigned int *) IRQ_ENA_ADR; + int_reg = (unsigned char *) IRQ_ENA_ADR; +#ifdef DEBUG_IRQ + printk(" --- Enabling IRQ level %d ---\n", irq_nr); +#endif + switch(irq_nr) { case 1: @@ -116,6 +125,7 @@ void enable_irq(unsigned int irq_nr) }; restore_flags(flags); + return; } @@ -163,7 +173,7 @@ void free_irq(unsigned int irq) unsigned long flags; if (irq > 14) { /* 14 irq levels on the sparc */ - printk("Trying to free IRQ%d\n", irq); + printk("Trying to free IRQ %d\n", irq); return; } if (!action->handler) { @@ -188,7 +198,7 @@ static void handle_nmi(struct pt_regs * regs) } #endif -static void unexpected_irq(int irq, struct pt_regs * regs) +void unexpected_irq(int irq, struct pt_regs * regs) { int i; @@ -229,6 +239,28 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) return; } +/* + * Since we need to special things to clear up the clock chip around + * the do_timer() call we have a special version of do_IRQ for the + * level 14 interrupt which does these things. + */ + +asmlinkage void do_sparc_timer(int irq, struct pt_regs * regs) +{ + struct irqaction *action = irq + irq_action; + register volatile int clear; + + kstat.interrupts[irq]++; + + /* I do the following already in the entry code, better safe than + * sorry for now. Reading the limit register clears the interrupt. + */ + clear = TIMER_STRUCT->timer_limit14; + + action->handler(irq, regs); + return; +} + /* * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return * stuff - the handler is also running with interrupts disabled unless @@ -241,6 +273,8 @@ asmlinkage void do_fast_IRQ(int irq) return; } +extern int first_descent; +extern void probe_clock(int); int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *), unsigned long irqflags, const char * devname) @@ -252,7 +286,10 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *), return -EINVAL; if(irq == 0) /* sched_init() requesting the timer IRQ */ - irq = 14; + { + irq = 14; + probe_clock(first_descent); + } action = irq + irq_action; @@ -263,6 +300,7 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *), return -EINVAL; save_flags(flags); + cli(); action->handler = handler; @@ -273,6 +311,7 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *), enable_irq(irq); restore_flags(flags); + return 0; } diff --git a/arch/sparc/kernel/probe.c b/arch/sparc/kernel/probe.c index ddd2c7b88b38..f08066409c0e 100644 --- a/arch/sparc/kernel/probe.c +++ b/arch/sparc/kernel/probe.c @@ -23,6 +23,8 @@ extern int node_get_child(int node); extern char* get_str_from_prom(int node, char* name, char* value); extern unsigned int* get_int_from_prom(int node, char* name, unsigned int *value); +int first_descent; + /* Cpu-type information and manufacturer strings */ @@ -275,13 +277,12 @@ probe_clock(int fchild) printk("%s\n", node_str); printk("At OBIO address: 0x%x Virtual address: 0x%x\n", - (unsigned int) 0xf3000000, (unsigned int) TIMER_STRUCT); + (unsigned int) TIMER_PHYSADDR, (unsigned int) TIMER_STRUCT); - mapioaddr((unsigned long) 0xf3000000, + mapioaddr((unsigned long) TIMER_PHYSADDR, (unsigned long) TIMER_STRUCT); - TIMER_STRUCT->timer_limit14=(((10000) << 10) | 0x80000000); - TIMER_STRUCT->timer_limit10=(((10000) << 10) | 0x80000000); + TIMER_STRUCT->timer_limit14=(((1000000/HZ) << 10) | 0x80000000); return; } @@ -390,7 +391,7 @@ probe_sbus(register int cpu_child_node) void probe_devices(void) { - register int nd, first_descent; + register int nd; register char* str; nd = prom_node_root; @@ -427,7 +428,6 @@ probe_devices(void) probe_cpu(); probe_vac(); probe_mmu(); - probe_clock(first_descent); /* printk("PROM Root Child Node: 0x%x Name: %s \n", nd, diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index d8771f4c62ec..05f0537a278c 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -92,8 +92,6 @@ void setup_arch(char **cmdline_p, printk("calling probe_devices...\n"); probe_devices(); /* cpu/fpu, mmu probes */ - swpipl(13); - *memory_start_p = (((unsigned long) &end)); } diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index 5b831edb0950..098a1f8e95f7 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c @@ -156,7 +156,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) */ /* Make the kernel text unwritable and cacheable, the prom - * loaded out text as writable, only sneaky sunos kernels need + * loaded our text as writable, only sneaky sunos kernels need * self-modifying code. */ diff --git a/drivers/block/README.ide b/drivers/block/README.ide index 588fa1bc32be..b3e7bdb81225 100644 --- a/drivers/block/README.ide +++ b/drivers/block/README.ide @@ -1,4 +1,4 @@ -README.ide -- Information regarding ide.c and ide-cd.c +README.ide -- Information regarding ide.c and ide-cd.c (IDE driver in 1.1.93) ================================================================================ Supported by: mlord@bnr.ca -- disks, interfaces, probing snyder@fnald0.fnal.gov -- cdroms, ATAPI, audio @@ -12,13 +12,13 @@ Major features of ide.c & ide-cd.c: - support for reading IDE ATAPI cdrom drives (NEC, MITSUMI, VERSA, SONY) - support for audio functions on FX400,NEC-260 cdrom drives (others?) - auto-detection of interfaces, drives, IRQs, and disk geometries + -- "single" drives should be jumpered as "master", not "slave" - support for BIOSs which report "more than 16 heads" on disk drives - uses LBA (slightly faster) on disk drives which support it - support for lots of fancy (E)IDE drive functions with hdparm utility - optional (compile time) support for 32-bit VLB data transfers - support for IDE multiple (block) mode (same as hd.c) - support for interrupt unmasking during I/O (better than hd.c) - - compile flag for auto detection/use of multiple mode setting from BIOS - improved handshaking and error detection/recovery - can co-exist with hd.c to control only the secondary interface @@ -66,6 +66,11 @@ or hdc=768,16,32 hdc=noprobe +Note that when only one IDE device is attached to an interface, +it must be jumpered as "single" or "master", *not* "slave". +Many folks have had "trouble" with cdroms because of this requirement +of the ATA (IDE) standard. + Courtesy of Scott Snyder, the driver now supports ATAPI cdrom drives such as the NEC-260 and the new MITSUMI triple/quad speed drives. Such drives will be identified at boot time, as hda,hdb,hdc or hdd, diff --git a/drivers/block/ide.c b/drivers/block/ide.c index 1983887ce3d6..32dc8fe23bd1 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide.c Version 3.11 January 25, 1995 + * linux/drivers/block/ide.c Version 3.12 February 19, 1995 * * Copyright (C) 1994, 1995 Linus Torvalds & authors (see below) */ @@ -101,6 +101,8 @@ * fix byte-ordering for some NEC cdrom drives * Version 3.10 disable multiple mode by default; was causing trouble * Version 3.11 fix mis-identification of old WD disks as cdroms + * Version 3,12 simplify logic for selecting initial mult_count + * (fixes problems with buggy WD drives) * * To do: * - special 32-bit controller-type detection & support @@ -136,8 +138,7 @@ #include #undef REALLY_FAST_IO /* define if ide ports are perfect */ -#define INITIAL_MULT_COUNT 0 /* undef to use BIOS setting on entry */ - /* or non-zero to enable block mode */ +#define INITIAL_MULT_COUNT 0 /* use zero to disable block mode */ #ifndef VLB_32BIT_IDE /* 0 for safety, 1 for 32-bit chipset:*/ #define VLB_32BIT_IDE 0 /* Winbond 83759F or OPTi 82C621 */ #endif @@ -903,8 +904,7 @@ static int do_special (ide_dev_t *dev) if (dev->type == disk) { if (dev->id && dev->mult_req > dev->id->max_multsect) dev->mult_req = dev->id->max_multsect; - if (dev->mult_req != dev->mult_count) - ide_cmd(dev,WIN_SETMULT,dev->mult_req,&set_multmode_intr); + ide_cmd(dev,WIN_SETMULT,dev->mult_req,&set_multmode_intr); } else { dev->mult_req = 0; printk("%s: multmode not supported by this device\n", dev->name); @@ -1696,24 +1696,13 @@ static void do_identify (ide_dev_t *dev, byte cmd) dev->select.b.lba ? "LBA, " : "", dev->bios_cyl, dev->bios_head, dev->bios_sect); - /* Keep current multiplemode setting, if any (from DOS/BIOS) */ + dev->mult_count = 0; if (id->max_multsect) { - if ((id->multsect_valid & 1) && id->multsect) - dev->mult_count = id->multsect; /* current setting */ -#ifdef INITIAL_MULT_COUNT dev->mult_req = INITIAL_MULT_COUNT; -#if INITIAL_MULT_COUNT - /* use specified value, or maximum, whichever is less */ - if (INITIAL_MULT_COUNT > id->max_multsect) + if (dev->mult_req > id->max_multsect) dev->mult_req = id->max_multsect; -#endif -#else /* use existing setting from DOS/BIOS: */ - if (dev->mult_count <= id->max_multsect) /* valid? */ - dev->mult_req = dev->mult_count; /* keep it */ -#endif /* INITIAL_MULT_COUNT */ - if (dev->mult_req != dev->mult_count) - dev->special.b.set_multmode = 1; - printk(", Mult=%d/%d", dev->mult_req, id->max_multsect); + dev->special.b.set_multmode = 1; + printk(", MaxMult=%d", id->max_multsect); } printk("\n"); } diff --git a/drivers/net/plip.c b/drivers/net/plip.c index fd331b4b4580..46bd56a7631d 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -171,6 +171,9 @@ struct plip_local { #elif defined(__mc68000__) unsigned char msb; unsigned char lsb; +#elif defined(__sparc__) + unsigned char msb; + unsigned char lsb; #elif defined(__MIPSEL__) unsigned char lsb; unsigned char msb; diff --git a/drivers/scsi/53c7,8xx.c b/drivers/scsi/53c7,8xx.c index 4895b5620376..8698173d6ce3 100644 --- a/drivers/scsi/53c7,8xx.c +++ b/drivers/scsi/53c7,8xx.c @@ -2810,7 +2810,7 @@ static void intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { /* 250ms selection timeout */ if ((((hostdata->chip / 100) == 8) && (sist1 & SIST1_800_STO)) || - (((hostdata->chip / 100) != 8) && sstat0_sist0 && SSTAT0_700_STO)) { + (((hostdata->chip / 100) != 8) && (sstat0_sist0 & SSTAT0_700_STO))) { fatal = 1; if (hostdata->options & OPTION_DEBUG_INTR) { printk ("scsi%d : Selection Timeout\n", host->host_no); diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index d6b5337eb71a..eb7ba3789420 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -387,3 +387,20 @@ void scsi_mem_init(unsigned long memory_end) continue; } } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h index e11fee788e7c..01b5f29c18a0 100644 --- a/drivers/scsi/hosts.h +++ b/drivers/scsi/hosts.h @@ -247,7 +247,7 @@ struct Scsi_Host /* These parameters should be set by the detect routine */ unsigned char *base; - short unsigned int io_port; + unsigned int io_port; unsigned char n_io_port; unsigned char irq; unsigned char dma_channel; @@ -356,3 +356,19 @@ extern void scsi_unregister_module(int, void *); #define SG_EXTRA_DEVS (SD_EXTRA_DEVS + SR_EXTRA_DEVS + ST_EXTRA_DEVS) #endif +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff --git a/drivers/scsi/qlogic.c b/drivers/scsi/qlogic.c index 3755063f6015..605e05e025db 100644 --- a/drivers/scsi/qlogic.c +++ b/drivers/scsi/qlogic.c @@ -18,7 +18,7 @@ Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994 (you can reference it, but it is incomplete and inaccurate in places) - Version 0.39a + Version 0.40a Functions as standalone, loadable, and PCMCIA driver, the latter from Dave Hind's PCMCIA package. @@ -29,14 +29,6 @@ /*----------------------------------------------------------------*/ /* Configuration */ -/* The following option is normally left alone. PCMCIA support needs to - change this to adapt to the different way the interrupt pin works. - - Set the following to 2 to use normal interrupt (active high/totempole- - tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open - drain */ -#define QL_INT_ACTIVE_HIGH 2 - /* Set the following to 1 to enable the use of interrupts. Note that 0 tends to be more stable, but slower (or ties up the system more) */ #define QL_USE_IRQ 1 @@ -51,21 +43,36 @@ without requiring a cold boot. It does take some time to recover from a reset, so it is slower, and I have seen timeouts so that devices weren't recognized when this was set. */ -#define QL_RESET_AT_START 1 +#define QL_RESET_AT_START 0 + +/* crystal frequency in megahertz (for offset 5 and 9) */ +#define XTALFREQ 40 -/* This will set fast (10Mhz) synchronous timing, FASTCLK must also be 1 */ +/*****/ +/* offset 0xc */ +/* This will set fast (10Mhz) synchronous timing when set to 1 + FASTCLK must also be 0 */ #define FASTSCSI 0 -/* This will set a faster sync transfer rate */ +/* This when set to 1 will set a faster sync transfer rate */ #define FASTCLK 0 -/* This bit needs to be set to 1 if your cabling is long or noisy */ +/*****/ +/* config register 1 (offset 8) options */ +/* This needs to be set to 1 if your cabling is long or noisy */ #define SLOWCABLE 0 +/* This should be 1 to enable parity detection */ +#define QL_ENABLE_PARITY 1 + +/*****/ +/* offset 6 */ /* This is the sync transfer divisor, 40Mhz/X will be the data rate The power on default is 5, the maximum normal value is 5 */ #define SYNCXFRPD 4 +/*****/ +/* offset 7 */ /* This is the count of how many synchronous transfers can take place i.e. how many reqs can occur before an ack is given. The maximum value for this is 15, the upper bits can modify @@ -77,15 +84,9 @@ cause the deassertion to be early by 1/2 clock. Bits 5&4 control the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */ -/* PCMCIA option adjustment */ -#ifdef PCMCIA -#undef QL_INT_ACTIVE_HIGH -#define QL_INT_ACTIVE_HIGH 0 -#endif - /*----------------------------------------------------------------*/ - -#ifdef MODULE +#if defined(MODULE) || defined(PCMCIA) +#include #include #endif @@ -103,17 +104,24 @@ /*----------------------------------------------------------------*/ /* driver state info, local to driver */ -static int qbase; /* Port */ +static int qbase = 0; /* Port */ static int qinitid; /* initiator ID */ static int qabort; /* Flag to cause an abort */ -static int qlirq; /* IRQ being used */ +static int qlirq = -1; /* IRQ being used */ static char qinfo[80]; /* description */ static Scsi_Cmnd *qlcmd; /* current command being processed */ +static int qlcfg5 = ( XTALFREQ << 5 ); /* 15625/512 */ +static int qlcfg6 = SYNCXFRPD; +static int qlcfg7 = SYNCOFFST; +static int qlcfg8 = ( SLOWCABLE << 7 ) | ( QL_ENABLE_PARITY << 4 ); +static int qlcfg9 = ( ( XTALFREQ + 4 ) / 5 ); +static int qlcfgc = ( FASTCLK << 3 ) | ( FASTSCSI << 4 ); + /*----------------------------------------------------------------*/ /* The qlogic card uses two register maps - These macros select which one */ #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) -#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd )) +#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb6 , qbase + 0xd )) /* following is watchdog timeout in microseconds */ #define WATCHDOG 5000000 @@ -270,27 +278,15 @@ unsigned long flags; outb(0x40, qbase + 0xb); /* enable features */ /* configurables */ -#if FASTSCSI -#if FASTCLK - outb(0x18, qbase + 0xc); -#else - outb(0x10, qbase + 0xc); -#endif -#else -#if FASTCLK - outb(8, qbase + 0xc); -#endif -#endif - -#if SLOWCABLE - outb(0xd0 | qinitid, qbase + 8); /* (initiator) bus id */ -#else - outb(0x50 | qinitid, qbase + 8); /* (initiator) bus id */ -#endif - outb( SYNCOFFST , qbase + 7 ); - outb( SYNCXFRPD , qbase + 6 ); + outb( qlcfgc , qbase + 0xc); +/* config: no reset interrupt, (initiator) bus id */ + outb( 0x40 | qlcfg8 | qinitid, qbase + 8); + outb( qlcfg7 , qbase + 7 ); + outb( qlcfg6 , qbase + 6 ); /**/ - outb(0x99, qbase + 5); /* timer */ + outb(qlcfg5, qbase + 5); /* select timer */ + outb(qlcfg9 & 7, qbase + 9); /* prescaler */ +/* outb(0x99, qbase + 5); */ outb(cmd->target, qbase + 4); for (i = 0; i < cmd->cmd_len; i++) @@ -482,6 +478,17 @@ int qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) } #endif +#ifdef PCMCIA +/*----------------------------------------------------------------*/ +/* allow PCMCIA code to preset the port */ +/* port should be 0 and irq to -1 respectively for autoprobing */ +void qlogic_preset(int port, int irq) +{ + qbase=port; + qlirq=irq; +} +#endif + /*----------------------------------------------------------------*/ /* look for qlogic card and init if found */ int qlogic_detect(Scsi_Host_Template * host) @@ -499,16 +506,20 @@ unsigned long flags; card, but I haven't tested this. */ - for (qbase = 0x230; qbase < 0x430; qbase += 0x100) { - if( check_region( qbase , 0x10 ) ) - continue; - REG1; - if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) - && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) ) - break; + if( !qbase ) { + for (qbase = 0x230; qbase < 0x430; qbase += 0x100) { + if( check_region( qbase , 0x10 ) ) + continue; + REG1; + if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) + && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) ) + break; + } + if (qbase == 0x430) + return 0; } - if (qbase == 0x430) - return 0; + else + printk( "Ql: Using preset base address of %03x\n", qbase ); qltyp = inb(qbase + 0xe) & 0xf8; qinitid = host->this_id; @@ -516,8 +527,9 @@ unsigned long flags; qinitid = 7; /* if no ID, use 7 */ outb(1, qbase + 8); /* set for PIO pseudo DMA */ REG0; - outb(0xd0 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */ - outb(0x99, qbase + 5); /* select timer */ + outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */ + outb(qlcfg5, qbase + 5); /* select timer */ + outb(qlcfg9, qbase + 9); /* prescaler */ qlirq = -1; #if QL_RESET_AT_START outb( 3 , qbase + 3 ); @@ -527,27 +539,31 @@ unsigned long flags; #endif #if QL_USE_IRQ /* IRQ probe - toggle pin and check request pending */ - save_flags( flags ); - cli(); - i = 0xffff; - j = 3; - outb(0x90, qbase + 3); /* illegal command - cause interrupt */ - REG1; - outb(10, 0x20); /* access pending interrupt map */ - outb(10, 0xa0); - while (j--) { - outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin off */ - i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */ - outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin on */ - i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */ + if( qlirq == -1 ) { + save_flags( flags ); + cli(); + i = 0xffff; + j = 3; + outb(0x90, qbase + 3); /* illegal command - cause interrupt */ + REG1; + outb(10, 0x20); /* access pending interrupt map */ + outb(10, 0xa0); + while (j--) { + outb(0xb2 , qbase + 0xd); /* int pin off */ + i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */ + outb(0xb6 , qbase + 0xd); /* int pin on */ + i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */ + } + REG0; + while (inb(qbase + 5)); /* purge int */ + while (i) /* find on bit */ + i >>= 1, qlirq++; /* should check for exactly 1 on */ + if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic")) + host->can_queue = 1; + restore_flags( flags ); } - REG0; - while (inb(qbase + 5)); /* purge int */ - while (i) /* find on bit */ - i >>= 1, qlirq++; /* should check for exactly 1 on */ - if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic")) - host->can_queue = 1; - restore_flags( flags ); + else + printk( "Ql: Using preset IRQ of %d\n", qlirq ); #endif request_region( qbase , 0x10 ,"qlogic"); hreg = scsi_register( host , 0 ); /* no host data */ @@ -557,8 +573,8 @@ unsigned long flags; if( qlirq != -1 ) hreg->irq = qlirq; - sprintf(qinfo, "Qlogic Driver version 0.39a, chip %02X at %03X, IRQ %d, Opts:%d%d", - qltyp, qbase, qlirq, QL_INT_ACTIVE_HIGH, QL_TURBO_PDMA ); + sprintf(qinfo, "Qlogic Driver version 0.40a, chip %02X at %03X, IRQ %d, TPdma:%d", + qltyp, qbase, qlirq, QL_TURBO_PDMA ); host->name = qinfo; return 1; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 3b944ff49d70..a54d8b790df2 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -32,6 +32,8 @@ #include "hosts.h" #include "constants.h" +#undef USE_STATIC_SCSI_MEMORY + /* static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/scsi.c,v 1.5 1993/09/24 12:45:18 drew Exp drew $"; */ @@ -148,6 +150,7 @@ static struct blist blacklist[] = {"CHINON","CD-ROM CDS-431","H42"}, /* Locks up if polled for lun != 0 */ {"CHINON","CD-ROM CDS-535","Q14"}, /* Lockup if polled for lun != 0 */ {"DENON","DRD-25X","V"}, /* A cdrom that locks up when probed at lun != 0 */ + {"HITACHI","DK312C","CM81"}, /* Responds to all lun - dtg */ {"HITACHI","DK314C","CR21" }, /* responds to all lun */ {"IMS", "CDD521/10","2.06"}, /* Locks-up when LUN>0 polled. */ {"MAXTOR","XT-3280","PR02"}, /* Locks-up when LUN>0 polled. */ @@ -190,8 +193,8 @@ static int blacklisted(unsigned char * response_data){ if(memcmp(blacklist[i].model, pnt, strlen(blacklist[i].model))) continue; return 1; - }; -}; + } +} /* * As the actual SCSI command runs in the background, we must set up a @@ -305,43 +308,39 @@ void scan_scsis (struct Scsi_Host * shpnt) unsigned char * scsi_result; Scsi_Device * SDpnt, *SDtail; struct Scsi_Device_Template * sdtpnt; - Scsi_Cmnd SCmd; + Scsi_Cmnd *SCpnt; - memset(&SCmd, 0, sizeof(SCmd)); ++in_scan_scsis; lun = 0; type = -1; - SCmd.next = NULL; - SCmd.prev = NULL; + SCpnt = (Scsi_Cmnd *) scsi_init_malloc(sizeof(Scsi_Cmnd), GFP_ATOMIC|GFP_DMA); SDpnt = (Scsi_Device *) scsi_init_malloc(sizeof (Scsi_Device), GFP_ATOMIC); - SCmd.device = SDpnt; /* This was really needed! (DB) */ - memset(SDpnt, 0, sizeof(Scsi_Device)); SDtail = scsi_devices; - if(scsi_devices) { - while(SDtail->next) SDtail = SDtail->next; - } + + if(scsi_devices) while(SDtail->next) SDtail = SDtail->next; /* Make sure we have something that is valid for DMA purposes */ scsi_result = ((current == task[0] || !shpnt->unchecked_isa_dma) ? &scsi_result0[0] : scsi_malloc(512)); - shpnt->host_queue = &SCmd; /* We need this so that - commands can time out */ + shpnt->host_queue = SCpnt; /* We need this so that commands can time out */ + for (dev = 0; dev < 8; ++dev) if (shpnt->this_id != dev) + /* * We need the for so our continue, etc. work fine. */ - for (lun = 0; lun < max_scsi_luns; ++lun) { + memset(SDpnt, 0, sizeof(Scsi_Device)); SDpnt->host = shpnt; SDpnt->id = dev; SDpnt->lun = lun; - SDpnt->device_wait = NULL; - SDpnt->next = NULL; - SDpnt->attached = 0; + + /* Some low level driver could use device->type (DB) */ + SDpnt->type = -1; /* * Assume that the device will have handshaking problems, and then * fix this field later if it turns out it doesn't. @@ -350,59 +349,55 @@ void scan_scsis (struct Scsi_Host * shpnt) scsi_cmd[0] = TEST_UNIT_READY; scsi_cmd[1] = lun << 5; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = 0; - - SCmd.host = shpnt; - SCmd.target = dev; - SCmd.lun = lun; - - SCmd.request.sem = NULL; /* Used for mutex if loading devices after boot */ - SCmd.request.dev = 0xffff; /* Mark not busy */ - SCmd.use_sg = 0; - SCmd.cmd_len = 0; - SCmd.old_use_sg = 0; - SCmd.transfersize = 0; - SCmd.underflow = 0; - - scsi_do_cmd (&SCmd, - (void *) scsi_cmd, (void *) - scsi_result, 256, scan_scsis_done, - SCSI_TIMEOUT + 400, 5); - - /* Wait for command to finish. Use simple wait if we are booting, else + scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = 0; + + memset(SCpnt, 0, sizeof(Scsi_Cmnd)); + SCpnt->host = SDpnt->host; + SCpnt->device = SDpnt; + SCpnt->target = SDpnt->id; + SCpnt->lun = SDpnt->lun; + + /* Used for mutex if loading devices after boot */ + SCpnt->request.sem = NULL; + + SCpnt->request.dev = 0xffff; /* Mark not busy */ + + scsi_do_cmd (SCpnt, (void *) scsi_cmd, (void *) scsi_result, + 256, scan_scsis_done, SCSI_TIMEOUT + 400, 5); + + /* Wait for command to finish. Use simple wait if we are booting, else do it right and use a mutex */ - if (current == task[0]){ - while (SCmd.request.dev != 0xfffe); - } else { - if (SCmd.request.dev != 0xfffe){ + if (current == task[0]) + while (SCpnt->request.dev != 0xfffe); + else if (SCpnt->request.dev != 0xfffe) { struct semaphore sem = MUTEX_LOCKED; - SCmd.request.sem = &sem; + + SCpnt->request.sem = &sem; down(&sem); + /* Hmm.. Have to ask about this one */ - while (SCmd.request.dev != 0xfffe) schedule(); - } - } + while (SCpnt->request.dev != 0xfffe) schedule(); + } #if defined(DEBUG) || defined(DEBUG_INIT) printk("scsi: scan SCSIS id %d lun %d\n", dev, lun); - printk("scsi: return code %08x\n", SCmd.result); + printk("scsi: return code %08x\n", SCpnt->result); #endif - if(SCmd.result) { - if ((driver_byte(SCmd.result) & DRIVER_SENSE) && - ((SCmd.sense_buffer[0] & 0x70) >> 4) == 7) { - if (SCmd.sense_buffer[2] &0xe0) + if(SCpnt->result) { + if ((driver_byte(SCpnt->result) & DRIVER_SENSE) && + ((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) { + if (SCpnt->sense_buffer[2] &0xe0) continue; /* No devices here... */ - if(((SCmd.sense_buffer[2] & 0xf) != NOT_READY) && - ((SCmd.sense_buffer[2] & 0xf) != UNIT_ATTENTION)) + if(((SCpnt->sense_buffer[2] & 0xf) != NOT_READY) && + ((SCpnt->sense_buffer[2] & 0xf) != UNIT_ATTENTION)) continue; } else break; - }; + } #if defined (DEBUG) || defined(DEBUG_INIT) printk("scsi: performing INQUIRY\n"); @@ -411,7 +406,6 @@ void scan_scsis (struct Scsi_Host * shpnt) /* * Build an INQUIRY command block. */ - scsi_cmd[0] = INQUIRY; scsi_cmd[1] = (lun << 5) & 0xe0; scsi_cmd[2] = 0; @@ -419,27 +413,25 @@ void scan_scsis (struct Scsi_Host * shpnt) scsi_cmd[4] = 255; scsi_cmd[5] = 0; - SCmd.request.dev = 0xffff; /* Mark not busy */ - SCmd.cmd_len = 0; + SCpnt->request.dev = 0xffff; /* Mark not busy */ + SCpnt->cmd_len = 0; - scsi_do_cmd (&SCmd, - (void *) scsi_cmd, (void *) - scsi_result, 256, scan_scsis_done, - SCSI_TIMEOUT, 3); + scsi_do_cmd (SCpnt, (void *) scsi_cmd, (void *) scsi_result, + 256, scan_scsis_done, SCSI_TIMEOUT, 3); - if (current == task[0]){ - while (SCmd.request.dev != 0xfffe); - } else { - if (SCmd.request.dev != 0xfffe){ + if (current == task[0]) + while (SCpnt->request.dev != 0xfffe); + else if (SCpnt->request.dev != 0xfffe) { struct semaphore sem = MUTEX_LOCKED; - SCmd.request.sem = &sem; + + SCpnt->request.sem = &sem; down(&sem); + /* Hmm.. Have to ask about this one */ - while (SCmd.request.dev != 0xfffe) schedule(); - } - } + while (SCpnt->request.dev != 0xfffe) schedule(); + } - the_result = SCmd.result; + the_result = SCpnt->result; #if defined(DEBUG) || defined(DEBUG_INIT) if (!the_result) @@ -578,25 +570,24 @@ void scan_scsis (struct Scsi_Host * shpnt) scsi_cmd[4] = 0x2a; scsi_cmd[5] = 0; - SCmd.request.dev = 0xffff; /* Mark not busy */ - SCmd.cmd_len = 0; + SCpnt->request.dev = 0xffff; /* Mark not busy */ + SCpnt->cmd_len = 0; - scsi_do_cmd (&SCmd, - (void *) scsi_cmd, (void *) - scsi_result, 0x2a, scan_scsis_done, + scsi_do_cmd (SCpnt, (void *) scsi_cmd, + (void *) scsi_result, 0x2a, scan_scsis_done, SCSI_TIMEOUT, 3); - if (current == task[0]){ - while (SCmd.request.dev != 0xfffe); - } else { - if (SCmd.request.dev != 0xfffe){ + if (current == task[0]) + while (SCpnt->request.dev != 0xfffe); + else if (SCpnt->request.dev != 0xfffe) { struct semaphore sem = MUTEX_LOCKED; - SCmd.request.sem = &sem; + + SCpnt->request.sem = &sem; down(&sem); + /* Hmm.. Have to ask about this one */ - while (SCmd.request.dev != 0xfffe) schedule(); - } - } + while (SCpnt->request.dev != 0xfffe) schedule(); + } } /* Add this device to the linked list at the end */ if(SDtail) @@ -619,11 +610,14 @@ void scan_scsis (struct Scsi_Host * shpnt) } } /* if result == DID_OK ends */ } /* for lun ends */ + shpnt->host_queue = NULL; /* No longer needed here */ /* Last device block does not exist. Free memory. */ scsi_init_free((char *) SDpnt, sizeof(Scsi_Device)); + scsi_init_free((char *) SCpnt, sizeof(Scsi_Cmnd)); + /* If we allocated a buffer so we could do DMA, free it now */ if (scsi_result != &scsi_result0[0]) scsi_free(scsi_result, 512); @@ -703,7 +697,7 @@ Scsi_Cmnd * request_queueable (struct request * req, Scsi_Device * device) SCpnt->lun == device->lun) if(SCpnt->request.dev < 0) break; SCpnt = SCpnt->next; - }; + } if (!SCpnt) return NULL; @@ -723,7 +717,7 @@ Scsi_Cmnd * request_queueable (struct request * req, Scsi_Device * device) req->sector += bh->b_size >> 9; if(!tablesize) break; bh = bhp; - }; + } if(req->nr_sectors && bh && bh->b_reqnext){ /* Any leftovers? */ SCpnt->request.bhtail = bh; req->bh = bh->b_reqnext; /* Divide request */ @@ -738,11 +732,11 @@ Scsi_Cmnd * request_queueable (struct request * req, Scsi_Device * device) } else { req->dev = -1; wake_up(&wait_for_request); - }; + } } else { SCpnt->request.dev = 0xffff; /* Busy, but no request */ SCpnt->request.sem = NULL; /* And no one is waiting for the device either */ - }; + } SCpnt->use_sg = 0; /* Reset the scatter-gather flag */ SCpnt->old_use_sg = 0; @@ -792,16 +786,16 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device, SCpnt->lun == device->lun) { SCwait = SCpnt; if(SCpnt->request.dev < 0) break; - }; + } SCpnt = SCpnt->next; - }; + } save_flags(flags); cli(); /* See if this request has already been queued by an interrupt routine */ if (req && ((req->dev < 0) || (req->dev != dev))) { restore_flags(flags); return NULL; - }; + } if (!SCpnt || SCpnt->request.dev >= 0) /* Might have changed */ { restore_flags(flags); @@ -810,7 +804,7 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device, printk("Attempt to allocate device target %d, lun %d\n", device->id ,device->lun); panic("No device found in allocate_device\n"); - }; + } SCSI_SLEEP(&device->device_wait, (SCwait->request.dev > 0)); } else { @@ -828,7 +822,7 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device, req->sector += bh->b_size >> 9; if(!tablesize) break; bh = bhp; - }; + } if(req->nr_sectors && bh && bh->b_reqnext){ /* Any leftovers? */ SCpnt->request.bhtail = bh; req->bh = bh->b_reqnext; /* Divide request */ @@ -845,15 +839,15 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device, req->dev = -1; *reqp = req->next; wake_up(&wait_for_request); - }; + } } else { SCpnt->request.dev = 0xffff; /* Busy */ SCpnt->request.sem = NULL; /* And no one is waiting for this to complete */ - }; + } restore_flags(flags); break; - }; - }; + } + } SCpnt->use_sg = 0; /* Reset the scatter-gather flag */ SCpnt->old_use_sg = 0; @@ -935,7 +929,7 @@ update_timeout(SCpnt, SCpnt->timeout_per_command); #ifdef DEBUG_DELAY clock = jiffies + 400; while (jiffies < clock); - printk("done(host = %d, result = %04x) : routine at %08x\n", host->host_no, temp, done); + printk("done(host = %d, result = %04x) : routine at %08x\n", host->host_no, temp); #endif scsi_done(SCpnt); } @@ -995,7 +989,7 @@ void scsi_do_cmd (Scsi_Cmnd * SCpnt, const void *cmnd , for (i = 0; i < 10; ++i) printk ("%02x ", ((unsigned char *) cmnd)[i]); printk("\n"); - }; + } #endif if (!host) @@ -1096,7 +1090,7 @@ static void reset (Scsi_Cmnd * SCpnt) if(SCpnt->flags & NEEDS_JUMPSTART) { SCpnt->flags &= ~NEEDS_JUMPSTART; scsi_request_sense (SCpnt); - }; + } #endif } @@ -1472,7 +1466,7 @@ static void scsi_done (Scsi_Cmnd * SCpnt) SCpnt->use_sg = SCpnt->old_use_sg; SCpnt->cmd_len = SCpnt->old_cmd_len; internal_cmnd (SCpnt); - }; + } break; default: INTERNAL_ERROR; @@ -1665,7 +1659,7 @@ int scsi_reset (Scsi_Cmnd * SCpnt) SCpnt1->flags |= IS_RESETTING; } SCpnt1 = SCpnt1->next; - }; + } host->last_reset = jiffies; temp = host->hostt->reset(SCpnt); @@ -1755,7 +1749,7 @@ static void scsi_main_timeout(void) save_flags(flags); cli(); } - }; + } } while (timed_out); restore_flags(flags); } @@ -1796,7 +1790,7 @@ static int update_timeout(Scsi_Cmnd * SCset, int timeout) if(SCset){ oldto = SCset->timeout - used; SCset->timeout = timeout + used; - }; + } least = 0xffffffff; @@ -1807,7 +1801,7 @@ static int update_timeout(Scsi_Cmnd * SCset, int timeout) if(SCpnt->timeout <= 0) SCpnt->timeout = -1; if(SCpnt->timeout > 0 && SCpnt->timeout < least) least = SCpnt->timeout; - }; + } /* If something is due to timeout again, then we will set the next timeout @@ -1864,8 +1858,8 @@ void *scsi_malloc(unsigned int len) printk("SMalloc: %d %x ",len, dma_malloc_pages[i] + (j << 9)); #endif return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9)); - }; - }; + } + } restore_flags(flags); return NULL; /* Nope. No more */ } @@ -1923,7 +1917,9 @@ int scsi_loadable_module_flag; /* Set after we scan builtin drivers */ void * scsi_init_malloc(unsigned int size, int priority) { unsigned long retval; -#if 0 /* Use the statically allocated memory instead of kmalloc (DB) */ + +/* Use the statically allocated memory instead of kmalloc (DB) */ +#if defined(USE_STATIC_SCSI_MEMORY) if(scsi_loadable_module_flag && !(priority & GFP_DMA)) #else if(scsi_loadable_module_flag) @@ -1946,6 +1942,7 @@ void * scsi_init_malloc(unsigned int size, int priority) scsi_init_memory_start += size; } } + memset((void *) retval, 0, size); return (void *) retval; } @@ -2035,9 +2032,9 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end SCpnt->next = host->host_queue; SCpnt->prev = NULL; host->host_queue = SCpnt; - }; - }; - }; + } + } + } if (scsi_devicelist) dma_sectors = 16; /* Base value we use */ @@ -2061,8 +2058,8 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize * host->cmd_per_lun; need_isa_buffer++; - }; - }; + } + } dma_sectors = (dma_sectors + 15) & 0xfff0; dma_free_sectors = dma_sectors; /* This must be a multiple of 16 */ @@ -2088,15 +2085,16 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end scsi_loadable_module_flag = 1; -#if 0 /* This allocates statically some extra memory to be used for modules, - until the kmalloc problem is fixed (DB) */ - - scsi_memory_upper_value = scsi_init_memory_start + - 2 * (scsi_init_memory_start - scsi_memory_lower_value); - printk ("scsi memory: lower %p, upper %p.\n", - (void *)scsi_memory_lower_value, (void *)scsi_memory_upper_value); +/* This allocates statically some extra memory to be used for modules, + until the kmalloc problem is fixed (DB) */ +#if defined(USE_STATIC_SCSI_MEMORY) + scsi_memory_upper_value = scsi_init_memory_start + 256 * 1024; + printk ("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n", + (scsi_memory_upper_value - scsi_memory_lower_value) / 1024, + (scsi_init_memory_start - scsi_memory_lower_value) / 1024, + (scsi_memory_upper_value - scsi_init_memory_start) / 1024); return scsi_memory_upper_value; #else return scsi_init_memory_start; @@ -2234,8 +2232,8 @@ static int scsi_register_host(Scsi_Host_Template * tpnt) host->host_queue = SCpnt; if(host->host_queue) host->host_queue->prev = SCpnt; - }; - }; + } + } } /* Next, check to see if we need to extend the DMA buffer pool */ { @@ -2261,8 +2259,8 @@ static int scsi_register_host(Scsi_Host_Template * tpnt) new_dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize * host->cmd_per_lun; new_need_isa_buffer++; - }; - }; + } + } new_dma_sectors = (new_dma_sectors + 15) & 0xfff0; @@ -2303,6 +2301,14 @@ static int scsi_register_host(Scsi_Host_Template * tpnt) if(sdtpnt->finish && sdtpnt->nr_dev) (*sdtpnt->finish)(); } + +#if defined(USE_STATIC_SCSI_MEMORY) + printk ("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n", + (scsi_memory_upper_value - scsi_memory_lower_value) / 1024, + (scsi_init_memory_start - scsi_memory_lower_value) / 1024, + (scsi_memory_upper_value - scsi_init_memory_start) / 1024); +#endif + return 0; } @@ -2325,7 +2331,7 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt) for(sdpnt = scsi_devices; sdpnt; sdpnt = sdpnt->next) if(sdpnt->host->hostt == tpnt && sdpnt->host->hostt->usage_count - && *sdpnt->host->hostt->usage_count) return; + && *sdpnt->host->hostt->usage_count) return; for(shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { @@ -2342,6 +2348,7 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt) return; } SCpnt->request.dev = 0xffe0; /* Mark as busy */ + restore_flags(flags); } } /* Next we detach the high level drivers from the Scsi_Device structures */ @@ -2414,6 +2421,13 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt) printk ("scsi : %d host%s.\n", next_scsi_host, (next_scsi_host == 1) ? "" : "s"); +#if defined(USE_STATIC_SCSI_MEMORY) + printk ("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n", + (scsi_memory_upper_value - scsi_memory_lower_value) / 1024, + (scsi_init_memory_start - scsi_memory_lower_value) / 1024, + (scsi_memory_upper_value - scsi_init_memory_start) / 1024); +#endif + scsi_make_blocked_list(); /* There were some hosts that were loaded at boot time, so we cannot @@ -2500,7 +2514,7 @@ scsi_dump_status(void) SCpnt->cmnd[0], SCpnt->sense_buffer[2], SCpnt->result); - }; + } printk("wait_for_request = %p\n", wait_for_request); /* Now dump the request lists for each block device */ printk("Dump of pending block device requests\n"); @@ -2523,3 +2537,20 @@ scsi_dump_status(void) } } #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h index e66df3ee4706..8a6f5cfeb12b 100644 --- a/drivers/scsi/scsi.h +++ b/drivers/scsi/scsi.h @@ -622,3 +622,20 @@ static Scsi_Cmnd * end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors }; } #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 0619340aff46..92f3eef3ece4 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -311,3 +311,20 @@ int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) { set_fs(oldfs); return tmp; } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index f43443862f11..17926231d342 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -384,7 +384,15 @@ static void do_sd_request (void) SCpnt = allocate_device(&CURRENT, rscsi_disks[DEVICE_NR(MINOR(CURRENT->dev))].device, 0); else SCpnt = NULL; + + /* + * The following restore_flags leads to latency problems. FIXME. + */ +#if 0 restore_flags(flags); +#else + sti(); +#endif /* This is a performance enhancement. We dig down into the request list and try and find a queueable request (i.e. device not busy, and host able to @@ -1273,3 +1281,20 @@ static void sd_detach(Scsi_Device * SDp) } return; } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff --git a/drivers/scsi/sd_ioctl.c b/drivers/scsi/sd_ioctl.c index 8c18d08430fa..5ca3f63e91f1 100644 --- a/drivers/scsi/sd_ioctl.c +++ b/drivers/scsi/sd_ioctl.c @@ -73,3 +73,19 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device , cmd, (void *) arg); } } +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index b8f62aea53ec..ded4192b4022 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c @@ -347,7 +347,8 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt) */ instance = scsi_register(tpnt, 0); hostno = instance->host_no; - if (request_irq((int) irq, seagate_reconnect_intr, SA_INTERRUPT, "seagate")) { + if (request_irq((int) irq, seagate_reconnect_intr, SA_INTERRUPT, + (controller_type == SEAGATE) ? "seagate" : "tmc-8xx")) { printk("scsi%d : unable to allocate IRQ%d\n", hostno, (int) irq); return 0; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 20712a9189df..9224533c1692 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -422,3 +422,20 @@ static void sg_detach(Scsi_Device * SDp) } return; } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index ab0f8e3dbd93..4814b93da8a7 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -305,8 +305,15 @@ static void sr_photocd(struct inode *inode) unsigned char *cmd; /* the scsi-command */ unsigned char *send; /* the data we send to the drive ... */ unsigned char *rec; /* ... and get back */ - int rc,is_xa; + int rc,is_xa,no_multi; + if (scsi_CDs[MINOR(inode->i_rdev)].xa_flags & 0x02) { +#ifdef DEBUG + printk("sr_photocd: drive does not support multisession CD's"); +#endif + return; + } + if (!suser()) { /* I'm not the superuser, so SCSI_IOCTL_SEND_COMMAND isn't allowed for me. * That's why mpcd_sector will be initialized with zero, because I'm not @@ -314,12 +321,18 @@ static void sr_photocd(struct inode *inode) * no disk change happened since the last call of this function and we can * keep the old value. */ - if (1 == scsi_CDs[MINOR(inode->i_rdev)].device->access_count) + if (1 == scsi_CDs[MINOR(inode->i_rdev)].device->access_count) { scsi_CDs[MINOR(inode->i_rdev)].mpcd_sector = 0; + scsi_CDs[MINOR(inode->i_rdev)].xa_flags &= ~0x01; + } return; } + sector = 0; + is_xa = 0; + no_multi = 0; cmd = rec = &buf[8]; + switch(scsi_CDs[MINOR(inode->i_rdev)].device->manufacturer) { case SCSI_MAN_NEC: @@ -336,22 +349,23 @@ static void sr_photocd(struct inode *inode) SCSI_IOCTL_SEND_COMMAND, buf); if (rc != 0) { printk("sr_photocd: ioctl error (NEC): 0x%x\n",rc); - sector = 0; - is_xa = 0; - } else { - min = (unsigned long) rec[15]/16*10 + (unsigned long) rec[15]%16; - sec = (unsigned long) rec[16]/16*10 + (unsigned long) rec[16]%16; - frame = (unsigned long) rec[17]/16*10 + (unsigned long) rec[17]%16; - /* if rec[14] isn't 0xb0, the drive does not support multisession CD's, use zero */ - sector = (0xb0 == rec[14]) ? min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame : 0; - is_xa = (rec[14] == 0xb0); + break; + } + if (rec[14] != 0 && rec[14] != 0xb0) { + printk("sr_photocd: Hmm, seems the CDROM does'nt support multisession CD's\n"); + no_multi = 1; + break; + } + min = (unsigned long) rec[15]/16*10 + (unsigned long) rec[15]%16; + sec = (unsigned long) rec[16]/16*10 + (unsigned long) rec[16]%16; + frame = (unsigned long) rec[17]/16*10 + (unsigned long) rec[17]%16; + sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame; + is_xa = (rec[14] == 0xb0); #ifdef DEBUG - printk("NEC: (%2x) %2li:%02li:%02li = %li\n",buf[8+14],min,sec,frame,sector); - if (sector) { - printk("sr_photocd: multisession CD detected. start: %lu\n",sector); - } -#endif + if (sector) { + printk("sr_photocd: multisession CD detected. start: %lu\n",sector); } +#endif break; case SCSI_MAN_TOSHIBA: @@ -369,15 +383,22 @@ static void sr_photocd(struct inode *inode) rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, SCSI_IOCTL_SEND_COMMAND, buf); if (rc != 0) { - printk("sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc); - sector = 0; - is_xa = 0; + if (rc == 0x28000002) { + /* Got a "not ready" - error. No chance to find out if this is + becauce there is no CD in the drive or becauce the drive + don't knows multisession CD's. So I need to do an extra check... */ + if (kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, + SCSI_IOCTL_TEST_UNIT_READY, NULL)) { + printk("sr_photocd: drive not ready\n"); + } else { + printk("sr_photocd: Hmm, seems the CDROM does'nt support multisession CD's\n"); + no_multi = 1; + } + } else + printk("sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc); break; /* if the first ioctl fails, we don't call the second one */ } is_xa = (rec[0] == 0x20); -#ifdef DEBUG - printk("sr_photocd: TOSHIBA %x\n",rec[0]); -#endif min = (unsigned long) rec[1]/16*10 + (unsigned long) rec[1]%16; sec = (unsigned long) rec[2]/16*10 + (unsigned long) rec[2]%16; frame = (unsigned long) rec[3]/16*10 + (unsigned long) rec[3]%16; @@ -436,12 +457,15 @@ static void sr_photocd(struct inode *inode) #ifdef DEBUG printk("sr_photocd: unknown drive, no special multisession code\n"); #endif - sector = 0; - is_xa = 0; break; } scsi_CDs[MINOR(inode->i_rdev)].mpcd_sector = sector; - scsi_CDs[MINOR(inode->i_rdev)].is_xa = is_xa; + if (is_xa) + scsi_CDs[MINOR(inode->i_rdev)].xa_flags |= 0x01; + else + scsi_CDs[MINOR(inode->i_rdev)].xa_flags &= ~0x01; + if (no_multi) + scsi_CDs[MINOR(inode->i_rdev)].xa_flags |= 0x02; return; } @@ -1045,3 +1069,20 @@ static void sr_detach(Scsi_Device * SDp) } return; } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h index 6200e0fb1a85..ef7d88328587 100644 --- a/drivers/scsi/sr.h +++ b/drivers/scsi/sr.h @@ -25,7 +25,7 @@ typedef struct unsigned sector_size; /* size in bytes */ Scsi_Device *device; unsigned long mpcd_sector; /* for reading multisession-CD's */ - char is_xa; /* is it an XA-CD ? */ + char xa_flags; /* some flags for handling XA-CD's */ unsigned char sector_bit_size; /* sector size = 2^sector_bit_size */ unsigned char sector_bit_shift; /* sectors/FS block = 2^sector_bit_shift*/ unsigned needs_sector_size:1; /* needs to get sector size */ diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 463d2d87d4c5..a5839a2b1182 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -409,7 +409,7 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne ms_info.addr.lba=scsi_CDs[target].mpcd_sector; else return (-EINVAL); - ms_info.xa_flag=scsi_CDs[target].is_xa; + ms_info.xa_flag=scsi_CDs[target].xa_flags & 0x01; err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession)); @@ -430,3 +430,20 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg); } } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index a0848e094b89..e5fb3df35267 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -11,7 +11,7 @@ Copyright 1992, 1993, 1994, 1995 Kai Makisara email Kai.Makisara@metla.fi - Last modified: Mon Jan 30 23:20:07 1995 by root@kai.home + Last modified: Sat Feb 18 10:51:25 1995 by root@kai.home */ #include @@ -74,6 +74,7 @@ static int debugging = 1; #endif #define MAX_RETRIES 0 +#define MAX_WRITE_RETRIES 0 #define MAX_READY_RETRIES 5 #define NO_TAPE NOT_READY @@ -110,10 +111,10 @@ st_chk_result(Scsi_Cmnd * SCpnt) { int dev = SCpnt->request.dev; int result = SCpnt->result; - unsigned char * sense = SCpnt->sense_buffer; + unsigned char * sense = SCpnt->sense_buffer, scode; char *stp; - if (!result && SCpnt->sense_buffer[0] == 0) + if (!result /* && SCpnt->sense_buffer[0] == 0 */ ) return 0; #ifdef DEBUG if (debugging) { @@ -123,13 +124,25 @@ st_chk_result(Scsi_Cmnd * SCpnt) SCpnt->request_bufflen); if (driver_byte(result) & DRIVER_SENSE) print_sense("st", SCpnt); - } + } else #endif -/* if ((sense[0] & 0x70) == 0x70 && - ((sense[2] & 0x80) )) - return 0; */ + scode = sense[2] & 0x0f; + if (!(driver_byte(result) & DRIVER_SENSE) || + ((sense[0] & 0x70) == 0x70 && + scode != NO_SENSE && + scode != RECOVERED_ERROR && + scode != UNIT_ATTENTION && + scode != BLANK_CHECK && + scode != VOLUME_OVERFLOW)) { /* Abnormal conditions for tape */ + printk("st%d: Error %x. ", dev, result); + if (driver_byte(result) & DRIVER_SENSE) + print_sense("st", SCpnt); + else + printk("\n"); + } + if ((sense[0] & 0x70) == 0x70 && - sense[2] == RECOVERED_ERROR + scode == RECOVERED_ERROR #ifdef ST_RECOVERED_WRITE_FATAL && SCpnt->cmnd[0] != WRITE_6 && SCpnt->cmnd[0] != WRITE_FILEMARKS @@ -312,7 +325,7 @@ flush_write_buffer(int dev) SCpnt->request.dev = dev; scsi_do_cmd (SCpnt, (void *) cmd, (STp->buffer)->b_data, transfer, - st_sleep_done, ST_TIMEOUT, MAX_RETRIES); + st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) ); @@ -472,7 +485,6 @@ scsi_tape_open(struct inode * inode, struct file * filp) printk("st%d: No tape.\n", dev); STp->ready = ST_NO_TAPE; } else { - printk("st%d: Error %x.\n", dev, SCpnt->result); (STp->mt_status)->mt_fileno = STp->drv_block = (-1); STp->ready = ST_NOT_READY; } @@ -484,6 +496,8 @@ scsi_tape_open(struct inode * inode, struct file * filp) STp->block_size = 0; STp->eof = ST_NOEOF; (STp->mt_status)->mt_fileno = STp->drv_block = 0; + if (scsi_tapes[dev].device->host->hostt->usage_count) + (*scsi_tapes[dev].device->host->hostt->usage_count)++; return 0; } @@ -637,7 +651,7 @@ scsi_tape_close(struct inode * inode, struct file * filp) SCpnt->request.dev = dev; scsi_do_cmd( SCpnt, (void *) cmd, (void *) (STp->buffer)->b_data, - 0, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); + 0, st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) ); @@ -797,7 +811,7 @@ st_write(struct inode * inode, struct file * filp, char * buf, int count) SCpnt->request.dev = dev; scsi_do_cmd (SCpnt, (void *) cmd, (STp->buffer)->b_data, transfer, - st_sleep_done, ST_TIMEOUT, MAX_RETRIES); + st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) ); @@ -910,7 +924,7 @@ st_write(struct inode * inode, struct file * filp, char * buf, int count) scsi_do_cmd (SCpnt, (void *) cmd, (STp->buffer)->b_data, (STp->buffer)->writing, - st_sleep_done, ST_TIMEOUT, MAX_RETRIES); + st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES); } else SCpnt->request.dev = -1; /* Mark as not busy */ diff --git a/include/asm-sparc/clock.h b/include/asm-sparc/clock.h index 6029236e20d6..ce5ce6762356 100644 --- a/include/asm-sparc/clock.h +++ b/include/asm-sparc/clock.h @@ -46,6 +46,8 @@ struct sparc_clock_info { unsigned char foo[14]; }; +#define TIMER_PHYSADDR 0xf3000000 + /* YUCK YUCK YUCK, grrr... */ #define TIMER_STRUCT ((struct sparc_timer_info *)((struct sparc_clock_info *) TIMER_VADDR)) diff --git a/include/asm-sparc/delay.h b/include/asm-sparc/delay.h index 9976b0d0d4e4..d6c4b360e205 100644 --- a/include/asm-sparc/delay.h +++ b/include/asm-sparc/delay.h @@ -14,7 +14,7 @@ extern __inline__ void __delay(unsigned int loops) { __asm__ __volatile__("\n1:\tcmp %0, 0\n\t" "bne,a 1b\n\t" - "sub %0, 1, %0\n": "=r" (loops) : "0" (loops)); + "sub %0, 1, %0\n": "=&r" (loops) : "0" (loops)); } /* udelay(usecs) is used for very short delays up to 1 millisecond. */ diff --git a/include/asm-sparc/head.h b/include/asm-sparc/head.h index fea569648518..fd909434c764 100644 --- a/include/asm-sparc/head.h +++ b/include/asm-sparc/head.h @@ -22,28 +22,36 @@ /* Generic trap entry. */ #define TRAP_ENTRY(type, label) \ - mov (type), %l3; b label; mov %psr, %l0; nop; + mov (type), %l3; b label; rd %psr, %l0; nop; /* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and * gets handled with another macro. */ #define TRAP_ENTRY_INTERRUPT(int_level) \ - mov int_level, %l4; b trap_entry; mov %psr, %l0; nop; + mov int_level, %l3; b stray_irq_entry; rd %psr, %l0; nop; /* Here is the macro for soft interrupts (ie. not as urgent as hard ones) - which need to jump to a different handler. -*/ + * which need to jump to a different handler. + */ #define TRAP_ENTRY_INTERRUPT_SOFT(int_level, ident) \ - mov int_level, %l4; mov %psr, %l0; b trap_entry; mov ident, %l3; + mov int_level, %l3; rd %psr, %l0; b stray_irq_entry; mov ident, %l4; + +/* The above two macros are for generic traps. The following is made + * especially for timer interrupts at IRQ level 14. + */ + +#define TRAP_ENTRY_TIMER \ + mov 10, %l3; rd %psr, %l0; b sparc_timer; nop; /* Non-maskable interrupt entry macro. You have to turn off all interrupts - to not receive this. This is usually due to a asynchronous memory error. - All we can really do is stop the show. :-( -*/ + * to not receive this. This is usually due to a asynchronous memory error. + * All we can really do is stop the show. :-( + */ + #define TRAP_ENTRY_INTERRUPT_NMI(t_type, jmp_to) \ - mov t_type, %l3; b jmp_to; mov %psr, %l0; nop; + mov t_type, %l3; b jmp_to; rd %psr, %l0; nop; /* Trap entry code in entry.S needs the offsets into task_struct * to get at the thread_struct goodies during window craziness. @@ -53,11 +61,11 @@ * See TRAP_WIN_CLEAN in entry.S for details. */ -#define THREAD_UWINDOWS 0x3a8 -#define THREAD_WIM 0x3ac -#define THREAD_W_SAVED 0x3b0 -#define THREAD_KSP 0x3b4 -#define THREAD_USP 0x3b8 -#define THREAD_REG_WINDOW 0x3c0 +#define THREAD_UWINDOWS 0x3bc +#define THREAD_WIM 0x3c0 +#define THREAD_W_SAVED 0x3c4 +#define THREAD_KSP 0x3c8 +#define THREAD_USP 0x3cc +#define THREAD_REG_WINDOW 0x3d4 #endif __SPARC_HEAD_H diff --git a/include/asm-sparc/io.h b/include/asm-sparc/io.h index 13f93c6b6838..5aa1a3fac8cb 100644 --- a/include/asm-sparc/io.h +++ b/include/asm-sparc/io.h @@ -91,9 +91,9 @@ extern inline void mapioaddr(unsigned long physaddr, unsigned long virt_addr) unsigned long page_entry; page_entry = physaddr >> PAGE_SHIFT; - page_entry |= (PTE_V | PTE_ACC | PTE_W | PTE_P | PTE_IO); /* kernel io addr */ + page_entry |= (PTE_V | PTE_ACC | PTE_NC | PTE_IO); /* kernel io addr */ - put_pte(page_entry, virt_addr); + put_pte(virt_addr, page_entry); return; } diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index b4dbd1300496..47018d37082f 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -145,17 +145,31 @@ extern unsigned long high_memory; extern inline int pte_none(pte_t pte) { return !pte_val(pte); } extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; } +extern inline int pte_inuse(pte_t *ptep) { return mem_map[MAP_NR(ptep)] > 1; } extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } +extern inline void pte_reuse(pte_t *ptep) +{ + if(!(mem_map[MAP_NR(ptep)] & MAP_PAGE_RESERVED)) + mem_map[MAP_NR(ptep)]++; +} extern inline int pmd_none(pmd_t pmd) { return !pmd_val(pmd); } extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE || pmd_val(pmd) > high_memory; } extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_VALID; } -extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = 0; } +extern inline int pmd_inuse(pmd_t *pmdp) { return 0; } +extern inline void pmd_clear(pmd_t *pmdp) { pmd_val(*pmdp) = 0; } +extern inline void pmd_reuse(pmd_t * pmdp) { } extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); } extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~PAGE_MASK) != _PAGE_TABLE || pgd_val(pgd) > high_memory; } extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_VALID; } +extern inline int pgd_inuse(pgd_t *pgdp) { return mem_map[MAP_NR(pgdp)] > 1; } extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; } +extern inline void pgd_reuse(pgd_t *pgdp) +{ + if (!(mem_map[MAP_NR(pgdp)] & MAP_PAGE_RESERVED)) + mem_map[MAP_NR(pgdp)]++; +} /* * The following only work if pte_present() is true. @@ -312,6 +326,15 @@ extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) return (pmd_t *) pgd; } +extern inline void pgd_free(pgd_t *pgd) +{ + free_page((unsigned long) pgd); +} +extern inline pgd_t *pgd_alloc(void) +{ + return (pgd_t *) get_free_page(GFP_KERNEL); +} + extern pgd_t swapper_pg_dir[1024]; #endif /* !(_SPARC_PGTABLE_H) */ diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h index 039039d76b34..94697a64b0fa 100644 --- a/include/asm-sparc/system.h +++ b/include/asm-sparc/system.h @@ -64,7 +64,7 @@ retval = ((retval>>8)&15); \ retval; }) #define cli() swpipl(15) /* 15 = no int's except nmi's */ -#define sti() swpipl(0) /* same as alpha */ +#define sti() swpipl(0) /* I'm scared */ #define save_flags(flags) do { flags = swpipl(15); } while (0) #define restore_flags(flags) swpipl(flags) diff --git a/include/linux/ip.h b/include/linux/ip.h index 961ad3eeb1a2..bcc1bdea8b18 100644 --- a/include/linux/ip.h +++ b/include/linux/ip.h @@ -49,6 +49,9 @@ struct timestamp { #elif defined(__alpha__) __u8 flags:4, overflow:4; +#elif defined(__sparc__) + __u8 overflow:4, + flags:4; #else #error "Adjust this structure to match your CPU" #endif @@ -96,6 +99,9 @@ struct iphdr { #elif defined(__alpha__) __u8 ihl:4, version:4; +#elif defined (__sparc__) + __u8 version:4, + ihl:4; #else #error "Adjust this structure to match your CPU" #endif diff --git a/include/linux/tcp.h b/include/linux/tcp.h index ddb8159716f2..32ef0ad126fd 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -76,6 +76,16 @@ struct tcphdr { ack:1, urg:1, res2:2; +#elif defined(__sparc__) + __u16 res2:2, + urg:1, + ack:1, + psh:1, + rst:1, + syn:1, + fin:1, + doff:4, + res1:4; #else #error "Adjust this structure for your cpu alignment rules" #endif diff --git a/mm/kmalloc.c b/mm/kmalloc.c index c69ae21072bc..23c5a458eb9b 100644 --- a/mm/kmalloc.c +++ b/mm/kmalloc.c @@ -207,8 +207,11 @@ while (tries --) page->nfree--; if (!page->nfree) { - sizes[order].firstfree = page->next; - page->next = NULL; + if(dma_flag) + sizes[order].dmafree = page->next; + else + sizes[order].firstfree = page->next; + page->next = NULL; } restore_flags(flags); diff --git a/mm/memory.c b/mm/memory.c index dfbc863c2dcb..29b8c5953591 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -502,7 +502,13 @@ static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned end = PMD_SIZE; do { pte_t oldpage = *pte; - *pte = mk_pte(offset, prot); + pte_clear(pte); + if (offset >= high_memory || (mem_map[MAP_NR(offset)] & MAP_PAGE_RESERVED)) + *pte = mk_pte(offset, prot); + else if (mem_map[MAP_NR(offset)]) { + mem_map[MAP_NR(offset)]++; + *pte = mk_pte(offset, prot); + } forget_pte(oldpage); address += PAGE_SIZE; offset += PAGE_SIZE; diff --git a/mm/swap.c b/mm/swap.c index 1464d26e4d47..23a82356fd8f 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -389,10 +389,10 @@ static inline int try_to_swap_out(struct vm_area_struct* vma, unsigned offset, p #define SWAP_RATIO 128 static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir, - unsigned long address, unsigned long size, unsigned long offset) + unsigned long address, unsigned long end) { pte_t * pte; - unsigned long end; + unsigned long pmd_end; if (pmd_none(*dir)) return 0; @@ -401,21 +401,22 @@ static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir, pmd_clear(dir); return 0; } + pte = pte_offset(dir, address); - offset += address & PMD_MASK; - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; + + pmd_end = (address + PMD_SIZE) & PMD_MASK; + if (end > pmd_end) + end = pmd_end; + do { - switch (try_to_swap_out(vma, offset+address-vma->vm_start, pte)) { + switch (try_to_swap_out(vma, address-vma->vm_start, pte)) { case 0: break; case 1: vma->vm_task->mm->rss--; /* continue with the following page the next time */ - vma->vm_task->mm->swap_address = address + offset + PAGE_SIZE; + vma->vm_task->mm->swap_address = address + PAGE_SIZE; return 1; default: @@ -429,10 +430,10 @@ static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir, } static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir, - unsigned long address, unsigned long size) + unsigned long address, unsigned long end) { pmd_t * pmd; - unsigned long offset, end; + unsigned long pgd_end; if (pgd_none(*dir)) return 0; @@ -441,14 +442,15 @@ static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir, pgd_clear(dir); return 0; } + pmd = pmd_offset(dir, address); - offset = address & PGDIR_MASK; - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; + + pgd_end = (address + PGDIR_SIZE) & PGDIR_MASK; + if (end > pgd_end) + end = pgd_end; + do { - if (swap_out_pmd(vma, pmd, address, end - address, offset)) + if (swap_out_pmd(vma, pmd, address, end)) return 1; address = (address + PMD_SIZE) & PMD_MASK; pmd++; @@ -457,10 +459,13 @@ static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir, } static int swap_out_vma(struct vm_area_struct * vma, pgd_t *pgdir, - unsigned long start, unsigned long end) + unsigned long start) { + unsigned long end; + + end = vma->vm_end; while (start < end) { - if (swap_out_pgd(vma, pgdir, start, end - start)) + if (swap_out_pgd(vma, pgdir, start, end)) return 1; start = (start + PGDIR_SIZE) & PGDIR_MASK; pgdir++; @@ -489,7 +494,7 @@ static int swap_out_process(struct task_struct * p) address = vma->vm_start; for (;;) { - if (swap_out_vma(vma, pgd_offset(p, address), address, vma->vm_end)) + if (swap_out_vma(vma, pgd_offset(p, address), address)) return 1; vma = vma->vm_next; if (!vma) @@ -554,16 +559,29 @@ static int swap_out(unsigned int priority) static int try_to_free_page(int priority) { + static int state = 0; int i=6; - while (i--) { - if (priority != GFP_NOBUFFER && shrink_buffers(i)) - return 1; - if (shm_swap(i)) - return 1; - if (swap_out(i)) - return 1; + switch (state) { + do { + case 0: + if (priority != GFP_NOBUFFER && shrink_buffers(i)) { + state = 1; + return 1; + } + case 1: + if (shm_swap(i)) { + state = 2; + return 1; + } + case 2: + if (swap_out(i)) { + state = 0; + return 1; + } + } while(--i); } + state = 2; return 0; } diff --git a/net/inet/af_inet.c b/net/inet/af_inet.c index 558193e779da..a0e05fd8821c 100644 --- a/net/inet/af_inet.c +++ b/net/inet/af_inet.c @@ -734,6 +734,20 @@ static int inet_dup(struct socket *newsock, struct socket *oldsock) return(inet_create(newsock,((struct sock *)(oldsock->data))->protocol)); } +/* + * Return 1 if we still have things to send in our buffers. + */ +static inline int closing(struct sock * sk) +{ + switch (sk->state) { + case TCP_FIN_WAIT1: + case TCP_CLOSING: + case TCP_LAST_ACK: + return 1; + } + return 0; +} + /* * The peer socket should always be NULL (or else). When we call this @@ -772,8 +786,7 @@ static int inet_release(struct socket *sock, struct socket *peer) cli(); if (sk->lingertime) current->timeout = jiffies + HZ*sk->lingertime; - while(sk->state < TCP_LAST_ACK && sk->state!= TCP_FIN_WAIT2 && - sk->state != TCP_TIME_WAIT && current->timeout>0) + while(closing(sk) && current->timeout>0) { interruptible_sleep_on(sk->sleep); if (current->signal & ~current->blocked) @@ -856,7 +869,7 @@ outside_loop: destroy_sock(sk2); goto outside_loop; } - if (!sk->reuse || sk2->state==TCP_LISTEN) + if (!sk->reuse) { sti(); return(-EADDRINUSE); @@ -866,7 +879,7 @@ outside_loop: continue; /* more than one */ if (sk2->saddr != sk->saddr) continue; /* socket per slot ! -FB */ - if (!sk2->reuse) + if (!sk2->reuse || sk2->state==TCP_LISTEN) { sti(); return(-EADDRINUSE); -- 2.39.5